Mercurial > hg > nginx
changeset 7463:180df83473a4
SSL: passwords support for dynamic certificate loading.
Passwords have to be copied to the configuration pool to be used
at runtime. Also, to prevent blocking on stdin (with "daemon off;")
an empty password list is provided.
To make things simpler, password handling was modified to allow
an empty array (with 0 elements and elts set to NULL) as an equivalent
of an array with 1 empty password.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Feb 2019 16:42:23 +0300 |
parents | be2af41d3620 |
children | e970de27966a |
files | src/event/ngx_event_openssl.c src/event/ngx_event_openssl.h src/http/modules/ngx_http_ssl_module.c src/http/ngx_http_request.c |
diffstat | 4 files changed, 77 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c Mon Feb 25 16:42:05 2019 +0300 +++ b/src/event/ngx_event_openssl.c Mon Feb 25 16:42:23 2019 +0300 @@ -771,7 +771,7 @@ break; } - if (--tries) { + if (tries-- > 1) { ERR_clear_error(); (void) BIO_reset(bio); pwd++; @@ -800,6 +800,10 @@ return 0; } + if (pwd == NULL) { + return 0; + } + if (pwd->len > (size_t) size) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "password is truncated to %d bytes", size); @@ -1215,6 +1219,69 @@ } +ngx_array_t * +ngx_ssl_preserve_passwords(ngx_conf_t *cf, ngx_array_t *passwords) +{ + ngx_str_t *opwd, *pwd; + ngx_uint_t i; + ngx_array_t *pwds; + ngx_pool_cleanup_t *cln; + static ngx_array_t empty_passwords; + + if (passwords == NULL) { + + /* + * If there are no passwords, an empty array is used + * to make sure OpenSSL's default password callback + * won't block on reading from stdin. + */ + + return &empty_passwords; + } + + /* + * Passwords are normally allocated from the temporary pool + * and cleared after parsing configuration. To be used at + * runtime they have to be copied to the configuration pool. + */ + + pwds = ngx_array_create(cf->pool, passwords->nelts, sizeof(ngx_str_t)); + if (pwds == NULL) { + return NULL; + } + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NULL; + } + + cln->handler = ngx_ssl_passwords_cleanup; + cln->data = pwds; + + opwd = passwords->elts; + + for (i = 0; i < passwords->nelts; i++) { + + pwd = ngx_array_push(pwds); + if (pwd == NULL) { + return NULL; + } + + pwd->len = opwd[i].len; + pwd->data = ngx_pnalloc(cf->pool, pwd->len); + + if (pwd->data == NULL) { + pwds->nelts--; + return NULL; + } + + ngx_memcpy(pwd->data, opwd[i].data, opwd[i].len); + } + + return pwds; +} + + static void ngx_ssl_passwords_cleanup(void *data) {
--- a/src/event/ngx_event_openssl.h Mon Feb 25 16:42:05 2019 +0300 +++ b/src/event/ngx_event_openssl.h Mon Feb 25 16:42:23 2019 +0300 @@ -183,6 +183,8 @@ RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, int key_length); 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); ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl,
--- a/src/http/modules/ngx_http_ssl_module.c Mon Feb 25 16:42:05 2019 +0300 +++ b/src/http/modules/ngx_http_ssl_module.c Mon Feb 25 16:42:23 2019 +0300 @@ -935,6 +935,11 @@ } } + conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords); + if (conf->passwords == NULL) { + return NGX_ERROR; + } + return NGX_OK; }
--- a/src/http/ngx_http_request.c Mon Feb 25 16:42:05 2019 +0300 +++ b/src/http/ngx_http_request.c Mon Feb 25 16:42:23 2019 +0300 @@ -995,7 +995,8 @@ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl key: \"%s\"", key.data); - if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, NULL) + if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, + sscf->passwords) != NGX_OK) { goto failed;