mirror of
https://github.com/nginx/nginx.git
synced 2024-12-12 18:29:00 +08:00
move the session cache callbacks to the ngx_openssl_module
This commit is contained in:
parent
528cdb7c2c
commit
3364dc6eb7
@ -64,11 +64,11 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
|
|||||||
#include <ngx_times.h>
|
#include <ngx_times.h>
|
||||||
#include <ngx_shmtx.h>
|
#include <ngx_shmtx.h>
|
||||||
#include <ngx_slab.h>
|
#include <ngx_slab.h>
|
||||||
|
#include <ngx_inet.h>
|
||||||
|
#include <ngx_cycle.h>
|
||||||
#if (NGX_OPENSSL)
|
#if (NGX_OPENSSL)
|
||||||
#include <ngx_event_openssl.h>
|
#include <ngx_event_openssl.h>
|
||||||
#endif
|
#endif
|
||||||
#include <ngx_inet.h>
|
|
||||||
#include <ngx_cycle.h>
|
|
||||||
#include <ngx_process_cycle.h>
|
#include <ngx_process_cycle.h>
|
||||||
#include <ngx_conf_file.h>
|
#include <ngx_conf_file.h>
|
||||||
#include <ngx_os.h>
|
#include <ngx_os.h>
|
||||||
|
@ -22,6 +22,16 @@ static void ngx_ssl_read_handler(ngx_event_t *rev);
|
|||||||
static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
|
static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
|
||||||
static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
|
static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
|
||||||
ngx_err_t err, char *text);
|
ngx_err_t err, char *text);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone);
|
||||||
|
static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
|
||||||
|
ngx_ssl_session_t *sess);
|
||||||
|
static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
|
||||||
|
u_char *id, int len, int *copy);
|
||||||
|
static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
|
||||||
|
static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
|
||||||
|
ngx_slab_pool_t *shpool, ngx_uint_t n);
|
||||||
|
|
||||||
static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
|
static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
|
||||||
static char *ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf);
|
static char *ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf);
|
||||||
static void ngx_openssl_exit(ngx_cycle_t *cycle);
|
static void ngx_openssl_exit(ngx_cycle_t *cycle);
|
||||||
@ -86,6 +96,7 @@ static long ngx_ssl_protocols[] = {
|
|||||||
|
|
||||||
int ngx_ssl_connection_index;
|
int ngx_ssl_connection_index;
|
||||||
int ngx_ssl_server_conf_index;
|
int ngx_ssl_server_conf_index;
|
||||||
|
int ngx_ssl_session_cache_index;
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
@ -117,6 +128,14 @@ ngx_ssl_init(ngx_log_t *log)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
|
||||||
|
NULL);
|
||||||
|
if (ngx_ssl_session_cache_index == -1) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
|
||||||
|
"SSL_CTX_get_ex_new_index() failed");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +298,7 @@ ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
|
|||||||
name = X509_get_issuer_name(cert);
|
name = X509_get_issuer_name(cert);
|
||||||
issuer = name ? X509_NAME_oneline(name, NULL, 0) : "(none)";
|
issuer = name ? X509_NAME_oneline(name, NULL, 0) : "(none)";
|
||||||
|
|
||||||
ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
"verify:%d, error:%d, depth:%d, "
|
"verify:%d, error:%d, depth:%d, "
|
||||||
"subject:\"%s\",issuer: \"%s\"",
|
"subject:\"%s\",issuer: \"%s\"",
|
||||||
ok, err, depth, subject, issuer);
|
ok, err, depth, subject, issuer);
|
||||||
@ -1033,7 +1052,7 @@ ngx_ssl_shutdown_handler(ngx_event_t *ev)
|
|||||||
c->timedout = 1;
|
c->timedout = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "SSL shutdown handler");
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
|
||||||
|
|
||||||
if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
|
if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
|
||||||
return;
|
return;
|
||||||
@ -1119,6 +1138,428 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
|
||||||
|
ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
|
||||||
|
{
|
||||||
|
long cache_mode;
|
||||||
|
|
||||||
|
cache_mode = SSL_SESS_CACHE_SERVER;
|
||||||
|
|
||||||
|
if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
|
||||||
|
cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
|
||||||
|
|
||||||
|
SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
|
||||||
|
|
||||||
|
if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
|
||||||
|
|
||||||
|
if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
|
||||||
|
SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_CTX_set_timeout(ssl->ctx, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shm_zone) {
|
||||||
|
shm_zone->init = ngx_ssl_session_cache_init;
|
||||||
|
|
||||||
|
SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
|
||||||
|
SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
|
||||||
|
SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);
|
||||||
|
|
||||||
|
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
|
||||||
|
== 0)
|
||||||
|
{
|
||||||
|
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||||
|
"SSL_CTX_set_ex_data() failed");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone)
|
||||||
|
{
|
||||||
|
ngx_slab_pool_t *shpool;
|
||||||
|
ngx_rbtree_node_t *sentinel;
|
||||||
|
ngx_ssl_session_cache_t *cache;
|
||||||
|
|
||||||
|
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||||
|
|
||||||
|
cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
|
||||||
|
if (cache == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->session_cache_head.prev = NULL;
|
||||||
|
cache->session_cache_head.next = &cache->session_cache_tail;
|
||||||
|
|
||||||
|
cache->session_cache_tail.prev = &cache->session_cache_head;
|
||||||
|
cache->session_cache_tail.next = NULL;
|
||||||
|
|
||||||
|
cache->session_rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
|
||||||
|
if (cache->session_rbtree == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
|
||||||
|
if (sentinel == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_rbtree_sentinel_init(sentinel);
|
||||||
|
|
||||||
|
cache->session_rbtree->root = sentinel;
|
||||||
|
cache->session_rbtree->sentinel = sentinel;
|
||||||
|
cache->session_rbtree->insert = ngx_rbtree_insert_value;
|
||||||
|
|
||||||
|
shm_zone->data = cache;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
|
||||||
|
* so they are outside the code locked by shared pool mutex
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
u_char *p, *id;
|
||||||
|
uint32_t hash;
|
||||||
|
SSL_CTX *ssl_ctx;
|
||||||
|
ngx_time_t *tp;
|
||||||
|
ngx_shm_zone_t *shm_zone;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_slab_pool_t *shpool;
|
||||||
|
ngx_ssl_sess_id_t *sess_id;
|
||||||
|
ngx_ssl_cached_sess_t *cached_sess;
|
||||||
|
ngx_ssl_session_cache_t *cache;
|
||||||
|
u_char buf[NGX_SSL_MAX_SESSION_SIZE];
|
||||||
|
|
||||||
|
len = i2d_SSL_SESSION(sess, NULL);
|
||||||
|
|
||||||
|
/* do not cache too big session */
|
||||||
|
|
||||||
|
if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
i2d_SSL_SESSION(sess, &p);
|
||||||
|
|
||||||
|
c = ngx_ssl_get_connection(ssl_conn);
|
||||||
|
|
||||||
|
ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
|
||||||
|
shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
|
||||||
|
|
||||||
|
cache = shm_zone->data;
|
||||||
|
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||||
|
|
||||||
|
ngx_shmtx_lock(&shpool->mutex);
|
||||||
|
|
||||||
|
/* drop one or two expired sessions */
|
||||||
|
ngx_ssl_expire_sessions(cache, shpool, 1);
|
||||||
|
|
||||||
|
cached_sess = ngx_slab_alloc_locked(shpool,
|
||||||
|
offsetof(ngx_ssl_cached_sess_t, asn1) + len);
|
||||||
|
|
||||||
|
if (cached_sess == NULL) {
|
||||||
|
|
||||||
|
/* drop the oldest non-expired session and try once more */
|
||||||
|
|
||||||
|
ngx_ssl_expire_sessions(cache, shpool, 0);
|
||||||
|
|
||||||
|
cached_sess = ngx_slab_alloc_locked(shpool,
|
||||||
|
offsetof(ngx_ssl_cached_sess_t, asn1) + len);
|
||||||
|
|
||||||
|
if (cached_sess == NULL) {
|
||||||
|
id = NULL;
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
|
||||||
|
if (id == NULL) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
|
||||||
|
if (sess_id == NULL) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memcpy(&cached_sess->asn1[0], buf, len);
|
||||||
|
|
||||||
|
ngx_memcpy(id, sess->session_id, sess->session_id_length);
|
||||||
|
|
||||||
|
hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
|
||||||
|
|
||||||
|
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"http ssl new session: %08XD:%d:%d",
|
||||||
|
hash, sess->session_id_length, len);
|
||||||
|
|
||||||
|
sess_id->node.key = hash;
|
||||||
|
sess_id->node.data = (u_char) sess->session_id_length;
|
||||||
|
sess_id->id = id;
|
||||||
|
sess_id->len = len;
|
||||||
|
sess_id->session = cached_sess;
|
||||||
|
|
||||||
|
tp = ngx_timeofday();
|
||||||
|
|
||||||
|
cached_sess->expire = tp->sec + SSL_CTX_get_timeout(ssl_ctx);
|
||||||
|
cached_sess->sess_id = sess_id;
|
||||||
|
|
||||||
|
cached_sess->next = cache->session_cache_head.next;
|
||||||
|
cached_sess->next->prev = cached_sess;
|
||||||
|
cached_sess->prev = &cache->session_cache_head;
|
||||||
|
cache->session_cache_head.next = cached_sess;
|
||||||
|
|
||||||
|
ngx_rbtree_insert(cache->session_rbtree, &sess_id->node);
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
if (cached_sess) {
|
||||||
|
ngx_slab_free_locked(shpool, cached_sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
ngx_slab_free_locked(shpool, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||||
|
"could not add new SSL session to the session cache");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_ssl_session_t *
|
||||||
|
ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
|
||||||
|
int *copy)
|
||||||
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x00908000
|
||||||
|
const
|
||||||
|
#endif
|
||||||
|
u_char *p;
|
||||||
|
uint32_t hash;
|
||||||
|
ngx_time_t *tp;
|
||||||
|
ngx_shm_zone_t *shm_zone;
|
||||||
|
ngx_slab_pool_t *shpool;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_rbtree_node_t *node, *sentinel;
|
||||||
|
ngx_ssl_session_t *sess;
|
||||||
|
ngx_ssl_sess_id_t *sess_id;
|
||||||
|
ngx_ssl_cached_sess_t *cached_sess;
|
||||||
|
ngx_ssl_session_cache_t *cache;
|
||||||
|
u_char buf[NGX_SSL_MAX_SESSION_SIZE];
|
||||||
|
|
||||||
|
c = ngx_ssl_get_connection(ssl_conn);
|
||||||
|
|
||||||
|
hash = ngx_crc32_short(id, len);
|
||||||
|
*copy = 0;
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"http ssl get session: %08XD:%d", hash, len);
|
||||||
|
|
||||||
|
shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
|
||||||
|
ngx_ssl_session_cache_index);
|
||||||
|
|
||||||
|
cache = shm_zone->data;
|
||||||
|
|
||||||
|
if (cache->session_rbtree == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sess = NULL;
|
||||||
|
|
||||||
|
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||||
|
|
||||||
|
ngx_shmtx_lock(&shpool->mutex);
|
||||||
|
|
||||||
|
node = cache->session_rbtree->root;
|
||||||
|
sentinel = cache->session_rbtree->sentinel;
|
||||||
|
|
||||||
|
while (node != sentinel) {
|
||||||
|
|
||||||
|
if (hash < node->key) {
|
||||||
|
node = node->left;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash > node->key) {
|
||||||
|
node = node->right;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash == node->key && (u_char) len == node->data) {
|
||||||
|
sess_id = (ngx_ssl_sess_id_t *) node;
|
||||||
|
|
||||||
|
if (ngx_strncmp(id, sess_id->id, len) == 0) {
|
||||||
|
|
||||||
|
cached_sess = sess_id->session;
|
||||||
|
|
||||||
|
tp = ngx_timeofday();
|
||||||
|
|
||||||
|
if (cached_sess->expire > tp->sec) {
|
||||||
|
ngx_memcpy(buf, &cached_sess->asn1[0], sess_id->len);
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
|
||||||
|
|
||||||
|
return sess;
|
||||||
|
}
|
||||||
|
|
||||||
|
cached_sess->next->prev = cached_sess->prev;
|
||||||
|
cached_sess->prev->next = cached_sess->next;
|
||||||
|
|
||||||
|
ngx_rbtree_delete(cache->session_rbtree, node);
|
||||||
|
|
||||||
|
ngx_slab_free_locked(shpool, cached_sess);
|
||||||
|
ngx_slab_free_locked(shpool, sess_id->id);
|
||||||
|
ngx_slab_free_locked(shpool, sess_id);
|
||||||
|
|
||||||
|
sess = NULL;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->right;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
|
||||||
|
return sess;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
|
||||||
|
{
|
||||||
|
u_char *id, len;
|
||||||
|
uint32_t hash;
|
||||||
|
ngx_shm_zone_t *shm_zone;
|
||||||
|
ngx_slab_pool_t *shpool;
|
||||||
|
ngx_rbtree_node_t *node, *sentinel;
|
||||||
|
ngx_ssl_sess_id_t *sess_id;
|
||||||
|
ngx_ssl_cached_sess_t *cached_sess;
|
||||||
|
ngx_ssl_session_cache_t *cache;
|
||||||
|
|
||||||
|
shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
|
||||||
|
|
||||||
|
cache = shm_zone->data;
|
||||||
|
|
||||||
|
id = sess->session_id;
|
||||||
|
len = (u_char) sess->session_id_length;
|
||||||
|
|
||||||
|
hash = ngx_crc32_short(id, (size_t) len);
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
|
||||||
|
"http ssl remove session: %08XD:%d", hash, len);
|
||||||
|
|
||||||
|
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||||
|
|
||||||
|
ngx_shmtx_lock(&shpool->mutex);
|
||||||
|
|
||||||
|
node = cache->session_rbtree->root;
|
||||||
|
sentinel = cache->session_rbtree->sentinel;
|
||||||
|
|
||||||
|
while (node != sentinel) {
|
||||||
|
|
||||||
|
if (hash < node->key) {
|
||||||
|
node = node->left;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash > node->key) {
|
||||||
|
node = node->right;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash == node->key && len == node->data) {
|
||||||
|
sess_id = (ngx_ssl_sess_id_t *) node;
|
||||||
|
|
||||||
|
if (ngx_strncmp(id, sess_id->id, (size_t) len) == 0) {
|
||||||
|
|
||||||
|
cached_sess = sess_id->session;
|
||||||
|
|
||||||
|
cached_sess->next->prev = cached_sess->prev;
|
||||||
|
cached_sess->prev->next = cached_sess->next;
|
||||||
|
|
||||||
|
ngx_rbtree_delete(cache->session_rbtree, node);
|
||||||
|
|
||||||
|
ngx_slab_free_locked(shpool, cached_sess);
|
||||||
|
ngx_slab_free_locked(shpool, sess_id->id);
|
||||||
|
ngx_slab_free_locked(shpool, sess_id);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->right;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
|
||||||
|
ngx_slab_pool_t *shpool, ngx_uint_t n)
|
||||||
|
{
|
||||||
|
ngx_time_t *tp;
|
||||||
|
ngx_ssl_sess_id_t *sess_id;
|
||||||
|
ngx_ssl_cached_sess_t *sess;
|
||||||
|
|
||||||
|
tp = ngx_timeofday();
|
||||||
|
|
||||||
|
while (n < 3) {
|
||||||
|
|
||||||
|
sess = cache->session_cache_tail.prev;
|
||||||
|
|
||||||
|
if (sess == &cache->session_cache_head) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n++ != 0 && sess->expire > tp->sec) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sess->next->prev = sess->prev;
|
||||||
|
sess->prev->next = sess->next;
|
||||||
|
|
||||||
|
sess_id = sess->sess_id;
|
||||||
|
|
||||||
|
ngx_rbtree_delete(cache->session_rbtree, &sess_id->node);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
|
||||||
|
"expire session: %08Xi", sess_id->node.key);
|
||||||
|
|
||||||
|
ngx_slab_free_locked(shpool, sess);
|
||||||
|
ngx_slab_free_locked(shpool, sess_id->id);
|
||||||
|
ngx_slab_free_locked(shpool, sess_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ngx_ssl_cleanup_ctx(void *data)
|
ngx_ssl_cleanup_ctx(void *data)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,41 @@ typedef struct {
|
|||||||
} ngx_ssl_connection_t;
|
} ngx_ssl_connection_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_SSL_DFLT_BUILTIN_SCACHE -2
|
||||||
|
#define NGX_SSL_NO_BUILTIN_SCACHE -3
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ngx_ssl_cached_sess_s ngx_ssl_cached_sess_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_SSL_MAX_SESSION_SIZE (4096 - offsetof(ngx_ssl_cached_sess_t, asn1))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_rbtree_node_t node;
|
||||||
|
u_char *id;
|
||||||
|
size_t len;
|
||||||
|
ngx_ssl_cached_sess_t *session;
|
||||||
|
} ngx_ssl_sess_id_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct ngx_ssl_cached_sess_s {
|
||||||
|
ngx_ssl_cached_sess_t *prev;
|
||||||
|
ngx_ssl_cached_sess_t *next;
|
||||||
|
time_t expire;
|
||||||
|
ngx_ssl_sess_id_t *sess_id;
|
||||||
|
u_char asn1[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_rbtree_t *session_rbtree;
|
||||||
|
ngx_ssl_cached_sess_t session_cache_head;
|
||||||
|
ngx_ssl_cached_sess_t session_cache_tail;
|
||||||
|
} ngx_ssl_session_cache_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define NGX_SSL_SSLv2 2
|
#define NGX_SSL_SSLv2 2
|
||||||
#define NGX_SSL_SSLv3 4
|
#define NGX_SSL_SSLv3 4
|
||||||
#define NGX_SSL_TLSv1 8
|
#define NGX_SSL_TLSv1 8
|
||||||
@ -69,6 +104,8 @@ ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
|||||||
ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||||
ngx_str_t *cert, ngx_int_t depth);
|
ngx_str_t *cert, ngx_int_t depth);
|
||||||
ngx_int_t ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl);
|
ngx_int_t ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl);
|
||||||
|
ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
|
||||||
|
ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout);
|
||||||
ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
|
ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
|
||||||
ngx_uint_t flags);
|
ngx_uint_t flags);
|
||||||
|
|
||||||
@ -93,8 +130,6 @@ ngx_int_t ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool,
|
|||||||
ngx_str_t *s);
|
ngx_str_t *s);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
|
ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
|
||||||
ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size);
|
ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size);
|
||||||
ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size);
|
ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size);
|
||||||
@ -109,6 +144,7 @@ void ngx_ssl_cleanup_ctx(void *data);
|
|||||||
|
|
||||||
extern int ngx_ssl_connection_index;
|
extern int ngx_ssl_connection_index;
|
||||||
extern int ngx_ssl_server_conf_index;
|
extern int ngx_ssl_server_conf_index;
|
||||||
|
extern int ngx_ssl_session_cache_index;
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */
|
#endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */
|
||||||
|
@ -18,17 +18,6 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
|
|||||||
#define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
|
#define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
|
||||||
|
|
||||||
|
|
||||||
#define NGX_HTTP_SSL_MAX_SESSION_SIZE \
|
|
||||||
(4096 - offsetof(ngx_http_ssl_cached_sess_t, asn1))
|
|
||||||
|
|
||||||
|
|
||||||
#define NGX_HTTP_SSL_DFLT_BUILTIN_SCACHE -2
|
|
||||||
#define NGX_HTTP_SSL_NO_BUILTIN_SCACHE -3
|
|
||||||
|
|
||||||
|
|
||||||
static void ngx_http_ssl_expire_sessions(ngx_http_ssl_sesssion_cache_t *cache,
|
|
||||||
ngx_slab_pool_t *shpool, ngx_uint_t expire);
|
|
||||||
|
|
||||||
static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
|
||||||
ngx_http_variable_value_t *v, uintptr_t data);
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
|
||||||
@ -199,385 +188,7 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static u_char ngx_http_session_id_ctx[] = "HTTP";
|
static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
|
||||||
ngx_http_ssl_session_cache_init(ngx_shm_zone_t *shm_zone)
|
|
||||||
{
|
|
||||||
ngx_slab_pool_t *shpool;
|
|
||||||
ngx_rbtree_node_t *sentinel;
|
|
||||||
ngx_http_ssl_sesssion_cache_t *cache;
|
|
||||||
|
|
||||||
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
|
||||||
|
|
||||||
cache = ngx_slab_alloc(shpool, sizeof(ngx_http_ssl_sesssion_cache_t));
|
|
||||||
if (cache == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
cache->session_cache_head.prev = NULL;
|
|
||||||
cache->session_cache_head.next = &cache->session_cache_tail;
|
|
||||||
|
|
||||||
cache->session_cache_tail.prev = &cache->session_cache_head;
|
|
||||||
cache->session_cache_tail.next = NULL;
|
|
||||||
|
|
||||||
cache->session_rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
|
|
||||||
if (cache->session_rbtree == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
|
|
||||||
if (sentinel == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_rbtree_sentinel_init(sentinel);
|
|
||||||
|
|
||||||
cache->session_rbtree->root = sentinel;
|
|
||||||
cache->session_rbtree->sentinel = sentinel;
|
|
||||||
cache->session_rbtree->insert = ngx_rbtree_insert_value;
|
|
||||||
|
|
||||||
shm_zone->data = cache;
|
|
||||||
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
|
|
||||||
* so they are outside the code locked by shared pool mutex
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
ngx_http_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
u_char *p, *id;
|
|
||||||
uint32_t hash;
|
|
||||||
ngx_time_t *tp;
|
|
||||||
ngx_slab_pool_t *shpool;
|
|
||||||
ngx_connection_t *c;
|
|
||||||
ngx_http_request_t *r;
|
|
||||||
ngx_http_ssl_sess_id_t *sess_id;
|
|
||||||
ngx_http_ssl_srv_conf_t *sscf;
|
|
||||||
ngx_http_ssl_cached_sess_t *cached_sess;
|
|
||||||
ngx_http_ssl_sesssion_cache_t *cache;
|
|
||||||
u_char buf[NGX_HTTP_SSL_MAX_SESSION_SIZE];
|
|
||||||
|
|
||||||
len = i2d_SSL_SESSION(sess, NULL);
|
|
||||||
|
|
||||||
/* do not cache too big session */
|
|
||||||
|
|
||||||
if (len > (int) NGX_HTTP_SSL_MAX_SESSION_SIZE) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = ngx_ssl_get_connection(ssl_conn);
|
|
||||||
r = c->data;
|
|
||||||
|
|
||||||
p = buf;
|
|
||||||
i2d_SSL_SESSION(sess, &p);
|
|
||||||
|
|
||||||
sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
|
|
||||||
|
|
||||||
cache = sscf->shm_zone->data;
|
|
||||||
shpool = (ngx_slab_pool_t *) sscf->shm_zone->shm.addr;
|
|
||||||
|
|
||||||
ngx_shmtx_lock(&shpool->mutex);
|
|
||||||
|
|
||||||
/* drop one or two expired sessions */
|
|
||||||
ngx_http_ssl_expire_sessions(cache, shpool, 1);
|
|
||||||
|
|
||||||
cached_sess = ngx_slab_alloc_locked(shpool,
|
|
||||||
offsetof(ngx_http_ssl_cached_sess_t, asn1) + len);
|
|
||||||
|
|
||||||
if (cached_sess == NULL) {
|
|
||||||
|
|
||||||
/* drop the oldest non-expired session and try once more */
|
|
||||||
|
|
||||||
ngx_http_ssl_expire_sessions(cache, shpool, 0);
|
|
||||||
|
|
||||||
cached_sess = ngx_slab_alloc_locked(shpool,
|
|
||||||
offsetof(ngx_http_ssl_cached_sess_t, asn1) + len);
|
|
||||||
|
|
||||||
if (cached_sess == NULL) {
|
|
||||||
id = NULL;
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
|
|
||||||
if (id == NULL) {
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_http_ssl_sess_id_t));
|
|
||||||
if (sess_id == NULL) {
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_memcpy(&cached_sess->asn1[0], buf, len);
|
|
||||||
|
|
||||||
ngx_memcpy(id, sess->session_id, sess->session_id_length);
|
|
||||||
|
|
||||||
hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
|
|
||||||
|
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
|
||||||
"http ssl new session: %08XD:%d:%d",
|
|
||||||
hash, sess->session_id_length, len);
|
|
||||||
|
|
||||||
sess_id->node.key = hash;
|
|
||||||
sess_id->node.data = (u_char) sess->session_id_length;
|
|
||||||
sess_id->id = id;
|
|
||||||
sess_id->len = len;
|
|
||||||
sess_id->session = cached_sess;
|
|
||||||
|
|
||||||
tp = ngx_timeofday();
|
|
||||||
|
|
||||||
cached_sess->expire = tp->sec + sscf->session_timeout;
|
|
||||||
cached_sess->sess_id = sess_id;
|
|
||||||
|
|
||||||
cached_sess->next = cache->session_cache_head.next;
|
|
||||||
cached_sess->next->prev = cached_sess;
|
|
||||||
cached_sess->prev = &cache->session_cache_head;
|
|
||||||
cache->session_cache_head.next = cached_sess;
|
|
||||||
|
|
||||||
ngx_rbtree_insert(cache->session_rbtree, &sess_id->node);
|
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
failed:
|
|
||||||
|
|
||||||
if (cached_sess) {
|
|
||||||
ngx_slab_free_locked(shpool, cached_sess);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id) {
|
|
||||||
ngx_slab_free_locked(shpool, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
|
||||||
"could not add new SSL session to the session cache");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_ssl_session_t *
|
|
||||||
ngx_http_ssl_get_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
|
|
||||||
int *copy)
|
|
||||||
{
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00908000
|
|
||||||
const
|
|
||||||
#endif
|
|
||||||
u_char *p;
|
|
||||||
uint32_t hash;
|
|
||||||
ngx_time_t *tp;
|
|
||||||
ngx_slab_pool_t *shpool;
|
|
||||||
ngx_connection_t *c;
|
|
||||||
ngx_rbtree_node_t *node, *sentinel;
|
|
||||||
ngx_ssl_session_t *sess;
|
|
||||||
ngx_http_request_t *r;
|
|
||||||
ngx_http_ssl_sess_id_t *sess_id;
|
|
||||||
ngx_http_ssl_srv_conf_t *sscf;
|
|
||||||
ngx_http_ssl_cached_sess_t *cached_sess;
|
|
||||||
ngx_http_ssl_sesssion_cache_t *cache;
|
|
||||||
u_char buf[NGX_HTTP_SSL_MAX_SESSION_SIZE];
|
|
||||||
|
|
||||||
c = ngx_ssl_get_connection(ssl_conn);
|
|
||||||
r = c->data;
|
|
||||||
|
|
||||||
sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
|
|
||||||
|
|
||||||
hash = ngx_crc32_short(id, len);
|
|
||||||
*copy = 0;
|
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
|
||||||
"http ssl get session: %08XD:%d", hash, len);
|
|
||||||
|
|
||||||
cache = sscf->shm_zone->data;
|
|
||||||
|
|
||||||
if (cache->session_rbtree == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sess = NULL;
|
|
||||||
|
|
||||||
shpool = (ngx_slab_pool_t *) sscf->shm_zone->shm.addr;
|
|
||||||
|
|
||||||
ngx_shmtx_lock(&shpool->mutex);
|
|
||||||
|
|
||||||
node = cache->session_rbtree->root;
|
|
||||||
sentinel = cache->session_rbtree->sentinel;
|
|
||||||
|
|
||||||
while (node != sentinel) {
|
|
||||||
|
|
||||||
if (hash < node->key) {
|
|
||||||
node = node->left;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash > node->key) {
|
|
||||||
node = node->right;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash == node->key && (u_char) len == node->data) {
|
|
||||||
sess_id = (ngx_http_ssl_sess_id_t *) node;
|
|
||||||
|
|
||||||
if (ngx_strncmp(id, sess_id->id, len) == 0) {
|
|
||||||
|
|
||||||
cached_sess = sess_id->session;
|
|
||||||
|
|
||||||
tp = ngx_timeofday();
|
|
||||||
|
|
||||||
if (cached_sess->expire > tp->sec) {
|
|
||||||
ngx_memcpy(buf, &cached_sess->asn1[0], sess_id->len);
|
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
|
||||||
|
|
||||||
p = buf;
|
|
||||||
sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
|
|
||||||
|
|
||||||
return sess;
|
|
||||||
}
|
|
||||||
|
|
||||||
cached_sess->next->prev = cached_sess->prev;
|
|
||||||
cached_sess->prev->next = cached_sess->next;
|
|
||||||
|
|
||||||
ngx_rbtree_delete(cache->session_rbtree, node);
|
|
||||||
|
|
||||||
ngx_slab_free_locked(shpool, cached_sess);
|
|
||||||
ngx_slab_free_locked(shpool, sess_id->id);
|
|
||||||
ngx_slab_free_locked(shpool, sess_id);
|
|
||||||
|
|
||||||
sess = NULL;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node->right;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
|
||||||
|
|
||||||
return sess;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ngx_http_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
|
|
||||||
{
|
|
||||||
u_char *id, len;
|
|
||||||
uint32_t hash;
|
|
||||||
ngx_slab_pool_t *shpool;
|
|
||||||
ngx_rbtree_node_t *node, *sentinel;
|
|
||||||
ngx_http_ssl_sess_id_t *sess_id;
|
|
||||||
ngx_http_ssl_srv_conf_t *sscf;
|
|
||||||
ngx_http_ssl_cached_sess_t *cached_sess;
|
|
||||||
ngx_http_ssl_sesssion_cache_t *cache;
|
|
||||||
|
|
||||||
sscf = ngx_ssl_get_server_conf(ssl);
|
|
||||||
|
|
||||||
cache = sscf->shm_zone->data;
|
|
||||||
|
|
||||||
id = sess->session_id;
|
|
||||||
len = (u_char) sess->session_id_length;
|
|
||||||
|
|
||||||
hash = ngx_crc32_short(id, (size_t) len);
|
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
|
|
||||||
"http ssl remove session: %08XD:%d", hash, len);
|
|
||||||
|
|
||||||
shpool = (ngx_slab_pool_t *) sscf->shm_zone->shm.addr;
|
|
||||||
|
|
||||||
ngx_shmtx_lock(&shpool->mutex);
|
|
||||||
|
|
||||||
node = cache->session_rbtree->root;
|
|
||||||
sentinel = cache->session_rbtree->sentinel;
|
|
||||||
|
|
||||||
while (node != sentinel) {
|
|
||||||
|
|
||||||
if (hash < node->key) {
|
|
||||||
node = node->left;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash > node->key) {
|
|
||||||
node = node->right;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash == node->key && len == node->data) {
|
|
||||||
sess_id = (ngx_http_ssl_sess_id_t *) node;
|
|
||||||
|
|
||||||
if (ngx_strncmp(id, sess_id->id, (size_t) len) == 0) {
|
|
||||||
|
|
||||||
cached_sess = sess_id->session;
|
|
||||||
|
|
||||||
cached_sess->next->prev = cached_sess->prev;
|
|
||||||
cached_sess->prev->next = cached_sess->next;
|
|
||||||
|
|
||||||
ngx_rbtree_delete(cache->session_rbtree, node);
|
|
||||||
|
|
||||||
ngx_slab_free_locked(shpool, cached_sess);
|
|
||||||
ngx_slab_free_locked(shpool, sess_id->id);
|
|
||||||
ngx_slab_free_locked(shpool, sess_id);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node->right;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ngx_http_ssl_expire_sessions(ngx_http_ssl_sesssion_cache_t *cache,
|
|
||||||
ngx_slab_pool_t *shpool, ngx_uint_t n)
|
|
||||||
{
|
|
||||||
ngx_time_t *tp;
|
|
||||||
ngx_http_ssl_sess_id_t *sess_id;
|
|
||||||
ngx_http_ssl_cached_sess_t *sess;
|
|
||||||
|
|
||||||
tp = ngx_timeofday();
|
|
||||||
|
|
||||||
while (n < 3) {
|
|
||||||
|
|
||||||
sess = cache->session_cache_tail.prev;
|
|
||||||
|
|
||||||
if (sess == &cache->session_cache_head) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n++ != 0 && sess->expire > tp->sec) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sess->next->prev = sess->prev;
|
|
||||||
sess->prev->next = sess->next;
|
|
||||||
|
|
||||||
sess_id = sess->sess_id;
|
|
||||||
|
|
||||||
ngx_rbtree_delete(cache->session_rbtree, &sess_id->node);
|
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
|
|
||||||
"expire session: %08Xi", sess_id->node.key);
|
|
||||||
|
|
||||||
ngx_slab_free_locked(shpool, sess);
|
|
||||||
ngx_slab_free_locked(shpool, sess_id->id);
|
|
||||||
ngx_slab_free_locked(shpool, sess_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
@ -695,7 +306,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_http_ssl_srv_conf_t *prev = parent;
|
ngx_http_ssl_srv_conf_t *prev = parent;
|
||||||
ngx_http_ssl_srv_conf_t *conf = child;
|
ngx_http_ssl_srv_conf_t *conf = child;
|
||||||
|
|
||||||
long cache_mode;
|
|
||||||
ngx_pool_cleanup_t *cln;
|
ngx_pool_cleanup_t *cln;
|
||||||
|
|
||||||
ngx_conf_merge_value(conf->enable, prev->enable, 0);
|
ngx_conf_merge_value(conf->enable, prev->enable, 0);
|
||||||
@ -784,39 +394,18 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|
|
||||||
ngx_conf_merge_value(conf->builtin_session_cache,
|
ngx_conf_merge_value(conf->builtin_session_cache,
|
||||||
prev->builtin_session_cache,
|
prev->builtin_session_cache,
|
||||||
NGX_HTTP_SSL_DFLT_BUILTIN_SCACHE);
|
NGX_SSL_DFLT_BUILTIN_SCACHE);
|
||||||
|
|
||||||
if (conf->shm_zone == NULL) {
|
if (conf->shm_zone == NULL) {
|
||||||
conf->shm_zone = prev->shm_zone;
|
conf->shm_zone = prev->shm_zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_mode = SSL_SESS_CACHE_SERVER;
|
if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
|
||||||
|
conf->builtin_session_cache,
|
||||||
if (conf->shm_zone
|
conf->shm_zone, conf->session_timeout)
|
||||||
&& conf->builtin_session_cache == NGX_HTTP_SSL_NO_BUILTIN_SCACHE)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
|
return NGX_CONF_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
SSL_CTX_set_session_cache_mode(conf->ssl.ctx, cache_mode);
|
|
||||||
|
|
||||||
SSL_CTX_set_session_id_context(conf->ssl.ctx, ngx_http_session_id_ctx,
|
|
||||||
sizeof(ngx_http_session_id_ctx) - 1);
|
|
||||||
|
|
||||||
if (conf->builtin_session_cache != NGX_HTTP_SSL_NO_BUILTIN_SCACHE) {
|
|
||||||
|
|
||||||
if (conf->builtin_session_cache != NGX_HTTP_SSL_DFLT_BUILTIN_SCACHE) {
|
|
||||||
SSL_CTX_sess_set_cache_size(conf->ssl.ctx,
|
|
||||||
conf->builtin_session_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
SSL_CTX_set_timeout(conf->ssl.ctx, conf->session_timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf->shm_zone) {
|
|
||||||
SSL_CTX_sess_set_new_cb(conf->ssl.ctx, ngx_http_ssl_new_session);
|
|
||||||
SSL_CTX_sess_set_get_cb(conf->ssl.ctx, ngx_http_ssl_get_session);
|
|
||||||
SSL_CTX_sess_set_remove_cb(conf->ssl.ctx, ngx_http_ssl_remove_session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
@ -838,7 +427,7 @@ ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
for (i = 1; i < cf->args->nelts; i++) {
|
for (i = 1; i < cf->args->nelts; i++) {
|
||||||
|
|
||||||
if (ngx_strcmp(value[i].data, "builtin") == 0) {
|
if (ngx_strcmp(value[i].data, "builtin") == 0) {
|
||||||
sscf->builtin_session_cache = NGX_HTTP_SSL_DFLT_BUILTIN_SCACHE;
|
sscf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -890,7 +479,7 @@ ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
if (n < (ngx_int_t) (8 * ngx_pagesize)) {
|
if (n < (ngx_int_t) (8 * ngx_pagesize)) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"session cache \"%V\" to small",
|
"session cache \"%V\" is too small",
|
||||||
&value[i]);
|
&value[i]);
|
||||||
|
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
@ -902,8 +491,6 @@ ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
sscf->shm_zone->init = ngx_http_ssl_session_cache_init;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,7 +498,7 @@ ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
|
if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
|
||||||
sscf->builtin_session_cache = NGX_HTTP_SSL_NO_BUILTIN_SCACHE;
|
sscf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
|
@ -13,33 +13,6 @@
|
|||||||
#include <ngx_http.h>
|
#include <ngx_http.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct ngx_http_ssl_cached_sess_s ngx_http_ssl_cached_sess_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ngx_rbtree_node_t node;
|
|
||||||
u_char *id;
|
|
||||||
size_t len;
|
|
||||||
ngx_http_ssl_cached_sess_t *session;
|
|
||||||
} ngx_http_ssl_sess_id_t;
|
|
||||||
|
|
||||||
|
|
||||||
struct ngx_http_ssl_cached_sess_s {
|
|
||||||
ngx_http_ssl_cached_sess_t *prev;
|
|
||||||
ngx_http_ssl_cached_sess_t *next;
|
|
||||||
time_t expire;
|
|
||||||
ngx_http_ssl_sess_id_t *sess_id;
|
|
||||||
u_char asn1[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ngx_rbtree_t *session_rbtree;
|
|
||||||
ngx_http_ssl_cached_sess_t session_cache_head;
|
|
||||||
ngx_http_ssl_cached_sess_t session_cache_tail;
|
|
||||||
} ngx_http_ssl_sesssion_cache_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_flag_t enable;
|
ngx_flag_t enable;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user