Move from debugging to logging for

- upstream_stats & stub system
This commit is contained in:
Willem Toorop 2018-12-07 14:02:17 +01:00
parent bdfdd99645
commit 8a7226baee
7 changed files with 239 additions and 141 deletions

View File

@ -187,18 +187,19 @@ _getdns_strdup2(const struct mem_funcs *mfs, const getdns_bindata *s)
Add code to open the trust store using wincrypt API and add Add code to open the trust store using wincrypt API and add
the root certs into openssl trust store */ the root certs into openssl trust store */
static int static int
add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) add_WIN_cacerts_to_openssl_store(getdns_context *ctxt, SSL_CTX* tls_ctx)
{ {
HCERTSTORE hSystemStore; HCERTSTORE hSystemStore;
PCCERT_CONTEXT pTargetCert = NULL; PCCERT_CONTEXT pTargetCert = NULL;
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_DEBUG
"Adding Windows certificates from system root store to CA store"); , "%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__
, "Adding Windows certificates from system root store to CA store")
;
/* load just once per context lifetime for this version of getdns /* load just once per context lifetime for this version of getdns
TODO: dynamically update CA trust changes as they are available */ TODO: dynamically update CA trust changes as they are available */
if (!tls_ctx) assert(tls_ctx);
return 0;
/* Call wincrypt's CertOpenStore to open the CA root store. */ /* Call wincrypt's CertOpenStore to open the CA root store. */
@ -211,19 +212,27 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
1 << 16, 1 << 16,
L"root")) == 0) L"root")) == 0)
{ {
_getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__
, "Could not CertOpenStore()");
return 0; return 0;
} }
X509_STORE* store = SSL_CTX_get_cert_store(tls_ctx); X509_STORE* store = SSL_CTX_get_cert_store(tls_ctx);
if (!store) if (!store) {
_getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__
, "Could not SSL_CTX_get_cert_store()");
return 0; return 0;
}
/* failure if the CA store is empty or the call fails */ /* failure if the CA store is empty or the call fails */
if ((pTargetCert = CertEnumCertificatesInStore( if ((pTargetCert = CertEnumCertificatesInStore(
hSystemStore, pTargetCert)) == 0) { hSystemStore, pTargetCert)) == 0) {
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_NOTICE
"CA certificate store for Windows is empty."); , "%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__
return 0; , "CA certificate store for Windows is empty.");
return 0;
} }
/* iterate over the windows cert store and add to openssl store */ /* iterate over the windows cert store and add to openssl store */
do do
@ -233,9 +242,13 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
pTargetCert->cbCertEncoded); pTargetCert->cbCertEncoded);
if (!cert1) { if (!cert1) {
/* return error if a cert fails */ /* return error if a cert fails */
DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(&ctxt->log
"Unable to parse certificate in memory", , GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR,
ERR_get_error(), ERR_error_string(ERR_get_error(), NULL)); , "%s %-35s: %s %d:%s\n"
, STUB_DEBUG_SETUP_TLS, __FUNC__
, "Unable to parse certificate in memory"
, ERR_get_error()
, ERR_error_string(ERR_get_error(), NULL));
return 0; return 0;
} }
else { else {
@ -247,9 +260,16 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
* certificate is already in the store. */ * certificate is already in the store. */
if(ERR_GET_LIB(error) != ERR_LIB_X509 || if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(&ctxt->log
"Error adding certificate", ERR_get_error(), , GETDNS_LOG_SYS_STUB
ERR_error_string(ERR_get_error(), NULL)); , GETDNS_LOG_ERR
, "%s %-35s: %s %d:%s\n"
, STUB_DEBUG_SETUP_TLS, __FUNC__
, "Error adding certificate"
, ERR_get_error()
, ERR_error_string( ERR_get_error()
, NULL)
);
X509_free(cert1); X509_free(cert1);
return 0; return 0;
} }
@ -264,12 +284,18 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
CertFreeCertificateContext(pTargetCert); CertFreeCertificateContext(pTargetCert);
if (hSystemStore) if (hSystemStore)
{ {
if (!CertCloseStore( if (!CertCloseStore(hSystemStore, 0)) {
hSystemStore, 0)) _getdns_log(&ctxt->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__
, "Could not CertCloseStore()");
return 0; return 0;
}
} }
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_INFO
"Completed adding Windows certificates to CA store successfully"); , "%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__
, "Completed adding Windows certificates to CA store successfully")
;
return 1; return 1;
} }
#endif #endif
@ -698,26 +724,6 @@ upstreams_create(getdns_context *context, size_t size)
} }
#if defined(USE_DANESSL) && defined(STUB_DEBUG) && STUB_DEBUG
static void _stub_debug_print_openssl_errors(void)
{
unsigned long err;
char buffer[1024];
const char *file;
const char *data;
int line;
int flags;
while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
ERR_error_string_n(err, buffer, sizeof(buffer));
if (flags & ERR_TXT_STRING)
DEBUG_STUB("DEBUG OpenSSL Error: %s:%s:%d:%s\n", buffer, file, line, data);
else
DEBUG_STUB("DEBUG OpenSSL Error: %s:%s:%d\n", buffer, file, line);
}
}
#endif
void void
_getdns_upstreams_dereference(getdns_upstreams *upstreams) _getdns_upstreams_dereference(getdns_upstreams *upstreams)
{ {
@ -760,9 +766,6 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
if (upstream->tls_obj != NULL) { if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj); SSL_shutdown(upstream->tls_obj);
#ifdef USE_DANESSL #ifdef USE_DANESSL
# if defined(STUB_DEBUG) && STUB_DEBUG
_stub_debug_print_openssl_errors();
# endif
DANESSL_cleanup(upstream->tls_obj); DANESSL_cleanup(upstream->tls_obj);
#endif #endif
SSL_free(upstream->tls_obj); SSL_free(upstream->tls_obj);
@ -789,22 +792,6 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
GETDNS_FREE(upstreams->mf, upstreams); GETDNS_FREE(upstreams->mf, upstreams);
} }
void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system,
getdns_loglevel_type level, const char *fmt, ...)
{
va_list args;
if (!upstream || !upstream->upstreams || !upstream->upstreams->log.func
|| !(upstream->upstreams->log.system & system)
|| level > upstream->upstreams->log.level)
return;
va_start(args, fmt);
upstream->upstreams->log.func(
upstream->upstreams->log.userarg, system, level, fmt, args);
va_end(args);
}
static void static void
upstream_backoff(getdns_upstream *upstream) { upstream_backoff(getdns_upstream *upstream) {
upstream->conn_state = GETDNS_CONN_BACKOFF; upstream->conn_state = GETDNS_CONN_BACKOFF;
@ -881,9 +868,6 @@ _getdns_upstream_reset(getdns_upstream *upstream)
if (upstream->tls_obj != NULL) { if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj); SSL_shutdown(upstream->tls_obj);
#ifdef USE_DANESSL #ifdef USE_DANESSL
# if defined(STUB_DEBUG) && STUB_DEBUG
_stub_debug_print_openssl_errors();
# endif
DANESSL_cleanup(upstream->tls_obj); DANESSL_cleanup(upstream->tls_obj);
#endif #endif
SSL_free(upstream->tls_obj); SSL_free(upstream->tls_obj);
@ -1941,20 +1925,6 @@ getdns_context_set_logfunc(getdns_context *context, void *userarg,
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
void _getdns_context_log(getdns_context *context, uint64_t system,
getdns_loglevel_type level, const char *fmt, ...)
{
va_list args;
if (!context || !context->log.func || !(context->log.system & system)
|| level > context->log.level)
return;
va_start(args, fmt);
context->log.func(context->log.userarg, system, level, fmt, args);
va_end(args);
}
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
/* /*
* Helpers to set options on the unbound ctx * Helpers to set options on the unbound ctx
@ -3692,8 +3662,11 @@ getdns_return_t
_getdns_context_prepare_for_resolution(getdns_context *context) _getdns_context_prepare_for_resolution(getdns_context *context)
{ {
getdns_return_t r; getdns_return_t r;
#if defined(HAVE_SSL_CTX_DANE_ENABLE) || defined(USE_DANESSL)
int osr;
#endif
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); assert(context);
if (context->destroying) if (context->destroying)
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
@ -3777,29 +3750,23 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
# ifndef USE_WINSOCK # ifndef USE_WINSOCK
else if (!SSL_CTX_set_default_verify_paths(context->tls_ctx)) { else if (!SSL_CTX_set_default_verify_paths(context->tls_ctx)) {
# else # else
else if (!add_WIN_cacerts_to_openssl_store(context->tls_ctx)) { else if (!add_WIN_cacerts_to_openssl_store(context, context->tls_ctx)) {
# endif /* USE_WINSOCK */ # endif /* USE_WINSOCK */
if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED)
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
} }
# if defined(HAVE_SSL_CTX_DANE_ENABLE) # if defined(HAVE_SSL_CTX_DANE_ENABLE)
# if defined(STUB_DEBUG) && STUB_DEBUG osr = SSL_CTX_dane_enable(context->tls_ctx);
int osr = _getdns_log(&context->log
# else , GETDNS_LOG_SYS_STUB, GETDNS_LOG_DEBUG
(void) , "%s %-35s: DEBUG: SSL_CTX_dane_enable() -> %d\n"
# endif , STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
SSL_CTX_dane_enable(context->tls_ctx);
DEBUG_STUB("%s %-35s: DEBUG: SSL_CTX_dane_enable() -> %d\n"
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
# elif defined(USE_DANESSL) # elif defined(USE_DANESSL)
# if defined(STUB_DEBUG) && STUB_DEBUG osr = DANESSL_CTX_init(context->tls_ctx);
int osr = _getdns_log(&context->log
# else , GETDNS_LOG_SYS_STUB, GETDNS_LOG_DEBUG
(void) , "%s %-35s: DEBUG: DANESSL_CTX_init() returned "
# endif "%d\n", STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
DANESSL_CTX_init(context->tls_ctx);
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_CTX_init() -> %d\n"
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
# endif # endif
#else /* HAVE_TLS_v1_2 */ #else /* HAVE_TLS_v1_2 */
if (tls_only_is_in_transports_list(context) == 1) if (tls_only_is_in_transports_list(context) == 1)

View File

@ -127,7 +127,7 @@ const getdns_tsig_info *_getdns_get_tsig_info(getdns_tsig_algo tsig_alg);
/* for doing public key pinning of TLS-capable upstreams: */ /* for doing public key pinning of TLS-capable upstreams: */
typedef struct sha256_pin { typedef struct sha256_pin {
char pin[SHA256_DIGEST_LENGTH]; uint8_t pin[SHA256_DIGEST_LENGTH];
struct sha256_pin *next; struct sha256_pin *next;
} sha256_pin_t; } sha256_pin_t;
@ -502,11 +502,38 @@ struct getdns_context {
#endif /* HAVE_MDNS_SUPPORT */ #endif /* HAVE_MDNS_SUPPORT */
}; /* getdns_context */ }; /* getdns_context */
void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system, static inline int _getdns_check_log(const getdns_log_config *log,
getdns_loglevel_type level, const char *fmt, ...); uint64_t system, getdns_loglevel_type level)
{ assert(log)
; return log->func && (log->system & system) && level <= log->level; }
void _getdns_context_log(getdns_context *context, uint64_t system, static inline void _getdns_log(const getdns_log_config *log,
getdns_loglevel_type level, const char *fmt, ...); uint64_t system, getdns_loglevel_type level, const char *fmt, ...)
{
va_list args;
if (!_getdns_check_log(log, system, level))
return;
va_start(args, fmt);
log->func(log->userarg, system, level, fmt, args);
va_end(args);
}
static inline void _getdns_upstream_log(const getdns_upstream *up,
uint64_t system, getdns_loglevel_type level, const char *fmt, ...)
{
va_list args;
if (!up || !up->upstreams
|| !_getdns_check_log(&up->upstreams->log, system, level))
return;
va_start(args, fmt);
up->upstreams->log.func(
up->upstreams->log.userarg, system, level, fmt, args);
va_end(args);
}
/** internal functions **/ /** internal functions **/

View File

@ -3481,7 +3481,7 @@ void _getdns_ta_notify_dnsreqs(getdns_context *context)
getdns_network_req *netreq, **netreq_p; getdns_network_req *netreq, **netreq_p;
int r = GETDNS_RETURN_GOOD; int r = GETDNS_RETURN_GOOD;
(void) _getdns_context_prepare_for_resolution(context); (void) _getdns_context_prepare_for_resolution(context);
*dnsreq_p = dnsreq->ta_notify; *dnsreq_p = dnsreq->ta_notify;
for ( netreq_p = dnsreq->netreqs for ( netreq_p = dnsreq->netreqs

View File

@ -557,8 +557,11 @@ typedef enum getdns_loglevel_type {
#define GETDNS_LOG_INFO_TEXT "Informational message" #define GETDNS_LOG_INFO_TEXT "Informational message"
#define GETDNS_LOG_DEBUG_TEXT "Debug-level message" #define GETDNS_LOG_DEBUG_TEXT "Debug-level message"
#define GETDNS_LOG_UPSTREAM_STATS 4096 #define GETDNS_LOG_UPSTREAM_STATS 0x1000
#define GETDNS_LOG_UPSTREAM_STATS_TEXT "Log messages about upstream statistics" #define GETDNS_LOG_UPSTREAM_STATS_TEXT "Log messages about upstream statistics"
#define GETDNS_LOG_SYS_STUB 0x2000
#define GETDNS_LOG_SYS_STUB_TEXT "Log messages involving non upstream specific stub matters"
typedef void (*getdns_logfunc_type) (void *userarg, uint64_t log_systems, typedef void (*getdns_logfunc_type) (void *userarg, uint64_t log_systems,
getdns_loglevel_type, const char *, va_list ap); getdns_loglevel_type, const char *, va_list ap);

View File

@ -55,6 +55,7 @@
#include <string.h> #include <string.h>
#include "context.h" #include "context.h"
#include "util-internal.h" #include "util-internal.h"
#include "gldns/parseutil.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
#define X509_STORE_CTX_get0_untrusted(store) store->untrusted #define X509_STORE_CTX_get0_untrusted(store) store->untrusted
@ -378,19 +379,19 @@ _getdns_associate_upstream_with_SSL(SSL *ssl,
} }
getdns_return_t getdns_return_t
_getdns_verify_pinset_match(const sha256_pin_t *pinset, _getdns_verify_pinset_match(const getdns_upstream *upstream,
X509_STORE_CTX *store) const sha256_pin_t *pinset, X509_STORE_CTX *store)
{ {
getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
X509 *x, *prev = NULL; X509 *x, *prev = NULL;
char x_name_spc[1024], *x_name, prev_name_spc[1024];
int i, len; int i, len;
unsigned char raw[4096]; unsigned char raw[4096];
unsigned char *next; unsigned char *next;
unsigned char buf[sizeof(pinset->pin)]; unsigned char buf[sizeof(pinset->pin)];
const sha256_pin_t *p; const sha256_pin_t *p;
if (pinset == NULL || store == NULL) assert(pinset);
return GETDNS_RETURN_GENERIC_ERROR; assert(store);
/* start at the base of the chain (the end-entity cert) and /* start at the base of the chain (the end-entity cert) and
* make sure that some valid element of the chain does match * make sure that some valid element of the chain does match
@ -407,29 +408,74 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
/* TODO: how do we handle raw public keys? */ /* TODO: how do we handle raw public keys? */
for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++, prev = x) { for ( i = 0
; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store))
; i++, prev = x) {
x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i); x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i);
#if defined(STUB_DEBUG) && STUB_DEBUG x_name = NULL;
DEBUG_STUB("%s %-35s: Name of cert: %d ",
STUB_DEBUG_SETUP_TLS, __FUNC__, i); if (upstream->upstreams
X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE); && _getdns_check_log(&upstream->upstreams->log,
fprintf(stderr, "\n"); GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG)) {
#endif
x_name = X509_NAME_oneline( X509_get_subject_name(x)
, x_name_spc
, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG
, "%-40s : Verifying pinsets with cert: %d %s\n"
, upstream->addr_str, i, x_name);
}
if (i > 0) { if (i > 0) {
/* we ensure that "prev" is signed by "x" */ /* we ensure that "prev" is signed by "x" */
EVP_PKEY *pkey = X509_get_pubkey(x); EVP_PKEY *pkey = X509_get_pubkey(x);
int verified; int verified;
if (!pkey) { if (!pkey) {
DEBUG_STUB("%s %-35s: Could not get pubkey from cert %d (%p)\n", if (!upstream->upstreams
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)x); || !_getdns_check_log(
&upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_ERR
))
return GETDNS_RETURN_GENERIC_ERROR;
if (!x_name)
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%-40s : Could not get pubkey from cert "
"cert: %d %s\n"
, upstream->addr_str, i, x_name);
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
} }
verified = X509_verify(prev, pkey); verified = X509_verify(prev, pkey);
EVP_PKEY_free(pkey); EVP_PKEY_free(pkey);
if (!verified) { if (!verified) {
DEBUG_STUB("%s %-35s: cert %d (%p) was not signed by cert %d\n", if (!upstream->upstreams
STUB_DEBUG_SETUP_TLS, __FUNC__, i-1, (void*)prev, i); || !_getdns_check_log(
&upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_ERR
))
return GETDNS_RETURN_GENERIC_ERROR;
if (!x_name)
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%-40s : Cert: %d %swas not signed "
"by cert %d %s\n", upstream->addr_str
, i - 1
, X509_NAME_oneline(
X509_get_subject_name(prev)
, prev_name_spc
, sizeof(prev_name_spc) )
, i, x_name);
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
} }
} }
@ -437,31 +483,85 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
/* digest the cert with sha256 */ /* digest the cert with sha256 */
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL); len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
if (len > (int)sizeof(raw)) { if (len > (int)sizeof(raw)) {
DEBUG_STUB("%s %-35s: Pubkey %d is larger than %"PRIsz" octets\n", if (!upstream->upstreams
STUB_DEBUG_SETUP_TLS, __FUNC__, i, sizeof(raw)); || !_getdns_check_log( &upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_WARNING ))
continue;
if (!x_name)
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING
, "%-40s : Skipping cert %d %s, because pubkey is "
"larger than buffer size (%"PRIsz" octets)\n"
, upstream->addr_str, i, x_name, sizeof(raw));
continue; continue;
} }
next = raw; next = raw;
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next); i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
if (next - raw != len) { if (next - raw != len) {
DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed %"PRIsz"\n", if (!upstream->upstreams
STUB_DEBUG_SETUP_TLS, __FUNC__, i, len, next - raw); || !_getdns_check_log( &upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_WARNING ))
continue;
if (!x_name)
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING
, "%-40s : Skipping cert %d %s, because pubkey si"
"ze %"PRIsz" differs from earlier reported %d\n"
, upstream->addr_str, i, x_name, next - raw, len);
continue; continue;
} }
SHA256(raw, len, buf); SHA256(raw, len, buf);
/* compare it */ /* compare it */
for (p = pinset; p; p = p->next) for (p = pinset; p; p = p->next) {
if (0 == memcmp(buf, p->pin, sizeof(p->pin))) { char pin_str[1024];
DEBUG_STUB("%s %-35s: Pubkey %d matched pin %p (%"PRIsz")\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p, sizeof(p->pin));
return GETDNS_RETURN_GOOD;
} else
DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p);
}
return ret; if (x_name) /* only when debugging */
gldns_b64_ntop( p->pin , sizeof(p->pin)
, pin_str, sizeof(pin_str) );
if (0 == memcmp(buf, p->pin, sizeof(p->pin))) {
if (!upstream->upstreams
|| !_getdns_check_log(
&upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_INFO))
return GETDNS_RETURN_GOOD;
if (!x_name) {
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
gldns_b64_ntop( p->pin , sizeof(p->pin)
, pin_str
, sizeof(pin_str) );
}
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_INFO
, "%-40s : Pubkey of cert %d %s matched "
"pin %s\n", upstream->addr_str
, i, x_name, pin_str);
return GETDNS_RETURN_GOOD;
}
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG
, "%-40s : Pubkey of cert %d %s did not match"
" pin %s\n", upstream->addr_str
, i, x_name, pin_str);
}
}
return GETDNS_RETURN_GENERIC_ERROR;
} }
/* pubkey-pinning.c */ /* pubkey-pinning.c */

View File

@ -61,8 +61,8 @@ _getdns_associate_upstream_with_SSL(SSL *ssl,
getdns_upstream *upstream); getdns_upstream *upstream);
getdns_return_t getdns_return_t
_getdns_verify_pinset_match(const sha256_pin_t *pinset, _getdns_verify_pinset_match(const getdns_upstream *upstream,
X509_STORE_CTX *store); const sha256_pin_t *pinset, X509_STORE_CTX *store);
#endif #endif
/* pubkey-pinning.h */ /* pubkey-pinning.h */

View File

@ -887,7 +887,8 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
/* Deal with the pinset validation */ /* Deal with the pinset validation */
if (upstream->tls_pubkey_pinset) if (upstream->tls_pubkey_pinset)
pinset_ret = _getdns_verify_pinset_match(upstream->tls_pubkey_pinset, ctx); pinset_ret = _getdns_verify_pinset_match(
upstream, upstream->tls_pubkey_pinset, ctx);
if (pinset_ret != GETDNS_RETURN_GOOD) { if (pinset_ret != GETDNS_RETURN_GOOD) {
DEBUG_STUB("%s %-35s: FD: %d, WARNING: Pinset validation failure!\n", DEBUG_STUB("%s %-35s: FD: %d, WARNING: Pinset validation failure!\n",
@ -2402,9 +2403,9 @@ upstream_find_for_netreq(getdns_network_req *netreq)
return fd; return fd;
} }
/* Handle better, will give generic error*/ /* Handle better, will give generic error*/
DEBUG_STUB("%s %-35s: MSG: %p No valid upstream! \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq); _getdns_log(&netreq->owner->context->log
_getdns_context_log(netreq->owner->context, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR, , GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
" *FAILURE* no valid transports or upstreams available!\n"); , " *FAILURE* no valid transports or upstreams available!\n");
return -1; return -1;
} }