mirror of https://github.com/openssl/openssl.git
				
				
				
			
							parent
							
								
									b0d6f3c58f
								
							
						
					
					
						commit
						cb3cec4adf
					
				
							
								
								
									
										161
									
								
								ssl/ssltest.c
								
								
								
								
							
							
						
						
									
										161
									
								
								ssl/ssltest.c
								
								
								
								
							|  | @ -295,6 +295,127 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) | ||||||
| static BIO *bio_err=NULL; | static BIO *bio_err=NULL; | ||||||
| static BIO *bio_stdout=NULL; | static BIO *bio_stdout=NULL; | ||||||
| 
 | 
 | ||||||
|  | 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 | #define SCT_EXT_TYPE 18 | ||||||
| 
 | 
 | ||||||
| /* WARNING : below extension types are *NOT* IETF assigned, and 
 | /* WARNING : below extension types are *NOT* IETF assigned, and 
 | ||||||
|  | @ -614,6 +735,9 @@ static void sv_usage(void) | ||||||
| 	fprintf(stderr," -serverinfo_sct  - have client offer and expect SCT\n"); | 	fprintf(stderr," -serverinfo_sct  - have client offer and expect SCT\n"); | ||||||
| 	fprintf(stderr," -serverinfo_tack - have client offer and expect TACK\n"); | 	fprintf(stderr," -serverinfo_tack - have client offer and expect TACK\n"); | ||||||
| 	fprintf(stderr," -custom_ext - try various custom extension callbacks\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) | static void print_details(SSL *c_ssl, const char *prefix) | ||||||
|  | @ -1102,6 +1226,21 @@ int main(int argc, char *argv[]) | ||||||
| 			{ | 			{ | ||||||
| 			custom_ext = 1; | 			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 | 		else | ||||||
| 			{ | 			{ | ||||||
| 			fprintf(stderr,"unknown option %s\n",*argv); | 			fprintf(stderr,"unknown option %s\n",*argv); | ||||||
|  | @ -1488,6 +1627,23 @@ bad: | ||||||
| 					   custom_ext_3_srv_second_cb, NULL); | 					   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); | 	c_ssl=SSL_new(c_ctx); | ||||||
| 	s_ssl=SSL_new(s_ctx); | 	s_ssl=SSL_new(s_ctx); | ||||||
| 
 | 
 | ||||||
|  | @ -1948,6 +2104,11 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, | ||||||
| 		ret = 1; | 		ret = 1; | ||||||
| 		goto err; | 		goto err; | ||||||
| 		} | 		} | ||||||
|  | 	if (verify_alpn(c_ssl, s_ssl) < 0) | ||||||
|  | 		{ | ||||||
|  | 		ret = 1; | ||||||
|  | 		goto err; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	if (custom_ext_error) | 	if (custom_ext_error) | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								test/testssl
								
								
								
								
							
							
						
						
									
										12
									
								
								test/testssl
								
								
								
								
							|  | @ -184,6 +184,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 | $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 | if ../util/shlib_wrap.sh ../apps/openssl no-srp; then | ||||||
|   echo skipping SRP tests |   echo skipping SRP tests | ||||||
| else | else | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue