diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index 67bd24d..e5371fe 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -48,6 +48,9 @@ int SSL_PEER_CERT_VERIFY_FAILED=0; */ #define DFLT_CIPHERS "ALL:-aNULL" +static unsigned char SSL_ALPN_HTTP_1_1[]={8, 'h', 't', 't', 'p', '/', '1', '.', '1',0}; +static unsigned char SSL_ALPN_HTTP_2[]={2, 'h','2',0}; + /* * Default elliptic curve for EC cipher suites. */ @@ -99,6 +102,7 @@ struct ssl_mgr unsigned int no_tls11; unsigned int no_tls12; unsigned int no_sessticket; + unsigned int no_alpn; CONST_SSL_METHOD * (* sslmethod)(void); //Parameter of SSL_CTX_new int ssl_min_version, ssl_max_version; @@ -151,6 +155,7 @@ struct ssl_stream struct ssl_chello * client_hello; //dir=upstream, a little weird, which send by downstream client. struct keyring * keyring; //dir=downstream. }; + const unsigned char* alpn_selected; struct __ssl_stream_debug _do_not_use; int is_peer_cert_verify_passed; }; @@ -320,7 +325,7 @@ void ssl_stat_init(struct ssl_mgr * mgr) return; } -static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt); +static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt, const unsigned char* selected_alpn); static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello * chello, evutil_socket_t fd); static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr); @@ -333,7 +338,7 @@ struct ssl_chello * ssl_peek_result_release_chello(future_result_t * result) } struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enum tfe_conn_dir dir, - struct ssl_chello * client_hello, struct keyring * kyr) + struct ssl_chello * client_hello, struct keyring * kyr, const unsigned char* selected_alpn) { int ret = 0; @@ -346,7 +351,7 @@ struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enu { case CONN_DIR_DOWNSTREAM: ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_DOWN_NEW])); - s_stream->ssl = downstream_ssl_create(mgr, kyr); + s_stream->ssl = downstream_ssl_create(mgr, kyr, selected_alpn); s_stream->keyring = kyr; break; case CONN_DIR_UPSTREAM: @@ -383,7 +388,10 @@ static void ssl_stream_free(struct ssl_stream * s_stream) break; default: assert(0); } - + if(s_stream->alpn_selected) + { + s_stream->alpn_selected=NULL; + } s_stream->mgr = NULL; free(s_stream); return; @@ -521,6 +529,8 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section MESA_load_profile_string_def(ini_profile, section, "default_ciphers", mgr->default_ciphers, sizeof(mgr->default_ciphers), DFLT_CIPHERS); MESA_load_profile_uint_def(ini_profile, section, "no_session_ticket", &(mgr->no_sessticket), 0); + MESA_load_profile_uint_def(ini_profile, section, "no_alpn", &(mgr->no_alpn), 0); + @@ -794,10 +804,10 @@ static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello * { SSL_set_tlsext_host_name(ssl, chello->sni); } - if (chello->alpn) + if (chello->alpn && !mgr->no_alpn) { ret=SSL_set_alpn_protos(ssl, (unsigned char*)chello->alpn, strlen(chello->alpn)); - assert(0); + assert(ret==0); } /* lower memory footprint for idle connections */ SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS); @@ -1017,6 +1027,24 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events, { log_ssl_master_key(s_stream->ssl, ctx->fd_upstream, CONN_DIR_UPSTREAM, mgr->fp_master_key); } + const unsigned char *alpn_data=NULL; + unsigned int alpn_len=0; + SSL_get0_alpn_selected(s_stream->ssl, &alpn_data, &alpn_len); + if(alpn_len>0&&alpn_data!=NULL) + { + if(0==memcmp(alpn_data, SSL_ALPN_HTTP_1_1+1, alpn_len)) + { + s_stream->alpn_selected=SSL_ALPN_HTTP_1_1; + } + else if(0==memcmp(alpn_data, SSL_ALPN_HTTP_2+1, alpn_len)) + { + s_stream->alpn_selected=SSL_ALPN_HTTP_2; + } + else + { + s_stream->alpn_selected=NULL; + } + } promise_success(p, ctx); } wrap_ssl_connect_server_ctx_free(ctx); @@ -1033,7 +1061,7 @@ static void peek_chello_on_succ(future_result_t * result, void * user) { ATOMIC_INC(&(ctx->mgr->stat_val[SSL_NO_SNI])); } - ctx->s_stream = ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL); + ctx->s_stream = ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL, NULL); ctx->bev = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_upstream, ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS); @@ -1274,11 +1302,34 @@ static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr) } + +static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, + unsigned int inlen, void *arg) { + int rv; + const unsigned char* selected_alpn=(const unsigned char*)arg; + (void)ssl; + unsigned char* _out=NULL; + unsigned char _outlen=0; + rv=SSL_select_next_proto(&_out, &_outlen, in, inlen, selected_alpn, strlen((const char*)selected_alpn)); + if(rv==OPENSSL_NPN_NEGOTIATED) + { + *out=_out; + *outlen=_outlen; + return SSL_TLSEXT_ERR_OK; + } + else //rv==OPENSSL_NPN_NO_OVERLAP + { + return SSL_TLSEXT_ERR_NOACK; + } +} + + /* * Create and set up a new SSL_CTX instance for terminating SSL. * Set up all the necessary callbacks, the keyring, the keyring chain and key. */ -static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt) +static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt, const unsigned char* selected_alpn) { SSL_CTX * sslctx = SSL_CTX_new(mgr->sslmethod()); if (!sslctx) return NULL; @@ -1332,7 +1383,10 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt) SSL_CTX_set_tmp_ecdh(sslctx, ecdh); EC_KEY_free(ecdh); } - + if(!mgr->no_alpn) + { + SSL_CTX_set_alpn_select_cb(sslctx, alpn_select_proto_cb, (void*)selected_alpn); + } SSL_CTX_use_certificate(sslctx, crt->cert); SSL_CTX_use_PrivateKey(sslctx, crt->key); @@ -1355,7 +1409,6 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt) /* lower memory footprint for idle connections */ SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS); } - return ssl; } @@ -1456,7 +1509,8 @@ void ask_keyring_on_succ(void * result, void * user) kyr = key_keeper_release_keyring(result); //kyr will be freed at ssl downstream closing. - ctx->downstream = ssl_stream_new(mgr, ctx->fd_downstream, CONN_DIR_DOWNSTREAM, NULL, kyr); + ctx->downstream = ssl_stream_new(mgr, ctx->fd_downstream, CONN_DIR_DOWNSTREAM, NULL, kyr, + ctx->origin_ssl?ctx->origin_ssl->alpn_selected:NULL); ctx->bev_down = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_downstream, ctx->downstream->ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_DEFER_CALLBACKS); bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev_down, 1);