手工合并李杰stek-roation分支,支持session ticket rotation,详见 #123
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include <tfe_proxy.h>
|
||||
#include <key_keeper.h>
|
||||
#include <ssl_sess_cache.h>
|
||||
#include <ssl_sess_ticket.h>
|
||||
#include <ssl_trusted_cert_storage.h>
|
||||
#include <ssl_utils.h>
|
||||
#include <ssl_service_cache.h>
|
||||
@@ -106,13 +107,6 @@ enum ssl_stream_stat
|
||||
|
||||
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
|
||||
{
|
||||
@@ -137,10 +131,12 @@ struct ssl_mgr
|
||||
|
||||
struct sess_cache * down_sess_cache;
|
||||
struct sess_cache * up_sess_cache;
|
||||
struct sess_ticket_box * down_stek_box;
|
||||
|
||||
struct ssl_service_cache* svc_cache;
|
||||
ssl_stream_new_hook* on_new_upstream_cb;
|
||||
void* upstream_cb_param;
|
||||
struct session_ticket_key ticket_key;
|
||||
struct sess_ticket_key ticket_key;
|
||||
|
||||
char default_ciphers[TFE_SYMBOL_MAX];
|
||||
DH * dh;
|
||||
@@ -589,11 +585,9 @@ void ssl_manager_destroy(struct ssl_mgr * mgr)
|
||||
struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section,
|
||||
struct event_base * ev_base_gc, void * logger)
|
||||
{
|
||||
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};
|
||||
unsigned int stek_group_num = 0;
|
||||
unsigned int stek_rotation_time = 0;
|
||||
|
||||
|
||||
struct ssl_mgr * mgr = ALLOC(struct ssl_mgr, 1);
|
||||
int ret = 0;
|
||||
@@ -649,20 +643,24 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
|
||||
&(mgr->cache_slots), 4 * 1024 * 1024);
|
||||
MESA_load_profile_uint_def(ini_profile, section, "session_cache_expire_seconds",
|
||||
&(mgr->sess_expire_seconds), 30 * 60);
|
||||
|
||||
|
||||
if(!mgr->no_sesscache)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
MESA_load_profile_uint_def(ini_profile, section, "stek_group_num", &stek_group_num, 1);
|
||||
MESA_load_profile_uint_def(ini_profile, section, "stek_rotation_time", &stek_rotation_time, 3600);
|
||||
|
||||
if(!mgr->no_sessticket)
|
||||
{
|
||||
mgr->down_stek_box = sess_ticket_box_create(ev_base_gc, stek_group_num, stek_rotation_time, logger);
|
||||
}
|
||||
|
||||
mgr->svc_cache=ssl_service_cache_create(mgr->cache_slots, mgr->sess_expire_seconds);
|
||||
|
||||
//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)
|
||||
{
|
||||
@@ -1310,80 +1308,84 @@ void ssl_async_upstream_create(struct future * f, struct ssl_mgr * mgr, evutil_s
|
||||
ctx->f_peek_chello = future_create("peek_sni", peek_chello_on_succ, peek_chello_on_fail, p);
|
||||
ssl_async_peek_client_hello(ctx->f_peek_chello, fd_downstream, !mgr->no_mirror_client_cipher_suite, 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)
|
||||
{
|
||||
enum STEK_GET_RET ret=STEK_NOT_FOUND;
|
||||
const EVP_MD *digest=EVP_sha256();
|
||||
const EVP_CIPHER *cipher=EVP_aes_256_cbc();
|
||||
size_t size=32;
|
||||
size_t size=32;
|
||||
struct ssl_stream* s_stream = (struct ssl_stream*) SSL_get_ex_data(ssl_conn, SSL_EX_DATA_IDX_SSLSTREAM);
|
||||
struct ssl_mgr* mgr= s_stream->mgr;
|
||||
void* logger = s_stream->mgr->logger;
|
||||
const char * sni = s_stream->peer->up_parts.client_hello->sni;
|
||||
struct sess_ticket_box * stek_box = s_stream->mgr->down_stek_box;
|
||||
struct sess_ticket_key cur_stek;
|
||||
|
||||
struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl_conn, SSL_CTX_EX_DATA_IDX_SSLMGR);
|
||||
assert(mgr!=NULL);
|
||||
|
||||
struct session_ticket_key* key=&(mgr->ticket_key);
|
||||
|
||||
unsigned char buf[33]={0};
|
||||
|
||||
ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TIKCET_QUERY]));
|
||||
unsigned char buf[33]={0};
|
||||
ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TIKCET_QUERY]));
|
||||
if (enc == 1)
|
||||
{
|
||||
/* encrypt session ticket */
|
||||
|
||||
|
||||
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;
|
||||
{
|
||||
|
||||
sess_ticket_box_get_key_for_enc(stek_box, sni, &cur_stek);
|
||||
/* encrypt session stek */
|
||||
if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1)
|
||||
{
|
||||
TFE_LOG_ERROR(mgr->logger, "Session Ticket RAND_bytes() failed");
|
||||
ret=STEK_ERROR;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
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_EncryptInit_ex(ectx, cipher, NULL, cur_stek.aes_key, iv) != 1)
|
||||
{
|
||||
TFE_LOG_ERROR(mgr->logger, "EVP_EncryptInit_ex() failed");
|
||||
ret=STEK_ERROR;
|
||||
goto leave;
|
||||
}
|
||||
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"
|
||||
,(int)(tfe_hexdump(buf, name ,16)-buf), buf);
|
||||
ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TICKET_NOTFOUND]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1)
|
||||
{
|
||||
if (HMAC_Init_ex(hctx, cur_stek.hmac_key, size, digest, NULL) != 1)
|
||||
{
|
||||
TFE_LOG_ERROR(mgr->logger, "HMAC_Init_ex() failed");
|
||||
return -1;
|
||||
ret=STEK_ERROR;
|
||||
goto leave;
|
||||
}
|
||||
memcpy(name, cur_stek.name, sizeof(cur_stek.name));
|
||||
ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TICKET_NEW]));
|
||||
ret=STEK_FOUND_FRESH;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* decrypt session stek */
|
||||
ret=sess_ticket_box_get_key_for_dec(stek_box, sni, name, &cur_stek);
|
||||
|
||||
|
||||
if (EVP_DecryptInit_ex(ectx, cipher, NULL, key[0].aes_key, iv) != 1)
|
||||
if(ret==STEK_FOUND_FRESH||ret==STEK_FOUND_STALED)
|
||||
{
|
||||
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.
|
||||
|
||||
if (HMAC_Init_ex(hctx, cur_stek.hmac_key, size, digest, NULL) != 1)
|
||||
{
|
||||
TFE_LOG_ERROR(logger, "HMAC_Init_ex() failed");
|
||||
ret= STEK_ERROR;
|
||||
goto leave;
|
||||
}
|
||||
if (EVP_DecryptInit_ex(ectx, cipher, NULL, cur_stek.aes_key, iv) != 1)
|
||||
{
|
||||
TFE_LOG_ERROR(logger, "EVP_DecryptInit_ex() failed");
|
||||
ret= STEK_ERROR;
|
||||
goto leave;
|
||||
}
|
||||
ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TICKET_REUSE]));
|
||||
}
|
||||
else
|
||||
{
|
||||
// full handshake and update the session stek_box
|
||||
TFE_LOG_DEBUG(logger, "full handshake and update the stek_box, STEK is overdue STEK.");
|
||||
TFE_LOG_INFO(logger, "ssl session stek_box decrypt, key: \"%*s\" not found",(int)(tfe_hexdump(buf, name ,16)-buf), buf);
|
||||
ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TICKET_NOTFOUND]));
|
||||
}
|
||||
}
|
||||
|
||||
leave:
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1441,7 +1443,8 @@ static void ossl_downsess_remove_cb(SSL_CTX * sslctx, SSL_SESSION * sess)
|
||||
*/
|
||||
static SSL_SESSION * ossl_downsess_get_cb(SSL * ssl, const unsigned char * id, int idlen, int * copy)
|
||||
{
|
||||
struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl, SSL_CTX_EX_DATA_IDX_SSLMGR);
|
||||
struct ssl_stream* s_stream = (struct ssl_stream*) SSL_get_ex_data(ssl, SSL_EX_DATA_IDX_SSLSTREAM);
|
||||
struct ssl_mgr * mgr = s_stream->mgr;
|
||||
SSL_SESSION * sess=NULL;
|
||||
if(!mgr->no_sesscache)
|
||||
{
|
||||
@@ -1566,7 +1569,7 @@ void downstream_ossl_init(struct ssl_stream *s_stream)
|
||||
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));
|
||||
ret = SSL_CTX_set_ex_data(sslctx, SSL_CTX_EX_DATA_IDX_SSLMGR, mgr);
|
||||
ret = SSL_CTX_set_ex_data(sslctx, SSL_CTX_EX_DATA_IDX_SSLMGR, mgr);//used by down session cache get
|
||||
assert(ret == 1);
|
||||
if (mgr->dh)
|
||||
{
|
||||
@@ -1607,9 +1610,9 @@ void downstream_ossl_init(struct ssl_stream *s_stream)
|
||||
SSL_CTX_free(sslctx); // SSL_new() increments refcount
|
||||
sslctx = NULL;
|
||||
|
||||
ret = SSL_set_ex_data(ssl, SSL_CTX_EX_DATA_IDX_SSLMGR, mgr);
|
||||
ret = SSL_set_ex_data(ssl, SSL_EX_DATA_IDX_SSLSTREAM, s_stream);
|
||||
assert(ret == 1);
|
||||
|
||||
|
||||
if (mgr->ssl_mode_release_buffers == 1)
|
||||
{
|
||||
/* lower memory footprint for idle connections */
|
||||
|
||||
Reference in New Issue
Block a user