SSL: encrypted certificate keys are exempt from object cache.

SSL object cache, as previously introduced in 1.27.2, did not take
into account encrypted certificate keys that might be unexpectedly
fetched from the cache regardless of the matching passphrase.  To
avoid this, caching of encrypted certificate keys is now disabled
based on the passphrase callback invocation.

A notable exception is encrypted certificate keys configured without
ssl_password_file.  They are loaded once resulting in the passphrase
prompt on startup and reused in other contexts as applicable.
This commit is contained in:
Sergey Kandaurov 2024-12-18 20:09:58 +04:00 committed by pluknet
parent 8311e14ae6
commit 7677d5646a

View File

@ -13,6 +13,8 @@
#define NGX_SSL_CACHE_DATA 1
#define NGX_SSL_CACHE_ENGINE 2
#define NGX_SSL_CACHE_DISABLED (ngx_array_t *) (uintptr_t) -1
#define ngx_ssl_cache_get_conf(cycle) \
(ngx_ssl_cache_t *) ngx_get_conf(cycle->conf_ctx, ngx_openssl_cache_module)
@ -61,6 +63,12 @@ typedef struct {
} ngx_ssl_cache_t;
typedef struct {
ngx_str_t *pwd;
unsigned encrypted:1;
} ngx_ssl_cache_pwd_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,
@ -228,9 +236,10 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
}
if (value == NULL) {
value = type->create(&id, err, data);
if (value == NULL) {
return NULL;
value = type->create(&id, err, &data);
if (value == NULL || data == NGX_SSL_CACHE_DISABLED) {
return value;
}
}
@ -269,7 +278,7 @@ ngx_ssl_cache_connection_fetch(ngx_pool_t *pool, ngx_uint_t index, char **err,
return NULL;
}
return ngx_ssl_cache_types[index].create(&id, err, data);
return ngx_ssl_cache_types[index].create(&id, err, &data);
}
@ -472,13 +481,13 @@ ngx_ssl_cache_cert_ref(char **err, void *data)
static void *
ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data)
{
ngx_array_t *passwords = data;
ngx_array_t **passwords = data;
BIO *bio;
EVP_PKEY *pkey;
ngx_str_t *pwd;
ngx_uint_t tries;
pem_password_cb *cb;
BIO *bio;
EVP_PKEY *pkey;
ngx_uint_t tries;
pem_password_cb *cb;
ngx_ssl_cache_pwd_t cb_data, *pwd;
if (id->type == NGX_SSL_CACHE_ENGINE) {
@ -531,12 +540,16 @@ ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data)
return NULL;
}
if (passwords) {
tries = passwords->nelts;
pwd = passwords->elts;
cb_data.encrypted = 0;
if (*passwords) {
cb_data.pwd = (*passwords)->elts;
tries = (*passwords)->nelts;
pwd = &cb_data;
cb = ngx_ssl_cache_pkey_password_callback;
} else {
cb_data.pwd = NULL;
tries = 1;
pwd = NULL;
cb = NULL;
@ -552,7 +565,7 @@ ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data)
if (tries-- > 1) {
ERR_clear_error();
(void) BIO_reset(bio);
pwd++;
cb_data.pwd++;
continue;
}
@ -561,6 +574,10 @@ ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data)
return NULL;
}
if (cb_data.encrypted) {
*passwords = NGX_SSL_CACHE_DISABLED;
}
BIO_free(bio);
return pkey;
@ -571,7 +588,9 @@ static int
ngx_ssl_cache_pkey_password_callback(char *buf, int size, int rwflag,
void *userdata)
{
ngx_str_t *pwd = userdata;
ngx_ssl_cache_pwd_t *data = userdata;
ngx_str_t *pwd;
if (rwflag) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
@ -580,6 +599,10 @@ ngx_ssl_cache_pkey_password_callback(char *buf, int size, int rwflag,
return 0;
}
data->encrypted = 1;
pwd = data->pwd;
if (pwd == NULL) {
return 0;
}