Welcome! Log In Create A New Profile

Advanced

[nginx] SSL: object caching.

Anonymous User
October 01, 2024 10:02AM
details: https://github.com/nginx/nginx/commit/7d7e8d2cb8d16e409e0d4c777b30f1d8d7838c7b
branches: master
commit: 7d7e8d2cb8d16e409e0d4c777b30f1d8d7838c7b
user: Sergey Kandaurov <pluknet@nginx.com>
date: Mon, 9 Sep 2024 19:03:20 +0400
description:
SSL: object caching.

Added ngx_openssl_cache_module, which indexes a type-aware object cache.
It maps an id to a unique instance, and provides references to it, which
are dropped when the cycle's pool is destroyed.

The cache will be used in subsequent patches.

Based on previous work by Mini Hawthorne.

---
auto/modules | 3 +-
src/event/ngx_event_openssl.h | 5 +
src/event/ngx_event_openssl_cache.c | 311 ++++++++++++++++++++++++++++++++++++
3 files changed, 318 insertions(+), 1 deletion(-)

diff --git a/auto/modules b/auto/modules
index 1a5e4212d..38b3aba78 100644
--- a/auto/modules
+++ b/auto/modules
@@ -1307,10 +1307,11 @@ fi

if [ $USE_OPENSSL = YES ]; then
ngx_module_type=CORE
- ngx_module_name=ngx_openssl_module
+ ngx_module_name="ngx_openssl_module ngx_openssl_cache_module"
ngx_module_incs=
ngx_module_deps=src/event/ngx_event_openssl.h
ngx_module_srcs="src/event/ngx_event_openssl.c
+ src/event/ngx_event_openssl_cache.c
src/event/ngx_event_openssl_stapling.c"
ngx_module_libs=
ngx_module_link=YES
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index 41566422a..fa2282ce8 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -224,6 +224,11 @@ ngx_int_t ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s);
void ngx_ssl_ocsp_cleanup(ngx_connection_t *c);
ngx_int_t ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data);

+void *ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
+ ngx_str_t *path, void *data);
+void *ngx_ssl_cache_connection_fetch(ngx_pool_t *pool, ngx_uint_t index,
+ char **err, ngx_str_t *path, void *data);
+
ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
ngx_array_t *ngx_ssl_preserve_passwords(ngx_conf_t *cf,
ngx_array_t *passwords);
diff --git a/src/event/ngx_event_openssl_cache.c b/src/event/ngx_event_openssl_cache.c
new file mode 100644
index 000000000..98867de50
--- /dev/null
+++ b/src/event/ngx_event_openssl_cache.c
@@ -0,0 +1,311 @@
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+
+#define NGX_SSL_CACHE_PATH 0
+
+
+typedef struct {
+ unsigned type:2;
+ unsigned len:30;
+ u_char *data;
+} ngx_ssl_cache_key_t;
+
+
+typedef void *(*ngx_ssl_cache_create_pt)(ngx_ssl_cache_key_t *id, char **err,
+ void *data);
+typedef void (*ngx_ssl_cache_free_pt)(void *data);
+typedef void *(*ngx_ssl_cache_ref_pt)(char **err, void *data);
+
+
+typedef struct {
+ ngx_ssl_cache_create_pt create;
+ ngx_ssl_cache_free_pt free;
+ ngx_ssl_cache_ref_pt ref;
+} ngx_ssl_cache_type_t;
+
+
+typedef struct {
+ ngx_rbtree_node_t node;
+ ngx_ssl_cache_key_t id;
+ ngx_ssl_cache_type_t *type;
+ void *value;
+} ngx_ssl_cache_node_t;
+
+
+typedef struct {
+ ngx_rbtree_t rbtree;
+ ngx_rbtree_node_t sentinel;
+} ngx_ssl_cache_t;
+
+
+static ngx_int_t ngx_ssl_cache_init_key(ngx_pool_t *pool, ngx_uint_t index,
+ ngx_str_t *path, ngx_ssl_cache_key_t *id);
+static ngx_ssl_cache_node_t *ngx_ssl_cache_lookup(ngx_ssl_cache_t *cache,
+ ngx_ssl_cache_type_t *type, ngx_ssl_cache_key_t *id, uint32_t hash);
+
+static void *ngx_openssl_cache_create_conf(ngx_cycle_t *cycle);
+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_core_module_t ngx_openssl_cache_module_ctx = {
+ ngx_string("openssl_cache"),
+ ngx_openssl_cache_create_conf,
+ NULL
+};
+
+
+ngx_module_t ngx_openssl_cache_module = {
+ NGX_MODULE_V1,
+ &ngx_openssl_cache_module_ctx, /* module context */
+ NULL, /* module directives */
+ NGX_CORE_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_ssl_cache_type_t ngx_ssl_cache_types[] = {
+
+};
+
+
+void *
+ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
+ ngx_str_t *path, void *data)
+{
+ uint32_t hash;
+ ngx_ssl_cache_t *cache;
+ ngx_ssl_cache_key_t id;
+ ngx_ssl_cache_type_t *type;
+ ngx_ssl_cache_node_t *cn;
+
+ if (ngx_ssl_cache_init_key(cf->pool, index, path, &id) != NGX_OK) {
+ return NULL;
+ }
+
+ cache = (ngx_ssl_cache_t *) ngx_get_conf(cf->cycle->conf_ctx,
+ ngx_openssl_cache_module);
+
+ type = &ngx_ssl_cache_types[index];
+ 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);
+ }
+
+ cn = ngx_palloc(cf->pool, sizeof(ngx_ssl_cache_node_t) + id.len + 1);
+ if (cn == NULL) {
+ return NULL;
+ }
+
+ cn->node.key = hash;
+ cn->id.data = (u_char *)(cn + 1);
+ cn->id.len = id.len;
+ cn->id.type = id.type;
+ cn->type = type;
+
+ 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);
+}
+
+
+void *
+ngx_ssl_cache_connection_fetch(ngx_pool_t *pool, ngx_uint_t index, char **err,
+ ngx_str_t *path, void *data)
+{
+ ngx_ssl_cache_key_t id;
+
+ if (ngx_ssl_cache_init_key(pool, index, path, &id) != NGX_OK) {
+ return NULL;
+ }
+
+ return ngx_ssl_cache_types[index].create(&id, err, data);
+}
+
+
+static ngx_int_t
+ngx_ssl_cache_init_key(ngx_pool_t *pool, ngx_uint_t index, ngx_str_t *path,
+ ngx_ssl_cache_key_t *id)
+{
+ if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, path)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ id->type = NGX_SSL_CACHE_PATH;
+
+ id->len = path->len;
+ id->data = path->data;
+
+ return NGX_OK;
+}
+
+
+static ngx_ssl_cache_node_t *
+ngx_ssl_cache_lookup(ngx_ssl_cache_t *cache, ngx_ssl_cache_type_t *type,
+ ngx_ssl_cache_key_t *id, uint32_t hash)
+{
+ ngx_int_t rc;
+ ngx_rbtree_node_t *node, *sentinel;
+ ngx_ssl_cache_node_t *cn;
+
+ node = cache->rbtree.root;
+ sentinel = cache->rbtree.sentinel;
+
+ while (node != sentinel) {
+
+ if (hash < node->key) {
+ node = node->left;
+ continue;
+ }
+
+ if (hash > node->key) {
+ node = node->right;
+ continue;
+ }
+
+ /* hash == node->key */
+
+ cn = (ngx_ssl_cache_node_t *) node;
+
+ if (type < cn->type) {
+ node = node->left;
+ continue;
+ }
+
+ if (type > cn->type) {
+ node = node->right;
+ continue;
+ }
+
+ /* type == cn->type */
+
+ rc = ngx_memn2cmp(id->data, cn->id.data, id->len, cn->id.len);
+
+ if (rc == 0) {
+ return cn;
+ }
+
+ node = (rc < 0) ? node->left : node->right;
+ }
+
+ return NULL;
+}
+
+
+static void *
+ngx_openssl_cache_create_conf(ngx_cycle_t *cycle)
+{
+ ngx_ssl_cache_t *cache;
+ ngx_pool_cleanup_t *cln;
+
+ cache = ngx_pcalloc(cycle->pool, sizeof(ngx_ssl_cache_t));
+ if (cache == NULL) {
+ return NULL;
+ }
+
+ cln = ngx_pool_cleanup_add(cycle->pool, 0);
+ if (cln == NULL) {
+ return NULL;
+ }
+
+ cln->handler = ngx_ssl_cache_cleanup;
+ cln->data = cache;
+
+ ngx_rbtree_init(&cache->rbtree, &cache->sentinel,
+ ngx_ssl_cache_node_insert);
+
+ return cache;
+}
+
+
+static void
+ngx_ssl_cache_cleanup(void *data)
+{
+ ngx_ssl_cache_t *cache = data;
+
+ ngx_rbtree_t *tree;
+ ngx_rbtree_node_t *node;
+ ngx_ssl_cache_node_t *cn;
+
+ tree = &cache->rbtree;
+
+ if (tree->root == tree->sentinel) {
+ return;
+ }
+
+ for (node = ngx_rbtree_min(tree->root, tree->sentinel);
+ node;
+ node = ngx_rbtree_next(tree, node))
+ {
+ cn = ngx_rbtree_data(node, ngx_ssl_cache_node_t, node);
+ cn->type->free(cn->value);
+ }
+}
+
+
+static void
+ngx_ssl_cache_node_insert(ngx_rbtree_node_t *temp,
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
+{
+ ngx_rbtree_node_t **p;
+ ngx_ssl_cache_node_t *n, *t;
+
+ for ( ;; ) {
+
+ n = ngx_rbtree_data(node, ngx_ssl_cache_node_t, node);
+ t = ngx_rbtree_data(temp, ngx_ssl_cache_node_t, node);
+
+ if (node->key != temp->key) {
+
+ p = (node->key < temp->key) ? &temp->left : &temp->right;
+
+ } else if (n->type != t->type) {
+
+ p = (n->type < t->type) ? &temp->left : &temp->right;
+
+ } else {
+
+ p = (ngx_memn2cmp(n->id.data, t->id.data, n->id.len, t->id.len)
+ < 0) ? &temp->left : &temp->right;
+ }
+
+ if (*p == sentinel) {
+ break;
+ }
+
+ temp = *p;
+ }
+
+ *p = node;
+ node->parent = temp;
+ node->left = sentinel;
+ node->right = sentinel;
+ ngx_rbt_red(node);
+}
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[nginx] SSL: object caching.

Anonymous User 128 October 01, 2024 10:02AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 155
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 500 on July 15, 2024
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready