Skip to content

Instantly share code, notes, and snippets.

@fukusaka
Last active January 2, 2016 03:59
Show Gist options
  • Save fukusaka/8247865 to your computer and use it in GitHub Desktop.
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
# 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