[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