在downstream ssl create 中处理alpn扩展选项的回调。
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user