[nginx] SSL: detect "listen ... ssl" without certificates (ticket #178).
Maxim Dounin
mdounin at mdounin.ru
Tue Apr 24 12:56:21 UTC 2018
details: http://hg.nginx.org/nginx/rev/7f955d3b9a0d
branches:
changeset: 7269:7f955d3b9a0d
user: Maxim Dounin <mdounin at mdounin.ru>
date: Tue Apr 24 15:29:01 2018 +0300
description:
SSL: detect "listen ... ssl" without certificates (ticket #178).
In mail and stream modules, no certificate provided is a fatal condition,
much like with the "ssl" and "starttls" directives.
In http, "listen ... ssl" can be used in a non-default server without
certificates as long as there is a certificate in the default one, so
missing certificate is only fatal for default servers.
diffstat:
src/http/modules/ngx_http_ssl_module.c | 33 ++++++++++++-
src/http/ngx_http_core_module.c | 3 +
src/http/ngx_http_core_module.h | 3 +
src/http/ngx_http_request.c | 13 +----
src/mail/ngx_mail_core_module.c | 9 +++
src/mail/ngx_mail_handler.c | 18 +------
src/mail/ngx_mail_ssl_module.c | 86 ++++++++++++++-------------------
src/mail/ngx_mail_ssl_module.h | 1 +
src/stream/ngx_stream_core_module.c | 10 +++
src/stream/ngx_stream_ssl_module.c | 36 +++++++++-----
src/stream/ngx_stream_ssl_module.h | 4 +
11 files changed, 123 insertions(+), 93 deletions(-)
diffs (406 lines):
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -966,10 +966,12 @@ invalid:
static ngx_int_t
ngx_http_ssl_init(ngx_conf_t *cf)
{
- ngx_uint_t s;
+ ngx_uint_t a, p, s;
+ ngx_http_conf_addr_t *addr;
+ ngx_http_conf_port_t *port;
ngx_http_ssl_srv_conf_t *sscf;
ngx_http_core_loc_conf_t *clcf;
- ngx_http_core_srv_conf_t **cscfp;
+ ngx_http_core_srv_conf_t **cscfp, *cscf;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
@@ -993,5 +995,32 @@ ngx_http_ssl_init(ngx_conf_t *cf)
}
}
+ if (cmcf->ports == NULL) {
+ return NGX_OK;
+ }
+
+ port = cmcf->ports->elts;
+ for (p = 0; p < cmcf->ports->nelts; p++) {
+
+ addr = port[p].addrs.elts;
+ for (a = 0; a < port[p].addrs.nelts; a++) {
+
+ if (!addr[a].opt.ssl) {
+ continue;
+ }
+
+ cscf = addr[a].default_server;
+ sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
+
+ if (sscf->certificates == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"ssl_certificate\" is defined for "
+ "the \"listen ... ssl\" directive in %s:%ui",
+ cscf->file_name, cscf->line);
+ return NGX_ERROR;
+ }
+ }
+ }
+
return NGX_OK;
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -3256,6 +3256,9 @@ ngx_http_core_create_srv_conf(ngx_conf_t
cscf->merge_slashes = NGX_CONF_UNSET;
cscf->underscores_in_headers = NGX_CONF_UNSET;
+ cscf->file_name = cf->conf_file->file.name.data;
+ cscf->line = cf->conf_file->line;
+
return cscf;
}
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -184,6 +184,9 @@ typedef struct {
/* server ctx */
ngx_http_conf_ctx_t *ctx;
+ u_char *file_name;
+ ngx_uint_t line;
+
ngx_str_t server_name;
size_t connection_pool_size;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -336,19 +336,8 @@ ngx_http_init_connection(ngx_connection_
sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
if (sscf->enable || hc->addr_conf->ssl) {
-
+ hc->ssl = 1;
c->log->action = "SSL handshaking";
-
- if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
- ngx_log_error(NGX_LOG_ERR, c->log, 0,
- "no \"ssl_certificate\" is defined "
- "in server listening on SSL port");
- ngx_http_close_connection(c);
- return;
- }
-
- hc->ssl = 1;
-
rev->handler = ngx_http_ssl_handshake;
}
}
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -474,7 +474,16 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx
if (ngx_strcmp(value[i].data, "ssl") == 0) {
#if (NGX_MAIL_SSL)
+ ngx_mail_ssl_conf_t *sslcf;
+
+ sslcf = ngx_mail_conf_get_module_srv_conf(cf, ngx_mail_ssl_module);
+
+ sslcf->listen = 1;
+ sslcf->file = cf->conf_file->file.name.data;
+ sslcf->line = cf->conf_file->line;
+
ls->ssl = 1;
+
continue;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -165,29 +165,13 @@ ngx_mail_init_connection(ngx_connection_
sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
- if (sslcf->enable) {
+ if (sslcf->enable || addr_conf->ssl) {
c->log->action = "SSL handshaking";
ngx_mail_ssl_init_connection(&sslcf->ssl, c);
return;
}
- if (addr_conf->ssl) {
-
- c->log->action = "SSL handshaking";
-
- if (sslcf->ssl.ctx == NULL) {
- ngx_log_error(NGX_LOG_ERR, c->log, 0,
- "no \"ssl_certificate\" is defined "
- "in server listening on SSL port");
- ngx_mail_close_connection(c);
- return;
- }
-
- ngx_mail_ssl_init_connection(&sslcf->ssl, c);
- return;
- }
-
}
#endif
diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c
--- a/src/mail/ngx_mail_ssl_module.c
+++ b/src/mail/ngx_mail_ssl_module.c
@@ -238,6 +238,7 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf)
/*
* set by ngx_pcalloc():
*
+ * scf->listen = 0;
* scf->protocols = 0;
* scf->dhparam = { 0, NULL };
* scf->ecdh_curve = { 0, NULL };
@@ -313,14 +314,17 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf,
conf->ssl.log = cf->log;
- if (conf->enable) {
+ if (conf->listen) {
+ mode = "listen ... ssl";
+
+ } else if (conf->enable) {
mode = "ssl";
} else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) {
mode = "starttls";
} else {
- mode = "";
+ return NGX_CONF_OK;
}
if (conf->file == NULL) {
@@ -328,51 +332,31 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf,
conf->line = prev->line;
}
- if (*mode) {
-
- if (conf->certificates == NULL) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"ssl_certificate\" is defined for "
- "the \"%s\" directive in %s:%ui",
- mode, conf->file, conf->line);
- return NGX_CONF_ERROR;
- }
-
- if (conf->certificate_keys == NULL) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"ssl_certificate_key\" is defined for "
- "the \"%s\" directive in %s:%ui",
- mode, conf->file, conf->line);
- return NGX_CONF_ERROR;
- }
+ if (conf->certificates == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"ssl_certificate\" is defined for "
+ "the \"%s\" directive in %s:%ui",
+ mode, conf->file, conf->line);
+ return NGX_CONF_ERROR;
+ }
- if (conf->certificate_keys->nelts < conf->certificates->nelts) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"ssl_certificate_key\" is defined "
- "for certificate \"%V\" and "
- "the \"%s\" directive in %s:%ui",
- ((ngx_str_t *) conf->certificates->elts)
- + conf->certificates->nelts - 1,
- mode, conf->file, conf->line);
- return NGX_CONF_ERROR;
- }
-
- } else {
+ if (conf->certificate_keys == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"ssl_certificate_key\" is defined for "
+ "the \"%s\" directive in %s:%ui",
+ mode, conf->file, conf->line);
+ return NGX_CONF_ERROR;
+ }
- if (conf->certificates == NULL) {
- return NGX_CONF_OK;
- }
-
- if (conf->certificate_keys == NULL
- || conf->certificate_keys->nelts < conf->certificates->nelts)
- {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"ssl_certificate_key\" is defined "
- "for certificate \"%V\"",
- ((ngx_str_t *) conf->certificates->elts)
- + conf->certificates->nelts - 1);
- return NGX_CONF_ERROR;
- }
+ if (conf->certificate_keys->nelts < conf->certificates->nelts) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"ssl_certificate_key\" is defined "
+ "for certificate \"%V\" and "
+ "the \"%s\" directive in %s:%ui",
+ ((ngx_str_t *) conf->certificates->elts)
+ + conf->certificates->nelts - 1,
+ mode, conf->file, conf->line);
+ return NGX_CONF_ERROR;
}
if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
@@ -494,8 +478,10 @@ ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_
return NGX_CONF_ERROR;
}
- scf->file = cf->conf_file->file.name.data;
- scf->line = cf->conf_file->line;
+ if (!scf->listen) {
+ scf->file = cf->conf_file->file.name.data;
+ scf->line = cf->conf_file->line;
+ }
return NGX_CONF_OK;
}
@@ -520,8 +506,10 @@ ngx_mail_ssl_starttls(ngx_conf_t *cf, ng
return NGX_CONF_ERROR;
}
- scf->file = cf->conf_file->file.name.data;
- scf->line = cf->conf_file->line;
+ if (!scf->listen) {
+ scf->file = cf->conf_file->file.name.data;
+ scf->line = cf->conf_file->line;
+ }
return NGX_CONF_OK;
}
diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h
--- a/src/mail/ngx_mail_ssl_module.h
+++ b/src/mail/ngx_mail_ssl_module.h
@@ -26,6 +26,7 @@ typedef struct {
ngx_ssl_t ssl;
ngx_uint_t starttls;
+ ngx_uint_t listen;
ngx_uint_t protocols;
ngx_uint_t verify;
diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c
--- a/src/stream/ngx_stream_core_module.c
+++ b/src/stream/ngx_stream_core_module.c
@@ -734,7 +734,17 @@ ngx_stream_core_listen(ngx_conf_t *cf, n
if (ngx_strcmp(value[i].data, "ssl") == 0) {
#if (NGX_STREAM_SSL)
+ ngx_stream_ssl_conf_t *sslcf;
+
+ sslcf = ngx_stream_conf_get_module_srv_conf(cf,
+ ngx_stream_ssl_module);
+
+ sslcf->listen = 1;
+ sslcf->file = cf->conf_file->file.name.data;
+ sslcf->line = cf->conf_file->line;
+
ls->ssl = 1;
+
continue;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c
--- a/src/stream/ngx_stream_ssl_module.c
+++ b/src/stream/ngx_stream_ssl_module.c
@@ -304,13 +304,6 @@ ngx_stream_ssl_handler(ngx_stream_sessio
if (c->ssl == NULL) {
c->log->action = "SSL handshaking";
- if (sslcf->ssl.ctx == NULL) {
- ngx_log_error(NGX_LOG_ERR, c->log, 0,
- "no \"ssl_certificate\" is defined "
- "in server listening on SSL port");
- return NGX_ERROR;
- }
-
rv = ngx_stream_ssl_init_connection(&sslcf->ssl, c);
if (rv != NGX_OK) {
@@ -510,6 +503,7 @@ ngx_stream_ssl_create_conf(ngx_conf_t *c
/*
* set by ngx_pcalloc():
*
+ * scf->listen = 0;
* scf->protocols = 0;
* scf->dhparam = { 0, NULL };
* scf->ecdh_curve = { 0, NULL };
@@ -582,18 +576,34 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf
conf->ssl.log = cf->log;
- if (conf->certificates == NULL) {
+ if (!conf->listen) {
return NGX_CONF_OK;
}
- if (conf->certificate_keys == NULL
- || conf->certificate_keys->nelts < conf->certificates->nelts)
- {
+ if (conf->certificates == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"ssl_certificate\" is defined for "
+ "the \"listen ... ssl\" directive in %s:%ui",
+ conf->file, conf->line);
+ return NGX_CONF_ERROR;
+ }
+
+ if (conf->certificate_keys == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"ssl_certificate_key\" is defined for "
+ "the \"listen ... ssl\" directive in %s:%ui",
+ conf->file, conf->line);
+ return NGX_CONF_ERROR;
+ }
+
+ if (conf->certificate_keys->nelts < conf->certificates->nelts) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"ssl_certificate_key\" is defined "
- "for certificate \"%V\"",
+ "for certificate \"%V\" and "
+ "the \"listen ... ssl\" directive in %s:%ui",
((ngx_str_t *) conf->certificates->elts)
- + conf->certificates->nelts - 1);
+ + conf->certificates->nelts - 1,
+ conf->file, conf->line);
return NGX_CONF_ERROR;
}
diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h
--- a/src/stream/ngx_stream_ssl_module.h
+++ b/src/stream/ngx_stream_ssl_module.h
@@ -21,6 +21,7 @@ typedef struct {
ngx_ssl_t ssl;
+ ngx_uint_t listen;
ngx_uint_t protocols;
ngx_uint_t verify;
@@ -47,6 +48,9 @@ typedef struct {
ngx_flag_t session_tickets;
ngx_array_t *session_ticket_keys;
+
+ u_char *file;
+ ngx_uint_t line;
} ngx_stream_ssl_conf_t;
More information about the nginx-devel
mailing list