[PATCH 4 of 6] SSL: add ngx_ssl_verify_client()

Piotr Sikora piotrsikora at google.com
Thu Aug 18 00:29:25 UTC 2016


# HG changeset patch
# User Piotr Sikora <piotrsikora at google.com>
# Date 1471428990 25200
#      Wed Aug 17 03:16:30 2016 -0700
# Node ID a9f36e1dd744130aa2ba080ae2a63f07986c8e83
# Parent  99c2f52beae28567bf2f8501d1a182cd20004c71
SSL: add ngx_ssl_verify_client().

No functional changes.

Signed-off-by: Piotr Sikora <piotrsikora at google.com>

diff -r 99c2f52beae2 -r a9f36e1dd744 src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -3075,6 +3075,39 @@ ngx_ssl_cleanup_ctx(void *data)
 
 
 ngx_int_t
+ngx_ssl_verify_client(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_uint_t verify)
+{
+    long   rc;
+    X509  *cert;
+
+    rc = SSL_get_verify_result(c->ssl->connection);
+
+    if (rc != X509_V_OK
+        && (verify != NGX_SSL_VERIFY_OPTIONAL_NO_CA
+            || !ngx_ssl_verify_error_optional(rc)))
+    {
+        ngx_ssl_remove_cached_session(ssl->ctx,
+                                      SSL_get0_session(c->ssl->connection));
+        return (ngx_int_t) rc;
+    }
+
+    if (verify == NGX_SSL_VERIFY_REQUIRED) {
+        cert = SSL_get_peer_certificate(c->ssl->connection);
+
+        if (cert == NULL) {
+            ngx_ssl_remove_cached_session(ssl->ctx,
+                                          SSL_get0_session(c->ssl->connection));
+            return NGX_DECLINED;
+        }
+
+        X509_free(cert);
+    }
+
+    return NGX_OK;
+}
+
+
+ngx_int_t
 ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name)
 {
     X509   *cert;
diff -r 99c2f52beae2 -r a9f36e1dd744 src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -188,12 +188,15 @@ ngx_int_t ngx_ssl_set_session(ngx_connec
 #define ngx_ssl_get_server_conf(ssl_ctx)                                      \
     SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_server_conf_index)
 
+ngx_int_t ngx_ssl_verify_client(ngx_connection_t *c, ngx_ssl_t *ssl,
+    ngx_uint_t verify);
 #define ngx_ssl_verify_error_optional(n)                                      \
     (n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT                              \
      || n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN                             \
      || n == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY                     \
      || n == X509_V_ERR_CERT_UNTRUSTED                                        \
      || n == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)
+#define ngx_ssl_verify_error_string(n)  X509_verify_cert_error_string((long) n)
 
 ngx_int_t ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name);
 
diff -r 99c2f52beae2 -r a9f36e1dd744 src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1845,8 +1845,7 @@ ngx_http_process_request(ngx_http_reques
 #if (NGX_HTTP_SSL)
 
     if (r->http_connection->ssl) {
-        long                      rc;
-        X509                     *cert;
+        ngx_int_t                 rc;
         ngx_http_ssl_srv_conf_t  *sscf;
 
         if (c->ssl == NULL) {
@@ -1859,39 +1858,23 @@ ngx_http_process_request(ngx_http_reques
         sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
 
         if (sscf->verify) {
-            rc = SSL_get_verify_result(c->ssl->connection);
-
-            if (rc != X509_V_OK
-                && (sscf->verify != NGX_SSL_VERIFY_OPTIONAL_NO_CA
-                    || !ngx_ssl_verify_error_optional(rc)))
-            {
+            rc = ngx_ssl_verify_client(c, &sscf->ssl, sscf->verify);
+
+            if (rc == NGX_DECLINED) {
                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
-                              "client SSL certificate verify error: (%l:%s)",
-                              rc, X509_verify_cert_error_string(rc));
-
-                ngx_ssl_remove_cached_session(sscf->ssl.ctx,
-                                       (SSL_get0_session(c->ssl->connection)));
+                              "client sent no required SSL certificate");
+
+                ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
+                return;
+
+            } else if (rc != NGX_OK) {
+                ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                              "client SSL certificate verify error: (%i:%s)",
+                              rc, ngx_ssl_verify_error_string(rc));
 
                 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
                 return;
             }
-
-            if (sscf->verify == NGX_SSL_VERIFY_REQUIRED) {
-                cert = SSL_get_peer_certificate(c->ssl->connection);
-
-                if (cert == NULL) {
-                    ngx_log_error(NGX_LOG_INFO, c->log, 0,
-                                  "client sent no required SSL certificate");
-
-                    ngx_ssl_remove_cached_session(sscf->ssl.ctx,
-                                       (SSL_get0_session(c->ssl->connection)));
-
-                    ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
-                    return;
-                }
-
-                X509_free(cert);
-            }
         }
     }
 
diff -r 99c2f52beae2 -r a9f36e1dd744 src/mail/ngx_mail_handler.c
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -16,8 +16,6 @@ static void ngx_mail_init_session(ngx_co
 #if (NGX_MAIL_SSL)
 static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
 static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c);
-static ngx_int_t ngx_mail_verify_cert(ngx_mail_session_t *s,
-    ngx_connection_t *c);
 #endif
 
 
@@ -247,15 +245,44 @@ ngx_mail_ssl_init_connection(ngx_ssl_t *
 static void
 ngx_mail_ssl_handshake_handler(ngx_connection_t *c)
 {
+    ngx_int_t                  rc;
     ngx_mail_session_t        *s;
+    ngx_mail_ssl_conf_t       *sslcf;
     ngx_mail_core_srv_conf_t  *cscf;
 
     if (c->ssl->handshaked) {
 
         s = c->data;
 
-        if (ngx_mail_verify_cert(s, c) != NGX_OK) {
-            return;
+        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+        if (sslcf->verify) {
+            rc = ngx_ssl_verify_client(c, &sslcf->ssl, sslcf->verify);
+
+            if (rc != NGX_OK) {
+                cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+                if (rc == NGX_DECLINED) {
+                    ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                                  "client sent no required SSL certificate");
+
+                    s->out = cscf->protocol->no_cert;
+
+                } else {
+                    ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                                  "client SSL certificate verify error: (%i:%s)",
+                                  rc, ngx_ssl_verify_error_string(rc));
+
+                    s->out = cscf->protocol->cert_error;
+                }
+
+                s->quit = 1;
+
+                c->write->handler = ngx_mail_send;
+
+                ngx_mail_send(s->connection->write);
+                return;
+            }
         }
 
         if (s->starttls) {
@@ -278,72 +305,6 @@ ngx_mail_ssl_handshake_handler(ngx_conne
     ngx_mail_close_connection(c);
 }
 
-
-static ngx_int_t
-ngx_mail_verify_cert(ngx_mail_session_t *s, ngx_connection_t *c)
-{
-    long                       rc;
-    X509                      *cert;
-    ngx_mail_ssl_conf_t       *sslcf;
-    ngx_mail_core_srv_conf_t  *cscf;
-
-    sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
-
-    if (!sslcf->verify) {
-        return NGX_OK;
-    }
-
-    rc = SSL_get_verify_result(c->ssl->connection);
-
-    if (rc != X509_V_OK
-        && (sslcf->verify != NGX_SSL_VERIFY_OPTIONAL_NO_CA
-            || !ngx_ssl_verify_error_optional(rc)))
-    {
-        ngx_log_error(NGX_LOG_INFO, c->log, 0,
-                      "client SSL certificate verify error: (%l:%s)",
-                      rc, X509_verify_cert_error_string(rc));
-
-        ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
-                                      (SSL_get0_session(c->ssl->connection)));
-
-        cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
-
-        s->out = cscf->protocol->cert_error;
-        s->quit = 1;
-
-        c->write->handler = ngx_mail_send;
-
-        ngx_mail_send(s->connection->write);
-        return NGX_ERROR;
-    }
-
-    if (sslcf->verify == NGX_SSL_VERIFY_REQUIRED) {
-        cert = SSL_get_peer_certificate(c->ssl->connection);
-
-        if (cert == NULL) {
-            ngx_log_error(NGX_LOG_INFO, c->log, 0,
-                          "client sent no required SSL certificate");
-
-            ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
-                                       (SSL_get0_session(c->ssl->connection)));
-
-            cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
-
-            s->out = cscf->protocol->no_cert;
-            s->quit = 1;
-
-            c->write->handler = ngx_mail_send;
-
-            ngx_mail_send(s->connection->write);
-            return NGX_ERROR;
-        }
-
-        X509_free(cert);
-    }
-
-    return NGX_OK;
-}
-
 #endif
 
 



More information about the nginx-devel mailing list