diff options
author | Maxim Dounin <mdounin@mdounin.ru> | 2019-02-25 16:42:23 +0300 |
---|---|---|
committer | Maxim Dounin <mdounin@mdounin.ru> | 2019-02-25 16:42:23 +0300 |
commit | 8772a0e0892e632c37f3b92b1d287ed9b473cb13 (patch) | |
tree | 7f5c5a9db242028cee1f99abafe261c6bcc79a31 | |
parent | 6e5a731edb6c1b8581c4b6fd2a2bf4ec0e768c24 (diff) |
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.
-rw-r--r-- | src/event/ngx_event_openssl.c | 69 | ||||
-rw-r--r-- | src/event/ngx_event_openssl.h | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_ssl_module.c | 5 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 3 |
4 files changed, 77 insertions, 2 deletions
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 1d1fa09d8..c6eb65c64 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -771,7 +771,7 @@ ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err, break; } - if (--tries) { + if (tries-- > 1) { ERR_clear_error(); (void) BIO_reset(bio); pwd++; @@ -800,6 +800,10 @@ ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata) 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 @@ cleanup: } +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) { diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 3c91c848b..21ed19e2d 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -183,6 +183,8 @@ ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, 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, diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 759762c5a..3134f0ec8 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -935,6 +935,11 @@ found: } } + conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords); + if (conf->passwords == NULL) { + return NGX_ERROR; + } + return NGX_OK; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 4e14d3b10..81d546a86 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -995,7 +995,8 @@ ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg) 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; |