]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Add routine from getdns to add windows cert store to the SSL_CTX.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 28 May 2018 13:22:10 +0000 (13:22 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 28 May 2018 13:22:10 +0000 (13:22 +0000)
git-svn-id: file:///svn/unbound/trunk@4697 be551aaa-1e26-0410-a405-d3ace91eadb9

configure
configure.ac
daemon/unbound.c
doc/Changelog
libunbound/libworker.c
testcode/streamtcp.c
util/config_file.c
util/config_file.h
util/net_help.c
util/net_help.h
winrc/win_svc.c

index 45cb7198d9eeaa0e31e99ebb862769e6d7199a2e..3f38929d8fd866bd54d0f6da6b38d16a50a00704 100755 (executable)
--- a/configure
+++ b/configure
@@ -19468,7 +19468,7 @@ else
   WINDRES="$ac_cv_prog_WINDRES"
 fi
 
-       LIBS="$LIBS -liphlpapi"
+       LIBS="$LIBS -liphlpapi -lcrypt32"
        WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
 
        WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
index 35a1096eb1d182f69f0b9bb7c7b4cedf5448f519..b4c484ec976fd4fa0968c66894c60f18a6dd7f7f 100644 (file)
@@ -1246,7 +1246,7 @@ if test "$USE_WINSOCK" = 1; then
 #include <windows.h>
        ])
        AC_CHECK_TOOL(WINDRES, windres)
-       LIBS="$LIBS -liphlpapi"
+       LIBS="$LIBS -liphlpapi -lcrypt32"
        WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
        AC_SUBST(WINAPPS)
        WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
index e4caf004819efa7242c9e574a1630667344e8861..138311013519a2b563b689bf5341277e304271a5 100644 (file)
@@ -431,7 +431,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
                        fatal_exit("could not set up listen SSL_CTX");
        }
        if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
-               cfg->tls_cert_bundle)))
+               cfg->tls_cert_bundle, cfg->tls_win_cert)))
                fatal_exit("could not set up connect SSL_CTX");
 #endif
 
index 84e3fac6dc6f070b82044fe47a0aad72e96030ca..fe1310f98143ed06d005ec1e644b7e1583ff3b17 100644 (file)
@@ -1,5 +1,6 @@
 28 May 2018: Wouter
        - Fix windows tcp and tls spin on events.
+       - Add routine from getdns to add windows cert store to the SSL_CTX.
 
 25 May 2018: Wouter
        - For TCP and TLS connections that don't establish, perform address
index 4aa9656af20340560d9fc561c57e5919fadeebe3..3dcaa7818f7dafff7a43938b133d395c0601c546 100644 (file)
@@ -158,9 +158,9 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
                hints_delete(w->env->hints);
                w->env->hints = NULL;
        }
-       if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0])) {
+       if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0]) || cfg->tls_win_cert) {
                w->sslctx = connect_sslctx_create(NULL, NULL,
-                       cfg->tls_cert_bundle);
+                       cfg->tls_cert_bundle, cfg->tls_win_cert);
                if(!w->sslctx) {
                        /* to make the setup fail after unlock */
                        hints_delete(w->env->hints);
index b494507def2659d8dc0d779b0f675ff6dbfaa655..0a636395fd35c1bbdf9f706e96e3271c381aea06 100644 (file)
@@ -284,7 +284,7 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs)
        SSL* ssl = NULL;
        if(!buf) fatal_exit("out of memory");
        if(usessl) {
-               ctx = connect_sslctx_create(NULL, NULL, NULL);
+               ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
                if(!ctx) fatal_exit("cannot create ssl ctx");
                ssl = outgoing_ssl_fd(ctx, fd);
                if(!ssl) fatal_exit("cannot create ssl");
index be90271343320114f3947886ab9879f757914138..9f623533f0f91c459ccd5b0948dd0e043b77dd0a 100644 (file)
@@ -109,6 +109,7 @@ config_create(void)
        cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT;
        cfg->ssl_upstream = 0;
        cfg->tls_cert_bundle = NULL;
+       cfg->tls_win_cert = 0;
        cfg->use_syslog = 1;
        cfg->log_identity = NULL; /* changed later with argv[0] */
        cfg->log_time_ascii = 0;
index 2b49d9c6ef5288f19285aabeb5302cb27a3b9f07..0473b2acf28d420eec3ee8ccf71d2deafa308eed 100644 (file)
@@ -102,6 +102,8 @@ struct config_file {
        int ssl_upstream;
        /** cert bundle for outgoing connections */
        char* tls_cert_bundle;
+       /** should the system certificate store get added to the cert bundle */
+       int tls_win_cert;
        /** additional tls ports */
        struct config_strlist* additional_tls_port;
 
index 40bfefb6426a05d107ba78b1c0c23fd077d11833..a5059b0addc1560146e596e5fb270e398a48e21a 100644 (file)
@@ -52,6 +52,9 @@
 #ifdef HAVE_OPENSSL_ERR_H
 #include <openssl/err.h>
 #endif
+#ifdef USE_WINSOCK
+#include <wincrypt.h>
+#endif
 
 /** max length of an IP address (the address portion) that we allow */
 #define MAX_ADDR_STRLEN 128 /* characters */
@@ -796,7 +799,97 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem)
 #endif
 }
 
-void* connect_sslctx_create(char* key, char* pem, char* verifypem)
+#ifdef USE_WINSOCK
+/* For windows, the CA trust store is not read by openssl.
+   Add code to open the trust store using wincrypt API and add
+   the root certs into openssl trust store */
+static int
+add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
+{
+       HCERTSTORE      hSystemStore;
+       PCCERT_CONTEXT  pTargetCert = NULL;
+       X509_STORE*     store;
+
+       verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store");
+
+       /* load just once per context lifetime for this version
+          TODO: dynamically update CA trust changes as they are available */
+       if (!tls_ctx)
+               return 0;
+
+       /* Call wincrypt's CertOpenStore to open the CA root store. */
+
+       if ((hSystemStore = CertOpenStore(
+               CERT_STORE_PROV_SYSTEM,
+               0,
+               0,
+               /* NOTE: mingw does not have this const: replace with 1 << 16 from code 
+                  CERT_SYSTEM_STORE_CURRENT_USER, */
+               1 << 16,
+               L"root")) == 0)
+       {
+               return 0;
+       }
+
+       store = SSL_CTX_get_cert_store(tls_ctx);
+       if (!store)
+               return 0;
+
+       /* failure if the CA store is empty or the call fails */
+       if ((pTargetCert = CertEnumCertificatesInStore(
+               hSystemStore, pTargetCert)) == 0) {
+               verbose(VERB_ALGO, "CA certificate store for Windows is empty.");
+               return 0;
+       }
+       /* iterate over the windows cert store and add to openssl store */
+       do
+       {
+               X509 *cert1 = d2i_X509(NULL,
+                       (const unsigned char **)&pTargetCert->pbCertEncoded,
+                       pTargetCert->cbCertEncoded);
+               if (!cert1) {
+                       /* return error if a cert fails */
+                       verbose(VERB_ALGO, "%s %d:%s",
+                               "Unable to parse certificate in memory",
+                               (int)ERR_get_error(), ERR_error_string(ERR_get_error(), NULL));
+                       return 0;
+               }
+               else {
+                       /* return error if a cert add to store fails */
+                       if (X509_STORE_add_cert(store, cert1) == 0) {
+                               unsigned long error = ERR_peek_last_error();
+
+                               /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
+                               * certificate is already in the store.  */
+                               if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
+                                  ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+                                       verbose(VERB_ALGO, "%s %d:%s\n",
+                                           "Error adding certificate", (int)ERR_get_error(),
+                                            ERR_error_string(ERR_get_error(), NULL));
+                                       X509_free(cert1);
+                                       return 0;
+                               }
+                       }
+                       X509_free(cert1);
+               }
+       } while ((pTargetCert = CertEnumCertificatesInStore(
+               hSystemStore, pTargetCert)) != 0);
+
+       /* Clean up memory and quit. */
+       if (pTargetCert)
+               CertFreeCertificateContext(pTargetCert);
+       if (hSystemStore)
+       {
+               if (!CertCloseStore(
+                       hSystemStore, 0))
+                       return 0;
+       }
+       verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully");
+       return 1;
+}
+#endif /* USE_WINSOCK */
+
+void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
 {
 #ifdef HAVE_SSL
        SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
@@ -836,17 +929,30 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem)
                        return NULL;
                }
        }
-       if(verifypem && verifypem[0]) {
-               if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
-                       log_crypto_err("error in SSL_CTX verify");
-                       SSL_CTX_free(ctx);
-                       return NULL;
+       if((verifypem && verifypem[0]) || wincert) {
+               if(verifypem && verifypem[0]) {
+                       if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
+                               log_crypto_err("error in SSL_CTX verify");
+                               SSL_CTX_free(ctx);
+                               return NULL;
+                       }
+               }
+#ifdef USE_WINSOCK
+               if(wincert) {
+                       if(!add_WIN_cacerts_to_openssl_store(ctx)) {
+                               log_crypto_err("error in add_WIN_cacerts_to_openssl_store");
+                               SSL_CTX_free(ctx);
+                               return NULL;
+                       }
                }
+#else
+               (void)wincert;
+#endif
                SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
        }
        return ctx;
 #else
-       (void)key; (void)pem; (void)verifypem;
+       (void)key; (void)pem; (void)verifypem; (void)wincert;
        return NULL;
 #endif
 }
index 1ecb13999f0f4174a0ed6a8beac589d5e43afe0b..de2e1accfd4034edc7089f6b671ff140248ff6f7 100644 (file)
@@ -395,9 +395,11 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem);
  * @param key: if nonNULL (also pem nonNULL), the client private key.
  * @param pem: client public key (or NULL if key is NULL).
  * @param verifypem: if nonNULL used for verifylocation file.
+ * @param wincert: add system certificate store to ctx (add to verifypem ca
+ *     certs).
  * @return SSL_CTX* or NULL on failure (logged).
  */
-void* connect_sslctx_create(char* key, char* pem, char* verifypem);
+void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert);
 
 /**
  * accept a new fd and wrap it in a BIO in SSL
index c5082ac3dff8ac3a07ff02a6bbe9baeec462e8ad..a87d73bf126baee9d5610c922262e732f1b573d6 100644 (file)
@@ -364,7 +364,7 @@ service_init(int r, struct daemon** d, struct config_file** c)
                        fatal_exit("could not set up listen SSL_CTX");
        }
        if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
-               cfg->tls_cert_bundle)))
+               cfg->tls_cert_bundle, cfg->tls_win_cert)))
                fatal_exit("could not set up connect SSL_CTX");
 
        /* open ports */