修复ssl session缓存中对openssl的不正确使用。

This commit is contained in:
zhengchao
2018-09-05 19:49:37 +08:00
parent bec5631a7d
commit 6bc0409756
5 changed files with 51 additions and 26 deletions

View File

@@ -27,3 +27,5 @@ struct bufferevent * ssl_downstream_create_result_release_bev(future_result_t *
void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct ssl_stream * upstream, void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct ssl_stream * upstream,
evutil_socket_t fd_downstream, int keyring_id, struct event_base * evbase); evutil_socket_t fd_downstream, int keyring_id, struct event_base * evbase);
void ssl_stream_free_and_close_fd(struct ssl_stream * stream, struct event_base * evbase, evutil_socket_t fd); void ssl_stream_free_and_close_fd(struct ssl_stream * stream, struct event_base * evbase, evutil_socket_t fd);
void ssl_stream_log_error(struct bufferevent * bev, enum tfe_conn_dir dir, void* logger);

View File

@@ -111,7 +111,6 @@ static void __signal_handler_cb(evutil_socket_t fd, short what, void * arg)
{ {
case SIGTERM: case SIGTERM:
case SIGQUIT: case SIGQUIT:
case SIGINT:
case SIGHUP: case SIGHUP:
break; break;
case SIGUSR1: case SIGUSR1:
@@ -127,9 +126,11 @@ static void __signal_handler_cb(evutil_socket_t fd, short what, void * arg)
static void __gc_handler_cb(evutil_socket_t fd, short what, void * arg) static void __gc_handler_cb(evutil_socket_t fd, short what, void * arg)
{ {
tfe_proxy * ctx = (tfe_proxy *) arg; /* tfe_proxy * ctx = (tfe_proxy *) arg;
(void)fd; (void)fd;
(void)what; (void)what;
*/
return;
} }
static void * __thread_ctx_entry(void * arg) static void * __thread_ctx_entry(void * arg)
@@ -166,7 +167,7 @@ struct tfe_thread_ctx * __thread_ctx_create(struct tfe_proxy * proxy, unsigned i
int ret = pthread_create(&__thread_ctx->thr, NULL, __thread_ctx_entry, (void *)__thread_ctx); int ret = pthread_create(&__thread_ctx->thr, NULL, __thread_ctx_entry, (void *)__thread_ctx);
if (unlikely(ret < 0)) if (unlikely(ret < 0))
{ {
TFE_LOG_ERROR(proxy->logger, "Failed at pthread_create() for thread %d: %s", strerror(errno)); TFE_LOG_ERROR(proxy->logger, "Failed at pthread_create() for thread %d: %s",errno, strerror(errno));
goto __errout; goto __errout;
} }
@@ -229,6 +230,13 @@ int main(int argc, char *argv[])
g_default_proxy->kni_acceptor_handler = kni_acceptor_init(g_default_proxy, main_profile, g_default_logger); g_default_proxy->kni_acceptor_handler = kni_acceptor_init(g_default_proxy, main_profile, g_default_logger);
CHECK_OR_EXIT(g_default_proxy->kni_acceptor_handler, "Failed at init KNI acceptor. Exit. "); CHECK_OR_EXIT(g_default_proxy->kni_acceptor_handler, "Failed at init KNI acceptor. Exit. ");
for (size_t i = 0; i < (sizeof(signals) / sizeof(int)); i++)
{
g_default_proxy->sev[i] = evsignal_new(g_default_proxy->evbase, signals[i], __signal_handler_cb, g_default_proxy);
CHECK_OR_EXIT( g_default_proxy->sev[i], "Failed at create signal event. Exit.");
evsignal_add(g_default_proxy->sev[i], NULL);
}
struct timeval gc_delay = {60, 0}; struct timeval gc_delay = {60, 0};
evtimer_add(g_default_proxy->gcev , &gc_delay); evtimer_add(g_default_proxy->gcev , &gc_delay);

View File

@@ -7,11 +7,11 @@
#include <MESA/MESA_htable.h> #include <MESA/MESA_htable.h>
#include <MESA/field_stat2.h> #include <MESA/field_stat2.h>
#define SESS_CACHE_NOT_FOUND -1 #define SESS_CACHE_NOT_FOUND -1
#define SESS_CACHE_FOUND 0 #define SESS_CACHE_FOUND 0
#define SESS_CACHE_UPDATE_OLD 1 #define SESS_CACHE_UPDATE_OLD 1
#define SESS_CACHE_ADD_NEW 2 #define SESS_CACHE_ADD_NEW 2
#define SESS_CACHE_INVALID 3 #define SESS_CACHE_INVALID 3
struct asn1_sess struct asn1_sess
{ {
@@ -45,25 +45,34 @@ static struct asn1_sess * ssl_sess_serialize(SSL_SESSION * sess)
{ {
struct asn1_sess * result = ALLOC(struct asn1_sess, 1); struct asn1_sess * result = ALLOC(struct asn1_sess, 1);
int __i2d_size = i2d_SSL_SESSION(sess, NULL); int i = i2d_SSL_SESSION(sess, NULL), j=0;
result->size = (size_t) __i2d_size; result->size = (size_t) i;
assert(__i2d_size > 0); unsigned char* temp=NULL;
assert(i > 0);
/* When using i2d_SSL_SESSION(), the memory location pointed to by pp must be large enough to /* 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 * 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 * 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, * calling i2d_SSL_SESSION() with pp=NULL, and obtain the size needed,
* then allocate the memory and call i2d_SSL_SESSION() again.*/ * then allocate the memory and call i2d_SSL_SESSION() again.
*Note that this will advance the value contained in *pp so it is necessary to save a copy of the original allocation.*/
result->buff = ALLOC(unsigned char, result->size); result->buff = temp = ALLOC(unsigned char, result->size);
i2d_SSL_SESSION(sess, &(result->buff));
j=i2d_SSL_SESSION(sess, &(temp));
assert(i == j);
assert(result->buff + i == temp);
return result; return result;
} }
static SSL_SESSION * ssl_sess_deserialize(const struct asn1_sess * asn1) static SSL_SESSION * ssl_sess_deserialize(const struct asn1_sess * asn1)
{ {
SSL_SESSION * sess = NULL; SSL_SESSION * sess = NULL;
d2i_SSL_SESSION(&sess, (const unsigned char **) &(asn1->buff), (long) asn1->size); /* increments asn1 */
const unsigned char *p=asn1->buff;
/* i2d_SSL_SESSION increments the pointer pointed to by p to point one byte after the saved data
* We save the pointer first.*/
sess=d2i_SSL_SESSION(NULL, &(p), (long) asn1->size); /* increments asn1 */
assert(sess!=NULL);
return sess; return sess;
} }
@@ -188,7 +197,7 @@ void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t
struct asn1_sess * asn1 = NULL; struct asn1_sess * asn1 = NULL;
asn1 = ssl_sess_serialize(sess); asn1 = ssl_sess_serialize(sess);
struct sess_set_args set_args{.hash = cache->hash, .new_sess = asn1}; struct sess_set_args set_args={.hash = cache->hash, .new_sess = asn1};
MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_set_cb, &set_args, &cb_ret); MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_set_cb, &set_args, &cb_ret);
if (cb_ret == SESS_CACHE_UPDATE_OLD) if (cb_ret == SESS_CACHE_UPDATE_OLD)
{ {
@@ -211,7 +220,7 @@ SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr,
MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_get_cb, &sess, &cb_ret); MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_get_cb, &sess, &cb_ret);
free(key); free(key);
key = NULL; key = NULL;
if (cb_ret == 1) if (cb_ret == SESS_CACHE_FOUND)
{ {
ATOMIC_INC(&(cache->hit_cnt)); ATOMIC_INC(&(cache->hit_cnt));
return sess; return sess;
@@ -238,9 +247,9 @@ void down_session_set(struct sess_cache * cache, const SSL_SESSION * sess)
*/ */
const unsigned char * id = SSL_SESSION_get_id(sess, &idlen); const unsigned char * id = SSL_SESSION_get_id(sess, &idlen);
struct sess_set_args set_args{.hash = cache->hash, .new_sess = asn1}; struct sess_set_args set_args={.hash = cache->hash, .new_sess = asn1};
MESA_htable_search_cb(cache->hash, id, (unsigned int) idlen, sess_cache_set_cb, &set_args, &cb_ret); MESA_htable_search_cb(cache->hash, id, idlen, sess_cache_set_cb, &set_args, &cb_ret);
if (cb_ret == SESS_CACHE_UPDATE_OLD) if (cb_ret == SESS_CACHE_UPDATE_OLD)
{ {
ssl_sess_free_serialized(asn1); ssl_sess_free_serialized(asn1);
@@ -254,7 +263,7 @@ SSL_SESSION * down_session_get(struct sess_cache * cache, const unsigned char *
long cb_ret = 0; long cb_ret = 0;
assert(cache->served_for == CONN_DIR_DOWNSTREAM); assert(cache->served_for == CONN_DIR_DOWNSTREAM);
MESA_htable_search_cb(cache->hash, id, (unsigned int) idlen, sess_cache_get_cb, &sess, &cb_ret); MESA_htable_search_cb(cache->hash, id, (unsigned int) idlen, sess_cache_get_cb, &sess, &cb_ret);
if (cb_ret == 1) if (cb_ret == SESS_CACHE_FOUND)
{ {
ATOMIC_INC(&(cache->hit_cnt)); ATOMIC_INC(&(cache->hit_cnt));
return sess; return sess;

View File

@@ -683,10 +683,10 @@ struct bufferevent * ssl_upstream_create_result_release_bev(future_result_t * re
ctx->bev = NULL; //giveup ownership ctx->bev = NULL; //giveup ownership
return ret; return ret;
} }
void ssl_handle_conn_origin_err(struct bufferevent * bev, void* logger) void ssl_stream_log_error(struct bufferevent * bev, enum tfe_conn_dir dir, void* logger)
{ {
unsigned long sslerr=0; unsigned long sslerr=0;
const char* dir_str=(dir==CONN_DIR_DOWNSTREAM?"downstream":"upstream");
/* Can happen for socket errs, ssl errs; /* Can happen for socket errs, ssl errs;
* may happen for unclean ssl socket shutdowns. */ * may happen for unclean ssl socket shutdowns. */
sslerr = bufferevent_get_openssl_error(bev); sslerr = bufferevent_get_openssl_error(bev);
@@ -703,8 +703,9 @@ void ssl_handle_conn_origin_err(struct bufferevent * bev, void* logger)
{ {
/* these can happen due to client cert auth, /* these can happen due to client cert auth,
* only log error if debugging is activated */ * only log error if debugging is activated */
TFE_LOG_ERROR(logger,"Error from upstream bufferevent: " TFE_LOG_ERROR(logger,"Handshake Error from %s bufferevent: "
"%i:%s %lu:%i:%s:%i:%s:%i:%s\n", "%i:%s %lu:%i:%s:%i:%s:%i:%s\n",
dir_str,
errno, errno,
errno ? strerror(errno) : "-", errno ? strerror(errno) : "-",
sslerr, sslerr,
@@ -733,8 +734,9 @@ void ssl_handle_conn_origin_err(struct bufferevent * bev, void* logger)
else else
{ {
/* real errors */ /* real errors */
TFE_LOG_ERROR(logger,"Error from upstream bufferevent: " TFE_LOG_ERROR(logger,"Error from %s bufferevent: "
"%i:%s %lu:%i:%s:%i:%s:%i:%s\n", "%i:%s %lu:%i:%s:%i:%s:%i:%s\n",
dir_str,
errno, errno,
errno ? strerror(errno) : "-", errno ? strerror(errno) : "-",
sslerr, sslerr,
@@ -778,7 +780,7 @@ static void ssl_connect_origin_eventcb(struct bufferevent * bev, short events, v
if (events & BEV_EVENT_ERROR) if (events & BEV_EVENT_ERROR)
{ {
ATOMIC_INC(&(ctx->mgr->stat_val[SSL_UP_ERR])); ATOMIC_INC(&(ctx->mgr->stat_val[SSL_UP_ERR]));
ssl_handle_conn_origin_err(bev,ctx->mgr->logger); ssl_stream_log_error(bev, CONN_DIR_UPSTREAM, ctx->mgr->logger);
promise_failed(promise, FUTURE_ERROR_EXCEPTION, "connect to original server failed."); promise_failed(promise, FUTURE_ERROR_EXCEPTION, "connect to original server failed.");
} }
else if(events & BEV_EVENT_EOF) else if(events & BEV_EVENT_EOF)

View File

@@ -404,6 +404,10 @@ static void __stream_bev_eventcb(struct bufferevent * bev, short events, void *
{ {
this_conn->closed = 1; this_conn->closed = 1;
reason = REASON_ERROR; reason = REASON_ERROR;
if(__IS_SSL(_stream))
{
ssl_stream_log_error(bev, dir, __STREAM_LOGGER(_stream));
}
goto call_plugin_close; goto call_plugin_close;
} }