summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxim Dounin <mdounin@mdounin.ru>2019-02-25 16:42:23 +0300
committerMaxim Dounin <mdounin@mdounin.ru>2019-02-25 16:42:23 +0300
commit8772a0e0892e632c37f3b92b1d287ed9b473cb13 (patch)
tree7f5c5a9db242028cee1f99abafe261c6bcc79a31
parent6e5a731edb6c1b8581c4b6fd2a2bf4ec0e768c24 (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.c69
-rw-r--r--src/event/ngx_event_openssl.h2
-rw-r--r--src/http/modules/ngx_http_ssl_module.c5
-rw-r--r--src/http/ngx_http_request.c3
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;