nginx/0008-add-ssl-pass-phrase-di...

783 lines
28 KiB
Diff

From c0f75dac24544bdae1ccfccf3d6a05c1b9243d8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?= <luhliari@redhat.com>
Date: Thu, 23 May 2024 14:09:05 +0200
Subject: [PATCH] Add ssl-pass-phrase-dialog
---
contrib/vim/syntax/nginx.vim | 1 +
src/event/ngx_event_openssl.c | 133 ++++++++++++++++++++---
src/event/ngx_event_openssl.h | 15 ++-
src/http/modules/ngx_http_grpc_module.c | 2 +-
src/http/modules/ngx_http_proxy_module.c | 2 +-
src/http/modules/ngx_http_ssl_module.c | 76 ++++++++++++-
src/http/modules/ngx_http_ssl_module.h | 2 +
src/http/modules/ngx_http_uwsgi_module.c | 2 +-
src/mail/ngx_mail_ssl_module.c | 68 +++++++++++-
src/mail/ngx_mail_ssl_module.h | 2 +
src/stream/ngx_stream_proxy_module.c | 2 +-
src/stream/ngx_stream_ssl_module.c | 62 ++++++++++-
src/stream/ngx_stream_ssl_module.h | 2 +
13 files changed, 344 insertions(+), 25 deletions(-)
diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim
index 6828cd3..9df0a53 100644
--- a/contrib/vim/syntax/nginx.vim
+++ b/contrib/vim/syntax/nginx.vim
@@ -624,6 +624,7 @@ syn keyword ngxDirective contained ssl_ocsp
syn keyword ngxDirective contained ssl_ocsp_cache
syn keyword ngxDirective contained ssl_ocsp_responder
syn keyword ngxDirective contained ssl_password_file
+syn keyword ngxDirective contained ssl_pass_phrase_dialog
syn keyword ngxDirective contained ssl_prefer_server_ciphers
syn keyword ngxDirective contained ssl_preread
syn keyword ngxDirective contained ssl_protocols
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index d6fe5bc..fb05ab9 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -9,9 +9,8 @@
#include <ngx_core.h>
#include <ngx_event.h>
-
#define NGX_SSL_PASSWORD_BUFFER_SIZE 4096
-
+#define NGX_PASS_PHRASE_ARG_MAX_LEN 255
typedef struct {
ngx_uint_t engine; /* unsigned engine:1; */
@@ -20,8 +19,8 @@ typedef struct {
static X509 *ngx_ssl_load_certificate(ngx_pool_t *pool, char **err,
ngx_str_t *cert, STACK_OF(X509) **chain);
-static EVP_PKEY *ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
- ngx_str_t *key, ngx_array_t *passwords);
+static EVP_PKEY *ngx_ssl_load_certificate_key(ngx_pool_t *pool,
+ char **err, ngx_str_t *key, ngx_array_t *passwords, ngx_ssl_ppdialog_conf_t *dlg);
static int ngx_ssl_password_callback(char *buf, int size, int rwflag,
void *userdata);
static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
@@ -87,6 +86,12 @@ static time_t ngx_ssl_parse_time(
#endif
ASN1_TIME *asn1time, ngx_log_t *log);
+static int ngx_ssl_read_pstream(const char *cmd, char *buf,
+ ngx_int_t bufsize);
+
+static int ngx_ssl_pass_phrase_callback(char *buf, int bufsize,
+ int rwflag, void *u);
+
static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void ngx_openssl_exit(ngx_cycle_t *cycle);
@@ -404,7 +409,7 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
ngx_int_t
ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs,
- ngx_array_t *keys, ngx_array_t *passwords)
+ ngx_array_t *keys, ngx_array_t *passwords, ngx_ssl_ppdialog_conf_t *dlg)
{
ngx_str_t *cert, *key;
ngx_uint_t i;
@@ -414,7 +419,7 @@ ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs,
for (i = 0; i < certs->nelts; i++) {
- if (ngx_ssl_certificate(cf, ssl, &cert[i], &key[i], passwords)
+ if (ngx_ssl_certificate(cf, ssl, &cert[i], &key[i], passwords, dlg)
!= NGX_OK)
{
return NGX_ERROR;
@@ -427,12 +432,13 @@ ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs,
ngx_int_t
ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
- ngx_str_t *key, ngx_array_t *passwords)
+ ngx_str_t *key, ngx_array_t *passwords, ngx_ssl_ppdialog_conf_t *dlg)
{
char *err;
X509 *x509;
EVP_PKEY *pkey;
STACK_OF(X509) *chain;
+ EVP_PKEY *pubkey;
x509 = ngx_ssl_load_certificate(cf->pool, &err, cert, &chain);
if (x509 == NULL) {
@@ -522,8 +528,23 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
}
#endif
- pkey = ngx_ssl_load_certificate_key(cf->pool, &err, key, passwords);
- if (pkey == NULL) {
+ pubkey = X509_get_pubkey(x509);
+ if (!pubkey){
+ ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+ "X509_get_pubkey() failed");
+ return NGX_ERROR;
+ }
+
+ if (dlg) {
+ dlg->cryptosystem = EVP_PKEY_get_base_id(pubkey);
+ }
+
+ EVP_PKEY_free(pubkey);
+
+ pkey = ngx_ssl_load_certificate_key(cf->pool, &err, key, passwords, dlg);
+ if (ngx_test_config){
+ return NGX_OK;
+ } else if (pkey == NULL) {
if (err != NULL) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"cannot load certificate key \"%s\": %s",
@@ -593,7 +614,7 @@ ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
#endif
- pkey = ngx_ssl_load_certificate_key(pool, &err, key, passwords);
+ pkey = ngx_ssl_load_certificate_key(pool, &err, key, passwords, NULL);
if (pkey == NULL) {
if (err != NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
@@ -771,10 +792,81 @@ ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, ngx_str_t *cert,
return x509;
}
+static int
+ngx_ssl_read_pstream(const char *cmd, char *buf, ngx_int_t bufsize)
+{
+ FILE *fp;
+ ngx_int_t i;
+ char c;
+
+ fp = popen(cmd, "r");
+ if (fp == NULL) {
+ return -1;
+ }
+
+ for (i = 0; (c = fgetc(fp)) != EOF &&
+ (i < bufsize - 1); i++) {
+
+ if (c == '\n' || c == '\r'){
+ break;
+ }
+
+ buf[i] = c;
+ }
+ buf[i] = '\0';
+
+ pclose(fp);
+
+ return 0;
+}
+
+static int
+ngx_ssl_pass_phrase_callback(char *buf, int bufsize, int rwflag, void *u)
+{
+ u_char cmd[NGX_PASS_PHRASE_ARG_MAX_LEN + 1] = {0};
+ u_char *cmd_end;
+ ngx_ssl_ppdialog_conf_t *dlg = (ngx_ssl_ppdialog_conf_t *)u;
+ ngx_str_t *pass_phrase_dialog = dlg->data;
+ char cryptosystem[4] = {0};
+ int ret;
+
+ /* remove exec: str from pass_phrase_dialog */
+ pass_phrase_dialog->data = pass_phrase_dialog->data + 5;
+ pass_phrase_dialog->len = pass_phrase_dialog->len - 5;
+
+ switch (dlg->cryptosystem){
+ case EVP_PKEY_RSA:
+ strncpy(cryptosystem, "RSA", 4);
+ break;
+ case EVP_PKEY_DSA:
+ strncpy(cryptosystem, "DSA", 4);
+ break;
+ case EVP_PKEY_EC:
+ strncpy(cryptosystem, "EC", 3);
+ break;
+ case EVP_PKEY_DH:
+ strncpy(cryptosystem, "DH", 3);
+ break;
+ default:
+ strncpy(cryptosystem, "UNK", 4);
+ break;
+ }
+
+ cmd_end = ngx_snprintf(cmd, NGX_PASS_PHRASE_ARG_MAX_LEN, "%V %V %s",
+ pass_phrase_dialog, dlg->server, cryptosystem);
+ *cmd_end = '\0';
+
+ ngx_log_stderr(0, "Executing external script: %s\n", cmd);
+
+ if ((ret = ngx_ssl_read_pstream((char *)cmd, buf, bufsize)) != 0){
+ return -1;
+ }
+
+ return strlen(buf);
+}
static EVP_PKEY *
-ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
- ngx_str_t *key, ngx_array_t *passwords)
+ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err, ngx_str_t *key, ngx_array_t *passwords, ngx_ssl_ppdialog_conf_t *dlg)
{
BIO *bio;
EVP_PKEY *pkey;
@@ -870,11 +962,26 @@ ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,
tries = 1;
pwd = NULL;
cb = NULL;
+
+ /** directive format: ssl_pass_phrase_dialog buildin|exec:filepath */
+ if (dlg && ngx_strncasecmp(dlg->data->data, (u_char *)"exec:", 5) == 0){
+ pwd = (void *)dlg;
+ cb = ngx_ssl_pass_phrase_callback;
+ } else {
+ pwd = NULL;
+ cb = NULL;
+ }
}
- for ( ;; ) {
+ /* skip decrypting private keys in config test phase to avoid
+ asking for pass phase twice */
+ if (ngx_test_config){
+ return NULL;
+ }
+ for ( ;; ) {
pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd);
+
if (pkey != NULL) {
break;
}
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index eb3288b..b275a38 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -74,9 +74,19 @@
#define ERR_peek_error_data(d, f) ERR_peek_error_line_data(NULL, NULL, d, f)
#endif
+#define NGX_SSL_PASS_PHRASE_ARG_MAX_LEN 255
+#define NGX_SSL_PASS_PHRASE_DEFAULT_VAL "builtin"
+#define NGX_SSL_SERVER_NULL "undefined"
typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t;
+typedef struct ngx_ssl_ppdialog_conf_s ngx_ssl_ppdialog_conf_t;
+
+struct ngx_ssl_ppdialog_conf_s {
+ ngx_str_t *data;
+ ngx_str_t *server;
+ ngx_int_t cryptosystem;
+};
struct ngx_ssl_s {
SSL_CTX *ctx;
@@ -84,7 +94,6 @@ struct ngx_ssl_s {
size_t buffer_size;
};
-
struct ngx_ssl_connection_s {
ngx_ssl_conn_t *connection;
SSL_CTX *session_ctx;
@@ -184,9 +193,9 @@ ngx_int_t ngx_ssl_init(ngx_log_t *log);
ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data);
ngx_int_t ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl,
- ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords);
+ ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords, ngx_ssl_ppdialog_conf_t *dlg);
ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
- ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords);
+ ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords, ngx_ssl_ppdialog_conf_t *dlg);
ngx_int_t ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords);
diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c
index 864fc4f..c1b5fb4 100644
--- a/src/http/modules/ngx_http_grpc_module.c
+++ b/src/http/modules/ngx_http_grpc_module.c
@@ -4925,7 +4925,7 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
if (ngx_ssl_certificate(cf, glcf->upstream.ssl,
&glcf->upstream.ssl_certificate->value,
&glcf->upstream.ssl_certificate_key->value,
- glcf->upstream.ssl_passwords)
+ glcf->upstream.ssl_passwords, NULL)
!= NGX_OK)
{
return NGX_ERROR;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 7c4061c..e971396 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -4974,7 +4974,7 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
if (ngx_ssl_certificate(cf, plcf->upstream.ssl,
&plcf->upstream.ssl_certificate->value,
&plcf->upstream.ssl_certificate_key->value,
- plcf->upstream.ssl_passwords)
+ plcf->upstream.ssl_passwords, NULL)
!= NGX_OK)
{
return NGX_ERROR;
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index e765a50..6af69d1 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -17,8 +17,9 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
#define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5"
#define NGX_DEFAULT_ECDH_CURVE "auto"
-#define NGX_HTTP_ALPN_PROTOS "\x08http/1.1\x08http/1.0\x08http/0.9"
+static ngx_str_t ngx_ssl_server_null = ngx_string(NGX_SSL_SERVER_NULL);
+#define NGX_HTTP_ALPN_PROTOS "\x08http/1.1\x08http/1.0\x08http/0.9"
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
static int ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
@@ -53,6 +54,9 @@ static char *ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post,
static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
+static char *ngx_conf_set_pass_phrase_dialog(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+
static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = {
{ ngx_string("SSLv2"), NGX_SSL_SSLv2 },
@@ -296,6 +300,13 @@ static ngx_command_t ngx_http_ssl_commands[] = {
offsetof(ngx_http_ssl_srv_conf_t, reject_handshake),
NULL },
+ { ngx_string("ssl_pass_phrase_dialog"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_pass_phrase_dialog,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ offsetof(ngx_http_ssl_srv_conf_t, pass_phrase_dialog),
+ NULL },
+
ngx_null_command
};
@@ -555,7 +566,7 @@ ngx_http_ssl_add_variables(ngx_conf_t *cf)
static void *
ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
{
- ngx_http_ssl_srv_conf_t *sscf;
+ ngx_http_ssl_srv_conf_t *sscf;
sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
if (sscf == NULL) {
@@ -577,6 +588,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
* sscf->ocsp_responder = { 0, NULL };
* sscf->stapling_file = { 0, NULL };
* sscf->stapling_responder = { 0, NULL };
+ * sscf->pass_phrase_dialog = NULL;
+ *
*/
sscf->enable = NGX_CONF_UNSET;
@@ -608,6 +621,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_ssl_srv_conf_t *prev = parent;
ngx_http_ssl_srv_conf_t *conf = child;
+ ngx_http_core_srv_conf_t *cscf;
+ ngx_ssl_ppdialog_conf_t dlg;
ngx_pool_cleanup_t *cln;
@@ -672,6 +687,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->stapling_responder,
prev->stapling_responder, "");
+ ngx_conf_merge_str_value(conf->pass_phrase_dialog,
+ prev->pass_phrase_dialog, NGX_SSL_PASS_PHRASE_DEFAULT_VAL);
+
conf->ssl.log = cf->log;
if (conf->enable) {
@@ -734,6 +752,30 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = &conf->ssl;
+ /** directive format: ssl_pass_phrase_dialog buildin|exec:filepath */
+ if (ngx_strncasecmp(conf->pass_phrase_dialog.data, (u_char *)"exec:", 5) == 0){
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog config directive SET: %s ", conf->pass_phrase_dialog.data);
+ } else if (ngx_strncasecmp(conf->pass_phrase_dialog.data, (u_char *)NGX_SSL_PASS_PHRASE_DEFAULT_VAL,
+ sizeof(NGX_SSL_PASS_PHRASE_DEFAULT_VAL)) != 0){
+
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog config directive accepts only the following "
+ "values: %s | exec:filepath", NGX_SSL_PASS_PHRASE_DEFAULT_VAL);
+
+ return NGX_CONF_ERROR;
+ }
+
+ cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
+
+ dlg.data = &conf->pass_phrase_dialog;
+ if (cscf->server_name.len != 0) {
+ dlg.server = &cscf->server_name;
+ } else {
+ dlg.server = &ngx_ssl_server_null;
+ }
+
+
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
@@ -784,7 +826,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
/* configure certificates */
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
- conf->certificate_keys, conf->passwords)
+ conf->certificate_keys, conf->passwords, &dlg)
!= NGX_OK)
{
return NGX_CONF_ERROR;
@@ -1333,3 +1375,31 @@ ngx_http_ssl_init(ngx_conf_t *cf)
return NGX_OK;
}
+
+static char *
+ngx_conf_set_pass_phrase_dialog(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_ssl_srv_conf_t *sscf = conf;
+ ngx_str_t *value;
+
+ if (sscf->pass_phrase_dialog.data){
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ sscf->pass_phrase_dialog = value[1];
+
+ if (sscf->pass_phrase_dialog.len == 0) {
+ return NGX_CONF_OK;
+ } else if (sscf->pass_phrase_dialog.len > NGX_SSL_PASS_PHRASE_ARG_MAX_LEN) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog argument length exceeded maximum possible length: %d",
+ NGX_SSL_PASS_PHRASE_ARG_MAX_LEN);
+
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
index 7ab0f7e..2f83d75 100644
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -67,6 +67,8 @@ typedef struct {
u_char *file;
ngx_uint_t line;
+
+ ngx_str_t pass_phrase_dialog;
} ngx_http_ssl_srv_conf_t;
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index d46741a..d728874 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -2461,7 +2461,7 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
if (ngx_ssl_certificate(cf, uwcf->upstream.ssl,
&uwcf->upstream.ssl_certificate->value,
&uwcf->upstream.ssl_certificate_key->value,
- uwcf->upstream.ssl_passwords)
+ uwcf->upstream.ssl_passwords, NULL)
!= NGX_OK)
{
return NGX_ERROR;
diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c
index 63af775..b3cd38e 100644
--- a/src/mail/ngx_mail_ssl_module.c
+++ b/src/mail/ngx_mail_ssl_module.c
@@ -13,6 +13,7 @@
#define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5"
#define NGX_DEFAULT_ECDH_CURVE "auto"
+static ngx_str_t ngx_ssl_server_null = ngx_string(NGX_SSL_SERVER_NULL);
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
static int ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
@@ -35,6 +36,8 @@ static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
+static char *ngx_conf_set_pass_phrase_dialog(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static ngx_conf_enum_t ngx_mail_starttls_state[] = {
{ ngx_string("off"), NGX_MAIL_STARTTLS_OFF },
@@ -216,6 +219,13 @@ static ngx_command_t ngx_mail_ssl_commands[] = {
offsetof(ngx_mail_ssl_conf_t, conf_commands),
&ngx_mail_ssl_conf_command_post },
+ { ngx_string("ssl_pass_phrase_dialog"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_pass_phrase_dialog,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_ssl_conf_t, pass_phrase_dialog),
+ NULL },
+
ngx_null_command
};
@@ -345,6 +355,8 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_mail_ssl_conf_t *prev = parent;
ngx_mail_ssl_conf_t *conf = child;
+ ngx_mail_core_srv_conf_t *cscf;
+ ngx_ssl_ppdialog_conf_t dlg;
char *mode;
ngx_pool_cleanup_t *cln;
@@ -386,6 +398,8 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
+ ngx_conf_merge_str_value(conf->pass_phrase_dialog,
+ prev->pass_phrase_dialog, NGX_SSL_PASS_PHRASE_DEFAULT_VAL);
conf->ssl.log = cf->log;
@@ -447,6 +461,29 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = &conf->ssl;
+ /** directive format: ssl_pass_phrase_dialog buildin|exec:filepath */
+ if (ngx_strncasecmp(conf->pass_phrase_dialog.data, (u_char *)"exec:", 5) == 0){
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog config directive SET: %s ", conf->pass_phrase_dialog.data);
+ } else if (ngx_strncasecmp(conf->pass_phrase_dialog.data, (u_char *)NGX_SSL_PASS_PHRASE_DEFAULT_VAL,
+ sizeof(NGX_SSL_PASS_PHRASE_DEFAULT_VAL)) != 0){
+
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog config directive accepts only the following "
+ "values: %s | exec:filepath", NGX_SSL_PASS_PHRASE_DEFAULT_VAL);
+
+ return NGX_CONF_ERROR;
+ }
+
+ cscf = ngx_mail_conf_get_module_srv_conf(cf, ngx_mail_core_module);
+
+ dlg.data = &conf->pass_phrase_dialog;
+ if (cscf->server_name.len != 0) {
+ dlg.server = &cscf->server_name;
+ } else {
+ dlg.server = &ngx_ssl_server_null;
+ }
+
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_mail_ssl_alpn_select, NULL);
#endif
@@ -459,7 +496,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
}
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
- conf->certificate_keys, conf->passwords)
+ conf->certificate_keys, conf->passwords, &dlg)
!= NGX_OK)
{
return NGX_CONF_ERROR;
@@ -743,3 +780,32 @@ ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
return NGX_CONF_OK;
#endif
}
+
+static char *
+ngx_conf_set_pass_phrase_dialog(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_mail_ssl_conf_t *sscf = conf;
+ ngx_str_t *value;
+
+ if (sscf->pass_phrase_dialog.data){
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ sscf->pass_phrase_dialog = value[1];
+
+ if (sscf->pass_phrase_dialog.len == 0) {
+ return NGX_CONF_OK;
+ } else if (sscf->pass_phrase_dialog.len > NGX_SSL_PASS_PHRASE_ARG_MAX_LEN) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog argument length exceeded maximum possible length: %d",
+ NGX_SSL_PASS_PHRASE_ARG_MAX_LEN);
+
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h
index a0a6113..3d87d50 100644
--- a/src/mail/ngx_mail_ssl_module.h
+++ b/src/mail/ngx_mail_ssl_module.h
@@ -57,6 +57,8 @@ typedef struct {
u_char *file;
ngx_uint_t line;
+
+ ngx_str_t pass_phrase_dialog;
} ngx_mail_ssl_conf_t;
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c
index 934e7d8..34d0195 100644
--- a/src/stream/ngx_stream_proxy_module.c
+++ b/src/stream/ngx_stream_proxy_module.c
@@ -2248,7 +2248,7 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf)
if (ngx_ssl_certificate(cf, pscf->ssl,
&pscf->ssl_certificate->value,
&pscf->ssl_certificate_key->value,
- pscf->ssl_passwords)
+ pscf->ssl_passwords, NULL)
!= NGX_OK)
{
return NGX_ERROR;
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c
index f922ac4..66b4b67 100644
--- a/src/stream/ngx_stream_ssl_module.c
+++ b/src/stream/ngx_stream_ssl_module.c
@@ -17,6 +17,8 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
#define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5"
#define NGX_DEFAULT_ECDH_CURVE "auto"
+#define NGX_SSL_STREAM_NAME "NGX_STREAM_SSL_MODULE"
+static ngx_str_t ngx_ssl_stream_default_name = ngx_string(NGX_SSL_STREAM_NAME);
static ngx_int_t ngx_stream_ssl_handler(ngx_stream_session_t *s);
static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl,
@@ -57,6 +59,9 @@ static char *ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
+static char *ngx_conf_set_pass_phrase_dialog(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+
static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf);
@@ -226,6 +231,13 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
0,
NULL },
+ { ngx_string("ssl_pass_phrase_dialog"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_pass_phrase_dialog,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_ssl_conf_t, pass_phrase_dialog),
+ NULL },
+
ngx_null_command
};
@@ -690,6 +702,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_stream_ssl_conf_t *prev = parent;
ngx_stream_ssl_conf_t *conf = child;
+ ngx_ssl_ppdialog_conf_t dlg;
ngx_pool_cleanup_t *cln;
@@ -730,6 +743,8 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
+ ngx_conf_merge_str_value(conf->pass_phrase_dialog,
+ prev->pass_phrase_dialog, NGX_SSL_PASS_PHRASE_DEFAULT_VAL);
conf->ssl.log = cf->log;
@@ -777,6 +792,23 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = &conf->ssl;
+ /** directive format: ssl_pass_phrase_dialog buildin|exec:filepath */
+ if (ngx_strncasecmp(conf->pass_phrase_dialog.data, (u_char *)"exec:", 5) == 0){
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog config directive SET: %s ", conf->pass_phrase_dialog.data);
+ } else if (ngx_strncasecmp(conf->pass_phrase_dialog.data, (u_char *)NGX_SSL_PASS_PHRASE_DEFAULT_VAL,
+ sizeof(NGX_SSL_PASS_PHRASE_DEFAULT_VAL)) != 0){
+
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog config directive accepts only the following "
+ "values: %s | exec:filepath", NGX_SSL_PASS_PHRASE_DEFAULT_VAL);
+
+ return NGX_CONF_ERROR;
+ }
+
+ dlg.data = &conf->pass_phrase_dialog;
+ dlg.server = &ngx_ssl_stream_default_name;
+
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
ngx_stream_ssl_servername);
@@ -821,7 +853,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
/* configure certificates */
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
- conf->certificate_keys, conf->passwords)
+ conf->certificate_keys, conf->passwords, &dlg)
!= NGX_OK)
{
return NGX_CONF_ERROR;
@@ -1207,3 +1239,31 @@ ngx_stream_ssl_init(ngx_conf_t *cf)
return NGX_OK;
}
+
+static char *
+ngx_conf_set_pass_phrase_dialog(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_stream_ssl_conf_t *sscf = conf;
+ ngx_str_t *value;
+
+ if (sscf->pass_phrase_dialog.data){
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ sscf->pass_phrase_dialog = value[1];
+
+ if (sscf->pass_phrase_dialog.len == 0) {
+ return NGX_CONF_OK;
+ } else if (sscf->pass_phrase_dialog.len > NGX_SSL_PASS_PHRASE_ARG_MAX_LEN) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "ssl_pass_phrase_dialog argument length exceeded maximum possible length: %d",
+ NGX_SSL_PASS_PHRASE_ARG_MAX_LEN);
+
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h
index e7c825e..d80daa4 100644
--- a/src/stream/ngx_stream_ssl_module.h
+++ b/src/stream/ngx_stream_ssl_module.h
@@ -56,6 +56,8 @@ typedef struct {
u_char *file;
ngx_uint_t line;
+
+ ngx_str_t pass_phrase_dialog;
} ngx_stream_ssl_conf_t;
--
2.44.0