diff --git a/common/include/tfe_utils.h b/common/include/tfe_utils.h index 19f950e..235161e 100644 --- a/common/include/tfe_utils.h +++ b/common/include/tfe_utils.h @@ -100,7 +100,7 @@ char* tfe_strdup(const char* s); #include -static inline void tfe_hexdump(FILE *f, const char * title, const void * buf, unsigned int len) +static inline void tfe_hexdump2file(FILE *f, const char * title, const void * buf, unsigned int len) { unsigned int i, out, ofs; const unsigned char *data = (const unsigned char *)buf; @@ -129,3 +129,15 @@ static inline void tfe_hexdump(FILE *f, const char * title, const void * buf, un #undef LINE_LEN } +static inline unsigned char* tfe_hexdump(unsigned char *dst, unsigned char *src, size_t len) +{ + static unsigned char hex[] = "0123456789abcdef"; + + while (len--) { + *dst++ = hex[*src >> 4]; + *dst++ = hex[*src++ & 0xf]; + } + + return dst; +} + diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index 201b25b..f0440ec 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -32,7 +32,7 @@ #include #include -#define SSL_EX_DATA_IDX_SSLMGR 0 +int SSL_EX_DATA_IDX_SSLMGR; #define MAX_NET_RETRIES 50 /* @@ -66,12 +66,22 @@ enum ssl_stream_stat SSL_DOWN_CACHE_SZ, SSL_DOWN_CACHE_QUERY, SSL_DOWN_CACHE_HIT, + SSL_DOWN_TICKET_NEW, + SSL_DOWN_TICKET_REUSE, SSL_NO_CHELLO, SSL_NO_SNI, SSL_FAKE_CRT, SSL_STAT_MAX }; + +struct session_ticket_key +{ + size_t size; + unsigned char name[16]; + unsigned char hmac_key[32]; + unsigned char aes_key[32]; +} ; struct ssl_mgr { unsigned int sslcomp; @@ -91,6 +101,9 @@ struct ssl_mgr struct sess_cache * down_sess_cache; struct sess_cache * up_sess_cache; + struct session_ticket_key ticket_key; + + char default_ciphers[TFE_STRING_MAX]; DH * dh; char * ecdhcurve; @@ -206,6 +219,8 @@ void ssl_stat_init(struct ssl_mgr * mgr) spec[SSL_DOWN_CACHE_SZ]="dsess_cache"; spec[SSL_DOWN_CACHE_QUERY]="dcache_query"; spec[SSL_DOWN_CACHE_HIT]="dsess_hitcnt"; + spec[SSL_DOWN_TICKET_NEW]="dtkt_new"; + spec[SSL_DOWN_TICKET_REUSE]="dtkt_reuse"; spec[SSL_NO_CHELLO]="ssl_no_chlo"; spec[SSL_NO_SNI]="ssl_no_sni"; @@ -396,7 +411,13 @@ ssl_stream_gc_cb(evutil_socket_t fd, short what, void * arg) struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section, struct event_base * ev_base_gc, void * logger, screen_stat_handle_t fs) { - struct timeval gc_delay = {0, 500*1000}; //Microseconds, we set 500 miliseconds here. + struct timeval gc_delay = {0, 500*1000}; //Microseconds, we set 500 miliseconds here. + unsigned char key_name[]="!mesalab-tfe3a~&"; + unsigned char aes_key_def[]={0xC5,0xAC,0xC1,0xA6,0xB2,0xBB,0xCA,0xC7,0xE3,0xBE,0xE3,0xB2,0xC6,0xA3,0xB1,0xB9 + ,0xA3,0xAC,0xB6,0xF8,0xCA,0xC7,0xD1,0xDB,0xBE,0xA6,0xC0,0xEF,0xD3,0xD0,0xB9,0x84}; + unsigned char hmac_key_def[]={0xD6,0xC8,0xD0,0xF2,0xC8,0xCB,0xBF,0xDA,0xBA,0xCD,0xBF,0xC6,0xBC,0xBC,0xA3,0xAC + ,0xC8,0xCB,0xC0,0xE0,0xC9,0xE7,0xBB,0xE1,0xB5,0xC4,0xBB,0xF9,0xCA,0xAF,0x19,0x84}; + struct ssl_mgr * mgr = ALLOC(struct ssl_mgr, 1); int ret = 0; char version_str[TFE_SYMBOL_MAX]; @@ -421,6 +442,7 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section } //tfe2a uses SSLv23_method, it was been deprecated and replaced with the TLS_method() in openssl 1.1.0. mgr->sslmethod = TLS_method; + SSL_EX_DATA_IDX_SSLMGR = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); MESA_load_profile_uint_def(ini_profile, section, "ssl_compression", &(mgr->sslcomp), 1); MESA_load_profile_uint_def(ini_profile, section, "no_ssl2", &(mgr->no_ssl2), 1); MESA_load_profile_uint_def(ini_profile, section, "no_ssl3", &(mgr->no_ssl3), 1); @@ -437,6 +459,13 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section mgr->up_sess_cache = ssl_sess_cache_create(mgr->cache_slots, mgr->sess_expire_seconds, CONN_DIR_UPSTREAM); mgr->down_sess_cache = ssl_sess_cache_create(mgr->cache_slots, mgr->sess_expire_seconds, CONN_DIR_DOWNSTREAM); + + //Reference to NGINX: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_ticket_key + //Support key rotation in futher. + + memcpy(mgr->ticket_key.name,key_name, sizeof(mgr->ticket_key.name)); + memcpy(mgr->ticket_key.aes_key, aes_key_def, sizeof(mgr->ticket_key.aes_key)); + memcpy(mgr->ticket_key.hmac_key, hmac_key_def, sizeof(mgr->ticket_key.hmac_key)); mgr->key_keeper = key_keeper_init(ini_profile, "key_keeper", logger); if (mgr->key_keeper == NULL) { @@ -926,6 +955,82 @@ extern void ssl_async_upstream_create(struct future * f, struct ssl_mgr * mgr, e ssl_async_peek_client_hello(ctx->f_peek_chello, fd_downstream, evbase, mgr->logger); } +static int ossl_session_ticket_key_callback(SSL *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc) +{ + const EVP_MD *digest=NULL; + const EVP_CIPHER *cipher=NULL; + size_t size=0; + struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl_conn, SSL_EX_DATA_IDX_SSLMGR); + struct session_ticket_key* key=&(mgr->ticket_key); + assert(mgr!=NULL); + digest = EVP_sha256(); + unsigned char buf[32]; + + if (enc == 1) + { + /* encrypt session ticket */ + cipher = EVP_aes_256_cbc(); + size = 32; + + if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) + { + TFE_LOG_ERROR(mgr->logger, "Session Ticket RAND_bytes() failed"); + return -1; + } + + if (EVP_EncryptInit_ex(ectx, cipher, NULL, key[0].aes_key, iv) != 1) + { + TFE_LOG_ERROR(mgr->logger, "EVP_EncryptInit_ex() failed"); + return -1; + } + + if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1) + { + TFE_LOG_ERROR(mgr->logger, "HMAC_Init_ex() failed"); + return -1; + } + memcpy(name, key[0].name, 16); + ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TICKET_NEW])); + return 1; + + } + else + { + /* decrypt session ticket */ + if(0!=memcmp(name, key[0].name, 16)) + { + TFE_LOG_INFO(mgr->logger, "ssl session ticket decrypt, key: \"%*s\" not found" + ,tfe_hexdump(buf, name ,16)-buf, buf); + return 0; + } + + cipher = EVP_aes_256_cbc(); + size = 32; + + + if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1) + { + TFE_LOG_ERROR(mgr->logger, "HMAC_Init_ex() failed"); + return -1; + } + + + if (EVP_DecryptInit_ex(ectx, cipher, NULL, key[0].aes_key, iv) != 1) + { + TFE_LOG_ERROR(mgr->logger, "EVP_DecryptInit_ex() failed"); + return -1; + } + ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TICKET_REUSE])); + //Todo: Implement key expire. + return 1; //Return 1 indicates that the ctx and hctx have been set and the session can continue on those parameters. + + } +} + + + /* * Called by OpenSSL when a new src SSL session is created. * OpenSSL increments the refcount before calling the callback and will @@ -1006,69 +1111,34 @@ static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr) SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); #endif /* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ -#ifdef SSL_OP_NO_TICKET - SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET); -#endif /* SSL_OP_NO_TICKET */ -#ifdef SSL_OP_NO_SSLv2 -#ifdef HAVE_SSLV2 - - if (mgr->no_ssl2) { -#endif /* HAVE_SSLV2 */ - - SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); - -#ifdef HAVE_SSLV2 + if (mgr->no_ssl2) + { + SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); } - -#endif /* HAVE_SSLV2 */ - -#endif /* !SSL_OP_NO_SSLv2 */ - -#ifdef HAVE_SSLV3 - - if (mgr->no_ssl3) { + if (mgr->no_ssl3) + { SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3); } -#endif /* HAVE_SSLV3 */ - -#ifdef HAVE_TLSV10 - if (mgr->no_tls10) { SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1); } - -#endif /* HAVE_TLSV10 */ - -#ifdef HAVE_TLSV11 - if (mgr->no_tls11) { SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1); } - -#endif /* HAVE_TLSV11 */ - -#ifdef HAVE_TLSV12 - if (mgr->no_tls12) { SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2); } - -#endif /* HAVE_TLSV12 */ - -#ifdef SSL_OP_NO_COMPRESSION - if (!mgr->sslcomp) { SSL_CTX_set_options(sslctx, SSL_OP_NO_COMPRESSION); } -#endif /* SSL_OP_NO_COMPRESSION */ } @@ -1100,6 +1170,8 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt) 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); + ret=SSL_CTX_set_tlsext_ticket_key_cb(sslctx, ossl_session_ticket_key_callback); + assert(ret!=0); SSL_CTX_set_session_cache_mode(sslctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL); SSL_CTX_set_session_id_context(sslctx, (const unsigned char *) mgr->ssl_session_context, sizeof(mgr->ssl_session_context)); diff --git a/plugin/protocol/http/src/http_entry.cpp b/plugin/protocol/http/src/http_entry.cpp index 3789da8..826afa8 100644 --- a/plugin/protocol/http/src/http_entry.cpp +++ b/plugin/protocol/http/src/http_entry.cpp @@ -59,7 +59,7 @@ enum tfe_stream_action __http_connection_entry_on_request(const struct tfe_strea struct http_half_private * hf_private_req_in = to_hf_request_private(hs_private); struct http_half_private * hf_private_req_user; - /* tfe_hexdump(stderr, __FUNCTION__, data, (unsigned int)len); */ + /* tfe_hexdump2file(stderr, __FUNCTION__, data, (unsigned int)len); */ int ret = 0; size_t __action_byptes;