diff --git a/m4/acx_getaddrinfo.m4 b/m4/acx_getaddrinfo.m4 index e88e1ddd..a4af9e1d 100644 --- a/m4/acx_getaddrinfo.m4 +++ b/m4/acx_getaddrinfo.m4 @@ -32,12 +32,12 @@ dnl see if on windows if test "$ac_cv_header_windows_h" = "yes"; then AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used]) USE_WINSOCK="1" - LIBS="$LIBS -lws2_32" + LIBS="$LIBS -lws2_32 -lcrypt32" fi ], dnl no quick getaddrinfo, try mingw32 and winsock2 library. ORIGLIBS="$LIBS" -LIBS="$LIBS -lws2_32" +LIBS="$LIBS -lws2_32 -lcrypt32" AC_LINK_IFELSE( [AC_LANG_PROGRAM( [ @@ -62,7 +62,7 @@ AC_LINK_IFELSE( )], [ ac_cv_func_getaddrinfo="yes" -dnl already: LIBS="$LIBS -lws2_32" +dnl already: LIBS="$LIBS -lws2_32 -lcrypt32" AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used]) USE_WINSOCK="1" ], diff --git a/src/context.c b/src/context.c index c47d4992..ae592017 100644 --- a/src/context.c +++ b/src/context.c @@ -43,7 +43,15 @@ #else #include #include -typedef unsigned short in_port_t; +typedef unsigned short in_port_t; + +#include +#include +#include + +#include +#include +#include #endif #include @@ -130,6 +138,66 @@ static void set_ub_edns_maximum_udp_payload_size(struct getdns_context*, /* Stuff to make it compile pedantically */ #define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code; + +#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 +X509_STORE *store; +X509_STORE_CTX *sslctx = NULL; +void add_cacerts_to_openssl_store(struct getdns_context *context) +{ + HCERTSTORE hSystemStore; + PCCERT_CONTEXT pTargetCert = NULL; + + // Call wincrypt's CertOpenStore to open the CA root store. + + if ((hSystemStore = CertOpenStore( + CERT_STORE_PROV_SYSTEM, + 0, + NULL, + // mingw does not have this const: replace with 1 << 16 from code + // CERT_SYSTEM_STORE_CURRENT_USER, + 1 << 16, + L"root")) == 0) + { + DEBUG_STUB("*** %s(CertOpenStore failed)\n", __FUNCTION__); + return; + } + store = SSL_CTX_get_cert_store(context->tls_ctx); + + // iterate over the windows cert store and add to openssl store + while (pTargetCert = CertEnumCertificatesInStore( + hSystemStore, + pTargetCert)) + { + BYTE* cert = pTargetCert->pbCertEncoded; + X509 *cert1 = d2i_X509(NULL, (const unsigned char **)&pTargetCert->pbCertEncoded, pTargetCert->cbCertEncoded); + if (!cert1) { + DEBUG_STUB("*** %s(%s)\n", __FUNCTION__, + "unable to parse certificate in memory"); + } + else { + if (X509_STORE_add_cert(store, cert1) == 0) + DEBUG_STUB("*** %s(%s)\n", __FUNCTION__, + "error adding certificate"); + X509_free(cert1); + } + } + // Clean up memory and quit. + + if (pTargetCert) + CertFreeCertificateContext(pTargetCert); + if (hSystemStore) + { + if (!CertCloseStore( + hSystemStore, 0)) + DEBUG_STUB("*** %s(%s)\n", __FUNCTION__, "CertCloseStore failed"); + } + +} +#endif + static void destroy_local_host(_getdns_rbnode_t * node, void *arg) { getdns_context *context = (getdns_context *)arg; @@ -2631,7 +2699,8 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, #ifndef USE_WINSOCK return GETDNS_RETURN_BAD_CONTEXT; #else - printf("Warning! Bad TLS context, check openssl version on Windows!\n");; + printf("Warning! Bad TLS context, check openssl version on Windows!\n"); + add_cacerts_to_openssl_store(context); #endif /* Be strict and only use the cipher suites recommended in RFC7525 Unless we later fallback to opportunistic. */