src/event/ngx_event_openssl_cache.c - nginx

Global variables defined

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Nginx, Inc.
  3. */


  4. #include <ngx_config.h>
  5. #include <ngx_core.h>
  6. #include <ngx_event.h>

  7. #ifdef ERR_R_OSSL_STORE_LIB
  8. #include <openssl/store.h>
  9. #include <openssl/ui.h>
  10. #endif


  11. #define NGX_SSL_CACHE_PATH    0
  12. #define NGX_SSL_CACHE_DATA    1
  13. #define NGX_SSL_CACHE_ENGINE  2
  14. #define NGX_SSL_CACHE_STORE   3

  15. #define NGX_SSL_CACHE_DISABLED  (ngx_array_t *) (uintptr_t) -1


  16. #define ngx_ssl_cache_get_conf(cycle)                                         \
  17.     (ngx_ssl_cache_t *) ngx_get_conf(cycle->conf_ctx, ngx_openssl_cache_module)

  18. #define ngx_ssl_cache_get_old_conf(cycle)                                     \
  19.     cycle->old_cycle->conf_ctx ? ngx_ssl_cache_get_conf(cycle->old_cycle)     \
  20.                                : NULL


  21. typedef struct {
  22.     unsigned                    type:2;
  23.     unsigned                    len:30;
  24.     u_char                     *data;
  25. } ngx_ssl_cache_key_t;


  26. typedef void *(*ngx_ssl_cache_create_pt)(ngx_ssl_cache_key_t *id, char **err,
  27.     void *data);
  28. typedef void (*ngx_ssl_cache_free_pt)(void *data);
  29. typedef void *(*ngx_ssl_cache_ref_pt)(char **err, void *data);


  30. typedef struct {
  31.     ngx_ssl_cache_create_pt     create;
  32.     ngx_ssl_cache_free_pt       free;
  33.     ngx_ssl_cache_ref_pt        ref;
  34. } ngx_ssl_cache_type_t;


  35. typedef struct {
  36.     ngx_rbtree_node_t           node;
  37.     ngx_queue_t                 queue;
  38.     ngx_ssl_cache_key_t         id;
  39.     ngx_ssl_cache_type_t       *type;
  40.     void                       *value;

  41.     time_t                      created;
  42.     time_t                      accessed;

  43.     time_t                      mtime;
  44.     ngx_file_uniq_t             uniq;
  45. } ngx_ssl_cache_node_t;


  46. struct ngx_ssl_cache_s {
  47.     ngx_rbtree_t                rbtree;
  48.     ngx_rbtree_node_t           sentinel;
  49.     ngx_queue_t                 expire_queue;

  50.     ngx_flag_t                  inheritable;

  51.     ngx_uint_t                  current;
  52.     ngx_uint_t                  max;
  53.     time_t                      valid;
  54.     time_t                      inactive;
  55. };


  56. typedef struct {
  57.     ngx_str_t                  *pwd;
  58.     unsigned                    encrypted:1;
  59. } ngx_ssl_cache_pwd_t;


  60. static ngx_int_t ngx_ssl_cache_init_key(ngx_pool_t *pool, ngx_uint_t index,
  61.     ngx_str_t *path, ngx_ssl_cache_key_t *id);
  62. static ngx_ssl_cache_node_t *ngx_ssl_cache_lookup(ngx_ssl_cache_t *cache,
  63.     ngx_ssl_cache_type_t *type, ngx_ssl_cache_key_t *id, uint32_t hash);
  64. static void ngx_ssl_cache_expire(ngx_ssl_cache_t *cache, ngx_uint_t n,
  65.     ngx_log_t *log);

  66. static void *ngx_ssl_cache_cert_create(ngx_ssl_cache_key_t *id, char **err,
  67.     void *data);
  68. static void ngx_ssl_cache_cert_free(void *data);
  69. static void *ngx_ssl_cache_cert_ref(char **err, void *data);

  70. static void *ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err,
  71.     void *data);
  72. static int ngx_ssl_cache_pkey_password_callback(char *buf, int size, int rwflag,
  73.     void *userdata);
  74. static void ngx_ssl_cache_pkey_free(void *data);
  75. static void *ngx_ssl_cache_pkey_ref(char **err, void *data);

  76. static void *ngx_ssl_cache_crl_create(ngx_ssl_cache_key_t *id, char **err,
  77.     void *data);
  78. static void ngx_ssl_cache_crl_free(void *data);
  79. static void *ngx_ssl_cache_crl_ref(char **err, void *data);

  80. static void *ngx_ssl_cache_ca_create(ngx_ssl_cache_key_t *id, char **err,
  81.     void *data);

  82. static BIO *ngx_ssl_cache_create_bio(ngx_ssl_cache_key_t *id, char **err);

  83. static void *ngx_openssl_cache_create_conf(ngx_cycle_t *cycle);
  84. static char *ngx_openssl_cache_init_conf(ngx_cycle_t *cycle, void *conf);
  85. static void ngx_ssl_cache_cleanup(void *data);
  86. static void ngx_ssl_cache_node_insert(ngx_rbtree_node_t *temp,
  87.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
  88. static void ngx_ssl_cache_node_free(ngx_rbtree_t *rbtree,
  89.     ngx_ssl_cache_node_t *cn);

  90. static ngx_int_t ngx_openssl_cache_init_worker(ngx_cycle_t *cycle);


  91. static ngx_command_t  ngx_openssl_cache_commands[] = {

  92.     { ngx_string("ssl_object_cache_inheritable"),
  93.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  94.       ngx_conf_set_flag_slot,
  95.       0,
  96.       offsetof(ngx_ssl_cache_t, inheritable),
  97.       NULL },

  98.       ngx_null_command
  99. };


  100. static ngx_core_module_t  ngx_openssl_cache_module_ctx = {
  101.     ngx_string("openssl_cache"),
  102.     ngx_openssl_cache_create_conf,
  103.     ngx_openssl_cache_init_conf
  104. };


  105. ngx_module_t  ngx_openssl_cache_module = {
  106.     NGX_MODULE_V1,
  107.     &ngx_openssl_cache_module_ctx,         /* module context */
  108.     ngx_openssl_cache_commands,            /* module directives */
  109.     NGX_CORE_MODULE,                       /* module type */
  110.     NULL,                                  /* init master */
  111.     NULL,                                  /* init module */
  112.     ngx_openssl_cache_init_worker,         /* init process */
  113.     NULL,                                  /* init thread */
  114.     NULL,                                  /* exit thread */
  115.     NULL,                                  /* exit process */
  116.     NULL,                                  /* exit master */
  117.     NGX_MODULE_V1_PADDING
  118. };


  119. static ngx_ssl_cache_type_t  ngx_ssl_cache_types[] = {

  120.     /* NGX_SSL_CACHE_CERT */
  121.     { ngx_ssl_cache_cert_create,
  122.       ngx_ssl_cache_cert_free,
  123.       ngx_ssl_cache_cert_ref },

  124.     /* NGX_SSL_CACHE_PKEY */
  125.     { ngx_ssl_cache_pkey_create,
  126.       ngx_ssl_cache_pkey_free,
  127.       ngx_ssl_cache_pkey_ref },

  128.     /* NGX_SSL_CACHE_CRL */
  129.     { ngx_ssl_cache_crl_create,
  130.       ngx_ssl_cache_crl_free,
  131.       ngx_ssl_cache_crl_ref },

  132.     /* NGX_SSL_CACHE_CA */
  133.     { ngx_ssl_cache_ca_create,
  134.       ngx_ssl_cache_cert_free,
  135.       ngx_ssl_cache_cert_ref }
  136. };


  137. void *
  138. ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
  139.     ngx_str_t *path, void *data)
  140. {
  141.     void                  *value;
  142.     time_t                 mtime;
  143.     uint32_t               hash;
  144.     ngx_int_t              rc;
  145.     ngx_uint_t             invalidate;
  146.     ngx_file_uniq_t        uniq;
  147.     ngx_file_info_t        fi;
  148.     ngx_ssl_cache_t       *cache, *old_cache;
  149.     ngx_ssl_cache_key_t    id;
  150.     ngx_ssl_cache_type_t  *type;
  151.     ngx_ssl_cache_node_t  *cn;

  152.     *err = NULL;

  153.     invalidate = index & NGX_SSL_CACHE_INVALIDATE;
  154.     index &= ~NGX_SSL_CACHE_INVALIDATE;

  155.     if (ngx_ssl_cache_init_key(cf->pool, index, path, &id) != NGX_OK) {
  156.         return NULL;
  157.     }

  158.     if (id.type == NGX_SSL_CACHE_DATA) {
  159.         invalidate = 0;
  160.     }

  161.     cache = (ngx_ssl_cache_t *) ngx_get_conf(cf->cycle->conf_ctx,
  162.                                              ngx_openssl_cache_module);

  163.     type = &ngx_ssl_cache_types[index];
  164.     hash = ngx_murmur_hash2(id.data, id.len);

  165.     cn = ngx_ssl_cache_lookup(cache, type, &id, hash);

  166.     if (cn != NULL) {
  167.         if (!invalidate) {
  168.             return type->ref(err, cn->value);
  169.         }

  170.         type->free(cn->value);
  171.         ngx_rbtree_delete(&cache->rbtree, &cn->node);
  172.     }

  173.     value = NULL;

  174.     if (id.type == NGX_SSL_CACHE_PATH
  175.         && (rc = ngx_file_info(id.data, &fi)) != NGX_FILE_ERROR)
  176.     {
  177.         mtime = ngx_file_mtime(&fi);
  178.         uniq = ngx_file_uniq(&fi);

  179.     } else {
  180.         rc = NGX_FILE_ERROR;
  181.         mtime = 0;
  182.         uniq = 0;
  183.     }

  184.     /* try to use a reference from the old cycle */

  185.     old_cache = ngx_ssl_cache_get_old_conf(cf->cycle);

  186.     if (old_cache && old_cache->inheritable && !invalidate) {
  187.         cn = ngx_ssl_cache_lookup(old_cache, type, &id, hash);

  188.         if (cn != NULL) {
  189.             switch (id.type) {

  190.             case NGX_SSL_CACHE_DATA:
  191.                 value = type->ref(err, cn->value);
  192.                 break;

  193.             default:
  194.                 if (rc != NGX_FILE_ERROR
  195.                     && uniq == cn->uniq && mtime == cn->mtime)
  196.                 {
  197.                     value = type->ref(err, cn->value);
  198.                 }
  199.                 break;
  200.             }
  201.         }
  202.     }

  203.     if (value == NULL) {
  204.         value = type->create(&id, err, &data);

  205.         if (value == NULL || data == NGX_SSL_CACHE_DISABLED) {
  206.             return value;
  207.         }
  208.     }

  209.     cn = ngx_palloc(cf->pool, sizeof(ngx_ssl_cache_node_t) + id.len + 1);
  210.     if (cn == NULL) {
  211.         type->free(value);
  212.         return NULL;
  213.     }

  214.     cn->node.key = hash;
  215.     cn->id.data = (u_char *)(cn + 1);
  216.     cn->id.len = id.len;
  217.     cn->id.type = id.type;
  218.     cn->type = type;
  219.     cn->value = value;
  220.     cn->mtime = mtime;
  221.     cn->uniq = uniq;

  222.     ngx_cpystrn(cn->id.data, id.data, id.len + 1);

  223.     ngx_queue_init(&cn->queue);

  224.     ngx_rbtree_insert(&cache->rbtree, &cn->node);

  225.     return type->ref(err, cn->value);
  226. }


  227. void *
  228. ngx_ssl_cache_connection_fetch(ngx_ssl_cache_t *cache, ngx_pool_t *pool,
  229.     ngx_uint_t index, char **err, ngx_str_t *path, void *data)
  230. {
  231.     void                  *value;
  232.     time_t                 now;
  233.     uint32_t               hash;
  234.     ngx_uint_t             invalidate;
  235.     ngx_file_info_t        fi;
  236.     ngx_ssl_cache_key_t    id;
  237.     ngx_ssl_cache_type_t  *type;
  238.     ngx_ssl_cache_node_t  *cn;

  239.     *err = NULL;

  240.     invalidate = index & NGX_SSL_CACHE_INVALIDATE;
  241.     index &= ~NGX_SSL_CACHE_INVALIDATE;

  242.     if (ngx_ssl_cache_init_key(pool, index, path, &id) != NGX_OK) {
  243.         return NULL;
  244.     }

  245.     type = &ngx_ssl_cache_types[index];

  246.     if (cache == NULL) {
  247.         return type->create(&id, err, &data);
  248.     }

  249.     now = ngx_time();

  250.     hash = ngx_murmur_hash2(id.data, id.len);

  251.     cn = ngx_ssl_cache_lookup(cache, type, &id, hash);

  252.     if (cn != NULL) {
  253.         ngx_queue_remove(&cn->queue);

  254.         if (id.type == NGX_SSL_CACHE_DATA) {
  255.             goto found;
  256.         }

  257.         if (!invalidate && now - cn->created <= cache->valid) {
  258.             goto found;
  259.         }

  260.         switch (id.type) {

  261.         case NGX_SSL_CACHE_PATH:

  262.             if (ngx_file_info(id.data, &fi) != NGX_FILE_ERROR) {

  263.                 if (!invalidate
  264.                     && ngx_file_uniq(&fi) == cn->uniq
  265.                     && ngx_file_mtime(&fi) == cn->mtime)
  266.                 {
  267.                     break;
  268.                 }

  269.                 cn->mtime = ngx_file_mtime(&fi);
  270.                 cn->uniq = ngx_file_uniq(&fi);

  271.             } else {
  272.                 cn->mtime = 0;
  273.                 cn->uniq = 0;
  274.             }

  275.             /* fall through */

  276.         default:
  277.             ngx_log_debug1(NGX_LOG_DEBUG_CORE, pool->log, 0,
  278.                            "update cached ssl object: %s", cn->id.data);

  279.             type->free(cn->value);

  280.             value = type->create(&id, err, &data);

  281.             if (value == NULL || data == NGX_SSL_CACHE_DISABLED) {
  282.                 ngx_rbtree_delete(&cache->rbtree, &cn->node);

  283.                 cache->current--;

  284.                 ngx_free(cn);

  285.                 return value;
  286.             }

  287.             cn->value = value;
  288.         }

  289.         cn->created = now;

  290.         goto found;
  291.     }

  292.     value = type->create(&id, err, &data);

  293.     if (value == NULL || data == NGX_SSL_CACHE_DISABLED) {
  294.         return value;
  295.     }

  296.     cn = ngx_alloc(sizeof(ngx_ssl_cache_node_t) + id.len + 1, pool->log);
  297.     if (cn == NULL) {
  298.         type->free(value);
  299.         return NULL;
  300.     }

  301.     cn->node.key = hash;
  302.     cn->id.data = (u_char *)(cn + 1);
  303.     cn->id.len = id.len;
  304.     cn->id.type = id.type;
  305.     cn->type = type;
  306.     cn->value = value;
  307.     cn->created = now;

  308.     ngx_cpystrn(cn->id.data, id.data, id.len + 1);

  309.     if (id.type == NGX_SSL_CACHE_PATH) {

  310.         if (ngx_file_info(id.data, &fi) != NGX_FILE_ERROR) {
  311.             cn->mtime = ngx_file_mtime(&fi);
  312.             cn->uniq = ngx_file_uniq(&fi);

  313.         } else {
  314.             cn->mtime = 0;
  315.             cn->uniq = 0;
  316.         }
  317.     }

  318.     ngx_ssl_cache_expire(cache, 1, pool->log);

  319.     if (cache->current >= cache->max) {
  320.         ngx_ssl_cache_expire(cache, 0, pool->log);
  321.     }

  322.     ngx_rbtree_insert(&cache->rbtree, &cn->node);

  323.     cache->current++;

  324. found:

  325.     cn->accessed = now;

  326.     ngx_queue_insert_head(&cache->expire_queue, &cn->queue);

  327.     return type->ref(err, cn->value);
  328. }


  329. static ngx_int_t
  330. ngx_ssl_cache_init_key(ngx_pool_t *pool, ngx_uint_t index, ngx_str_t *path,
  331.     ngx_ssl_cache_key_t *id)
  332. {
  333.     if (index <= NGX_SSL_CACHE_PKEY
  334.         && ngx_strncmp(path->data, "data:", sizeof("data:") - 1) == 0)
  335.     {
  336.         id->type = NGX_SSL_CACHE_DATA;

  337.     } else if (index == NGX_SSL_CACHE_PKEY
  338.         && ngx_strncmp(path->data, "engine:", sizeof("engine:") - 1) == 0)
  339.     {
  340.         id->type = NGX_SSL_CACHE_ENGINE;

  341.     } else if (index == NGX_SSL_CACHE_PKEY
  342.         && ngx_strncmp(path->data, "store:", sizeof("store:") - 1) == 0)
  343.     {
  344.         id->type = NGX_SSL_CACHE_STORE;

  345.     } else {
  346.         if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, path)
  347.             != NGX_OK)
  348.         {
  349.             return NGX_ERROR;
  350.         }

  351.         id->type = NGX_SSL_CACHE_PATH;
  352.     }

  353.     id->len = path->len;
  354.     id->data = path->data;

  355.     return NGX_OK;
  356. }


  357. static ngx_ssl_cache_node_t *
  358. ngx_ssl_cache_lookup(ngx_ssl_cache_t *cache, ngx_ssl_cache_type_t *type,
  359.     ngx_ssl_cache_key_t *id, uint32_t hash)
  360. {
  361.     ngx_int_t              rc;
  362.     ngx_rbtree_node_t     *node, *sentinel;
  363.     ngx_ssl_cache_node_t  *cn;

  364.     node = cache->rbtree.root;
  365.     sentinel = cache->rbtree.sentinel;

  366.     while (node != sentinel) {

  367.         if (hash < node->key) {
  368.             node = node->left;
  369.             continue;
  370.         }

  371.         if (hash > node->key) {
  372.             node = node->right;
  373.             continue;
  374.         }

  375.         /* hash == node->key */

  376.         cn = (ngx_ssl_cache_node_t *) node;

  377.         if (type < cn->type) {
  378.             node = node->left;
  379.             continue;
  380.         }

  381.         if (type > cn->type) {
  382.             node = node->right;
  383.             continue;
  384.         }

  385.         /* type == cn->type */

  386.         rc = ngx_memn2cmp(id->data, cn->id.data, id->len, cn->id.len);

  387.         if (rc == 0) {
  388.             return cn;
  389.         }

  390.         node = (rc < 0) ? node->left : node->right;
  391.     }

  392.     return NULL;
  393. }


  394. static void
  395. ngx_ssl_cache_expire(ngx_ssl_cache_t *cache, ngx_uint_t n,
  396.     ngx_log_t *log)
  397. {
  398.     time_t                 now;
  399.     ngx_queue_t           *q;
  400.     ngx_ssl_cache_node_t  *cn;

  401.     now = ngx_time();

  402.     while (n < 3) {

  403.         if (ngx_queue_empty(&cache->expire_queue)) {
  404.             return;
  405.         }

  406.         q = ngx_queue_last(&cache->expire_queue);

  407.         cn = ngx_queue_data(q, ngx_ssl_cache_node_t, queue);

  408.         if (n++ != 0 && now - cn->accessed <= cache->inactive) {
  409.             return;
  410.         }

  411.         ngx_ssl_cache_node_free(&cache->rbtree, cn);

  412.         cache->current--;
  413.     }
  414. }


  415. static void *
  416. ngx_ssl_cache_cert_create(ngx_ssl_cache_key_t *id, char **err, void *data)
  417. {
  418.     BIO             *bio;
  419.     X509            *x509;
  420.     u_long           n;
  421.     STACK_OF(X509)  *chain;

  422.     chain = sk_X509_new_null();
  423.     if (chain == NULL) {
  424.         *err = "sk_X509_new_null() failed";
  425.         return NULL;
  426.     }

  427.     bio = ngx_ssl_cache_create_bio(id, err);
  428.     if (bio == NULL) {
  429.         sk_X509_pop_free(chain, X509_free);
  430.         return NULL;
  431.     }

  432.     /* certificate itself */

  433.     x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
  434.     if (x509 == NULL) {
  435.         *err = "PEM_read_bio_X509_AUX() failed";
  436.         BIO_free(bio);
  437.         sk_X509_pop_free(chain, X509_free);
  438.         return NULL;
  439.     }

  440.     if (sk_X509_push(chain, x509) == 0) {
  441.         *err = "sk_X509_push() failed";
  442.         BIO_free(bio);
  443.         X509_free(x509);
  444.         sk_X509_pop_free(chain, X509_free);
  445.         return NULL;
  446.     }

  447.     /* rest of the chain */

  448.     for ( ;; ) {

  449.         x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
  450.         if (x509 == NULL) {
  451.             n = ERR_peek_last_error();

  452.             if (ERR_GET_LIB(n) == ERR_LIB_PEM
  453.                 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
  454.             {
  455.                 /* end of file */
  456.                 ERR_clear_error();
  457.                 break;
  458.             }

  459.             /* some real error */

  460.             *err = "PEM_read_bio_X509() failed";
  461.             BIO_free(bio);
  462.             sk_X509_pop_free(chain, X509_free);
  463.             return NULL;
  464.         }

  465.         if (sk_X509_push(chain, x509) == 0) {
  466.             *err = "sk_X509_push() failed";
  467.             BIO_free(bio);
  468.             X509_free(x509);
  469.             sk_X509_pop_free(chain, X509_free);
  470.             return NULL;
  471.         }
  472.     }

  473.     BIO_free(bio);

  474.     return chain;
  475. }


  476. static void
  477. ngx_ssl_cache_cert_free(void *data)
  478. {
  479.     sk_X509_pop_free(data, X509_free);
  480. }


  481. static void *
  482. ngx_ssl_cache_cert_ref(char **err, void *data)
  483. {
  484.     int              n, i;
  485.     X509            *x509;
  486.     STACK_OF(X509)  *chain;

  487.     chain = sk_X509_dup(data);
  488.     if (chain == NULL) {
  489.         *err = "sk_X509_dup() failed";
  490.         return NULL;
  491.     }

  492.     n = sk_X509_num(chain);

  493.     for (i = 0; i < n; i++) {
  494.         x509 = sk_X509_value(chain, i);

  495. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  496.         X509_up_ref(x509);
  497. #else
  498.         CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
  499. #endif
  500.     }

  501.     return chain;
  502. }


  503. static void *
  504. ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data)
  505. {
  506.     ngx_array_t  **passwords = data;

  507.     BIO                  *bio;
  508.     EVP_PKEY             *pkey;
  509.     ngx_uint_t            tries;
  510.     pem_password_cb      *cb;
  511.     ngx_ssl_cache_pwd_t   cb_data, *pwd;

  512.     if (id->type == NGX_SSL_CACHE_ENGINE) {

  513. #ifndef OPENSSL_NO_ENGINE

  514.         u_char  *p, *last;
  515.         ENGINE  *engine;

  516.         p = id->data + sizeof("engine:") - 1;
  517.         last = (u_char *) ngx_strchr(p, ':');

  518.         if (last == NULL) {
  519.             *err = "invalid syntax";
  520.             return NULL;
  521.         }

  522.         *last = '\0';

  523.         engine = ENGINE_by_id((char *) p);

  524.         *last++ = ':';

  525.         if (engine == NULL) {
  526.             *err = "ENGINE_by_id() failed";
  527.             return NULL;
  528.         }

  529.         pkey = ENGINE_load_private_key(engine, (char *) last, NULL, NULL);

  530.         if (pkey == NULL) {
  531.             *err = "ENGINE_load_private_key() failed";
  532.             ENGINE_free(engine);
  533.             return NULL;
  534.         }

  535.         ENGINE_free(engine);

  536.         return pkey;

  537. #else

  538.         *err = "loading \"engine:...\" certificate keys is not supported";
  539.         return NULL;

  540. #endif
  541.     }

  542.     cb_data.encrypted = 0;

  543.     if (*passwords) {
  544.         cb_data.pwd = (*passwords)->elts;
  545.         tries = (*passwords)->nelts;
  546.         pwd = &cb_data;
  547.         cb = ngx_ssl_cache_pkey_password_callback;

  548.     } else {
  549.         cb_data.pwd = NULL;
  550.         tries = 1;
  551.         pwd = NULL;
  552.         cb = NULL;
  553.     }

  554.     if (id->type == NGX_SSL_CACHE_STORE) {

  555. #ifdef ERR_R_OSSL_STORE_LIB

  556.         u_char           *uri;
  557.         UI_METHOD        *method;
  558.         OSSL_STORE_CTX   *store;
  559.         OSSL_STORE_INFO  *info;

  560.         method = (cb != NULL) ? UI_UTIL_wrap_read_pem_callback(cb, 0) : NULL;
  561.         uri = id->data + sizeof("store:") - 1;

  562.         store = OSSL_STORE_open((char *) uri, method, pwd, NULL, NULL);

  563.         if (store == NULL) {
  564.             *err = "OSSL_STORE_open() failed";

  565.             if (method != NULL) {
  566.                 UI_destroy_method(method);
  567.             }

  568.             return NULL;
  569.         }

  570.         pkey = NULL;

  571.         while (pkey == NULL && !OSSL_STORE_eof(store)) {
  572.             info = OSSL_STORE_load(store);

  573.             if (info == NULL) {
  574.                 continue;
  575.             }

  576.             if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
  577.                 pkey = OSSL_STORE_INFO_get1_PKEY(info);
  578.             }

  579.             OSSL_STORE_INFO_free(info);
  580.         }

  581.         OSSL_STORE_close(store);

  582.         if (method != NULL) {
  583.             UI_destroy_method(method);
  584.         }

  585.         if (pkey == NULL) {
  586.             *err = "OSSL_STORE_load() failed";
  587.             return NULL;
  588.         }

  589.         if (cb_data.encrypted) {
  590.             *passwords = NGX_SSL_CACHE_DISABLED;
  591.         }

  592.         return pkey;

  593. #else

  594.         *err = "loading \"store:...\" certificate keys is not supported";
  595.         return NULL;

  596. #endif
  597.     }

  598.     bio = ngx_ssl_cache_create_bio(id, err);
  599.     if (bio == NULL) {
  600.         return NULL;
  601.     }

  602.     for ( ;; ) {

  603.         pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd);
  604.         if (pkey != NULL) {
  605.             break;
  606.         }

  607.         if (tries-- > 1) {
  608.             ERR_clear_error();
  609.             (void) BIO_reset(bio);
  610.             cb_data.pwd++;
  611.             continue;
  612.         }

  613.         *err = "PEM_read_bio_PrivateKey() failed";
  614.         BIO_free(bio);
  615.         return NULL;
  616.     }

  617.     if (cb_data.encrypted) {
  618.         *passwords = NGX_SSL_CACHE_DISABLED;
  619.     }

  620.     BIO_free(bio);

  621.     return pkey;
  622. }


  623. static int
  624. ngx_ssl_cache_pkey_password_callback(char *buf, int size, int rwflag,
  625.     void *userdata)
  626. {
  627.     ngx_ssl_cache_pwd_t  *data = userdata;

  628.     ngx_str_t  *pwd;

  629.     if (rwflag) {
  630.         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
  631.                       "ngx_ssl_cache_pkey_password_callback() is called "
  632.                       "for encryption");
  633.         return 0;
  634.     }

  635.     data->encrypted = 1;

  636.     pwd = data->pwd;

  637.     if (pwd == NULL) {
  638.         return 0;
  639.     }

  640.     if (pwd->len > (size_t) size) {
  641.         ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
  642.                       "password is truncated to %d bytes", size);
  643.     } else {
  644.         size = pwd->len;
  645.     }

  646.     ngx_memcpy(buf, pwd->data, size);

  647.     return size;
  648. }


  649. static void
  650. ngx_ssl_cache_pkey_free(void *data)
  651. {
  652.     EVP_PKEY_free(data);
  653. }


  654. static void *
  655. ngx_ssl_cache_pkey_ref(char **err, void *data)
  656. {
  657.     EVP_PKEY  *pkey = data;

  658. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  659.     EVP_PKEY_up_ref(pkey);
  660. #else
  661.     CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
  662. #endif

  663.     return data;
  664. }


  665. static void *
  666. ngx_ssl_cache_crl_create(ngx_ssl_cache_key_t *id, char **err, void *data)
  667. {
  668.     BIO                 *bio;
  669.     u_long               n;
  670.     X509_CRL            *x509;
  671.     STACK_OF(X509_CRL)  *chain;

  672.     chain = sk_X509_CRL_new_null();
  673.     if (chain == NULL) {
  674.         *err = "sk_X509_CRL_new_null() failed";
  675.         return NULL;
  676.     }

  677.     bio = ngx_ssl_cache_create_bio(id, err);
  678.     if (bio == NULL) {
  679.         sk_X509_CRL_pop_free(chain, X509_CRL_free);
  680.         return NULL;
  681.     }

  682.     for ( ;; ) {

  683.         x509 = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
  684.         if (x509 == NULL) {
  685.             n = ERR_peek_last_error();

  686.             if (ERR_GET_LIB(n) == ERR_LIB_PEM
  687.                 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE
  688.                 && sk_X509_CRL_num(chain) > 0)
  689.             {
  690.                 /* end of file */
  691.                 ERR_clear_error();
  692.                 break;
  693.             }

  694.             /* some real error */

  695.             *err = "PEM_read_bio_X509_CRL() failed";
  696.             BIO_free(bio);
  697.             sk_X509_CRL_pop_free(chain, X509_CRL_free);
  698.             return NULL;
  699.         }

  700.         if (sk_X509_CRL_push(chain, x509) == 0) {
  701.             *err = "sk_X509_CRL_push() failed";
  702.             BIO_free(bio);
  703.             X509_CRL_free(x509);
  704.             sk_X509_CRL_pop_free(chain, X509_CRL_free);
  705.             return NULL;
  706.         }
  707.     }

  708.     BIO_free(bio);

  709.     return chain;
  710. }


  711. static void
  712. ngx_ssl_cache_crl_free(void *data)
  713. {
  714.     sk_X509_CRL_pop_free(data, X509_CRL_free);
  715. }


  716. static void *
  717. ngx_ssl_cache_crl_ref(char **err, void *data)
  718. {
  719.     int                  n, i;
  720.     X509_CRL            *x509;
  721.     STACK_OF(X509_CRL)  *chain;

  722.     chain = sk_X509_CRL_dup(data);
  723.     if (chain == NULL) {
  724.         *err = "sk_X509_CRL_dup() failed";
  725.         return NULL;
  726.     }

  727.     n = sk_X509_CRL_num(chain);

  728.     for (i = 0; i < n; i++) {
  729.         x509 = sk_X509_CRL_value(chain, i);

  730. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  731.         X509_CRL_up_ref(x509);
  732. #else
  733.         CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509_CRL);
  734. #endif
  735.     }

  736.     return chain;
  737. }


  738. static void *
  739. ngx_ssl_cache_ca_create(ngx_ssl_cache_key_t *id, char **err, void *data)
  740. {
  741.     BIO             *bio;
  742.     X509            *x509;
  743.     u_long           n;
  744.     STACK_OF(X509)  *chain;

  745.     chain = sk_X509_new_null();
  746.     if (chain == NULL) {
  747.         *err = "sk_X509_new_null() failed";
  748.         return NULL;
  749.     }

  750.     bio = ngx_ssl_cache_create_bio(id, err);
  751.     if (bio == NULL) {
  752.         sk_X509_pop_free(chain, X509_free);
  753.         return NULL;
  754.     }

  755.     for ( ;; ) {

  756.         x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
  757.         if (x509 == NULL) {
  758.             n = ERR_peek_last_error();

  759.             if (ERR_GET_LIB(n) == ERR_LIB_PEM
  760.                 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE
  761.                 && sk_X509_num(chain) > 0)
  762.             {
  763.                 /* end of file */
  764.                 ERR_clear_error();
  765.                 break;
  766.             }

  767.             /* some real error */

  768.             *err = "PEM_read_bio_X509_AUX() failed";
  769.             BIO_free(bio);
  770.             sk_X509_pop_free(chain, X509_free);
  771.             return NULL;
  772.         }

  773.         if (sk_X509_push(chain, x509) == 0) {
  774.             *err = "sk_X509_push() failed";
  775.             BIO_free(bio);
  776.             X509_free(x509);
  777.             sk_X509_pop_free(chain, X509_free);
  778.             return NULL;
  779.         }
  780.     }

  781.     BIO_free(bio);

  782.     return chain;
  783. }


  784. static BIO *
  785. ngx_ssl_cache_create_bio(ngx_ssl_cache_key_t *id, char **err)
  786. {
  787.     BIO  *bio;

  788.     if (id->type == NGX_SSL_CACHE_DATA) {

  789.         bio = BIO_new_mem_buf(id->data + sizeof("data:") - 1,
  790.                               id->len - (sizeof("data:") - 1));
  791.         if (bio == NULL) {
  792.             *err = "BIO_new_mem_buf() failed";
  793.         }

  794.         return bio;
  795.     }

  796.     bio = BIO_new_file((char *) id->data, "r");
  797.     if (bio == NULL) {
  798.         *err = "BIO_new_file() failed";
  799.     }

  800.     return bio;
  801. }


  802. static void *
  803. ngx_openssl_cache_create_conf(ngx_cycle_t *cycle)
  804. {
  805.     ngx_ssl_cache_t  *cache;

  806.     cache = ngx_ssl_cache_init(cycle->pool, 0, 0, 0);
  807.     if (cache == NULL) {
  808.         return NULL;
  809.     }

  810.     cache->inheritable = NGX_CONF_UNSET;

  811.     return cache;
  812. }


  813. static char *
  814. ngx_openssl_cache_init_conf(ngx_cycle_t *cycle, void *conf)
  815. {
  816.     ngx_ssl_cache_t *cache = conf;

  817.     ngx_conf_init_value(cache->inheritable, 1);

  818.     return NGX_CONF_OK;
  819. }


  820. ngx_ssl_cache_t *
  821. ngx_ssl_cache_init(ngx_pool_t *pool, ngx_uint_t max, time_t valid,
  822.     time_t inactive)
  823. {
  824.     ngx_ssl_cache_t     *cache;
  825.     ngx_pool_cleanup_t  *cln;

  826.     cache = ngx_pcalloc(pool, sizeof(ngx_ssl_cache_t));
  827.     if (cache == NULL) {
  828.         return NULL;
  829.     }

  830.     ngx_rbtree_init(&cache->rbtree, &cache->sentinel,
  831.                     ngx_ssl_cache_node_insert);

  832.     ngx_queue_init(&cache->expire_queue);

  833.     cache->max = max;
  834.     cache->valid = valid;
  835.     cache->inactive = inactive;

  836.     cln = ngx_pool_cleanup_add(pool, 0);
  837.     if (cln == NULL) {
  838.         return NULL;
  839.     }

  840.     cln->handler = ngx_ssl_cache_cleanup;
  841.     cln->data = cache;

  842.     return cache;
  843. }


  844. static void
  845. ngx_ssl_cache_cleanup(void *data)
  846. {
  847.     ngx_ssl_cache_t  *cache = data;

  848.     ngx_rbtree_t          *tree;
  849.     ngx_rbtree_node_t     *node;
  850.     ngx_ssl_cache_node_t  *cn;

  851.     tree = &cache->rbtree;

  852.     if (tree->root == tree->sentinel) {
  853.         return;
  854.     }

  855.     node = ngx_rbtree_min(tree->root, tree->sentinel);

  856.     while (node != NULL) {
  857.         cn = ngx_rbtree_data(node, ngx_ssl_cache_node_t, node);
  858.         node = ngx_rbtree_next(tree, node);

  859.         ngx_ssl_cache_node_free(tree, cn);

  860.         if (cache->max) {
  861.             cache->current--;
  862.         }
  863.     }

  864.     if (cache->current) {
  865.         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
  866.                       "%ui items still left in ssl cache",
  867.                       cache->current);
  868.     }

  869.     if (!ngx_queue_empty(&cache->expire_queue)) {
  870.         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
  871.                       "queue still is not empty in ssl cache");

  872.     }
  873. }


  874. static void
  875. ngx_ssl_cache_node_free(ngx_rbtree_t *rbtree, ngx_ssl_cache_node_t *cn)
  876. {
  877.     cn->type->free(cn->value);

  878.     ngx_rbtree_delete(rbtree, &cn->node);

  879.     if (!ngx_queue_empty(&cn->queue)) {
  880.         ngx_queue_remove(&cn->queue);

  881.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
  882.                        "delete cached ssl object: %s", cn->id.data);

  883.         ngx_free(cn);
  884.     }
  885. }


  886. static void
  887. ngx_ssl_cache_node_insert(ngx_rbtree_node_t *temp,
  888.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
  889. {
  890.     ngx_rbtree_node_t     **p;
  891.     ngx_ssl_cache_node_t   *n, *t;

  892.     for ( ;; ) {

  893.         n = ngx_rbtree_data(node, ngx_ssl_cache_node_t, node);
  894.         t = ngx_rbtree_data(temp, ngx_ssl_cache_node_t, node);

  895.         if (node->key != temp->key) {

  896.             p = (node->key < temp->key) ? &temp->left : &temp->right;

  897.         } else if (n->type != t->type) {

  898.             p = (n->type < t->type) ? &temp->left : &temp->right;

  899.         } else {

  900.             p = (ngx_memn2cmp(n->id.data, t->id.data, n->id.len, t->id.len)
  901.                  < 0) ? &temp->left : &temp->right;
  902.         }

  903.         if (*p == sentinel) {
  904.             break;
  905.         }

  906.         temp = *p;
  907.     }

  908.     *p = node;
  909.     node->parent = temp;
  910.     node->left = sentinel;
  911.     node->right = sentinel;
  912.     ngx_rbt_red(node);
  913. }


  914. static ngx_int_t
  915. ngx_openssl_cache_init_worker(ngx_cycle_t *cycle)
  916. {
  917. #ifdef ERR_R_OSSL_STORE_LIB

  918.     if (ngx_process != NGX_PROCESS_WORKER) {
  919.         return NGX_OK;
  920.     }

  921.     UI_set_default_method(UI_null());

  922. #endif

  923.     return NGX_OK;
  924. }