Last active
January 2, 2016 03:59
-
-
Save fukusaka/8247865 to your computer and use it in GitHub Desktop.
rework patch ssl_pass_phrase_dialog for nginx 1.4.4 ref http://forum.nginx.org/read.php?2,214641,214641
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ref http://forum.nginx.org/read.php?2,214641,214641 | |
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c | |
index 62ce12c14355267b2031c8cad52abcb77d462b1e..f9e0ea4532557a5895f8c9a9ada42e8ab7884b94 100644 | |
--- a/src/event/ngx_event_openssl.c | |
+++ b/src/event/ngx_event_openssl.c | |
@@ -42,6 +42,9 @@ 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); | |
+static int ngx_http_ssl_pass_phase_callback(char *buf, int bufsize, | |
+ int verify, void *userdata); | |
+static int ngx_enhanced_system(char* cmd, char *argv[], char* buf, int len); | |
static ngx_command_t ngx_openssl_commands[] = { | |
@@ -234,7 +237,7 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) | |
ngx_int_t | |
ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, | |
- ngx_str_t *key) | |
+ ngx_str_t *key, ngx_str_t *pass_phrase_conf, ngx_str_t *server_id) | |
{ | |
BIO *bio; | |
X509 *x509; | |
@@ -323,6 +326,21 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, | |
return NGX_ERROR; | |
} | |
+ if (ngx_strncasecmp(pass_phrase_conf->data, (u_char *) "exec:", 5) == 0) { | |
+ ngx_http_ssl_pass_phase_t *ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_pass_phase_t)); | |
+ ctx->pass_phrase_conf = *pass_phrase_conf; | |
+ ctx->server_id = *server_id; | |
+ ctx->log = ssl->log; | |
+ | |
+ SSL_CTX_set_default_passwd_cb(ssl->ctx, ngx_http_ssl_pass_phase_callback); | |
+ SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, (void *)ctx); | |
+ | |
+ } else if (ngx_strncasecmp(pass_phrase_conf->data, (u_char *) "builtin", 7) != 0) { | |
+ ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, | |
+ "The arg of ssl_pass_phrase_dialog directive is incorrect: builtin | exec:path"); | |
+ return NGX_ERROR; | |
+ } | |
+ | |
if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data, | |
SSL_FILETYPE_PEM) | |
== 0) | |
@@ -335,6 +353,91 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, | |
return NGX_OK; | |
} | |
+static int | |
+ngx_http_ssl_pass_phase_callback(char *buf, int bufsize, int verify, void *userdata) | |
+{ | |
+ int ret; | |
+ char cmd[PASS_PHRASE_ARG_LEN + 1] = {0}; | |
+ char *argv[3] = { NULL }; | |
+ | |
+ ngx_http_ssl_pass_phase_t *ctx = userdata; | |
+ | |
+ argv[0] = cmd; | |
+ u_char *p = ngx_cpymem(cmd, ctx->pass_phrase_conf.data + 5, ctx->pass_phrase_conf.len - 5); | |
+ *p = '\0'; | |
+ | |
+ if (ctx->server_id.len > 0) { | |
+ argv[1] = (char *) ctx->server_id.data; | |
+ } | |
+ | |
+ ret = ngx_enhanced_system(cmd, argv, buf, bufsize); | |
+ if (ret != 0) { | |
+ return -1; | |
+ } | |
+ | |
+ /* To support echo command in Linux, Unix shell */ | |
+ if (buf[strlen(buf) - 1] == '\n') { | |
+ buf[strlen(buf) - 1] = '\0'; | |
+ } | |
+ | |
+ return strlen(buf); | |
+} | |
+ | |
+/** | |
+ * ngx_enhanced_system() | |
+ * | |
+ * @param[in] cmdstring : External command(executable or shell) | |
+ * @param[out] buf : The buffer to store the result of the external command. | |
+ * @param[in] len : The length of the buffer. | |
+ * | |
+ * @return 0: success -1: fail | |
+ */ | |
+static int | |
+ngx_enhanced_system(char* cmd, char *argv[], char* buf, int len) | |
+{ | |
+ int fd[2]; | |
+ pid_t pid; | |
+ int n, count; | |
+ | |
+ memset(buf, 0, len); | |
+ | |
+ if (pipe(fd) < 0) { | |
+ return -1; | |
+ } | |
+ | |
+ if ((pid = fork()) < 0) { | |
+ return -1; | |
+ } else if (pid > 0) { /* parent process */ | |
+ close(fd[1]); /* close write end */ | |
+ count = 0; | |
+ | |
+ while ((n = read(fd[0], buf + count, len)) > 0 && count > len) { | |
+ count += n; | |
+ } | |
+ | |
+ close(fd[0]); | |
+ | |
+ if (waitpid(pid, NULL, 0) != pid) { | |
+ return -1; | |
+ } | |
+ | |
+ } else { /* child process */ | |
+ close(fd[0]); /* close read end */ | |
+ | |
+ if (fd[1] != STDOUT_FILENO) { | |
+ if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) { | |
+ return -1; | |
+ } | |
+ close(fd[1]); | |
+ } | |
+ | |
+ if (execv(cmd, argv) == -1) { | |
+ return -1; | |
+ } | |
+ } | |
+ | |
+ return 0; | |
+} | |
ngx_int_t | |
ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, | |
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h | |
index bf81d2529c9a5dad253b325f29bb8ab921fc6a2a..40a0dbabb4d7ed9e361345183f6e754adc9ae3ee 100644 | |
--- a/src/event/ngx_event_openssl.h | |
+++ b/src/event/ngx_event_openssl.h | |
@@ -82,6 +82,11 @@ typedef struct { | |
} ngx_ssl_session_cache_t; | |
+typedef struct { | |
+ ngx_str_t pass_phrase_conf; | |
+ ngx_str_t server_id; | |
+ ngx_log_t *log; | |
+} ngx_http_ssl_pass_phase_t; | |
#define NGX_SSL_SSLv2 0x0002 | |
#define NGX_SSL_SSLv3 0x0004 | |
@@ -95,11 +100,12 @@ typedef struct { | |
#define NGX_SSL_BUFSIZE 16384 | |
+#define PASS_PHRASE_ARG_LEN 255 | |
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_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, | |
- ngx_str_t *cert, ngx_str_t *key); | |
+ ngx_str_t *cert, ngx_str_t *key, ngx_str_t *pass_phrase_conf, ngx_str_t *server_id); | |
ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, | |
ngx_str_t *cert, ngx_int_t depth); | |
ngx_int_t ngx_ssl_trusted_certificate(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 a6c803da0dcf64b23e269a010170bc4858c76dea..22f35473a1b32db68b6233e205bbcf98454858df 100644 | |
--- a/src/http/modules/ngx_http_ssl_module.c | |
+++ b/src/http/modules/ngx_http_ssl_module.c | |
@@ -38,6 +38,9 @@ static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, | |
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, | |
void *conf); | |
+static char *ngx_conf_set_pass_phrase_dialog(ngx_conf_t *cf, | |
+ ngx_command_t *cmd, void *conf); | |
+ | |
static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf); | |
@@ -195,6 +198,13 @@ static ngx_command_t ngx_http_ssl_commands[] = { | |
offsetof(ngx_http_ssl_srv_conf_t, stapling_verify), | |
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_conf), | |
+ NULL }, | |
+ | |
ngx_null_command | |
}; | |
@@ -476,6 +486,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) | |
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); | |
+ ngx_conf_merge_str_value(conf->pass_phrase_conf, prev->pass_phrase_conf, "builtin"); | |
+ | |
ngx_conf_merge_value(conf->stapling, prev->stapling, 0); | |
ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0); | |
ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, ""); | |
@@ -547,8 +559,31 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) | |
cln->handler = ngx_ssl_cleanup_ctx; | |
cln->data = &conf->ssl; | |
+ ngx_str_t server_id = {0, NULL}; | |
+ { | |
+ ngx_http_core_srv_conf_t *cscf | |
+ = (ngx_http_core_srv_conf_t *) ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); | |
+ | |
+ ngx_http_core_main_conf_t *cmcf | |
+ = (ngx_http_core_main_conf_t *) ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
+ | |
+ ngx_http_conf_port_t *ports | |
+ = cmcf->ports->elts; | |
+ | |
+ if (cmcf->ports->nelts >= 1) { | |
+ server_id.data = ngx_pcalloc(cf->pool, cscf->server_name.len + 1 + 5 + 1); | |
+ ngx_snprintf(server_id.data, cscf->server_name.len + 1 + 5 + 1, | |
+ "%*s:%d", | |
+ cscf->server_name.len, cscf->server_name.data, ntohs(ports[0].port)); | |
+ server_id.len = ngx_strlen(server_id.data); | |
+ } | |
+ | |
+ ngx_ssl_error(NGX_LOG_DEBUG, cf->log, 0, | |
+ "server_id %*s", server_id.len, server_id.data); | |
+ } | |
+ | |
if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, | |
- &conf->certificate_key) | |
+ &conf->certificate_key, &conf->pass_phrase_conf, &server_id) | |
!= NGX_OK) | |
{ | |
return NGX_CONF_ERROR; | |
@@ -768,6 +803,36 @@ invalid: | |
return NGX_CONF_ERROR; | |
} | |
+static char * | |
+ngx_conf_set_pass_phrase_dialog(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
+{ | |
+ char *p = conf; | |
+ ngx_str_t *field, *value; | |
+ int len; | |
+ | |
+ field = (ngx_str_t *) (p + cmd->offset); | |
+ | |
+ if (field->data) { | |
+ return "is duplicate"; | |
+ } | |
+ | |
+ value = cf->args->elts; | |
+ | |
+ *field = value[1]; | |
+ | |
+ if (field->len == 0) { | |
+ return NGX_CONF_OK; | |
+ } else if (field->len > PASS_PHRASE_ARG_LEN) { | |
+ len = PASS_PHRASE_ARG_LEN; | |
+ | |
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
+ "The length of ssl_pass_phrase_dialog argument is more than %d", len); | |
+ | |
+ return NGX_CONF_ERROR; | |
+ } | |
+ | |
+ return NGX_CONF_OK; | |
+} | |
static ngx_int_t | |
ngx_http_ssl_init(ngx_conf_t *cf) | |
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h | |
index c4c576ef63be9c51f4af06faa4c38890e8cd78fd..d39d34247623c96a7a2b7ae5b60389143eca739f 100644 | |
--- a/src/http/modules/ngx_http_ssl_module.h | |
+++ b/src/http/modules/ngx_http_ssl_module.h | |
@@ -32,6 +32,7 @@ typedef struct { | |
ngx_str_t certificate; | |
ngx_str_t certificate_key; | |
+ ngx_str_t pass_phrase_conf; | |
ngx_str_t dhparam; | |
ngx_str_t ecdh_curve; | |
ngx_str_t client_certificate; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment