[nginx] SSL: object cache inheritance from the old configuration cycle.

noreply at nginx.com noreply at nginx.com
Fri Jan 17 00:38:02 UTC 2025


details:   https://github.com/nginx/nginx/commit/8311e14ae614529aabe9e72e87051d191b723fb4
branches:  master
commit:    8311e14ae614529aabe9e72e87051d191b723fb4
user:      Sergey Kandaurov <pluknet at nginx.com>
date:      Wed, 18 Dec 2024 20:03:35 +0400
description:
SSL: object cache inheritance from the old configuration cycle.

Memory based objects are always inherited, engine based objects are
never inherited to adhere the volatile nature of engines, file based
objects are inherited subject to modification time and file index.

The previous behaviour to bypass cache from the old configuration cycle
is preserved with a new directive "ssl_object_cache_inheritable off;".

---
 src/event/ngx_event_openssl_cache.c | 107 +++++++++++++++++++++++++++++++++---
 1 file changed, 99 insertions(+), 8 deletions(-)

diff --git a/src/event/ngx_event_openssl_cache.c b/src/event/ngx_event_openssl_cache.c
index 8829e2879..9d1962759 100644
--- a/src/event/ngx_event_openssl_cache.c
+++ b/src/event/ngx_event_openssl_cache.c
@@ -14,6 +14,14 @@
 #define NGX_SSL_CACHE_ENGINE  2
 
 
+#define ngx_ssl_cache_get_conf(cycle)                                         \
+    (ngx_ssl_cache_t *) ngx_get_conf(cycle->conf_ctx, ngx_openssl_cache_module)
+
+#define ngx_ssl_cache_get_old_conf(cycle)                                     \
+    cycle->old_cycle->conf_ctx ? ngx_ssl_cache_get_conf(cycle->old_cycle)     \
+                               : NULL
+
+
 typedef struct {
     unsigned                    type:2;
     unsigned                    len:30;
@@ -39,12 +47,17 @@ typedef struct {
     ngx_ssl_cache_key_t         id;
     ngx_ssl_cache_type_t       *type;
     void                       *value;
+
+    time_t                      mtime;
+    ngx_file_uniq_t             uniq;
 } ngx_ssl_cache_node_t;
 
 
 typedef struct {
     ngx_rbtree_t                rbtree;
     ngx_rbtree_node_t           sentinel;
+
+    ngx_flag_t                  inheritable;
 } ngx_ssl_cache_t;
 
 
@@ -76,22 +89,36 @@ static void *ngx_ssl_cache_ca_create(ngx_ssl_cache_key_t *id, char **err,
 static BIO *ngx_ssl_cache_create_bio(ngx_ssl_cache_key_t *id, char **err);
 
 static void *ngx_openssl_cache_create_conf(ngx_cycle_t *cycle);
+static char *ngx_openssl_cache_init_conf(ngx_cycle_t *cycle, void *conf);
 static void ngx_ssl_cache_cleanup(void *data);
 static void ngx_ssl_cache_node_insert(ngx_rbtree_node_t *temp,
     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
 
 
+static ngx_command_t  ngx_openssl_cache_commands[] = {
+
+    { ngx_string("ssl_object_cache_inheritable"),
+      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      0,
+      offsetof(ngx_ssl_cache_t, inheritable),
+      NULL },
+
+      ngx_null_command
+};
+
+
 static ngx_core_module_t  ngx_openssl_cache_module_ctx = {
     ngx_string("openssl_cache"),
     ngx_openssl_cache_create_conf,
-    NULL
+    ngx_openssl_cache_init_conf
 };
 
 
 ngx_module_t  ngx_openssl_cache_module = {
     NGX_MODULE_V1,
     &ngx_openssl_cache_module_ctx,         /* module context */
-    NULL,                                  /* module directives */
+    ngx_openssl_cache_commands,            /* module directives */
     NGX_CORE_MODULE,                       /* module type */
     NULL,                                  /* init master */
     NULL,                                  /* init module */
@@ -132,8 +159,13 @@ void *
 ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
     ngx_str_t *path, void *data)
 {
+    void                  *value;
+    time_t                 mtime;
     uint32_t               hash;
-    ngx_ssl_cache_t       *cache;
+    ngx_int_t              rc;
+    ngx_file_uniq_t        uniq;
+    ngx_file_info_t        fi;
+    ngx_ssl_cache_t       *cache, *old_cache;
     ngx_ssl_cache_key_t    id;
     ngx_ssl_cache_type_t  *type;
     ngx_ssl_cache_node_t  *cn;
@@ -151,12 +183,60 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
     hash = ngx_murmur_hash2(id.data, id.len);
 
     cn = ngx_ssl_cache_lookup(cache, type, &id, hash);
+
     if (cn != NULL) {
         return type->ref(err, cn->value);
     }
 
+    value = NULL;
+
+    if (id.type == NGX_SSL_CACHE_PATH
+        && (rc = ngx_file_info(id.data, &fi)) != NGX_FILE_ERROR)
+    {
+        mtime = ngx_file_mtime(&fi);
+        uniq = ngx_file_uniq(&fi);
+
+    } else {
+        rc = NGX_FILE_ERROR;
+        mtime = 0;
+        uniq = 0;
+    }
+
+    /* try to use a reference from the old cycle */
+
+    old_cache = ngx_ssl_cache_get_old_conf(cf->cycle);
+
+    if (old_cache && old_cache->inheritable) {
+        cn = ngx_ssl_cache_lookup(old_cache, type, &id, hash);
+
+        if (cn != NULL) {
+            switch (id.type) {
+
+            case NGX_SSL_CACHE_DATA:
+                value = type->ref(err, cn->value);
+                break;
+
+            default:
+                if (rc != NGX_FILE_ERROR
+                    && uniq == cn->uniq && mtime == cn->mtime)
+                {
+                    value = type->ref(err, cn->value);
+                }
+                break;
+            }
+        }
+    }
+
+    if (value == NULL) {
+        value = type->create(&id, err, data);
+        if (value == NULL) {
+            return NULL;
+        }
+    }
+
     cn = ngx_palloc(cf->pool, sizeof(ngx_ssl_cache_node_t) + id.len + 1);
     if (cn == NULL) {
+        type->free(value);
         return NULL;
     }
 
@@ -165,14 +245,12 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
     cn->id.len = id.len;
     cn->id.type = id.type;
     cn->type = type;
+    cn->value = value;
+    cn->mtime = mtime;
+    cn->uniq = uniq;
 
     ngx_cpystrn(cn->id.data, id.data, id.len + 1);
 
-    cn->value = type->create(&id, err, data);
-    if (cn->value == NULL) {
-        return NULL;
-    }
-
     ngx_rbtree_insert(&cache->rbtree, &cn->node);
 
     return type->ref(err, cn->value);
@@ -729,6 +807,8 @@ ngx_openssl_cache_create_conf(ngx_cycle_t *cycle)
         return NULL;
     }
 
+    cache->inheritable = NGX_CONF_UNSET;
+
     cln = ngx_pool_cleanup_add(cycle->pool, 0);
     if (cln == NULL) {
         return NULL;
@@ -744,6 +824,17 @@ ngx_openssl_cache_create_conf(ngx_cycle_t *cycle)
 }
 
 
+static char *
+ngx_openssl_cache_init_conf(ngx_cycle_t *cycle, void *conf)
+{
+    ngx_ssl_cache_t *cache = conf;
+
+    ngx_conf_init_value(cache->inheritable, 1);
+
+    return NGX_CONF_OK;
+}
+
+
 static void
 ngx_ssl_cache_cleanup(void *data)
 {


More information about the nginx-devel mailing list