Merge branch 'develop' into devel/default_eventloop

This commit is contained in:
Willem Toorop 2016-02-04 15:17:25 +01:00
commit e6f5cdb45b
3 changed files with 128 additions and 32 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

@ -44,6 +44,14 @@
#include <winsock2.h>
#include <iphlpapi.h>
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,86 @@ 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 */
static int
add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
{
HCERTSTORE hSystemStore;
PCCERT_CONTEXT pTargetCert = NULL;
/* load just once per context lifetime for this version of getdns
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;
}
X509_STORE* 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) {
DEBUG_STUB("*** %s(%s %d:%s)\n", __FUNCTION__,
"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 */
DEBUG_STUB("*** %s(%s %d:%s)\n", __FUNCTION__,
"unable to parse certificate in memory",
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) {
DEBUG_STUB("*** %s(%s %d:%s)\n", __FUNCTION__,
"error adding certificate", ERR_get_error(),
ERR_error_string(ERR_get_error(), NULL));
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;
}
return 1;
}
#endif
static void destroy_local_host(_getdns_rbnode_t * node, void *arg)
{
getdns_context *context = (getdns_context *)arg;
@ -864,8 +952,9 @@ set_os_defaults(struct getdns_context *context)
*token = 0;
(void) strlcpy(domain, parse, sizeof(domain));
} else if (strncmp(parse, "search", 6) == 0) {
continue;
}
if (strncmp(parse, "search", 6) == 0) {
parse += 6;
do {
parse += strspn(parse, " \t");
@ -879,8 +968,9 @@ set_os_defaults(struct getdns_context *context)
*token = prev_ch;
parse = token;
} while (*parse);
} else if (strncmp(parse, "nameserver", 10) != 0)
continue;
}
if (strncmp(parse, "nameserver", 10) != 0)
continue;
parse += 10;
@ -2658,30 +2748,7 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
/* Transport can in theory be set per query in stub mode */
if (context->resolution_type == GETDNS_RESOLUTION_STUB &&
tls_is_in_transports_list(context) == 1) {
if (context->tls_ctx == NULL) {
#ifdef HAVE_TLS_v1_2
/* Create client context, use TLS v1.2 only for now */
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
if(context->tls_ctx == NULL)
#ifndef USE_WINSOCK
return GETDNS_RETURN_BAD_CONTEXT;
#else
printf("Warning! Bad TLS context, check openssl version on Windows!\n");;
#endif
/* Be strict and only use the cipher suites recommended in RFC7525
Unless we later fallback to opportunistic. */
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS))
return GETDNS_RETURN_BAD_CONTEXT;
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx))
return GETDNS_RETURN_BAD_CONTEXT;
#else
if (tls_only_is_in_transports_list(context) == 1)
return GETDNS_RETURN_BAD_CONTEXT;
/* A null tls_ctx will make TLS fail and fallback to the other
transports will kick-in.*/
#endif
}
/* Check minimum require authentication level*/
if (tls_only_is_in_transports_list(context) == 1 &&
context->tls_auth == GETDNS_AUTHENTICATION_REQUIRED) {
context->tls_auth_min = GETDNS_AUTHENTICATION_REQUIRED;
@ -2690,6 +2757,35 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
else {
context->tls_auth_min = GETDNS_AUTHENTICATION_NONE;
}
if (context->tls_ctx == NULL) {
#ifdef HAVE_TLS_v1_2
/* Create client context, use TLS v1.2 only for now */
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
if(context->tls_ctx == NULL)
return GETDNS_RETURN_BAD_CONTEXT;
/* Be strict and only use the cipher suites recommended in RFC7525
Unless we later fallback to opportunistic. */
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS))
return GETDNS_RETURN_BAD_CONTEXT;
/* For strict authentication, we must have local root certs available
Set up is done only when the tls_ctx is created (per getdns_context)*/
#ifndef USE_WINSOCK
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx)) {
#else
if (!add_WIN_cacerts_to_openssl_store(context->tls_ctx)) {
#endif /* USE_WINSOCK */
if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED)
return GETDNS_RETURN_BAD_CONTEXT;
}
#else /* HAVE_TLS_v1_2 */
if (tls_only_is_in_transports_list(context) == 1)
return GETDNS_RETURN_BAD_CONTEXT;
/* A null tls_ctx will make TLS fail and fallback to the other
transports will kick-in.*/
#endif /* HAVE_TLS_v1_2 */
}
}
/* Block use of TLS ONLY in recursive mode as it won't work */

View File

@ -99,7 +99,7 @@ getdns_dict* getdns_pubkey_pin_create_from_string(
getdns_dict* out = NULL;
/* we only do sha256 right now, make sure this is well-formed */
if (strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH))
if (!str || strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH))
return NULL;
for (i = PIN_PREFIX_LENGTH; i < PIN_PREFIX_LENGTH + B64_ENCODED_SHA256_LENGTH - 1; i++)
if (!((str[i] >= 'a' && str[i] <= 'z') ||