diff src/event/ngx_event_openssl.c @ 7653:8409f9df6219

SSL: client certificate validation with OCSP (ticket #1534). OCSP validation for client certificates is enabled by the "ssl_ocsp" directive. OCSP responder can be optionally specified by "ssl_ocsp_responder". When session is reused, peer chain is not available for validation. If the verified chain contains certificates from the peer chain not available at the server, validation will fail.
author Roman Arutyunyan <arut@nginx.com>
date Fri, 22 May 2020 17:30:12 +0300
parents f1720934c45b
children 699f6e55bbb4 7995cd199b52
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -130,6 +130,7 @@ int  ngx_ssl_connection_index;
 int  ngx_ssl_server_conf_index;
 int  ngx_ssl_session_cache_index;
 int  ngx_ssl_session_ticket_keys_index;
+int  ngx_ssl_ocsp_index;
 int  ngx_ssl_certificate_index;
 int  ngx_ssl_next_certificate_index;
 int  ngx_ssl_certificate_name_index;
@@ -213,6 +214,13 @@ ngx_ssl_init(ngx_log_t *log)
         return NGX_ERROR;
     }
 
+    ngx_ssl_ocsp_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+    if (ngx_ssl_ocsp_index == -1) {
+        ngx_ssl_error(NGX_LOG_ALERT, log, 0,
+                      "SSL_CTX_get_ex_new_index() failed");
+        return NGX_ERROR;
+    }
+
     ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
                                                          NULL);
     if (ngx_ssl_certificate_index == -1) {
@@ -1594,6 +1602,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
 {
     int        n, sslerr;
     ngx_err_t  err;
+    ngx_int_t  rc;
 
 #ifdef SSL_READ_EARLY_DATA_SUCCESS
     if (c->ssl->try_early_data) {
@@ -1601,6 +1610,10 @@ ngx_ssl_handshake(ngx_connection_t *c)
     }
 #endif
 
+    if (c->ssl->in_ocsp) {
+        return ngx_ssl_ocsp_validate(c);
+    }
+
     ngx_ssl_clear_error(c->log);
 
     n = SSL_do_handshake(c->ssl->connection);
@@ -1621,8 +1634,6 @@ ngx_ssl_handshake(ngx_connection_t *c)
         ngx_ssl_handshake_log(c);
 #endif
 
-        c->ssl->handshaked = 1;
-
         c->recv = ngx_ssl_recv;
         c->send = ngx_ssl_write;
         c->recv_chain = ngx_ssl_recv_chain;
@@ -1641,6 +1652,20 @@ ngx_ssl_handshake(ngx_connection_t *c)
 #endif
 #endif
 
+        rc = ngx_ssl_ocsp_validate(c);
+
+        if (rc == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+
+        if (rc == NGX_AGAIN) {
+            c->read->handler = ngx_ssl_handshake_handler;
+            c->write->handler = ngx_ssl_handshake_handler;
+            return NGX_AGAIN;
+        }
+
+        c->ssl->handshaked = 1;
+
         return NGX_OK;
     }
 
@@ -1710,6 +1735,7 @@ ngx_ssl_try_early_data(ngx_connection_t 
     u_char     buf;
     size_t     readbytes;
     ngx_err_t  err;
+    ngx_int_t  rc;
 
     ngx_ssl_clear_error(c->log);
 
@@ -1744,7 +1770,6 @@ ngx_ssl_try_early_data(ngx_connection_t 
         c->ssl->early_buf = buf;
         c->ssl->early_preread = 1;
 
-        c->ssl->handshaked = 1;
         c->ssl->in_early = 1;
 
         c->recv = ngx_ssl_recv;
@@ -1752,6 +1777,20 @@ ngx_ssl_try_early_data(ngx_connection_t 
         c->recv_chain = ngx_ssl_recv_chain;
         c->send_chain = ngx_ssl_send_chain;
 
+        rc = ngx_ssl_ocsp_validate(c);
+
+        if (rc == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+
+        if (rc == NGX_AGAIN) {
+            c->read->handler = ngx_ssl_handshake_handler;
+            c->write->handler = ngx_ssl_handshake_handler;
+            return NGX_AGAIN;
+        }
+
+        c->ssl->handshaked = 1;
+
         return NGX_OK;
     }
 
@@ -2735,6 +2774,8 @@ ngx_ssl_shutdown(ngx_connection_t *c)
     int        n, sslerr, mode;
     ngx_err_t  err;
 
+    ngx_ssl_ocsp_cleanup(c);
+
     if (SSL_in_init(c->ssl->connection)) {
         /*
          * OpenSSL 1.0.2f complains if SSL_shutdown() is called during
@@ -4894,11 +4935,14 @@ ngx_ssl_get_client_verify(ngx_connection
     rc = SSL_get_verify_result(c->ssl->connection);
 
     if (rc == X509_V_OK) {
-        ngx_str_set(s, "SUCCESS");
-        return NGX_OK;
-    }
-
-    str = X509_verify_cert_error_string(rc);
+        if (ngx_ssl_ocsp_get_status(c, &str) == NGX_OK) {
+            ngx_str_set(s, "SUCCESS");
+            return NGX_OK;
+        }
+
+    } else {
+        str = X509_verify_cert_error_string(rc);
+    }
 
     s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str));
     if (s->data == NULL) {