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_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 | ||||
| 
 | ||||
| /* 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_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) | ||||
|  | @ -1102,6 +1226,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); | ||||
|  | @ -1488,6 +1627,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); | ||||
| 
 | ||||
|  | @ -1948,6 +2104,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) | ||||
| 		{ | ||||
|  |  | |||
							
								
								
									
										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 | ||||
| 
 | ||||
| 
 | ||||
| ############################################################################# | ||||
| # 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…
	
		Reference in New Issue