在downstream ssl create 中处理alpn扩展选项的回调。

This commit is contained in:
zhengchao
2018-10-29 17:30:22 +08:00
parent fd0c9ce6c2
commit 4bb03d6e38

View File

@@ -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);