Merge branch 'develop' into feature/abstract-tls

This commit is contained in:
Jim Hague 2019-01-14 18:40:59 +00:00
commit 3fe0c94357
58 changed files with 2235 additions and 1259 deletions

View File

@ -1,4 +1,40 @@
* 2018-0?-??: Version 1.4.3 * 2019-01-??: Version 1.5.1
* Issue #415: Filter out #defines etc. when creating
symbols file. Thanks Zero King
* Be consistent and always fail connection setup if setting ciphers/curves/
TLS version/cipher suites fails.
* 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 * Bugfix finding signer for validating NSEC and NSEC3s, which
caused trouble with the partly tracing DNSSEC from the root caused trouble with the partly tracing DNSSEC from the root
up, introduced in 1.4.2. Thanks Philip Homburg up, introduced in 1.4.2. Thanks Philip Homburg

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

@ -37,7 +37,7 @@ sinclude(./m4/ac_lib_nettle.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
@ -64,13 +64,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
# --------------- # ---------------
@ -106,8 +106,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)
@ -401,44 +402,45 @@ yes)
esac esac
USE_NSS="no" USE_NSS="no"
AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path], dnl AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path],
[use libnss instead of openssl, installed at path.]), dnl [use libnss instead of openssl, installed at path.]),
[ dnl [
USE_NSS="yes" dnl USE_NSS="yes"
AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto]) dnl AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto])
if test "$withval" != "" -a "$withval" != "yes"; then dnl if test "$withval" != "" -a "$withval" != "yes"; then
CPPFLAGS="$CPPFLAGS -I$withval/include/nss3" dnl CPPFLAGS="$CPPFLAGS -I$withval/include/nss3"
LDFLAGS="$LDFLAGS -L$withval/lib" dnl LDFLAGS="$LDFLAGS -L$withval/lib"
ACX_RUNTIME_PATH_ADD([$withval/lib]) dnl ACX_RUNTIME_PATH_ADD([$withval/lib])
CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS" dnl CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS"
else dnl else
CPPFLAGS="$CPPFLAGS -I/usr/include/nss3" dnl CPPFLAGS="$CPPFLAGS -I/usr/include/nss3"
CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS" dnl CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
fi dnl fi
LIBS="$LIBS -lnss3 -lnspr4" dnl LIBS="$LIBS -lnss3 -lnspr4"
SSLLIB="" dnl SSLLIB=""
] dnl ]
) dnl )
# libnettle # libnettle
USE_NETTLE="no" USE_NETTLE="no"
AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path], dnl AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path],
[use libnettle as crypto library, installed at path.]), dnl [use libnettle as crypto library, installed at path.]),
[ dnl [
USE_NETTLE="yes" dnl USE_NETTLE="yes"
AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto]) dnl AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT]) dnl AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT])
if test "$withval" != "" -a "$withval" != "yes"; then dnl if test "$withval" != "" -a "$withval" != "yes"; then
CPPFLAGS="$CPPFLAGS -I$withval/include/nettle" dnl CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
LDFLAGS="$LDFLAGS -L$withval/lib" dnl LDFLAGS="$LDFLAGS -L$withval/lib"
ACX_RUNTIME_PATH_ADD([$withval/lib]) dnl ACX_RUNTIME_PATH_ADD([$withval/lib])
else dnl else
CPPFLAGS="$CPPFLAGS -I/usr/include/nettle" dnl CPPFLAGS="$CPPFLAGS -I/usr/include/nettle"
fi dnl fi
LIBS="$LIBS -lhogweed -lnettle -lgmp" dnl LIBS="$LIBS -lhogweed -lnettle -lgmp"
SSLLIB="" dnl SSLLIB=""
] dnl ]
) dnl )
# Which TLS and crypto libs to use. # Which TLS and crypto libs to use.
AC_ARG_WITH([gnutls], AC_ARG_WITH([gnutls],
[AS_HELP_STRING([--with-gnutls], [AS_HELP_STRING([--with-gnutls],
@ -497,7 +499,7 @@ fi
AC_CHECK_HEADERS([openssl/conf.h openssl/ssl.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 X509_get_notAfter X509_get0_notAfter SSL_CTX_set_ciphersuites SSL_set_ciphersuites OPENSSL_init_crypto DSA_set0_pqg DSA_set0_key RSA_set0_key]) 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 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 OPENSSL_init_crypto DSA_set0_pqg DSA_set0_key RSA_set0_key])
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_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

View File

@ -523,10 +523,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)
{ {
@ -573,7 +571,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);
} }
@ -581,20 +580,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);
@ -626,7 +631,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);
} }
@ -642,7 +649,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;
@ -657,8 +666,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);
@ -687,18 +694,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 = _getdns_tas_validate(&context->mf, &a->xml, &p7s_bd, else if (!(tas = _getdns_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)))
@ -823,7 +832,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;
@ -870,7 +883,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);
} }
@ -920,7 +937,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);
} }
@ -959,9 +978,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
@ -977,15 +994,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;
} }
@ -1036,9 +1057,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);
@ -1046,8 +1069,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) {
@ -1060,8 +1085,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) {
@ -1095,8 +1122,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);
} }
@ -1110,7 +1139,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);
} }
@ -1129,28 +1161,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;
@ -1160,8 +1195,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));
@ -1178,7 +1214,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;
@ -1187,38 +1224,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);
@ -1226,35 +1272,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;
@ -1371,7 +1426,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;
@ -1456,8 +1514,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);
@ -1465,11 +1525,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 */
@ -1544,17 +1606,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

@ -64,7 +64,8 @@ uint16_t _getdns_parse_xml_trust_anchors_buf(gldns_buffer *gbuf, uint64_t *now_m
**/ **/
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>
@ -67,6 +60,9 @@
#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))
@ -82,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)))
@ -90,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)))
@ -99,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);
@ -108,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)
@ -119,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
/* /*
@ -187,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
@ -217,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)
{ {
@ -230,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)
@ -278,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)
@ -291,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
@ -326,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,
@ -355,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)
{ {
@ -403,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);
@ -426,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;
@ -550,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

@ -128,7 +128,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;
@ -207,9 +207,15 @@ typedef struct getdns_upstream {
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;
@ -264,7 +270,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;
@ -342,6 +348,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;
@ -351,7 +359,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;
@ -359,7 +370,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;
@ -434,6 +445,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;
@ -491,11 +503,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 **/
@ -552,8 +591,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

@ -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;
@ -788,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)
{ {
@ -850,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)
@ -1364,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;
@ -1683,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;
@ -1752,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;
@ -1780,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() */
@ -1827,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;
@ -2112,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;
@ -2215,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)
{ {
@ -2267,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;
@ -2571,7 +2573,7 @@ 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;
@ -2606,7 +2608,7 @@ 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, &opt_out))) { mf, now, skew, ta, &node->ds, &opt_out))) {
node->ds_signer = keytag; node->ds_signer = keytag;
@ -2621,12 +2623,18 @@ static int chain_node_get_trusted_keys(
* key_proves_nonexistance() will set opt_out also for * key_proves_nonexistance() will set opt_out also for
* these conditions. * these conditions.
*/ */
return opt_out ? GETDNS_DNSSEC_INSECURE if (opt_out)
: GETDNS_DNSSEC_SECURE; return GETDNS_DNSSEC_INSECURE;
}
if ((keytag = a_key_signed_rrset_no_wc( /* 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;
@ -2635,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
@ -2707,7 +2716,7 @@ 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;
@ -2794,8 +2803,8 @@ static int chain_head_validate_with_ta(struct mem_funcs *mf,
/* 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;
@ -2944,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;
@ -3280,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 */
@ -3293,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) {
@ -3307,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) {
@ -3464,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
@ -3589,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)
{ {
@ -3671,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,
@ -3685,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;
@ -3766,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,8 +16,8 @@ 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/sldns/ svn co https://nlnetlabs.nl/svn/unbound/trunk/sldns/
for f in sldns/*.[ch] for f in ldns/*.[ch]
do do
sed -e 's/sldns_/gldns_/g' \ sed -e 's/sldns_/gldns_/g' \
-e 's/LDNS_/GLDNS_/g' \ -e 's/LDNS_/GLDNS_/g' \

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

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018, NLnet Labs * Copyright (c) 2018-2019, NLnet Labs
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -53,14 +53,18 @@
#define HAVE_TLS_CTX_CURVES_LIST 0 #define HAVE_TLS_CTX_CURVES_LIST 0
#define HAVE_TLS_CONN_CURVES_LIST 0 #define HAVE_TLS_CONN_CURVES_LIST 0
typedef struct getdns_log_config getdns_log_config;
typedef struct _getdns_tls_context { typedef struct _getdns_tls_context {
struct mem_funcs* mfs; struct mem_funcs* mfs;
char* cipher_list; char* cipher_list;
char* cipher_suites;
char* curve_list; char* curve_list;
bool min_proto_1_2; gnutls_protocol_t min_tls;
gnutls_protocol_t max_tls;
char* ca_trust_file; char* ca_trust_file;
char* ca_trust_path; char* ca_trust_path;
const getdns_log_config* log;
} _getdns_tls_context; } _getdns_tls_context;
typedef struct _getdns_tls_connection { typedef struct _getdns_tls_connection {
@ -70,10 +74,14 @@ typedef struct _getdns_tls_connection {
_getdns_tls_context* ctx; _getdns_tls_context* ctx;
struct mem_funcs* mfs; struct mem_funcs* mfs;
char* cipher_list; char* cipher_list;
char* cipher_suites;
char* curve_list; char* curve_list;
gnutls_protocol_t min_tls;
gnutls_protocol_t max_tls;
dane_query_t dane_query; dane_query_t dane_query;
dane_state_t dane_state; dane_state_t dane_state;
char* tlsa; char* tlsa;
const getdns_log_config* log;
} _getdns_tls_connection; } _getdns_tls_connection;
typedef struct _getdns_tls_session { typedef struct _getdns_tls_session {

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018, NLnet Labs * Copyright (c) 2018-2019, NLnet Labs
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,17 +43,27 @@
/* /*
* Cipher suites recommended in RFC7525. * Cipher suites recommended in RFC7525.
* *
* The following string generates a list with the same ciphers that are * The following strings generate a list with the same ciphers that are
* generated by the equivalent string in the OpenSSL version of this file. * generated by the equivalent string in the OpenSSL version of this file.
*/ */
char const * const _getdns_tls_context_default_cipher_list = static char const * const _getdns_tls_context_default_cipher_list =
"NONE:+AES-256-GCM:+AES-128-GCM:+CHACHA20-POLY1305:" "+ECDHE-RSA:+ECDHE-ECDSA:+AEAD";
"+ECDHE-RSA:+ECDHE-ECDSA:+SIGN-RSA-SHA384:+AEAD:"
"+COMP-ALL:+VERS-TLS-ALL:+CURVE-ALL"; static char const * const _getdns_tls_context_default_cipher_suites =
"+AES-256-GCM:+AES-128-GCM:+CHACHA20-POLY1305";
static char const * const _getdns_tls_connection_opportunistic_cipher_list = static char const * const _getdns_tls_connection_opportunistic_cipher_list =
"NORMAL"; "NORMAL";
static char const * const _getdns_tls_priorities[] = {
NULL, /* No protocol */
"+VERS-TLS1.0", /* SSL3 */
"+VERS-TLS1.0", /* TLS1.0 */
"+VERS-TLS1.1", /* TLS1.1 */
"+VERS-TLS1.2", /* TLS1.2 */
"+VERS-TLS1.3", /* TLS1.3 */
};
static char* getdns_strdup(struct mem_funcs* mfs, const char* s) static char* getdns_strdup(struct mem_funcs* mfs, const char* s)
{ {
char* res; char* res;
@ -92,6 +102,13 @@ static int set_connection_ciphers(_getdns_tls_connection* conn)
char* pri = NULL; char* pri = NULL;
int res; int res;
pri = getdns_priappend(conn->mfs, pri, "NONE:+COMP-ALL:+SIGN-RSA-SHA384");
if (conn->cipher_suites)
pri = getdns_priappend(conn->mfs, pri, conn->cipher_suites);
else if (conn->ctx->cipher_suites)
pri = getdns_priappend(conn->mfs, pri, conn->ctx->cipher_suites);
if (conn->cipher_list) if (conn->cipher_list)
pri = getdns_priappend(conn->mfs, pri, conn->cipher_list); pri = getdns_priappend(conn->mfs, pri, conn->cipher_list);
else if (conn->ctx->cipher_list) else if (conn->ctx->cipher_list)
@ -101,12 +118,39 @@ static int set_connection_ciphers(_getdns_tls_connection* conn)
pri = getdns_priappend(conn->mfs, pri, conn->curve_list); pri = getdns_priappend(conn->mfs, pri, conn->curve_list);
else if (conn->ctx->curve_list) else if (conn->ctx->curve_list)
pri = getdns_priappend(conn->mfs, pri, conn->ctx->curve_list); pri = getdns_priappend(conn->mfs, pri, conn->ctx->curve_list);
else
pri = getdns_priappend(conn->mfs, pri, "+CURVE-ALL");
if (pri) gnutls_protocol_t min = conn->min_tls;
gnutls_protocol_t max = conn->max_tls;
if (!min) min = conn->ctx->min_tls;
if (!max) max = conn->ctx->max_tls;
if (!min && !max) {
pri = getdns_priappend(conn->mfs, pri, "+VERS-TLS-ALL");
} else {
if (!max) max = GNUTLS_TLS_VERSION_MAX;
for (gnutls_protocol_t i = min; i <= max; ++i)
pri = getdns_priappend(conn->mfs, pri, _getdns_tls_priorities[i]);
}
if (pri) {
res = gnutls_priority_set_direct(conn->tls, pri, NULL); res = gnutls_priority_set_direct(conn->tls, pri, NULL);
if (res != GNUTLS_E_SUCCESS) {
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS connection with "
, pri
, gnutls_strerror(res));
}
}
else else
res = gnutls_set_default_priority(conn->tls); res = gnutls_set_default_priority(conn->tls);
GETDNS_FREE(*conn->mfs, pri); GETDNS_FREE(*conn->mfs, pri);
return res; return res;
} }
@ -142,6 +186,17 @@ static getdns_return_t get_gnu_mac_algorithm(int algorithm, gnutls_mac_algorithm
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
static gnutls_protocol_t _getdns_tls_version2gnutls_version(getdns_tls_version_t v)
{
switch (v) {
case GETDNS_SSL3 : return GNUTLS_SSL3;
case GETDNS_TLS1 : return GNUTLS_TLS1;
case GETDNS_TLS1_1: return GNUTLS_TLS1_1;
case GETDNS_TLS1_2: return GNUTLS_TLS1_2;
default : return GNUTLS_TLS_VERSION_MAX;
}
}
static _getdns_tls_x509* _getdns_tls_x509_new(struct mem_funcs* mfs, gnutls_datum_t cert) static _getdns_tls_x509* _getdns_tls_x509_new(struct mem_funcs* mfs, gnutls_datum_t cert)
{ {
_getdns_tls_x509* res; _getdns_tls_x509* res;
@ -158,7 +213,7 @@ void _getdns_tls_init()
gnutls_global_init(); gnutls_global_init();
} }
_getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs) _getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs, const getdns_log_config* log)
{ {
_getdns_tls_context* res; _getdns_tls_context* res;
@ -166,10 +221,11 @@ _getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs)
return NULL; return NULL;
res->mfs = mfs; res->mfs = mfs;
res->min_proto_1_2 = false; res->cipher_list = res->cipher_suites = res->curve_list = NULL;
res->cipher_list = res->curve_list = NULL; res->min_tls = res->max_tls = 0;
res->ca_trust_file = NULL; res->ca_trust_file = NULL;
res->ca_trust_path = NULL; res->ca_trust_path = NULL;
res->log = log;
return res; return res;
} }
@ -182,6 +238,7 @@ getdns_return_t _getdns_tls_context_free(struct mem_funcs* mfs, _getdns_tls_cont
GETDNS_FREE(*mfs, ctx->ca_trust_path); GETDNS_FREE(*mfs, ctx->ca_trust_path);
GETDNS_FREE(*mfs, ctx->ca_trust_file); GETDNS_FREE(*mfs, ctx->ca_trust_file);
GETDNS_FREE(*mfs, ctx->curve_list); GETDNS_FREE(*mfs, ctx->curve_list);
GETDNS_FREE(*mfs, ctx->cipher_suites);
GETDNS_FREE(*mfs, ctx->cipher_list); GETDNS_FREE(*mfs, ctx->cipher_list);
GETDNS_FREE(*mfs, ctx); GETDNS_FREE(*mfs, ctx);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -192,12 +249,18 @@ void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx)
(void) ctx; (void) ctx;
} }
getdns_return_t _getdns_tls_context_set_min_proto_1_2(_getdns_tls_context* ctx) getdns_return_t _getdns_tls_context_set_min_max_tls_version(_getdns_tls_context* ctx, getdns_tls_version_t min, getdns_tls_version_t max)
{ {
if (!ctx) if (!ctx)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
ctx->min_proto_1_2 = true; ctx->min_tls = _getdns_tls_version2gnutls_version(min);
return GETDNS_RETURN_NOT_IMPLEMENTED; ctx->max_tls = _getdns_tls_version2gnutls_version(max);
return GETDNS_RETURN_GOOD;
}
const char* _getdns_tls_context_get_default_cipher_list()
{
return _getdns_tls_context_default_cipher_list;
} }
getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list) getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list)
@ -213,6 +276,24 @@ getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, co
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
const char* _getdns_tls_context_get_default_cipher_suites()
{
return _getdns_tls_context_default_cipher_suites;
}
getdns_return_t _getdns_tls_context_set_cipher_suites(_getdns_tls_context* ctx, const char* list)
{
if (!ctx)
return GETDNS_RETURN_INVALID_PARAMETER;
if (!list)
list = _getdns_tls_context_default_cipher_suites;
GETDNS_FREE(*ctx->mfs, ctx->cipher_suites);
ctx->cipher_suites = getdns_strdup(ctx->mfs, list);
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_context_set_curves_list(_getdns_tls_context* ctx, const char* list) getdns_return_t _getdns_tls_context_set_curves_list(_getdns_tls_context* ctx, const char* list)
{ {
if (!ctx) if (!ctx)
@ -235,7 +316,7 @@ getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char*
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
_getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd) _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd, const getdns_log_config* log)
{ {
_getdns_tls_connection* res; _getdns_tls_connection* res;
@ -250,11 +331,12 @@ _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdn
res->mfs = mfs; res->mfs = mfs;
res->cred = NULL; res->cred = NULL;
res->tls = NULL; res->tls = NULL;
res->cipher_list = NULL; res->cipher_list = res->cipher_suites = res->curve_list = NULL;
res->curve_list = NULL; res->min_tls = res->max_tls = 0;
res->dane_state = NULL; res->dane_state = NULL;
res->dane_query = NULL; res->dane_query = NULL;
res->tlsa = NULL; res->tlsa = NULL;
res->log = log;
if (gnutls_certificate_allocate_credentials(&res->cred) != GNUTLS_E_SUCCESS) if (gnutls_certificate_allocate_credentials(&res->cred) != GNUTLS_E_SUCCESS)
goto failed; goto failed;
@ -270,8 +352,10 @@ _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdn
if (gnutls_init(&res->tls, GNUTLS_CLIENT | GNUTLS_NONBLOCK) != GNUTLS_E_SUCCESS) if (gnutls_init(&res->tls, GNUTLS_CLIENT | GNUTLS_NONBLOCK) != GNUTLS_E_SUCCESS)
goto failed; goto failed;
if (set_connection_ciphers(res) != GNUTLS_E_SUCCESS) if (set_connection_ciphers(res) != GNUTLS_E_SUCCESS) {
goto failed; goto failed;
}
if (gnutls_credentials_set(res->tls, GNUTLS_CRD_CERTIFICATE, res->cred) != GNUTLS_E_SUCCESS) if (gnutls_credentials_set(res->tls, GNUTLS_CRD_CERTIFICATE, res->cred) != GNUTLS_E_SUCCESS)
goto failed; goto failed;
if (dane_state_init(&res->dane_state, DANE_F_IGNORE_DNSSEC) != DANE_E_SUCCESS) if (dane_state_init(&res->dane_state, DANE_F_IGNORE_DNSSEC) != DANE_E_SUCCESS)
@ -300,6 +384,7 @@ getdns_return_t _getdns_tls_connection_free(struct mem_funcs* mfs, _getdns_tls_c
gnutls_certificate_free_credentials(conn->cred); gnutls_certificate_free_credentials(conn->cred);
GETDNS_FREE(*mfs, conn->tlsa); GETDNS_FREE(*mfs, conn->tlsa);
GETDNS_FREE(*mfs, conn->curve_list); GETDNS_FREE(*mfs, conn->curve_list);
GETDNS_FREE(*mfs, conn->cipher_suites);
GETDNS_FREE(*mfs, conn->cipher_list); GETDNS_FREE(*mfs, conn->cipher_list);
GETDNS_FREE(*mfs, conn); GETDNS_FREE(*mfs, conn);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -321,6 +406,15 @@ getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
getdns_return_t _getdns_tls_connection_set_min_max_tls_version(_getdns_tls_connection* conn, getdns_tls_version_t min, getdns_tls_version_t max)
{
if (!conn)
return GETDNS_RETURN_INVALID_PARAMETER;
conn->min_tls = _getdns_tls_version2gnutls_version(min);
conn->max_tls = _getdns_tls_version2gnutls_version(max);
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list) getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list)
{ {
if (!conn || !conn->tls) if (!conn || !conn->tls)
@ -337,6 +431,19 @@ getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* c
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
} }
getdns_return_t _getdns_tls_connection_set_cipher_suites(_getdns_tls_connection* conn, const char* list)
{
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
GETDNS_FREE(*conn->mfs, conn->cipher_list);
conn->cipher_suites = getdns_strdup(conn->mfs, list);
if (set_connection_ciphers(conn) == GNUTLS_E_SUCCESS)
return GETDNS_RETURN_GOOD;
else
return GETDNS_RETURN_GENERIC_ERROR;
}
getdns_return_t _getdns_tls_connection_set_curves_list(_getdns_tls_connection* conn, const char* list) getdns_return_t _getdns_tls_connection_set_curves_list(_getdns_tls_connection* conn, const char* list)
{ {
if (!conn || !conn->tls) if (!conn || !conn->tls)
@ -400,9 +507,6 @@ getdns_return_t _getdns_tls_connection_do_handshake(_getdns_tls_connection* conn
r = gnutls_handshake(conn->tls); r = gnutls_handshake(conn->tls);
if (r == GNUTLS_E_SUCCESS) { if (r == GNUTLS_E_SUCCESS) {
if (conn->ctx->min_proto_1_2 &&
gnutls_protocol_get_version(conn->tls) < GNUTLS_TLS1_2)
return GETDNS_RETURN_GENERIC_ERROR;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
else else

View File

@ -36,9 +36,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 +84,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

@ -3,7 +3,7 @@
write_symbols() { write_symbols() {
OUTPUT=$1 OUTPUT=$1
shift shift
grep 'getdns_[0-9a-zA-Z_]*(' $* | grep -v '^#' | grep -v 'INLINE' | grep -v 'getdns_extra\.h\.in: \* if' \ grep -h 'getdns_[0-9a-zA-Z_]*(' $* | grep -v '^#' | grep -v 'INLINE' | grep -v '^ \* if' \
| sed -e 's/(.*$//g' -e 's/^.*getdns_/getdns_/g' | LC_ALL=C sort | uniq > $OUTPUT | sed -e 's/(.*$//g' -e 's/^.*getdns_/getdns_/g' | LC_ALL=C sort | uniq > $OUTPUT
} }

View File

@ -20,6 +20,9 @@
#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
@ -38,6 +41,16 @@
#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
@ -97,6 +110,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 *

View File

@ -58,7 +58,7 @@
#include "pubkey-pinning-internal.h" #include "pubkey-pinning-internal.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #if OPENSSL_VERSION_NUMBER < 0x10100000
#define X509_STORE_CTX_get0_untrusted(store) store->untrusted #define X509_STORE_CTX_get0_untrusted(store) store->untrusted
#endif #endif
@ -106,7 +106,7 @@ _get_ssl_getdns_upstream_idx(X509_STORE *store)
{ {
static volatile int idx = -1; static volatile int idx = -1;
if (idx < 0) { if (idx < 0) {
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #if OPENSSL_VERSION_NUMBER < 0x10100000
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
#else #else
X509_STORE_lock(store); X509_STORE_lock(store);
@ -114,7 +114,7 @@ _get_ssl_getdns_upstream_idx(X509_STORE *store)
if (idx < 0) if (idx < 0)
idx = SSL_get_ex_new_index(0, "associated getdns upstream", idx = SSL_get_ex_new_index(0, "associated getdns upstream",
NULL,NULL,NULL); NULL,NULL,NULL);
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #if OPENSSL_VERSION_NUMBER < 0x10100000
CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
#else #else
X509_STORE_unlock(store); X509_STORE_unlock(store);
@ -123,27 +123,6 @@ _get_ssl_getdns_upstream_idx(X509_STORE *store)
return idx; return idx;
} }
getdns_upstream*
_getdns_upstream_from_x509_store(X509_STORE_CTX *store)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
int uidx = _get_ssl_getdns_upstream_idx();
#else
int uidx = _get_ssl_getdns_upstream_idx(X509_STORE_CTX_get0_store(store));
#endif
int sslidx = SSL_get_ex_data_X509_STORE_CTX_idx();
const SSL *ssl;
/* all *_get_ex_data() should return NULL on failure anyway */
ssl = X509_STORE_CTX_get_ex_data(store, sslidx);
if (ssl)
return (getdns_upstream*) SSL_get_ex_data(ssl, uidx);
else
return NULL;
/* TODO: if we want more details about errors somehow, we
* might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
}
getdns_return_t getdns_return_t
_getdns_associate_upstream_with_connection(_getdns_tls_connection *conn, _getdns_associate_upstream_with_connection(_getdns_tls_connection *conn,
getdns_upstream *upstream) getdns_upstream *upstream)
@ -151,7 +130,7 @@ _getdns_associate_upstream_with_connection(_getdns_tls_connection *conn,
if (!conn || !conn->ssl) if (!conn || !conn->ssl)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #if OPENSSL_VERSION_NUMBER < 0x10100000
int uidx = _get_ssl_getdns_upstream_idx(); int uidx = _get_ssl_getdns_upstream_idx();
#else #else
int uidx = _get_ssl_getdns_upstream_idx(SSL_CTX_get_cert_store(SSL_get_SSL_CTX(conn->ssl))); int uidx = _get_ssl_getdns_upstream_idx(SSL_CTX_get_cert_store(SSL_get_SSL_CTX(conn->ssl)));
@ -164,91 +143,4 @@ _getdns_associate_upstream_with_connection(_getdns_tls_connection *conn,
* might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/ * might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
} }
getdns_return_t
_getdns_verify_pinset_match(const sha256_pin_t *pinset,
X509_STORE_CTX *store)
{
getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
X509 *x, *prev = NULL;
int i, len;
unsigned char raw[4096];
unsigned char *next;
unsigned char buf[sizeof(pinset->pin)];
const sha256_pin_t *p;
if (pinset == NULL || store == NULL)
return GETDNS_RETURN_GENERIC_ERROR;
/* start at the base of the chain (the end-entity cert) and
* make sure that some valid element of the chain does match
* the pinset. */
/* Testing with OpenSSL 1.0.1e-1 on debian indicates that
* store->untrusted holds the chain offered by the server in
* the order that the server offers it. If the server offers
* bogus certificates (that is, matching and valid certs that
* belong to private keys that the server does not control),
* the the verification will succeed (including this pinset
* check), but the handshake will fail outside of this
* verification. */
/* TODO: how do we handle raw public keys? */
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);
#if defined(STUB_DEBUG) && STUB_DEBUG
DEBUG_STUB("%s %-35s: Name of cert: %d ",
STUB_DEBUG_SETUP_TLS, __FUNC__, i);
X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE);
fprintf(stderr, "\n");
#endif
if (i > 0) {
/* we ensure that "prev" is signed by "x" */
EVP_PKEY *pkey = X509_get_pubkey(x);
int verified;
if (!pkey) {
DEBUG_STUB("%s %-35s: Could not get pubkey from cert %d (%p)\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)x);
return GETDNS_RETURN_GENERIC_ERROR;
}
verified = X509_verify(prev, pkey);
EVP_PKEY_free(pkey);
if (!verified) {
DEBUG_STUB("%s %-35s: cert %d (%p) was not signed by cert %d\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i-1, (void*)prev, i);
return GETDNS_RETURN_GENERIC_ERROR;
}
}
/* digest the cert with sha256 */
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
if (len > (int)sizeof(raw)) {
DEBUG_STUB("%s %-35s: Pubkey %d is larger than %"PRIsz" octets\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, sizeof(raw));
continue;
}
next = raw;
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
if (next - raw != len) {
DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed %"PRIsz"\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, len, next - raw);
continue;
}
SHA256(raw, len, buf);
/* compare it */
for (p = pinset; p; p = p->next)
if (0 == memcmp(buf, p->pin, sizeof(p->pin))) {
DEBUG_STUB("%s %-35s: Pubkey %d matched pin %p (%"PRIsz")\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p, sizeof(p->pin));
return GETDNS_RETURN_GOOD;
} else
DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p);
}
return ret;
}
/* pubkey-pinning.c */ /* pubkey-pinning.c */

View File

@ -36,16 +36,7 @@
#include <openssl/x509.h> #include <openssl/x509.h>
/* internal functions for associating X.509 verification processes in getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size);
* OpenSSL with getdns_upstream objects. */
getdns_upstream*
_getdns_upstream_from_x509_store(X509_STORE_CTX *store);
getdns_return_t
_getdns_verify_pinset_match(const sha256_pin_t *pinset,
X509_STORE_CTX *store);
#endif #endif
/* pubkey-pinning-internal.h */ /* pubkey-pinning-internal.h */

View File

@ -55,13 +55,16 @@
#define GETDNS_TLS_MAX_DIGEST_LENGTH (EVP_MAX_MD_SIZE) #define GETDNS_TLS_MAX_DIGEST_LENGTH (EVP_MAX_MD_SIZE)
typedef struct sha256_pin sha256_pin_t; typedef struct sha256_pin sha256_pin_t;
typedef struct getdns_log_config getdns_log_config;
typedef struct _getdns_tls_context { typedef struct _getdns_tls_context {
SSL_CTX* ssl; SSL_CTX* ssl;
const getdns_log_config* log;
} _getdns_tls_context; } _getdns_tls_context;
typedef struct _getdns_tls_connection { typedef struct _getdns_tls_connection {
SSL* ssl; SSL* ssl;
const getdns_log_config* log;
#if defined(USE_DANESSL) #if defined(USE_DANESSL)
const char* auth_name; const char* auth_name;
sha256_pin_t* pinset; sha256_pin_t* pinset;

View File

@ -46,6 +46,7 @@
#include "debug.h" #include "debug.h"
#include "context.h" #include "context.h"
#include "const-info.h"
#ifdef USE_DANESSL #ifdef USE_DANESSL
# include "ssl_dane/danessl.h" # include "ssl_dane/danessl.h"
@ -62,33 +63,20 @@
#endif #endif
/* Cipher suites recommended in RFC7525. */ /* Cipher suites recommended in RFC7525. */
char const * const _getdns_tls_context_default_cipher_list = static char const * const _getdns_tls_context_default_cipher_list =
"TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:" #ifndef HAVE_SSL_CTX_SET_CIPHERSUITES
"TLS13-CHACHA20-POLY1305-SHA256:EECDH+AESGCM:EECDH+CHACHA20"; "TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:"
"TLS13-CHACHA20-POLY1305-SHA256:"
#endif
"EECDH+AESGCM:EECDH+CHACHA20";
static char const * const _getdns_tls_context_default_cipher_suites =
"TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:"
"TLS_CHACHA20_POLY1305_SHA256";
static char const * const _getdns_tls_connection_opportunistic_cipher_list = static char const * const _getdns_tls_connection_opportunistic_cipher_list =
"DEFAULT"; "DEFAULT";
#if defined(USE_DANESSL) && defined(STUB_DEBUG) && STUB_DEBUG
static void _stub_debug_print_openssl_errors(void)
{
unsigned long err;
char buffer[1024];
const char *file;
const char *data;
int line;
int flags;
while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
ERR_error_string_n(err, buffer, sizeof(buffer));
if (flags & ERR_TXT_STRING)
DEBUG_STUB("DEBUG OpenSSL Error: %s:%s:%d:%s\n", buffer, file, line, data);
else
DEBUG_STUB("DEBUG OpenSSL Error: %s:%s:%d\n", buffer, file, line);
}
}
#endif
static int _getdns_tls_verify_always_ok(int ok, X509_STORE_CTX *ctx) static int _getdns_tls_verify_always_ok(int ok, X509_STORE_CTX *ctx)
{ {
# if defined(STUB_DEBUG) && STUB_DEBUG # if defined(STUB_DEBUG) && STUB_DEBUG
@ -156,23 +144,63 @@ static const EVP_MD* get_digester(int algorithm)
return digester; return digester;
} }
#if HAVE_DECL_SSL_SET_MIN_PROTO_VERSION
static 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
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
/* For windows, the CA trust store is not read by openssl. /* For windows, the CA trust store is not read by openssl.
Add code to open the trust store using wincrypt API and add Add code to open the trust store using wincrypt API and add
the root certs into openssl trust store */ the root certs into openssl trust store */
static int static int
add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx, const getdns_log_config* log)
{ {
HCERTSTORE hSystemStore; HCERTSTORE hSystemStore;
PCCERT_CONTEXT pTargetCert = NULL; PCCERT_CONTEXT pTargetCert = NULL;
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_DEBUG
"Adding Windows certificates from system root store to CA store"); , "%s: %s\n", STUB_DEBUG_SETUP_TLS,
, "Adding Windows certificates from system root store to CA store")
;
/* load just once per context lifetime for this version of getdns /* load just once per context lifetime for this version of getdns
TODO: dynamically update CA trust changes as they are available */ TODO: dynamically update CA trust changes as they are available */
if (!tls_ctx) assert(tls_ctx);
return 0;
/* Call wincrypt's CertOpenStore to open the CA root store. */ /* Call wincrypt's CertOpenStore to open the CA root store. */
@ -185,19 +213,27 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
1 << 16, 1 << 16,
L"root")) == 0) L"root")) == 0)
{ {
_getdns_log(log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "Could not CertOpenStore()");
return 0; return 0;
} }
X509_STORE* store = SSL_CTX_get_cert_store(tls_ctx); X509_STORE* store = SSL_CTX_get_cert_store(tls_ctx);
if (!store) if (!store) {
_getdns_log(log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "Could not SSL_CTX_get_cert_store()");
return 0; return 0;
}
/* failure if the CA store is empty or the call fails */ /* failure if the CA store is empty or the call fails */
if ((pTargetCert = CertEnumCertificatesInStore( if ((pTargetCert = CertEnumCertificatesInStore(
hSystemStore, pTargetCert)) == 0) { hSystemStore, pTargetCert)) == 0) {
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_NOTICE
"CA certificate store for Windows is empty."); , "%s: %s\n", STUB_DEBUG_SETUP_TLS
return 0; , "CA certificate store for Windows is empty.");
return 0;
} }
/* iterate over the windows cert store and add to openssl store */ /* iterate over the windows cert store and add to openssl store */
do do
@ -207,9 +243,13 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
pTargetCert->cbCertEncoded); pTargetCert->cbCertEncoded);
if (!cert1) { if (!cert1) {
/* return error if a cert fails */ /* return error if a cert fails */
DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(log
"Unable to parse certificate in memory", , GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR,
ERR_get_error(), ERR_error_string(ERR_get_error(), NULL)); , "%s: %s %d:%s\n"
, STUB_DEBUG_SETUP_TLS
, "Unable to parse certificate in memory"
, ERR_get_error()
, ERR_error_string(ERR_get_error(), NULL));
return 0; return 0;
} }
else { else {
@ -221,9 +261,16 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
* certificate is already in the store. */ * certificate is already in the store. */
if(ERR_GET_LIB(error) != ERR_LIB_X509 || if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(log
"Error adding certificate", ERR_get_error(), , GETDNS_LOG_SYS_STUB
ERR_error_string(ERR_get_error(), NULL)); , GETDNS_LOG_ERR
, "%s: %s %d:%s\n"
, STUB_DEBUG_SETUP_TLS
, "Error adding certificate"
, ERR_get_error()
, ERR_error_string( ERR_get_error()
, NULL)
);
X509_free(cert1); X509_free(cert1);
return 0; return 0;
} }
@ -238,12 +285,18 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
CertFreeCertificateContext(pTargetCert); CertFreeCertificateContext(pTargetCert);
if (hSystemStore) if (hSystemStore)
{ {
if (!CertCloseStore( if (!CertCloseStore(hSystemStore, 0)) {
hSystemStore, 0)) _getdns_log(log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "Could not CertCloseStore()");
return 0; return 0;
}
} }
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, _getdns_log(log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_INFO
"Completed adding Windows certificates to CA store successfully"); , "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "Completed adding Windows certificates to CA store successfully")
;
return 1; return 1;
} }
#endif #endif
@ -265,13 +318,15 @@ void _getdns_tls_init()
#endif #endif
} }
_getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs) _getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs, const getdns_log_config* log)
{ {
_getdns_tls_context* res; _getdns_tls_context* res;
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_context))) if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_context)))
return NULL; return NULL;
res->log = log;
/* Create client context, use TLS v1.2 only for now */ /* Create client context, use TLS v1.2 only for now */
# ifdef HAVE_TLS_CLIENT_METHOD # ifdef HAVE_TLS_CLIENT_METHOD
res->ssl = SSL_CTX_new(TLS_client_method()); res->ssl = SSL_CTX_new(TLS_client_method());
@ -279,6 +334,15 @@ _getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs)
res->ssl = SSL_CTX_new(TLSv1_2_client_method()); res->ssl = SSL_CTX_new(TLSv1_2_client_method());
# endif # endif
if(res->ssl == NULL) { if(res->ssl == NULL) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error creating TLS context"
, ssl_err);
GETDNS_FREE(*mfs, res); GETDNS_FREE(*mfs, res);
return NULL; return NULL;
} }
@ -297,35 +361,90 @@ getdns_return_t _getdns_tls_context_free(struct mem_funcs* mfs, _getdns_tls_cont
void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx) void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx)
{ {
int osr; int osr;
(void) osr;
#if defined(HAVE_SSL_CTX_DANE_ENABLE) #if defined(HAVE_SSL_CTX_DANE_ENABLE)
osr = SSL_CTX_dane_enable(ctx->ssl); osr = SSL_CTX_dane_enable(ctx->ssl);
DEBUG_STUB("%s %-35s: DEBUG: SSL_CTX_dane_enable() -> %d\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
#elif defined(USE_DANESSL) #elif defined(USE_DANESSL)
osr = DANESSL_CTX_init(ctx->ssl); osr = DANESSL_CTX_init(ctx->ssl);
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_CTX_init() -> %d\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
#else #else
#error Must have either DANE SSL or OpenSSL v1.1. #error Must have either DANE SSL or OpenSSL v1.1.
#endif #endif
if (!osr) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_WARNING
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Could not enable DANE on TLX context"
, ssl_err);
}
} }
getdns_return_t _getdns_tls_context_set_min_proto_1_2(_getdns_tls_context* ctx) getdns_return_t _getdns_tls_context_set_min_max_tls_version(_getdns_tls_context* ctx, getdns_tls_version_t min, getdns_tls_version_t max)
{ {
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION #if HAVE_DECL_SSL_SET_MIN_PROTO_VERSION
char ssl_err[256];
int min_ssl = _getdns_tls_version2openssl_version(min);
int max_ssl = _getdns_tls_version2openssl_version(max);
if (!ctx || !ctx->ssl) if (!ctx || !ctx->ssl)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
if (!SSL_CTX_set_min_proto_version(ctx->ssl, TLS1_2_VERSION)) if (min && !SSL_CTX_set_min_proto_version(ctx->ssl, min_ssl)) {
struct const_info* ci = _getdns_get_const_info(min);
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"minimum TLS version"
, ci->name
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
if (max && !SSL_CTX_set_max_proto_version(ctx->ssl, max_ssl)) {
struct const_info* ci = _getdns_get_const_info(min);
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"minimum TLS version"
, ci->name
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
#else #else
/*
* We've used TLSv1_2_client_method() creating the context, so
* error if they asked for anything other than TLS 1.2 or better.
*/
(void) ctx; (void) ctx;
if ((!min || min == GETDNS_TLS1_2) && !max)
return GETDNS_RETURN_GOOD;
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support setting of minimum or maximum "
"TLS versions");
return GETDNS_RETURN_NOT_IMPLEMENTED; return GETDNS_RETURN_NOT_IMPLEMENTED;
#endif #endif
} }
const char* _getdns_tls_context_get_default_cipher_list()
{
return _getdns_tls_context_default_cipher_list;
}
getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list) getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list)
{ {
if (!ctx || !ctx->ssl) if (!ctx || !ctx->ssl)
@ -334,8 +453,60 @@ getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, co
if (!list) if (!list)
list = _getdns_tls_context_default_cipher_list; list = _getdns_tls_context_default_cipher_list;
if (!SSL_CTX_set_cipher_list(ctx->ssl, list)) if (!SSL_CTX_set_cipher_list(ctx->ssl, list)) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"cipher list"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
return GETDNS_RETURN_GOOD;
}
const char* _getdns_tls_context_get_default_cipher_suites()
{
return _getdns_tls_context_default_cipher_suites;
}
getdns_return_t _getdns_tls_context_set_cipher_suites(_getdns_tls_context* ctx, const char* list)
{
if (!ctx || !ctx->ssl)
return GETDNS_RETURN_INVALID_PARAMETER;
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
if (!list)
list = _getdns_tls_context_default_cipher_suites;
if (!SSL_CTX_set_ciphersuites(ctx->ssl, list)) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"cipher suites"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
#else
if (list) {
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support configuring cipher suites");
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
#endif
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -345,10 +516,29 @@ getdns_return_t _getdns_tls_context_set_curves_list(_getdns_tls_context* ctx, co
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
#if HAVE_TLS_CTX_CURVES_LIST #if HAVE_TLS_CTX_CURVES_LIST
if (list && if (list &&
!SSL_CTX_set1_curves_list(ctx->ssl, list)) !SSL_CTX_set1_curves_list(ctx->ssl, list)) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"curves list"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
#else #else
(void) list; if (list) {
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support configuring curves list");
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
#endif #endif
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -357,20 +547,53 @@ getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char*
{ {
if (!ctx || !ctx->ssl) if (!ctx || !ctx->ssl)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
if ((file || path) && if (file || path) {
SSL_CTX_load_verify_locations(ctx->ssl, file, path)) if (!SSL_CTX_load_verify_locations(ctx->ssl, file, path)) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err
, sizeof(ssl_err));
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB
, GETDNS_LOG_WARNING
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Could not load verify locations"
, ssl_err);
} else {
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB
, GETDNS_LOG_DEBUG
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "Verify locations loaded");
}
return GETDNS_RETURN_GOOD; /* pass */ return GETDNS_RETURN_GOOD; /* pass */
}
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
else if (SSL_CTX_set_default_verify_paths(ctx->ssl)) else if (SSL_CTX_set_default_verify_paths(ctx->ssl))
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
else {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err
, sizeof(ssl_err));
_getdns_log(ctx->log
, GETDNS_LOG_SYS_STUB
, GETDNS_LOG_WARNING
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Could not load default verify locations"
, ssl_err);
}
#else #else
else if (add_WIN_cacerts_to_openssl_store(ctx->ssl)) else if (add_WIN_cacerts_to_openssl_store(ctx->ssl, ctx->log))
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
#endif /* USE_WINSOCK */ #endif /* USE_WINSOCK */
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
} }
_getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd) _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd, const getdns_log_config* log)
{ {
_getdns_tls_connection* res; _getdns_tls_connection* res;
@ -392,6 +615,8 @@ _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdn
return NULL; return NULL;
} }
res->log = log;
/* Connection is a client. */ /* Connection is a client. */
SSL_set_connect_state(res->ssl); SSL_set_connect_state(res->ssl);
@ -415,9 +640,6 @@ getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
#ifdef USE_DANESSL #ifdef USE_DANESSL
# if defined(STUB_DEBUG) && STUB_DEBUG
_stub_debug_print_openssl_errors();
# endif
DANESSL_cleanup(conn->ssl); DANESSL_cleanup(conn->ssl);
#endif #endif
@ -428,6 +650,64 @@ getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn)
} }
} }
getdns_return_t _getdns_tls_connection_set_min_max_tls_version(_getdns_tls_connection* conn, getdns_tls_version_t min, getdns_tls_version_t max)
{
#if HAVE_DECL_SSL_SET_MIN_PROTO_VERSION
char ssl_err[256];
int min_ssl = _getdns_tls_version2openssl_version(min);
int max_ssl = _getdns_tls_version2openssl_version(max);
if (!conn || !conn->ssl)
return GETDNS_RETURN_INVALID_PARAMETER;
if (min && !SSL_set_min_proto_version(conn->ssl, min_ssl)) {
struct const_info* ci = _getdns_get_const_info(min);
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS connection with "
"minimum TLS version"
, ci->name
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
if (max && !SSL_set_max_proto_version(conn->ssl, max_ssl)) {
struct const_info* ci = _getdns_get_const_info(min);
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS connection with "
"minimum TLS version"
, ci->name
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
return GETDNS_RETURN_GOOD;
#else
/*
* We've used TLSv1_2_client_method() creating the context, so
* error if they asked for anything other than TLS 1.2 or better.
*/
(void) conn;
if ((!min || min == GETDNS_TLS1_2) && !max)
return GETDNS_RETURN_GOOD;
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support setting of minimum or maximum "
"TLS versions");
return GETDNS_RETURN_NOT_IMPLEMENTED;
#endif
}
getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list) getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list)
{ {
if (!conn || !conn->ssl) if (!conn || !conn->ssl)
@ -436,8 +716,53 @@ getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* c
if (!list) if (!list)
list = _getdns_tls_connection_opportunistic_cipher_list; list = _getdns_tls_connection_opportunistic_cipher_list;
if (!SSL_set_cipher_list(conn->ssl, list)) if (!SSL_set_cipher_list(conn->ssl, list)) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS connection with "
"cipher list"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_set_cipher_suites(_getdns_tls_connection* conn, const char* list)
{
if (!conn || !conn->ssl || !list)
return GETDNS_RETURN_INVALID_PARAMETER;
#ifdef HAVE_SSL_SET_CIPHERSUITES
if (!SSL_set_ciphersuites(conn->ssl, list)) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS connection with "
"cipher suites"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
#else
if (list) {
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support configuring cipher suites");
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
#endif
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -447,10 +772,29 @@ getdns_return_t _getdns_tls_connection_set_curves_list(_getdns_tls_connection* c
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
#if HAVE_TLS_CONN_CURVES_LIST #if HAVE_TLS_CONN_CURVES_LIST
if (list && if (list &&
!SSL_set1_curves_list(conn->ssl, list)) !SSL_set1_curves_list(conn->ssl, list)) {
char ssl_err[256];
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS connection with "
"curves list"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
#else #else
(void) list; if (list) {
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support configuring curves list");
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
#endif #endif
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }

View File

@ -77,6 +77,23 @@ 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);
(void) str; /* In case log_err() does nothing. */
}
/* 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 +113,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 +129,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 +194,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 +222,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:
@ -248,22 +295,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 ...

View File

@ -51,6 +51,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"
#include "pubkey-pinning.h" #include "pubkey-pinning.h"
#include "pubkey-pinning-internal.h" #include "pubkey-pinning-internal.h"
@ -85,14 +86,13 @@ 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)
{ {
size_t i; size_t i;
uint8_t buf[SHA256_DIGEST_LENGTH]; uint8_t buf[SHA256_DIGEST_LENGTH];
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))
@ -253,7 +253,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)
{ {
@ -289,5 +289,3 @@ _getdns_get_pubkey_pinset_list(getdns_context *ctx,
getdns_list_destroy(out); getdns_list_destroy(out);
return r; return r;
} }
/* pubkey-pinning.c */

View File

@ -34,17 +34,11 @@
#ifndef PUBKEY_PINNING_H_ #ifndef PUBKEY_PINNING_H_
#define PUBKEY_PINNING_H_ #define PUBKEY_PINNING_H_
/* getdns_pubkey_pin_create_from_string() is implemented in pubkey-pinning.c */
#include "getdns/getdns_extra.h"
#include "tls.h" #include "tls.h"
/**
** Internal functions, implemented in pubkey-pinning-internal.c.
**/
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size);
/**
** Public interface.
**/
/* create and populate a pinset linked list from a getdns_list pinset */ /* create and populate a pinset linked list from a getdns_list pinset */
getdns_return_t getdns_return_t
_getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list, _getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list,
@ -54,7 +48,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);
@ -62,7 +56,5 @@ getdns_return_t
_getdns_associate_upstream_with_connection(_getdns_tls_connection *conn, _getdns_associate_upstream_with_connection(_getdns_tls_connection *conn,
getdns_upstream *upstream); getdns_upstream *upstream);
getdns_dict* getdns_pubkey_pin_create_from_string(getdns_context* context, const char* str);
#endif #endif
/* pubkey-pinning.h */ /* pubkey-pinning.h */

View File

@ -93,7 +93,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;
@ -168,7 +168,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;
@ -475,6 +475,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;
@ -618,6 +621,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
@ -649,9 +653,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);
@ -678,7 +685,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
@ -726,6 +733,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;
@ -906,6 +914,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

@ -822,19 +822,45 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
getdns_context *context = dnsreq->context; getdns_context *context = dnsreq->context;
if (context->tls_ctx == NULL) if (context->tls_ctx == NULL)
return NULL; return NULL;
_getdns_tls_connection* tls = _getdns_tls_connection_new(&context->my_mf, context->tls_ctx, fd); _getdns_tls_connection* tls = _getdns_tls_connection_new(&context->my_mf, context->tls_ctx, fd, &upstream->upstreams->log);
if(!tls) if(!tls)
return NULL; return NULL;
#if HAVE_TLS_CONN_CURVES_LIST
getdns_return_t r = GETDNS_RETURN_GOOD;
if (upstream->tls_curves_list) if (upstream->tls_curves_list)
_getdns_tls_connection_set_curves_list(tls, upstream->tls_curves_list); r = _getdns_tls_connection_set_curves_list(tls, upstream->tls_curves_list);
#endif if (!r && upstream->tls_ciphersuites)
r = _getdns_tls_connection_set_cipher_suites(tls, upstream->tls_ciphersuites);
if (!r)
r = _getdns_tls_connection_set_min_max_tls_version(tls, upstream->tls_min_version, upstream->tls_max_version);
if (!r)
{
if (upstream->tls_fallback_ok)
r = _getdns_tls_connection_set_cipher_list(tls, NULL);
else if (upstream->tls_cipher_list)
r = _getdns_tls_connection_set_cipher_list(tls, upstream->tls_cipher_list);
}
/* 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_connection(tls, upstream) != GETDNS_RETURN_GOOD) { if (!r)
_getdns_tls_connection_free(&context->my_mf, tls); r = _getdns_associate_upstream_with_connection(tls, upstream);
if (r) {
_getdns_tls_connection_free(&upstream->upstreams->mf, tls);
upstream->tls_auth_state = r;
return NULL; return NULL;
} }
if (upstream->tls_fallback_ok) {
DEBUG_STUB("%s %-35s: WARNING: Using Opportunistic TLS (fallback allowed)!\n",
STUB_DEBUG_SETUP_TLS, __FUNC__);
} else {
DEBUG_STUB("%s %-35s: Using Strict TLS \n",
STUB_DEBUG_SETUP_TLS, __FUNC__);
}
/* NOTE: this code will fallback on a given upstream, without trying /* NOTE: this code will fallback on a given upstream, without trying
authentication on other upstreams first. This is non-optimal and but avoids authentication on other upstreams first. This is non-optimal and but avoids
multiple TLS handshakes before getting a usable connection. */ multiple TLS handshakes before getting a usable connection. */
@ -874,16 +900,6 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
upstream->tls_fallback_ok = 1; upstream->tls_fallback_ok = 1;
} }
} }
if (upstream->tls_fallback_ok) {
_getdns_tls_connection_set_cipher_list(tls, NULL);
DEBUG_STUB("%s %-35s: WARNING: Using Opportunistic TLS (fallback allowed)!\n",
STUB_DEBUG_SETUP_TLS, __FUNC__);
} else {
if (upstream->tls_cipher_list)
_getdns_tls_connection_set_cipher_list(tls, upstream->tls_cipher_list);
DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS,
__FUNC__);
}
_getdns_tls_connection_set_host_pinset(tls, upstream->tls_auth_name, upstream->tls_pubkey_pinset); _getdns_tls_connection_set_host_pinset(tls, upstream->tls_auth_name, upstream->tls_pubkey_pinset);
@ -1811,7 +1827,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");
@ -2070,9 +2086,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

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018, NLnet Labs * Copyright (c) 2018-2019, NLnet Labs
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -57,10 +57,11 @@ void _getdns_tls_init();
/** /**
* Create a new TLS context. * Create a new TLS context.
* *
* @param mfs point to getdns memory functions. * @param mfs pointer to getdns memory functions.
* @paam log pointer to context log config.
* @return pointer to new context or NULL on error. * @return pointer to new context or NULL on error.
*/ */
_getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs); _getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs, const getdns_log_config* log);
/** /**
* Free a TLS context. * Free a TLS context.
@ -80,15 +81,25 @@ getdns_return_t _getdns_tls_context_free(struct mem_funcs* mfs, _getdns_tls_cont
void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx); void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx);
/** /**
* Set TLS 1.2 as minimum TLS version. * Set minimum and maximum TLS versions.
* If max or min are 0, that boundary is not set.
* *
* @param ctx the context. * @param ctx the context.
* @param min the minimum TLS version.
* @param max the maximum TLS version.
* @return GETDNS_RETURN_GOOD on success. * @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer. * @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_NOT_IMPLEMENTED if not implemented. * @return GETDNS_RETURN_NOT_IMPLEMENTED if not implemented.
* @return GETDNS_RETURN_BAD_CONTEXT on failure. * @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/ */
getdns_return_t _getdns_tls_context_set_min_proto_1_2(_getdns_tls_context* ctx); getdns_return_t _getdns_tls_context_set_min_max_tls_version(_getdns_tls_context* ctx, getdns_tls_version_t min, getdns_tls_version_t max);
/**
* Get the default context cipher list.
*
* @return the default context cipher list.
*/
const char* _getdns_tls_context_get_default_cipher_list();
/** /**
* Set list of allowed ciphers. * Set list of allowed ciphers.
@ -101,6 +112,24 @@ getdns_return_t _getdns_tls_context_set_min_proto_1_2(_getdns_tls_context* ctx);
*/ */
getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list); getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list);
/**
* Get the default context cipher suites.
*
* @return the default context cipher suites.
*/
const char* _getdns_tls_context_get_default_cipher_suites();
/**
* Set list of allowed cipher suites.
*
* @param ctx the context.
* @param list the list of cipher suites. NULL for default setting.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_context_set_cipher_suites(_getdns_tls_context* ctx, const char* list);
/** /**
* Set list of allowed curves. * Set list of allowed curves.
* *
@ -134,9 +163,10 @@ getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char*
* @param mfs pointer to getdns memory functions. * @param mfs pointer to getdns memory functions.
* @param ctx the context. * @param ctx the context.
* @param fd the file descriptor to associate with the connection. * @param fd the file descriptor to associate with the connection.
* @paam log pointer to connection log config.
* @return pointer to new connection or NULL on error. * @return pointer to new connection or NULL on error.
*/ */
_getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd); _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd, const getdns_log_config* log);
/** /**
* Free a TLS connection. * Free a TLS connection.
@ -160,6 +190,20 @@ getdns_return_t _getdns_tls_connection_free(struct mem_funcs* mfs, _getdns_tls_c
*/ */
getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn); getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn);
/**
* Set minimum and maximum TLS versions for this connection.
* If max or min are 0, that boundary is not set.
*
* @param conn the connection.
* @param min the minimum TLS version.
* @param max the maximum TLS version.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_NOT_IMPLEMENTED if not implemented.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_connection_set_min_max_tls_version(_getdns_tls_connection* conn, getdns_tls_version_t min, getdns_tls_version_t max);
/** /**
* Set list of allowed ciphers on this connection. * Set list of allowed ciphers on this connection.
* *
@ -171,6 +215,17 @@ getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn);
*/ */
getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list); getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list);
/**
* Set list of allowed cipher suites on this connection.
*
* @param conn the connection.
* @param list the list of cipher suites. NULL for default setting.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_connection_set_cipher_suites(_getdns_tls_connection* conn, const char* list);
/** /**
* Set list of allowed curves on this connection. * Set list of allowed curves on this connection.
* *
@ -407,9 +462,4 @@ void _getdns_tls_sha1(const void* data, size_t data_size, unsigned char* buf);
*/ */
void _getdns_tls_cookie_sha256(uint32_t secret, void* addr, size_t addrlen, unsigned char* buf, size_t* buflen); void _getdns_tls_cookie_sha256(uint32_t secret, void* addr, size_t addrlen, unsigned char* buf, size_t* buflen);
/**
* Default context cipher list.
*/
const char* const _getdns_tls_context_default_cipher_list;
#endif /* _GETDNS_TLS_H */ #endif /* _GETDNS_TLS_H */

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

@ -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);
/** /**

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;