diff src/http/modules/ngx_http_ssl_module.c @ 974:8dfb3aa75de2

move the session cache callbacks to the ngx_openssl_module
author Igor Sysoev <igor@sysoev.ru>
date Wed, 03 Jan 2007 15:25:40 +0000
parents e1ede83911ef
children 86c5c9288acc
line wrap: on
line diff
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -18,17 +18,6 @@ typedef ngx_int_t (*ngx_ssl_variable_han
 #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 ngx_http_variable_t  ngx_http_ssl
 };
 
 
-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_merge_srv_conf(ngx_conf_t *
     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_http_ssl_merge_srv_conf(ngx_conf_t *
 
     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 @@ ngx_http_ssl_session_cache(ngx_conf_t *c
     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 @@ ngx_http_ssl_session_cache(ngx_conf_t *c
 
             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 @@ ngx_http_ssl_session_cache(ngx_conf_t *c
                 return NGX_CONF_ERROR;
             }
 
-            sscf->shm_zone->init = ngx_http_ssl_session_cache_init;
-
             continue;
         }
 
@@ -911,7 +498,7 @@ ngx_http_ssl_session_cache(ngx_conf_t *c
     }
 
     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;