move the session cache callbacks to the ngx_openssl_module
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index f4163e9..c54884b 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -64,11 +64,11 @@
#include <ngx_times.h>
#include <ngx_shmtx.h>
#include <ngx_slab.h>
+#include <ngx_inet.h>
+#include <ngx_cycle.h>
#if (NGX_OPENSSL)
#include <ngx_event_openssl.h>
#endif
-#include <ngx_inet.h>
-#include <ngx_cycle.h>
#include <ngx_process_cycle.h>
#include <ngx_conf_file.h>
#include <ngx_os.h>
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index c5389e3..ba83e7f 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -22,6 +22,16 @@
static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
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 char *ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf);
static void ngx_openssl_exit(ngx_cycle_t *cycle);
@@ -86,6 +96,7 @@
int ngx_ssl_connection_index;
int ngx_ssl_server_conf_index;
+int ngx_ssl_session_cache_index;
ngx_int_t
@@ -117,6 +128,14 @@
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;
}
@@ -279,7 +298,7 @@
name = X509_get_issuer_name(cert);
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, "
"subject:\"%s\",issuer: \"%s\"",
ok, err, depth, subject, issuer);
@@ -1033,7 +1052,7 @@
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) {
return;
@@ -1119,6 +1138,428 @@
}
+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
ngx_ssl_cleanup_ctx(void *data)
{
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index 758f579..078b2ba 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -51,6 +51,41 @@
} 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_SSLv3 4
#define NGX_SSL_TLSv1 8
@@ -69,6 +104,8 @@
ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
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_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_uint_t flags);
@@ -93,8 +130,6 @@
ngx_str_t *s);
-
-
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_write(ngx_connection_t *c, u_char *data, size_t size);
@@ -109,6 +144,7 @@
extern int ngx_ssl_connection_index;
extern int ngx_ssl_server_conf_index;
+extern int ngx_ssl_session_cache_index;
#endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index 412aa47..e77e767 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -18,17 +18,6 @@
#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,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
@@ -199,385 +188,7 @@
};
-static u_char ngx_http_session_id_ctx[] = "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_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
static ngx_int_t
@@ -695,7 +306,6 @@
ngx_http_ssl_srv_conf_t *prev = parent;
ngx_http_ssl_srv_conf_t *conf = child;
- long cache_mode;
ngx_pool_cleanup_t *cln;
ngx_conf_merge_value(conf->enable, prev->enable, 0);
@@ -784,39 +394,18 @@
ngx_conf_merge_value(conf->builtin_session_cache,
prev->builtin_session_cache,
- NGX_HTTP_SSL_DFLT_BUILTIN_SCACHE);
+ NGX_SSL_DFLT_BUILTIN_SCACHE);
if (conf->shm_zone == NULL) {
conf->shm_zone = prev->shm_zone;
}
- cache_mode = SSL_SESS_CACHE_SERVER;
-
- if (conf->shm_zone
- && conf->builtin_session_cache == NGX_HTTP_SSL_NO_BUILTIN_SCACHE)
+ if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
+ conf->builtin_session_cache,
+ conf->shm_zone, conf->session_timeout)
+ != NGX_OK)
{
- cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
- }
-
- 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_ERROR;
}
return NGX_CONF_OK;
@@ -838,7 +427,7 @@
for (i = 1; i < cf->args->nelts; i++) {
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;
}
@@ -890,7 +479,7 @@
if (n < (ngx_int_t) (8 * ngx_pagesize)) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "session cache \"%V\" to small",
+ "session cache \"%V\" is too small",
&value[i]);
return NGX_CONF_ERROR;
@@ -902,8 +491,6 @@
return NGX_CONF_ERROR;
}
- sscf->shm_zone->init = ngx_http_ssl_session_cache_init;
-
continue;
}
@@ -911,7 +498,7 @@
}
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;
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
index 7a5c6d5..1ef1ffe 100644
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -13,33 +13,6 @@
#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 {
ngx_flag_t enable;