[RFC][PATCH 1/1] Add option to use directory for trusted CAs

eero.aaltonen at vaisala.com eero.aaltonen at vaisala.com
Fri Jul 7 15:02:15 UTC 2023


From: Eero Aaltonen <eero.aaltonen at vaisala.com>

Allow configuring trusted CAs to a directory with certificates and hash
symlinks generated with `openssl rehash`.

Signed-off-by: Eero Aaltonen <eero.aaltonen at vaisala.com>
---
 src/event/ngx_event_openssl.c            | 24 +++++++++++++++++-------
 src/event/ngx_event_openssl.h            |  2 +-
 src/http/modules/ngx_http_grpc_module.c  |  1 +
 src/http/modules/ngx_http_proxy_module.c |  1 +
 src/http/modules/ngx_http_ssl_module.c   | 15 +++++++++++++--
 src/http/modules/ngx_http_ssl_module.h   |  1 +
 src/http/modules/ngx_http_uwsgi_module.c |  1 +
 src/mail/ngx_mail_ssl_module.c           |  5 +++--
 src/stream/ngx_stream_proxy_module.c     |  1 +
 src/stream/ngx_stream_ssl_module.c       |  5 +++--
 src/stream/ngx_stream_ssl_module.h       |  1 +
 11 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index d762d6b..3da406c 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -870,24 +870,31 @@ ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
 
 ngx_int_t
 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
-    ngx_int_t depth)
+    ngx_str_t *ca_dir, ngx_int_t depth)
 {
     STACK_OF(X509_NAME)  *list;
+    char *ca_file = NULL;
+    char *ca_path = NULL;
 
     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_ssl_verify_callback);
 
     SSL_CTX_set_verify_depth(ssl->ctx, depth);
 
-    if (cert->len == 0) {
+    if (cert->len == 0 && ca_dir->len == 0) {
         return NGX_OK;
     }
 
-    if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
-        return NGX_ERROR;
+    if (ca_dir->len != 0) {
+        ca_path = ca_dir->data;
+    }
+    if (cert->len != 0) {
+        ca_file = cert->data;
+        if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
+            return NGX_ERROR;
+        }
     }
 
-    if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
-        == 0)
+    if (SSL_CTX_load_verify_locations(ssl->ctx, ca_file, ca_path) == 0)
     {
         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                       "SSL_CTX_load_verify_locations(\"%s\") failed",
@@ -902,6 +909,10 @@ ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
 
     ERR_clear_error();
 
+    if (cert->len == 0) { // TODO: load CAs from ca_dir?
+        return NGX_OK;
+    }
+
     list = SSL_load_client_CA_file((char *) cert->data);
 
     if (list == NULL) {
@@ -915,7 +926,6 @@ ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
     return NGX_OK;
 }
 
-
 ngx_int_t
 ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
     ngx_int_t depth)
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index 329760d..0a3481e 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -179,7 +179,7 @@ ngx_int_t ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
 ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
     ngx_uint_t prefer_server_ciphers);
 ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
-    ngx_str_t *cert, ngx_int_t depth);
+    ngx_str_t *cert, ngx_str_t *ca_dir, ngx_int_t depth);
 ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
     ngx_str_t *cert, ngx_int_t depth);
 ngx_int_t ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl);
diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c
index 53bc547..d5728e6 100644
--- a/src/http/modules/ngx_http_grpc_module.c
+++ b/src/http/modules/ngx_http_grpc_module.c
@@ -35,6 +35,7 @@ typedef struct {
     ngx_uint_t                 ssl_protocols;
     ngx_str_t                  ssl_ciphers;
     ngx_uint_t                 ssl_verify_depth;
+    ngx_str_t                  ssl_ca_dir;
     ngx_str_t                  ssl_trusted_certificate;
     ngx_str_t                  ssl_crl;
     ngx_str_t                  ssl_certificate;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index a63c3ed..6dda907 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -122,6 +122,7 @@ typedef struct {
     ngx_uint_t                     ssl_protocols;
     ngx_str_t                      ssl_ciphers;
     ngx_uint_t                     ssl_verify_depth;
+    ngx_str_t                      ssl_ca_dir;
     ngx_str_t                      ssl_trusted_certificate;
     ngx_str_t                      ssl_crl;
     ngx_str_t                      ssl_certificate;
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index a47d696..c80b614 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -182,6 +182,13 @@ static ngx_command_t  ngx_http_ssl_commands[] = {
       offsetof(ngx_http_ssl_srv_conf_t, client_certificate),
       NULL },
 
+    { ngx_string("ssl_client_ca_dir"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_str_slot,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_ssl_srv_conf_t, client_ca_dir),
+      NULL },
+
     { ngx_string("ssl_trusted_certificate"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_slot,
@@ -609,6 +616,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
      *     sscf->dhparam = { 0, NULL };
      *     sscf->ecdh_curve = { 0, NULL };
      *     sscf->client_certificate = { 0, NULL };
+     *     sscf->client_ca_dir = { 0, NULL };
      *     sscf->trusted_certificate = { 0, NULL };
      *     sscf->crl = { 0, NULL };
      *     sscf->ciphers = { 0, NULL };
@@ -690,6 +698,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
 
     ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
                          "");
+    ngx_conf_merge_str_value(conf->client_ca_dir,
+                         prev->client_ca_dir, "");
     ngx_conf_merge_str_value(conf->trusted_certificate,
                          prev->trusted_certificate, "");
     ngx_conf_merge_str_value(conf->crl, prev->crl, "");
@@ -840,14 +850,15 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
 
     if (conf->verify) {
 
-        if (conf->client_certificate.len == 0 && conf->verify != 3) {
+        if (conf->verify != 3 && conf->client_certificate.len == 0 && conf->client_ca_dir.len == 0) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                          "no ssl_client_certificate for ssl_verify_client");
+                          "ssl_verify_client needs ssl_client_certificate or ssl_client_ca_dir");
             return NGX_CONF_ERROR;
         }
 
         if (ngx_ssl_client_certificate(cf, &conf->ssl,
                                        &conf->client_certificate,
+                                       &conf->client_ca_dir,
                                        conf->verify_depth)
             != NGX_OK)
         {
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
index 7ab0f7e..e90b79b 100644
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -43,6 +43,7 @@ typedef struct {
     ngx_str_t                       dhparam;
     ngx_str_t                       ecdh_curve;
     ngx_str_t                       client_certificate;
+    ngx_str_t                       client_ca_dir;
     ngx_str_t                       trusted_certificate;
     ngx_str_t                       crl;
 
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 1334f44..7e13a08 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -52,6 +52,7 @@ typedef struct {
     ngx_uint_t                 ssl_protocols;
     ngx_str_t                  ssl_ciphers;
     ngx_uint_t                 ssl_verify_depth;
+    ngx_str_t                  ssl_ca_dir;
     ngx_str_t                  ssl_trusted_certificate;
     ngx_str_t                  ssl_crl;
     ngx_str_t                  ssl_certificate;
diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c
index 7eae83e..062d4d7 100644
--- a/src/mail/ngx_mail_ssl_module.c
+++ b/src/mail/ngx_mail_ssl_module.c
@@ -403,14 +403,15 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
 
     if (conf->verify) {
 
-        if (conf->client_certificate.len == 0 && conf->verify != 3) {
+        if (conf->verify != 3 && conf->client_certificate.len == 0 && conf->client_ca_dir.len == 0) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                          "no ssl_client_certificate for ssl_verify_client");
+                          "ssl_verify_client needs ssl_client_certificate or ssl_client_ca_dir");
             return NGX_CONF_ERROR;
         }
 
         if (ngx_ssl_client_certificate(cf, &conf->ssl,
                                        &conf->client_certificate,
+                                       &conf->client_ca_dir,
                                        conf->verify_depth)
             != NGX_OK)
         {
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c
index 01cda7a..1ad4ceb 100644
--- a/src/stream/ngx_stream_proxy_module.c
+++ b/src/stream/ngx_stream_proxy_module.c
@@ -44,6 +44,7 @@ typedef struct {
 
     ngx_flag_t                       ssl_verify;
     ngx_uint_t                       ssl_verify_depth;
+    ngx_str_t                        ssl_ca_dir;
     ngx_str_t                        ssl_trusted_certificate;
     ngx_str_t                        ssl_crl;
     ngx_str_t                        ssl_certificate;
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c
index d8c0471..adaa825 100644
--- a/src/stream/ngx_stream_ssl_module.c
+++ b/src/stream/ngx_stream_ssl_module.c
@@ -761,14 +761,15 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
 
     if (conf->verify) {
 
-        if (conf->client_certificate.len == 0 && conf->verify != 3) {
+        if (conf->verify != 3 && conf->client_certificate.len == 0 && conf->client_ca_dir.len == 0) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                          "no ssl_client_certificate for ssl_verify_client");
+                          "ssl_verify_client needs ssl_client_certificate or ssl_client_ca_dir");
             return NGX_CONF_ERROR;
         }
 
         if (ngx_ssl_client_certificate(cf, &conf->ssl,
                                        &conf->client_certificate,
+                                       &conf->client_ca_dir,
                                        conf->verify_depth)
             != NGX_OK)
         {
diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h
index c6e24be..607146e 100644
--- a/src/stream/ngx_stream_ssl_module.h
+++ b/src/stream/ngx_stream_ssl_module.h
@@ -40,6 +40,7 @@ typedef struct {
     ngx_str_t        dhparam;
     ngx_str_t        ecdh_curve;
     ngx_str_t        client_certificate;
+    ngx_str_t        client_ca_dir;
     ngx_str_t        trusted_certificate;
     ngx_str_t        crl;
 
-- 
2.25.1


More information about the nginx-devel mailing list