Merge branch 'release/1.5.0'

This commit is contained in:
Willem Toorop 2018-12-21 17:22:17 +01:00
commit 215d553c0b
56 changed files with 2398 additions and 1166 deletions

View File

@ -1,3 +1,38 @@
* 2018-12-21: Version 1.5.0
* RFE getdnsapi/stubby#121 log re-instantiating TLS
upstreams (because they reached tls_backoff_time) at
log level 4 (WARNING)
* GETDNS_RESPSTATUS_NO_NAME for NODATA answers too
* ZONEMD rr-type
* getdns_query queries for addresses when a query name
without a type is given.
* RFE #408: Fetching of trust anchors will be retried
after failure, after a certain backoff time. The time
can be configured with
getdns_context_set_trust_anchors_backoff_time().
* RFE #408: A "dnssec" extension that requires DNSSEC
verification. When this extension is set, Indeterminate
DNSSEC status will not be returned.
* Issue #410: Unspecified ownership of get_api_information()
* Fix for DNSSEC bug in finding most specific key when
trust anchor proves non-existance of one of the labels
along the authentication chain other than the non-
existance of a DS record on a zonecut.
* Enhancement getdnsapi/stubby#56 & getdnsapi/stubby#130:
Configurable minimum and maximum TLS versions with
getdns_context_set_tls_min_version() and
getdns_context_set_tls_max_version() functions and
tls_min_version and tls_max_version configuration parameters
for upstreams.
* Configurable TLS1.3 ciphersuites with the
getdns_context_set_tls_ciphersuites() function and
tls_ciphersuites config parameter for upstreams.
* Bugfix in upstream string configurations: tls_cipher_list and
tls_curve_list
* Bugfix finding signer for validating NSEC and NSEC3s, which
caused trouble with the partly tracing DNSSEC from the root
up, introduced in 1.4.2. Thanks Philip Homburg
* 2018-05-11: Version 1.4.2 * 2018-05-11: Version 1.4.2
* Bugfix getdnsapi/stubby#87: Detect and ignore duplicate certs * Bugfix getdnsapi/stubby#87: Detect and ignore duplicate certs
in the Windows root CA store. in the Windows root CA store.

View File

@ -165,7 +165,7 @@ distclean:
rm -f m4/ltoptions.m4 rm -f m4/ltoptions.m4
rm -f m4/ltsugar.m4 rm -f m4/ltsugar.m4
rm -f m4/ltversion.m4 rm -f m4/ltversion.m4
rm -f $(distdir).tar.gz $(distdir).tar.gz.sha256 rm -f $(distdir).tar.gz $(distdir).tar.gz.sha256 $(distdir).tar.gz.sha1
rm -f $(distdir).tar.gz.md5 $(distdir).tar.gz.asc rm -f $(distdir).tar.gz.md5 $(distdir).tar.gz.asc
megaclean: megaclean:
@ -177,11 +177,14 @@ autoclean: megaclean
dist: $(distdir).tar.gz dist: $(distdir).tar.gz
pub: $(distdir).tar.gz.sha256 $(distdir).tar.gz.md5 $(distdir).tar.gz.asc pub: $(distdir).tar.gz.sha256 $(distdir).tar.gz.md5 $(distdir).tar.gz.asc $(distdir).tar.gz.sha1
$(distdir).tar.gz.sha256: $(distdir).tar.gz $(distdir).tar.gz.sha256: $(distdir).tar.gz
openssl sha256 $(distdir).tar.gz >$@ openssl sha256 $(distdir).tar.gz >$@
$(distdir).tar.gz.sha1: $(distdir).tar.gz
openssl sha1 $(distdir).tar.gz >$@
$(distdir).tar.gz.md5: $(distdir).tar.gz $(distdir).tar.gz.md5: $(distdir).tar.gz
openssl md5 $(distdir).tar.gz >$@ openssl md5 $(distdir).tar.gz >$@

View File

@ -36,7 +36,7 @@ sinclude(./m4/acx_getaddrinfo.m4)
sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/ax_check_compile_flag.m4)
sinclude(./m4/pkg.m4) sinclude(./m4/pkg.m4)
AC_INIT([getdns], [1.4.2], [team@getdnsapi.net], [getdns], [https://getdnsapi.net]) AC_INIT([getdns], [1.5.0], [team@getdnsapi.net], [getdns], [https://getdnsapi.net])
# Autoconf 2.70 will have set up runstatedir. 2.69 is frequently (Debian) # Autoconf 2.70 will have set up runstatedir. 2.69 is frequently (Debian)
# patched to do the same, but frequently (MacOS) not. So add a with option # patched to do the same, but frequently (MacOS) not. So add a with option
@ -63,13 +63,13 @@ AC_ARG_WITH([current-date],
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"]) [CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"]) AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01040200]) AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01050000])
AC_SUBST(API_VERSION, ["December 2015"]) AC_SUBST(API_VERSION, ["December 2015"])
AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00]) AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API" GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
AC_DEFINE_UNQUOTED([STUBBY_PACKAGE], ["stubby"], [Stubby package]) AC_DEFINE_UNQUOTED([STUBBY_PACKAGE], ["stubby"], [Stubby package])
AC_DEFINE_UNQUOTED([STUBBY_PACKAGE_STRING], ["0.2.3$STUBBY_RELEASE_CANDIDATE"], [Stubby package string]) AC_DEFINE_UNQUOTED([STUBBY_PACKAGE_STRING], ["0.2.4$STUBBY_RELEASE_CANDIDATE"], [Stubby package string])
# Library version # Library version
# --------------- # ---------------
@ -105,8 +105,9 @@ AC_DEFINE_UNQUOTED([STUBBY_PACKAGE_STRING], ["0.2.3$STUBBY_RELEASE_CANDIDATE"],
# getdns-1.3.0 had libversion 9:0:3 # getdns-1.3.0 had libversion 9:0:3
# getdns-1.4.0 had libversion 10:0:0 # getdns-1.4.0 had libversion 10:0:0
# getdns-1.4.1 had libversion 10:1:0 # getdns-1.4.1 had libversion 10:1:0
# getdns-1.4.2 has libversion 10:2:0 # getdns-1.4.2 had libversion 10:2:0
GETDNS_LIBVERSION=10:2:0 # getdns-1.5.0 has libversion 11:0:1
GETDNS_LIBVERSION=11:0:1
AC_SUBST(GETDNS_COMPILATION_COMMENT) AC_SUBST(GETDNS_COMPILATION_COMMENT)
AC_SUBST(GETDNS_LIBVERSION) AC_SUBST(GETDNS_LIBVERSION)
@ -400,9 +401,49 @@ yes)
esac esac
USE_NSS="no" USE_NSS="no"
dnl AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path],
dnl [use libnss instead of openssl, installed at path.]),
dnl [
dnl USE_NSS="yes"
dnl AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto])
dnl if test "$withval" != "" -a "$withval" != "yes"; then
dnl CPPFLAGS="$CPPFLAGS -I$withval/include/nss3"
dnl LDFLAGS="$LDFLAGS -L$withval/lib"
dnl ACX_RUNTIME_PATH_ADD([$withval/lib])
dnl CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS"
dnl else
dnl CPPFLAGS="$CPPFLAGS -I/usr/include/nss3"
dnl CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
dnl fi
dnl LIBS="$LIBS -lnss3 -lnspr4"
dnl SSLLIB=""
dnl ]
dnl )
# libnettle
USE_NETTLE="no"
dnl AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path],
dnl [use libnettle as crypto library, installed at path.]),
dnl [
dnl USE_NETTLE="yes"
dnl AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
dnl AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT])
dnl if test "$withval" != "" -a "$withval" != "yes"; then
dnl CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
dnl LDFLAGS="$LDFLAGS -L$withval/lib"
dnl ACX_RUNTIME_PATH_ADD([$withval/lib])
dnl else
dnl CPPFLAGS="$CPPFLAGS -I/usr/include/nettle"
dnl fi
dnl LIBS="$LIBS -lhogweed -lnettle -lgmp"
dnl SSLLIB=""
dnl ]
dnl )
# openssl # openssl
if test $USE_NSS = "no"; then if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
ACX_WITH_SSL_OPTIONAL ACX_WITH_SSL
fi
ACX_LIB_SSL ACX_LIB_SSL
AC_MSG_CHECKING([for LibreSSL]) AC_MSG_CHECKING([for LibreSSL])
if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
@ -414,11 +455,11 @@ if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/conf.h openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/engine.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_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 SSL_CTX_dane_enable SSL_dane_enable SSL_dane_tlsa_add X509_check_host]) 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 X509_check_host X509_get_notAfter X509_get0_notAfter SSL_CTX_set_ciphersuites SSL_set_ciphersuites])
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set1_curves_list,SSL_set1_curves_list], [], [], [ AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set1_curves_list,SSL_set1_curves_list,SSL_set_min_proto_version,SSL_get_min_proto_version], [], [], [
AC_INCLUDES_DEFAULT AC_INCLUDES_DEFAULT
#ifdef HAVE_OPENSSL_ERR_H #ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h> #include <openssl/err.h>
@ -438,7 +479,6 @@ AC_INCLUDES_DEFAULT
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/evp.h> #include <openssl/evp.h>
]) ])
fi
AC_MSG_CHECKING([whether we need to compile/link DANE support]) AC_MSG_CHECKING([whether we need to compile/link DANE support])
DANESSL_XTRA_OBJS="" DANESSL_XTRA_OBJS=""
@ -581,7 +621,7 @@ AC_MSG_RESULT($ac_cv_c_gost_works)
AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support])) AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support]))
use_gost="no" use_gost="no"
if test $USE_NSS = "no"; then if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
case "$enable_gost" in case "$enable_gost" in
no) no)
;; ;;
@ -595,7 +635,7 @@ case "$enable_gost" in
fi fi
;; ;;
esac esac
fi dnl !USE_NSS fi dnl !USE_NSS && !USE_NETTLE
AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support])) AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support]))
use_ecdsa="no" use_ecdsa="no"
@ -603,7 +643,7 @@ case "$enable_ecdsa" in
no) no)
;; ;;
*) *)
if test $USE_NSS = "no"; then if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])]) AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])]) AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
@ -635,6 +675,7 @@ case "$enable_dsa" in
;; ;;
*) dnl default *) dnl default
# detect if DSA is supported, and turn it off if not. # detect if DSA is supported, and turn it off if not.
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
AC_CHECK_FUNC(DSA_SIG_new, [ AC_CHECK_FUNC(DSA_SIG_new, [
AC_CHECK_TYPE(DSA_SIG*, [ AC_CHECK_TYPE(DSA_SIG*, [
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.]) AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
@ -659,6 +700,9 @@ AC_INCLUDES_DEFAULT
]) ])
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.]) ], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
fi ]) fi ])
else
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
fi
;; ;;
esac esac
@ -668,15 +712,40 @@ case "$enable_ed25519" in
no) no)
;; ;;
*) *)
if test "$USE_NSS" = "no" -a "$USE_NETTLE" = "no"; then if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
AC_CHECK_DECLS([NID_ED25519], [ AC_CHECK_DECLS([NID_ED25519], [
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
use_ed25519="yes" use_ed25519="yes"
], [ if test "x$enable_ed25519" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED25519 and you used --enable-ed25519.]) ], [ if test "x$enable_ed25519" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED25519 and you used --enable-ed25519.])
fi ], [AC_INCLUDES_DEFAULT fi ], [AC_INCLUDES_DEFAULT
#include <openssl/evp.h> #include <openssl/evp.h>
]) ])
fi fi
if test $USE_NETTLE = "yes"; then
AC_CHECK_HEADERS([nettle/eddsa.h], use_ed25519="yes",, [AC_INCLUDES_DEFAULT])
fi
if test $use_ed25519 = "yes"; then
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
fi
;;
esac
AC_ARG_ENABLE(ed448, AC_HELP_STRING([--disable-ed448], [Disable ED448 support]))
use_ed448="no"
case "$enable_ed448" in
no)
;;
*)
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
AC_CHECK_DECLS([NID_ED448], [
use_ed448="yes"
], [ if test "x$enable_ed448" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED448 and you used --enable-ed448.])
fi ], [AC_INCLUDES_DEFAULT
#include <openssl/evp.h>
])
fi
if test $use_ed448 = "yes"; then
AC_DEFINE_UNQUOTED([USE_ED448], [1], [Define this to enable ED448 support.])
fi
;; ;;
esac esac

View File

@ -703,7 +703,7 @@ static uint8_t *tas_validate(struct mem_funcs *mf,
success = NULL; success = NULL;
} }
} else } else
DEBUG_ANCHOR("Could not allocate space for " DEBUG_ANCHOR("Cannot allocate space for "
"trust anchors\n"); "trust anchors\n");
} else { } else {
success = tas; success = tas;
@ -736,57 +736,71 @@ void _getdns_context_equip_with_anchor(
if ((r = getdns_context_get_trust_anchors_verify_CA( if ((r = getdns_context_get_trust_anchors_verify_CA(
context, &verify_CA))) context, &verify_CA)))
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify" _getdns_log( &context->log
" CA: \"%s\"\n", __FUNC__ , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, getdns_get_errorstr_by_id(r)); , "Cannot get trust anchor verify CA: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
else if (!verify_CA || !*verify_CA) else if (!verify_CA || !*verify_CA)
DEBUG_ANCHOR("NOTICE: Trust anchor verification explicitely " _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "Trust anchor verification explicitly "
"disabled by empty verify CA\n"); "disabled by empty verify CA\n");
else if ((r = getdns_context_get_trust_anchors_verify_email( else if ((r = getdns_context_get_trust_anchors_verify_email(
context, &verify_email))) context, &verify_email)))
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify email " _getdns_log( &context->log
"address: \"%s\"\n", __FUNC__ , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, getdns_get_errorstr_by_id(r)); , "Cannot get trust anchor verify email address: "
"\"%s\"\n", getdns_get_errorstr_by_id(r));
else if (!verify_email || !*verify_email) else if (!verify_email || !*verify_email)
DEBUG_ANCHOR("NOTICE: Trust anchor verification explicitely " _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "Trust anchor verification explicitly "
"disabled by empty verify email\n"); "disabled by empty verify email\n");
else if (!(xml_data = _getdns_context_get_priv_file(context, else if (!(xml_data = _getdns_context_get_priv_file(context,
"root-anchors.xml", xml_spc, sizeof(xml_spc), &xml_len))) "root-anchors.xml", xml_spc, sizeof(xml_spc), &xml_len)))
DEBUG_ANCHOR("DEBUG %s(): root-anchors.xml not present\n" _getdns_log( &context->log
, __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "root-anchors.xml not present\n");
else if (!(p7s_data = _getdns_context_get_priv_file(context, else if (!(p7s_data = _getdns_context_get_priv_file(context,
"root-anchors.p7s", p7s_spc, sizeof(p7s_spc), &p7s_len))) "root-anchors.p7s", p7s_spc, sizeof(p7s_spc), &p7s_len)))
DEBUG_ANCHOR("DEBUG %s(): root-anchors.p7s not present\n" _getdns_log( &context->log
, __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "root-anchors.xml not present\n");
else if (!(xml = BIO_new_mem_buf(xml_data, xml_len))) else if (!(xml = BIO_new_mem_buf(xml_data, xml_len)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating xml BIO\n" _getdns_log( &context->log
, __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed allocating xml BIO\n");
else if (!(p7s = BIO_new_mem_buf(p7s_data, p7s_len))) else if (!(p7s = BIO_new_mem_buf(p7s_data, p7s_len)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating p7s BIO\n" _getdns_log( &context->log
, __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed allocating p7s BIO\n");
else if (!(crt = BIO_new_mem_buf((void *)verify_CA, -1))) else if (!(crt = BIO_new_mem_buf((void *)verify_CA, -1)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating crt BIO\n" _getdns_log( &context->log
, __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed allocating crt BIO\n");
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL))) else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
DEBUG_ANCHOR("ERROR %s(): Parsing builtin certificate\n" _getdns_log( &context->log
, __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Cannot parse builtin certificate\n");
else if (!(store = X509_STORE_new())) else if (!(store = X509_STORE_new()))
DEBUG_ANCHOR("ERROR %s(): Failed allocating store\n" _getdns_log( &context->log
, __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed allocating X509 store\n");
else if (!X509_STORE_add_cert(store, x)) else if (!X509_STORE_add_cert(store, x))
DEBUG_ANCHOR("ERROR %s(): Adding certificate to store\n" _getdns_log( &context->log
, __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Cannot add certificate to X509 store\n");
else if (_getdns_verify_p7sig(xml, p7s, store, verify_email)) { else if (_getdns_verify_p7sig(xml, p7s, store, verify_email)) {
uint8_t ta_spc[sizeof(context->trust_anchors_spc)]; uint8_t ta_spc[sizeof(context->trust_anchors_spc)];
@ -799,15 +813,21 @@ void _getdns_context_equip_with_anchor(
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms, if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms,
(char *)xml_data, xml_len)) (char *)xml_data, xml_len))
DEBUG_ANCHOR("Failed to parse trust anchor XML data"); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed to parse trust anchor XML data\n");
else if ((ta_len = gldns_buffer_position(&gbuf)) > sizeof(ta_spc)) { else if ((ta_len = gldns_buffer_position(&gbuf)) > sizeof(ta_spc)) {
if ((ta = GETDNS_XMALLOC(context->mf, uint8_t, ta_len))) { if ((ta = GETDNS_XMALLOC(context->mf, uint8_t, ta_len))) {
gldns_buffer_init_frm_data(&gbuf, ta, gldns_buffer_init_frm_data(&gbuf, ta,
gldns_buffer_position(&gbuf)); gldns_buffer_position(&gbuf));
if (!_getdns_parse_xml_trust_anchors_buf( if (!_getdns_parse_xml_trust_anchors_buf(
&gbuf, now_ms, (char *)xml_data, xml_len)) { &gbuf, now_ms, (char *)xml_data, xml_len)) {
DEBUG_ANCHOR("Failed to re-parse trust" _getdns_log( &context->log
" anchor XML data"); , GETDNS_LOG_SYS_ANCHOR
, GETDNS_LOG_ERR
, "Error re-parsing trust "
"anchor XML data\n");
GETDNS_FREE(context->mf, ta); GETDNS_FREE(context->mf, ta);
} else { } else {
context->trust_anchors = ta; context->trust_anchors = ta;
@ -816,7 +836,11 @@ void _getdns_context_equip_with_anchor(
_getdns_ta_notify_dnsreqs(context); _getdns_ta_notify_dnsreqs(context);
} }
} else } else
DEBUG_ANCHOR("Could not allocate space for XML file"); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR
, GETDNS_LOG_ERR
, "Cannot allocate space for "
"XML file");
} else { } else {
(void)memcpy(context->trust_anchors_spc, ta_spc, ta_len); (void)memcpy(context->trust_anchors_spc, ta_spc, ta_len);
context->trust_anchors = context->trust_anchors_spc; context->trust_anchors = context->trust_anchors_spc;
@ -828,7 +852,9 @@ void _getdns_context_equip_with_anchor(
(void *)context->trust_anchors, (int)context->trust_anchors_len); (void *)context->trust_anchors, (int)context->trust_anchors_len);
} else { } else {
DEBUG_ANCHOR("Verifying trust-anchors failed!\n"); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Verifying trust-anchors XML failed!\n");
} }
if (store) X509_STORE_free(store); if (store) X509_STORE_free(store);
if (x) X509_free(x); if (x) X509_free(x);
@ -855,10 +881,8 @@ static const char tas_write_xml_p7s_buf[] =
"\r\n"; "\r\n";
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
static inline const char * rt_str(uint16_t rt) static inline const char * rt_str(uint16_t rt)
{ return rt == GETDNS_RRTYPE_A ? "A" : rt == GETDNS_RRTYPE_AAAA ? "AAAA" : "?"; } { return rt == GETDNS_RRTYPE_A ? "A" : rt == GETDNS_RRTYPE_AAAA ? "AAAA" : "?"; }
#endif
static int tas_busy(tas_connection *a) static int tas_busy(tas_connection *a)
{ {
@ -905,7 +929,8 @@ static void tas_success(getdns_context *context, tas_connection *a)
tas_cleanup(context, a); tas_cleanup(context, a);
tas_cleanup(context, other); tas_cleanup(context, other);
DEBUG_ANCHOR("Successfully fetched new trust anchors\n"); _getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "Successfully fetched new trust anchors\n");
context->trust_anchors_source = GETDNS_TASRC_XML; context->trust_anchors_source = GETDNS_TASRC_XML;
_getdns_ta_notify_dnsreqs(context); _getdns_ta_notify_dnsreqs(context);
} }
@ -913,20 +938,26 @@ static void tas_success(getdns_context *context, tas_connection *a)
static void tas_fail(getdns_context *context, tas_connection *a) static void tas_fail(getdns_context *context, tas_connection *a)
{ {
tas_connection *other = &context->a == a ? &context->aaaa : &context->a; tas_connection *other = &context->a == a ? &context->aaaa : &context->a;
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
uint16_t rt = &context->a == a ? GETDNS_RRTYPE_A : GETDNS_RRTYPE_AAAA; uint16_t rt = &context->a == a ? GETDNS_RRTYPE_A : GETDNS_RRTYPE_AAAA;
uint16_t ort = rt == GETDNS_RRTYPE_A ? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A;
#endif
tas_cleanup(context, a); tas_cleanup(context, a);
if (!tas_busy(other)) { if (!tas_busy(other)) {
DEBUG_ANCHOR("Fatal error fetching trust anchor: " _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Fatal error fetching trust anchor: "
"%s connection failed too\n", rt_str(rt)); "%s connection failed too\n", rt_str(rt));
context->trust_anchors_source = GETDNS_TASRC_FAILED; context->trust_anchors_source = GETDNS_TASRC_FAILED;
context->trust_anchors_backoff_expiry =
_getdns_get_now_ms() + context->trust_anchors_backoff_time;
_getdns_ta_notify_dnsreqs(context); _getdns_ta_notify_dnsreqs(context);
} else } else
DEBUG_ANCHOR("%s connection failed, waiting for %s\n" _getdns_log( &context->log
, rt_str(rt), rt_str(ort)); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
, "%s connection failed, waiting for %s\n"
, rt_str(rt)
, rt_str( rt == GETDNS_RRTYPE_A
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A));
} }
static void tas_connect(getdns_context *context, tas_connection *a); static void tas_connect(getdns_context *context, tas_connection *a);
@ -958,7 +989,9 @@ static void tas_timeout_cb(void *userarg)
a = &context->a; a = &context->a;
else a = &context->aaaa; else a = &context->aaaa;
DEBUG_ANCHOR("Trust anchor fetch timeout\n"); _getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
, "Trust anchor fetch timeout\n");
GETDNS_CLEAR_EVENT(a->loop, &a->event); GETDNS_CLEAR_EVENT(a->loop, &a->event);
tas_next(context, a); tas_next(context, a);
} }
@ -974,7 +1007,9 @@ static void tas_reconnect_cb(void *userarg)
a = &context->a; a = &context->a;
else a = &context->aaaa; else a = &context->aaaa;
DEBUG_ANCHOR("Waiting for second document timeout. Reconnecting...\n"); _getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "Waiting for second document timeout. Reconnecting...\n");
GETDNS_CLEAR_EVENT(a->loop, &a->event); GETDNS_CLEAR_EVENT(a->loop, &a->event);
close(a->fd); close(a->fd);
a->fd = -1; a->fd = -1;
@ -989,8 +1024,6 @@ static void tas_read_cb(void *userarg);
static void tas_write_cb(void *userarg); static void tas_write_cb(void *userarg);
static void tas_doc_read(getdns_context *context, tas_connection *a) static void tas_doc_read(getdns_context *context, tas_connection *a)
{ {
DEBUG_ANCHOR("doc (size: %d)\n", (int)a->tcp.read_buf_len);
assert(a->tcp.read_pos == a->tcp.read_buf + a->tcp.read_buf_len); assert(a->tcp.read_pos == a->tcp.read_buf + a->tcp.read_buf_len);
assert(context); assert(context);
@ -1019,18 +1052,20 @@ static void tas_doc_read(getdns_context *context, tas_connection *a)
if ((r = getdns_context_get_trust_anchors_verify_CA( if ((r = getdns_context_get_trust_anchors_verify_CA(
context, (const char **)&verify_CA.data))) context, (const char **)&verify_CA.data)))
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify" _getdns_log( &context->log
" CA: \"%s\"\n", __FUNC__ , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, getdns_get_errorstr_by_id(r)); , "Cannot get trust anchor verify CA: "
"\"%s\"\n", getdns_get_errorstr_by_id(r));
else if (!(verify_CA.size = strlen((const char *)verify_CA.data))) else if (!(verify_CA.size = strlen((const char *)verify_CA.data)))
; /* pass */ ; /* pass */
else if ((r = getdns_context_get_trust_anchors_verify_email( else if ((r = getdns_context_get_trust_anchors_verify_email(
context, &verify_email))) context, &verify_email)))
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify" _getdns_log( &context->log
" email address: \"%s\"\n", __FUNC__ , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, getdns_get_errorstr_by_id(r)); , "Cannot get trust anchor verify email: "
"\"%s\"\n", getdns_get_errorstr_by_id(r));
else if (!(tas = tas_validate(&context->mf, &a->xml, &p7s_bd, else if (!(tas = tas_validate(&context->mf, &a->xml, &p7s_bd,
&verify_CA, verify_email, &now_ms, tas, &tas_len))) &verify_CA, verify_email, &now_ms, tas, &tas_len)))
@ -1155,7 +1190,11 @@ static void tas_read_cb(void *userarg)
DEBUG_ANCHOR("i: %d, n: %d, doc_len: %d\n" DEBUG_ANCHOR("i: %d, n: %d, doc_len: %d\n"
, (int)i, (int)n, doc_len); , (int)i, (int)n, doc_len);
if (!doc) if (!doc)
DEBUG_ANCHOR("Memory error"); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR
, GETDNS_LOG_ERR
, "Memory error while reading "
"trust anchor\n");
else { else {
ssize_t surplus = n - i; ssize_t surplus = n - i;
@ -1202,7 +1241,11 @@ static void tas_read_cb(void *userarg)
} else if (_getdns_socketerror_wants_retry()) } else if (_getdns_socketerror_wants_retry())
return; return;
DEBUG_ANCHOR("Read error: %d %s\n", (int)n, _getdns_errnostr()); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Error while receiving trust anchor: %s\n"
, _getdns_errnostr());
GETDNS_CLEAR_EVENT(a->loop, &a->event); GETDNS_CLEAR_EVENT(a->loop, &a->event);
tas_next(context, a); tas_next(context, a);
} }
@ -1252,7 +1295,9 @@ static void tas_write_cb(void *userarg)
} else if (_getdns_socketerror_wants_retry()) } else if (_getdns_socketerror_wants_retry())
return; return;
DEBUG_ANCHOR("Write error: %s\n", _getdns_errnostr()); _getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Error while sending to trust anchor site: %s\n"
, _getdns_errnostr());
GETDNS_CLEAR_EVENT(a->loop, &a->event); GETDNS_CLEAR_EVENT(a->loop, &a->event);
tas_next(context, a); tas_next(context, a);
} }
@ -1291,9 +1336,7 @@ static getdns_return_t _getdns_get_tas_url_hostname(
static void tas_connect(getdns_context *context, tas_connection *a) static void tas_connect(getdns_context *context, tas_connection *a)
{ {
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
char a_buf[40]; char a_buf[40];
#endif
int r; int r;
#ifdef HAVE_FCNTL #ifdef HAVE_FCNTL
@ -1309,15 +1352,19 @@ static void tas_connect(getdns_context *context, tas_connection *a)
tas_next(context, a); tas_next(context, a);
return; return;
} }
DEBUG_ANCHOR("Initiating connection to %s\n"
, inet_ntop(( a->req->request_type == GETDNS_RRTYPE_A _getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
? AF_INET : AF_INET6) , "Setting op connection to: %s\n"
, a->rr->rr_i.rr_type + 10, a_buf, sizeof(a_buf))); , inet_ntop( ( a->req->request_type == GETDNS_RRTYPE_A
? AF_INET : AF_INET6)
, a->rr->rr_i.rr_type + 10
, a_buf, sizeof(a_buf)));
if ((a->fd = socket(( a->req->request_type == GETDNS_RRTYPE_A if ((a->fd = socket(( a->req->request_type == GETDNS_RRTYPE_A
? AF_INET : AF_INET6), SOCK_STREAM, IPPROTO_TCP)) == -1) { ? AF_INET : AF_INET6), SOCK_STREAM, IPPROTO_TCP)) == -1) {
DEBUG_ANCHOR("Error creating socket: %s\n", _getdns_log( &context->log
_getdns_errnostr()); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Error creating socket: %s\n", _getdns_errnostr());
tas_next(context, a); tas_next(context, a);
return; return;
} }
@ -1368,9 +1415,11 @@ static void tas_connect(getdns_context *context, tas_connection *a)
} }
if ((R = _getdns_get_tas_url_hostname( if ((R = _getdns_get_tas_url_hostname(
context, tas_hostname, &path))) { context, tas_hostname, &path))) {
DEBUG_ANCHOR("ERROR %s(): Could not get_tas_url_hostname" _getdns_log( &context->log
": \"%s\"", __FUNC__ , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, getdns_get_errorstr_by_id(r)); , "Cannot get hostname from trust anchor "
"url: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
goto error; goto error;
} }
hostname_len = strlen(tas_hostname); hostname_len = strlen(tas_hostname);
@ -1378,8 +1427,10 @@ static void tas_connect(getdns_context *context, tas_connection *a)
tas_hostname[--hostname_len] = '\0'; tas_hostname[--hostname_len] = '\0';
path_len = strlen(path); path_len = strlen(path);
if (path_len < 4) { if (path_len < 4) {
DEBUG_ANCHOR("ERROR %s(): path of tas_url \"%s\" too " _getdns_log( &context->log
"small\n", __FUNC__, path); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Trust anchor path \"%s\" too small\n"
, path);
goto error; goto error;
} }
if (a->state == TAS_RETRY_GET_PS7) { if (a->state == TAS_RETRY_GET_PS7) {
@ -1392,8 +1443,10 @@ static void tas_connect(getdns_context *context, tas_connection *a)
fmt = tas_write_xml_p7s_buf; fmt = tas_write_xml_p7s_buf;
} }
if (!(write_buf = GETDNS_XMALLOC(context->mf, char, buf_sz))) { if (!(write_buf = GETDNS_XMALLOC(context->mf, char, buf_sz))) {
DEBUG_ANCHOR("ERROR %s(): Could not allocate write " _getdns_log( &context->log
"buffer\n", __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Cannot allocate write buffer for "
"sending to trust anchor host\n");
goto error; goto error;
} }
if (a->state == TAS_RETRY_GET_PS7) { if (a->state == TAS_RETRY_GET_PS7) {
@ -1427,8 +1480,10 @@ static void tas_connect(getdns_context *context, tas_connection *a)
DEBUG_ANCHOR("Scheduled write with event\n"); DEBUG_ANCHOR("Scheduled write with event\n");
return; return;
} else } else
DEBUG_ANCHOR("Connect error: %s\n", _getdns_errnostr()); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Error connecting to trust anchor host: %s\n "
, _getdns_errnostr());
error: error:
tas_next(context, a); tas_next(context, a);
} }
@ -1442,7 +1497,10 @@ static void tas_happy_eyeballs_cb(void *userarg)
if (tas_fetching(&context->aaaa)) if (tas_fetching(&context->aaaa))
return; return;
else { else {
DEBUG_ANCHOR("AAAA came too late, clearing Happy Eyeballs timer\n"); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "Too late reception of AAAA for trust anchor "
"host for Happy Eyeballs\n");
GETDNS_CLEAR_EVENT(context->a.loop, &context->a.event); GETDNS_CLEAR_EVENT(context->a.loop, &context->a.event);
tas_connect(context, &context->a); tas_connect(context, &context->a);
} }
@ -1461,28 +1519,31 @@ static void _tas_hostname_lookup_cb(getdns_dns_req *dnsreq)
&a->rrset_spc, a->req->response, a->req->response_len); &a->rrset_spc, a->req->response, a->req->response_len);
if (!a->rrset) { if (!a->rrset) {
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
char tas_hostname[256] = "<no hostname>"; char tas_hostname[256] = "<no hostname>";
(void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL); (void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL);
DEBUG_ANCHOR("%s lookup for %s returned no response\n" _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "%s lookup for %s returned no response\n"
, rt_str(a->req->request_type), tas_hostname); , rt_str(a->req->request_type), tas_hostname);
#endif
} else if (a->req->response_len < dnsreq->name_len + 12 || } else if (a->req->response_len < dnsreq->name_len + 12 ||
!_getdns_dname_equal(a->req->response + 12, dnsreq->name) || !_getdns_dname_equal(a->req->response + 12, dnsreq->name) ||
a->rrset->rr_type != a->req->request_type) { a->rrset->rr_type != a->req->request_type) {
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
char tas_hostname[256] = "<no hostname>"; char tas_hostname[256] = "<no hostname>";
(void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL); (void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL);
DEBUG_ANCHOR("%s lookup for %s returned wrong response\n" _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "%s lookup for %s returned wrong response\n"
, rt_str(a->req->request_type), tas_hostname); , rt_str(a->req->request_type), tas_hostname);
#endif
} else if (!(a->rr = _getdns_rrtype_iter_init(&a->rr_spc, a->rrset))) { } else if (!(a->rr = _getdns_rrtype_iter_init(&a->rr_spc, a->rrset))) {
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
char tas_hostname[256] = "<no hostname>"; char tas_hostname[256] = "<no hostname>";
(void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL); (void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL);
DEBUG_ANCHOR("%s lookup for %s returned no addresses\n" _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "%s lookup for %s returned no addresses\n"
, rt_str(a->req->request_type), tas_hostname); , rt_str(a->req->request_type), tas_hostname);
#endif
} else { } else {
tas_connection *other = a == &context->a ? &context->aaaa tas_connection *other = a == &context->a ? &context->aaaa
: &context->a; : &context->a;
@ -1492,8 +1553,9 @@ static void _tas_hostname_lookup_cb(getdns_dns_req *dnsreq)
; /* pass */ ; /* pass */
else if (a == &context->a && tas_busy(other)) { else if (a == &context->a && tas_busy(other)) {
DEBUG_ANCHOR("Postponing connection initiation: " _getdns_log( &context->log
"Happy Eyeballs\n"); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "Waiting 25ms for AAAA to arrive\n");
GETDNS_SCHEDULE_EVENT(a->loop, a->fd, 25, GETDNS_SCHEDULE_EVENT(a->loop, a->fd, 25,
getdns_eventloop_event_init(&a->event, getdns_eventloop_event_init(&a->event,
a->req->owner, NULL, NULL, tas_happy_eyeballs_cb)); a->req->owner, NULL, NULL, tas_happy_eyeballs_cb));
@ -1510,7 +1572,8 @@ static void _tas_hostname_lookup_cb(getdns_dns_req *dnsreq)
tas_fail(context, a); tas_fail(context, a);
} }
void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop) void _getdns_start_fetching_ta(
getdns_context *context, getdns_eventloop *loop, uint64_t *now_ms)
{ {
getdns_return_t r; getdns_return_t r;
size_t scheduled; size_t scheduled;
@ -1519,38 +1582,47 @@ void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop)
const char *verify_email; const char *verify_email;
if ((r = _getdns_get_tas_url_hostname(context, tas_hostname, NULL))) { if ((r = _getdns_get_tas_url_hostname(context, tas_hostname, NULL))) {
DEBUG_ANCHOR("ERROR %s(): Could not get_tas_url_hostname" _getdns_log( &context->log
": \"%s\"", __FUNC__ , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, getdns_get_errorstr_by_id(r)); , "Cannot get hostname from trust anchor url: "
"\"%s\"\n", getdns_get_errorstr_by_id(r));
return; return;
} else if ((r = getdns_context_get_trust_anchors_verify_CA( } else if ((r = getdns_context_get_trust_anchors_verify_CA(
context, &verify_CA))) { context, &verify_CA))) {
DEBUG_ANCHOR("ERROR %s(): Could not get verify CA" _getdns_log( &context->log
": \"%s\"", __FUNC__ , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, getdns_get_errorstr_by_id(r)); , "Cannot get trust anchor verify CA: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
return; return;
} else if (!verify_CA || !*verify_CA) { } else if (!verify_CA || !*verify_CA) {
DEBUG_ANCHOR("NOTICE: Trust anchor fetching explicitely " _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "Trust anchor verification explicitly "
"disabled by empty verify CA\n"); "disabled by empty verify CA\n");
return; return;
} else if ((r = getdns_context_get_trust_anchors_verify_email( } else if ((r = getdns_context_get_trust_anchors_verify_email(
context, &verify_email))) { context, &verify_email))) {
DEBUG_ANCHOR("ERROR %s(): Could not get verify email address" _getdns_log( &context->log
": \"%s\"", __FUNC__ , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, getdns_get_errorstr_by_id(r)); , "Cannot get trust anchor verify email: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
return; return;
} else if (!verify_email || !*verify_email) { } else if (!verify_email || !*verify_email) {
DEBUG_ANCHOR("NOTICE: Trust anchor fetching explicitely " _getdns_log( &context->log
"disabled by empty verify email address\n"); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "Trust anchor verification explicitly "
"disabled by empty verify email\n");
return; return;
} else if (!_getdns_context_can_write_appdata(context)) { } else if (!_getdns_context_can_write_appdata(context)) {
DEBUG_ANCHOR("NOTICE %s(): Not fetching TA, because " _getdns_log( &context->log
"non writeable appdata directory\n", __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
, "Not fetching TA, because "
"non writeable appdata directory\n");
return; return;
} }
DEBUG_ANCHOR("Hostname: %s\n", tas_hostname); DEBUG_ANCHOR("Hostname: %s\n", tas_hostname);
@ -1558,35 +1630,44 @@ void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop)
loop == &context->sync_eventloop.loop ? "" : "a"); loop == &context->sync_eventloop.loop ? "" : "a");
scheduled = 0; scheduled = 0;
#if 1
context->a.state = TAS_LOOKUP_ADDRESSES; context->a.state = TAS_LOOKUP_ADDRESSES;
if ((r = _getdns_general_loop(context, loop, if ((r = _getdns_general_loop(context, loop,
tas_hostname, GETDNS_RRTYPE_A, tas_hostname, GETDNS_RRTYPE_A,
no_dnssec_checking_disabled_opportunistic, no_dnssec_checking_disabled_opportunistic,
context, &context->a.req, NULL, _tas_hostname_lookup_cb))) { context, &context->a.req, NULL, _tas_hostname_lookup_cb))) {
DEBUG_ANCHOR("Error scheduling A lookup for %s: %s\n" _getdns_log( &context->log
, tas_hostname, getdns_get_errorstr_by_id(r)); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
, "Error scheduling A lookup for %s: %s\n"
, tas_hostname, getdns_get_errorstr_by_id(r));
} else } else
scheduled += 1; scheduled += 1;
#endif
#if 1
context->aaaa.state = TAS_LOOKUP_ADDRESSES; context->aaaa.state = TAS_LOOKUP_ADDRESSES;
if ((r = _getdns_general_loop(context, loop, if ((r = _getdns_general_loop(context, loop,
tas_hostname, GETDNS_RRTYPE_AAAA, tas_hostname, GETDNS_RRTYPE_AAAA,
no_dnssec_checking_disabled_opportunistic, no_dnssec_checking_disabled_opportunistic,
context, &context->aaaa.req, NULL, _tas_hostname_lookup_cb))) { context, &context->aaaa.req, NULL, _tas_hostname_lookup_cb))) {
DEBUG_ANCHOR("Error scheduling AAAA lookup for %s: %s\n" _getdns_log( &context->log
, tas_hostname, getdns_get_errorstr_by_id(r)); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
, "Error scheduling AAAA lookup for %s: %s\n"
, tas_hostname, getdns_get_errorstr_by_id(r));
} else } else
scheduled += 1; scheduled += 1;
#endif
if (!scheduled) { if (!scheduled) {
DEBUG_ANCHOR("Fatal error fetching trust anchor: Unable to " _getdns_log( &context->log
"schedule address requests for %s\n" , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
, tas_hostname); , "Error scheduling address lookups for %s\n"
, tas_hostname);
context->trust_anchors_source = GETDNS_TASRC_FAILED; context->trust_anchors_source = GETDNS_TASRC_FAILED;
if (now_ms) {
if (*now_ms == 0) *now_ms = _getdns_get_now_ms();
context->trust_anchors_backoff_expiry =
*now_ms + context->trust_anchors_backoff_time;
} else
context->trust_anchors_backoff_expiry =
_getdns_get_now_ms() + context->trust_anchors_backoff_time;
_getdns_ta_notify_dnsreqs(context); _getdns_ta_notify_dnsreqs(context);
} else } else
context->trust_anchors_source = GETDNS_TASRC_FETCHING; context->trust_anchors_source = GETDNS_TASRC_FETCHING;
@ -1703,7 +1784,10 @@ static void _getdns_context_read_root_ksk(getdns_context *context)
buf_sz *= 2; buf_sz *= 2;
} }
if (!(buf = GETDNS_XMALLOC(context->mf, uint8_t, buf_sz))) { if (!(buf = GETDNS_XMALLOC(context->mf, uint8_t, buf_sz))) {
DEBUG_ANCHOR("ERROR %s(): Memory error\n", __FUNC__); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Error allocating memory to read "
"root.key\n");
break;; break;;
} }
ptr = buf; ptr = buf;
@ -1788,8 +1872,10 @@ _getdns_context_update_root_ksk(
break; break;
} }
if (str_buf != str_spc) { if (str_buf != str_spc) {
DEBUG_ANCHOR("ERROR %s(): Buffer size determination " _getdns_log( &context->log
"error\n", __FUNC__); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Error determining buffer size for root "
"KSK\n");
if (str_buf) if (str_buf)
GETDNS_FREE(context->mf, str_buf); GETDNS_FREE(context->mf, str_buf);
@ -1797,11 +1883,13 @@ _getdns_context_update_root_ksk(
} }
if (!(str_pos = str_buf = GETDNS_XMALLOC( context->mf, char, if (!(str_pos = str_buf = GETDNS_XMALLOC( context->mf, char,
(str_sz = sizeof(str_spc) - remaining) + 1))) { (str_sz = sizeof(str_spc) - remaining) + 1))) {
DEBUG_ANCHOR("ERROR %s(): Memory error\n", __FUNC__); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Error allocating memory to read "
"root KSK\n");
return; return;
} }
remaining = str_sz + 1; remaining = str_sz + 1;
DEBUG_ANCHOR("Retrying with buf size: %d\n", remaining);
}; };
/* Write presentation format DNSKEY rrset to "root.key" file */ /* Write presentation format DNSKEY rrset to "root.key" file */
@ -1876,17 +1964,21 @@ _getdns_context_update_root_ksk(
break; break;
} }
if (!ta) { if (!ta) {
DEBUG_ANCHOR("NOTICE %s(): Key with id %d " _getdns_log( &context->log
"*not* found in TA.\n" , GETDNS_LOG_SYS_ANCHOR
"\"root-anchors.xml\" need " , GETDNS_LOG_NOTICE
"updating.\n", __FUNC__ , "Key with id %d not found in TA; "
"\"root-anchors.xml\" needs to be "
"updated.\n"
, context->root_ksk.ids[i]); , context->root_ksk.ids[i]);
context->trust_anchors_source = context->trust_anchors_source =
GETDNS_TASRC_XML_UPDATE; GETDNS_TASRC_XML_UPDATE;
break; break;
} }
DEBUG_ANCHOR("DEBUG %s(): Key with id %d found in TA\n" _getdns_log( &context->log
, __FUNC__, context->root_ksk.ids[i]); , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "Key with id %d found in TA\n"
, context->root_ksk.ids[i]);
} }
} }
if (str_buf && str_buf != str_spc) if (str_buf && str_buf != str_spc)

View File

@ -41,7 +41,8 @@
void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms); void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms);
void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop); void _getdns_start_fetching_ta(
getdns_context *context, getdns_eventloop *loop, uint64_t *now_ms);
#define MAX_KSKS 16 #define MAX_KSKS 16
#define RRSIG_RDATA_LEN 16 #define RRSIG_RDATA_LEN 16

View File

@ -51,6 +51,9 @@
#else /* !__GNUC__ */ #else /* !__GNUC__ */
#define inline #define inline
#endif /* !__GNUC__ */ #endif /* !__GNUC__ */
#ifndef MAP_ANON
#define MAP_ANON MAP_ANONYMOUS
#endif
#define KEYSZ 32 #define KEYSZ 32
#define IVSZ 8 #define IVSZ 8
@ -71,6 +74,72 @@ static struct {
static inline void _rs_rekey(u_char *dat, size_t datlen); static inline void _rs_rekey(u_char *dat, size_t datlen);
/*
* Basic sanity checking; wish we could do better.
*/
static int
fallback_gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return -1;
return 0;
}
/* fallback for getentropy in case libc returns failure */
static int
fallback_getentropy_urandom(void *buf, size_t len)
{
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
# ifdef HAVE_FCNTL
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
# endif
#endif
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char*)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (fallback_gotdata(buf, len) == 0) {
errno = save_errno;
return 0; /* satisfied */
}
nodevrandom:
errno = EIO;
return -1;
}
static inline void static inline void
_rs_init(u_char *buf, size_t n) _rs_init(u_char *buf, size_t n)
{ {
@ -114,14 +183,14 @@ _rs_stir(void)
u_char rnd[KEYSZ + IVSZ]; u_char rnd[KEYSZ + IVSZ];
if (getentropy(rnd, sizeof rnd) == -1) { if (getentropy(rnd, sizeof rnd) == -1) {
if(errno != ENOSYS ||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
#ifdef SIGKILL #ifdef SIGKILL
raise(SIGKILL); raise(SIGKILL);
#else #else
#ifdef GETDNS_ON_WINDOWS exit(9); /* windows */
DebugBreak();
#endif
exit(9); /* windows */
#endif #endif
}
} }
if (!rs) if (!rs)
@ -131,9 +200,6 @@ _rs_stir(void)
explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
/* invalidate rs_buf */ /* invalidate rs_buf */
#ifdef GETDNS_ON_WINDOWS
_Analysis_assume_(rs != NULL);
#endif
rs->rs_have = 0; rs->rs_have = 0;
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
@ -145,15 +211,7 @@ _rs_stir_if_needed(size_t len)
{ {
#ifndef MAP_INHERIT_ZERO #ifndef MAP_INHERIT_ZERO
static pid_t _rs_pid = 0; static pid_t _rs_pid = 0;
#ifdef GETDNS_ON_WINDOWS
/*
* TODO: if compiling for the Windows Runtime, use GetCurrentProcessId(),
* but this requires linking with kernel32.lib
*/
pid_t pid = _getpid();
#else
pid_t pid = getpid(); pid_t pid = getpid();
#endif
/* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */ /* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */
if (_rs_pid == 0 || _rs_pid != pid) { if (_rs_pid == 0 || _rs_pid != pid) {
@ -164,9 +222,6 @@ _rs_stir_if_needed(size_t len)
#endif #endif
if (!rs || rs->rs_count <= len) if (!rs || rs->rs_count <= len)
_rs_stir(); _rs_stir();
#ifdef GETDNS_ON_WINDOWS
_Analysis_assume_(rs != NULL);
#endif
if (rs->rs_count <= len) if (rs->rs_count <= len)
rs->rs_count = 0; rs->rs_count = 0;
else else

View File

@ -39,7 +39,7 @@ arc4random_uniform(uint32_t upper_bound)
return 0; return 0;
/* 2**32 % x == (2**32 - x) % x */ /* 2**32 % x == (2**32 - x) % x */
min = ((uint32_t)(-(int32_t)upper_bound)) % upper_bound; min = -upper_bound % upper_bound;
/* /*
* This could theoretically loop forever but each retry has * This could theoretically loop forever but each retry has

View File

@ -1,4 +1,4 @@
/* $OpenBSD: getentropy_linux.c,v 1.45 2018/03/13 22:53:28 bcook Exp $ */ /* $OpenBSD: getentropy_linux.c,v 1.20 2014/07/12 15:43:49 beck Exp $ */
/* /*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org> * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
@ -15,17 +15,13 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://man.openbsd.org/getentropy.2
*/ */
#define WITH_DL_ITERATE_PHDR 1
#ifdef WITH_DL_ITERATE_PHDR
#define _GNU_SOURCE 1
/* #define _POSIX_C_SOURCE 199309L */
#endif
#include "config.h" #include "config.h"
/*
#define _POSIX_C_SOURCE 199309L
#define _GNU_SOURCE 1
*/
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -43,9 +39,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#ifdef WITH_DL_ITERATE_PHDR
#include <link.h>
#endif
#include <termios.h> #include <termios.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h> #include <signal.h>
@ -62,10 +55,14 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/sysctl.h>
#ifdef HAVE_GETAUXVAL #ifdef HAVE_GETAUXVAL
#include <sys/auxv.h> #include <sys/auxv.h>
#endif #endif
#include <sys/vfs.h> #include <sys/vfs.h>
#ifndef MAP_ANON
#define MAP_ANON MAP_ANONYMOUS
#endif
#define REPEAT 5 #define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b))
@ -81,7 +78,6 @@
#if defined(HAVE_SSL) #if defined(HAVE_SSL)
#define CRYPTO_SHA512_CTX SHA512_CTX #define CRYPTO_SHA512_CTX SHA512_CTX
#define CRYPTO_SHA512_INIT(x) SHA512_Init(x) #define CRYPTO_SHA512_INIT(x) SHA512_Init(x)
#define CRYPTO_SHA512_UPDATE(c, x, l) (SHA512_Update((c), (char *)(x), (l)))
#define CRYPTO_SHA512_FINAL(r, c) SHA512_Final(r, c) #define CRYPTO_SHA512_FINAL(r, c) SHA512_Final(r, c)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) #define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
@ -89,7 +85,6 @@
#elif defined(HAVE_NETTLE) #elif defined(HAVE_NETTLE)
#define CRYPTO_SHA512_CTX struct sha512_ctx #define CRYPTO_SHA512_CTX struct sha512_ctx
#define CRYPTO_SHA512_INIT(x) sha512_init(x) #define CRYPTO_SHA512_INIT(x) sha512_init(x)
#define CRYPTO_SHA512_UPDATE(c, x, l) (sha512_update((c), (l), (uint8_t *)(x)))
#define CRYPTO_SHA512_FINAL(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r) #define CRYPTO_SHA512_FINAL(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
#define HR(x, l) (sha512_update(&ctx, (l), (uint8_t *)(x))) #define HR(x, l) (sha512_update(&ctx, (l), (uint8_t *)(x)))
#define HD(x) (sha512_update(&ctx, sizeof (x), (uint8_t *)&(x))) #define HD(x) (sha512_update(&ctx, sizeof (x), (uint8_t *)&(x)))
@ -98,8 +93,11 @@
int getentropy(void *buf, size_t len); int getentropy(void *buf, size_t len);
#ifdef CAN_REFERENCE_MAIN
extern int main(int, char *argv[]);
#endif
static int gotdata(char *buf, size_t len); static int gotdata(char *buf, size_t len);
#if defined(SYS_getrandom) && defined(GRND_NONBLOCK) #if defined(SYS_getrandom) && defined(__NR_getrandom)
static int getentropy_getrandom(void *buf, size_t len); static int getentropy_getrandom(void *buf, size_t len);
#endif #endif
static int getentropy_urandom(void *buf, size_t len); static int getentropy_urandom(void *buf, size_t len);
@ -107,9 +105,6 @@ static int getentropy_urandom(void *buf, size_t len);
static int getentropy_sysctl(void *buf, size_t len); static int getentropy_sysctl(void *buf, size_t len);
#endif #endif
static int getentropy_fallback(void *buf, size_t len); static int getentropy_fallback(void *buf, size_t len);
#ifdef WITH_DL_ITERATE_PHDR
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
#endif
int int
getentropy(void *buf, size_t len) getentropy(void *buf, size_t len)
@ -118,21 +113,18 @@ getentropy(void *buf, size_t len)
if (len > 256) { if (len > 256) {
errno = EIO; errno = EIO;
return (-1); return -1;
} }
#if defined(SYS_getrandom) && defined(GRND_NONBLOCK) #if defined(SYS_getrandom) && defined(__NR_getrandom)
/* /*
* Try descriptor-less getrandom(), in non-blocking mode. * Try descriptor-less getrandom()
*
* The design of Linux getrandom is broken. It has an
* uninitialized phase coupled with blocking behaviour, which
* is unacceptable from within a library at boot time without
* possible recovery. See http://bugs.python.org/issue26839#msg267745
*/ */
ret = getentropy_getrandom(buf, len); ret = getentropy_getrandom(buf, len);
if (ret != -1) if (ret != -1)
return (ret); return (ret);
if (errno != ENOSYS)
return (-1);
#endif #endif
/* /*
@ -186,7 +178,7 @@ getentropy(void *buf, size_t len)
* - Do the best under the circumstances.... * - Do the best under the circumstances....
* *
* This code path exists to bring light to the issue that Linux * This code path exists to bring light to the issue that Linux
* still does not provide a failsafe API for entropy collection. * does not provide a failsafe API for entropy collection.
* *
* We hope this demonstrates that Linux should either retain their * We hope this demonstrates that Linux should either retain their
* sysctl ABI, or consider providing a new failsafe API which * sysctl ABI, or consider providing a new failsafe API which
@ -216,11 +208,11 @@ gotdata(char *buf, size_t len)
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
any_set |= buf[i]; any_set |= buf[i];
if (any_set == 0) if (any_set == 0)
return (-1); return -1;
return (0); return 0;
} }
#if defined(SYS_getrandom) && defined(GRND_NONBLOCK) #if defined(SYS_getrandom) && defined(__NR_getrandom)
static int static int
getentropy_getrandom(void *buf, size_t len) getentropy_getrandom(void *buf, size_t len)
{ {
@ -229,7 +221,7 @@ getentropy_getrandom(void *buf, size_t len)
if (len > 256) if (len > 256)
return (-1); return (-1);
do { do {
ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK); ret = syscall(SYS_getrandom, buf, len, 0);
} while (ret == -1 && errno == EINTR); } while (ret == -1 && errno == EINTR);
if (ret != (int)len) if (ret != (int)len)
@ -277,7 +269,7 @@ start:
} }
for (i = 0; i < len; ) { for (i = 0; i < len; ) {
size_t wanted = len - i; size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted); ssize_t ret = read(fd, (char*)buf + i, wanted);
if (ret == -1) { if (ret == -1) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
@ -290,11 +282,11 @@ start:
close(fd); close(fd);
if (gotdata(buf, len) == 0) { if (gotdata(buf, len) == 0) {
errno = save_errno; errno = save_errno;
return (0); /* satisfied */ return 0; /* satisfied */
} }
nodevrandom: nodevrandom:
errno = EIO; errno = EIO;
return (-1); return -1;
} }
#ifdef SYS__sysctl #ifdef SYS__sysctl
@ -325,11 +317,11 @@ getentropy_sysctl(void *buf, size_t len)
} }
sysctlfailed: sysctlfailed:
errno = EIO; errno = EIO;
return (-1); return -1;
} }
#endif /* SYS__sysctl */ #endif /* SYS__sysctl */
static const int cl[] = { static int cl[] = {
CLOCK_REALTIME, CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC #ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC, CLOCK_MONOTONIC,
@ -354,18 +346,6 @@ static const int cl[] = {
#endif #endif
}; };
#ifdef WITH_DL_ITERATE_PHDR
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
CRYPTO_SHA512_CTX *ctx = data;
(void)size;
CRYPTO_SHA512_UPDATE(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
#endif
static int static int
getentropy_fallback(void *buf, size_t len) getentropy_fallback(void *buf, size_t len)
{ {
@ -402,10 +382,6 @@ getentropy_fallback(void *buf, size_t len)
cnt += (int)tv.tv_usec; cnt += (int)tv.tv_usec;
} }
#ifdef WITH_DL_ITERATE_PHDR
dl_iterate_phdr(getentropy_phdr, &ctx);
#endif
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts); HX(clock_gettime(cl[ii], &ts) == -1, ts);
@ -425,6 +401,9 @@ getentropy_fallback(void *buf, size_t len)
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset); sigset);
#ifdef CAN_REFERENCE_MAIN
HF(main); /* an addr in program */
#endif
HF(getentropy); /* an addr in this library */ HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */ HF(printf); /* an addr in libc */
p = (char *)&p; p = (char *)&p;
@ -549,34 +528,33 @@ getentropy_fallback(void *buf, size_t len)
HD(cnt); HD(cnt);
} }
#ifdef HAVE_GETAUXVAL #ifdef HAVE_GETAUXVAL
#ifdef AT_RANDOM # ifdef AT_RANDOM
/* Not as random as you think but we take what we are given */ /* Not as random as you think but we take what we are given */
p = (char *) getauxval(AT_RANDOM); p = (char *) getauxval(AT_RANDOM);
if (p) if (p)
HR(p, 16); HR(p, 16);
#endif # endif
#ifdef AT_SYSINFO_EHDR # ifdef AT_SYSINFO_EHDR
p = (char *) getauxval(AT_SYSINFO_EHDR); p = (char *) getauxval(AT_SYSINFO_EHDR);
if (p) if (p)
HR(p, pgs); HR(p, pgs);
#endif # endif
#ifdef AT_BASE # ifdef AT_BASE
p = (char *) getauxval(AT_BASE); p = (char *) getauxval(AT_BASE);
if (p) if (p)
HD(p); HD(p);
#endif # endif
#endif #endif /* HAVE_GETAUXVAL */
CRYPTO_SHA512_FINAL(results, &ctx); CRYPTO_SHA512_FINAL(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i)); memcpy((char*)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i); i += min(sizeof(results), len - i);
} }
memset(&ctx, 0, sizeof ctx);
memset(results, 0, sizeof results); memset(results, 0, sizeof results);
if (gotdata(buf, len) == 0) { if (gotdata(buf, len) == 0) {
errno = save_errno; errno = save_errno;
return (0); /* satisfied */ return 0; /* satisfied */
} }
errno = EIO; errno = EIO;
return (-1); return -1;
} }

View File

@ -93,6 +93,10 @@ static struct const_info consts_info[] = {
{ 632, "GETDNS_CONTEXT_CODE_TLS_CA_FILE", GETDNS_CONTEXT_CODE_TLS_CA_FILE_TEXT }, { 632, "GETDNS_CONTEXT_CODE_TLS_CA_FILE", GETDNS_CONTEXT_CODE_TLS_CA_FILE_TEXT },
{ 633, "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT }, { 633, "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT },
{ 634, "GETDNS_CONTEXT_CODE_TLS_CURVES_LIST", GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT }, { 634, "GETDNS_CONTEXT_CODE_TLS_CURVES_LIST", GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT },
{ 635, "GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES", GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES_TEXT },
{ 636, "GETDNS_CONTEXT_CODE_TLS_MIN_VERSION", GETDNS_CONTEXT_CODE_TLS_MIN_VERSION_TEXT },
{ 637, "GETDNS_CONTEXT_CODE_TLS_MAX_VERSION", GETDNS_CONTEXT_CODE_TLS_MAX_VERSION_TEXT },
{ 638, "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME", GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME_TEXT },
{ 699, "GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE", GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE_TEXT }, { 699, "GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE", GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE_TEXT },
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT }, { 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT }, { 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
@ -115,7 +119,16 @@ static struct const_info consts_info[] = {
{ 1202, "GETDNS_TRANSPORT_TLS", GETDNS_TRANSPORT_TLS_TEXT }, { 1202, "GETDNS_TRANSPORT_TLS", GETDNS_TRANSPORT_TLS_TEXT },
{ 1300, "GETDNS_AUTHENTICATION_NONE", GETDNS_AUTHENTICATION_NONE_TEXT }, { 1300, "GETDNS_AUTHENTICATION_NONE", GETDNS_AUTHENTICATION_NONE_TEXT },
{ 1301, "GETDNS_AUTHENTICATION_REQUIRED", GETDNS_AUTHENTICATION_REQUIRED_TEXT }, { 1301, "GETDNS_AUTHENTICATION_REQUIRED", GETDNS_AUTHENTICATION_REQUIRED_TEXT },
{ 4096, "GETDNS_LOG_UPSTREAM_STATS", GETDNS_LOG_UPSTREAM_STATS_TEXT }, { 1400, "GETDNS_SSL3", GETDNS_SSL3_TEXT },
{ 1401, "GETDNS_TLS1", GETDNS_TLS1_TEXT },
{ 1402, "GETDNS_TLS1_1", GETDNS_TLS1_1_TEXT },
{ 1403, "GETDNS_TLS1_2", GETDNS_TLS1_2_TEXT },
{ 1404, "GETDNS_TLS1_3", GETDNS_TLS1_3_TEXT },
{ 8192, "GETDNS_LOG_SYS_STUB", GETDNS_LOG_SYS_STUB_TEXT },
{ 12288, "GETDNS_LOG_UPSTREAM_STATS", GETDNS_LOG_UPSTREAM_STATS_TEXT },
{ 16384, "GETDNS_LOG_SYS_RECURSING", GETDNS_LOG_SYS_RECURSING_TEXT },
{ 24576, "GETDNS_LOG_SYS_RESOLVING", GETDNS_LOG_SYS_RESOLVING_TEXT },
{ 32768, "GETDNS_LOG_SYS_ANCHOR", GETDNS_LOG_SYS_ANCHOR_TEXT },
}; };
static int const_info_cmp(const void *a, const void *b) static int const_info_cmp(const void *a, const void *b)
@ -190,10 +203,14 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 }, { "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 },
{ "GETDNS_CONTEXT_CODE_TLS_CA_FILE", 632 }, { "GETDNS_CONTEXT_CODE_TLS_CA_FILE", 632 },
{ "GETDNS_CONTEXT_CODE_TLS_CA_PATH", 631 }, { "GETDNS_CONTEXT_CODE_TLS_CA_PATH", 631 },
{ "GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES", 635 },
{ "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", 633 }, { "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", 633 },
{ "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 }, { "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 },
{ "GETDNS_CONTEXT_CODE_TLS_CURVES_LIST", 634 }, { "GETDNS_CONTEXT_CODE_TLS_CURVES_LIST", 634 },
{ "GETDNS_CONTEXT_CODE_TLS_MAX_VERSION", 637 },
{ "GETDNS_CONTEXT_CODE_TLS_MIN_VERSION", 636 },
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 }, { "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME", 638 },
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", 625 }, { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", 625 },
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA", 626 }, { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA", 626 },
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL", 627 }, { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL", 627 },
@ -212,7 +229,11 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_LOG_ERR", 3 }, { "GETDNS_LOG_ERR", 3 },
{ "GETDNS_LOG_INFO", 6 }, { "GETDNS_LOG_INFO", 6 },
{ "GETDNS_LOG_NOTICE", 5 }, { "GETDNS_LOG_NOTICE", 5 },
{ "GETDNS_LOG_UPSTREAM_STATS", 4096 }, { "GETDNS_LOG_SYS_ANCHOR", 32768 },
{ "GETDNS_LOG_SYS_RECURSING", 16384 },
{ "GETDNS_LOG_SYS_RESOLVING", 24576 },
{ "GETDNS_LOG_SYS_STUB", 8192 },
{ "GETDNS_LOG_UPSTREAM_STATS", 12288 },
{ "GETDNS_LOG_WARNING", 4 }, { "GETDNS_LOG_WARNING", 4 },
{ "GETDNS_NAMESPACE_DNS", 500 }, { "GETDNS_NAMESPACE_DNS", 500 },
{ "GETDNS_NAMESPACE_LOCALNAMES", 501 }, { "GETDNS_NAMESPACE_LOCALNAMES", 501 },
@ -279,6 +300,7 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_RRCLASS_IN", 1 }, { "GETDNS_RRCLASS_IN", 1 },
{ "GETDNS_RRCLASS_NONE", 254 }, { "GETDNS_RRCLASS_NONE", 254 },
{ "GETDNS_RRTYPE_A", 1 }, { "GETDNS_RRTYPE_A", 1 },
{ "GETDNS_RRTYPE_A6", 38 },
{ "GETDNS_RRTYPE_AAAA", 28 }, { "GETDNS_RRTYPE_AAAA", 28 },
{ "GETDNS_RRTYPE_AFSDB", 18 }, { "GETDNS_RRTYPE_AFSDB", 18 },
{ "GETDNS_RRTYPE_ANY", 255 }, { "GETDNS_RRTYPE_ANY", 255 },
@ -299,6 +321,8 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_RRTYPE_DOA", 259 }, { "GETDNS_RRTYPE_DOA", 259 },
{ "GETDNS_RRTYPE_DS", 43 }, { "GETDNS_RRTYPE_DS", 43 },
{ "GETDNS_RRTYPE_EID", 31 }, { "GETDNS_RRTYPE_EID", 31 },
{ "GETDNS_RRTYPE_EUI48", 108 },
{ "GETDNS_RRTYPE_EUI64", 109 },
{ "GETDNS_RRTYPE_GID", 102 }, { "GETDNS_RRTYPE_GID", 102 },
{ "GETDNS_RRTYPE_GPOS", 27 }, { "GETDNS_RRTYPE_GPOS", 27 },
{ "GETDNS_RRTYPE_HINFO", 13 }, { "GETDNS_RRTYPE_HINFO", 13 },
@ -308,6 +332,8 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_RRTYPE_IXFR", 251 }, { "GETDNS_RRTYPE_IXFR", 251 },
{ "GETDNS_RRTYPE_KEY", 25 }, { "GETDNS_RRTYPE_KEY", 25 },
{ "GETDNS_RRTYPE_KX", 36 }, { "GETDNS_RRTYPE_KX", 36 },
{ "GETDNS_RRTYPE_L32", 105 },
{ "GETDNS_RRTYPE_L64", 106 },
{ "GETDNS_RRTYPE_LOC", 29 }, { "GETDNS_RRTYPE_LOC", 29 },
{ "GETDNS_RRTYPE_LP", 107 }, { "GETDNS_RRTYPE_LP", 107 },
{ "GETDNS_RRTYPE_MAILA", 254 }, { "GETDNS_RRTYPE_MAILA", 254 },
@ -327,6 +353,8 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_RRTYPE_NSAP", 22 }, { "GETDNS_RRTYPE_NSAP", 22 },
{ "GETDNS_RRTYPE_NSAP_PTR", 23 }, { "GETDNS_RRTYPE_NSAP_PTR", 23 },
{ "GETDNS_RRTYPE_NSEC", 47 }, { "GETDNS_RRTYPE_NSEC", 47 },
{ "GETDNS_RRTYPE_NSEC3", 50 },
{ "GETDNS_RRTYPE_NSEC3PARAM", 51 },
{ "GETDNS_RRTYPE_NULL", 10 }, { "GETDNS_RRTYPE_NULL", 10 },
{ "GETDNS_RRTYPE_NXT", 30 }, { "GETDNS_RRTYPE_NXT", 30 },
{ "GETDNS_RRTYPE_OPENPGPKEY", 61 }, { "GETDNS_RRTYPE_OPENPGPKEY", 61 },
@ -355,6 +383,13 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_RRTYPE_UNSPEC", 103 }, { "GETDNS_RRTYPE_UNSPEC", 103 },
{ "GETDNS_RRTYPE_URI", 256 }, { "GETDNS_RRTYPE_URI", 256 },
{ "GETDNS_RRTYPE_WKS", 11 }, { "GETDNS_RRTYPE_WKS", 11 },
{ "GETDNS_RRTYPE_X25", 19 },
{ "GETDNS_RRTYPE_ZONEMD", 63 },
{ "GETDNS_SSL3", 1400 },
{ "GETDNS_TLS1", 1401 },
{ "GETDNS_TLS1_1", 1402 },
{ "GETDNS_TLS1_2", 1403 },
{ "GETDNS_TLS1_3", 1404 },
{ "GETDNS_TRANSPORT_TCP", 1201 }, { "GETDNS_TRANSPORT_TCP", 1201 },
{ "GETDNS_TRANSPORT_TCP_ONLY", 542 }, { "GETDNS_TRANSPORT_TCP_ONLY", 542 },
{ "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", 543 }, { "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", 543 },

File diff suppressed because it is too large Load Diff

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;
@ -200,15 +200,21 @@ typedef struct getdns_upstream {
getdns_network_req *write_queue_last; getdns_network_req *write_queue_last;
_getdns_rbtree_t netreq_by_query_id; _getdns_rbtree_t netreq_by_query_id;
/* TLS specific connection handling*/ /* TLS specific connection handling */
SSL* tls_obj; SSL* tls_obj;
SSL_SESSION* tls_session; SSL_SESSION* tls_session;
getdns_tls_hs_state_t tls_hs_state; getdns_tls_hs_state_t tls_hs_state;
getdns_auth_state_t tls_auth_state; getdns_auth_state_t tls_auth_state;
unsigned tls_fallback_ok : 1; unsigned tls_fallback_ok : 1;
/* TLS settings */
char *tls_cipher_list; char *tls_cipher_list;
char *tls_ciphersuites;
char *tls_curves_list; char *tls_curves_list;
/* Auth credentials*/ getdns_tls_version_t tls_min_version;
getdns_tls_version_t tls_max_version;
/* Auth credentials */
char tls_auth_name[256]; char tls_auth_name[256];
sha256_pin_t *tls_pubkey_pinset; sha256_pin_t *tls_pubkey_pinset;
@ -263,7 +269,7 @@ typedef struct getdns_upstreams {
size_t count; size_t count;
size_t current_udp; size_t current_udp;
size_t current_stateful; size_t current_stateful;
uint16_t max_backoff_value; uint16_t max_backoff_value;
uint16_t tls_backoff_time; uint16_t tls_backoff_time;
uint16_t tls_connection_retries; uint16_t tls_connection_retries;
getdns_log_config log; getdns_log_config log;
@ -341,6 +347,8 @@ struct getdns_context {
char *trust_anchors_url; char *trust_anchors_url;
char *trust_anchors_verify_CA; char *trust_anchors_verify_CA;
char *trust_anchors_verify_email; char *trust_anchors_verify_email;
uint64_t trust_anchors_backoff_time;
uint64_t trust_anchors_backoff_expiry;
_getdns_ksks root_ksk; _getdns_ksks root_ksk;
@ -350,7 +358,10 @@ struct getdns_context {
char *tls_ca_path; char *tls_ca_path;
char *tls_ca_file; char *tls_ca_file;
char *tls_cipher_list; char *tls_cipher_list;
char *tls_ciphersuites;
char *tls_curves_list; char *tls_curves_list;
getdns_tls_version_t tls_min_version;
getdns_tls_version_t tls_max_version;
getdns_upstreams *upstreams; getdns_upstreams *upstreams;
uint16_t limit_outstanding_queries; uint16_t limit_outstanding_queries;
@ -358,7 +369,7 @@ struct getdns_context {
getdns_tls_authentication_t tls_auth; /* What user requested for TLS*/ getdns_tls_authentication_t tls_auth; /* What user requested for TLS*/
getdns_tls_authentication_t tls_auth_min; /* Derived minimum auth allowed*/ getdns_tls_authentication_t tls_auth_min; /* Derived minimum auth allowed*/
uint8_t round_robin_upstreams; uint8_t round_robin_upstreams;
uint16_t max_backoff_value; uint16_t max_backoff_value;
uint16_t tls_backoff_time; uint16_t tls_backoff_time;
uint16_t tls_connection_retries; uint16_t tls_connection_retries;
@ -433,6 +444,7 @@ struct getdns_context {
getdns_dict *header; getdns_dict *header;
getdns_dict *add_opt_parameters; getdns_dict *add_opt_parameters;
unsigned add_warning_for_bad_dns : 1; unsigned add_warning_for_bad_dns : 1;
unsigned dnssec : 1;
unsigned dnssec_return_all_statuses : 1; unsigned dnssec_return_all_statuses : 1;
unsigned dnssec_return_full_validation_chain : 1; unsigned dnssec_return_full_validation_chain : 1;
unsigned dnssec_return_only_secure : 1; unsigned dnssec_return_only_secure : 1;
@ -490,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 **/
@ -551,8 +590,9 @@ void _getdns_upstreams_dereference(getdns_upstreams *upstreams);
void _getdns_upstream_shutdown(getdns_upstream *upstream); void _getdns_upstream_shutdown(getdns_upstream *upstream);
FILE *_getdns_context_get_priv_fp(getdns_context *context, const char *fn); FILE *_getdns_context_get_priv_fp(
uint8_t *_getdns_context_get_priv_file(getdns_context *context, const getdns_context *context, const char *fn);
uint8_t *_getdns_context_get_priv_file(const getdns_context *context,
const char *fn, uint8_t *buf, size_t buf_len, size_t *file_sz); const char *fn, uint8_t *buf, size_t buf_len, size_t *file_sz);
int _getdns_context_write_priv_file(getdns_context *context, int _getdns_context_write_priv_file(getdns_context *context,

View File

@ -434,7 +434,7 @@ getdns_dict_create_with_memory_functions(void *(*malloc)(size_t),
/*-------------------------- getdns_dict_create_with_context */ /*-------------------------- getdns_dict_create_with_context */
struct getdns_dict * struct getdns_dict *
getdns_dict_create_with_context(struct getdns_context *context) getdns_dict_create_with_context(const getdns_context *context)
{ {
if (context) if (context)
return getdns_dict_create_with_extended_memory_functions( return getdns_dict_create_with_extended_memory_functions(
@ -655,7 +655,8 @@ getdns_dict_set_bindata(
/*---------------------------------------- getdns_dict_set_bindata */ /*---------------------------------------- getdns_dict_set_bindata */
getdns_return_t getdns_return_t
getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value) getdns_dict_util_set_string(getdns_dict *dict,
const char *name, const char *value)
{ {
getdns_item *item; getdns_item *item;
getdns_bindata *newbindata; getdns_bindata *newbindata;
@ -1078,9 +1079,12 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent,
strcmp(item->node.key, "transport") == 0 || strcmp(item->node.key, "transport") == 0 ||
strcmp(item->node.key, "resolution_type") == 0 || strcmp(item->node.key, "resolution_type") == 0 ||
strcmp(item->node.key, "tls_authentication") == 0 || strcmp(item->node.key, "tls_authentication") == 0 ||
strcmp(item->node.key, "tls_min_version") == 0 ||
strcmp(item->node.key, "tls_max_version") == 0 ||
/* extensions */ /* extensions */
strcmp(item->node.key, "add_warning_for_bad_dns") == 0 || strcmp(item->node.key, "add_warning_for_bad_dns") == 0 ||
strcmp(item->node.key, "dnssec") == 0 ||
strcmp(item->node.key, "dnssec_return_all_statuses") == 0 || strcmp(item->node.key, "dnssec_return_all_statuses") == 0 ||
strcmp(item->node.key, "dnssec_return_full_validation_chain") == 0 || strcmp(item->node.key, "dnssec_return_full_validation_chain") == 0 ||
strcmp(item->node.key, "dnssec_return_only_secure") == 0 || strcmp(item->node.key, "dnssec_return_only_secure") == 0 ||

View File

@ -178,7 +178,7 @@
* "DNSSEC Validation". * "DNSSEC Validation".
* *
* Many functions are of key verification boolean return type; e.g. * Many functions are of key verification boolean return type; e.g.
* key_proves_non_existance(), ds_authenticates_keys(), a_key_signed_rrset() * key_proves_nonexistance(), ds_authenticates_keys(), a_key_signed_rrset()
* These will return the keytag identifying the key that was used to * These will return the keytag identifying the key that was used to
* authenticate + 0x10000 to allow keytag 0. * authenticate + 0x10000 to allow keytag 0.
* *
@ -523,7 +523,7 @@ static void val_chain_sched(chain_head *head, const uint8_t *dname);
static void val_chain_sched_ds(chain_head *head, const uint8_t *dname); static void val_chain_sched_ds(chain_head *head, const uint8_t *dname);
static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig); static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig);
static chain_head *add_rrset2val_chain(struct mem_funcs *mf, static chain_head *add_rrset2val_chain(const struct mem_funcs *mf,
chain_head **chain_p, _getdns_rrset *rrset, getdns_network_req *netreq) chain_head **chain_p, _getdns_rrset *rrset, getdns_network_req *netreq)
{ {
chain_head *head; chain_head *head;
@ -671,8 +671,18 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
/* On the first chain, max_node == NULL. /* On the first chain, max_node == NULL.
* Schedule a root DNSKEY query, we always need that. * Schedule a root DNSKEY query, we always need that.
*/ */
if (!(node[-1].parent = max_node)) { if (!(node[-1].parent = max_node))
val_chain_sched(head, (uint8_t *)"\0"); val_chain_sched(head, (uint8_t *)"\0");
/* For an NSEC or NSEC3 query, stop at that. If it is valid it will
* have a signature which will be chased.
*/
if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC ||
head->rrset.rr_type == GETDNS_RRTYPE_NSEC3)
return head;
/* Otherwise, schedule key lookups for the tld and sld too. */
if (!max_node) {
if (head->node_count > 1) if (head->node_count > 1)
val_chain_sched(head, node[-2].ds.name); val_chain_sched(head, node[-2].ds.name);
if (head->node_count > 2) if (head->node_count > 2)
@ -778,7 +788,7 @@ static int is_synthesized_cname(_getdns_rrset *cname)
* When a SOA query was successful, a query for DS will follow for that * When a SOA query was successful, a query for DS will follow for that
* owner name. * owner name.
*/ */
static void add_pkt2val_chain(struct mem_funcs *mf, static void add_pkt2val_chain(const struct mem_funcs *mf,
chain_head **chain_p, uint8_t *pkt, size_t pkt_len, chain_head **chain_p, uint8_t *pkt, size_t pkt_len,
getdns_network_req *netreq) getdns_network_req *netreq)
{ {
@ -840,7 +850,7 @@ static void add_pkt2val_chain(struct mem_funcs *mf,
* checked eventually. * checked eventually.
* But only if we know the question of course... * But only if we know the question of course...
*/ */
static void add_question2val_chain(struct mem_funcs *mf, static void add_question2val_chain(const struct mem_funcs *mf,
chain_head **chain_p, uint8_t *pkt, size_t pkt_len, chain_head **chain_p, uint8_t *pkt, size_t pkt_len,
const uint8_t *qname, uint16_t qtype, uint16_t qclass, const uint8_t *qname, uint16_t qtype, uint16_t qclass,
getdns_network_req *netreq) getdns_network_req *netreq)
@ -1354,8 +1364,9 @@ static int _rr_iter_rdata_cmp(const void *a, const void *b)
* nc_name will be set to the next closer (within rrset->name). * nc_name will be set to the next closer (within rrset->name).
*/ */
#define VAL_RRSET_SPC_SZ 256 #define VAL_RRSET_SPC_SZ 256
static int _getdns_verify_rrsig(struct mem_funcs *mf, static int _getdns_verify_rrsig(const struct mem_funcs *mf,
_getdns_rrset *rrset, _getdns_rrsig_iter *rrsig, _getdns_rrtype_iter *key, const uint8_t **nc_name) _getdns_rrset *rrset, _getdns_rrsig_iter *rrsig, _getdns_rrtype_iter *key,
const uint8_t **nc_name)
{ {
int r; int r;
int to_skip; int to_skip;
@ -1673,8 +1684,9 @@ static int check_dates(time_t now, int32_t skew, int32_t exp, int32_t inc)
/* Returns whether dnskey signed rrset. If the rrset was a valid wildcard /* Returns whether dnskey signed rrset. If the rrset was a valid wildcard
* expansion, nc_name will point to the next closer part of the name in rrset. * expansion, nc_name will point to the next closer part of the name in rrset.
*/ */
static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew, static int dnskey_signed_rrset(const struct mem_funcs *mf, time_t now,
_getdns_rrtype_iter *dnskey, _getdns_rrset *rrset, const uint8_t **nc_name) uint32_t skew, _getdns_rrtype_iter *dnskey, _getdns_rrset *rrset,
const uint8_t **nc_name)
{ {
_getdns_rrsig_iter rrsig_spc, *rrsig; _getdns_rrsig_iter rrsig_spc, *rrsig;
_getdns_rdf_iter rdf_spc, *rdf; _getdns_rdf_iter rdf_spc, *rdf;
@ -1742,7 +1754,7 @@ static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
} }
/* Returns whether a dnskey for keyset signed a non wildcard rrset. */ /* Returns whether a dnskey for keyset signed a non wildcard rrset. */
static int a_key_signed_rrset_no_wc(struct mem_funcs *mf, time_t now, static int a_key_signed_rrset_no_wc(const struct mem_funcs *mf, time_t now,
uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset) uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset)
{ {
_getdns_rrtype_iter dnskey_spc, *dnskey; _getdns_rrtype_iter dnskey_spc, *dnskey;
@ -1770,13 +1782,13 @@ static int a_key_signed_rrset_no_wc(struct mem_funcs *mf, time_t now,
return 0; return 0;
} }
static int find_nsec_covering_name( static int find_nsec_covering_name(const struct mem_funcs *mf,
struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey, time_t now, uint32_t skew, _getdns_rrset *dnskey,
_getdns_rrset *rrset, const uint8_t *name, int *opt_out); _getdns_rrset *rrset, const uint8_t *name, int *opt_out);
/* Returns whether a dnskey for keyset signed rrset. */ /* Returns whether a dnskey for keyset signed rrset. */
static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew, static int a_key_signed_rrset(const struct mem_funcs *mf, time_t now,
_getdns_rrset *keyset, _getdns_rrset *rrset) uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset)
{ {
_getdns_rrtype_iter dnskey_spc, *dnskey; _getdns_rrtype_iter dnskey_spc, *dnskey;
const uint8_t *nc_name; /* Initialized by dnskey_signed_rrset() */ const uint8_t *nc_name; /* Initialized by dnskey_signed_rrset() */
@ -1817,7 +1829,7 @@ static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
/* Returns whether a DS in ds_set matches a dnskey in dnskey_set which in turn /* Returns whether a DS in ds_set matches a dnskey in dnskey_set which in turn
* signed the dnskey set. * signed the dnskey set.
*/ */
static int ds_authenticates_keys(struct mem_funcs *mf, static int ds_authenticates_keys(const struct mem_funcs *mf,
time_t now, uint32_t skew, _getdns_rrset *ds_set, _getdns_rrset *dnskey_set) time_t now, uint32_t skew, _getdns_rrset *ds_set, _getdns_rrset *dnskey_set)
{ {
_getdns_rrtype_iter dnskey_spc, *dnskey; _getdns_rrtype_iter dnskey_spc, *dnskey;
@ -2102,8 +2114,8 @@ static int nsec3_covers_name(
} }
} }
static int find_nsec_covering_name( static int find_nsec_covering_name(const struct mem_funcs *mf, time_t now,
struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey, uint32_t skew, _getdns_rrset *dnskey,
_getdns_rrset *rrset, const uint8_t *name, int *opt_out) _getdns_rrset *rrset, const uint8_t *name, int *opt_out)
{ {
_getdns_rrset_iter i_spc, *i; _getdns_rrset_iter i_spc, *i;
@ -2205,7 +2217,7 @@ static int find_nsec_covering_name(
} }
static int nsec3_find_next_closer( static int nsec3_find_next_closer(
struct mem_funcs *mf, time_t now, uint32_t skew, const struct mem_funcs *mf, time_t now, uint32_t skew,
_getdns_rrset *dnskey, _getdns_rrset *rrset, _getdns_rrset *dnskey, _getdns_rrset *rrset,
const uint8_t *nc_name, int *opt_out) const uint8_t *nc_name, int *opt_out)
{ {
@ -2257,7 +2269,7 @@ static int nsec3_find_next_closer(
* verifying key: it returns keytag + NSEC3_ITERATION_COUNT_HIGH (0x20000) * verifying key: it returns keytag + NSEC3_ITERATION_COUNT_HIGH (0x20000)
*/ */
static int key_proves_nonexistance( static int key_proves_nonexistance(
struct mem_funcs *mf, time_t now, uint32_t skew, const struct mem_funcs *mf, time_t now, uint32_t skew,
_getdns_rrset *keyset, _getdns_rrset *rrset, int *opt_out) _getdns_rrset *keyset, _getdns_rrset *rrset, int *opt_out)
{ {
_getdns_rrset nsec_rrset, *cover, *ce; _getdns_rrset nsec_rrset, *cover, *ce;
@ -2270,6 +2282,7 @@ static int key_proves_nonexistance(
assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY); assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
debug_sec_print_rrset("Commencing NX proof for: ", rrset);
if (opt_out) if (opt_out)
*opt_out = 0; *opt_out = 0;
@ -2319,6 +2332,14 @@ static int key_proves_nonexistance(
&& (keytag = a_key_signed_rrset_no_wc( && (keytag = a_key_signed_rrset_no_wc(
mf, now, skew, keyset, &nsec_rrset))) { mf, now, skew, keyset, &nsec_rrset))) {
/* Flag an insecure delegation via opt_out.
* See usage of key_proves_nonexistance() from
* chain_node_get_trusted_keys() for explanation.
*/
if (opt_out && rrset->rr_type == GETDNS_RRTYPE_DS)
*opt_out = bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA);
debug_sec_print_rrset("NSEC NODATA proof for: ", rrset); debug_sec_print_rrset("NSEC NODATA proof for: ", rrset);
return keytag; return keytag;
} }
@ -2464,6 +2485,15 @@ static int key_proves_nonexistance(
&& ( keytag & NSEC3_ITERATION_COUNT_HIGH && ( keytag & NSEC3_ITERATION_COUNT_HIGH
|| nsec3_matches_name(ce, rrset->name))) { || nsec3_matches_name(ce, rrset->name))) {
/* Flag an insecure delegation via opt_out.
* See usage of key_proves_nonexistance() from
* chain_node_get_trusted_keys() for explanation.
*/
if (opt_out && rrset->rr_type == GETDNS_RRTYPE_DS)
*opt_out =
bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA);
debug_sec_print_rrset("NSEC3 No Data for: ", rrset); debug_sec_print_rrset("NSEC3 No Data for: ", rrset);
return keytag; return keytag;
} }
@ -2543,10 +2573,11 @@ static int key_proves_nonexistance(
* non-existence of a DS along the path is proofed, and SECURE otherwise. * non-existence of a DS along the path is proofed, and SECURE otherwise.
*/ */
static int chain_node_get_trusted_keys( static int chain_node_get_trusted_keys(
struct mem_funcs *mf, time_t now, uint32_t skew, const struct mem_funcs *mf, time_t now, uint32_t skew,
chain_node *node, _getdns_rrset *ta, _getdns_rrset **keys) chain_node *node, _getdns_rrset *ta, _getdns_rrset **keys)
{ {
int s, keytag; int s, keytag;
int opt_out;
/* Ascend up to the root */ /* Ascend up to the root */
if (! node) if (! node)
@ -2577,16 +2608,33 @@ static int chain_node_get_trusted_keys(
*keys = ta; *keys = ta;
return GETDNS_DNSSEC_SECURE; return GETDNS_DNSSEC_SECURE;
} }
/* ta is parent's ZSK */ /* ta is parent's ZSK proving insecurity below this node? */
if ((keytag = key_proves_nonexistance( if ((keytag = key_proves_nonexistance(
mf, now, skew, ta, &node->ds, NULL))) { mf, now, skew, ta, &node->ds, &opt_out))) {
node->ds_signer = keytag; node->ds_signer = keytag;
return GETDNS_DNSSEC_INSECURE;
}
if ((keytag = a_key_signed_rrset_no_wc( /* When the proof is in an opt_out span, result will
* be INSECURE regardless the purpose of the searched
* for key.
*
* Otherwise, INSECURE only when this is a zonecut.
* i.e. a NODATA proof, with the NS bit and no SOA bit.
*
* key_proves_nonexistance() will set opt_out also for
* these conditions.
*/
if (opt_out)
return GETDNS_DNSSEC_INSECURE;
/* If this is not an insecurity proof,
* continue searching one label up.
*/
/* ta is parent's ZSK authenticating DS? */
} else if ((keytag = a_key_signed_rrset_no_wc(
mf, now, skew, ta, &node->ds))) { mf, now, skew, ta, &node->ds))) {
node->ds_signer = keytag; node->ds_signer = keytag;
/* DS should authenticate the DNSKEY rrset now */
if ((keytag = ds_authenticates_keys( if ((keytag = ds_authenticates_keys(
mf, now, skew, &node->ds, &node->dnskey))) { mf, now, skew, &node->ds, &node->dnskey))) {
*keys = &node->dnskey; *keys = &node->dnskey;
@ -2595,6 +2643,7 @@ static int chain_node_get_trusted_keys(
? GETDNS_DNSSEC_INSECURE ? GETDNS_DNSSEC_INSECURE
: GETDNS_DNSSEC_SECURE; : GETDNS_DNSSEC_SECURE;
} }
/* DS without DNSKEY rrset == BOGUS */
return GETDNS_DNSSEC_BOGUS; return GETDNS_DNSSEC_BOGUS;
} }
} else } else
@ -2612,10 +2661,22 @@ static int chain_node_get_trusted_keys(
/* keys is an authenticated dnskey rrset always now (i.e. ZSK) */ /* keys is an authenticated dnskey rrset always now (i.e. ZSK) */
ta = *keys; ta = *keys;
/* Back down to the head */ /* Back down to the head */
/*************************/
if ((keytag = key_proves_nonexistance( if ((keytag = key_proves_nonexistance(
mf, now, skew, ta, &node->ds, NULL))) { mf, now, skew, ta, &node->ds, &opt_out))) {
node->ds_signer = keytag; node->ds_signer = keytag;
return GETDNS_DNSSEC_INSECURE;
/* When the proof is in an opt_out span, result will be
* INSECURE regardless the purpose of the searched for key.
*
* Otherwise, INSECURE only when this is a zonecut.
* i.e. a NODATA proof, with the NS bit, but no SOA bit.
*
* key_proves_nonexistance() will set opt_out also for these
* conditions. (NODATA of DS with NS bit and wihout SOA bit)
*/
return opt_out ? GETDNS_DNSSEC_INSECURE
: GETDNS_DNSSEC_SECURE;
} }
if (key_matches_signer(ta, &node->ds)) { if (key_matches_signer(ta, &node->ds)) {
@ -2655,22 +2716,64 @@ static int chain_node_get_trusted_keys(
* For this first a secure keyset is looked up, with which the keyset is * For this first a secure keyset is looked up, with which the keyset is
* evaluated. * evaluated.
*/ */
static int chain_head_validate_with_ta(struct mem_funcs *mf, static int chain_head_validate_with_ta(const struct mem_funcs *mf,
time_t now, uint32_t skew, chain_head *head, _getdns_rrset *ta) time_t now, uint32_t skew, chain_head *head, _getdns_rrset *ta)
{ {
_getdns_rrset *keys; _getdns_rrset *keys;
int s, keytag, opt_out; int s, keytag, opt_out;
debug_sec_print_rrset("validating ", &head->rrset); _getdns_rrtype_iter nsec_spc, *nsec_rr;
debug_sec_print_rrset("with trust anchor ", ta); _getdns_rdf_iter bitmap_spc, *bitmap;
chain_node *parent;
debug_sec_print_rrset("Validating ", &head->rrset);
debug_sec_print_rrset("\twith trust anchor ", ta);
/* A DS is never at the apex */
if ( head->rrset.rr_type == GETDNS_RRTYPE_DS
&& head->parent->parent)
parent = head->parent->parent;
/* Only at the apex, a NSEC is signed with a DNSKEY with the same
* owner name. All other are signed by the parent domain or higher.
* Besides a shortcut, choosing to search for a trusted key from the
* parent is essential for NSECs at a delagation point! (which would
* otherwise turn out BOGUS).
*/
else if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC
&& head->parent->parent
&& (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, &head->rrset))
&& (bitmap = _getdns_rdf_iter_init_at(
&bitmap_spc, &nsec_rr->rr_i, 1))
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
parent = head->parent->parent;
/* NSEC3 is always signed by the parent domain!
* ( the ownername of the NSEC3 itself is not in the original zone!
* so a search for a trusted key at that name gives either INSECURE
* (with opt-out) or BOGUS! )
*/
else if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC3
&& head->parent->parent)
parent = head->parent->parent;
else
parent = head->parent;
if ((s = chain_node_get_trusted_keys( if ((s = chain_node_get_trusted_keys(
mf, now, skew, head->parent, ta, &keys)) != GETDNS_DNSSEC_SECURE) mf, now, skew, parent, ta, &keys)) != GETDNS_DNSSEC_SECURE) {
debug_sec_print_rrset("Could not get trusted keys "
"for validating ", &head->rrset);
DEBUG_SEC("\tstatus: %d\n", (int)s);
return s; return s;
}
debug_sec_print_rrset("Validating ", &head->rrset);
debug_sec_print_rrset("\twith keys ", keys);
if (_getdns_rrset_has_rrs(&head->rrset)) { if (_getdns_rrset_has_rrs(&head->rrset)) {
if ((keytag = a_key_signed_rrset( if ((keytag = a_key_signed_rrset(
mf, now, skew, keys, &head->rrset))) { mf, now, skew, keys, &head->rrset))) {
DEBUG_SEC("Key %d proved\n", (int)keytag);
debug_sec_print_rrset("\tSECURE: ", &head->rrset);
head->signer = keytag; head->signer = keytag;
return GETDNS_DNSSEC_SECURE; return GETDNS_DNSSEC_SECURE;
@ -2679,23 +2782,29 @@ static int chain_head_validate_with_ta(struct mem_funcs *mf,
skew, keys, &head->rrset, &opt_out)) skew, keys, &head->rrset, &opt_out))
&& opt_out) { && opt_out) {
DEBUG_SEC("Key %d proved (optout)\n", (int)keytag);
debug_sec_print_rrset("\tINSECURE: ", &head->rrset);
head->signer = keytag; head->signer = keytag;
return GETDNS_DNSSEC_INSECURE; return GETDNS_DNSSEC_INSECURE;
} }
} else if ((keytag = key_proves_nonexistance(mf, now, skew, } else if ((keytag = key_proves_nonexistance(mf, now, skew,
keys, &head->rrset, &opt_out))) { keys, &head->rrset, &opt_out))) {
DEBUG_SEC("Key %d proved (NX)\n", (int)keytag);
debug_sec_print_rrset("\tSECURE: ", &head->rrset);
head->signer = keytag; head->signer = keytag;
return opt_out || (keytag & NSEC3_ITERATION_COUNT_HIGH) return opt_out || (keytag & NSEC3_ITERATION_COUNT_HIGH)
? GETDNS_DNSSEC_INSECURE : GETDNS_DNSSEC_SECURE; ? GETDNS_DNSSEC_INSECURE : GETDNS_DNSSEC_SECURE;
} }
debug_sec_print_rrset("BOGUS: ", &head->rrset);
debug_sec_print_rrset("\twith trust anchor: ", ta);
return GETDNS_DNSSEC_BOGUS; return GETDNS_DNSSEC_BOGUS;
} }
/* The DNSSEC status of the rrset in head is evaluated by trying the trust /* The DNSSEC status of the rrset in head is evaluated by trying the trust
* anchors in tas in turn. The best outcome counts. * anchors in tas in turn. The best outcome counts.
*/ */
static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew, static int chain_head_validate(const struct mem_funcs *mf, time_t now,
chain_head *head, _getdns_rrset_iter *tas) uint32_t skew, chain_head *head, _getdns_rrset_iter *tas)
{ {
_getdns_rrset_iter *i; _getdns_rrset_iter *i;
_getdns_rrset *ta, dnskey_ta, ds_ta; _getdns_rrset *ta, dnskey_ta, ds_ta;
@ -2844,7 +2953,7 @@ static void chain_clear_netreq_dnssec_status(chain_head *chain)
* processing each head in turn. The worst outcome is the dnssec status for * processing each head in turn. The worst outcome is the dnssec status for
* the whole. * the whole.
*/ */
static int chain_validate_dnssec(struct mem_funcs *mf, static int chain_validate_dnssec(const struct mem_funcs *mf,
time_t now, uint32_t skew, chain_head *chain, _getdns_rrset_iter *tas) time_t now, uint32_t skew, chain_head *chain, _getdns_rrset_iter *tas)
{ {
int s = GETDNS_DNSSEC_INDETERMINATE, t; int s = GETDNS_DNSSEC_INDETERMINATE, t;
@ -3180,7 +3289,6 @@ static void check_chain_complete(chain_head *chain)
} else if (_getdns_bogus(dnsreq)) { } else if (_getdns_bogus(dnsreq)) {
_getdns_rrsig_iter rrsig_spc; _getdns_rrsig_iter rrsig_spc;
DEBUG_ANCHOR("Request was bogus!\n");
if ((head = chain) && (node = _to_the_root(head->parent)) if ((head = chain) && (node = _to_the_root(head->parent))
/* The root DNSKEY rrset */ /* The root DNSKEY rrset */
@ -3193,13 +3301,15 @@ static void check_chain_complete(chain_head *chain)
&& _getdns_rrsig_iter_init(&rrsig_spc, &node->dnskey) && _getdns_rrsig_iter_init(&rrsig_spc, &node->dnskey)
){ ){
DEBUG_ANCHOR("root DNSKEY set was bogus!\n"); _getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_NOTICE
, "root DNSKEY set was bogus!\n");
if (!dnsreq->waiting_for_ta) { if (!dnsreq->waiting_for_ta) {
uint64_t now = 0; uint64_t now_ms = 0;
dnsreq->waiting_for_ta = 1; dnsreq->waiting_for_ta = 1;
_getdns_context_equip_with_anchor( _getdns_context_equip_with_anchor(
context, &now); context, &now_ms);
if (context->trust_anchors_source if (context->trust_anchors_source
== GETDNS_TASRC_XML) { == GETDNS_TASRC_XML) {
@ -3207,9 +3317,19 @@ static void check_chain_complete(chain_head *chain)
check_chain_complete(chain); check_chain_complete(chain);
return; return;
} }
_getdns_start_fetching_ta( if (context->trust_anchors_source ==
context, dnsreq->loop); GETDNS_TASRC_FAILED
&& 0 == _getdns_ms_until_expiry2(
context->trust_anchors_backoff_expiry,
&now_ms)) {
context->trust_anchors_source =
GETDNS_TASRC_NONE;
}
if (context->trust_anchors_source
!= GETDNS_TASRC_FAILED) {
_getdns_start_fetching_ta(
context, dnsreq->loop, &now_ms);
}
if (dnsreq->waiting_for_ta && if (dnsreq->waiting_for_ta &&
context->trust_anchors_source context->trust_anchors_source
== GETDNS_TASRC_FETCHING) { == GETDNS_TASRC_FETCHING) {
@ -3364,7 +3484,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
@ -3489,7 +3609,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
*****************************************************************************/ *****************************************************************************/
static int wire_validate_dnssec(struct mem_funcs *mf, static int wire_validate_dnssec(const struct mem_funcs *mf,
time_t now, uint32_t skew, uint8_t *to_val, size_t to_val_len, time_t now, uint32_t skew, uint8_t *to_val, size_t to_val_len,
uint8_t *support, size_t support_len, uint8_t *tas, size_t tas_len) uint8_t *support, size_t support_len, uint8_t *tas, size_t tas_len)
{ {
@ -3571,9 +3691,9 @@ static int wire_validate_dnssec(struct mem_funcs *mf,
* *
*/ */
getdns_return_t getdns_return_t
getdns_validate_dnssec2(getdns_list *records_to_validate, getdns_validate_dnssec2(const getdns_list *records_to_validate,
getdns_list *support_records, const getdns_list *support_records,
getdns_list *trust_anchors, const getdns_list *trust_anchors,
time_t now, uint32_t skew) time_t now, uint32_t skew)
{ {
uint8_t to_val_buf[4096], *to_val, uint8_t to_val_buf[4096], *to_val,
@ -3585,7 +3705,7 @@ getdns_validate_dnssec2(getdns_list *records_to_validate,
tas_len = sizeof(tas_buf); tas_len = sizeof(tas_buf);
int r = GETDNS_RETURN_MEMORY_ERROR; int r = GETDNS_RETURN_MEMORY_ERROR;
struct mem_funcs *mf; const struct mem_funcs *mf;
size_t i; size_t i;
getdns_dict *reply; getdns_dict *reply;
@ -3666,9 +3786,9 @@ exit_free_support:
getdns_return_t getdns_return_t
getdns_validate_dnssec(getdns_list *records_to_validate, getdns_validate_dnssec(const getdns_list *records_to_validate,
getdns_list *support_records, const getdns_list *support_records,
getdns_list *trust_anchors) const getdns_list *trust_anchors)
{ {
return getdns_validate_dnssec2(records_to_validate, support_records, return getdns_validate_dnssec2(records_to_validate, support_records,
trust_anchors, time(NULL), 0); trust_anchors, time(NULL), 0);

View File

@ -218,12 +218,14 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
&& !dns_req->avoid_dnssec_roadblocks && !dns_req->avoid_dnssec_roadblocks
&& (dns_req->dnssec_return_status || && (dns_req->dnssec_return_status ||
dns_req->dnssec_return_only_secure || dns_req->dnssec_return_only_secure ||
dns_req->dnssec ||
dns_req->dnssec_return_all_statuses dns_req->dnssec_return_all_statuses
)) ))
#endif #endif
|| ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING || ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING
&& (dns_req->dnssec_return_status || && (dns_req->dnssec_return_status ||
dns_req->dnssec_return_only_secure || dns_req->dnssec_return_only_secure ||
dns_req->dnssec ||
dns_req->dnssec_return_all_statuses) dns_req->dnssec_return_all_statuses)
&& _getdns_bogus(dns_req)) && _getdns_bogus(dns_req))
)) { )) {
@ -241,7 +243,6 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
#if defined(REQ_DEBUG) && REQ_DEBUG #if defined(REQ_DEBUG) && REQ_DEBUG
debug_req("getting validation chain for ", *dns_req->netreqs); debug_req("getting validation chain for ", *dns_req->netreqs);
#endif #endif
DEBUG_ANCHOR("Valchain lookup\n");
_getdns_get_validation_chain(dns_req); _getdns_get_validation_chain(dns_req);
} else } else
_getdns_call_user_callback( _getdns_call_user_callback(
@ -423,6 +424,7 @@ _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms)
if ( context->resolution_type == GETDNS_RESOLUTION_RECURSING if ( context->resolution_type == GETDNS_RESOLUTION_RECURSING
|| dns_req->dnssec_return_status || dns_req->dnssec_return_status
|| dns_req->dnssec_return_only_secure || dns_req->dnssec_return_only_secure
|| dns_req->dnssec
|| dns_req->dnssec_return_all_statuses || dns_req->dnssec_return_all_statuses
|| dns_req->dnssec_return_validation_chain) { || dns_req->dnssec_return_validation_chain) {
#endif #endif
@ -492,7 +494,7 @@ extformatcmp(const void *a, const void *b)
/*---------------------------------------- validate_extensions */ /*---------------------------------------- validate_extensions */
static getdns_return_t static getdns_return_t
validate_extensions(struct getdns_dict * extensions) validate_extensions(const getdns_dict * extensions)
{ {
/** /**
* this is a comprehensive list of extensions and their data types * this is a comprehensive list of extensions and their data types
@ -503,6 +505,7 @@ validate_extensions(struct getdns_dict * extensions)
static getdns_extension_format extformats[] = { static getdns_extension_format extformats[] = {
{"add_opt_parameters" , t_dict, 1}, {"add_opt_parameters" , t_dict, 1},
{"add_warning_for_bad_dns" , t_int , 1}, {"add_warning_for_bad_dns" , t_int , 1},
{"dnssec" , t_int , 1},
{"dnssec_return_all_statuses" , t_int , 1}, {"dnssec_return_all_statuses" , t_int , 1},
{"dnssec_return_full_validation_chain", t_int , 1}, {"dnssec_return_full_validation_chain", t_int , 1},
{"dnssec_return_only_secure" , t_int , 1}, {"dnssec_return_only_secure" , t_int , 1},
@ -555,7 +558,7 @@ validate_extensions(struct getdns_dict * extensions)
static getdns_return_t static getdns_return_t
getdns_general_ns(getdns_context *context, getdns_eventloop *loop, getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions, const char *name, uint16_t request_type, const getdns_dict *extensions,
void *userarg, getdns_network_req **return_netreq_p, void *userarg, getdns_network_req **return_netreq_p,
getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces) getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces)
{ {
@ -591,13 +594,18 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
_getdns_context_track_outbound_request(req); _getdns_context_track_outbound_request(req);
if (req->dnssec_extension_set) { if (req->dnssec_extension_set) {
if (context->trust_anchors_source == GETDNS_TASRC_FAILED
&& _getdns_ms_until_expiry2(
context->trust_anchors_backoff_expiry, &now_ms) == 0) {
context->trust_anchors_source = GETDNS_TASRC_NONE;
}
if (context->trust_anchors_source == GETDNS_TASRC_XML_UPDATE) if (context->trust_anchors_source == GETDNS_TASRC_XML_UPDATE)
_getdns_start_fetching_ta(context, loop); _getdns_start_fetching_ta(context, loop, &now_ms);
else if (context->trust_anchors_source == GETDNS_TASRC_NONE) { else if (context->trust_anchors_source == GETDNS_TASRC_NONE) {
_getdns_context_equip_with_anchor(context, &now_ms); _getdns_context_equip_with_anchor(context, &now_ms);
if (context->trust_anchors_source == GETDNS_TASRC_NONE) { if (context->trust_anchors_source == GETDNS_TASRC_NONE) {
_getdns_start_fetching_ta(context, loop); _getdns_start_fetching_ta(context, loop, &now_ms);
} }
} }
} }
@ -706,7 +714,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
getdns_return_t getdns_return_t
_getdns_general_loop(getdns_context *context, getdns_eventloop *loop, _getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions, const char *name, uint16_t request_type, const getdns_dict *extensions,
void *userarg, getdns_network_req **netreq_p, void *userarg, getdns_network_req **netreq_p,
getdns_callback_t callback, internal_cb_t internal_cb) getdns_callback_t callback, internal_cb_t internal_cb)
{ {
@ -718,33 +726,33 @@ _getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
getdns_return_t getdns_return_t
_getdns_address_loop(getdns_context *context, getdns_eventloop *loop, _getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, getdns_dict *extensions, void *userarg, const char *name, const getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callback) getdns_transaction_t *transaction_id, getdns_callback_t callback)
{ {
getdns_dict *my_extensions = extensions; getdns_dict *my_extensions = NULL;
getdns_return_t r; getdns_return_t r;
uint32_t value; uint32_t value;
getdns_network_req *netreq = NULL; getdns_network_req *netreq = NULL;
if (!my_extensions) { if (!extensions) {
if (!(my_extensions=getdns_dict_create_with_context(context))) if (!(my_extensions=getdns_dict_create_with_context(context)))
return GETDNS_RETURN_MEMORY_ERROR; return GETDNS_RETURN_MEMORY_ERROR;
} else if ( } else if (
getdns_dict_get_int(my_extensions, "return_both_v4_and_v6", &value) getdns_dict_get_int(extensions, "return_both_v4_and_v6", &value)
&& (r = _getdns_dict_copy(extensions, &my_extensions))) && (r = _getdns_dict_copy(extensions, &my_extensions)))
return r; return r;
if (my_extensions != extensions && (r = getdns_dict_set_int( if (my_extensions && (r = getdns_dict_set_int(
my_extensions, "return_both_v4_and_v6", GETDNS_EXTENSION_TRUE))) my_extensions, "return_both_v4_and_v6", GETDNS_EXTENSION_TRUE)))
return r; return r;
r = getdns_general_ns(context, loop, r = getdns_general_ns(context, loop,
name, GETDNS_RRTYPE_AAAA, my_extensions, name, GETDNS_RRTYPE_AAAA, my_extensions ? my_extensions : extensions,
userarg, &netreq, callback, NULL, 1); userarg, &netreq, callback, NULL, 1);
if (netreq && transaction_id) if (netreq && transaction_id)
*transaction_id = netreq->owner->trans_id; *transaction_id = netreq->owner->trans_id;
if (my_extensions != extensions) if (my_extensions)
getdns_dict_destroy(my_extensions); getdns_dict_destroy(my_extensions);
return r; return r;
@ -752,7 +760,7 @@ _getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
getdns_return_t getdns_return_t
_getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop, _getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
getdns_dict *address, getdns_dict *extensions, void *userarg, const getdns_dict *address, const getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callback) getdns_transaction_t *transaction_id, getdns_callback_t callback)
{ {
struct getdns_bindata *address_data; struct getdns_bindata *address_data;
@ -842,7 +850,7 @@ _getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
getdns_return_t getdns_return_t
_getdns_service_loop(getdns_context *context, getdns_eventloop *loop, _getdns_service_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, getdns_dict *extensions, void *userarg, const char *name, const getdns_dict *extensions, void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callback) getdns_transaction_t * transaction_id, getdns_callback_t callback)
{ {
getdns_return_t r; getdns_return_t r;
@ -859,7 +867,7 @@ _getdns_service_loop(getdns_context *context, getdns_eventloop *loop,
*/ */
getdns_return_t getdns_return_t
getdns_general(getdns_context *context, getdns_general(getdns_context *context,
const char *name, uint16_t request_type, getdns_dict *extensions, const char *name, uint16_t request_type, const getdns_dict *extensions,
void *userarg, getdns_transaction_t * transaction_id, void *userarg, getdns_transaction_t * transaction_id,
getdns_callback_t callbackfn) getdns_callback_t callbackfn)
{ {
@ -881,7 +889,7 @@ getdns_general(getdns_context *context,
*/ */
getdns_return_t getdns_return_t
getdns_address(getdns_context *context, getdns_address(getdns_context *context,
const char *name, getdns_dict *extensions, void *userarg, const char *name, const getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn) getdns_transaction_t *transaction_id, getdns_callback_t callbackfn)
{ {
if (!context) return GETDNS_RETURN_INVALID_PARAMETER; if (!context) return GETDNS_RETURN_INVALID_PARAMETER;
@ -896,7 +904,7 @@ getdns_address(getdns_context *context,
*/ */
getdns_return_t getdns_return_t
getdns_hostname(getdns_context *context, getdns_hostname(getdns_context *context,
getdns_dict *address, getdns_dict *extensions, void *userarg, const getdns_dict *address, const getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn) getdns_transaction_t *transaction_id, getdns_callback_t callbackfn)
{ {
if (!context) return GETDNS_RETURN_INVALID_PARAMETER; if (!context) return GETDNS_RETURN_INVALID_PARAMETER;
@ -910,7 +918,7 @@ getdns_hostname(getdns_context *context,
*/ */
getdns_return_t getdns_return_t
getdns_service(getdns_context *context, getdns_service(getdns_context *context,
const char *name, getdns_dict *extensions, void *userarg, const char *name, const getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn) getdns_transaction_t *transaction_id, getdns_callback_t callbackfn)
{ {
if (!context) return GETDNS_RETURN_INVALID_PARAMETER; if (!context) return GETDNS_RETURN_INVALID_PARAMETER;

View File

@ -63,25 +63,25 @@ int _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms);
getdns_return_t getdns_return_t
_getdns_general_loop(getdns_context *context, getdns_eventloop *loop, _getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions, const char *name, uint16_t request_type, const getdns_dict *extensions,
void *userarg, getdns_network_req **netreq_p, void *userarg, getdns_network_req **netreq_p,
getdns_callback_t callbackfn, internal_cb_t internal_cb); getdns_callback_t callbackfn, internal_cb_t internal_cb);
getdns_return_t getdns_return_t
_getdns_address_loop(getdns_context *context, getdns_eventloop *loop, _getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, getdns_dict *extensions, const char *name, const getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id, void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn); getdns_callback_t callbackfn);
getdns_return_t getdns_return_t
_getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop, _getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
getdns_dict *address, getdns_dict *extensions, const getdns_dict *address, const getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id, void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn); getdns_callback_t callbackfn);
getdns_return_t getdns_return_t
_getdns_service_loop(getdns_context *context, getdns_eventloop *loop, _getdns_service_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, getdns_dict *extensions, const char *name, const getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id, void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn); getdns_callback_t callbackfn);

View File

@ -416,6 +416,7 @@ typedef enum getdns_callback_type_t {
#define GETDNS_RRTYPE_CDNSKEY 60 #define GETDNS_RRTYPE_CDNSKEY 60
#define GETDNS_RRTYPE_OPENPGPKEY 61 #define GETDNS_RRTYPE_OPENPGPKEY 61
#define GETDNS_RRTYPE_CSYNC 62 #define GETDNS_RRTYPE_CSYNC 62
#define GETDNS_RRTYPE_ZONEMD 63
#define GETDNS_RRTYPE_SPF 99 #define GETDNS_RRTYPE_SPF 99
#define GETDNS_RRTYPE_UINFO 100 #define GETDNS_RRTYPE_UINFO 100
#define GETDNS_RRTYPE_UID 101 #define GETDNS_RRTYPE_UID 101
@ -743,7 +744,7 @@ getdns_list *getdns_list_create();
* used to create and initialize the list. * used to create and initialize the list.
* @return pointer to an allocated list, NULL if insufficient memory * @return pointer to an allocated list, NULL if insufficient memory
*/ */
getdns_list *getdns_list_create_with_context(getdns_context *context); getdns_list *getdns_list_create_with_context(const getdns_context *context);
/** /**
* create a new list with no items, creating and initializing it with the * create a new list with no items, creating and initializing it with the
@ -863,7 +864,7 @@ getdns_dict *getdns_dict_create();
* used to create and initialize the dict. * used to create and initialize the dict.
* @return pointer to an allocated dict, NULL if insufficient memory * @return pointer to an allocated dict, NULL if insufficient memory
*/ */
getdns_dict *getdns_dict_create_with_context(getdns_context *context); getdns_dict *getdns_dict_create_with_context(const getdns_context *context);
/** /**
* create a new dict with no items, creating and initializing it with the * create a new dict with no items, creating and initializing it with the
@ -1030,9 +1031,9 @@ getdns_return_t
getdns_general(getdns_context *context, getdns_general(getdns_context *context,
const char *name, const char *name,
uint16_t request_type, uint16_t request_type,
getdns_dict *extensions, const getdns_dict *extensions,
void *userarg, void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn); getdns_transaction_t *transaction_id, getdns_callback_t callbackfn);
/** /**
* retrieve address assigned to a DNS name * retrieve address assigned to a DNS name
@ -1048,9 +1049,9 @@ getdns_general(getdns_context *context,
getdns_return_t getdns_return_t
getdns_address(getdns_context *context, getdns_address(getdns_context *context,
const char *name, const char *name,
getdns_dict *extensions, const getdns_dict *extensions,
void *userarg, void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn); getdns_transaction_t *transaction_id, getdns_callback_t callbackfn);
/** /**
* retrieve hostname assigned to an IP address * retrieve hostname assigned to an IP address
@ -1065,10 +1066,10 @@ getdns_address(getdns_context *context,
*/ */
getdns_return_t getdns_return_t
getdns_hostname(getdns_context *context, getdns_hostname(getdns_context *context,
getdns_dict *address, const getdns_dict *address,
getdns_dict *extensions, const getdns_dict *extensions,
void *userarg, void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn); getdns_transaction_t *transaction_id, getdns_callback_t callbackfn);
/** /**
* retrieve a service assigned to a DNS name * retrieve a service assigned to a DNS name
@ -1084,9 +1085,9 @@ getdns_hostname(getdns_context *context,
getdns_return_t getdns_return_t
getdns_service(getdns_context *context, getdns_service(getdns_context *context,
const char *name, const char *name,
getdns_dict *extensions, const getdns_dict *extensions,
void *userarg, void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn); getdns_transaction_t *transaction_id, getdns_callback_t callbackfn);
/** @} /** @}
*/ */
@ -1201,7 +1202,7 @@ getdns_return_t
getdns_general_sync(getdns_context *context, getdns_general_sync(getdns_context *context,
const char *name, const char *name,
uint16_t request_type, uint16_t request_type,
getdns_dict *extensions, const getdns_dict *extensions,
getdns_dict **response); getdns_dict **response);
/** /**
@ -1216,7 +1217,7 @@ getdns_general_sync(getdns_context *context,
getdns_return_t getdns_return_t
getdns_address_sync(getdns_context *context, getdns_address_sync(getdns_context *context,
const char *name, const char *name,
getdns_dict *extensions, const getdns_dict *extensions,
getdns_dict **response); getdns_dict **response);
/** /**
@ -1230,8 +1231,8 @@ getdns_address_sync(getdns_context *context,
*/ */
getdns_return_t getdns_return_t
getdns_hostname_sync(getdns_context *context, getdns_hostname_sync(getdns_context *context,
getdns_dict *address, const getdns_dict *address,
getdns_dict *extensions, const getdns_dict *extensions,
getdns_dict **response); getdns_dict **response);
/** /**
@ -1246,7 +1247,7 @@ getdns_hostname_sync(getdns_context *context,
getdns_return_t getdns_return_t
getdns_service_sync(getdns_context *context, getdns_service_sync(getdns_context *context,
const char *name, const char *name,
getdns_dict *extensions, const getdns_dict *extensions,
getdns_dict **response); getdns_dict **response);
/** @} /** @}
@ -1341,9 +1342,8 @@ char *getdns_convert_alabel_to_ulabel(const char *alabel);
* depending on the validation status. * depending on the validation status.
*/ */
getdns_return_t getdns_return_t
getdns_validate_dnssec(getdns_list *to_validate, getdns_validate_dnssec(const getdns_list *to_validate,
getdns_list *support_records, const getdns_list *support_records, const getdns_list *trust_anchors);
getdns_list *trust_anchors);
/** /**
* Get the default list of trust anchor records that is used by the library * Get the default list of trust anchor records that is used by the library
@ -1444,7 +1444,7 @@ getdns_context_set_resolution_type(getdns_context *context,
*/ */
getdns_return_t getdns_return_t
getdns_context_set_namespaces(getdns_context *context, getdns_context_set_namespaces(getdns_context *context,
size_t namespace_count, getdns_namespace_t *namespaces); size_t namespace_count, const getdns_namespace_t *namespaces);
/** /**
* Specifies what transport are used for DNS lookups. The default is * Specifies what transport are used for DNS lookups. The default is
@ -1812,9 +1812,11 @@ getdns_context_set_extended_memory_functions(getdns_context *context,
* GETDNS_RESOLUTION_STUB. * GETDNS_RESOLUTION_STUB.
* - all_context (a dict) with names for all the other settings in * - all_context (a dict) with names for all the other settings in
* context. * context.
* The application is responsible for cleaning up the returned dictionary
* object with getdns_dict_destroy.
*/ */
getdns_dict* getdns_dict*
getdns_context_get_api_information(getdns_context* context); getdns_context_get_api_information(const getdns_context *context);
/** @} /** @}
*/ */

View File

@ -102,6 +102,15 @@ extern "C" {
#define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT "Change related to getdns_context_set_tls_cipher_list" #define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT "Change related to getdns_context_set_tls_cipher_list"
#define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST 634 #define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST 634
#define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT "Change related to getdns_context_set_tls_curves_list" #define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT "Change related to getdns_context_set_tls_curves_list"
#define GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES 635
#define GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES_TEXT "Change related to getdns_context_set_tls_ciphersuites"
#define GETDNS_CONTEXT_CODE_TLS_MIN_VERSION 636
#define GETDNS_CONTEXT_CODE_TLS_MIN_VERSION_TEXT "Change related to getdns_context_set_tls_min_version"
#define GETDNS_CONTEXT_CODE_TLS_MAX_VERSION 637
#define GETDNS_CONTEXT_CODE_TLS_MAX_VERSION_TEXT "Change related to getdns_context_set_tls_max_version"
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME 638
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_trust_anchors_backoff_time"
/** @} /** @}
*/ */
@ -352,7 +361,7 @@ struct getdns_eventloop_vmt {
* @return GETDNS_RETURN_INVALID_PARAMETER when context or eventloop were NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or eventloop were NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_set_eventloop(getdns_context* context, getdns_context_set_eventloop(getdns_context *context,
getdns_eventloop *eventloop); getdns_eventloop *eventloop);
/** /**
@ -368,7 +377,7 @@ getdns_context_set_eventloop(getdns_context* context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or evenloop were NULL * @return GETDNS_RETURN_INVALID_PARAMETER when context or evenloop were NULL
*/ */
getdns_return_t getdns_return_t
getdns_context_get_eventloop(getdns_context* context, getdns_context_get_eventloop(const getdns_context *context,
getdns_eventloop **eventloop); getdns_eventloop **eventloop);
/** /**
@ -548,8 +557,18 @@ 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 0x3000
#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 about stub resolving"
#define GETDNS_LOG_SYS_RECURSING 0x4000
#define GETDNS_LOG_SYS_RECURSING_TEXT "Log messages about recursive resolving"
#define GETDNS_LOG_SYS_RESOLVING 0x6000
#define GETDNS_LOG_SYS_RESOLVING_TEXT "Log messages about resolving"
#define GETDNS_LOG_SYS_ANCHOR 0x8000
#define GETDNS_LOG_SYS_ANCHOR_TEXT "Log messages about fetching trust anchors"
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);
@ -694,6 +713,22 @@ getdns_return_t
getdns_context_set_trust_anchors_verify_email( getdns_context_set_trust_anchors_verify_email(
getdns_context *context, const char *verify_email); getdns_context *context, const char *verify_email);
/**
* Configure the amount of milliseconds the trust anchors should not be tried
* to be fetched after failure. Default is 2500 which is two and a half seconds.
* Setting the trust anchors backoff time will cause fetching to be retried
* immediatly.
* @see getdns_context_get_trust_anchors_backoff_time
* @param context The context to configure
* @param value Number of milliseconds before fetch trust anchors
* will be retried.
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null.
*/
getdns_return_t
getdns_context_set_trust_anchors_backoff_time(
getdns_context *context, uint64_t value);
/** /**
* Initialized the context's upstream recursive servers and suffixes * Initialized the context's upstream recursive servers and suffixes
* with the values from the given resolv.conf file. * with the values from the given resolv.conf file.
@ -755,6 +790,18 @@ getdns_return_t
getdns_context_set_tls_cipher_list( getdns_context_set_tls_cipher_list(
getdns_context *context, const char *cipher_list); getdns_context *context, const char *cipher_list);
/**
* Configure the available TLS1.3 ciphersuites for authenticated TLS upstreams.
* @see getdns_context_get_tls_ciphersuites
* @param[in] context The context to configure
* @param[in] ciphersuites The cipher list
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_set_tls_ciphersuites(
getdns_context *context, const char *ciphersuites);
/** /**
* Sets the supported curves TLS upstreams. * Sets the supported curves TLS upstreams.
* @see getdns_context_get_tls_curves_list * @see getdns_context_get_tls_curves_list
@ -768,6 +815,80 @@ getdns_return_t
getdns_context_set_tls_curves_list( getdns_context_set_tls_curves_list(
getdns_context *context, const char *curves_list); getdns_context *context, const char *curves_list);
typedef enum getdns_tls_version_t {
GETDNS_SSL3 = 1400,
GETDNS_TLS1 = 1401,
GETDNS_TLS1_1 = 1402,
GETDNS_TLS1_2 = 1403,
GETDNS_TLS1_3 = 1404
} getdns_tls_version_t;
#define GETDNS_SSL3_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
#define GETDNS_TLS1_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
#define GETDNS_TLS1_1_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
#define GETDNS_TLS1_2_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
#define GETDNS_TLS1_3_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
/**
* Configure context for minimum supported TLS version.
* @see getdns_context_set_tls_max_version
* @see getdns_context_get_tls_min_version
* @param context The context to configure
* @param min_version is one of GETDNS_SSL3, GETDNS_TLS1, GETDNS_TLS1_1,
* GETDNS_TLS1_2, GETDNS_TLS1_3
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null or value has an
* invalid value.
*/
getdns_return_t
getdns_context_set_tls_min_version(
getdns_context *context, getdns_tls_version_t min_version);
/**
* Get configured minimum supported TLS version.
* @see getdns_context_get_tls_max_version
* @see getdns_context_set_tls_min_version
* @param context The context to configure
* @param min_version is one of GETDNS_SSL3, GETDNS_TLS1, GETDNS_TLS1_1,
* GETDNS_TLS1_2, GETDNS_TLS1_3
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null or value has an
* invalid value.
*/
getdns_return_t
getdns_context_get_tls_min_version(
const getdns_context *context, getdns_tls_version_t *min_version);
/**
* Configure context for maximum supported TLS version.
* @see getdns_context_set_tls_min_version
* @see getdns_context_get_tls_max_version
* @param context The context to configure
* @param max_version is one of GETDNS_SSL3, GETDNS_TLS1, GETDNS_TLS1_1,
* GETDNS_TLS1_2, GETDNS_TLS1_3
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null or value has an
* invalid value.
*/
getdns_return_t
getdns_context_set_tls_max_version(
getdns_context *context, getdns_tls_version_t max_version);
/**
* Get configured maximum supported TLS version.
* @see getdns_context_get_tls_min_version
* @see getdns_context_set_tls_max_version
* @param context The context to configure
* @param max_version is one of GETDNS_SSL3, GETDNS_TLS1, GETDNS_TLS1_1,
* GETDNS_TLS1_2, GETDNS_TLS1_3
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null or value has an
* invalid value.
*/
getdns_return_t
getdns_context_get_tls_max_version(
const getdns_context *context, getdns_tls_version_t *max_version);
/** /**
* Get the current resolution type setting from this context. * Get the current resolution type setting from this context.
* @see getdns_context_set_resolution_type * @see getdns_context_set_resolution_type
@ -779,8 +900,8 @@ getdns_context_set_tls_curves_list(
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_resolution_type(getdns_context *context, getdns_context_get_resolution_type(const getdns_context *context,
getdns_resolution_t* value); getdns_resolution_t *value);
/** /**
* Get a copy of the namespaces list setting from this context. * Get a copy of the namespaces list setting from this context.
@ -794,8 +915,8 @@ getdns_context_get_resolution_type(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_namespaces(getdns_context *context, getdns_context_get_namespaces(const getdns_context *context,
size_t* namespace_count, getdns_namespace_t **namespaces); size_t *namespace_count, getdns_namespace_t **namespaces);
/** /**
* Get what transports are used for DNS lookups. * Get what transports are used for DNS lookups.
@ -808,8 +929,8 @@ getdns_context_get_namespaces(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_dns_transport(getdns_context *context, getdns_context_get_dns_transport(const getdns_context *context,
getdns_transport_t* value); getdns_transport_t *value);
/** /**
* Get a copy of the transports list setting from this context. * Get a copy of the transports list setting from this context.
@ -824,8 +945,8 @@ getdns_context_get_dns_transport(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_dns_transport_list(getdns_context *context, getdns_context_get_dns_transport_list(const getdns_context *context,
size_t* transport_count, getdns_transport_list_t **transports); size_t *transport_count, getdns_transport_list_t **transports);
/** /**
* Get the current limit for outstanding queries setting from this context. * Get the current limit for outstanding queries setting from this context.
@ -836,8 +957,8 @@ getdns_context_get_dns_transport_list(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or limit was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or limit was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_limit_outstanding_queries(getdns_context *context, getdns_context_get_limit_outstanding_queries(const getdns_context *context,
uint16_t* limit); uint16_t *limit);
/** /**
* Get the current number of milliseconds the API will wait for request * Get the current number of milliseconds the API will wait for request
@ -850,7 +971,7 @@ getdns_context_get_limit_outstanding_queries(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or limit was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or limit was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_timeout(getdns_context *context, uint64_t* timeout); getdns_context_get_timeout(const getdns_context *context, uint64_t *timeout);
/** /**
* Get the current number of milliseconds the API will leave an idle TCP or TLS * Get the current number of milliseconds the API will leave an idle TCP or TLS
@ -864,7 +985,8 @@ getdns_context_get_timeout(getdns_context *context, uint64_t* timeout);
* @return GETDNS_RETURN_INVALID_PARAMETER when context or timeout was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or timeout was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_idle_timeout(getdns_context *context, uint64_t* timeout); getdns_context_get_idle_timeout(
const getdns_context *context, uint64_t *timeout);
/** /**
* Get the setting that says whether or not DNS queries follow redirects. * Get the setting that says whether or not DNS queries follow redirects.
@ -876,8 +998,8 @@ getdns_context_get_idle_timeout(getdns_context *context, uint64_t* timeout);
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_follow_redirects(getdns_context *context, getdns_context_get_follow_redirects(const getdns_context *context,
getdns_redirects_t* value); getdns_redirects_t *value);
/** /**
* Get a copy of the list of addresses in use for looking up top-level domains * Get a copy of the list of addresses in use for looking up top-level domains
@ -894,7 +1016,7 @@ getdns_context_get_follow_redirects(getdns_context *context,
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated * @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
*/ */
getdns_return_t getdns_return_t
getdns_context_get_dns_root_servers(getdns_context *context, getdns_context_get_dns_root_servers(const getdns_context *context,
getdns_list **addresses); getdns_list **addresses);
/** /**
@ -912,8 +1034,8 @@ getdns_context_get_dns_root_servers(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_append_name(getdns_context *context, getdns_context_get_append_name(const getdns_context *context,
getdns_append_name_t* value); getdns_append_name_t *value);
/** /**
* Get a copy of the list of suffixes to be appended based on the value off the * Get a copy of the list of suffixes to be appended based on the value off the
@ -929,7 +1051,7 @@ getdns_context_get_append_name(getdns_context *context,
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated * @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
*/ */
getdns_return_t getdns_return_t
getdns_context_get_suffix(getdns_context *context, getdns_list **value); getdns_context_get_suffix(const getdns_context *context, getdns_list **value);
/** /**
* Get a copy of the list of DNSSEC trust anchors in use by context. * Get a copy of the list of DNSSEC trust anchors in use by context.
@ -944,7 +1066,7 @@ getdns_context_get_suffix(getdns_context *context, getdns_list **value);
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated * @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
*/ */
getdns_return_t getdns_return_t
getdns_context_get_dnssec_trust_anchors(getdns_context *context, getdns_context_get_dnssec_trust_anchors(const getdns_context *context,
getdns_list **value); getdns_list **value);
/** /**
@ -958,8 +1080,8 @@ getdns_context_get_dnssec_trust_anchors(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_dnssec_allowed_skew(getdns_context *context, getdns_context_get_dnssec_allowed_skew(const getdns_context *context,
uint32_t* value); uint32_t *value);
/** /**
* Get a copy of the list of upstream that will be targeted in stub resolution * Get a copy of the list of upstream that will be targeted in stub resolution
@ -975,7 +1097,7 @@ getdns_context_get_dnssec_allowed_skew(getdns_context *context,
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated * @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
*/ */
getdns_return_t getdns_return_t
getdns_context_get_upstream_recursive_servers(getdns_context *context, getdns_context_get_upstream_recursive_servers(const getdns_context *context,
getdns_list **upstream_list); getdns_list **upstream_list);
/** /**
@ -990,8 +1112,8 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_edns_maximum_udp_payload_size(getdns_context *context, getdns_context_get_edns_maximum_udp_payload_size(const getdns_context *context,
uint16_t* value); uint16_t *value);
/** /**
* Get the rcode advertised in an EDNS0 OPT record setting from context * Get the rcode advertised in an EDNS0 OPT record setting from context
@ -1002,8 +1124,8 @@ getdns_context_get_edns_maximum_udp_payload_size(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_edns_extended_rcode(getdns_context *context, getdns_context_get_edns_extended_rcode(const getdns_context *context,
uint8_t* value); uint8_t *value);
/** /**
* Get the version advertised in an EDNS0 OPT record setting from context * Get the version advertised in an EDNS0 OPT record setting from context
@ -1014,7 +1136,7 @@ getdns_context_get_edns_extended_rcode(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_edns_version(getdns_context *context, uint8_t* value); getdns_context_get_edns_version(const getdns_context *context, uint8_t *value);
/** /**
* Get the DO bit advertised in an EDNS0 OPT record setting from context * Get the DO bit advertised in an EDNS0 OPT record setting from context
@ -1026,7 +1148,7 @@ getdns_context_get_edns_version(getdns_context *context, uint8_t* value);
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value); getdns_context_get_edns_do_bit(const getdns_context *context, uint8_t *value);
/** /**
* Get whether queries with this context will have the EDNS Client Subnet * Get whether queries with this context will have the EDNS Client Subnet
@ -1039,7 +1161,8 @@ getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value);
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t* value); getdns_context_get_edns_client_subnet_private(const getdns_context *context,
uint8_t *value);
/** /**
* Get the blocksize that will be used to pad outgoing queries over TLS. * Get the blocksize that will be used to pad outgoing queries over TLS.
@ -1051,7 +1174,8 @@ getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t*
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t* value); getdns_context_get_tls_query_padding_blocksize(
const getdns_context *context, uint16_t *value);
/** /**
* Get whether the upstream needs to be authenticated with DNS over TLS. * Get whether the upstream needs to be authenticated with DNS over TLS.
@ -1069,8 +1193,8 @@ getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_tls_authentication(getdns_context *context, getdns_context_get_tls_authentication(const getdns_context *context,
getdns_tls_authentication_t* value); getdns_tls_authentication_t *value);
/** /**
* Get whether the context is configured to round robin queries over the available * Get whether the context is configured to round robin queries over the available
@ -1082,8 +1206,8 @@ getdns_context_get_tls_authentication(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_round_robin_upstreams(getdns_context *context, getdns_context_get_round_robin_upstreams(const getdns_context *context,
uint8_t* value); uint8_t *value);
/** /**
* Get the amount of seconds a TLS connection should not be tried with * Get the amount of seconds a TLS connection should not be tried with
@ -1097,8 +1221,8 @@ getdns_context_get_round_robin_upstreams(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_tls_backoff_time(getdns_context *context, getdns_context_get_tls_backoff_time(const getdns_context *context,
uint16_t* value); uint16_t *value);
/** /**
* Get the number of times getdns retries to setup DNS over TLS with a * Get the number of times getdns retries to setup DNS over TLS with a
@ -1112,8 +1236,8 @@ getdns_context_get_tls_backoff_time(getdns_context *context,
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_tls_connection_retries(getdns_context *context, getdns_context_get_tls_connection_retries(const getdns_context *context,
uint16_t* value); uint16_t *value);
/** /**
* Get the currently registered callback function and user defined argument * Get the currently registered callback function and user defined argument
@ -1130,7 +1254,8 @@ getdns_context_get_tls_connection_retries(getdns_context *context,
* @return GETDNS_RETURN_GOOD on success or an error code on failure. * @return GETDNS_RETURN_GOOD on success or an error code on failure.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_update_callback(getdns_context *context, void **userarg, getdns_context_get_update_callback(const getdns_context *context,
void **userarg,
void (**value) (getdns_context *, getdns_context_code_t, void *)); void (**value) (getdns_context *, getdns_context_code_t, void *));
@ -1184,7 +1309,7 @@ getdns_context_get_update_callback(getdns_context *context, void **userarg,
*/ */
getdns_return_t getdns_return_t
getdns_context_get_trust_anchors_url( getdns_context_get_trust_anchors_url(
getdns_context *context, const char **url); const getdns_context *context, const char **url);
/** /**
* Gets the public certificate for the Certificate Authority with which to * Gets the public certificate for the Certificate Authority with which to
@ -1203,7 +1328,7 @@ getdns_context_get_trust_anchors_url(
*/ */
getdns_return_t getdns_return_t
getdns_context_get_trust_anchors_verify_CA( getdns_context_get_trust_anchors_verify_CA(
getdns_context *context, const char **verify_CA); const getdns_context *context, const char **verify_CA);
/** /**
* Gets the email address for the Subject of the signer's certificate from the * Gets the email address for the Subject of the signer's certificate from the
@ -1220,7 +1345,21 @@ getdns_context_get_trust_anchors_verify_CA(
*/ */
getdns_return_t getdns_return_t
getdns_context_get_trust_anchors_verify_email( getdns_context_get_trust_anchors_verify_email(
getdns_context *context, const char **verify_email); const getdns_context *context, const char **verify_email);
/**
* Get the amount of milliseconds the trust anchors will not be tried to be
* fetched after failure.
* @see getdns_context_set_trust_anchors_backoff_time
* @param context The context to configure
* @param value Number of milliseconds before fetch trust anchors
* will be retried.
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null.
*/
getdns_return_t
getdns_context_get_trust_anchors_backoff_time(
const getdns_context *context, uint64_t *value);
/** /**
* Get the value with which the context's upstream recursive servers * Get the value with which the context's upstream recursive servers
@ -1233,7 +1372,8 @@ getdns_context_get_trust_anchors_verify_email(
* @return GETDNS_RETURN_GOOD when successful and error code otherwise. * @return GETDNS_RETURN_GOOD when successful and error code otherwise.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_resolvconf(getdns_context *context, const char **resolvconf); getdns_context_get_resolvconf(
const getdns_context *context, const char **resolvconf);
/** /**
* Get the value with which the context's GETDNS_NAMESPACE_LOCALNAMES namespace * Get the value with which the context's GETDNS_NAMESPACE_LOCALNAMES namespace
@ -1246,7 +1386,8 @@ getdns_context_get_resolvconf(getdns_context *context, const char **resolvconf);
* @return GETDNS_RETURN_GOOD when successful and error code otherwise. * @return GETDNS_RETURN_GOOD when successful and error code otherwise.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_hosts(getdns_context *context, const char **hosts); getdns_context_get_hosts(
const getdns_context *context, const char **hosts);
/** /**
* Get the location of the directory for CA certificates for verification * Get the location of the directory for CA certificates for verification
@ -1260,7 +1401,8 @@ getdns_context_get_hosts(getdns_context *context, const char **hosts);
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_tls_ca_path(getdns_context *context, const char **tls_ca_path); getdns_context_get_tls_ca_path(
const getdns_context *context, const char **tls_ca_path);
/** /**
* Get the file location with CA certificates for verification purposes. * Get the file location with CA certificates for verification purposes.
@ -1273,7 +1415,8 @@ getdns_context_get_tls_ca_path(getdns_context *context, const char **tls_ca_path
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL. * @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_get_tls_ca_file(getdns_context *context, const char **tls_ca_file); getdns_context_get_tls_ca_file(
const getdns_context *context, const char **tls_ca_file);
/** /**
* Get the list of available ciphers for authenticated TLS upstreams. * Get the list of available ciphers for authenticated TLS upstreams.
@ -1285,7 +1428,20 @@ getdns_context_get_tls_ca_file(getdns_context *context, const char **tls_ca_file
*/ */
getdns_return_t getdns_return_t
getdns_context_get_tls_cipher_list( getdns_context_get_tls_cipher_list(
getdns_context *context, const char **cipher_list); const getdns_context *context, const char **cipher_list);
/**
* Get the configured available TLS1.3 ciphersuited for authenticated TLS
* upstreams.
* @see getdns_context_set_tls_ciphersuites
* @param[in] context The context configure
* @param[out] ciphersuites The cipher list
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_get_tls_ciphersuites(
const getdns_context *context, const char **ciphersuites);
/** /**
* Get the supported curves list if one has been set earlier. * Get the supported curves list if one has been set earlier.
@ -1300,7 +1456,7 @@ getdns_context_get_tls_cipher_list(
*/ */
getdns_return_t getdns_return_t
getdns_context_get_tls_curves_list( getdns_context_get_tls_curves_list(
getdns_context *context, const char **curves_list); const getdns_context *context, const char **curves_list);
/** @} /** @}
*/ */
@ -1388,7 +1544,8 @@ const char *getdns_get_errorstr_by_id(uint16_t err);
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated * @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
*/ */
getdns_return_t getdns_return_t
getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value); getdns_dict_util_set_string(
getdns_dict *dict, const char *name, const char *value);
/** /**
* Get the string associated with the speicifed name. The string should not * Get the string associated with the speicifed name. The string should not
@ -1401,7 +1558,8 @@ getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value);
* @return GETDNS_RETURN_NO_SUCH_DICT_NAME if dict is invalid or name does not exist * @return GETDNS_RETURN_NO_SUCH_DICT_NAME if dict is invalid or name does not exist
*/ */
getdns_return_t getdns_return_t
getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result); getdns_dict_util_get_string(
const getdns_dict * dict, const char *name, char **result);
/** @} /** @}
*/ */
@ -1442,9 +1600,9 @@ getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result);
* return code. * return code.
*/ */
getdns_return_t getdns_return_t
getdns_validate_dnssec2(getdns_list *to_validate, getdns_validate_dnssec2(const getdns_list *to_validate,
getdns_list *support_records, const getdns_list *support_records,
getdns_list *trust_anchors, const getdns_list *trust_anchors,
time_t validation_time, uint32_t skew); time_t validation_time, uint32_t skew);
@ -1487,9 +1645,9 @@ getdns_validate_dnssec2(getdns_list *to_validate,
* @param str the pinning string to parse * @param str the pinning string to parse
* @return a dict created from ctx, or NULL if the string did not match. * @return a dict created from ctx, or NULL if the string did not match.
*/ */
getdns_dict* getdns_pubkey_pin_create_from_string( getdns_dict *getdns_pubkey_pin_create_from_string(
getdns_context* context, const getdns_context *context,
const char* str); const char *str);
/** /**
@ -1506,8 +1664,8 @@ getdns_dict* getdns_pubkey_pin_create_from_string(
* @return GETDNS_RETURN_GOOD if the pinset passes the sanity check. * @return GETDNS_RETURN_GOOD if the pinset passes the sanity check.
*/ */
getdns_return_t getdns_pubkey_pinset_sanity_check( getdns_return_t getdns_pubkey_pinset_sanity_check(
const getdns_list* pinset, const getdns_list *pinset,
getdns_list* errorlist); getdns_list *errorlist);
/** @} /** @}
*/ */
@ -2155,7 +2313,7 @@ getdns_context_set_listen_addresses(
*/ */
getdns_return_t getdns_return_t
getdns_reply(getdns_context *context, getdns_reply(getdns_context *context,
getdns_dict *reply, getdns_transaction_t request_id); const getdns_dict *reply, getdns_transaction_t request_id);
/** @} /** @}
@ -2179,7 +2337,7 @@ getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen);
* WARNING! Do not use this function. This function will be removed in * WARNING! Do not use this function. This function will be removed in
* future versions of getdns. * future versions of getdns.
*/ */
getdns_return_t getdns_context_process_async(getdns_context* context); getdns_return_t getdns_context_process_async(getdns_context *context);
/** /**
* Return the number of pending requests and the point of time of the next * Return the number of pending requests and the point of time of the next
@ -2187,8 +2345,8 @@ getdns_return_t getdns_context_process_async(getdns_context* context);
* WARNING! Do not use this function. This function will be removed in * WARNING! Do not use this function. This function will be removed in
* future versions of getdns. * future versions of getdns.
*/ */
uint32_t getdns_context_get_num_pending_requests(getdns_context* context, uint32_t getdns_context_get_num_pending_requests(const getdns_context *context,
struct timeval* next_timeout); struct timeval *next_timeout);
/** /**
* Detach the eventloop from the context. Resets the context with the default * Detach the eventloop from the context. Resets the context with the default
@ -2213,7 +2371,7 @@ getdns_context_detach_eventloop(getdns_context *context);
* @return GETDNS_RETURN_GOOD on success * @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_INVALID_PARAMETER if context is NULL * @return GETDNS_RETURN_INVALID_PARAMETER if context is NULL
*/ */
getdns_return_t getdns_context_set_use_threads(getdns_context* context, getdns_return_t getdns_context_set_use_threads(getdns_context *context,
int use_threads); int use_threads);
/** @} /** @}

View File

@ -3,7 +3,7 @@
# Meant to be run from this directory # Meant to be run from this directory
rm -fr gldns rm -fr gldns
mkdir gldns mkdir gldns
svn co http://unbound.net/svn/trunk/sldns/ svn co https://nlnetlabs.nl/svn/unbound/trunk/sldns/
mv gbuffer.h sbuffer.h mv gbuffer.h sbuffer.h
mv gbuffer.c sbuffer.c mv gbuffer.c sbuffer.c
for f in sldns/*.[ch] for f in sldns/*.[ch]

View File

@ -130,7 +130,7 @@ struct gldns_buffer
/** If the buffer is fixed it cannot be resized */ /** If the buffer is fixed it cannot be resized */
unsigned _fixed : 1; unsigned _fixed : 1;
/** If the buffer is vfixed, no more than capacity bytes willl be /** If the buffer is vfixed, no more than capacity bytes will be
* written to _data, however the _position counter will be updated * written to _data, however the _position counter will be updated
* with the amount that would have been written in consecutive * with the amount that would have been written in consecutive
* writes. This allows for a modus operandi in which a sequence is * writes. This allows for a modus operandi in which a sequence is
@ -160,7 +160,7 @@ gldns_buffer_invariant(gldns_buffer *buffer)
assert(buffer != NULL); assert(buffer != NULL);
assert(buffer->_position <= buffer->_limit || buffer->_vfixed); assert(buffer->_position <= buffer->_limit || buffer->_vfixed);
assert(buffer->_limit <= buffer->_capacity); assert(buffer->_limit <= buffer->_capacity);
assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0)); assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0 && buffer->_limit == 0));
} }
#endif #endif

View File

@ -16,7 +16,7 @@ then
mv sbuffer.h gbuffer.h mv sbuffer.h gbuffer.h
mv sbuffer.c gbuffer.c mv sbuffer.c gbuffer.c
else else
svn co http://unbound.net/svn/trunk/ldns/ svn co https://nlnetlabs.nl/svn/unbound/trunk/sldns/
for f in ldns/*.[ch] for f in ldns/*.[ch]
do do
sed -e 's/sldns_/gldns_/g' \ sed -e 's/sldns_/gldns_/g' \
@ -27,5 +27,5 @@ else
done done
mv sbuffer.h gbuffer.h mv sbuffer.h gbuffer.h
mv sbuffer.c gbuffer.c mv sbuffer.c gbuffer.c
rm -r ldns rm -fr sldns
fi fi

View File

@ -20,8 +20,11 @@
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/md5.h> #include <openssl/md5.h>
#ifdef HAVE_OPENSSL_CONF_H
# include <openssl/conf.h>
#endif
#ifdef HAVE_OPENSSL_ENGINE_H #ifdef HAVE_OPENSSL_ENGINE_H
# include <openssl/engine.h> # include <openssl/engine.h>
#endif #endif
#ifdef HAVE_OPENSSL_BN_H #ifdef HAVE_OPENSSL_BN_H
#include <openssl/bn.h> #include <openssl/bn.h>
@ -89,6 +92,14 @@ gldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
return 256; return 256;
case GLDNS_ECDSAP384SHA384: case GLDNS_ECDSAP384SHA384:
return 384; return 384;
#endif
#ifdef USE_ED25519
case GLDNS_ED25519:
return 256;
#endif
#ifdef USE_ED448
case GLDNS_ED448:
return 456;
#endif #endif
default: default:
return 0; return 0;
@ -122,6 +133,16 @@ uint16_t gldns_calc_keytag_raw(const uint8_t* key, size_t keysize)
#ifdef HAVE_SSL #ifdef HAVE_SSL
#ifdef USE_GOST #ifdef USE_GOST
/** store GOST engine reference loaded into OpenSSL library */ /** store GOST engine reference loaded into OpenSSL library */
#ifdef OPENSSL_NO_ENGINE
int
gldns_key_EVP_load_gost_id(void)
{
return 0;
}
void gldns_key_EVP_unload_gost(void)
{
}
#else
ENGINE* gldns_gost_engine = NULL; ENGINE* gldns_gost_engine = NULL;
int int
@ -181,6 +202,7 @@ void gldns_key_EVP_unload_gost(void)
gldns_gost_engine = NULL; gldns_gost_engine = NULL;
} }
} }
#endif /* ifndef OPENSSL_NO_ENGINE */
#endif /* USE_GOST */ #endif /* USE_GOST */
DSA * DSA *
@ -409,6 +431,27 @@ gldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
} }
#endif /* USE_ED25519 */ #endif /* USE_ED25519 */
#ifdef USE_ED448
EVP_PKEY*
gldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
{
/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
0x71, 0x03, 0x3a, 0x00};
int pre_len = 12;
uint8_t buf[256];
EVP_PKEY *evp_key;
/* pp gets modified by d2i() */
const unsigned char* pp = (unsigned char*)buf;
if(keylen != 57 || keylen + pre_len > sizeof(buf))
return NULL; /* wrong length */
memmove(buf, pre, pre_len);
memmove(buf+pre_len, key, keylen);
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
return evp_key;
}
#endif /* USE_ED448 */
int int
gldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, gldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
const EVP_MD* md) const EVP_MD* md)

View File

@ -101,6 +101,15 @@ RSA *gldns_key_buf2rsa_raw(unsigned char* key, size_t len);
*/ */
EVP_PKEY* gldns_ed255192pkey_raw(const unsigned char* key, size_t len); EVP_PKEY* gldns_ed255192pkey_raw(const unsigned char* key, size_t len);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with ED448.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_ed4482pkey_raw(const unsigned char* key, size_t len);
/** /**
* Utility function to calculate hash using generic EVP_MD pointer. * Utility function to calculate hash using generic EVP_MD pointer.
* \param[in] data the data to hash. * \param[in] data the data to hash.

View File

@ -58,7 +58,7 @@ time_t gldns_mktime_from_utc(const struct tm *tm);
* The function interprets time as the number of seconds since epoch * The function interprets time as the number of seconds since epoch
* with respect to now using serial arithmetics (rfc1982). * with respect to now using serial arithmetics (rfc1982).
* That number of seconds is then converted to broken-out time information. * That number of seconds is then converted to broken-out time information.
* This is especially useful when converting the inception and expiration * This is especially usefull when converting the inception and expiration
* fields of RRSIG records. * fields of RRSIG records.
* *
* \param[in] time number of seconds since epoch (midnight, January 1st, 1970) * \param[in] time number of seconds since epoch (midnight, January 1st, 1970)

View File

@ -150,6 +150,9 @@ static const gldns_rdf_type type_openpgpkey_wireformat[] = {
static const gldns_rdf_type type_csync_wireformat[] = { static const gldns_rdf_type type_csync_wireformat[] = {
GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_NSEC GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_NSEC
}; };
static const gldns_rdf_type type_zonemd_wireformat[] = {
GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT8, GLDNS_RDF_TYPE_INT8, GLDNS_RDF_TYPE_HEX
};
/* nsec3 is some vars, followed by same type of data of nsec */ /* nsec3 is some vars, followed by same type of data of nsec */
static const gldns_rdf_type type_nsec3_wireformat[] = { static const gldns_rdf_type type_nsec3_wireformat[] = {
/* GLDNS_RDF_TYPE_NSEC3_VARS, GLDNS_RDF_TYPE_NSEC3_NEXT_OWNER, GLDNS_RDF_TYPE_NSEC*/ /* GLDNS_RDF_TYPE_NSEC3_VARS, GLDNS_RDF_TYPE_NSEC3_NEXT_OWNER, GLDNS_RDF_TYPE_NSEC*/
@ -341,12 +344,9 @@ static gldns_rr_descriptor rdata_field_descriptors[] = {
{GLDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
/* 52 */ /* 52 */
{GLDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
/*53 */ /* 53 */
#ifdef DRAFT_RRTYPES
{GLDNS_RR_TYPE_SMIMEA, "SMIMEA", 4, 4, type_tlsa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_SMIMEA, "SMIMEA", 4, 4, type_tlsa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
#else /* 54 */
{GLDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
#endif
{GLDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
/* 55 /* 55
* Hip ends with 0 or more Rendezvous Servers represented as dname's. * Hip ends with 0 or more Rendezvous Servers represented as dname's.
@ -375,7 +375,8 @@ static gldns_rr_descriptor rdata_field_descriptors[] = {
{GLDNS_RR_TYPE_OPENPGPKEY, "OPENPGPKEY", 1, 1, type_openpgpkey_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_OPENPGPKEY, "OPENPGPKEY", 1, 1, type_openpgpkey_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
/* 62 */ /* 62 */
{GLDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
{GLDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, /* 63 */
{GLDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
{GLDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
{GLDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
{GLDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },

View File

@ -182,9 +182,7 @@ enum gldns_enum_rr_type
GLDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */ GLDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */
GLDNS_RR_TYPE_NSEC3PARAMS = 51, GLDNS_RR_TYPE_NSEC3PARAMS = 51,
GLDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */ GLDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
GLDNS_RR_TYPE_SMIMEA = 53, /* draft-ietf-dane-smime, TLSA-like but may GLDNS_RR_TYPE_SMIMEA = 53, /* RFC 8162 */
be extended */
GLDNS_RR_TYPE_HIP = 55, /* RFC 5205 */ GLDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
/** draft-reid-dnsext-zs */ /** draft-reid-dnsext-zs */
@ -197,6 +195,7 @@ enum gldns_enum_rr_type
GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */ GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */
GLDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ GLDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */
GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */
GLDNS_RR_TYPE_ZONEMD = 63, /* draft-wessels-dns-zone-digest */
GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */

View File

@ -1225,6 +1225,17 @@ int gldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len)
return GLDNS_WIREPARSE_ERR_OK; return GLDNS_WIREPARSE_ERR_OK;
} }
/** see if the string ends, or ends in whitespace */
static int
gldns_is_last_of_string(const char* str)
{
if(*str == 0) return 1;
while(isspace((unsigned char)*str))
str++;
if(*str == 0) return 1;
return 0;
}
int gldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) int gldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
{ {
const char* s = str; const char* s = str;
@ -1234,7 +1245,7 @@ int gldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
s++; s++;
continue; continue;
} }
if(dlen == 0 && *s == '0' && *(s+1) == 0) { if(dlen == 0 && *s == '0' && gldns_is_last_of_string(s+1)) {
*len = 0; *len = 0;
return GLDNS_WIREPARSE_ERR_OK; return GLDNS_WIREPARSE_ERR_OK;
} }

View File

@ -1065,7 +1065,11 @@ int gldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
d4 = (*d)[4]; d4 = (*d)[4];
d5 = (*d)[5]; d5 = (*d)[5];
tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5; tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
w = gldns_str_print(s, sl, "%"PRIu64, (uint64_t)tsigtime); #ifndef USE_WINSOCK
w = gldns_str_print(s, sl, "%llu", (long long)tsigtime);
#else
w = gldns_str_print(s, sl, "%I64u", (long long)tsigtime);
#endif
(*d)+=6; (*d)+=6;
(*dl)-=6; (*dl)-=6;
return w; return w;
@ -1752,8 +1756,13 @@ int gldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
if(error_code < llq_errors_num) if(error_code < llq_errors_num)
w += gldns_str_print(s, sl, " %s", llq_errors[error_code]); w += gldns_str_print(s, sl, " %s", llq_errors[error_code]);
else w += gldns_str_print(s, sl, " error %d", (int)error_code); else w += gldns_str_print(s, sl, " error %d", (int)error_code);
w += gldns_str_print(s, sl, " id %"PRIx64" lease-life %lu", #ifndef USE_WINSOCK
(uint64_t)llq_id, (unsigned long)lease_life); w += gldns_str_print(s, sl, " id %llx lease-life %lu",
(unsigned long long)llq_id, (unsigned long)lease_life);
#else
w += gldns_str_print(s, sl, " id %I64x lease-life %lu",
(unsigned long long)llq_id, (unsigned long)lease_life);
#endif
return w; return w;
} }

View File

@ -1,6 +1,7 @@
getdns_address getdns_address
getdns_address_sync getdns_address_sync
getdns_cancel_callback getdns_cancel_callback
getdns_context_
getdns_context_config getdns_context_config
getdns_context_create getdns_context_create
getdns_context_create_with_extended_memory_functions getdns_context_create_with_extended_memory_functions
@ -36,9 +37,13 @@ getdns_context_get_tls_backoff_time
getdns_context_get_tls_ca_file getdns_context_get_tls_ca_file
getdns_context_get_tls_ca_path getdns_context_get_tls_ca_path
getdns_context_get_tls_cipher_list getdns_context_get_tls_cipher_list
getdns_context_get_tls_ciphersuites
getdns_context_get_tls_connection_retries getdns_context_get_tls_connection_retries
getdns_context_get_tls_curves_list getdns_context_get_tls_curves_list
getdns_context_get_tls_max_version
getdns_context_get_tls_min_version
getdns_context_get_tls_query_padding_blocksize getdns_context_get_tls_query_padding_blocksize
getdns_context_get_trust_anchors_backoff_time
getdns_context_get_trust_anchors_url getdns_context_get_trust_anchors_url
getdns_context_get_trust_anchors_verify_CA getdns_context_get_trust_anchors_verify_CA
getdns_context_get_trust_anchors_verify_email getdns_context_get_trust_anchors_verify_email
@ -80,9 +85,13 @@ getdns_context_set_tls_backoff_time
getdns_context_set_tls_ca_file getdns_context_set_tls_ca_file
getdns_context_set_tls_ca_path getdns_context_set_tls_ca_path
getdns_context_set_tls_cipher_list getdns_context_set_tls_cipher_list
getdns_context_set_tls_ciphersuites
getdns_context_set_tls_connection_retries getdns_context_set_tls_connection_retries
getdns_context_set_tls_curves_list getdns_context_set_tls_curves_list
getdns_context_set_tls_max_version
getdns_context_set_tls_min_version
getdns_context_set_tls_query_padding_blocksize getdns_context_set_tls_query_padding_blocksize
getdns_context_set_trust_anchors_backoff_time
getdns_context_set_trust_anchors_url getdns_context_set_trust_anchors_url
getdns_context_set_trust_anchors_verify_CA getdns_context_set_trust_anchors_verify_CA
getdns_context_set_trust_anchors_verify_email getdns_context_set_trust_anchors_verify_email

View File

@ -418,7 +418,7 @@ getdns_list_create_with_memory_functions(void *(*malloc)(size_t),
/*-------------------------- getdns_list_create_with_context */ /*-------------------------- getdns_list_create_with_context */
struct getdns_list * struct getdns_list *
getdns_list_create_with_context(struct getdns_context *context) getdns_list_create_with_context(const getdns_context *context)
{ {
if (context) if (context)
return getdns_list_create_with_extended_memory_functions( return getdns_list_create_with_extended_memory_functions(

View File

@ -14,7 +14,7 @@ cat > const-info.c << END_OF_HEAD
static struct const_info consts_info[] = { static struct const_info consts_info[] = {
{ -1, NULL, "/* <unknown getdns value> */" }, { -1, NULL, "/* <unknown getdns value> */" },
END_OF_HEAD END_OF_HEAD
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%7d", $3); consts[key] = $1; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/^#define GETDNS_RRTYPE/ && !/^#define GETDNS_RRCLASS/ && !/^#define GETDNS_OPCODE/ && !/^#define GETDNS_RCODE/ && !/_TEXT/{ key = sprintf("%7d", $3); consts[key] = $2; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%7d", $4); consts[key] = $2; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ "val", \""name"\", "name"_TEXT },"}}' getdns/getdns_extra.h.in getdns/getdns.h.in const-info.h| sed 's/,,/,/g' >> const-info.c gawk --non-decimal-data '/^[ ]+GETDNS_[A-Z0-9_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%7d", $3); consts[key] = $1; }/^#define GETDNS_[A-Z0-9_]+[ ]+(0[xX][0-9a-fA-F]+|[0-9]+)/ && !/^#define GETDNS_RRTYPE/ && !/^#define GETDNS_RRCLASS/ && !/^#define GETDNS_OPCODE/ && !/^#define GETDNS_RCODE/ && !/_TEXT/{ key = sprintf("%7d", $3); consts[key] = $2; }/^#define GETDNS_[A-Z0-9_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%7d", $4); consts[key] = $2; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ "val", \""name"\", "name"_TEXT },"}}' getdns/getdns_extra.h.in getdns/getdns.h.in const-info.h| sed 's/,,/,/g' >> const-info.c
cat >> const-info.c << END_OF_TAIL cat >> const-info.c << END_OF_TAIL
}; };
@ -49,7 +49,7 @@ getdns_get_errorstr_by_id(uint16_t err)
static struct const_name_info consts_name_info[] = { static struct const_name_info consts_name_info[] = {
END_OF_TAIL END_OF_TAIL
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%d", $3); consts[$1] = key; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/_TEXT/{ key = sprintf("%d", $3); consts[$2] = key; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%d", $4); consts[$2] = key; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ \""val"\", "name" },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in const-info.h| sed 's/,,/,/g' >> const-info.c gawk --non-decimal-data '/^[ ]+GETDNS_[A-Z0-9_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%d", $3); consts[$1] = key; }/^#define GETDNS_[A-Z0-9_]+[ ]+(0[xX][0-9a-fA-F]+|[0-9]+)/ && !/_TEXT/{ key = sprintf("%d", $3); consts[$2] = key; }/^#define GETDNS_[A-Z0-9_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%d", $4); consts[$2] = key; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ \""val"\", "name" },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in const-info.h| sed 's/,,/,/g' >> const-info.c
cat >> const-info.c << END_OF_TAIL cat >> const-info.c << END_OF_TAIL
}; };

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
@ -92,16 +93,15 @@ static const getdns_bindata sha256 = {
It is the caller's responsibility to call getdns_dict_destroy when It is the caller's responsibility to call getdns_dict_destroy when
it is no longer needed. it is no longer needed.
*/ */
getdns_dict* getdns_pubkey_pin_create_from_string( getdns_dict *getdns_pubkey_pin_create_from_string(
getdns_context* context, const getdns_context *context, const char *str)
const char* str)
{ {
BIO *bio = NULL; BIO *bio = NULL;
size_t i; size_t i;
uint8_t buf[SHA256_DIGEST_LENGTH]; uint8_t buf[SHA256_DIGEST_LENGTH];
char inbuf[B64_ENCODED_SHA256_LENGTH + 1]; char inbuf[B64_ENCODED_SHA256_LENGTH + 1];
getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf }; getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf };
getdns_dict* out = NULL; getdns_dict *out = NULL;
/* we only do sha256 right now, make sure this is well-formed */ /* we only do sha256 right now, make sure this is well-formed */
if (!str || strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH)) if (!str || strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH))
@ -270,7 +270,7 @@ _getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list,
} }
getdns_return_t getdns_return_t
_getdns_get_pubkey_pinset_list(getdns_context *ctx, _getdns_get_pubkey_pinset_list(const getdns_context *ctx,
const sha256_pin_t *pinset_in, const sha256_pin_t *pinset_in,
getdns_list **pinset_list) getdns_list **pinset_list)
{ {
@ -378,20 +378,20 @@ _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
* the pinset. */ * the pinset. */
@ -407,29 +407,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 +482,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)); if (x_name) /* only when debugging */
return GETDNS_RETURN_GOOD; gldns_b64_ntop( p->pin , sizeof(p->pin)
} else , pin_str, sizeof(pin_str) );
DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p);
}
return ret; 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

@ -44,7 +44,7 @@ _getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list,
/* create a getdns_list version of the pinset */ /* create a getdns_list version of the pinset */
getdns_return_t getdns_return_t
_getdns_get_pubkey_pinset_list(getdns_context *ctx, _getdns_get_pubkey_pinset_list(const getdns_context *ctx,
const sha256_pin_t *pinset_in, const sha256_pin_t *pinset_in,
getdns_list **pinset_list); getdns_list **pinset_list);
@ -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

@ -92,7 +92,7 @@ getdns_dict *no_dnssec_checking_disabled_opportunistic
= &no_dnssec_checking_disabled_opportunistic_spc; = &no_dnssec_checking_disabled_opportunistic_spc;
static int static int
is_extension_set(getdns_dict *extensions, const char *name, int default_value) is_extension_set(const getdns_dict *extensions, const char *name, int default_value)
{ {
getdns_return_t r; getdns_return_t r;
uint32_t value; uint32_t value;
@ -167,7 +167,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
int with_opt, int edns_maximum_udp_payload_size, int with_opt, int edns_maximum_udp_payload_size,
uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit, uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit,
uint16_t opt_options_size, size_t noptions, getdns_list *options, uint16_t opt_options_size, size_t noptions, getdns_list *options,
size_t wire_data_sz, size_t max_query_sz, getdns_dict *extensions) size_t wire_data_sz, size_t max_query_sz, const getdns_dict *extensions)
{ {
uint8_t *buf; uint8_t *buf;
getdns_dict *option; getdns_dict *option;
@ -495,6 +495,9 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
void void
_getdns_network_validate_tsig(getdns_network_req *req) _getdns_network_validate_tsig(getdns_network_req *req)
{ {
#if defined(HAVE_NSS) || defined(HAVE_NETTLE)
(void)req;
#else
_getdns_rr_iter rr_spc, *rr; _getdns_rr_iter rr_spc, *rr;
_getdns_rdf_iter rdf_spc, *rdf; _getdns_rdf_iter rdf_spc, *rdf;
const uint8_t *request_mac; const uint8_t *request_mac;
@ -668,6 +671,7 @@ _getdns_network_validate_tsig(getdns_network_req *req)
gldns_write_uint16(req->response, gldns_read_uint16(req->query)); gldns_write_uint16(req->response, gldns_read_uint16(req->query));
gldns_write_uint16(req->response + 10, gldns_write_uint16(req->response + 10,
gldns_read_uint16(req->response + 10) + 1); gldns_read_uint16(req->response + 10) + 1);
#endif
} }
void void
@ -699,9 +703,12 @@ static const uint8_t no_suffixes[] = { 1, 0 };
/* create a new dns req to be submitted */ /* create a new dns req to be submitted */
getdns_dns_req * getdns_dns_req *
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions, const char *name, uint16_t request_type, const getdns_dict *extensions,
uint64_t *now_ms) uint64_t *now_ms)
{ {
int dnssec = is_extension_set(
extensions, "dnssec",
context->dnssec);
int dnssec_return_status = is_extension_set( int dnssec_return_status = is_extension_set(
extensions, "dnssec_return_status", extensions, "dnssec_return_status",
context->dnssec_return_status); context->dnssec_return_status);
@ -728,7 +735,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|| is_extension_set(extensions, "dnssec_roadblock_avoidance", || is_extension_set(extensions, "dnssec_roadblock_avoidance",
context->dnssec_roadblock_avoidance); context->dnssec_roadblock_avoidance);
#endif #endif
int dnssec_extension_set = dnssec_return_status int dnssec_extension_set = dnssec || dnssec_return_status
|| dnssec_return_only_secure || dnssec_return_all_statuses || dnssec_return_only_secure || dnssec_return_all_statuses
|| dnssec_return_validation_chain || dnssec_return_validation_chain
|| dnssec_return_full_validation_chain || dnssec_return_full_validation_chain
@ -776,6 +783,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
int opportunistic = 0; int opportunistic = 0;
if (extensions == no_dnssec_checking_disabled_opportunistic) { if (extensions == no_dnssec_checking_disabled_opportunistic) {
dnssec = 0;
dnssec_return_status = 0; dnssec_return_status = 0;
dnssec_return_only_secure = 0; dnssec_return_only_secure = 0;
dnssec_return_all_statuses = 0; dnssec_return_all_statuses = 0;
@ -956,6 +964,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->context = context; result->context = context;
result->loop = loop; result->loop = loop;
result->trans_id = (uint64_t) (intptr_t) result; result->trans_id = (uint64_t) (intptr_t) result;
result->dnssec = dnssec;
result->dnssec_return_status = dnssec_return_status; result->dnssec_return_status = dnssec_return_status;
result->dnssec_return_only_secure = dnssec_return_only_secure; result->dnssec_return_only_secure = dnssec_return_only_secure;
result->dnssec_return_all_statuses = dnssec_return_all_statuses; result->dnssec_return_all_statuses = dnssec_return_all_statuses;

View File

@ -613,6 +613,11 @@ static _getdns_rdata_def csync_rdata[] = {
{ "serial" , GETDNS_RDF_I4 , NULL }, { "serial" , GETDNS_RDF_I4 , NULL },
{ "flags" , GETDNS_RDF_I2 , NULL }, { "flags" , GETDNS_RDF_I2 , NULL },
{ "type_bit_maps" , GETDNS_RDF_X , NULL }}; { "type_bit_maps" , GETDNS_RDF_X , NULL }};
static _getdns_rdata_def zonemd_rdata[] = {
{ "serial" , GETDNS_RDF_I4 , NULL },
{ "digest_type" , GETDNS_RDF_I1 , NULL },
{ "reserved" , GETDNS_RDF_I1 , NULL },
{ "digest" , GETDNS_RDF_X , NULL }};
static _getdns_rdata_def spf_rdata[] = { static _getdns_rdata_def spf_rdata[] = {
{ "text" , GETDNS_RDF_S_M , NULL }}; { "text" , GETDNS_RDF_S_M , NULL }};
static _getdns_rdata_def nid_rdata[] = { static _getdns_rdata_def nid_rdata[] = {
@ -723,9 +728,9 @@ static _getdns_rr_def _getdns_rr_defs[] = {
{ "TALINK", talink_rdata, ALEN( talink_rdata) }, { "TALINK", talink_rdata, ALEN( talink_rdata) },
{ "CDS", ds_rdata, ALEN( ds_rdata) }, { "CDS", ds_rdata, ALEN( ds_rdata) },
{ "CDNSKEY", dnskey_rdata, ALEN( dnskey_rdata) }, { "CDNSKEY", dnskey_rdata, ALEN( dnskey_rdata) },
{ "OPENPGPKEY", openpgpkey_rdata, ALEN(openpgpkey_rdata) }, /* 61 - */ { "OPENPGPKEY", openpgpkey_rdata, ALEN(openpgpkey_rdata) },
{ "CSYNC", csync_rdata, ALEN( csync_rdata) }, /* - 62 */ { "CSYNC", csync_rdata, ALEN( csync_rdata) },
{ NULL, NULL, 0 }, { "ZONEMD", zonemd_rdata, ALEN( zonemd_rdata) }, /* - 63 */
{ NULL, NULL, 0 }, { NULL, NULL, 0 },
{ NULL, NULL, 0 }, { NULL, NULL, 0 },
{ NULL, NULL, 0 }, { NULL, NULL, 0 },

View File

@ -287,8 +287,8 @@ _getdns_cancel_reply(getdns_context *context, connection *conn)
} }
getdns_return_t getdns_return_t
getdns_reply( getdns_reply(getdns_context *context,
getdns_context *context, getdns_dict *reply, getdns_transaction_t request_id) const getdns_dict *reply, getdns_transaction_t request_id)
{ {
/* TODO: Check request_id at context->outbound_requests */ /* TODO: Check request_id at context->outbound_requests */
connection *conn = (connection *)(intptr_t)request_id; connection *conn = (connection *)(intptr_t)request_id;

View File

@ -58,6 +58,7 @@
#ifdef USE_DANESSL #ifdef USE_DANESSL
# include "ssl_dane/danessl.h" # include "ssl_dane/danessl.h"
#endif #endif
#include "const-info.h"
/* WSA TODO: /* WSA TODO:
* STUB_TCP_RETRY added to deal with edge triggered event loops (versus * STUB_TCP_RETRY added to deal with edge triggered event loops (versus
@ -886,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",
@ -931,8 +933,86 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
return NULL; return NULL;
} }
#if defined(HAVE_DECL_SSL_SET1_CURVES_LIST) && HAVE_DECL_SSL_SET1_CURVES_LIST #if defined(HAVE_DECL_SSL_SET1_CURVES_LIST) && HAVE_DECL_SSL_SET1_CURVES_LIST
if (upstream->tls_curves_list) if (upstream->tls_curves_list
(void) SSL_set1_curves_list(ssl, upstream->tls_curves_list); && !SSL_set1_curves_list(ssl, upstream->tls_curves_list)) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring tls_curves_list "
"\"%s\"\n", upstream->addr_str, upstream->tls_curves_list);
SSL_free(ssl);
return NULL;
}
#else
if (upstream->tls_curves_list) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : tls_curves_list not supported "
"in tls library\n", upstream->addr_str);
SSL_free(ssl);
return NULL;
}
#endif
#ifdef HAVE_SSL_SET_CIPHERSUITES
if (upstream->tls_ciphersuites &&
!SSL_set_ciphersuites(ssl, upstream->tls_ciphersuites)) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring tls_ciphersuites "
"\"%s\"\n", upstream->addr_str, upstream->tls_ciphersuites);
}
#else
if (upstream->tls_ciphersuites) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : tls_ciphersuites not "
"supported in tls library\n", upstream->addr_str);
SSL_free(ssl);
return NULL;
}
#endif
#if defined(HAVE_DECL_SSL_SET_MIN_PROTO_VERSION) \
&& HAVE_DECL_SSL_SET_MIN_PROTO_VERSION
if (upstream->tls_min_version && !SSL_set_min_proto_version(ssl,
_getdns_tls_version2openssl_version(upstream->tls_min_version))) {
struct const_info *ci =
_getdns_get_const_info(upstream->tls_min_version);
if (ci && *ci->name)
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring "
"tls_min_version \"%s\"\n", upstream->addr_str,
ci->name);
else
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring "
"tls_min_version \"%d\"\n", upstream->addr_str,
upstream->tls_min_version);
}
if (upstream->tls_max_version && !SSL_set_max_proto_version(ssl,
_getdns_tls_version2openssl_version(upstream->tls_max_version))) {
struct const_info *ci =
_getdns_get_const_info(upstream->tls_max_version);
if (ci && *ci->name)
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring "
"tls_max_version \"%s\"\n", upstream->addr_str,
ci->name);
else
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring "
"tls_max_version \"%d\"\n", upstream->addr_str,
upstream->tls_max_version);
}
#else
if (upstream->tls_min_version) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : tls_min_version not "
"supported in tls library\n", upstream->addr_str);
SSL_free(ssl);
return NULL;
}
if (upstream->tls_max_version) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : tls_max_version not "
"supported in tls library\n", upstream->addr_str);
SSL_free(ssl);
return NULL;
}
#endif #endif
/* make sure we'll be able to find the context again when we need it */ /* make sure we'll be able to find the context again when we need it */
if (_getdns_associate_upstream_with_SSL(ssl, upstream) != GETDNS_RETURN_GOOD) { if (_getdns_associate_upstream_with_SSL(ssl, upstream) != GETDNS_RETURN_GOOD) {
@ -1006,8 +1086,13 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
DEBUG_STUB("%s %-35s: WARNING: Using Oppotunistic TLS (fallback allowed)!\n", DEBUG_STUB("%s %-35s: WARNING: Using Oppotunistic TLS (fallback allowed)!\n",
STUB_DEBUG_SETUP_TLS, __FUNC__); STUB_DEBUG_SETUP_TLS, __FUNC__);
} else { } else {
if (upstream->tls_cipher_list) if (upstream->tls_cipher_list &&
SSL_set_cipher_list(ssl, upstream->tls_cipher_list); !SSL_set_cipher_list(ssl, upstream->tls_cipher_list))
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : Error configuring cipher_list\"%s\"\n",
upstream->addr_str, upstream->tls_cipher_list);
DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS, DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS,
__FUNC__); __FUNC__);
} }
@ -1139,10 +1224,10 @@ tls_do_handshake(getdns_upstream *upstream)
long verify_result = SSL_get_verify_result(upstream->tls_obj); long verify_result = SSL_get_verify_result(upstream->tls_obj);
/* In case of DANESSL use, and a tls_auth_name was given alongside a pinset, /* In case of DANESSL use, and a tls_auth_name was given alongside a pinset,
* we need to verify auth_name explicitely (otherwise it will not be checked, * we need to verify auth_name explicitly (otherwise it will not be checked,
* because this is not required with DANE with an EE match). * because this is not required with DANE with an EE match).
* This is not needed with native OpenSSL DANE, because EE name checks have * This is not needed with native OpenSSL DANE, because EE name checks have
* to be disabled explicitely. * to be disabled explicitly.
*/ */
#if defined(HAVE_X509_CHECK_HOST) && (defined(USE_DANESSL) || !defined(HAVE_SSL_HN_AUTH)) #if defined(HAVE_X509_CHECK_HOST) && (defined(USE_DANESSL) || !defined(HAVE_SSL_HN_AUTH))
int xch; int xch;
@ -2059,7 +2144,7 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
if (upstreams->upstreams[i].conn_state == GETDNS_CONN_BACKOFF && if (upstreams->upstreams[i].conn_state == GETDNS_CONN_BACKOFF &&
upstreams->upstreams[i].conn_retry_time < now) { upstreams->upstreams[i].conn_retry_time < now) {
upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED; upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED;
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE, _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING,
"%-40s : Upstream : Re-instating %s for this upstream\n", "%-40s : Upstream : Re-instating %s for this upstream\n",
upstreams->upstreams[i].addr_str, upstreams->upstreams[i].addr_str,
upstreams->upstreams[i].transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"); upstreams->upstreams[i].transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP");
@ -2318,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;
} }

View File

@ -164,7 +164,7 @@ getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type,
getdns_return_t getdns_return_t
getdns_general_sync(getdns_context *context, const char *name, getdns_general_sync(getdns_context *context, const char *name,
uint16_t request_type, getdns_dict *extensions, getdns_dict **response) uint16_t request_type, const getdns_dict *extensions, getdns_dict **response)
{ {
getdns_sync_data data; getdns_sync_data data;
getdns_return_t r; getdns_return_t r;
@ -190,7 +190,7 @@ getdns_general_sync(getdns_context *context, const char *name,
getdns_return_t getdns_return_t
getdns_address_sync(getdns_context *context, const char *name, getdns_address_sync(getdns_context *context, const char *name,
getdns_dict *extensions, getdns_dict **response) const getdns_dict *extensions, getdns_dict **response)
{ {
getdns_sync_data data; getdns_sync_data data;
getdns_return_t r; getdns_return_t r;
@ -215,8 +215,8 @@ getdns_address_sync(getdns_context *context, const char *name,
} }
getdns_return_t getdns_return_t
getdns_hostname_sync(getdns_context *context, getdns_dict *address, getdns_hostname_sync(getdns_context *context, const getdns_dict *address,
getdns_dict *extensions, getdns_dict **response) const getdns_dict *extensions, getdns_dict **response)
{ {
getdns_sync_data data; getdns_sync_data data;
getdns_return_t r; getdns_return_t r;
@ -242,7 +242,7 @@ getdns_hostname_sync(getdns_context *context, getdns_dict *address,
getdns_return_t getdns_return_t
getdns_service_sync(getdns_context *context, const char *name, getdns_service_sync(getdns_context *context, const char *name,
getdns_dict *extensions, getdns_dict **response) const getdns_dict *extensions, getdns_dict **response)
{ {
getdns_sync_data data; getdns_sync_data data;
getdns_return_t r; getdns_return_t r;

View File

@ -178,7 +178,7 @@
{ {
/* /*
* name = "localhost" name should be resolved from host file * name = "localhost" name should be resolved from host file
* expect: NOERROR/NODATA response: * expect: NOERROR response:
* status = GETDNS_RESPSTATUS_GOOD * status = GETDNS_RESPSTATUS_GOOD
* rcode = 0 * rcode = 0
* ancount = 1 (number of records in ANSWER section) * ancount = 1 (number of records in ANSWER section)
@ -192,7 +192,7 @@
CONTEXT_CREATE(TRUE); CONTEXT_CREATE(TRUE);
EVENT_BASE_CREATE; EVENT_BASE_CREATE;
ASSERT_RC(getdns_address(context, "localhost", NULL, ASSERT_RC(getdns_address(context, "localhost.", NULL,
&fn_ref, &transaction_id, callbackfn), &fn_ref, &transaction_id, callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_address()"); GETDNS_RETURN_GOOD, "Return code from getdns_address()");

View File

@ -127,7 +127,7 @@
CONTEXT_CREATE(TRUE); CONTEXT_CREATE(TRUE);
ASSERT_RC(getdns_address_sync(context, "localhost", NULL, &response), ASSERT_RC(getdns_address_sync(context, "localhost.", NULL, &response),
GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()");
EXTRACT_LOCAL_RESPONSE; EXTRACT_LOCAL_RESPONSE;
@ -147,7 +147,7 @@
/* /*
* name = "willem.getdnsapi.net" need to replace this with domain from unbound zone * name = "willem.getdnsapi.net" need to replace this with domain from unbound zone
* expect: NOERROR/NODATA response: * expect: NOERROR/NODATA response:
* status = GETDNS_RESPSTATUS_GOOD * status = GETDNS_RESPSTATUS_NO_DATA
* rcode = 0 * rcode = 0
* ancount = 0 (number of records in ANSWER section) * ancount = 0 (number of records in ANSWER section)
*/ */
@ -162,6 +162,7 @@
EXTRACT_RESPONSE; EXTRACT_RESPONSE;
assert_noerror(&ex_response); assert_noerror(&ex_response);
assert_nodata(&ex_response);
//assert_soa_in_authority(&ex_response); //assert_soa_in_authority(&ex_response);
CONTEXT_DESTROY; CONTEXT_DESTROY;

View File

@ -70,6 +70,7 @@ void extract_response(struct getdns_dict *response, struct extracted_response *e
* If it is absent, do not try to decompose the replies_tree, because the * If it is absent, do not try to decompose the replies_tree, because the
* answer most likely came not from DNS. * answer most likely came not from DNS.
*/ */
ex_response->response = response;
have_answer_type = getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type) == have_answer_type = getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type) ==
GETDNS_RETURN_GOOD; GETDNS_RETURN_GOOD;
@ -159,10 +160,15 @@ void extract_local_response(struct getdns_dict *response, struct extracted_respo
void assert_noerror(struct extracted_response *ex_response) void assert_noerror(struct extracted_response *ex_response)
{ {
uint32_t rcode; uint32_t rcode;
uint32_t ancount = 0;
ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\"");
ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\"");
ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode); ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode);
ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount),
GETDNS_RETURN_GOOD, "Failed to extract \"ancount\"");
ASSERT_RC(ex_response->status, ((ancount > 0) ? GETDNS_RESPSTATUS_GOOD : GETDNS_RESPSTATUS_NO_NAME), "Unexpected value for \"status\"");
} }
/* /*
@ -181,6 +187,8 @@ void assert_nodata(struct extracted_response *ex_response)
ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), ASSERT_RC(getdns_list_get_length(ex_response->answer, &length),
GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length");
ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length);
ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_NO_NAME, "Unexpected value for \"status\"");
} }
/* /*
@ -233,11 +241,14 @@ void assert_address_in_answer(struct extracted_response *ex_response, int a, int
*/ */
void assert_address_in_just_address_answers(struct extracted_response *ex_response) void assert_address_in_just_address_answers(struct extracted_response *ex_response)
{ {
size_t length; size_t length = 0;
char *resp_str = "";
ASSERT_RC(getdns_list_get_length(ex_response->just_address_answers, &length), ASSERT_RC(getdns_list_get_length(ex_response->just_address_answers, &length),
GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\" length"); GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\" length");
ck_assert_msg(length > 0, "Expected \"just_address_answers\" length > 0, got %d", length); if (length == 0) resp_str = getdns_pretty_print_dict(ex_response->response);
ck_assert_msg(length > 0, "Expected \"just_address_answers\" length > 0, got %d\n%s", length, resp_str);
if (length == 0) free(resp_str);
} }
/* /*

View File

@ -41,6 +41,7 @@
struct extracted_response { struct extracted_response {
uint32_t top_answer_type; uint32_t top_answer_type;
struct getdns_dict *response;
struct getdns_bindata *top_canonical_name; struct getdns_bindata *top_canonical_name;
struct getdns_list *just_address_answers; struct getdns_list *just_address_answers;
struct getdns_list *replies_full; struct getdns_list *replies_full;

View File

@ -264,8 +264,6 @@
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()"); GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()");
ASSERT_RC(getdns_context_set_edns_maximum_udp_payload_size(context, 512), ASSERT_RC(getdns_context_set_edns_maximum_udp_payload_size(context, 512),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_edns_maximum_udp_payload_size()"); GETDNS_RETURN_GOOD, "Return code from getdns_context_set_edns_maximum_udp_payload_size()");
ASSERT_RC(getdns_context_set_timeout(context, 2000),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_edns_maximum_udp_payload_size()");
ASSERT_RC(getdns_general_sync(context, "large.getdnsapi.net", GETDNS_RRTYPE_TXT, extensions, &response), ASSERT_RC(getdns_general_sync(context, "large.getdnsapi.net", GETDNS_RRTYPE_TXT, extensions, &response),
GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()");
@ -292,17 +290,14 @@
struct getdns_dict *extensions = getdns_dict_create(); struct getdns_dict *extensions = getdns_dict_create();
/* /*
* Not all servers in the path to large.getdnsapi.net seem to support * Not all root servers seem to support TCP reliably. To mitigate,
* TCP consistently. Many (root) servers are anycasted which decreases * we put our faith in k.root-servers.net.
* reliability of TCP availability (as we've seen in practice).
* To mitigate we provide our own root server for which we are sure that
* it supports TCP. The .net authoritative server are still out of our
* control tough. But because they are managed by a single party I
* suspect them to be a bit more reliable.
*/ */
struct getdns_list *root_servers = getdns_list_create(); struct getdns_list *root_servers = getdns_list_create();
struct getdns_list *root_servers2 = getdns_list_create(); struct getdns_list *root_servers2 = getdns_list_create();
struct getdns_bindata nlnetlabs_root = { 4, (void *)"\xB9\x31\x8D\x25" }; struct getdns_bindata k4_root = { 4, (void *)"\xC1\x00\x0E\x81" };
struct getdns_bindata k6_root = { 16, (void *)
"\x20\x01\x07\xFD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" };
struct getdns_bindata *answer = NULL; struct getdns_bindata *answer = NULL;
uint32_t status; uint32_t status;
@ -319,7 +314,9 @@
/* Re-do over TCP */ /* Re-do over TCP */
ASSERT_RC(getdns_dict_set_int(extensions,"return_call_reporting", GETDNS_EXTENSION_TRUE), ASSERT_RC(getdns_dict_set_int(extensions,"return_call_reporting", GETDNS_EXTENSION_TRUE),
GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()");
ASSERT_RC(getdns_list_set_bindata(root_servers, 0, &nlnetlabs_root), ASSERT_RC(getdns_list_set_bindata(root_servers, 0, &k6_root),
GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()");
ASSERT_RC(getdns_list_set_bindata(root_servers, 1, &k4_root),
GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()"); GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()");
ASSERT_RC(getdns_context_set_dns_root_servers(context, root_servers), ASSERT_RC(getdns_context_set_dns_root_servers(context, root_servers),
@ -328,8 +325,13 @@
GETDNS_RETURN_GOOD, "Return code from getdns_context_get_dns_root_servers()"); GETDNS_RETURN_GOOD, "Return code from getdns_context_get_dns_root_servers()");
ASSERT_RC(getdns_list_get_bindata(root_servers2, 0, &answer), ASSERT_RC(getdns_list_get_bindata(root_servers2, 0, &answer),
GETDNS_RETURN_GOOD, "Return code from getdns_list_get_bindata()"); GETDNS_RETURN_GOOD, "Return code from getdns_list_get_bindata()");
ck_assert_msg(strncmp((char *)answer->data, (char *)nlnetlabs_root.data, 4) == 0, ck_assert_msg(strncmp((char *)answer->data, (char *)k6_root.data, 16) == 0,
"Expected answer data to be 185.49.141.37"); "Expected answer data to be 2001:7fd::1");
ASSERT_RC(getdns_list_get_bindata(root_servers2, 1, &answer),
GETDNS_RETURN_GOOD, "Return code from getdns_list_get_bindata()");
ck_assert_msg(strncmp((char *)answer->data, (char *)k4_root.data, 4) == 0,
"Expected answer data to be 193.0.14.129");
ASSERT_RC(getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TCP_ONLY), ASSERT_RC(getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TCP_ONLY),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()"); GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()");
ASSERT_RC(getdns_context_set_edns_maximum_udp_payload_size(context, 512), ASSERT_RC(getdns_context_set_edns_maximum_udp_payload_size(context, 512),

View File

@ -146,7 +146,7 @@
* name = "google.com" * name = "google.com"
* request_type = 0 (minimum valid RRTYPE) * request_type = 0 (minimum valid RRTYPE)
* expect: NOERROR/NODATA response: * expect: NOERROR/NODATA response:
* status = GETDNS_RESPSTATUS_GOOD * status = GETDNS_RESPSTATUS_NO_NAME
* rcode = 0 * rcode = 0
* ancount = 0 (number of records in ANSWER section) * ancount = 0 (number of records in ANSWER section)
*/ */
@ -180,7 +180,7 @@
* name = "google.com" * name = "google.com"
* request_type = 65279 (maximum unassigned RRTYPE) * request_type = 65279 (maximum unassigned RRTYPE)
* expect: NOERROR/NODATA response: * expect: NOERROR/NODATA response:
* status = GETDNS_RESPSTATUS_GOOD * status = GETDNS_RESPSTATUS_NO_NAME
* rcode = 0 * rcode = 0
* ancount = 0 (number of records in ANSWER section) * ancount = 0 (number of records in ANSWER section)
*/ */
@ -322,7 +322,7 @@
* name = "willem.getdnsapi.net" and unbound zone * name = "willem.getdnsapi.net" and unbound zone
* request_type = GETDNS_RRTYPE_MX * request_type = GETDNS_RRTYPE_MX
* expect: NOERROR/NODATA response: * expect: NOERROR/NODATA response:
* status = GETDNS_RESPSTATUS_GOOD * status = GETDNS_RESPSTATUS_NO_NAME
* rcode = 0 * rcode = 0
* ancount = 0 (number of records in ANSWER section) * ancount = 0 (number of records in ANSWER section)
*/ */

View File

@ -128,7 +128,7 @@
* name = "google.com" * name = "google.com"
* request_type = 0 (minimum valid RRTYPE) * request_type = 0 (minimum valid RRTYPE)
* expect: NOERROR/NODATA response: * expect: NOERROR/NODATA response:
* status = GETDNS_RESPSTATUS_GOOD * status = GETDNS_RESPSTATUS_NO_NAME
* rcode = 0 * rcode = 0
* ancount = 0 (number of records in ANSWER section) * ancount = 0 (number of records in ANSWER section)
*/ */
@ -155,7 +155,7 @@
* name = "google.com" * name = "google.com"
* request_type = 65279 (maximum unassigned RRTYPE) * request_type = 65279 (maximum unassigned RRTYPE)
* expect: NOERROR/NODATA response: * expect: NOERROR/NODATA response:
* status = GETDNS_RESPSTATUS_GOOD * status = GETDNS_RESPSTATUS_NO_NAME
* rcode = 0 * rcode = 0
* ancount = 0 (number of records in ANSWER section) * ancount = 0 (number of records in ANSWER section)
*/ */
@ -269,7 +269,7 @@
* name = "willem.getdnsapi.net" an unbound zone (as in no MX) * name = "willem.getdnsapi.net" an unbound zone (as in no MX)
* request_type = GETDNS_RRTYPE_MX * request_type = GETDNS_RRTYPE_MX
* expect: NOERROR/NODATA response: * expect: NOERROR/NODATA response:
* status = GETDNS_RESPSTATUS_GOOD * status = GETDNS_RESPSTATUS_NO_NAME
* rcode = 0 * rcode = 0
* ancount = 0 (number of records in ANSWER section) * ancount = 0 (number of records in ANSWER section)
*/ */

View File

@ -10,8 +10,8 @@ then
else else
HAVE_SSL_HN_AUTH=0 HAVE_SSL_HN_AUTH=0
fi fi
SERVER_IP="8.8.8.8" SERVER_IP="64.6.64.6"
SERVER_IPv6="2001:4860:4860::8888" SERVER_IPv6="2620:74:1b::1:1"
SERVER_IP_TSIG="185.49.141.37^" SERVER_IP_TSIG="185.49.141.37^"
SERVER_IPv6_TSIG="2a04:b900:0:100::37^" SERVER_IPv6_TSIG="2a04:b900:0:100::37^"
@ -134,7 +134,7 @@ for (( ii = 0; ii < 1; ii++)); do
if [[ $HAVE_SSL_HN_AUTH = 1 ]] if [[ $HAVE_SSL_HN_AUTH = 1 ]]
then then
NUM_GOOD_QUERIES=9 NUM_GOOD_QUERIES=8
GOOD_QUERIES=( GOOD_QUERIES=(
"-s -A getdnsapi.net -l U @${SERVER_IP} +edns_cookies" "U" "-" "-s -A getdnsapi.net -l U @${SERVER_IP} +edns_cookies" "U" "-"
"-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-" "-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-"
@ -143,18 +143,18 @@ for (( ii = 0; ii < 1; ii++)); do
"-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N" "-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP}" "L" "S" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP}" "L" "S"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S")
"-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-") # "-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-")
else else
NUM_GOOD_QUERIES=7 NUM_GOOD_QUERIES=6
GOOD_QUERIES=( GOOD_QUERIES=(
"-s -A getdnsapi.net -l U @${SERVER_IP} +edns_cookies" "U" "-" "-s -A getdnsapi.net -l U @${SERVER_IP} +edns_cookies" "U" "-"
"-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-" "-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-"
"-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_ALG}:${TSIG_NAME}:${TSIG_SECRET}" "U" "-" "-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_ALG}:${TSIG_NAME}:${TSIG_SECRET}" "U" "-"
"-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_NAME}:${TSIG_SECRET}" "U" "-" "-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_NAME}:${TSIG_SECRET}" "U" "-"
"-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N" "-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S")
"-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-") # "-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-")
fi fi
#"-s -A getdnsapi.net -l L -m @${TLS_SERVER_SS_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_SS_KEY}\"" "L" "S" #"-s -A getdnsapi.net -l L -m @${TLS_SERVER_SS_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_SS_KEY}\"" "L" "S"

View File

@ -3,8 +3,9 @@
export SRCDIR=`dirname $0` export SRCDIR=`dirname $0`
. `dirname $0`/setup-env.sh . `dirname $0`/setup-env.sh
# pass a single test name as the first parameter (without .tpgk extension) # pass a single test name as the first parameter
ONE_TEST=$1 ONE_TEST=${1%/}
ONE_TEST=${ONE_TEST%.tpkg}
shift shift
"${TPKG}" $* exe ${SRCDIR}/${ONE_TEST}.tpkg "${TPKG}" $* exe ${SRCDIR}/${ONE_TEST}.tpkg

View File

@ -183,6 +183,7 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\ntsig spec: [<algorithm>:]<name>:<secret in Base64>\n"); fprintf(out, "\ntsig spec: [<algorithm>:]<name>:<secret in Base64>\n");
fprintf(out, "\nextensions:\n"); fprintf(out, "\nextensions:\n");
fprintf(out, "\t+add_warning_for_bad_dns\n"); fprintf(out, "\t+add_warning_for_bad_dns\n");
fprintf(out, "\t+dnssec\n");
fprintf(out, "\t+dnssec_return_status\n"); fprintf(out, "\t+dnssec_return_status\n");
fprintf(out, "\t+dnssec_return_only_secure\n"); fprintf(out, "\t+dnssec_return_only_secure\n");
fprintf(out, "\t+dnssec_return_all_statuses\n"); fprintf(out, "\t+dnssec_return_all_statuses\n");
@ -580,11 +581,15 @@ getdns_return_t parse_args(int argc, char **argv)
size_t upstream_count = 0; size_t upstream_count = 0;
FILE *fh; FILE *fh;
int int_value; int int_value;
int got_rrtype = 0;
int got_calltype = 0;
int got_qname = 0;
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
arg = argv[i]; arg = argv[i];
if ((t = get_rrtype(arg)) >= 0) { if ((t = get_rrtype(arg)) >= 0) {
request_type = t; request_type = t;
got_rrtype = 1;
continue; continue;
} else if (arg[0] == '+') { } else if (arg[0] == '+') {
@ -653,6 +658,7 @@ getdns_return_t parse_args(int argc, char **argv)
continue; continue;
} else if (arg[0] != '-') { } else if (arg[0] != '-') {
got_qname = 1;
name = arg; name = arg;
continue; continue;
} }
@ -666,6 +672,7 @@ getdns_return_t parse_args(int argc, char **argv)
break; break;
case 'A': case 'A':
calltype = ADDRESS; calltype = ADDRESS;
got_calltype = 1;
break; break;
case 'b': case 'b':
if (c[1] != 0 || ++i >= argc || !*argv[i]) { if (c[1] != 0 || ++i >= argc || !*argv[i]) {
@ -739,9 +746,11 @@ getdns_return_t parse_args(int argc, char **argv)
break; break;
case 'G': case 'G':
calltype = GENERAL; calltype = GENERAL;
got_calltype = 1;
break; break;
case 'H': case 'H':
calltype = HOSTNAME; calltype = HOSTNAME;
got_calltype = 1;
break; break;
case 'h': case 'h':
print_usage(stdout, argv[0]); print_usage(stdout, argv[0]);
@ -870,6 +879,7 @@ getdns_return_t parse_args(int argc, char **argv)
break; break;
case 'S': case 'S':
calltype = SERVICE; calltype = SERVICE;
got_calltype = 1;
break; break;
case 't': case 't':
if (c[1] != 0 || ++i >= argc || !*argv[i]) { if (c[1] != 0 || ++i >= argc || !*argv[i]) {
@ -1093,6 +1103,9 @@ getdns_return_t parse_args(int argc, char **argv)
} }
next: ; next: ;
} }
if (!got_calltype && !got_rrtype && got_qname) {
calltype = ADDRESS;
}
if (r) if (r)
return r; return r;
if (pubkey_pinset && upstream_count) { if (pubkey_pinset && upstream_count) {

View File

@ -25,6 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "config.h"
#include <ctype.h> #include <ctype.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
@ -217,8 +218,11 @@ static bool extract_cert_expiry(const unsigned char *data, size_t len, time_t *t
int day_diff, sec_diff; int day_diff, sec_diff;
const long SECS_IN_DAY = 60 * 60 * 24; const long SECS_IN_DAY = 60 * 60 * 24;
ASN1_TIME *not_after = X509_get_notAfter(cert); #if defined(X509_get_notAfter) || defined(HAVE_X509_GET_NOTAFTER)
const ASN1_TIME *not_after = X509_get_notAfter(cert);
#elif defined(X509_get0_notAfter) || defined(HAVE_X509_GET0_NOTAFTER)
const ASN1_TIME *not_after = X509_get0_notAfter(cert);
#endif
*t = time(NULL); *t = time(NULL);
#if OPENSSL_VERSION_NUMBER < 0x10002000 || defined(LIBRESSL_VERSION_NUMBER) #if OPENSSL_VERSION_NUMBER < 0x10002000 || defined(LIBRESSL_VERSION_NUMBER)

View File

@ -299,6 +299,7 @@ typedef struct getdns_dns_req {
unsigned suffix_appended : 1; unsigned suffix_appended : 1;
/* request extensions */ /* request extensions */
unsigned dnssec : 1;
unsigned dnssec_return_status : 1; unsigned dnssec_return_status : 1;
unsigned dnssec_return_only_secure : 1; unsigned dnssec_return_only_secure : 1;
unsigned dnssec_return_all_statuses : 1; unsigned dnssec_return_all_statuses : 1;
@ -431,7 +432,8 @@ extern getdns_dict *no_dnssec_checking_disabled_opportunistic;
/* dns request utils */ /* dns request utils */
getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions, uint64_t *now_ms); const char *name, uint16_t request_type, const getdns_dict *extensions,
uint64_t *now_ms);
void _getdns_dns_req_free(getdns_dns_req * req); void _getdns_dns_req_free(getdns_dns_req * req);

View File

@ -54,7 +54,8 @@
getdns_return_t getdns_return_t
getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result) getdns_dict_util_get_string(const getdns_dict *dict,
const char *name, char **result)
{ {
struct getdns_bindata *bindata = NULL; struct getdns_bindata *bindata = NULL;
if (!result) { if (!result) {
@ -710,7 +711,7 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req,
else goto error; else goto error;
/* other stuff /* other stuff
* Note that spec doesn't explicitely mention these. * Note that spec doesn't explicitly mention these.
* They are only showcased in the response dict example */ * They are only showcased in the response dict example */
if (getdns_dict_set_int(result, "answer_type", GETDNS_NAMETYPE_DNS)) if (getdns_dict_set_int(result, "answer_type", GETDNS_NAMETYPE_DNS))
goto error; goto error;
@ -1119,9 +1120,11 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
int rrsigs_in_answer = 0; int rrsigs_in_answer = 0;
getdns_dict *reply; getdns_dict *reply;
getdns_bindata *canonical_name = NULL; getdns_bindata *canonical_name = NULL;
int nreplies = 0, nanswers = 0, nsecure = 0, ninsecure = 0, nbogus = 0; int nreplies = 0, nanswers = 0;
int nsecure = 0, ninsecure = 0, nindeterminate = 0, nbogus = 0;
getdns_dict *netreq_debug; getdns_dict *netreq_debug;
_srvs srvs = { 0, 0, NULL }; _srvs srvs = { 0, 0, NULL };
_getdns_rrset_spc answer_spc;
/* info (bools) about dns_req */ /* info (bools) about dns_req */
int dnssec_return_status; int dnssec_return_status;
@ -1133,7 +1136,8 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
if (!(result = getdns_dict_create_with_context(context))) if (!(result = getdns_dict_create_with_context(context)))
return NULL; return NULL;
dnssec_return_status = completed_request->dnssec_return_status || dnssec_return_status = completed_request->dnssec ||
completed_request->dnssec_return_status ||
completed_request->dnssec_return_only_secure || completed_request->dnssec_return_only_secure ||
completed_request->dnssec_return_all_statuses completed_request->dnssec_return_all_statuses
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
@ -1192,16 +1196,18 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
_getdns_network_validate_tsig(netreq); _getdns_network_validate_tsig(netreq);
nreplies++; nreplies++;
if (netreq->dnssec_status == GETDNS_DNSSEC_SECURE) switch (netreq->dnssec_status) {
nsecure++; case GETDNS_DNSSEC_SECURE : nsecure++;
else if (netreq->dnssec_status != GETDNS_DNSSEC_BOGUS) break;
ninsecure++; case GETDNS_DNSSEC_INSECURE : ninsecure++;
break;
if (dnssec_return_status && case GETDNS_DNSSEC_INDETERMINATE: nindeterminate++;
netreq->dnssec_status == GETDNS_DNSSEC_BOGUS) ninsecure++;
nbogus++; break;
case GETDNS_DNSSEC_BOGUS : if (dnssec_return_status)
nbogus++;
break;
}
if (! completed_request->dnssec_return_all_statuses && if (! completed_request->dnssec_return_all_statuses &&
! completed_request->dnssec_return_validation_chain) { ! completed_request->dnssec_return_validation_chain) {
if (dnssec_return_status && if (dnssec_return_status &&
@ -1210,6 +1216,9 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
else if (completed_request->dnssec_return_only_secure else if (completed_request->dnssec_return_only_secure
&& netreq->dnssec_status != GETDNS_DNSSEC_SECURE) && netreq->dnssec_status != GETDNS_DNSSEC_SECURE)
continue; continue;
else if (completed_request->dnssec &&
netreq->dnssec_status == GETDNS_DNSSEC_INDETERMINATE)
continue;
else if (netreq->tsig_status == GETDNS_DNSSEC_BOGUS) else if (netreq->tsig_status == GETDNS_DNSSEC_BOGUS)
continue; continue;
} }
@ -1227,8 +1236,8 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
/* TODO: Check instead if canonical_name for request_type /* TODO: Check instead if canonical_name for request_type
* is in the answer section. * is in the answer section.
*/ */
if (GLDNS_RCODE_NOERROR == if (_getdns_rrset_answer(&answer_spc, netreq->response
GLDNS_RCODE_WIRE(netreq->response)) , netreq->response_len))
nanswers++; nanswers++;
if (dnssec_return_status || if (dnssec_return_status ||
@ -1287,9 +1296,14 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
if (getdns_dict_set_int(result, GETDNS_STR_KEY_STATUS, if (getdns_dict_set_int(result, GETDNS_STR_KEY_STATUS,
completed_request->request_timed_out || completed_request->request_timed_out ||
nreplies == 0 ? GETDNS_RESPSTATUS_ALL_TIMEOUT : nreplies == 0 ? GETDNS_RESPSTATUS_ALL_TIMEOUT :
completed_request->dnssec_return_only_secure && nsecure == 0 && ninsecure > 0 ( completed_request->dnssec
&& nsecure == 0 && nindeterminate ) > 0
? GETDNS_RESPSTATUS_NO_SECURE_ANSWERS : ? GETDNS_RESPSTATUS_NO_SECURE_ANSWERS :
completed_request->dnssec_return_only_secure && nsecure == 0 && nbogus > 0 ( completed_request->dnssec_return_only_secure
&& nsecure == 0 && ninsecure ) > 0
? GETDNS_RESPSTATUS_NO_SECURE_ANSWERS :
( completed_request->dnssec_return_only_secure
|| completed_request->dnssec ) && nsecure == 0 && nbogus > 0
? GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS : ? GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS :
nanswers == 0 ? GETDNS_RESPSTATUS_NO_NAME nanswers == 0 ? GETDNS_RESPSTATUS_NO_NAME
: GETDNS_RESPSTATUS_GOOD)) : GETDNS_RESPSTATUS_GOOD))
@ -1442,7 +1456,7 @@ _getdns_validate_dname(const char* dname) {
} /* _getdns_validate_dname */ } /* _getdns_validate_dname */
static void _getdns_reply2wire_buf(gldns_buffer *buf, getdns_dict *reply) static void _getdns_reply2wire_buf(gldns_buffer *buf, const getdns_dict *reply)
{ {
getdns_dict *rr_dict, *q_dict, *h_dict; getdns_dict *rr_dict, *q_dict, *h_dict;
getdns_list *section; getdns_list *section;
@ -1498,7 +1512,7 @@ static void _getdns_reply2wire_buf(gldns_buffer *buf, getdns_dict *reply)
} }
} }
static void _getdns_list2wire_buf(gldns_buffer *buf, getdns_list *l) static void _getdns_list2wire_buf(gldns_buffer *buf, const getdns_list *l)
{ {
getdns_dict *rr_dict; getdns_dict *rr_dict;
size_t i, pkt_start; size_t i, pkt_start;
@ -1536,8 +1550,8 @@ static void _getdns_list2wire_buf(gldns_buffer *buf, getdns_list *l)
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, ancount); gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, ancount);
} }
uint8_t *_getdns_list2wire( uint8_t *_getdns_list2wire(const getdns_list *l,
getdns_list *l, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf) uint8_t *buf, size_t *buf_len, const struct mem_funcs *mf)
{ {
gldns_buffer gbuf; gldns_buffer gbuf;
size_t sz; size_t sz;
@ -1557,8 +1571,8 @@ uint8_t *_getdns_list2wire(
return buf; return buf;
} }
uint8_t *_getdns_reply2wire( uint8_t *_getdns_reply2wire(const getdns_dict *r,
getdns_dict *r, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf) uint8_t *buf, size_t *buf_len, const struct mem_funcs *mf)
{ {
gldns_buffer gbuf; gldns_buffer gbuf;
size_t sz; size_t sz;
@ -1578,7 +1592,7 @@ uint8_t *_getdns_reply2wire(
return buf; return buf;
} }
void _getdns_wire2list(uint8_t *pkt, size_t pkt_len, getdns_list *l) void _getdns_wire2list(const uint8_t *pkt, size_t pkt_len, getdns_list *l)
{ {
_getdns_rr_iter rr_spc, *rr; _getdns_rr_iter rr_spc, *rr;
getdns_dict *rr_dict; getdns_dict *rr_dict;

View File

@ -147,17 +147,18 @@ _getdns_rr_iter2rr_dict_canonical(
struct mem_funcs *mf, _getdns_rr_iter *i, uint32_t *orig_ttl); struct mem_funcs *mf, _getdns_rr_iter *i, uint32_t *orig_ttl);
struct getdns_dns_req; struct getdns_dns_req;
struct getdns_dict *_getdns_create_getdns_response(struct getdns_dns_req *completed_request); struct getdns_dict *_getdns_create_getdns_response(
struct getdns_dns_req *completed_request);
getdns_return_t _getdns_validate_dname(const char* dname); getdns_return_t _getdns_validate_dname(const char* dname);
uint8_t *_getdns_list2wire( uint8_t *_getdns_list2wire(const getdns_list *l,
getdns_list *l, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf); uint8_t *buf, size_t *buf_len, const struct mem_funcs *mf);
uint8_t *_getdns_reply2wire( uint8_t *_getdns_reply2wire(const getdns_dict *r,
getdns_dict *r, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf); uint8_t *buf, size_t *buf_len, const struct mem_funcs *mf);
void _getdns_wire2list(uint8_t *pkt, size_t pkt_len, getdns_list *l); void _getdns_wire2list(const uint8_t *pkt, size_t pkt_len, getdns_list *l);
/** /**
@ -218,5 +219,46 @@ INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms)
return *now_ms >= expires ? 0 : expires - *now_ms; return *now_ms >= expires ? 0 : expires - *now_ms;
} }
#if defined(HAVE_DECL_SSL_SET_MIN_PROTO_VERSION) \
&& HAVE_DECL_SSL_SET_MIN_PROTO_VERSION
INLINE int _getdns_tls_version2openssl_version(getdns_tls_version_t v)
{
switch (v) {
# ifdef SSL3_VERSION
case GETDNS_SSL3 : return SSL3_VERSION;
# endif
# ifdef TLS1_VERSION
case GETDNS_TLS1 : return TLS1_VERSION;
# endif
# ifdef TLS1_1_VERSION
case GETDNS_TLS1_1: return TLS1_1_VERSION;
# endif
# ifdef TLS1_2_VERSION
case GETDNS_TLS1_2: return TLS1_2_VERSION;
# endif
# ifdef TLS1_3_VERSION
case GETDNS_TLS1_3: return TLS1_3_VERSION;
# endif
default :
# if defined(TLS_MAX_VERSION)
return TLS_MAX_VERSION;
# elif defined(TLS1_3_VERSION)
return TLS1_3_VERSION;
# elif defined(TLS1_2_VERSION)
return TLS1_2_VERSION;
# elif defined(TLS1_1_VERSION)
return TLS1_1_VERSION;
# elif defined(TLS1_VERSION)
return TLS1_VERSION;
# elif defined(SSL3_VERSION)
return SSL3_VERSION;
# else
return -1;
# endif
}
}
#endif
#endif #endif
/* util-internal.h */ /* util-internal.h */

View File

@ -143,7 +143,7 @@ int rbtree_find_less_equal(rbtree_type *rbtree, const void *key,
* @param rbtree: tree * @param rbtree: tree
* @return: smallest element or NULL if tree empty. * @return: smallest element or NULL if tree empty.
*/ */
rbnode_type *rbtree_first(rbtree_type *rbtree); rbnode_type *rbtree_first(const rbtree_type *rbtree);
/** /**
* Returns last (largest) node in the tree * Returns last (largest) node in the tree

View File

@ -546,7 +546,7 @@ rbtree_find_less_equal(rbtree_type *rbtree, const void *key,
* *
*/ */
rbnode_type * rbnode_type *
rbtree_first (rbtree_type *rbtree) rbtree_first (const rbtree_type *rbtree)
{ {
rbnode_type *node; rbnode_type *node;

View File

@ -77,6 +77,22 @@ int fake_dsa = 0;
/** fake SHA1 support for unit tests */ /** fake SHA1 support for unit tests */
int fake_sha1 = 0; int fake_sha1 = 0;
/**
* Output a libcrypto openssl error to the logfile.
* @param str: string to add to it.
* @param e: the error to output, error number from ERR_get_error().
*/
static void
log_crypto_error(const char* str, unsigned long e)
{
char buf[128];
/* or use ERR_error_string if ERR_error_string_n is not avail TODO */
ERR_error_string_n(e, buf, sizeof(buf));
/* buf now contains */
/* error:[error code]:[library name]:[function name]:[reason string] */
log_err("%s crypto %s", str, buf);
}
/* return size of digest if supported, or 0 otherwise */ /* return size of digest if supported, or 0 otherwise */
size_t size_t
nsec3_hash_algo_size_supported(int id) nsec3_hash_algo_size_supported(int id)
@ -96,7 +112,13 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
{ {
switch(algo) { switch(algo) {
case NSEC3_HASH_SHA1: case NSEC3_HASH_SHA1:
#ifdef OPENSSL_FIPS
if(!sldns_digest_evp(buf, len, res, EVP_sha1()))
log_crypto_error("could not digest with EVP_sha1",
ERR_get_error());
#else
(void)SHA1(buf, len, res); (void)SHA1(buf, len, res);
#endif
return 1; return 1;
default: default:
return 0; return 0;
@ -106,7 +128,13 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
void void
secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
{ {
#ifdef OPENSSL_FIPS
if(!sldns_digest_evp(buf, len, res, EVP_sha256()))
log_crypto_error("could not digest with EVP_sha256",
ERR_get_error());
#else
(void)SHA256(buf, len, res); (void)SHA256(buf, len, res);
#endif
} }
/** /**
@ -165,12 +193,24 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
switch(algo) { switch(algo) {
#if defined(HAVE_EVP_SHA1) && defined(USE_SHA1) #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
case LDNS_SHA1: case LDNS_SHA1:
#ifdef OPENSSL_FIPS
if(!sldns_digest_evp(buf, len, res, EVP_sha1()))
log_crypto_error("could not digest with EVP_sha1",
ERR_get_error());
#else
(void)SHA1(buf, len, res); (void)SHA1(buf, len, res);
#endif
return 1; return 1;
#endif #endif
#ifdef HAVE_EVP_SHA256 #ifdef HAVE_EVP_SHA256
case LDNS_SHA256: case LDNS_SHA256:
#ifdef OPENSSL_FIPS
if(!sldns_digest_evp(buf, len, res, EVP_sha256()))
log_crypto_error("could not digest with EVP_sha256",
ERR_get_error());
#else
(void)SHA256(buf, len, res); (void)SHA256(buf, len, res);
#endif
return 1; return 1;
#endif #endif
#ifdef USE_GOST #ifdef USE_GOST
@ -181,7 +221,13 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
#endif #endif
#ifdef USE_ECDSA #ifdef USE_ECDSA
case LDNS_SHA384: case LDNS_SHA384:
#ifdef OPENSSL_FIPS
if(!sldns_digest_evp(buf, len, res, EVP_sha384()))
log_crypto_error("could not digest with EVP_sha384",
ERR_get_error());
#else
(void)SHA384(buf, len, res); (void)SHA384(buf, len, res);
#endif
return 1; return 1;
#endif #endif
default: default:
@ -231,7 +277,10 @@ dnskey_algo_id_is_supported(int id)
#ifdef USE_ED25519 #ifdef USE_ED25519
case LDNS_ED25519: case LDNS_ED25519:
#endif #endif
#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) #ifdef USE_ED448
case LDNS_ED448:
#endif
#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) || defined(USE_ED25519) || defined(USE_ED448)
return 1; return 1;
#endif #endif
@ -245,22 +294,6 @@ dnskey_algo_id_is_supported(int id)
} }
} }
/**
* Output a libcrypto openssl error to the logfile.
* @param str: string to add to it.
* @param e: the error to output, error number from ERR_get_error().
*/
static void
log_crypto_error(const char* str, unsigned long e)
{
char buf[128];
/* or use ERR_error_string if ERR_error_string_n is not avail TODO */
ERR_error_string_n(e, buf, sizeof(buf));
/* buf now contains */
/* error:[error code]:[library name]:[function name]:[reason string] */
log_err("%s crypto %s", str, buf);
}
#ifdef USE_DSA #ifdef USE_DSA
/** /**
* Setup DSA key digest in DER encoding ... * Setup DSA key digest in DER encoding ...
@ -569,6 +602,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
*digest_type = NULL; *digest_type = NULL;
break; break;
#endif /* USE_ED25519 */ #endif /* USE_ED25519 */
#ifdef USE_ED448
case LDNS_ED448:
*evp_key = sldns_ed4482pkey_raw(key, keylen);
if(!*evp_key) {
verbose(VERB_QUERY, "verify: "
"sldns_ed4482pkey_raw failed");
return 0;
}
*digest_type = NULL;
break;
#endif /* USE_ED448 */
default: default:
verbose(VERB_QUERY, "verify: unknown algorithm %d", verbose(VERB_QUERY, "verify: unknown algorithm %d",
algo); algo);

View File

@ -68,6 +68,10 @@ enum sec_status { sec_status_bogus = 0
#define LDNS_ECDSAP256SHA256 GLDNS_ECDSAP256SHA256 #define LDNS_ECDSAP256SHA256 GLDNS_ECDSAP256SHA256
#define LDNS_ECDSAP384SHA384 GLDNS_ECDSAP384SHA384 #define LDNS_ECDSAP384SHA384 GLDNS_ECDSAP384SHA384
#define LDNS_ECC_GOST GLDNS_ECC_GOST #define LDNS_ECC_GOST GLDNS_ECC_GOST
#define LDNS_ED25519 GLDNS_ED25519
#define LDNS_ED448 GLDNS_ED448
#define sldns_ed255192pkey_raw gldns_ed255192pkey_raw
#define sldns_ed4482pkey_raw gldns_ed4482pkey_raw
#define sldns_key_EVP_load_gost_id gldns_key_EVP_load_gost_id #define sldns_key_EVP_load_gost_id gldns_key_EVP_load_gost_id
#define sldns_digest_evp gldns_digest_evp #define sldns_digest_evp gldns_digest_evp
#define sldns_key_buf2dsa_raw gldns_key_buf2dsa_raw #define sldns_key_buf2dsa_raw gldns_key_buf2dsa_raw

2
stubby

@ -1 +1 @@
Subproject commit 8fb853ac8d6148fd9b53fdcbc107ecd375071ec5 Subproject commit 58200cadec6371f95e31a7f3735225c5a46ecf75