Added a wincrypt adapter to read CA trust certs from Windows CA store and feed them into openssl for TLS hostname authentication

This commit is contained in:
unknown 2016-01-23 18:47:03 -05:00
parent b39ddf01d0
commit 7e9563faed
2 changed files with 74 additions and 5 deletions

View File

@ -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"
],

View File

@ -43,7 +43,15 @@
#else
#include <winsock2.h>
#include <iphlpapi.h>
typedef unsigned short in_port_t;
typedef unsigned short in_port_t;
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#endif
#include <sys/stat.h>
@ -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. */