Check pins with DANE functions when available

This commit is contained in:
Willem Toorop 2018-01-04 15:58:09 +01:00
parent 2ff1bf6152
commit 540735a956
3 changed files with 97 additions and 12 deletions

View File

@ -408,7 +408,7 @@ fi
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version])
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version SSL_CTX_dane_enable SSL_dane_enable SSL_dane_tlsa_add])
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_OPENSSL_ERR_H

View File

@ -3622,6 +3622,11 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED)
return GETDNS_RETURN_BAD_CONTEXT;
}
# ifdef HAVE_SSL_CTX_DANE_ENABLE
int 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);
# endif
#else /* HAVE_TLS_v1_2 */
if (tls_only_is_in_transports_list(context) == 1)
return GETDNS_RETURN_BAD_CONTEXT;

View File

@ -827,7 +827,16 @@ tls_requested(getdns_network_req *netreq)
1 : 0;
}
int
#ifdef HAVE_SSL_DANE_ENABLE
static int
_getdns_tls_verify_always_ok(int preverify_ok, X509_STORE_CTX *ctx)
{ (void)preverify_ok; (void)ctx; return 1; }
#else
static int
tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
getdns_upstream *upstream;
@ -837,11 +846,11 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
return 0;
int err = X509_STORE_CTX_get_error(ctx);
#if defined(STUB_DEBUG) && STUB_DEBUG
# if defined(STUB_DEBUG) && STUB_DEBUG
DEBUG_STUB("%s %-35s: FD: %d Verify result: (%d) \"%s\"\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err,
X509_verify_cert_error_string(err));
#endif
# endif
if (!preverify_ok && !upstream->tls_fallback_ok)
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : Verify failed : Transport=TLS - *Failure* - (%d) \"%s\"\n",
@ -849,14 +858,14 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
X509_verify_cert_error_string(err));
/* First deal with the hostname authentication done by OpenSSL. */
#ifdef X509_V_ERR_HOSTNAME_MISMATCH
# if defined(STUB_DEBUG) && STUB_DEBUG
# ifdef X509_V_ERR_HOSTNAME_MISMATCH
# if defined(STUB_DEBUG) && STUB_DEBUG
/*Report if error is hostname mismatch*/
if (err == X509_V_ERR_HOSTNAME_MISMATCH && upstream->tls_fallback_ok)
DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
# endif
#else
# endif
# else
/* if we weren't built against OpenSSL with hostname matching we
* could not have matched the hostname, so this would be an automatic
* tls_auth_fail if there is a hostname provided*/
@ -864,7 +873,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
preverify_ok = 0;
}
#endif
# endif
/* Now deal with the pinset validation*/
if (upstream->tls_pubkey_pinset)
@ -910,6 +919,8 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
return (upstream->tls_fallback_ok) ? 1 : preverify_ok;
}
#endif /* HAVE_SSL_DANE_ENABLE */
static SSL*
tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
{
@ -992,7 +1003,30 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS,
__FUNC__);
}
#ifdef HAVE_SSL_DANE_ENABLE
int osr = SSL_dane_enable(ssl, *upstream->tls_auth_name ? upstream->tls_auth_name : NULL);
DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_enable(\"%s\") -> %d\n"
, STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->tls_auth_name, osr);
SSL_set_verify(ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok);
sha256_pin_t *pin_p;
size_t n_pins = 0;
for (pin_p = upstream->tls_pubkey_pinset; pin_p; pin_p = pin_p->next) {
osr = SSL_dane_tlsa_add(ssl, 2, 1, 1,
(unsigned char *)pin_p->pin, SHA256_DIGEST_LENGTH);
DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_tlsa_add() -> %d\n"
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
if (osr > 0)
++n_pins;
osr = SSL_dane_tlsa_add(ssl, 3, 1, 1,
(unsigned char *)pin_p->pin, SHA256_DIGEST_LENGTH);
DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_tlsa_add() -> %d\n"
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
if (osr > 0)
++n_pins;
}
#else
SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
#endif
SSL_set_connect_state(ssl);
(void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
@ -1048,16 +1082,62 @@ tls_do_handshake(getdns_upstream *upstream)
return STUB_SETUP_ERROR;
}
}
upstream->tls_hs_state = GETDNS_HS_DONE;
upstream->conn_state = GETDNS_CONN_OPEN;
upstream->conn_completed++;
/* A re-used session is not verified so need to fix up state in that case */
if (SSL_session_reused(upstream->tls_obj))
upstream->tls_auth_state = upstream->last_tls_auth_state;
else if (upstream->tls_pubkey_pinset || upstream->tls_auth_name[0]) {
X509 *peer_cert = SSL_get_peer_certificate(upstream->tls_obj);
long verify_result = SSL_get_verify_result(upstream->tls_obj);
upstream->tls_auth_state = peer_cert && verify_result == X509_V_OK
? GETDNS_AUTH_OK : GETDNS_AUTH_FAILED;
X509_free(peer_cert);
if (!peer_cert)
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS,
( upstream->tls_fallback_ok
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
"%-40s : Verify failed : Transport=TLS - %s - "
"Remote did not offer certificate\n",
upstream->addr_str,
( upstream->tls_fallback_ok
? "Allowed because of Opportunistic profile"
: "*Failure*" ));
else if (verify_result != X509_V_OK)
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS,
( upstream->tls_fallback_ok
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
"%-40s : Verify failed : Transport=TLS - %s - "
"(%d) \"%s\"\n", upstream->addr_str,
( upstream->tls_fallback_ok
? "Allowed because of Opportunistic profile"
: "*Failure*" ), verify_result,
X509_verify_cert_error_string(verify_result));
else
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : Verify passed : Transport=TLS - %s - "
"(%d) \"%s\"\n", upstream->addr_str,
( upstream->tls_fallback_ok
? "Allowed because of Opportunistic profile"
: "*Failure*" ), verify_result,
X509_verify_cert_error_string(verify_result));
if (upstream->tls_auth_state == GETDNS_AUTH_FAILED
&& !upstream->tls_fallback_ok)
return STUB_SETUP_ERROR;
}
DEBUG_STUB("%s %-35s: FD: %d Handshake succeeded with auth state %s. Session is %s.\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd,
_getdns_auth_str(upstream->tls_auth_state),
SSL_session_reused(upstream->tls_obj) ?"re-used":"new");
upstream->tls_hs_state = GETDNS_HS_DONE;
upstream->conn_state = GETDNS_CONN_OPEN;
upstream->conn_completed++;
if (upstream->tls_session != NULL)
SSL_SESSION_free(upstream->tls_session);
upstream->tls_session = SSL_get1_session(upstream->tls_obj);