s4:lib/tls: add support for gnutls_certificate_set_x509_{system_trust,trust_dir}()
authorStefan Metzmacher <metze@samba.org>
Fri, 9 Feb 2024 10:31:30 +0000 (11:31 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 23 Apr 2024 23:50:34 +0000 (23:50 +0000)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/client/http_test.c
source4/lib/tls/tls.h
source4/lib/tls/tls_tstream.c

index ca542ba1c6b548c7dc115693ae1e41879377cae0..158b2d1a8dfd2384d538910c6ca86ffc2586cefe 100644 (file)
@@ -339,12 +339,16 @@ int main(int argc, const char *argv[])
                        http_info->server_addr, http_info->server_port,
                        use_tls ? " with tls" : " without tls");
                if (use_tls) {
+                       bool system_cas = false;
+                       const char * const *ca_dirs = NULL;
                        const char *crl_file = NULL;
                        const char *tls_priority = "NORMAL:-VERS-SSL3.0";
                        enum tls_verify_peer_state verify_peer =
                                TLS_VERIFY_PEER_CA_ONLY;
 
                        status = tstream_tls_params_client(mem_ctx,
+                                                  system_cas,
+                                                  ca_dirs,
                                                   ca_file,
                                                   crl_file,
                                                   tls_priority,
index 03063204e853f4150c9869eb89ade8d64d798c74..061973cd8fa61f36c4d52d3772a9fe219773743f 100644 (file)
@@ -56,6 +56,8 @@ enum tls_verify_peer_state {
 const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer);
 
 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
+                                  bool system_cas,
+                                  const char * const *ca_dirs,
                                   const char *ca_file,
                                   const char *crl_file,
                                   const char *tls_priority,
index f6ba7bdc1d255774688af9d7b401d0708d8e9b69..6b2c4c674c9b88fe3626d3b8fdbf74e8cf7a383e 100644 (file)
@@ -950,6 +950,8 @@ const DATA_BLOB *tstream_tls_channel_bindings(struct tstream_context *tls_tstrea
 }
 
 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
+                                  bool system_cas,
+                                  const char * const *ca_dirs,
                                   const char *ca_file,
                                   const char *crl_file,
                                   const char *tls_priority,
@@ -959,6 +961,8 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
 {
        struct tstream_tls_params *__tlsp = NULL;
        struct tstream_tls_params_internal *tlsp = NULL;
+       bool got_ca = false;
+       size_t i;
        int ret;
 
        __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
@@ -996,6 +1000,40 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
+       if (system_cas) {
+               ret = gnutls_certificate_set_x509_system_trust(tlsp->x509_cred);
+               if (ret < 0) {
+                       DBG_ERR("gnutls_certificate_set_x509_system_trust() - %s\n",
+                               gnutls_strerror(ret));
+                       TALLOC_FREE(__tlsp);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+               if (ret > 0) {
+                       got_ca = true;
+               }
+       }
+
+       for (i = 0; ca_dirs != NULL && ca_dirs[i] != NULL; i++) {
+               const char *ca_dir = ca_dirs[i];
+
+               if (!directory_exist(ca_dir)) {
+                       continue;
+               }
+
+               ret = gnutls_certificate_set_x509_trust_dir(tlsp->x509_cred,
+                                                           ca_dir,
+                                                           GNUTLS_X509_FMT_PEM);
+               if (ret < 0) {
+                       DBG_ERR("gnutls_certificate_set_x509_trust_dir(%s) - %s\n",
+                               ca_dir, gnutls_strerror(ret));
+                       TALLOC_FREE(__tlsp);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+               if (ret > 0) {
+                       got_ca = true;
+               }
+       }
+
        if (ca_file && *ca_file && file_exist(ca_file)) {
                ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
                                                             ca_file,
@@ -1006,11 +1044,17 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
                        TALLOC_FREE(__tlsp);
                        return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
                }
-       } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
-               DEBUG(0,("TLS failed to missing cafile %s - "
-                        "with 'tls verify peer = %s'\n",
-                        ca_file,
-                        tls_verify_peer_string(tlsp->verify_peer)));
+               if (ret > 0) {
+                       got_ca = true;
+               }
+       }
+
+       if (!got_ca && tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
+               D_ERR("TLS: 'tls verify peer = %s' requires "
+                     "'tls trust system cas', "
+                     "'tls ca directories' or "
+                     "'tls cafile'\n",
+                     tls_verify_peer_string(tlsp->verify_peer));
                TALLOC_FREE(__tlsp);
                return NT_STATUS_INVALID_PARAMETER_MIX;
        }
@@ -1052,6 +1096,8 @@ NTSTATUS tstream_tls_params_client_lpcfg(TALLOC_CTX *mem_ctx,
                                         struct tstream_tls_params **tlsp)
 {
        TALLOC_CTX *frame = talloc_stackframe();
+       bool system_cas = false;
+       const char * const *ca_dirs = NULL;
        const char *ptr = NULL;
        char *ca_file = NULL;
        char *crl_file = NULL;
@@ -1060,6 +1106,9 @@ NTSTATUS tstream_tls_params_client_lpcfg(TALLOC_CTX *mem_ctx,
                TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
        NTSTATUS status;
 
+       system_cas = lpcfg_tls_trust_system_cas(lp_ctx);
+       ca_dirs = lpcfg_tls_ca_directories(lp_ctx);
+
        ptr = lpcfg__tls_cafile(lp_ctx);
        if (ptr != NULL) {
                ca_file = lpcfg_tls_cafile(frame, lp_ctx);
@@ -1082,6 +1131,8 @@ NTSTATUS tstream_tls_params_client_lpcfg(TALLOC_CTX *mem_ctx,
        verify_peer = lpcfg_tls_verify_peer(lp_ctx);
 
        status = tstream_tls_params_client(mem_ctx,
+                                          system_cas,
+                                          ca_dirs,
                                           ca_file,
                                           crl_file,
                                           tls_priority,