Loading apps/s_client.c +1 −0 Original line number Diff line number Diff line Loading @@ -1329,6 +1329,7 @@ bad: goto end; } SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); OPENSSL_free(alpn); } #endif #ifndef OPENSSL_NO_TLSEXT Loading ssl/ssltest.c +161 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,127 @@ static int verify_npn(SSL *client, SSL *server) } #endif static const char *alpn_client; static const char *alpn_server; static const char *alpn_expected; static unsigned char *alpn_selected; /* next_protos_parse parses a comma separated list of strings into a string * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. * outlen: (output) set to the length of the resulting buffer on success. * err: (maybe NULL) on failure, an error message line is written to this BIO. * in: a NUL termianted string like "abc,def,ghi" * * returns: a malloced buffer or NULL on failure. */ static unsigned char *next_protos_parse(unsigned short *outlen, const char *in) { size_t len; unsigned char *out; size_t i, start = 0; len = strlen(in); if (len >= 65535) return NULL; out = OPENSSL_malloc(strlen(in) + 1); if (!out) return NULL; for (i = 0; i <= len; ++i) { if (i == len || in[i] == ',') { if (i - start > 255) { OPENSSL_free(out); return NULL; } out[start] = i - start; start = i + 1; } else out[i+1] = in[i]; } *outlen = len + 1; return out; } static int cb_server_alpn(SSL *s, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { unsigned char *protos; unsigned short protos_len; protos = next_protos_parse(&protos_len, alpn_server); if (protos == NULL) { fprintf(stderr, "failed to parser ALPN server protocol string: %s\n", alpn_server); abort(); } if (SSL_select_next_proto((unsigned char**) out, outlen, protos, protos_len, in, inlen) != OPENSSL_NPN_NEGOTIATED) { OPENSSL_free(protos); return SSL_TLSEXT_ERR_NOACK; } /* Make a copy of the selected protocol which will be freed in verify_alpn. */ alpn_selected = OPENSSL_malloc(*outlen); memcpy(alpn_selected, *out, *outlen); *out = alpn_selected; OPENSSL_free(protos); return SSL_TLSEXT_ERR_OK; } static int verify_alpn(SSL *client, SSL *server) { const unsigned char *client_proto, *server_proto; unsigned int client_proto_len = 0, server_proto_len = 0; SSL_get0_alpn_selected(client, &client_proto, &client_proto_len); SSL_get0_alpn_selected(server, &server_proto, &server_proto_len); if (alpn_selected != NULL) { OPENSSL_free(alpn_selected); alpn_selected = NULL; } if (client_proto_len != server_proto_len || memcmp(client_proto, server_proto, client_proto_len) != 0) { BIO_printf(bio_stdout, "ALPN selected protocols differ!\n"); goto err; } if (client_proto_len > 0 && alpn_expected == NULL) { BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n"); goto err; } if (alpn_expected != NULL && (client_proto_len != strlen(alpn_expected) || memcmp(client_proto, alpn_expected, client_proto_len) != 0)) { BIO_printf(bio_stdout, "ALPN selected protocols not equal to expected protocol: %s\n", alpn_expected); goto err; } return 0; err: BIO_printf(bio_stdout, "ALPN results: client: '"); BIO_write(bio_stdout, client_proto, client_proto_len); BIO_printf(bio_stdout, "', server: '"); BIO_write(bio_stdout, server_proto, server_proto_len); BIO_printf(bio_stdout, "'\n"); BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n", alpn_client, alpn_server); return -1; } #define SCT_EXT_TYPE 18 /* WARNING : below extension types are *NOT* IETF assigned, and Loading Loading @@ -689,6 +810,9 @@ static void sv_usage(void) fprintf(stderr," -serverinfo_sct - have client offer and expect SCT\n"); fprintf(stderr," -serverinfo_tack - have client offer and expect TACK\n"); fprintf(stderr," -custom_ext - try various custom extension callbacks\n"); fprintf(stderr," -alpn_client <string> - have client side offer ALPN\n"); fprintf(stderr," -alpn_server <string> - have server side offer ALPN\n"); fprintf(stderr," -alpn_expected <string> - the ALPN protocol that should be negotiated\n"); } static void print_details(SSL *c_ssl, const char *prefix) Loading Loading @@ -1118,6 +1242,21 @@ int main(int argc, char *argv[]) { custom_ext = 1; } else if (strcmp(*argv,"-alpn_client") == 0) { if (--argc < 1) goto bad; alpn_client = *(++argv); } else if (strcmp(*argv,"-alpn_server") == 0) { if (--argc < 1) goto bad; alpn_server = *(++argv); } else if (strcmp(*argv,"-alpn_expected") == 0) { if (--argc < 1) goto bad; alpn_expected = *(++argv); } else { fprintf(stderr,"unknown option %s\n",*argv); Loading Loading @@ -1487,6 +1626,23 @@ bad: custom_ext_3_srv_second_cb, NULL); } if (alpn_server) SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL); if (alpn_client) { unsigned short alpn_len; unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client); if (alpn == NULL) { BIO_printf(bio_err, "Error parsing -alpn_client argument\n"); goto end; } SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len); OPENSSL_free(alpn); } c_ssl=SSL_new(c_ctx); s_ssl=SSL_new(s_ctx); Loading Loading @@ -1949,6 +2105,11 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, ret = 1; goto err; } if (verify_alpn(c_ssl, s_ssl) < 0) { ret = 1; goto err; } if (custom_ext_error) { Loading test/testssl +12 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,18 @@ $ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_sct -serverinf $ssltest -bio_pair -tls1 -custom_ext -serverinfo_file $serverinfo -serverinfo_sct -serverinfo_tack || exit 1 ############################################################################# # ALPN tests $ssltest -bio_pair -tls1 -alpn_client foo -alpn_server bar || exit 1 $ssltest -bio_pair -tls1 -alpn_client foo -alpn_server foo -alpn_expected foo || exit 1 $ssltest -bio_pair -tls1 -alpn_client foo,bar -alpn_server foo -alpn_expected foo || exit 1 $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server foo -alpn_expected foo || exit 1 $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server foo,bar -alpn_expected foo || exit 1 $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server bar,foo -alpn_expected bar || exit 1 $ssltest -bio_pair -tls1 -alpn_client foo,bar -alpn_server bar,foo -alpn_expected bar || exit 1 $ssltest -bio_pair -tls1 -alpn_client baz -alpn_server bar,foo || exit 1 if ../util/shlib_wrap.sh ../apps/openssl no-srp; then echo skipping SRP tests else Loading Loading
apps/s_client.c +1 −0 Original line number Diff line number Diff line Loading @@ -1329,6 +1329,7 @@ bad: goto end; } SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); OPENSSL_free(alpn); } #endif #ifndef OPENSSL_NO_TLSEXT Loading
ssl/ssltest.c +161 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,127 @@ static int verify_npn(SSL *client, SSL *server) } #endif static const char *alpn_client; static const char *alpn_server; static const char *alpn_expected; static unsigned char *alpn_selected; /* next_protos_parse parses a comma separated list of strings into a string * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. * outlen: (output) set to the length of the resulting buffer on success. * err: (maybe NULL) on failure, an error message line is written to this BIO. * in: a NUL termianted string like "abc,def,ghi" * * returns: a malloced buffer or NULL on failure. */ static unsigned char *next_protos_parse(unsigned short *outlen, const char *in) { size_t len; unsigned char *out; size_t i, start = 0; len = strlen(in); if (len >= 65535) return NULL; out = OPENSSL_malloc(strlen(in) + 1); if (!out) return NULL; for (i = 0; i <= len; ++i) { if (i == len || in[i] == ',') { if (i - start > 255) { OPENSSL_free(out); return NULL; } out[start] = i - start; start = i + 1; } else out[i+1] = in[i]; } *outlen = len + 1; return out; } static int cb_server_alpn(SSL *s, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { unsigned char *protos; unsigned short protos_len; protos = next_protos_parse(&protos_len, alpn_server); if (protos == NULL) { fprintf(stderr, "failed to parser ALPN server protocol string: %s\n", alpn_server); abort(); } if (SSL_select_next_proto((unsigned char**) out, outlen, protos, protos_len, in, inlen) != OPENSSL_NPN_NEGOTIATED) { OPENSSL_free(protos); return SSL_TLSEXT_ERR_NOACK; } /* Make a copy of the selected protocol which will be freed in verify_alpn. */ alpn_selected = OPENSSL_malloc(*outlen); memcpy(alpn_selected, *out, *outlen); *out = alpn_selected; OPENSSL_free(protos); return SSL_TLSEXT_ERR_OK; } static int verify_alpn(SSL *client, SSL *server) { const unsigned char *client_proto, *server_proto; unsigned int client_proto_len = 0, server_proto_len = 0; SSL_get0_alpn_selected(client, &client_proto, &client_proto_len); SSL_get0_alpn_selected(server, &server_proto, &server_proto_len); if (alpn_selected != NULL) { OPENSSL_free(alpn_selected); alpn_selected = NULL; } if (client_proto_len != server_proto_len || memcmp(client_proto, server_proto, client_proto_len) != 0) { BIO_printf(bio_stdout, "ALPN selected protocols differ!\n"); goto err; } if (client_proto_len > 0 && alpn_expected == NULL) { BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n"); goto err; } if (alpn_expected != NULL && (client_proto_len != strlen(alpn_expected) || memcmp(client_proto, alpn_expected, client_proto_len) != 0)) { BIO_printf(bio_stdout, "ALPN selected protocols not equal to expected protocol: %s\n", alpn_expected); goto err; } return 0; err: BIO_printf(bio_stdout, "ALPN results: client: '"); BIO_write(bio_stdout, client_proto, client_proto_len); BIO_printf(bio_stdout, "', server: '"); BIO_write(bio_stdout, server_proto, server_proto_len); BIO_printf(bio_stdout, "'\n"); BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n", alpn_client, alpn_server); return -1; } #define SCT_EXT_TYPE 18 /* WARNING : below extension types are *NOT* IETF assigned, and Loading Loading @@ -689,6 +810,9 @@ static void sv_usage(void) fprintf(stderr," -serverinfo_sct - have client offer and expect SCT\n"); fprintf(stderr," -serverinfo_tack - have client offer and expect TACK\n"); fprintf(stderr," -custom_ext - try various custom extension callbacks\n"); fprintf(stderr," -alpn_client <string> - have client side offer ALPN\n"); fprintf(stderr," -alpn_server <string> - have server side offer ALPN\n"); fprintf(stderr," -alpn_expected <string> - the ALPN protocol that should be negotiated\n"); } static void print_details(SSL *c_ssl, const char *prefix) Loading Loading @@ -1118,6 +1242,21 @@ int main(int argc, char *argv[]) { custom_ext = 1; } else if (strcmp(*argv,"-alpn_client") == 0) { if (--argc < 1) goto bad; alpn_client = *(++argv); } else if (strcmp(*argv,"-alpn_server") == 0) { if (--argc < 1) goto bad; alpn_server = *(++argv); } else if (strcmp(*argv,"-alpn_expected") == 0) { if (--argc < 1) goto bad; alpn_expected = *(++argv); } else { fprintf(stderr,"unknown option %s\n",*argv); Loading Loading @@ -1487,6 +1626,23 @@ bad: custom_ext_3_srv_second_cb, NULL); } if (alpn_server) SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL); if (alpn_client) { unsigned short alpn_len; unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client); if (alpn == NULL) { BIO_printf(bio_err, "Error parsing -alpn_client argument\n"); goto end; } SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len); OPENSSL_free(alpn); } c_ssl=SSL_new(c_ctx); s_ssl=SSL_new(s_ctx); Loading Loading @@ -1949,6 +2105,11 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, ret = 1; goto err; } if (verify_alpn(c_ssl, s_ssl) < 0) { ret = 1; goto err; } if (custom_ext_error) { Loading
test/testssl +12 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,18 @@ $ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_sct -serverinf $ssltest -bio_pair -tls1 -custom_ext -serverinfo_file $serverinfo -serverinfo_sct -serverinfo_tack || exit 1 ############################################################################# # ALPN tests $ssltest -bio_pair -tls1 -alpn_client foo -alpn_server bar || exit 1 $ssltest -bio_pair -tls1 -alpn_client foo -alpn_server foo -alpn_expected foo || exit 1 $ssltest -bio_pair -tls1 -alpn_client foo,bar -alpn_server foo -alpn_expected foo || exit 1 $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server foo -alpn_expected foo || exit 1 $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server foo,bar -alpn_expected foo || exit 1 $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server bar,foo -alpn_expected bar || exit 1 $ssltest -bio_pair -tls1 -alpn_client foo,bar -alpn_server bar,foo -alpn_expected bar || exit 1 $ssltest -bio_pair -tls1 -alpn_client baz -alpn_server bar,foo || exit 1 if ../util/shlib_wrap.sh ../apps/openssl no-srp; then echo skipping SRP tests else Loading