I'am very glad that this patch is useful for you.
The below is the patch or the diff. It's based on the nginx 0.8.54 or nginx 0.8.55.
Perhaps it also works for other version. Maybe you need to merge it by hand.
Index: src/http/modules/ngx_http_ssl_module.c
===================================================================
--- src/http/modules/ngx_http_ssl_module.c (revision 347)
+++ src/http/modules/ngx_http_ssl_module.c (revision 348)
@@ -14,6 +14,7 @@
#define NGX_DEFAULT_CIPHERS "HIGH:!ADH:!MD5"
+#define PASS_PHRASE_ARG_LEN 255
static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
@@ -31,6 +32,11 @@
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static int ngx_enhanced_system(char* cmdstring, char* buf, int len);
+static int ngx_http_ssl_pass_phase_callback(char *buf, int bufsize,
+ int verify, void *srv);
+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 },
@@ -141,6 +147,13 @@
offsetof(ngx_http_ssl_srv_conf_t, crl),
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
};
@@ -213,6 +226,124 @@
static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
+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 int
+ngx_http_ssl_pass_phase_callback(char *buf, int bufsize, int verify, void *srv)
+{
+ ngx_str_t pass_phase_file;
+ int ret;
+ char cmdline[PASS_PHRASE_ARG_LEN + 1] = {0};
+
+ ngx_http_ssl_srv_conf_t * conf = srv;
+
+ /* get the executable file path */
+ pass_phase_file.data = conf->pass_phrase_conf.data + 5;
+ pass_phase_file.len = conf->pass_phrase_conf.len - 5;
+
+ ngx_memcpy(cmdline, pass_phase_file.data, pass_phase_file.len);
+ cmdline[pass_phase_file.len] = '\0';
+
+ ret = ngx_enhanced_system(cmdline, 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* cmdstring, 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 (execl("/bin/sh", "sh", "-c", cmdstring, (char*)0) == -1) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
static ngx_int_t
ngx_http_ssl_static_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
@@ -316,6 +447,8 @@
* sscf->crl = { 0, NULL };
* sscf->ciphers = { 0, NULL };
* sscf->shm_zone = NULL;
+ *
+ * sscf->pass_phrase_conf = { 0, NULL };
*/
sscf->enable = NGX_CONF_UNSET;
@@ -362,7 +495,9 @@
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");
+
conf->ssl.log = cf->log;
if (conf->enable) {
@@ -401,6 +536,18 @@
return NGX_CONF_ERROR;
}
+ if (ngx_strncasecmp(conf->pass_phrase_conf.data, (u_char*)"exec:", 5) == 0) {
+
+ SSL_CTX_set_default_passwd_cb(conf->ssl.ctx, ngx_http_ssl_pass_phase_callback);
+
+ SSL_CTX_set_default_passwd_cb_userdata(conf->ssl.ctx, (void *)conf);
+
+ } else if (ngx_strncasecmp(conf->pass_phrase_conf.data, (u_char*)"builtin", 7) != 0) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "The arg of ssl_pass_phrase_dialog directive is incorrect: builtin | exec:path");
+ return NGX_CONF_ERROR;
+ }
+
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
Index: src/http/modules/ngx_http_ssl_module.h
===================================================================
--- src/http/modules/ngx_http_ssl_module.h (revision 347)
+++ src/http/modules/ngx_http_ssl_module.h (revision 348)
@@ -41,6 +41,8 @@
u_char *file;
ngx_uint_t line;
+
+ ngx_str_t pass_phrase_conf;
} ngx_http_ssl_srv_conf_t;