From 0f87411d01212dc9ec052d92c75e8cbe06f983de Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 24 Aug 2018 10:55:47 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=95=B4=E7=90=86ssl=20stream=E7=9A=84shut?= =?UTF-8?q?down=E6=B5=81=E7=A8=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platform/include/internal/ssl_stream.h | 2 +- platform/src/ssl_stream.cpp | 568 +++++++------------------ 2 files changed, 146 insertions(+), 424 deletions(-) diff --git a/platform/include/internal/ssl_stream.h b/platform/include/internal/ssl_stream.h index 806822c..47b619f 100644 --- a/platform/include/internal/ssl_stream.h +++ b/platform/include/internal/ssl_stream.h @@ -8,7 +8,7 @@ struct ssl_stream; struct ssl_mgr; -struct ssl_mgr* init_ssl_manager(const char* ini_profile, const char* section); +struct ssl_mgr* init_ssl_manager(const char* ini_profile, const char* section, void* logger); void destroy_ssl_manager(struct ssl_mgr* mgr); struct ssl_chello diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index d29ea7f..ba0c5de 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -48,9 +48,11 @@ struct ssl_mgr char * ecdhcurve; char * crlurl; uint8_t SSL_MODE_RELEASE_BUFFERS; + void *logger; }; struct ssl_stream { + enum tfe_conn_dir dir; SSL * ssl; struct ssl_mgr* ref_mgr; char* sni; @@ -70,10 +72,20 @@ struct ssl_connect_origin_ctx struct sockaddr addr; socklen_t addrlen; }; +/* + * SSL shutdown context. + */ +struct ssl_shutdown_ctx { + struct ssl_stream* s_stream; + struct event_base *evbase; + struct event *ev; + unsigned int retries; +}; -struct ssl_mgr* init_ssl_manager(const char* ini_profile, const char* section) +struct ssl_mgr* init_ssl_manager(const char* ini_profile, const char* section, void* logger) { - struct ssl_mgr* mgr=ALLOC(struct ssl_mgr*, 1); + struct ssl_mgr* mgr=ALLOC(struct ssl_mgr, 1); + mgr->logger=logger; memcpy(mgr->ssl_session_context,"mesa-tfe",sizeof(mgr->ssl_session_context)); return mgr; } @@ -267,7 +279,7 @@ static SSL* upstream_ssl_create(struct ssl_mgr* mgr, const struct ssl_chello* ch sslctx = SSL_CTX_new(mgr->sslmethod()); - pxy_sslctx_setoptions(sslctx, mgr); + sslctx_set_opts(sslctx, mgr); #if OPENSSL_VERSION_NUMBER >= 0x10100000L if (mgr->sslversion) { @@ -394,6 +406,7 @@ void ssl_async_connect_origin(struct future* future, struct ssl_mgr* mgr, const assert(ret==0); ctx->ssl=ALLOC(struct ssl_stream,1); ctx->ssl->ref_mgr=mgr; + ctx->ssl->dir=CONN_DIR_UPSTREAM; ctx->ssl->sni=tfe_strdup(chello->sni); ctx->ssl->ssl=upstream_ssl_create(mgr, chello, &(ctx->addr), ctx->addrlen); ctx->bev = bufferevent_openssl_socket_new(evbase, fd, ctx->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS); @@ -403,194 +416,6 @@ void ssl_async_connect_origin(struct future* future, struct ssl_mgr* mgr, const bufferevent_enable(ctx->bev, EV_READ | EV_WRITE); } -/* - * Dump information on a cert to the debug log. - */ -static void pxy_debug_crt(X509 * crt) -{ - char * sj = ssl_x509_subject(crt); - if (sj) - { - log_dbg_printf("Subject DN: %s\n", sj); - free(sj); - } - - char * names = ssl_x509_names_to_str(crt); - if (names) - { - log_dbg_printf("Common Names: %s\n", names); - free(names); - } - - char * fpr; - if (!(fpr = ssl_x509_fingerprint(crt, 1))) - { - log_err_printf("Warning: Error generating X509 fingerprint\n"); - } - else - { - log_dbg_printf("Fingerprint: %s\n", fpr); - free(fpr); - } - -#ifdef DEBUG_CERTIFICATE - /* dump cert */ - log_dbg_print_free(ssl_x509_to_str(crt)); - log_dbg_print_free(ssl_x509_to_pem(crt)); -#endif /* DEBUG_CERTIFICATE */ -} - -static void -pxy_log_connect_nonhttp(pxy_conn_ctx_t * ctx) -{ - char * msg; - int rv; - - /* - * The following ifdef's within asprintf arguments list generates - * warnings with -Wembedded-directive on some compilers. - * Not fixing the code in order to avoid more code duplication. - */ - - if (!ctx->src.ssl) - { - rv = asprintf(&msg, "%s %s %s %s %s" - #ifdef HAVE_LOCAL_PROCINFO - " %s" - #endif /* HAVE_LOCAL_PROCINFO */ - "\n", - ctx->passthrough ? "passthrough" : "tcp", - STRORDASH(ctx->srchost_str), - STRORDASH(ctx->srcport_str), - STRORDASH(ctx->dsthost_str), - STRORDASH(ctx->dstport_str) - ); - } - else - { - rv = asprintf(&msg, "%s %s %s %s %s " - "sni:%s names:%s " - "sproto:%s:%s dproto:%s:%s " - "origcrt:%s usedcrt:%s\n", - ctx->clienthello_found ? "upgrade" : "ssl", - STRORDASH(ctx->srchost_str), - STRORDASH(ctx->srcport_str), - STRORDASH(ctx->dsthost_str), - STRORDASH(ctx->dstport_str), - STRORDASH(ctx->sni), - STRORDASH(ctx->ssl_names), - SSL_get_version(ctx->src.ssl), - SSL_get_cipher(ctx->src.ssl), - SSL_get_version(ctx->dst.ssl), - SSL_get_cipher(ctx->dst.ssl), - STRORDASH(ctx->origcrtfpr), - STRORDASH(ctx->usedcrtfpr) - ); - } - if ((rv < 0) || !msg) - { - ctx->enomem = 1; - goto out; - } - if (!ctx->opts->detach) - { - log_err_printf("%s", msg); - } - if (ctx->opts->connectlog) - { - } - else - { - free(msg); - } -out: - return; -} - -static void -pxy_log_connect_http(pxy_conn_ctx_t * ctx) -{ - char * msg; - int rv; - -#ifdef DEBUG_PROXY - if (ctx->passthrough) { - log_err_printf("Warning: pxy_log_connect_http called while in " - "passthrough mode\n"); - return; - } -#endif - - - /* - * The following ifdef's within asprintf arguments list generates - * warnings with -Wembedded-directive on some compilers. - * Not fixing the code in order to avoid more code duplication. - */ - - if (!ctx->spec->ssl) - { - rv = asprintf(&msg, "http %s %s %s %s %s %s %s %s %s %s\n", - STRORDASH(ctx->srchost_str), - STRORDASH(ctx->srcport_str), - STRORDASH(ctx->dsthost_str), - STRORDASH(ctx->dstport_str), - STRORDASH(ctx->http_host), - STRORDASH(ctx->http_method), - STRORDASH(ctx->http_uri), - STRORDASH(ctx->http_status_code), - STRORDASH(ctx->http_content_length), - ctx->ocsp_denied ? " ocsp:denied" : ""); - } - else - { - rv = asprintf(&msg, "https %s %s %s %s %s %s %s %s %s " - "sni:%s names:%s " - "sproto:%s:%s dproto:%s:%s " - "origcrt:%s usedcrt:%s" - #ifdef HAVE_LOCAL_PROCINFO - " %s" - #endif /* HAVE_LOCAL_PROCINFO */ - "%s\n", - STRORDASH(ctx->srchost_str), - STRORDASH(ctx->srcport_str), - STRORDASH(ctx->dsthost_str), - STRORDASH(ctx->dstport_str), - STRORDASH(ctx->http_host), - STRORDASH(ctx->http_method), - STRORDASH(ctx->http_uri), - STRORDASH(ctx->http_status_code), - STRORDASH(ctx->http_content_length), - STRORDASH(ctx->sni), - STRORDASH(ctx->ssl_names), - SSL_get_version(ctx->src.ssl), - SSL_get_cipher(ctx->src.ssl), - SSL_get_version(ctx->dst.ssl), - SSL_get_cipher(ctx->dst.ssl), - STRORDASH(ctx->origcrtfpr), - STRORDASH(ctx->usedcrtfpr), - ctx->ocsp_denied ? " ocsp:denied" : ""); - } - if ((rv < 0) || !msg) - { - ctx->enomem = 1; - goto out; - } - if (!ctx->opts->detach) - { - log_err_printf("%s", msg); - } - if (ctx->opts->connectlog) - { - } - - else - { - free(msg); - } -out: - return; -} /* * Called by OpenSSL when a new src SSL session is created. @@ -601,7 +426,7 @@ out: */ static int -pxy_ossl_sessnew_cb(SSL * ssl, SSL_SESSION * sess) +ossl_sessnew_cb(SSL * ssl, SSL_SESSION * sess) { struct ssl_mgr* mgr=(struct ssl_mgr*) SSL_get_ex_data(ssl, SSL_EX_DATA_IDX_SSLMGR, mgr); @@ -625,7 +450,7 @@ pxy_ossl_sessnew_cb(SSL * ssl, SSL_SESSION * sess) * we do not need to free the reference here. */ static void -pxy_ossl_sessremove_cb(UNUSED SSL_CTX * sslctx, SSL_SESSION * sess) +ossl_sessremove_cb(UNUSED SSL_CTX * sslctx, SSL_SESSION * sess) { struct ssl_mgr* mgr=(struct ssl_mgr*) SSL_get_ex_data(ssl, SSL_EX_DATA_IDX_SSLMGR, mgr); if (sess) @@ -640,7 +465,7 @@ pxy_ossl_sessremove_cb(UNUSED SSL_CTX * sslctx, SSL_SESSION * sess) OPENSSL_VERSION_NUMBER >= 0x10100000L required. */ static SSL_SESSION * -pxy_ossl_sessget_cb(UNUSED SSL *ssl, const unsigned char *id, int idlen, int *copy) +ossl_sessget_cb(UNUSED SSL *ssl, const unsigned char *id, int idlen, int *copy) { struct ssl_mgr* mgr=(struct ssl_mgr*) SSL_get_ex_data(ssl, SSL_EX_DATA_IDX_SSLMGR, mgr); SSL_SESSION * sess; @@ -654,7 +479,7 @@ pxy_ossl_sessget_cb(UNUSED SSL *ssl, const unsigned char *id, int idlen, int *co * Set SSL_CTX options that are the same for incoming and outgoing SSL_CTX. */ static void -pxy_sslctx_setoptions(SSL_CTX * sslctx, struct ssl_mgr* mgr) +sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr* mgr) { SSL_CTX_set_options(sslctx, SSL_OP_ALL); #ifdef SSL_OP_TLS_ROLLBACK_BUG @@ -715,223 +540,6 @@ pxy_sslctx_setoptions(SSL_CTX * sslctx, struct ssl_mgr* mgr) } -static int -pxy_srccert_write_to_gendir(pxy_conn_ctx_t * ctx, X509 * crt, int is_orig) -{ - char * fn; - int rv; - - if (!ctx->origcrtfpr) - return -1; - if (is_orig) - { - rv = asprintf(&fn, "%s/%s.crt", ctx->opts->certgendir, - ctx->origcrtfpr); - } - else - { - if (!ctx->usedcrtfpr) - return -1; - rv = asprintf(&fn, "%s/%s-%s.crt", ctx->opts->certgendir, - ctx->origcrtfpr, ctx->usedcrtfpr); - } - if (rv == -1) - { - ctx->enomem = 1; - return -1; - } - - free(fn); - return rv; -} - -static void pxy_srccert_write(pxy_conn_ctx_t * ctx) -{ - if (ctx->opts->certgen_writeall || ctx->generated_cert) - { - if (pxy_srccert_write_to_gendir(ctx, - SSL_get_certificate(ctx->src.ssl), 0) == -1) - { - log_err_printf("Failed to write used cert\n"); - } - } - if (ctx->opts->certgen_writeall) - { - if (pxy_srccert_write_to_gendir(ctx, ctx->origcrt, 1) == -1) - { - log_err_printf("Failed to write orig cert\n"); - } - } -} - -/* - * Create new SSL context for the incoming connection, based on the original - * destination SSL cert. - * Returns NULL if no suitable cert could be found. - */ - - -static SSL * downstream_ssl_create(cert_t * cert, struct tfe_config* opts) -{ - - assert(cert!=NULL); - SSL_CTX * sslctx = downstream_sslctx_create(ctx, cert->crt, cert->chain, - cert->key); - - if (!sslctx) - { - return NULL; - } - SSL * ssl = SSL_new(sslctx); - SSL_CTX_free(sslctx); /* SSL_new() increments refcount */ - if (!ssl) - { - return NULL; - } -#ifdef SSL_MODE_RELEASE_BUFFERS - /* lower memory footprint for idle connections */ - SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS); -#endif /* SSL_MODE_RELEASE_BUFFERS */ - return ssl; -} - -/* - * OpenSSL servername callback, called when OpenSSL receives a servername - * TLS extension in the clientHello. Must switch to a new SSL_CTX with - * a different cert if we want to replace the server cert here. - * We generate a new cert if the current one does not match the - * supplied servername. This should only happen if the original destination - * server supplies a cert which does not match the server name we - * indicate to it. - */ -static int pxy_ossl_servername_cb(SSL * ssl, UNUSED int * al, void * arg) -{ - pxy_conn_ctx_t * ctx = (pxy_conn_ctx_t *) arg; - const char * sn; - X509 * sslcrt; - - if (!(sn = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) - return SSL_TLSEXT_ERR_NOACK; - - if (!ctx->sni) - { - if (OPTS_DEBUG(ctx->opts)) - { - log_dbg_printf("Warning: SNI parser yielded no " - "hostname, copying OpenSSL one: " - "[NULL] != [%s]\n", sn); - } - ctx->sni = strdup(sn); - if (!ctx->sni) - { - ctx->enomem = 1; - return SSL_TLSEXT_ERR_NOACK; - } - } - if (OPTS_DEBUG(ctx->opts)) - { - if (strcmp(sn, ctx->sni) != 0) - { - /* - * This may happen if the client resumes a session, but - * uses a different SNI hostname when resuming than it - * used when the session was created. OpenSSL - * correctly ignores the SNI in the ClientHello in this - * case, but since we have already sent the SNI onwards - * to the original destination, there is no way back. - * We log an error and hope this never happens. - */ - log_dbg_printf("Warning: SNI parser yielded different " - "hostname than OpenSSL callback for " - "the same ClientHello message: " - "[%s] != [%s]\n", ctx->sni, sn); - } - } - - /* generate a new cert with sn as additional altSubjectName - * and replace it both in the current SSL ctx and in the cert cache */ - if (!ctx->immutable_cert && - !ssl_x509_names_match((sslcrt = SSL_get_certificate(ssl)), sn)) - { - X509 * newcrt; - SSL_CTX * newsslctx; - - if (OPTS_DEBUG(ctx->opts)) - { - log_dbg_printf("Certificate cache: UPDATE " - "(SNI mismatch)\n"); - } - newcrt = ssl_x509_forge(ctx->opts->cacrt, ctx->opts->cakey, - sslcrt, ctx->opts->key, - sn, ctx->opts->crlurl); - if (!newcrt) - { - ctx->enomem = 1; - return SSL_TLSEXT_ERR_NOACK; - } - cachemgr_fkcrt_set(ctx->origcrt, newcrt); - ctx->generated_cert = 1; - if (OPTS_DEBUG(ctx->opts)) - { - log_dbg_printf("===> Updated forged server " - "cert:\n"); - pxy_debug_crt(newcrt); - } - if (WANT_CONNECT_LOG(ctx)) - { - if (ctx->ssl_names) - { - free(ctx->ssl_names); - } - ctx->ssl_names = ssl_x509_names_to_str(newcrt); - if (!ctx->ssl_names) - { - ctx->enomem = 1; - } - } - if (WANT_CONNECT_LOG(ctx) || ctx->opts->certgendir) - { - if (ctx->usedcrtfpr) - { - free(ctx->usedcrtfpr); - } - ctx->usedcrtfpr = ssl_x509_fingerprint(newcrt, 0); - if (!ctx->usedcrtfpr) - { - ctx->enomem = 1; - } - } - - newsslctx = downstream_sslctx_create(ctx, newcrt, ctx->opts->chain, - ctx->opts->key); - if (!newsslctx) - { - X509_free(newcrt); - ctx->enomem = 1; - return SSL_TLSEXT_ERR_NOACK; - } - SSL_set_SSL_CTX(ssl, newsslctx); /* decr's old incr new refc */ - SSL_CTX_free(newsslctx); - X509_free(newcrt); - } - else if (OPTS_DEBUG(ctx->opts)) - { - log_dbg_printf("Certificate cache: KEEP (SNI match or " - "target mode)\n"); - } - - return SSL_TLSEXT_ERR_OK; -} - - - -void ssl_upstream_free(struct ssl_upstream* p) -{ - X509_free(p->orig_cert); - //todo close ssl with a callback. - //SSL_free(ctx->ssl); -} - /* * Create and set up a new SSL_CTX instance for terminating SSL. * Set up all the necessary callbacks, the cert, the cert chain and key. @@ -942,7 +550,7 @@ static SSL_CTX * down_sslctx_create(struct ssl_mgr* mgr, struct cert* crt) if (!sslctx) return NULL; - pxy_sslctx_setoptions(sslctx, mgr); + sslctx_set_opts(sslctx, mgr); //TFE's OPENSSL_VERSION_NUMBER >= 0x10100000L if (mgr->sslversion) { @@ -953,9 +561,9 @@ static SSL_CTX * down_sslctx_create(struct ssl_mgr* mgr, struct cert* crt) } } - SSL_CTX_sess_set_new_cb(sslctx, pxy_ossl_sessnew_cb); - SSL_CTX_sess_set_remove_cb(sslctx, pxy_ossl_sessremove_cb); - SSL_CTX_sess_set_get_cb(sslctx, pxy_ossl_sessget_cb); + SSL_CTX_sess_set_new_cb(sslctx, ossl_sessnew_cb); + SSL_CTX_sess_set_remove_cb(sslctx, ossl_sessremove_cb); + SSL_CTX_sess_set_get_cb(sslctx, ossl_sessget_cb); SSL_CTX_set_session_cache_mode(sslctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL); #ifdef USE_SSL_SESSION_ID_CONTEXT @@ -1000,9 +608,8 @@ static SSL_CTX * down_sslctx_create(struct ssl_mgr* mgr, struct cert* crt) /* - * Create new SSL context for the incoming connection, based on the original - * destination SSL cert. - * Returns NULL if no suitable cert could be found. + * Create new SSL context for the incoming connection, based on the a designate cert + * Returns NULL when openssl error. */ struct ssl_stream * ssl_downstream_create(struct ssl_mgr* mgr, struct ssl_chello* hello, struct cert* crt) { @@ -1013,6 +620,7 @@ struct ssl_stream * ssl_downstream_create(struct ssl_mgr* mgr, struct ssl_chello } p=ALLOC(struct ssl_stream, 1); p->ref_mgr=mgr; + p->dir=CONN_DIR_DOWNSTREAM; //could be optimized by store the sslctx. SSL_CTX * sslctx = down_sslctx_create(mgr,crt); cert_mgr_free_cert(crt); @@ -1040,11 +648,125 @@ error_out: return NULL; } -void ssl_stream_free_and_close_fd(struct ssl_stream* stream, struct event_base *evbase, evutil_socket_t fd) + +/* + * Cleanly shut down an SSL socket. Libevent currently has no support for + * cleanly shutting down an SSL socket so we work around that by using a + * low-level event. This works for recent versions of OpenSSL. OpenSSL + * with the older SSL_shutdown() semantics, not exposing WANT_READ/WRITE + * may or may not work. + */ +static struct ssl_shutdown_ctx * ssl_shutdown_ctx_new(struct ssl_stream* s_stream, struct event_base *evbase) { - free(stream->sni); - stream->sni=NULL; -// X509_free(p->fake_cert); + struct ssl_shutdown_ctx *ctx = ALLOC(struct ssl_shutdown_ctx,1); + ctx->evbase = evbase; + ctx->s_stream = s_stream; + ctx->ev = NULL; + ctx->retries = 0; + return ctx; +} + +static void ssl_shutdown_ctx_free(struct ssl_shutdown_ctx *ctx) +{ + free(ctx); +} +static void ssl_stream_free(struct ssl_stream* s_stream) +{ + SSL_free(s_stream->ssl); + s_stream->ssl=NULL; + free(s_stream->sni); + s_stream->sni=NULL; + s_stream->ref_mgr=NULL + free(s_stream); + return; +} +/* + * The shutdown socket event handler. This is either + * scheduled as a timeout-only event, or as a fd read or + * fd write event, depending on whether SSL_shutdown() + * indicates it needs read or write on the socket. + */ +static void +pxy_ssl_shutdown_cb(evutil_socket_t fd, UNUSED short what, void *arg) +{ + struct ssl_shutdown_ctx *ctx = (struct ssl_shutdown_ctx *)arg; + struct timeval retry_delay = {0, 100}; + void *logger=ctx->s_stream->ref_mgr->logger; + short want = 0; + int rv=0, sslerr=0; + + if (ctx->ev) { + event_free(ctx->ev); + ctx->ev = NULL; + } + + /* + * Use the new (post-2008) semantics for SSL_shutdown() on a + * non-blocking socket. SSL_shutdown() returns -1 and WANT_READ + * if the other end's close notify was not received yet, and + * WANT_WRITE it could not write our own close notify. + * + * This is a good collection of recent and relevant documents: + * http://bugs.python.org/issue8108 + */ + rv = SSL_shutdown(ctx->s_stream->ssl); + if (rv == 1) + goto complete; + if (rv != -1) { + goto retry; + } + switch ((sslerr = SSL_get_error(ctx->s_stream->ssl, rv))) { + case SSL_ERROR_WANT_READ: + want = EV_READ; + goto retry; + case SSL_ERROR_WANT_WRITE: + want = EV_WRITE; + goto retry; + case SSL_ERROR_ZERO_RETURN: + goto retry; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + goto complete; + default: + TFE_LOG_ERROR(logger, "Unhandled SSL_shutdown() " + "error %i. Closing fd.\n", sslerr); + goto complete; + } + goto complete; + +retry: + if (ctx->retries++ >= 50) { + TFE_LOG_ERROR(logger,"Failed to shutdown SSL connection cleanly: " + "Max retries reached. Closing fd.\n"); + goto complete; + } + ctx->ev = event_new(ctx->evbase, fd, want, pxy_ssl_shutdown_cb, ctx); + if (ctx->ev) { + event_add(ctx->ev, &retry_delay); + return; + } + TFE_LOG_ERROR(logger,"Failed to shutdown SSL connection cleanly: " + "Cannot create event. Closing fd.\n"); + +complete: + ssl_stream_free(ctx->s_stream); + evutil_closesocket(fd); + ssl_shutdown_ctx_free(ctx); + +} + +/* + * Cleanly shutdown an SSL session on file descriptor fd using low-level + * file descriptor readiness events on event base evbase. + * Guarantees that SSL and the corresponding SSL_CTX are freed and the + * socket is closed, eventually, or in the case of fatal errors, immediately. + */ +void ssl_stream_free_and_close_fd(struct ssl_stream* s_stream, struct event_base *evbase, evutil_socket_t fd) +{ + struct ssl_shutdown_ctx *sslshutctx=NULL; + sslshutctx = ssl_shutdown_ctx_new(s_stream, evbase); + pxy_ssl_shutdown_cb(fd, 0, sslshutctx); + return; } From 6d7940ff0055639bb7cb92294edc1f20b0ddb89f Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 24 Aug 2018 18:38:17 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=AE=8C=E6=88=90ssl=20session=20cache?= =?UTF-8?q?=E9=83=A8=E5=88=86=E7=9A=84=E7=BC=96=E5=86=99=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platform/src/ssl_sess_cache.cpp | 299 ++++++++++++++++++++++++++++++++ platform/src/ssl_sess_cache.h | 15 ++ 2 files changed, 314 insertions(+) create mode 100644 platform/src/ssl_sess_cache.cpp create mode 100644 platform/src/ssl_sess_cache.h diff --git a/platform/src/ssl_sess_cache.cpp b/platform/src/ssl_sess_cache.cpp new file mode 100644 index 0000000..3f05093 --- /dev/null +++ b/platform/src/ssl_sess_cache.cpp @@ -0,0 +1,299 @@ +#include + +#include +#include +#include +#include + +#define SESS_CACHE_NOT_FOUND -1 +#define SESS_CACHE_FOUND 0 +#define SESS_CACHE_UPDATE_OLD 1 +#define SESS_CACHE_ADD_NEW 2 +#define SESS_CACHE_INVALID 3 + +struct asn1_sess +{ + unsigned char* buff; + size_t size; +}; +struct sess_set_args +{ + MESA_htable_handle hash; + struct asn1_sess* new_sess; +}; +struct sess_cache +{ + enum tfe_conn_dir served_for; + MESA_htable_handle hash; + long long hit_cnt, miss_cnt,del_err; +}; + +static void ssl_sess_free_serialized(void *data) +{ + struct asn1_sess* p=(struct asn1_sess*)data; + free(p->buff); + p->size=0; + free(p); + return; +} +static struct asn1_sess* ssl_sess_serialize(SSL_SESSION *sess) +{ + struct asn1_sess* result=ALLOC(struct asn1_sess,1); + result->size = i2d_SSL_SESSION(sess, NULL); + /*When using i2d_SSL_SESSION(), the memory location pointed to by pp must be large enough to hold the binary representation of the session. + There is no known limit on the size of the created ASN1 representation, so the necessary amount of space should be obtained by first calling + i2d_SSL_SESSION() with pp=NULL, and obtain the size needed, then allocate the memory and call i2d_SSL_SESSION() again.*/ + result->buff=ALLOC(unsigned char,result->size); + i2d_SSL_SESSION(sess, &(result->buff)); + return result; +} +static SSL_SESSION * ssl_sess_deserialize(const struct asn1_sess* asn1) +{ + SSL_SESSION *sess=NULL; + sess = d2i_SSL_SESSION(NULL, &(asn1->buff), asn1->size); /* increments asn1 */ + return sess; +} +static int ssl_sess_varify_cb(void *data, int eliminate_type) +{ + SSL_SESSION *sess=NULL; + int ret=0; + const struct asn1_sess* asn1=(struct asn1_sess*)data; + if(eliminate_type==ELIMINATE_TYPE_NUM) + { + return 1; //direct expired. + } + sess=ssl_sess_deserialize(asn1); + ret=ssl_session_is_valid(sess); + SSL_SESSION_free(sess); + if(ret==0) + { + return 1; //should be expired (deleted). + } + else + { + return 0; + } +} + +static long sess_cache_get_cb(void *data, const uchar *key, uint size, void *user_arg) +{ + SSL_SESSION *sess=NULL; + int is_valid=0; + if(data==NULL) + { + return SESS_CACHE_NOT_FOUND; + } + const struct asn1_sess* asn1=(struct asn1_sess*)data; + sess=ssl_sess_deserialize(data,asn1); + is_valid=ssl_session_is_valid(sess); + if(is_valid==0) + { + SSL_SESSION_free(sess); + return SESS_CACHE_INVALID; + } + else + { + *(SSL_SESSION **)user_arg=sess; + return SESS_CACHE_FOUND; + } +} + +static long sess_cache_set_cb(void *data, const uchar *key, uint size, void *user_arg) +{ + + struct sess_set_args* args=(struct sess_set_args*)user_arg; + struct asn1_sess* new_asn1=args->new_sess; + struct asn1_sess *cur_asn1=(struct asn1_sess*)data; + int ret=0; + if(cur_asn1!=NULL) + { + free(cur_asn1->buff); + cur_asn1->size=new_asn1->size; + cur_asn1->buff=ALLOC(unsigned char, cur_asn1->size); + memcpy(cur_asn1->buff,new_asn1->buff,cur_asn1->size); + return SESS_CACHE_UPDATE_OLD; + } + else + { + ret=MESA_htable_add(args->hash, key, size, new_asn1); + assert(ret>=0); + return SESS_CACHE_ADD_NEW; + } +} + +static int upsess_mk_key(struct sockaddr * addr, socklen_t addr_len, const char* sni, unsigned char** key_buf) +{ + size_t key_size=0; + unsigned char* tmp=NULL, p=NULL; + size_t tmp_size; + dynbuf_t tmp, *db; + short port; + size_t snilen; + + switch (((struct sockaddr_storage *)addr)->ss_family) { + case AF_INET: + tmp = (unsigned char *) + &((struct sockaddr_in*)addr)->sin_addr; + tmp_size = sizeof(struct in_addr); + port = ((struct sockaddr_in*)addr)->sin_port; + break; + case AF_INET6: + tmp = (unsigned char *) + &((struct sockaddr_in6*)addr)->sin6_addr; + tmp_size = sizeof(struct in6_addr); + port = ((struct sockaddr_in6*)addr)->sin6_port; + break; + default: + //should never happens. + assert(0); + break; + } + snilen = sni ? strlen(sni) : 0; + key_size=tmp_size+sizeof(port)+snilen; + *key_buf=ALLOC(unsigned char, key_size); + p=*key_buff; + memcpy(p,tmp,tmp_size); + p+=tmp_size; + memcpy(p, (char*)&port, sizeof(port)); + p+=sizeof(port); + return key_size; + +} +void up_session_set(struct sess_cache* cache, struct sockaddr * addr, socklen_t addr_len, const char* sni, SSL_SESSION * sess) +{ + char* key=NULL; + int ret=0; + size_t key_size=0; + long cb_ret=0; + void* no_use=NULL; + assert(cache->served_for==CONN_DIR_UPSTREAM); + key_size=upsess_mk_key(addr, addr_len, sni, &key); + struct asn1_sess* asn1=NULL; + asn1=ssl_sess_serialize(sess); + + struct sess_set_args set_args; + set_args.hash=cache->hash; + set_args.new_sess=asn1; + no_use=MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_set_cb, &set_args,&cb_ret); + if(cb_ret==SESS_CACHE_UPDATE_OLD) + { + ssl_sess_free_serialized(asn1); + } + free(key); + return; +} +SSL_SESSION* up_session_get(struct sess_cache* cache, struct sockaddr * addr, socklen_t addr_len, const char* sni) +{ + SSL_SESSION* sess=NULL; + void* no_use=NULL; + long cb_ret=0; + char* key=NULL; + size_t key_size=0; + assert(cache->served_for==CONN_DIR_UPSTREAM); + key_size=upsess_mk_key(addr, addr_len, sni, &key); + no_use=MESA_htable_search_cb(cache->hash, key, key_size,sess_cache_get_cb, &sess, &cb_ret); + free(key); + key=NULL; + if(cb_ret==1) + { + cache->hit_cnt++; + return sess; + } + else + { + cache->miss_cnt++; + return NULL; + } +} + +void down_session_set(struct sess_cache* cache, const SSL_SESSION* sess) +{ + unsigned int idlen=0; + struct asn1_sess* asn1=NULL; + long cb_ret=0; + void* no_use=NULL; + int ret=0; + assert(cache->served_for==CONN_DIR_DOWNSTREAM); + asn1=ssl_sess_serialize(sess); + /* + * SSL_SESSION_get_id() returns a pointer to the internal session id value for the session s. + * The length of the id in bytes is stored in *idlen. The length may be 0. + * The caller should not free the returned pointer directly. + */ + const unsigned char* id = SSL_SESSION_get_id(sess, &idlen); + struct sess_set_args set_args; + set_args.hash=cache->hash; + set_args.new_sess=asn1; + no_use=MESA_htable_search_cb(cache->hash, id, (unsigned int)idlen, sess_cache_set_cb, &set_args,&cb_ret); + if(cb_ret==SESS_CACHE_UPDATE_OLD) + { + ssl_sess_free_serialized(asn1); + } + return; +} +SSL_SESSION* down_session_get(struct sess_cache* cache, unsigned char * id, int idlen) +{ + SSL_SESSION* sess=NULL; + void* no_use=NULL; + long cb_ret=0; + assert(cache->served_for==CONN_DIR_DOWNSTREAM); + no_use=MESA_htable_search_cb(cache->hash, id, (unsigned int)idlen, sess_cache_get_cb, &sess,&cb_ret); + if(cb_ret==1) + { + cache->hit_cnt++; + return sess; + } + else + { + cache->miss_cnt++; + return NULL; + } +} + +void down_session_del(struct sess_cache* cache, const SSL_SESSION* sess) +{ + assert(cache->served_for==CONN_DIR_DOWNSTREAM); + unsigned int len=0; + const unsigned char* id = SSL_SESSION_get_id(sess, &len); + int ret=MESA_htable_del(cache->hash, id, len, NULL); + if(ret!=MESA_HTABLE_RET_OK) + { + cache->del_err++; + } + return; +} +struct sess_cache* ssl_sess_cache_create(int slot_size, int expire_seconds, enum tfe_conn_dir served) +{ + struct sess_cache* cache=ALLOC(struct sess_cache, 1); + MESA_htable_handle htable=NULL; + int ret=0,max_num=slot_size*4; + htable=MESA_htable_born(); + value=0;//no print + ret=MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, &(value), sizeof(value)); + value=1;//thread safe + ret=MESA_htable_set_opt(htable, MHO_THREAD_SAFE, value, sizeof(value)); + assert(ret==0); + value=16; + ret=MESA_htable_set_opt(htable, MHO_MUTEX_NUM, value, sizeof(value)); + ret=MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &(slot_size), sizeof(slot_size)); + ret=MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &(max_num), sizeof(max_num)); + ret=MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &(expire_seconds), sizeof(expire_seconds)); + value=HASH_ELIMINATE_ALGO_FIFO; + ret=MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &(value), sizeof(value)); + ret=MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, ssl_sess_free_serialized, sizeof(ssl_sess_free_serialized)); + ret=MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY, ssl_sess_varify_cb, sizeof(ssl_sess_varify_cb)); + assert(ret==0); + ret=MESA_htable_mature(htable); + assert(ret==0); + cache->hash=htable; + cache->served_for=served; + return cache; +} +void ssl_sess_cache_destroy(struct sess_cache* cache) +{ + MESA_htable_destroy(cache->hash, NULL); + cache->hash=NULL; + free(cache); + return; +} + diff --git a/platform/src/ssl_sess_cache.h b/platform/src/ssl_sess_cache.h new file mode 100644 index 0000000..ece9db0 --- /dev/null +++ b/platform/src/ssl_sess_cache.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +#include + +struct sess_cache; +struct sess_cache* ssl_sess_cache_create(int slot_size, int expire_seconds, enum tfe_conn_dir served); +void ssl_sess_cache_destroy(struct sess_cache* cache); + +void up_session_set(struct sess_cache* cache, struct sockaddr * addr, socklen_t addr_len, const char* sni, SSL_SESSION * value) +SSL_SESSION* up_session_get(struct sess_cache* cache, struct sockaddr *addr, socklen_t addr_len, const char* sni); +void down_session_set(struct sess_cache* cache, const SSL_SESSION* sess); +SSL_SESSION* down_session_get(struct sess_cache* cache, unsigned char * id, int idlen); + From b000487322d5f34dd0dc0adee5452962db8993d2 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 24 Aug 2018 19:22:43 +0800 Subject: [PATCH 3/3] =?UTF-8?q?ssl=20stream=E9=9A=90=E8=97=8Fpeek=5Fsni?= =?UTF-8?q?=E5=92=8Ccert=20store=E7=9A=84=E5=A4=84=E7=90=86=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platform/include/internal/ssl_stream.h | 27 ++--- platform/src/ssl_stream.cpp | 160 ++++++++++++++----------- 2 files changed, 95 insertions(+), 92 deletions(-) diff --git a/platform/include/internal/ssl_stream.h b/platform/include/internal/ssl_stream.h index 47b619f..b6407fc 100644 --- a/platform/include/internal/ssl_stream.h +++ b/platform/include/internal/ssl_stream.h @@ -2,35 +2,22 @@ #include #include #include - +#include struct ssl_stream; struct ssl_mgr; -struct ssl_mgr* init_ssl_manager(const char* ini_profile, const char* section, void* logger); -void destroy_ssl_manager(struct ssl_mgr* mgr); - -struct ssl_chello -{ - //client hello - int version; - char* sni; - char* cipher_suites; -}; - -struct ssl_chello* ssl_peek_result_release_chello(future_result_t* result); -void ssl_chello_free(struct ssl_chello* client_hello); -void ssl_async_peek_client_hello(struct future* future, evutil_socket_t fd, struct event_base *evbase); - +struct ssl_mgr* ssl_manager_init(const char* ini_profile, const char* section, struct event_base *evbase, void* logger, screen_stat_handle_t* fs); +void ssl_manager_destroy(struct ssl_mgr* mgr); struct ssl_stream* ssl_upstream_create_result_release_stream(future_result_t* result); struct bufferevent* ssl_upstream_create_result_release_bev(future_result_t* result); -void ssl_async_upstream_create(struct future* future, struct ssl_mgr* mgr, const struct ssl_chello* chello, evutil_socket_t fd, struct event_base *evbase); +void ssl_async_upstream_create(struct future* f, struct ssl_mgr* mgr, evutil_socket_t fd_upstream, evutil_socket_t fd_downstream, struct event_base *evbase); +struct ssl_stream* ssl_downstream_create_result_release_stream(future_result_t* result); +struct bufferevent* ssl_downstream_create_result_release_bev(future_result_t* result); +void ssl_async_downstream_create(struct future* f, struct ssl_mgr* mgr, struct ssl_stream* upstream, evutil_socket_t fd_downstream, struct event_base *evbase); - -struct ssl_stream * ssl_downstream_create(struct ssl_mgr* mgr, struct ssl_chello* hello, struct cert* crt); void ssl_stream_free_and_close_fd(struct ssl_stream* stream, struct event_base *evbase, evutil_socket_t fd); - diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index ba0c5de..c6f3565 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -27,23 +27,27 @@ #include #include #include +#include #include #include #define SSL_EX_DATA_IDX_SSLMGR 0 +#define MAX_NET_RETRIES 50 struct ssl_mgr { - uint8_t sslcomp; - uint8_t no_ssl2; - uint8_t no_ssl3; - uint8_t no_tls10; - uint8_t no_tls11; - uint8_t no_tls12; - CONST_SSL_METHOD *(*sslmethod)(void); + int sslcomp; + int no_ssl2; + int no_ssl3; + int no_tls10; + int no_tls11; + int no_tls12; + CONST_SSL_METHOD *(*sslmethod)(void); //Parameter of SSL_CTX_new int sslversion; char ssl_session_context[8]; - MESA_htable_handle down_sess_cache; - MESA_htable_handle up_sess_cache; - char* default_ciphers; + int cache_slot_num; + int sess_expire_seconds; + struct sess_cache* down_sess_cache; + struct sess_cache* up_sess_cache; + char* default_ciphers[TFE_SYMBOL_MAX]; DH * dh; char * ecdhcurve; char * crlurl; @@ -57,13 +61,19 @@ struct ssl_stream struct ssl_mgr* ref_mgr; char* sni; }; +struct ssl_chello +{ + //client hello + int version; + char* sni; + char* cipher_suites; +}; + struct peek_client_hello_ctx { - unsigned char sni_peek_retries; /* max 64 SNI parse retries */ struct event* ev; struct event_base* evbase; - }; struct ssl_connect_origin_ctx { @@ -81,64 +91,76 @@ struct ssl_shutdown_ctx { struct event *ev; unsigned int retries; }; - -struct ssl_mgr* init_ssl_manager(const char* ini_profile, const char* section, void* logger) +static int parse_ssl_version(const char * version_str) { - struct ssl_mgr* mgr=ALLOC(struct ssl_mgr, 1); - mgr->logger=logger; - memcpy(mgr->ssl_session_context,"mesa-tfe",sizeof(mgr->ssl_session_context)); - return mgr; + int sslversion=-1; + assert(OPENSSL_VERSION_NUMBER >= 0x10100000L); + /* + * Support for SSLv2 and the corresponding SSLv2_method(), + * SSLv2_server_method() and SSLv2_client_method() functions were + * removed in OpenSSL 1.1.0. + */ + if (!strcmp(version_str, "ssl3")) + { + sslversion = SSL3_VERSION; + } + else if (!strcmp(version_str, "tls10") || !strcmp(version_str, "tls1")) + { + sslversion = TLS1_VERSION; + } + else if (!strcmp(version_str, "tls11")) + { + sslversion = TLS1_1_VERSION; + } + else if (!strcmp(version_str, "tls12")) + { + sslversion = TLS1_2_VERSION; + } + else + { + sslversion =-1; + } + return sslversion; } -void destroy_ssl_manager(struct ssl_mgr* mgr) +void ssl_manager_destroy(struct ssl_mgr* mgr) { free(mgr); } -SSL_SESSION* up_session_get(MESA_htable_handle* cache, struct sockaddr * addr, socklen_t addr_len, const char* sni) -{ -} -void up_session_set(MESA_htable_handle* cache, struct sockaddr * addr, socklen_t addr_len, const char* sni, SSL_SESSION * value) +struct ssl_mgr* ssl_manager_init(const char* ini_profile, const char* section, void* logger) { - -} -SSL_SESSION* down_session_get(MESA_htable_handle* cache, unsigned char * id, int idlen) -{ - dynbuf_t *valbuf = (dynbuf_t *)val; - MESA_htable_search_cb(const MESA_htable_handle table, const uchar * key, uint size, hash_cb_fun_t * cb, void * arg, long * cb_ret); - SSL_SESSION *sess; - const unsigned char *p; - - p = (const unsigned char *)valbuf->buf; - sess = d2i_SSL_SESSION(NULL, &p, valbuf->sz); /* increments p */ - if (!sess) - return NULL; - if (!ssl_session_is_valid(sess)) { - SSL_SESSION_free(sess); - return NULL; + struct ssl_mgr* mgr=ALLOC(struct ssl_mgr, 1); + int ret=0,value=0; + char version_str[TFE_SYMBOL_MAX]; + mgr->logger=logger; + MESA_load_profile_string_def(ini_profile, section, "ssl_version", version_str, sizeof(version_str),"tls12"); + mgr->sslversion=parse_ssl_version(version_str); + if(mgr->sslversion<0) + { + TFE_LOG_ERROR(logger, "Unsupported SSL/TLS protocol %s",version_str); + goto error_out; } - if (copy) - return sess; - SSL_SESSION_free(sess); - return ((void*)-1); + //tfe2a uses SSLv23_method, it was been deprecated and replaced with the TLS_method() in openssl 1.1.0. + mgr->sslmethod=TLS_method; + MESA_load_profile_int_def(ini_profile, section, "ssl_compression", &(mgr->sslcomp), 1); + MESA_load_profile_int_def(ini_profile, section, "no_ssl2", &(mgr->no_ssl2), 1); + MESA_load_profile_int_def(ini_profile, section, "no_ssl3", &(mgr->no_ssl3), 1); + MESA_load_profile_int_def(ini_profile, section, "no_tls10", &(mgr->no_tls10), 1); + MESA_load_profile_int_def(ini_profile, section, "no_tls11", &(mgr->no_tls11), 0); + MESA_load_profile_int_def(ini_profile, section, "no_tls12", &(mgr->no_tls12), 0); + MESA_load_profile_int_def(ini_profile, section, "session_cache_slot_num", &(mgr->cache_slot_num), 4*1024*1024); + MESA_load_profile_int_def(ini_profile, section, "session_cache_slot_num", &(mgr->sess_expire_seconds), 30*60); + + mgr->up_sess_cache=ssl_sess_cache_create(mgr->cache_slot_num, mgr->sess_expire_seconds,CONN_DIR_UPSTREAM); + mgr->down_sess_cache=ssl_sess_cache_create(mgr->cache_slot_num, mgr->sess_expire_seconds,CONN_DIR_DOWNSTREAM); + memcpy(mgr->ssl_session_context,"mesa-tfe",sizeof(mgr->ssl_session_context)); + return mgr; +error_out: + ssl_manager_destroy(mgr); + return NULL; } -void down_session_set(MESA_htable_handle* cache, SSL_SESSION* sess) -{ - unsigned int len=0; - const unsigned char* id = SSL_SESSION_get_id(sess, &len); - unsigned char *p=NULL; - size_t asn1sz=0; - asn1sz = i2d_SSL_SESSION(sess, NULL); - p=ALLOC(char, asn1sz); - i2d_SSL_SESSION(sess, &p); /* updates p */ - int ret=MESA_htable_add(cache, id, len, p); - return; -} -void down_session_del(MESA_htable_handle* cache, SSL_SESSION* sess) -{ - -} void peek_client_hello_ctx_free(void* ctx) { @@ -223,7 +245,7 @@ static void peek_client_hello_cb(evutil_socket_t fd, short what, void * arg) goto failed; } - if(ctx->sni_peek_retries++ > 50) + if(ctx->sni_peek_retries++ > MAX_NET_RETRIES) { TFE_LOG_ERROR("Peek failed due to too many retries\n"); reason="too many peek retries"; @@ -324,11 +346,6 @@ static SSL* upstream_ssl_create(struct ssl_mgr* mgr, const struct ssl_chello* ch return ssl; } - -void ssl_stream_shutdown(struct bufferevent *bev,struct ssl_stream* ssl) -{ - //TODO: -} void ssl_connect_origin_ctx_free(struct ssl_connect_origin_ctx* ctx) { if(ctx->ssl!=NULL) @@ -395,7 +412,7 @@ static void ssl_connect_origin_eventcb(struct bufferevent * bev, short events, v return } -void ssl_async_connect_origin(struct future* future, struct ssl_mgr* mgr, const struct ssl_chello* chello, evutil_socket_t fd, struct event_base *evbase) +void ssl_async_upstream_create(struct future* f, struct ssl_mgr* mgr, const struct ssl_chello* chello, evutil_socket_t fd, struct event_base *evbase) { struct promise* p=future_to_promise(future); struct ssl_connect_origin_ctx* ctx=ALLOC(struct ssl_connect_origin_ctx, 1); @@ -453,6 +470,7 @@ static void ossl_sessremove_cb(UNUSED SSL_CTX * sslctx, SSL_SESSION * sess) { struct ssl_mgr* mgr=(struct ssl_mgr*) SSL_get_ex_data(ssl, SSL_EX_DATA_IDX_SSLMGR, mgr); + assert(mgr!=NULL); if (sess) { down_session_del(mgr->down_sess_cache, sess); @@ -566,11 +584,8 @@ static SSL_CTX * down_sslctx_create(struct ssl_mgr* mgr, struct cert* crt) SSL_CTX_sess_set_get_cb(sslctx, ossl_sessget_cb); SSL_CTX_set_session_cache_mode(sslctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL); -#ifdef USE_SSL_SESSION_ID_CONTEXT SSL_CTX_set_session_id_context(sslctx, (void *)(mgr->ssl_session_context), sizeof(mgr->ssl_session_context)); -#endif /* USE_SSL_SESSION_ID_CONTEXT */ - #ifndef OPENSSL_NO_DH if (mgr->dh) { @@ -611,8 +626,9 @@ static SSL_CTX * down_sslctx_create(struct ssl_mgr* mgr, struct cert* crt) * Create new SSL context for the incoming connection, based on the a designate cert * Returns NULL when openssl error. */ -struct ssl_stream * ssl_downstream_create(struct ssl_mgr* mgr, struct ssl_chello* hello, struct cert* crt) +void ssl_async_downstream_create(struct future* f, struct ssl_mgr* mgr, struct ssl_chello* hello, evutil_socket_t fd, struct event_base *evbase) { + struct cert* crt; struct ssl_stream* p=NULL; if(crt==NULL) { @@ -639,7 +655,7 @@ struct ssl_stream * ssl_downstream_create(struct ssl_mgr* mgr, struct ssl_chello if(mgr->SSL_MODE_RELEASE_BUFFERS==1) { /* lower memory footprint for idle connections */ - SSL_set_mode( p->ssl, SSL_get_mode(p->ssl) | SSL_MODE_RELEASE_BUFFERS); + SSL_set_mode(p->ssl, SSL_get_mode(p->ssl) | SSL_MODE_RELEASE_BUFFERS); } p->sni=tfe_strdup(hello->sni); return p; @@ -735,7 +751,7 @@ pxy_ssl_shutdown_cb(evutil_socket_t fd, UNUSED short what, void *arg) goto complete; retry: - if (ctx->retries++ >= 50) { + if (ctx->retries++ >= MAX_NET_RETRIES) { TFE_LOG_ERROR(logger,"Failed to shutdown SSL connection cleanly: " "Max retries reached. Closing fd.\n"); goto complete;