diff --git a/ChangeLog b/ChangeLog index 0c366782..561179a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 caused trouble with the partly tracing DNSSEC from the root up, introduced in 1.4.2. Thanks Philip Homburg diff --git a/Makefile.in b/Makefile.in index 53ffb04a..f92fccdf 100644 --- a/Makefile.in +++ b/Makefile.in @@ -165,7 +165,7 @@ distclean: rm -f m4/ltoptions.m4 rm -f m4/ltsugar.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 megaclean: @@ -177,11 +177,14 @@ autoclean: megaclean 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 openssl sha256 $(distdir).tar.gz >$@ +$(distdir).tar.gz.sha1: $(distdir).tar.gz + openssl sha1 $(distdir).tar.gz >$@ + $(distdir).tar.gz.md5: $(distdir).tar.gz openssl md5 $(distdir).tar.gz >$@ diff --git a/configure.ac b/configure.ac index d5a7f25e..d8d764df 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ sinclude(./m4/ac_lib_nettle.m4) sinclude(./m4/ax_check_compile_flag.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) # 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`"]) 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_NUMERIC_VERSION, [0x07df0c00]) 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_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 # --------------- @@ -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.4.0 had libversion 10:0:0 # getdns-1.4.1 had libversion 10:1:0 -# getdns-1.4.2 has libversion 10:2:0 -GETDNS_LIBVERSION=10:2:0 +# getdns-1.4.2 had 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_LIBVERSION) @@ -401,44 +402,45 @@ yes) esac USE_NSS="no" -AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path], - [use libnss instead of openssl, installed at path.]), - [ - USE_NSS="yes" - AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto]) - if test "$withval" != "" -a "$withval" != "yes"; then - CPPFLAGS="$CPPFLAGS -I$withval/include/nss3" - LDFLAGS="$LDFLAGS -L$withval/lib" - ACX_RUNTIME_PATH_ADD([$withval/lib]) - CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS" - else - CPPFLAGS="$CPPFLAGS -I/usr/include/nss3" - CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS" - fi - LIBS="$LIBS -lnss3 -lnspr4" - SSLLIB="" - ] -) +dnl AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path], +dnl [use libnss instead of openssl, installed at path.]), +dnl [ +dnl USE_NSS="yes" +dnl AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto]) +dnl if test "$withval" != "" -a "$withval" != "yes"; then +dnl CPPFLAGS="$CPPFLAGS -I$withval/include/nss3" +dnl LDFLAGS="$LDFLAGS -L$withval/lib" +dnl ACX_RUNTIME_PATH_ADD([$withval/lib]) +dnl CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS" +dnl else +dnl CPPFLAGS="$CPPFLAGS -I/usr/include/nss3" +dnl CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS" +dnl fi +dnl LIBS="$LIBS -lnss3 -lnspr4" +dnl SSLLIB="" +dnl ] +dnl ) # libnettle USE_NETTLE="no" -AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path], - [use libnettle as crypto library, installed at path.]), - [ - USE_NETTLE="yes" - AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto]) - AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT]) - if test "$withval" != "" -a "$withval" != "yes"; then - CPPFLAGS="$CPPFLAGS -I$withval/include/nettle" - LDFLAGS="$LDFLAGS -L$withval/lib" - ACX_RUNTIME_PATH_ADD([$withval/lib]) - else - CPPFLAGS="$CPPFLAGS -I/usr/include/nettle" - fi - LIBS="$LIBS -lhogweed -lnettle -lgmp" - SSLLIB="" - ] -) +dnl AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path], +dnl [use libnettle as crypto library, installed at path.]), +dnl [ +dnl USE_NETTLE="yes" +dnl AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto]) +dnl AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT]) +dnl if test "$withval" != "" -a "$withval" != "yes"; then +dnl CPPFLAGS="$CPPFLAGS -I$withval/include/nettle" +dnl LDFLAGS="$LDFLAGS -L$withval/lib" +dnl ACX_RUNTIME_PATH_ADD([$withval/lib]) +dnl else +dnl CPPFLAGS="$CPPFLAGS -I/usr/include/nettle" +dnl fi +dnl LIBS="$LIBS -lhogweed -lnettle -lgmp" +dnl SSLLIB="" +dnl ] +dnl ) + # Which TLS and crypto libs to use. AC_ARG_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/engine.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version 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_INCLUDES_DEFAULT #ifdef HAVE_OPENSSL_ERR_H diff --git a/src/anchor.c b/src/anchor.c index 12f16841..602a0153 100644 --- a/src/anchor.c +++ b/src/anchor.c @@ -523,10 +523,8 @@ static const char tas_write_xml_p7s_buf[] = "\r\n"; -#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG static inline const char * rt_str(uint16_t rt) { return rt == GETDNS_RRTYPE_A ? "A" : rt == GETDNS_RRTYPE_AAAA ? "AAAA" : "?"; } -#endif 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, 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; _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) { 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 ort = rt == GETDNS_RRTYPE_A ? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A; -#endif + tas_cleanup(context, a); 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)); 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); } else - DEBUG_ANCHOR("%s connection failed, waiting for %s\n" - , rt_str(rt), rt_str(ort)); + _getdns_log( &context->log + , 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); @@ -626,7 +631,9 @@ static void tas_timeout_cb(void *userarg) a = &context->a; 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); tas_next(context, a); } @@ -642,7 +649,9 @@ static void tas_reconnect_cb(void *userarg) a = &context->a; 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); close(a->fd); a->fd = -1; @@ -657,8 +666,6 @@ static void tas_read_cb(void *userarg); static void tas_write_cb(void *userarg); 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(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( context, (const char **)&verify_CA.data))) - DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify" - " CA: \"%s\"\n", __FUNC__ - , getdns_get_errorstr_by_id(r)); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "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))) ; /* pass */ else if ((r = getdns_context_get_trust_anchors_verify_email( context, &verify_email))) - DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify" - " email address: \"%s\"\n", __FUNC__ - , getdns_get_errorstr_by_id(r)); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "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, &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" , (int)i, (int)n, doc_len); 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 { ssize_t surplus = n - i; @@ -870,7 +883,11 @@ static void tas_read_cb(void *userarg) } else if (_getdns_socketerror_wants_retry()) 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); tas_next(context, a); } @@ -920,7 +937,9 @@ static void tas_write_cb(void *userarg) } else if (_getdns_socketerror_wants_retry()) 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); 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) { -#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG char a_buf[40]; -#endif int r; #ifdef HAVE_FCNTL @@ -977,15 +994,19 @@ static void tas_connect(getdns_context *context, tas_connection *a) tas_next(context, a); return; } - DEBUG_ANCHOR("Initiating connection to %s\n" - , 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))); + + _getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG + , "Setting op connection to: %s\n" + , 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 ? AF_INET : AF_INET6), SOCK_STREAM, IPPROTO_TCP)) == -1) { - DEBUG_ANCHOR("Error creating socket: %s\n", - _getdns_errnostr()); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error creating socket: %s\n", _getdns_errnostr()); tas_next(context, a); return; } @@ -1036,9 +1057,11 @@ static void tas_connect(getdns_context *context, tas_connection *a) } if ((R = _getdns_get_tas_url_hostname( context, tas_hostname, &path))) { - DEBUG_ANCHOR("ERROR %s(): Could not get_tas_url_hostname" - ": \"%s\"", __FUNC__ - , getdns_get_errorstr_by_id(r)); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Cannot get hostname from trust anchor " + "url: \"%s\"\n" + , getdns_get_errorstr_by_id(r)); goto error; } hostname_len = strlen(tas_hostname); @@ -1046,8 +1069,10 @@ static void tas_connect(getdns_context *context, tas_connection *a) tas_hostname[--hostname_len] = '\0'; path_len = strlen(path); if (path_len < 4) { - DEBUG_ANCHOR("ERROR %s(): path of tas_url \"%s\" too " - "small\n", __FUNC__, path); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Trust anchor path \"%s\" too small\n" + , path); goto error; } 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; } if (!(write_buf = GETDNS_XMALLOC(context->mf, char, buf_sz))) { - DEBUG_ANCHOR("ERROR %s(): Could not allocate write " - "buffer\n", __FUNC__); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Cannot allocate write buffer for " + "sending to trust anchor host\n"); goto error; } 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"); return; } 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: tas_next(context, a); } @@ -1110,7 +1139,10 @@ static void tas_happy_eyeballs_cb(void *userarg) if (tas_fetching(&context->aaaa)) return; 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); 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); if (!a->rrset) { -#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG char tas_hostname[256] = ""; (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); -#endif + } else if (a->req->response_len < dnsreq->name_len + 12 || !_getdns_dname_equal(a->req->response + 12, dnsreq->name) || a->rrset->rr_type != a->req->request_type) { -#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG char tas_hostname[256] = ""; (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); -#endif + } else if (!(a->rr = _getdns_rrtype_iter_init(&a->rr_spc, a->rrset))) { -#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG char tas_hostname[256] = ""; (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); -#endif + } else { tas_connection *other = a == &context->a ? &context->aaaa : &context->a; @@ -1160,8 +1195,9 @@ static void _tas_hostname_lookup_cb(getdns_dns_req *dnsreq) ; /* pass */ else if (a == &context->a && tas_busy(other)) { - DEBUG_ANCHOR("Postponing connection initiation: " - "Happy Eyeballs\n"); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG + , "Waiting 25ms for AAAA to arrive\n"); GETDNS_SCHEDULE_EVENT(a->loop, a->fd, 25, getdns_eventloop_event_init(&a->event, 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); } -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; size_t scheduled; @@ -1187,38 +1224,47 @@ void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop) const char *verify_email; if ((r = _getdns_get_tas_url_hostname(context, tas_hostname, NULL))) { - DEBUG_ANCHOR("ERROR %s(): Could not get_tas_url_hostname" - ": \"%s\"", __FUNC__ - , getdns_get_errorstr_by_id(r)); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Cannot get hostname from trust anchor url: " + "\"%s\"\n", getdns_get_errorstr_by_id(r)); return; } else if ((r = getdns_context_get_trust_anchors_verify_CA( context, &verify_CA))) { - DEBUG_ANCHOR("ERROR %s(): Could not get verify CA" - ": \"%s\"", __FUNC__ - , getdns_get_errorstr_by_id(r)); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Cannot get trust anchor verify CA: \"%s\"\n" + , getdns_get_errorstr_by_id(r)); return; } 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"); return; } else if ((r = getdns_context_get_trust_anchors_verify_email( context, &verify_email))) { - DEBUG_ANCHOR("ERROR %s(): Could not get verify email address" - ": \"%s\"", __FUNC__ - , getdns_get_errorstr_by_id(r)); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Cannot get trust anchor verify email: \"%s\"\n" + , getdns_get_errorstr_by_id(r)); return; } else if (!verify_email || !*verify_email) { - DEBUG_ANCHOR("NOTICE: Trust anchor fetching explicitely " - "disabled by empty verify email address\n"); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO + , "Trust anchor verification explicitly " + "disabled by empty verify email\n"); return; } else if (!_getdns_context_can_write_appdata(context)) { - DEBUG_ANCHOR("NOTICE %s(): Not fetching TA, because " - "non writeable appdata directory\n", __FUNC__); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING + , "Not fetching TA, because " + "non writeable appdata directory\n"); return; } 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"); scheduled = 0; -#if 1 context->a.state = TAS_LOOKUP_ADDRESSES; if ((r = _getdns_general_loop(context, loop, tas_hostname, GETDNS_RRTYPE_A, no_dnssec_checking_disabled_opportunistic, context, &context->a.req, NULL, _tas_hostname_lookup_cb))) { - DEBUG_ANCHOR("Error scheduling A lookup for %s: %s\n" - , tas_hostname, getdns_get_errorstr_by_id(r)); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING + , "Error scheduling A lookup for %s: %s\n" + , tas_hostname, getdns_get_errorstr_by_id(r)); } else scheduled += 1; -#endif -#if 1 context->aaaa.state = TAS_LOOKUP_ADDRESSES; if ((r = _getdns_general_loop(context, loop, tas_hostname, GETDNS_RRTYPE_AAAA, no_dnssec_checking_disabled_opportunistic, context, &context->aaaa.req, NULL, _tas_hostname_lookup_cb))) { - DEBUG_ANCHOR("Error scheduling AAAA lookup for %s: %s\n" - , tas_hostname, getdns_get_errorstr_by_id(r)); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING + , "Error scheduling AAAA lookup for %s: %s\n" + , tas_hostname, getdns_get_errorstr_by_id(r)); } else scheduled += 1; -#endif if (!scheduled) { - DEBUG_ANCHOR("Fatal error fetching trust anchor: Unable to " - "schedule address requests for %s\n" - , tas_hostname); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING + , "Error scheduling address lookups for %s\n" + , tas_hostname); + 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); } else context->trust_anchors_source = GETDNS_TASRC_FETCHING; @@ -1371,7 +1426,10 @@ static void _getdns_context_read_root_ksk(getdns_context *context) buf_sz *= 2; } 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;; } ptr = buf; @@ -1456,8 +1514,10 @@ _getdns_context_update_root_ksk( break; } if (str_buf != str_spc) { - DEBUG_ANCHOR("ERROR %s(): Buffer size determination " - "error\n", __FUNC__); + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error determining buffer size for root " + "KSK\n"); if (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, (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; } remaining = str_sz + 1; - DEBUG_ANCHOR("Retrying with buf size: %d\n", remaining); }; /* Write presentation format DNSKEY rrset to "root.key" file */ @@ -1544,17 +1606,21 @@ _getdns_context_update_root_ksk( break; } if (!ta) { - DEBUG_ANCHOR("NOTICE %s(): Key with id %d " - "*not* found in TA.\n" - "\"root-anchors.xml\" need " - "updating.\n", __FUNC__ + _getdns_log( &context->log + , GETDNS_LOG_SYS_ANCHOR + , GETDNS_LOG_NOTICE + , "Key with id %d not found in TA; " + "\"root-anchors.xml\" needs to be " + "updated.\n" , context->root_ksk.ids[i]); context->trust_anchors_source = GETDNS_TASRC_XML_UPDATE; break; } - DEBUG_ANCHOR("DEBUG %s(): Key with id %d found in TA\n" - , __FUNC__, context->root_ksk.ids[i]); + _getdns_log( &context->log + , 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) diff --git a/src/anchor.h b/src/anchor.h index 139dd341..34a31cf8 100644 --- a/src/anchor.h +++ b/src/anchor.h @@ -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_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 RRSIG_RDATA_LEN 16 diff --git a/src/compat/arc4random.c b/src/compat/arc4random.c index 7c9570b9..b2159abd 100644 --- a/src/compat/arc4random.c +++ b/src/compat/arc4random.c @@ -51,6 +51,9 @@ #else /* !__GNUC__ */ #define inline #endif /* !__GNUC__ */ +#ifndef MAP_ANON +#define MAP_ANON MAP_ANONYMOUS +#endif #define KEYSZ 32 #define IVSZ 8 @@ -71,6 +74,72 @@ static struct { 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 _rs_init(u_char *buf, size_t n) { @@ -114,14 +183,14 @@ _rs_stir(void) u_char rnd[KEYSZ + IVSZ]; if (getentropy(rnd, sizeof rnd) == -1) { + if(errno != ENOSYS || + fallback_getentropy_urandom(rnd, sizeof rnd) == -1) { #ifdef SIGKILL - raise(SIGKILL); + raise(SIGKILL); #else -#ifdef GETDNS_ON_WINDOWS - DebugBreak(); -#endif - exit(9); /* windows */ + exit(9); /* windows */ #endif + } } if (!rs) @@ -131,9 +200,6 @@ _rs_stir(void) explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ /* invalidate rs_buf */ -#ifdef GETDNS_ON_WINDOWS - _Analysis_assume_(rs != NULL); -#endif rs->rs_have = 0; memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); @@ -145,15 +211,7 @@ _rs_stir_if_needed(size_t len) { #ifndef MAP_INHERIT_ZERO 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(); -#endif /* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */ if (_rs_pid == 0 || _rs_pid != pid) { @@ -164,9 +222,6 @@ _rs_stir_if_needed(size_t len) #endif if (!rs || rs->rs_count <= len) _rs_stir(); -#ifdef GETDNS_ON_WINDOWS - _Analysis_assume_(rs != NULL); -#endif if (rs->rs_count <= len) rs->rs_count = 0; else diff --git a/src/compat/arc4random_uniform.c b/src/compat/arc4random_uniform.c index c03c2c9b..154260eb 100644 --- a/src/compat/arc4random_uniform.c +++ b/src/compat/arc4random_uniform.c @@ -39,7 +39,7 @@ arc4random_uniform(uint32_t upper_bound) return 0; /* 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 diff --git a/src/compat/getentropy_linux.c b/src/compat/getentropy_linux.c index abb28f49..b86c0fba 100644 --- a/src/compat/getentropy_linux.c +++ b/src/compat/getentropy_linux.c @@ -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 @@ -15,17 +15,13 @@ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * 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" +/* +#define _POSIX_C_SOURCE 199309L +#define _GNU_SOURCE 1 +*/ #include #include #include @@ -43,9 +39,6 @@ #include #include #include -#ifdef WITH_DL_ITERATE_PHDR -#include -#endif #include #include #include @@ -67,6 +60,9 @@ #include #endif #include +#ifndef MAP_ANON +#define MAP_ANON MAP_ANONYMOUS +#endif #define REPEAT 5 #define min(a, b) (((a) < (b)) ? (a) : (b)) @@ -82,7 +78,6 @@ #if defined(HAVE_SSL) #define CRYPTO_SHA512_CTX SHA512_CTX #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 HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) @@ -90,7 +85,6 @@ #elif defined(HAVE_NETTLE) #define CRYPTO_SHA512_CTX struct sha512_ctx #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 HR(x, l) (sha512_update(&ctx, (l), (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); +#ifdef CAN_REFERENCE_MAIN +extern int main(int, char *argv[]); +#endif 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); #endif 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); #endif 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 getentropy(void *buf, size_t len) @@ -119,21 +113,18 @@ getentropy(void *buf, size_t len) if (len > 256) { 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. - * - * 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 + * Try descriptor-less getrandom() */ ret = getentropy_getrandom(buf, len); if (ret != -1) return (ret); + if (errno != ENOSYS) + return (-1); #endif /* @@ -187,7 +178,7 @@ getentropy(void *buf, size_t len) * - Do the best under the circumstances.... * * 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 * 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) any_set |= buf[i]; if (any_set == 0) - return (-1); - return (0); + return -1; + return 0; } -#if defined(SYS_getrandom) && defined(GRND_NONBLOCK) +#if defined(SYS_getrandom) && defined(__NR_getrandom) static int getentropy_getrandom(void *buf, size_t len) { @@ -230,7 +221,7 @@ getentropy_getrandom(void *buf, size_t len) if (len > 256) return (-1); do { - ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK); + ret = syscall(SYS_getrandom, buf, len, 0); } while (ret == -1 && errno == EINTR); if (ret != (int)len) @@ -278,7 +269,7 @@ start: } for (i = 0; i < len; ) { 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 (errno == EAGAIN || errno == EINTR) @@ -291,11 +282,11 @@ start: close(fd); if (gotdata(buf, len) == 0) { errno = save_errno; - return (0); /* satisfied */ + return 0; /* satisfied */ } nodevrandom: errno = EIO; - return (-1); + return -1; } #ifdef SYS__sysctl @@ -326,11 +317,11 @@ getentropy_sysctl(void *buf, size_t len) } sysctlfailed: errno = EIO; - return (-1); + return -1; } #endif /* SYS__sysctl */ -static const int cl[] = { +static int cl[] = { CLOCK_REALTIME, #ifdef CLOCK_MONOTONIC CLOCK_MONOTONIC, @@ -355,18 +346,6 @@ static const int cl[] = { #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 getentropy_fallback(void *buf, size_t len) { @@ -403,10 +382,6 @@ getentropy_fallback(void *buf, size_t len) 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++) 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, sigset); +#ifdef CAN_REFERENCE_MAIN + HF(main); /* an addr in program */ +#endif HF(getentropy); /* an addr in this library */ HF(printf); /* an addr in libc */ p = (char *)&p; @@ -550,34 +528,33 @@ getentropy_fallback(void *buf, size_t len) HD(cnt); } #ifdef HAVE_GETAUXVAL -#ifdef AT_RANDOM +# ifdef AT_RANDOM /* Not as random as you think but we take what we are given */ p = (char *) getauxval(AT_RANDOM); if (p) HR(p, 16); -#endif -#ifdef AT_SYSINFO_EHDR +# endif +# ifdef AT_SYSINFO_EHDR p = (char *) getauxval(AT_SYSINFO_EHDR); if (p) HR(p, pgs); -#endif -#ifdef AT_BASE +# endif +# ifdef AT_BASE p = (char *) getauxval(AT_BASE); if (p) HD(p); -#endif -#endif +# endif +#endif /* HAVE_GETAUXVAL */ 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); } - memset(&ctx, 0, sizeof ctx); memset(results, 0, sizeof results); if (gotdata(buf, len) == 0) { errno = save_errno; - return (0); /* satisfied */ + return 0; /* satisfied */ } errno = EIO; - return (-1); + return -1; } diff --git a/src/const-info.c b/src/const-info.c index 644676e6..ebff80a4 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -93,6 +93,10 @@ static struct const_info consts_info[] = { { 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 }, { 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 }, { 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_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 }, { 1300, "GETDNS_AUTHENTICATION_NONE", GETDNS_AUTHENTICATION_NONE_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) @@ -190,10 +203,14 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 }, { "GETDNS_CONTEXT_CODE_TLS_CA_FILE", 632 }, { "GETDNS_CONTEXT_CODE_TLS_CA_PATH", 631 }, + { "GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES", 635 }, { "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", 633 }, { "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 }, { "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_TRUST_ANCHORS_BACKOFF_TIME", 638 }, { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", 625 }, { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA", 626 }, { "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_INFO", 6 }, { "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_NAMESPACE_DNS", 500 }, { "GETDNS_NAMESPACE_LOCALNAMES", 501 }, @@ -279,6 +300,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RRCLASS_IN", 1 }, { "GETDNS_RRCLASS_NONE", 254 }, { "GETDNS_RRTYPE_A", 1 }, + { "GETDNS_RRTYPE_A6", 38 }, { "GETDNS_RRTYPE_AAAA", 28 }, { "GETDNS_RRTYPE_AFSDB", 18 }, { "GETDNS_RRTYPE_ANY", 255 }, @@ -299,6 +321,8 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RRTYPE_DOA", 259 }, { "GETDNS_RRTYPE_DS", 43 }, { "GETDNS_RRTYPE_EID", 31 }, + { "GETDNS_RRTYPE_EUI48", 108 }, + { "GETDNS_RRTYPE_EUI64", 109 }, { "GETDNS_RRTYPE_GID", 102 }, { "GETDNS_RRTYPE_GPOS", 27 }, { "GETDNS_RRTYPE_HINFO", 13 }, @@ -308,6 +332,8 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RRTYPE_IXFR", 251 }, { "GETDNS_RRTYPE_KEY", 25 }, { "GETDNS_RRTYPE_KX", 36 }, + { "GETDNS_RRTYPE_L32", 105 }, + { "GETDNS_RRTYPE_L64", 106 }, { "GETDNS_RRTYPE_LOC", 29 }, { "GETDNS_RRTYPE_LP", 107 }, { "GETDNS_RRTYPE_MAILA", 254 }, @@ -327,6 +353,8 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RRTYPE_NSAP", 22 }, { "GETDNS_RRTYPE_NSAP_PTR", 23 }, { "GETDNS_RRTYPE_NSEC", 47 }, + { "GETDNS_RRTYPE_NSEC3", 50 }, + { "GETDNS_RRTYPE_NSEC3PARAM", 51 }, { "GETDNS_RRTYPE_NULL", 10 }, { "GETDNS_RRTYPE_NXT", 30 }, { "GETDNS_RRTYPE_OPENPGPKEY", 61 }, @@ -355,6 +383,13 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RRTYPE_UNSPEC", 103 }, { "GETDNS_RRTYPE_URI", 256 }, { "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_ONLY", 542 }, { "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", 543 }, diff --git a/src/context.c b/src/context.c index 5c40f2e3..aa0478ff 100644 --- a/src/context.c +++ b/src/context.c @@ -117,15 +117,15 @@ typedef struct host_name_addrs { } host_name_addrs; -/* If changing these lists also remember to +/* If changing these lists also remember to change the value of GETDNS_UPSTREAM_TRANSPORTS */ -static getdns_transport_list_t +static getdns_transport_list_t getdns_upstream_transports[GETDNS_UPSTREAM_TRANSPORTS] = { GETDNS_TRANSPORT_TCP, GETDNS_TRANSPORT_TLS, }; -static in_port_t +static in_port_t getdns_port_array[GETDNS_UPSTREAM_TRANSPORTS] = { GETDNS_PORT_DNS, GETDNS_PORT_DNS_OVER_TLS @@ -168,7 +168,7 @@ _getdns_strdup2(const struct mem_funcs *mfs, const getdns_bindata *s) return NULL; else { r[s->size] = '\0'; - return memcpy(r, s, s->size); + return memcpy(r, s->data, s->size); } } @@ -202,16 +202,15 @@ static void destroy_local_host(_getdns_rbnode_t * node, void *arg) * TODO: Determine from OS */ static getdns_return_t -create_default_namespaces(struct getdns_context *context) +create_default_namespaces(getdns_context *context) { - context->namespaces = GETDNS_XMALLOC(context->my_mf, getdns_namespace_t, 2); - if(context->namespaces == NULL) - return GETDNS_RETURN_GENERIC_ERROR; + if (!( context->namespaces + = GETDNS_XMALLOC(context->my_mf, getdns_namespace_t, 2))) + return GETDNS_RETURN_MEMORY_ERROR; context->namespaces[0] = GETDNS_NAMESPACE_LOCALNAMES; context->namespaces[1] = GETDNS_NAMESPACE_DNS; context->namespace_count = 2; - return GETDNS_RETURN_GOOD; } @@ -219,11 +218,11 @@ create_default_namespaces(struct getdns_context *context) * Helper to get default transports. */ static getdns_return_t -create_default_dns_transports(struct getdns_context *context) +create_default_dns_transports(getdns_context *context) { - context->dns_transports = GETDNS_XMALLOC(context->my_mf, getdns_transport_list_t, 2); - if(context->dns_transports == NULL) - return GETDNS_RETURN_GENERIC_ERROR; + if (!( context->dns_transports + = GETDNS_XMALLOC(context->my_mf, getdns_transport_list_t, 2))) + return GETDNS_RETURN_MEMORY_ERROR; context->dns_transports[0] = GETDNS_TRANSPORT_UDP; context->dns_transports[1] = GETDNS_TRANSPORT_TCP; @@ -287,7 +286,7 @@ local_host_cmp(const void *id1, const void *id2) } /** return 0 on success */ -static int +static getdns_return_t add_local_host(getdns_context *context, getdns_dict *address, const char *str) { uint8_t host_name[256]; @@ -296,9 +295,10 @@ add_local_host(getdns_context *context, getdns_dict *address, const char *str) getdns_bindata *address_type; int hnas_found = 0; getdns_list **addrs; + getdns_return_t r; if (gldns_str2wire_dname_buf(str, host_name, &host_name_len)) - return -1; + return GETDNS_RETURN_BAD_DOMAIN_NAME; canonicalize_dname(host_name); @@ -307,7 +307,7 @@ add_local_host(getdns_context *context, getdns_dict *address, const char *str) if (!(hnas = (host_name_addrs *)GETDNS_XMALLOC(context->mf, uint8_t, sizeof(host_name_addrs) + host_name_len))) - return -1; + return GETDNS_RETURN_MEMORY_ERROR; hnas->ipv4addrs = NULL; hnas->ipv6addrs = NULL; @@ -317,35 +317,33 @@ add_local_host(getdns_context *context, getdns_dict *address, const char *str) } else hnas_found = 1; - if (getdns_dict_get_bindata(address, "address_type", &address_type) || - - address_type->size < 4 || - - !(addrs = address_type->data[3] == '4'? &hnas->ipv4addrs + if ((r = getdns_dict_get_bindata(address,"address_type",&address_type)) + || address_type->size < 4 + || !(addrs = address_type->data[3] == '4'? &hnas->ipv4addrs : address_type->data[3] == '6'? &hnas->ipv4addrs : NULL)) { if (!hnas_found) GETDNS_FREE(context->mf, hnas); - return -1; + return r ? r : GETDNS_RETURN_WRONG_TYPE_REQUESTED; } if (!*addrs && !(*addrs = getdns_list_create_with_context(context))) { if (!hnas_found) GETDNS_FREE(context->mf, hnas); - return -1; + return GETDNS_RETURN_MEMORY_ERROR; } - if (_getdns_list_append_this_dict(*addrs, address)) { + if ((r = _getdns_list_append_this_dict(*addrs, address))) { if (!hnas_found) { getdns_list_destroy(*addrs); GETDNS_FREE(context->mf, hnas); } - return -1; + return r; } else if (!hnas_found) (void)_getdns_rbtree_insert(&context->local_hosts, &hnas->node); - return 0; + return GETDNS_RETURN_GOOD; } static getdns_dict * -sockaddr_dict(getdns_context *context, struct sockaddr *sa) +sockaddr_dict(const getdns_context *context, struct sockaddr *sa) { getdns_dict *address = getdns_dict_create_with_context(context); char addrstr[1024], *b; @@ -463,7 +461,7 @@ getdns_return_t getdns_context_set_hosts(getdns_context *context, const char *hosts) { /* enough space in buf for longest allowed domain name */ - char buf[1024]; + char buf[2048]; char *pos = buf, prev_c, *start_of_word = NULL; FILE *in; int start_of_line = 1; @@ -475,7 +473,7 @@ getdns_context_set_hosts(getdns_context *context, const char *hosts) if (!(in = fopen(hosts, "r"))) return GETDNS_RETURN_IO_ERROR; - (void)strlcpy(context->fchg_hosts.fn, hosts, _GETDNS_PATH_MAX); + (void) strlcpy(context->fchg_hosts.fn, hosts, _GETDNS_PATH_MAX); (void) memset(&context->fchg_hosts.prevstat, 0, sizeof(struct stat)); context->fchg_hosts.changes = GETDNS_FCHG_NOCHANGES; context->fchg_hosts.errors = GETDNS_FCHG_NOERROR; @@ -489,7 +487,7 @@ getdns_context_set_hosts(getdns_context *context, const char *hosts) /* Break out of for to read more */ for (;;) { /* Skip whitespace */ - while (*pos == ' ' || *pos == '\f' + while (*pos == ' ' || *pos == '\f' || *pos == '\t' || *pos == '\v') pos++; @@ -528,7 +526,7 @@ getdns_context_set_hosts(getdns_context *context, const char *hosts) *pos = '\0'; if (start_of_line) { start_of_line = 0; - if (address) + if (address) getdns_dict_destroy(address); if (!(address = str_addr_dict(context, start_of_word))) @@ -567,7 +565,7 @@ read_more: ; } getdns_return_t -getdns_context_get_hosts(getdns_context *context, const char **hosts) +getdns_context_get_hosts(const getdns_context *context, const char **hosts) { if (!context || !hosts) return GETDNS_RETURN_INVALID_PARAMETER; @@ -583,15 +581,18 @@ upstreams_create(getdns_context *context, size_t size) getdns_upstreams *r = (void *) GETDNS_XMALLOC(context->mf, char, sizeof(getdns_upstreams) + sizeof(getdns_upstream) * size); - r->mf = context->mf; - r->referenced = 1; - r->count = 0; - r->current_udp = 0; - r->current_stateful = 0; - r->max_backoff_value = context->max_backoff_value; - r->tls_backoff_time = context->tls_backoff_time; - r->tls_connection_retries = context->tls_connection_retries; - r->log = context->log; + + if (r) { + r->mf = context->mf; + r->referenced = 1; + r->count = 0; + r->current_udp = 0; + r->current_stateful = 0; + r->max_backoff_value = context->max_backoff_value; + r->tls_backoff_time = context->tls_backoff_time; + r->tls_connection_retries = context->tls_connection_retries; + r->log = context->log; + } return r; } @@ -653,28 +654,14 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams) upstream->tls_pubkey_pinset = NULL; if (upstream->tls_cipher_list) GETDNS_FREE(upstreams->mf, upstream->tls_cipher_list); + if (upstream->tls_ciphersuites) + GETDNS_FREE(upstreams->mf, upstream->tls_ciphersuites); if (upstream->tls_curves_list) GETDNS_FREE(upstreams->mf, upstream->tls_curves_list); } GETDNS_FREE(upstreams->mf, upstreams); } -void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system, - getdns_loglevel_type level, const char *fmt, ...) -{ - va_list args; - - if (!upstream || !upstream->upstreams || !upstream->upstreams->log.func - || !(upstream->upstreams->log.system & system) - || level > upstream->upstreams->log.level) - return; - - va_start(args, fmt); - upstream->upstreams->log.func( - upstream->upstreams->log.userarg, system, level, fmt, args); - va_end(args); -} - static void upstream_backoff(getdns_upstream *upstream) { upstream->conn_state = GETDNS_CONN_BACKOFF; @@ -707,8 +694,8 @@ static void _getdns_upstream_reset(getdns_upstream *upstream) { /* Back off connections that never got up service at all (probably no - TCP service or incompatible TLS version/cipher). - Leave choice between working upstreams to the stub. + TCP service or incompatible TLS version/cipher). + Leave choice between working upstreams to the stub. This back-off should be time based for TLS according to RFC7858. For now, use the same basis if we simply can't get TCP service either.*/ /* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/ @@ -722,16 +709,16 @@ _getdns_upstream_reset(getdns_upstream *upstream) && upstream->total_responses == 0) || (upstream->conn_completed >= conn_retries && - upstream->total_responses == 0 && + upstream->total_responses == 0 && upstream->total_timeouts > GETDNS_TRANSPORT_FAIL_MULT)) { upstream_backoff(upstream); } /* If we didn't backoff it would be nice to reset the conn_backoff_interval - if the upstream is working well again otherwise it would get stuck at the + if the upstream is working well again otherwise it would get stuck at the tls_backoff_time forever... How about */ - if (upstream->conn_state != GETDNS_CONN_BACKOFF && + if (upstream->conn_state != GETDNS_CONN_BACKOFF && upstream->responses_received > 1) upstream->conn_backoff_interval = 1; @@ -911,7 +898,7 @@ upstream_init(getdns_upstream *upstream, upstream->addr_len = ai->ai_addrlen; (void) memcpy(&upstream->addr, ai->ai_addr, ai->ai_addrlen); - inet_ntop(upstream->addr.ss_family, upstream_addr(upstream), + inet_ntop(upstream->addr.ss_family, upstream_addr(upstream), upstream->addr_str, INET6_ADDRSTRLEN); /* How is this upstream doing on connections? */ @@ -941,7 +928,10 @@ upstream_init(getdns_upstream *upstream, upstream->tls_obj = NULL; upstream->tls_session = NULL; upstream->tls_cipher_list = NULL; + upstream->tls_ciphersuites = NULL; upstream->tls_curves_list = NULL; + upstream->tls_min_version = (getdns_tls_version_t)0; + upstream->tls_max_version = (getdns_tls_version_t)0; upstream->transport = GETDNS_TRANSPORT_TCP; upstream->tls_hs_state = GETDNS_HS_NONE; upstream->tls_auth_name[0] = '\0'; @@ -1004,7 +994,7 @@ static int get_dns_suffix_windows(getdns_list *suffix, char* domain) { returnStatus = RegQueryValueEx(hKey, TEXT("SearchList"), 0, &dwType,(LPBYTE)&lszValue, &dwSize); - if (returnStatus == ERROR_SUCCESS) + if (returnStatus == ERROR_SUCCESS) { if ((strlen(lszValue)) > 0) { parse = lszValue; @@ -1070,7 +1060,7 @@ set_os_defaults_windows(getdns_context *context) info = (FIXED_INFO *)malloc(sizeof(FIXED_INFO)); if (info == NULL) - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_MEMORY_ERROR; if ((info_err = GetNetworkParams(info, &buflen)) == ERROR_BUFFER_OVERFLOW) { free(info); @@ -1250,7 +1240,8 @@ getdns_context_set_resolvconf(getdns_context *context, const char *resolvconf) #endif getdns_return_t -getdns_context_get_resolvconf(getdns_context *context, const char **resolvconf) +getdns_context_get_resolvconf( + const getdns_context *context, const char **resolvconf) { if (!context || !resolvconf) return GETDNS_RETURN_INVALID_PARAMETER; @@ -1447,11 +1438,15 @@ getdns_context_create_with_extended_memory_functions( result->trust_anchors_url = NULL; result->trust_anchors_verify_email = NULL; result->trust_anchors_verify_CA = NULL; + result->trust_anchors_backoff_time = 2500; result->appdata_dir = NULL; result->tls_ca_path = NULL; result->tls_ca_file = NULL; result->tls_cipher_list = NULL; + result->tls_ciphersuites = NULL; result->tls_curves_list = NULL; + result->tls_min_version = GETDNS_TLS1_2; + result->tls_max_version = (getdns_tls_version_t)0; (void) memset(&result->root_ksk, 0, sizeof(result->root_ksk)); @@ -1506,6 +1501,7 @@ getdns_context_create_with_extended_memory_functions( result->header = NULL; result->add_opt_parameters = NULL; result->add_warning_for_bad_dns = 0; + result->dnssec = 0; result->dnssec_return_all_statuses = 0; result->dnssec_return_full_validation_chain = 0; result->dnssec_return_only_secure = 0; @@ -1532,7 +1528,7 @@ getdns_context_create_with_extended_memory_functions( result->edns_maximum_udp_payload_size = -1; if ((r = create_default_dns_transports(result))) goto error; - result->tls_auth = GETDNS_AUTHENTICATION_NONE; + result->tls_auth = GETDNS_AUTHENTICATION_NONE; result->tls_auth_min = GETDNS_AUTHENTICATION_NONE; result->round_robin_upstreams = 0; result->tls_backoff_time = 3600; @@ -1571,7 +1567,7 @@ getdns_context_create_with_extended_memory_functions( #endif // resolv.conf does not exist on Windows, handle differently -#ifndef USE_WINSOCK +#ifndef USE_WINSOCK if ((set_from_os & 1)) { (void) getdns_context_set_resolvconf(result, GETDNS_FN_RESOLVCONF); (void) getdns_context_set_hosts(result, GETDNS_FN_HOSTS); @@ -1715,6 +1711,8 @@ getdns_context_destroy(struct getdns_context *context) GETDNS_FREE(context->mf, context->tls_ca_file); if (context->tls_cipher_list) GETDNS_FREE(context->mf, context->tls_cipher_list); + if (context->tls_ciphersuites) + GETDNS_FREE(context->mf, context->tls_ciphersuites); if (context->tls_curves_list) GETDNS_FREE(context->mf, context->tls_curves_list); @@ -1749,7 +1747,8 @@ getdns_context_set_update_callback(getdns_context *context, void *userarg, } 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 (**cb)(getdns_context *, getdns_context_code_t, void *)) { if (!context || !userarg || !cb) @@ -1777,20 +1776,6 @@ getdns_context_set_logfunc(getdns_context *context, void *userarg, return GETDNS_RETURN_GOOD; } -void _getdns_context_log(getdns_context *context, uint64_t system, - getdns_loglevel_type level, const char *fmt, ...) -{ - va_list args; - - if (!context || !context->log.func || !(context->log.system & system) - || level > context->log.level) - return; - - va_start(args, fmt); - context->log.func(context->log.userarg, system, level, fmt, args); - va_end(args); -} - #ifdef HAVE_LIBUNBOUND /* * Helpers to set options on the unbound ctx @@ -1970,7 +1955,7 @@ getdns_context_set_resolution_type(struct getdns_context *context, */ getdns_return_t getdns_context_set_namespaces(getdns_context *context, - size_t namespace_count, getdns_namespace_t *namespaces) + size_t namespace_count, const getdns_namespace_t *namespaces) { size_t i; getdns_return_t r = GETDNS_RETURN_GOOD; @@ -2088,7 +2073,7 @@ set_ub_dns_transport(struct getdns_context* context) { break; } } - if (fallback == 0) + if (fallback == 0) /* Use TLS if it is the only thing.*/ set_ub_string_opt(context, "ssl-upstream:", "yes"); break; @@ -2195,7 +2180,7 @@ getdns_context_set_tls_authentication(getdns_context *context, getdns_tls_authentication_t value) { RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - if (value != GETDNS_AUTHENTICATION_NONE && + if (value != GETDNS_AUTHENTICATION_NONE && value != GETDNS_AUTHENTICATION_REQUIRED) { return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } @@ -2231,7 +2216,7 @@ getdns_context_set_round_robin_upstreams(getdns_context *context, uint8_t value) * before the upstream which has previously timed out will be tried again. * @see getdns_context_get_max_backoff_value * @param[in] context The context to configure - * @param[in[ value Number of messages sent to other upstreams before + * @param[in[ value Number of messages sent to other upstreams before * retrying the upstream which had timed out. * @return GETDNS_RETURN_GOOD on success * @return GETDNS_RETURN_INVALID_PARAMETER if context is null. @@ -2930,13 +2915,18 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context, if (dict && getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) { getdns_list *pubkey_pinset = NULL; getdns_bindata *tls_cipher_list = NULL; + getdns_bindata *tls_ciphersuites = NULL; getdns_bindata *tls_curves_list = NULL; + uint32_t tls_version; + /* Missing support in TLS library is + * detected and reported during connection setup. + */ if ((r = getdns_dict_get_bindata( dict, "tls_auth_name", &tls_auth_name)) == GETDNS_RETURN_GOOD) { if (tls_auth_name->size >= sizeof(upstream->tls_auth_name)) { - /* tls_auth_name's are + /* tls_auth_name's are * domain names in presentation * format and, taking escaping * into account, should not @@ -2969,19 +2959,26 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context, ? _getdns_strdup2(&upstreams->mf , tls_cipher_list) : NULL; + (void) getdns_dict_get_bindata( + dict, "tls_ciphersuites", &tls_ciphersuites); + upstream->tls_ciphersuites = tls_ciphersuites + ? _getdns_strdup2(&upstreams->mf + , tls_ciphersuites) + : NULL; (void) getdns_dict_get_bindata( dict, "tls_curves_list", &tls_curves_list); if (tls_curves_list) { -#if HAVE_TLS_CONN_CURVES_LIST - upstream->tls_curves_list = + upstream->tls_curves_list = _getdns_strdup2(&upstreams->mf , tls_curves_list); -#else - freeaddrinfo(ai); - goto not_implemented; -#endif } else upstream->tls_curves_list = NULL; + if (!getdns_dict_get_int( + dict, "tls_min_version", &tls_version)) + upstream->tls_min_version = tls_version; + if (!getdns_dict_get_int( + dict, "tls_max_version", &tls_version)) + upstream->tls_max_version = tls_version; } if ((upstream->tsig_alg = tsig_alg)) { if (tsig_name) { @@ -3019,11 +3016,6 @@ invalid_parameter: error: _getdns_upstreams_dereference(upstreams); return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; -#if !HAVE_TLS_CONN_CURVES_LIST -not_implemented: - _getdns_upstreams_dereference(upstreams); - return GETDNS_RETURN_NOT_IMPLEMENTED; -#endif } /* getdns_context_set_upstream_recursive_servers */ @@ -3382,18 +3374,36 @@ ub_setup_stub(struct ub_ctx *ctx, getdns_context *context) getdns_upstream *upstream; char addr[1024]; getdns_upstreams *upstreams = context->upstreams; + int r; - (void) ub_ctx_set_fwd(ctx, NULL); + if ((r = ub_ctx_set_fwd(ctx, NULL))) { + _getdns_log(&context->log + , GETDNS_LOG_SYS_STUB, GETDNS_LOG_WARNING + , "%s: %s (%s)\n" + , STUB_DEBUG_SETUP + , "Error while clearing forwarding modus on unbound context" + , ub_strerror(r)); + } for (i = 0; i < upstreams->count; i++) { upstream = &upstreams->upstreams[i]; - /*[TLS]: Use only the TLS subset of upstreams when TLS is the only thing - * used. All other cases must currently fallback to TCP for libunbound.*/ + /* [TLS]: Use only the TLS subset of upstreams when TLS is the + * only thing used. All other cases must currently fallback to + * TCP for libunbound.*/ if (context->dns_transports[0] == GETDNS_TRANSPORT_TLS && context->dns_transport_count ==1 && upstream->transport != GETDNS_TRANSPORT_TLS) continue; upstream_ntop_buf(upstream, addr, 1024); - ub_ctx_set_fwd(ctx, addr); + if ((r = ub_ctx_set_fwd(ctx, addr))) { + _getdns_log(&context->log + , GETDNS_LOG_SYS_STUB, GETDNS_LOG_WARNING + , "%s: %s '%s' (%s)\n" + , STUB_DEBUG_SETUP + , "Error while setting up unbound context for " + "forwarding to" + , addr + , ub_strerror(r)); + } } /* Allow lookups of: @@ -3463,8 +3473,16 @@ ub_setup_recursing(struct ub_ctx *ctx, getdns_context *context) { _getdns_rr_iter rr_spc, *rr; char ta_str[8192]; + int r; - (void) ub_ctx_set_fwd(ctx, NULL); + if ((r = ub_ctx_set_fwd(ctx, NULL))) { + _getdns_log(&context->log + , GETDNS_LOG_SYS_RECURSING, GETDNS_LOG_WARNING + , "%s: %s (%s)\n" + , STUB_DEBUG_SETUP + , "Error while clearing forwarding modus on unbound context" + , ub_strerror(r)); + } if (!context->unbound_ta_set && context->trust_anchors) { for ( rr = _getdns_rr_iter_init( &rr_spc , context->trust_anchors @@ -3473,7 +3491,17 @@ ub_setup_recursing(struct ub_ctx *ctx, getdns_context *context) (void) gldns_wire2str_rr_buf((UNCONST_UINT8_p)rr->pos, rr->nxt - rr->pos, ta_str, sizeof(ta_str)); - (void) ub_ctx_add_ta(ctx, ta_str); + if ((r = ub_ctx_add_ta(ctx, ta_str))) { + _getdns_log(&context->log + , GETDNS_LOG_SYS_RECURSING + , GETDNS_LOG_WARNING + , "%s: %s '%s' (%s)\n" + , STUB_DEBUG_SETUP + , "Error while equiping unbound context " + "with trust anchor" + , ta_str + , ub_strerror(r)); + } } context->unbound_ta_set = 1; } @@ -3488,8 +3516,15 @@ _getdns_ns_dns_setup(struct getdns_context *context) switch (context->resolution_type) { case GETDNS_RESOLUTION_STUB: - if (!context->upstreams || !context->upstreams->count) - return GETDNS_RETURN_GENERIC_ERROR; + if (!context->upstreams || !context->upstreams->count) { + _getdns_log(&context->log + , GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR + , "%s: %s\n" + , STUB_DEBUG_SETUP + , "Stub resolution requested, but no upstreams " + "configured"); + return GETDNS_RETURN_BAD_CONTEXT; + } #ifdef STUB_NATIVE_DNSSEC # ifdef DNSSEC_ROADBLOCK_AVOIDANCE # ifdef HAVE_LIBUNBOUND @@ -3514,6 +3549,12 @@ _getdns_ns_dns_setup(struct getdns_context *context) return GETDNS_RETURN_NOT_IMPLEMENTED; #endif } + _getdns_log(&context->log + , GETDNS_LOG_SYS_RESOLVING + , GETDNS_LOG_ERR + , "%s: %s (%d)\n", STUB_DEBUG_SETUP + , "Unknown resolution type: " + , context->resolution_type); return GETDNS_RETURN_BAD_CONTEXT; } @@ -3522,49 +3563,65 @@ _getdns_context_prepare_for_resolution(getdns_context *context) { getdns_return_t r; - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); + assert(context); if (context->destroying) return GETDNS_RETURN_BAD_CONTEXT; /* Transport can in theory be set per query in stub mode */ - if (context->resolution_type == GETDNS_RESOLUTION_STUB && + if (context->resolution_type == GETDNS_RESOLUTION_STUB && tls_is_in_transports_list(context) == 1) { /* Check minimum require authentication level*/ - if (tls_only_is_in_transports_list(context) == 1 && + if (tls_only_is_in_transports_list(context) == 1 && context->tls_auth == GETDNS_AUTHENTICATION_REQUIRED) { context->tls_auth_min = GETDNS_AUTHENTICATION_REQUIRED; - /* TODO: If no auth data provided for any upstream, fail here */ + /* TODO: If no auth data provided for any upstream, + * fail here + */ } else { context->tls_auth_min = GETDNS_AUTHENTICATION_NONE; } if (context->tls_ctx == NULL) { - context->tls_ctx = _getdns_tls_context_new(&context->my_mf); + context->tls_ctx = _getdns_tls_context_new(&context->my_mf, &context->log); if (context->tls_ctx == NULL) return GETDNS_RETURN_BAD_CONTEXT; - r = _getdns_tls_context_set_min_proto_1_2(context->tls_ctx); - if (r && r != GETDNS_RETURN_NOT_IMPLEMENTED) { + r = _getdns_tls_context_set_min_max_tls_version(context->tls_ctx, context->tls_min_version, context->tls_max_version); + if (r) { _getdns_tls_context_free(&context->my_mf, context->tls_ctx); context->tls_ctx = NULL; - return GETDNS_RETURN_BAD_CONTEXT; + return r; } + /* Be strict and only use the cipher suites recommended in RFC7525 Unless we later fallback to opportunistic. */ - if (_getdns_tls_context_set_cipher_list(context->tls_ctx, context->tls_cipher_list)) - return GETDNS_RETURN_BAD_CONTEXT; - - if (context->tls_curves_list && - _getdns_tls_context_set_curves_list(context->tls_ctx, context->tls_curves_list)) - return GETDNS_RETURN_BAD_CONTEXT; - + r = _getdns_tls_context_set_cipher_list(context->tls_ctx, context->tls_cipher_list); + if (!r) + r = _getdns_tls_context_set_cipher_suites(context->tls_ctx, context->tls_ciphersuites); + if (!r && context->tls_curves_list) + r = _getdns_tls_context_set_curves_list(context->tls_ctx, context->tls_curves_list); + if (r) { + _getdns_tls_context_free(&context->my_mf, context->tls_ctx); + context->tls_ctx = NULL; + return r; + } /* For strict authentication, we must have local root certs available Set up is done only when the tls_ctx is created (per getdns_context)*/ if (_getdns_tls_context_set_ca(context->tls_ctx, context->tls_ca_file, context->tls_ca_path)) { - if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) + if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) { + _getdns_log(&context->log + , GETDNS_LOG_SYS_STUB + , GETDNS_LOG_DEBUG + , "%s: %s\n" + , STUB_DEBUG_SETUP_TLS + , "Authentication is needed but no " + "verify location could be loaded"); + _getdns_tls_context_free(&context->my_mf, context->tls_ctx); + context->tls_ctx = NULL; return GETDNS_RETURN_BAD_CONTEXT; + } } _getdns_tls_context_pinset_init(context->tls_ctx); } @@ -3574,9 +3631,17 @@ _getdns_context_prepare_for_resolution(getdns_context *context) /* Note: If TLS is used in recursive mode this will try TLS on port * 53 so it is blocked here. */ if (context->resolution_type == GETDNS_RESOLUTION_RECURSING && - tls_only_is_in_transports_list(context) == 1) - return GETDNS_RETURN_BAD_CONTEXT; - + tls_only_is_in_transports_list(context) == 1) { + _getdns_log(&context->log + , GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR + , "%s: %s\n" + , STUB_DEBUG_SETUP_TLS + , "TLS only transport is not supported for the recursing " + "resolution type"); + _getdns_tls_context_free(&context->my_mf, context->tls_ctx); + context->tls_ctx = NULL; + return GETDNS_RETURN_NOT_IMPLEMENTED; + } if (context->resolution_type_set == context->resolution_type) /* already set and no config changes * have caused this to be bad. @@ -3587,8 +3652,6 @@ _getdns_context_prepare_for_resolution(getdns_context *context) * the spec calls for us to treat the namespace list as ordered * so we need to respect that order */ - - r = _getdns_ns_dns_setup(context); if (r == GETDNS_RETURN_GOOD) context->resolution_type_set = context->resolution_type; @@ -3647,7 +3710,7 @@ _getdns_bindata_destroy(struct mem_funcs *mfs, /* TODO: Remove next_timeout argument from getdns_context_get_num_pending_requests */ uint32_t -getdns_context_get_num_pending_requests(getdns_context* context, +getdns_context_get_num_pending_requests(const getdns_context* context, struct timeval* next_timeout) { (void)next_timeout; @@ -3721,7 +3784,8 @@ getdns_context_set_eventloop(getdns_context* context, getdns_eventloop* loop) } getdns_return_t -getdns_context_get_eventloop(getdns_context *context, getdns_eventloop **loop) +getdns_context_get_eventloop( + const getdns_context *context, getdns_eventloop **loop) { if (!context || !loop) return GETDNS_RETURN_INVALID_PARAMETER; @@ -3734,9 +3798,9 @@ getdns_context_get_eventloop(getdns_context *context, getdns_eventloop **loop) return GETDNS_RETURN_GOOD; } -static size_t _getdns_get_appdata(getdns_context *context, char *path); +static size_t _getdns_get_appdata(const getdns_context *context, char *path); static getdns_dict* -_get_context_settings(getdns_context* context) +_get_context_settings(const getdns_context* context) { getdns_dict *result = getdns_dict_create_with_context(context); getdns_list *list; @@ -3787,6 +3851,8 @@ _get_context_settings(getdns_context* context) context->tls_query_padding_blocksize) || getdns_dict_set_int(result, "resolution_type", context->resolution_type) + || getdns_dict_set_int(result, "trust_anchors_backoff_time", + context->trust_anchors_backoff_time) ) goto error; @@ -3867,8 +3933,16 @@ _get_context_settings(getdns_context* context) (void) getdns_dict_util_set_string(result, "tls_ca_file", str_value); if (!getdns_context_get_tls_cipher_list(context, &str_value) && str_value) (void) getdns_dict_util_set_string(result, "tls_cipher_list", str_value); + if (!getdns_context_get_tls_ciphersuites(context, &str_value) && str_value) + (void) getdns_dict_util_set_string(result, "tls_ciphersuites", str_value); if (!getdns_context_get_tls_curves_list(context, &str_value) && str_value) (void) getdns_dict_util_set_string(result, "tls_curves_list", str_value); + if (context->tls_min_version) + (void) getdns_dict_set_int( result, "tls_min_version" + , context->tls_min_version); + if (context->tls_max_version) + (void) getdns_dict_set_int( result, "tls_max_version" + , context->tls_max_version); /* Default settings for extensions */ (void)getdns_dict_set_int( @@ -3883,6 +3957,10 @@ _get_context_settings(getdns_context* context) result, "dnssec_return_full_validation_chain", context->dnssec_return_full_validation_chain ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE); + (void)getdns_dict_set_int( + result, "dnssec", + context->dnssec ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE); + (void)getdns_dict_set_int( result, "dnssec_return_only_secure", context->dnssec_return_only_secure ? GETDNS_EXTENSION_TRUE @@ -3934,7 +4012,7 @@ error: } getdns_dict* -getdns_context_get_api_information(getdns_context* context) +getdns_context_get_api_information(const getdns_context* context) { getdns_dict* result; getdns_dict* settings; @@ -4021,7 +4099,7 @@ _getdns_context_local_namespace_resolve( getdns_context *context = dnsreq->context; host_name_addrs *hnas; uint8_t lookup[256]; - getdns_list empty_list = { 0, 0, NULL, { NULL, {{ NULL, NULL, NULL }}}}; + getdns_list empty_list = { 0, 0, NULL, { NULL, {{ NULL,NULL,NULL}}}}; getdns_bindata bindata; getdns_list *jaa; size_t i; @@ -4032,9 +4110,10 @@ _getdns_context_local_namespace_resolve( int ipv6 = dnsreq->netreqs[0]->request_type == GETDNS_RRTYPE_AAAA || (dnsreq->netreqs[1] && dnsreq->netreqs[1]->request_type == GETDNS_RRTYPE_AAAA); + getdns_return_t r; if (!ipv4 && !ipv6) - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; /*Do the lookup*/ (void)memcpy(lookup, dnsreq->name, dnsreq->name_len); @@ -4042,59 +4121,61 @@ _getdns_context_local_namespace_resolve( if (!(hnas = (host_name_addrs *) _getdns_rbtree_search(&context->local_hosts, lookup))) - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_NO_SUCH_DICT_NAME; if (!hnas->ipv4addrs && (!ipv6 || !hnas->ipv6addrs)) - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_NO_SUCH_DICT_NAME; if (!hnas->ipv6addrs && (!ipv4 || !hnas->ipv4addrs)) - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_NO_SUCH_DICT_NAME; if (!(*response = getdns_dict_create_with_context(context))) - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_MEMORY_ERROR; bindata.size = dnsreq->name_len; bindata.data = dnsreq->name; - if (getdns_dict_set_bindata(*response, "canonical_name", &bindata)) + if ((r = getdns_dict_set_bindata(*response,"canonical_name",&bindata))) goto error; empty_list.mf = context->mf; - if (getdns_dict_set_list(*response, "replies_full", &empty_list)) + if ((r = getdns_dict_set_list(*response, "replies_full", &empty_list))) goto error; - if (getdns_dict_set_list(*response, "replies_tree", &empty_list)) + if ((r = getdns_dict_set_list(*response, "replies_tree", &empty_list))) goto error; - if (getdns_dict_set_int(*response, "status", GETDNS_RESPSTATUS_GOOD)) + if ((r=getdns_dict_set_int(*response,"status",GETDNS_RESPSTATUS_GOOD))) goto error; if (!ipv4 || !hnas->ipv4addrs) { - if (getdns_dict_set_list(*response, - "just_address_answers", hnas->ipv6addrs)) + if ((r = getdns_dict_set_list(*response, + "just_address_answers", hnas->ipv6addrs))) goto error; return GETDNS_RETURN_GOOD; } else if (!ipv6 || !hnas->ipv6addrs) { - if (getdns_dict_set_list(*response, - "just_address_answers", hnas->ipv4addrs)) + if ((r = getdns_dict_set_list(*response, + "just_address_answers", hnas->ipv4addrs))) goto error; return GETDNS_RETURN_GOOD; } - if (!(jaa = getdns_list_create_with_context(context))) + if (!(jaa = getdns_list_create_with_context(context))) { + r = GETDNS_RETURN_MEMORY_ERROR; goto error; + } for (i = 0; !getdns_list_get_dict(hnas->ipv4addrs, i, &addr); i++) - if (_getdns_list_append_dict(jaa, addr)) + if ((r = _getdns_list_append_dict(jaa, addr))) break; for (i = 0; !getdns_list_get_dict(hnas->ipv6addrs, i, &addr); i++) - if (_getdns_list_append_dict(jaa, addr)) + if ((r = _getdns_list_append_dict(jaa, addr))) break; - if (!_getdns_dict_set_this_list(*response, "just_address_answers", jaa)) + if (!(r = _getdns_dict_set_this_list(*response, "just_address_answers", jaa))) return GETDNS_RETURN_GOOD; else getdns_list_destroy(jaa); error: getdns_dict_destroy(*response); - return GETDNS_RETURN_GENERIC_ERROR; + return r; } struct mem_funcs * @@ -4104,197 +4185,117 @@ priv_getdns_context_mf(getdns_context *context) } /** begin getters **/ + +#define CONTEXT_GETTER2(NAME,TYPE,VALUE) \ + getdns_return_t \ + getdns_context_get_ ## NAME ( \ + const getdns_context *context, TYPE *value) \ + { if (!context || !value) return GETDNS_RETURN_INVALID_PARAMETER \ + ; *value = context-> VALUE; return GETDNS_RETURN_GOOD; } + +#define CONTEXT_GETTER(NAME,TYPE) CONTEXT_GETTER2(NAME,TYPE,NAME) + +CONTEXT_GETTER(resolution_type, getdns_resolution_t) + getdns_return_t -getdns_context_get_resolution_type(getdns_context *context, - getdns_resolution_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->resolution_type; - return GETDNS_RETURN_GOOD; +getdns_context_get_namespaces(const getdns_context *context, + size_t* namespace_count, getdns_namespace_t **namespaces) +{ + if (!context || !namespace_count || !namespaces) + return GETDNS_RETURN_INVALID_PARAMETER; + *namespace_count = context->namespace_count; + if (!context->namespace_count) { + *namespaces = NULL; + return GETDNS_RETURN_GOOD; + } + // use normal malloc here so users can do normal free + *namespaces = malloc( + context->namespace_count * sizeof(getdns_namespace_t)); + memcpy(*namespaces, context->namespaces, + context->namespace_count * sizeof(getdns_namespace_t)); + return GETDNS_RETURN_GOOD; } getdns_return_t -getdns_context_get_namespaces(getdns_context *context, - size_t* namespace_count, getdns_namespace_t **namespaces) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(namespace_count, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(namespaces, GETDNS_RETURN_INVALID_PARAMETER); - *namespace_count = context->namespace_count; - if (!context->namespace_count) { - *namespaces = NULL; - return GETDNS_RETURN_GOOD; - } - // use normal malloc here so users can do normal free - *namespaces = malloc(context->namespace_count * sizeof(getdns_namespace_t)); - memcpy(*namespaces, context->namespaces, - context->namespace_count * sizeof(getdns_namespace_t)); - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_dns_transport(getdns_context *context, - getdns_transport_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - int count = context->dns_transport_count; - getdns_transport_list_t *transports = context->dns_transports; - if (!count) - return GETDNS_RETURN_WRONG_TYPE_REQUESTED; - - /* Best effort mapping for backwards compatibility*/ - if (transports[0] == GETDNS_TRANSPORT_UDP) { - if (count == 1) - *value = GETDNS_TRANSPORT_UDP_ONLY; - else if (count == 2 && transports[1] == GETDNS_TRANSPORT_TCP) - *value = GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP; - else - return GETDNS_RETURN_WRONG_TYPE_REQUESTED; - } - if (transports[0] == GETDNS_TRANSPORT_TCP) { - if (count == 1) - *value = GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN; - } - if (transports[0] == GETDNS_TRANSPORT_TLS) { - if (count == 1) - *value = GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN; - else if (count == 2 && transports[1] == GETDNS_TRANSPORT_TCP) - *value = GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN; - else - return GETDNS_RETURN_WRONG_TYPE_REQUESTED; - } - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_dns_transport_list(getdns_context *context, - size_t* transport_count, getdns_transport_list_t **transports) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(transport_count, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(transports, GETDNS_RETURN_INVALID_PARAMETER); - *transport_count = context->dns_transport_count; - if (!context->dns_transport_count) { - *transports = NULL; - return GETDNS_RETURN_GOOD; - } - // use normal malloc here so users can do normal free - *transports = malloc(context->dns_transport_count * sizeof(getdns_transport_list_t)); - memcpy(*transports, context->dns_transports, - context->dns_transport_count * sizeof(getdns_transport_list_t)); - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_tls_authentication(getdns_context *context, - getdns_tls_authentication_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->tls_auth; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_round_robin_upstreams(getdns_context *context, - uint8_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->round_robin_upstreams; - return GETDNS_RETURN_GOOD; -} - -/** - * Get the maximum number of messages that can be sent to other upstreams - * before the upstream which has previously timed out will be tried again. - * @see getdns_context_set_max_backoff_value - * @param[in] context The context from which to get the setting - * @param[out] value Number of messages sent to other upstreams before - * retrying the upstream which had timed out. - * @return GETDNS_RETURN_GOOD on success - * @return GETDNS_RETURN_INVALID_PARAMETER if context is null. - */ -getdns_return_t -getdns_context_get_max_backoff_value(getdns_context *context, - uint16_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->max_backoff_value; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_tls_backoff_time(getdns_context *context, - uint16_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->tls_backoff_time; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_tls_connection_retries(getdns_context *context, - uint16_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->tls_connection_retries; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_limit_outstanding_queries(getdns_context *context, - uint16_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->limit_outstanding_queries; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_timeout(getdns_context *context, uint64_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->timeout; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_idle_timeout(getdns_context *context, uint64_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->idle_timeout; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_follow_redirects( - getdns_context *context, getdns_redirects_t* value) +getdns_context_get_dns_transport( + const getdns_context *context, getdns_transport_t* value) { if (!context || !value) return GETDNS_RETURN_INVALID_PARAMETER; - *value = context->follow_redirects; - return GETDNS_RETURN_NOT_IMPLEMENTED; + + if (context->dns_transport_count == 0) + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + /* Best effort mapping for backwards compatibility*/ + if (context->dns_transports[0] == GETDNS_TRANSPORT_UDP) { + if (context->dns_transport_count == 1) + *value = GETDNS_TRANSPORT_UDP_ONLY; + else if (context->dns_transport_count == 2 + && context->dns_transports[1] == GETDNS_TRANSPORT_TCP) + *value = GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP; + else + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + } + if (context->dns_transports[0] == GETDNS_TRANSPORT_TCP) { + if (context->dns_transport_count == 1) + *value = GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN; + } + if (context->dns_transports[0] == GETDNS_TRANSPORT_TLS) { + if (context->dns_transport_count == 1) + *value = GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN; + else if (context->dns_transport_count == 2 + && context->dns_transports[1] == GETDNS_TRANSPORT_TCP) + *value = GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN; + else + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + } + return GETDNS_RETURN_GOOD; } getdns_return_t -getdns_context_get_dns_root_servers(getdns_context *context, - getdns_list **value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = NULL; - if (context->dns_root_servers) - return _getdns_list_copy(context->dns_root_servers, value); - return GETDNS_RETURN_GOOD; +getdns_context_get_dns_transport_list(const getdns_context *context, + size_t* transport_count, getdns_transport_list_t **transports) +{ + if (!context || !transport_count || !transports) + return GETDNS_RETURN_INVALID_PARAMETER; + *transport_count = context->dns_transport_count; + if (!context->dns_transport_count) { + *transports = NULL; + return GETDNS_RETURN_GOOD; + } + // use normal malloc here so users can do normal free + *transports = malloc( + context->dns_transport_count * sizeof(getdns_transport_list_t)); + memcpy(*transports, context->dns_transports, + context->dns_transport_count * sizeof(getdns_transport_list_t)); + return GETDNS_RETURN_GOOD; } -getdns_return_t -getdns_context_get_append_name(getdns_context *context, - getdns_append_name_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->append_name; - return GETDNS_RETURN_GOOD; -} +CONTEXT_GETTER2(tls_authentication, getdns_tls_authentication_t, tls_auth) +CONTEXT_GETTER(round_robin_upstreams , uint8_t) +CONTEXT_GETTER(max_backoff_value , uint16_t) +CONTEXT_GETTER(tls_backoff_time , uint16_t) +CONTEXT_GETTER(tls_connection_retries , uint16_t) +CONTEXT_GETTER(limit_outstanding_queries , uint16_t) +CONTEXT_GETTER(timeout , uint64_t) +CONTEXT_GETTER(idle_timeout , uint64_t) +CONTEXT_GETTER(follow_redirects , getdns_redirects_t) getdns_return_t -getdns_context_get_suffix(getdns_context *context, getdns_list **value) +getdns_context_get_dns_root_servers( + const getdns_context *context, getdns_list **value) +{ + if (!context || !value) return GETDNS_RETURN_INVALID_PARAMETER; + if (context->dns_root_servers) + return _getdns_list_copy(context->dns_root_servers, value); + *value = NULL; + return GETDNS_RETURN_GOOD; +} + +CONTEXT_GETTER(append_name , getdns_append_name_t) + +getdns_return_t +getdns_context_get_suffix(const getdns_context *context, getdns_list **value) { size_t dname_len; const uint8_t *dname; @@ -4332,10 +4333,9 @@ getdns_context_get_suffix(getdns_context *context, getdns_list **value) getdns_return_t getdns_context_get_dnssec_trust_anchors( - getdns_context *context, getdns_list **value) + const getdns_context *context, getdns_list **value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); + if (!context || !value) return GETDNS_RETURN_INVALID_PARAMETER; if (context->trust_anchors) { if ((*value = getdns_list_create_with_context(context))) @@ -4351,17 +4351,17 @@ getdns_context_get_dnssec_trust_anchors( } getdns_return_t -getdns_context_get_dnssec_allowed_skew(getdns_context *context, - uint32_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->dnssec_allowed_skew; - return GETDNS_RETURN_GOOD; +getdns_context_get_dnssec_allowed_skew( + const getdns_context *context, uint32_t* value) +{ + if (!context || !value) return GETDNS_RETURN_INVALID_PARAMETER; + *value = context->dnssec_allowed_skew; + return GETDNS_RETURN_GOOD; } getdns_return_t -getdns_context_get_upstream_recursive_servers(getdns_context *context, - getdns_list **upstreams_r) +getdns_context_get_upstream_recursive_servers( + const getdns_context *context, getdns_list **upstreams_r) { size_t i; getdns_list *upstreams; @@ -4452,11 +4452,26 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context, d, "tls_cipher_list", upstream->tls_cipher_list); } + if (upstream->tls_ciphersuites) { + (void) getdns_dict_util_set_string( + d, "tls_ciphersuites", + upstream->tls_ciphersuites); + } if (upstream->tls_curves_list) { (void) getdns_dict_util_set_string( d, "tls_curves_list", upstream->tls_curves_list); } + if (upstream->tls_min_version) { + (void) getdns_dict_set_int( + d, "tls_min_version", + upstream->tls_min_version); + } + if (upstream->tls_max_version) { + (void) getdns_dict_set_int( + d, "tls_max_version", + upstream->tls_max_version); + } } } if (!r) @@ -4472,55 +4487,20 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context, } getdns_return_t -getdns_context_get_edns_maximum_udp_payload_size(getdns_context *context, - uint16_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->edns_maximum_udp_payload_size == -1 ? 0 - : context->edns_maximum_udp_payload_size; - return GETDNS_RETURN_GOOD; +getdns_context_get_edns_maximum_udp_payload_size( + const getdns_context *context, uint16_t* value) +{ + if (!context || !value) return GETDNS_RETURN_INVALID_PARAMETER; + *value = context->edns_maximum_udp_payload_size == -1 ? 0 + : context->edns_maximum_udp_payload_size; + return GETDNS_RETURN_GOOD; } -getdns_return_t -getdns_context_get_edns_extended_rcode(getdns_context *context, - uint8_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->edns_extended_rcode; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_edns_version(getdns_context *context, uint8_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->edns_version; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->edns_do_bit; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->edns_client_subnet_private; - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t* value) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); - RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER); - *value = context->tls_query_padding_blocksize; - return GETDNS_RETURN_GOOD; -} +CONTEXT_GETTER(edns_extended_rcode , uint8_t) +CONTEXT_GETTER(edns_version , uint8_t) +CONTEXT_GETTER(edns_do_bit , uint8_t) +CONTEXT_GETTER(edns_client_subnet_private , uint8_t) +CONTEXT_GETTER(tls_query_padding_blocksize, uint16_t) static int _streq(const getdns_bindata *name, const char *str) { @@ -4669,6 +4649,7 @@ _getdns_context_config_setting(getdns_context *context, CONTEXT_SETTING_STRING(trust_anchors_url) CONTEXT_SETTING_STRING(trust_anchors_verify_CA) CONTEXT_SETTING_STRING(trust_anchors_verify_email) + CONTEXT_SETTING_INT(trust_anchors_backoff_time) CONTEXT_SETTING_STRING(appdata_dir) #ifndef USE_WINSOCK CONTEXT_SETTING_STRING(resolvconf) @@ -4677,7 +4658,10 @@ _getdns_context_config_setting(getdns_context *context, CONTEXT_SETTING_STRING(tls_ca_path) CONTEXT_SETTING_STRING(tls_ca_file) CONTEXT_SETTING_STRING(tls_cipher_list) + CONTEXT_SETTING_STRING(tls_ciphersuites) CONTEXT_SETTING_STRING(tls_curves_list) + CONTEXT_SETTING_INT(tls_min_version) + CONTEXT_SETTING_INT(tls_max_version) /**************************************/ /**** ****/ @@ -4685,6 +4669,7 @@ _getdns_context_config_setting(getdns_context *context, /**** ****/ /**************************************/ EXTENSION_SETTING_BOOL(add_warning_for_bad_dns) + EXTENSION_SETTING_BOOL(dnssec) EXTENSION_SETTING_BOOL(dnssec_return_all_statuses) EXTENSION_SETTING_BOOL(dnssec_return_full_validation_chain) EXTENSION_SETTING_BOOL(dnssec_return_only_secure) @@ -4777,7 +4762,7 @@ getdns_context_config(getdns_context *context, const getdns_dict *config_dict) return r; } -static size_t _getdns_get_appdata(getdns_context *context, char *path) +static size_t _getdns_get_appdata(const getdns_context *context, char *path) { size_t len = 0; @@ -4791,12 +4776,15 @@ static size_t _getdns_get_appdata(getdns_context *context, char *path) } else if (! SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) - DEBUG_ANCHOR("ERROR %s(): Could not get %%AppData%% directory\n" - , __FUNC__); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_NOTICE + , "Could not get %%AppData%% directory\n"); - else if ((len = strlen(path)) + sizeof(APPDATA_SUBDIR) + 2 >= _GETDNS_PATH_MAX) - DEBUG_ANCHOR("ERROR %s(): Home path too long for appdata\n" - , __FUNC__); + else if ((len = strlen(path)) + + sizeof(APPDATA_SUBDIR) + 2 >= _GETDNS_PATH_MAX) + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Path name for appdata directory too long\n"); #else # define SLASHTOK '/' # define APPDATA_SUBDIR ".getdns" @@ -4808,12 +4796,14 @@ static size_t _getdns_get_appdata(getdns_context *context, char *path) len = strlen(path); } else if (!(home = p ? p->pw_dir : getenv("HOME"))) - DEBUG_ANCHOR("ERROR %s(): Could not get home directory\n" - , __FUNC__); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_NOTICE + , "Unable to determine home directory location\n"); else if ((len = strlen(home)) + sizeof(APPDATA_SUBDIR) + 2 >= _GETDNS_PATH_MAX) - DEBUG_ANCHOR("ERROR %s(): Home path too long for appdata\n" - , __FUNC__); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Path name for appdata directory too long\n"); else if (!strcpy(path, home)) ; /* strcpy returns path always */ @@ -4838,8 +4828,10 @@ static size_t _getdns_get_appdata(getdns_context *context, char *path) mkdir(path, 0755) #endif && errno != EEXIST) - DEBUG_ANCHOR("ERROR %s(): Could not mkdir %s: %s\n" - , __FUNC__, path, strerror(errno)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "mkdir(\"%s\") failed: %s\n" + , path, _getdns_errnostr()); else { path[len++] = SLASHTOK; path[len ] = '\0'; @@ -4850,36 +4842,31 @@ static size_t _getdns_get_appdata(getdns_context *context, char *path) return 0; } -FILE *_getdns_context_get_priv_fp(getdns_context *context, const char *fn) +FILE *_getdns_context_get_priv_fp( + const getdns_context *context, const char *fn) { char path[_GETDNS_PATH_MAX]; FILE *f = NULL; size_t len = _getdns_get_appdata(context, path); - (void) context; -/* - * Commented out to enable fallback to current directory - * - * if (!(len = _getdns_get_appdata(context, path))) - * DEBUG_ANCHOR("ERROR %s(): Could nog get application data path\n" - * , __FUNC__); - * - * else - */ if (len + strlen(fn) >= sizeof(path)) - DEBUG_ANCHOR("ERROR %s(): Application data too long\n", __FUNC__); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Path name for appdata directory too long\n"); + else if (!strcpy(path + len, fn)) ; /* strcpy returns path + len always */ else if (!(f = fopen(path, "r"))) - DEBUG_ANCHOR("ERROR %s(): Opening \"%s\": %s\n" - , __FUNC__, path, strerror(errno)); - + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO + , "Error opening \"%s\": %s\n" + , path, _getdns_errnostr()); return f; } -uint8_t *_getdns_context_get_priv_file(getdns_context *context, +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) { FILE *f = NULL; @@ -4893,20 +4880,26 @@ uint8_t *_getdns_context_get_priv_file(getdns_context *context, return buf; } else if (fseek(f, 0, SEEK_END) < 0) - DEBUG_ANCHOR("ERROR %s(): Determining size of \"%s\": %s\n" - , __FUNC__, fn, strerror(errno)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error determining size of \"%s\": %s\n" + , fn, _getdns_errnostr()); else if (!(buf = GETDNS_XMALLOC( context->mf, uint8_t, (buf_len = ftell(f) + 1)))) - DEBUG_ANCHOR("ERROR %s(): Allocating %d memory for \"%s\"\n" - , __FUNC__, (int)buf_len, fn); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error allocating %d bytes of memory for \"%s\"\n" + , (int)buf_len, fn); else { rewind(f); if ((*file_sz = fread(buf, 1, buf_len, f)) >= buf_len || !feof(f)) { GETDNS_FREE(context->mf, buf); - DEBUG_ANCHOR("ERROR %s(): Reading \"%s\": %s\n" - , __FUNC__, fn, strerror(errno)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error reding \"%s\": %s\n" + , fn, _getdns_errnostr()); } else { buf[*file_sz] = 0; @@ -4928,46 +4921,51 @@ int _getdns_context_write_priv_file(getdns_context *context, FILE *f = NULL; size_t len = _getdns_get_appdata(context, path); -/* - * Commented out to enable fallback to current directory - * - * if (!(len = _getdns_get_appdata(context, path))) - * DEBUG_ANCHOR("ERROR %s(): Could nog get application data path\n" - * , __FUNC__); - * - * else - */ if (len + 6 >= sizeof(tmpfn) || len + strlen(fn) >= sizeof(path)) - DEBUG_ANCHOR("ERROR %s(): Application data too long\n", __FUNC__); - + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Application data filename \"%s\" too long\n" + , fn); else if (snprintf(tmpfn, sizeof(tmpfn), "%sXXXXXX", path) < 0) - DEBUG_ANCHOR("ERROR %s(): Creating temporary filename template: \"%s\"\n" - , __FUNC__, tmpfn); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error creating temporary file template \"%s\"\n" + , tmpfn); else if (!strcpy(path + len, fn)) ; /* strcpy returns path + len always */ else if ((fd = mkstemp(tmpfn)) < 0) - DEBUG_ANCHOR("ERROR %s(): Creating temporary file \"%s\": %s\n" - , __FUNC__, tmpfn, strerror(errno)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO + , "Could not create temporary file \"%s\": %s\n" + , tmpfn, _getdns_errnostr()); else if (!(f = fdopen(fd, "w"))) - DEBUG_ANCHOR("ERROR %s(): Opening temporary file: %s\n" - , __FUNC__, strerror(errno)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error opening temporary file \"%s\": %s\n" + , tmpfn, _getdns_errnostr()); else if (fwrite(content->data, 1, content->size, f) < content->size) - DEBUG_ANCHOR("ERROR %s(): Writing temporary file: %s\n" - , __FUNC__, strerror(errno)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error writing to temporary file \"%s\": %s\n" + , tmpfn, _getdns_errnostr()); else if (fclose(f) < 0) - DEBUG_ANCHOR("ERROR %s(): Closing temporary file: %s\n" - , __FUNC__, strerror(errno)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error closing temporary file \"%s\": %s\n" + , tmpfn, _getdns_errnostr()); else if (rename(tmpfn, path) < 0) - DEBUG_ANCHOR("ERROR %s(): Renaming temporary file: %s\n" - , __FUNC__, strerror(errno)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error renaming temporary file \"%s\" to \"%s\"" + ": %s\n", tmpfn, path, _getdns_errnostr()); else { context->can_write_appdata = PROP_ABLE; return 1; @@ -4979,6 +4977,8 @@ int _getdns_context_write_priv_file(getdns_context *context, (void) close(fd); context->can_write_appdata = PROP_UNABLE; + context->trust_anchors_backoff_expiry = + _getdns_get_now_ms() + context->trust_anchors_backoff_time; return 0; } @@ -4991,9 +4991,12 @@ int _getdns_context_can_write_appdata(getdns_context *context) if (context->can_write_appdata == PROP_ABLE) return 1; - else if (context->can_write_appdata == PROP_UNABLE) - return 0; - + else if (context->can_write_appdata == PROP_UNABLE) { + if (_getdns_ms_until_expiry( + context->trust_anchors_backoff_expiry) > 0) + return 0; + context->can_write_appdata = PROP_UNKNOWN; + } (void) snprintf( test_fn, sizeof(test_fn) , "write-test-%d.tmp", arc4random()); @@ -5001,26 +5004,21 @@ int _getdns_context_can_write_appdata(getdns_context *context) return 0; len = _getdns_get_appdata(context, path); -/* - * Commented out to enable fallback to current directory - * - * - * if (!(len = _getdns_get_appdata(context, path))) - * DEBUG_ANCHOR("ERROR %s(): Could not get application data path\n" - * , __FUNC__); - * - * else - */ + if (len + strlen(test_fn) >= sizeof(path)) - DEBUG_ANCHOR("ERROR %s(): Application data too long\n", __FUNC__); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Application data too long \"%s\" + \"%s\"\n" + , path, test_fn); else if (!strcpy(path + len, test_fn)) ; /* strcpy returns path + len always */ else if (unlink(path) < 0) - DEBUG_ANCHOR("ERROR %s(): Unlinking write test file \"%s\": %s\n" - , __FUNC__, path, strerror(errno)); - + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Error unlinking write test file: \"%s\": %s\n" + , path, _getdns_errnostr()); return 1; } @@ -5064,7 +5062,7 @@ getdns_context_set_trust_anchors_url( getdns_return_t getdns_context_get_trust_anchors_url( - getdns_context *context, const char **url) + const getdns_context *context, const char **url) { if (!context || !url) return GETDNS_RETURN_INVALID_PARAMETER; @@ -5094,7 +5092,7 @@ getdns_context_set_trust_anchors_verify_CA( getdns_return_t getdns_context_get_trust_anchors_verify_CA( - getdns_context *context, const char **verify_CA) + const getdns_context *context, const char **verify_CA) { if (!verify_CA) return GETDNS_RETURN_INVALID_PARAMETER; @@ -5124,7 +5122,7 @@ getdns_context_set_trust_anchors_verify_email( getdns_return_t getdns_context_get_trust_anchors_verify_email( - getdns_context *context, const char **verify_email) + const getdns_context *context, const char **verify_email) { if (!verify_email) return GETDNS_RETURN_INVALID_PARAMETER; @@ -5135,6 +5133,23 @@ getdns_context_get_trust_anchors_verify_email( return GETDNS_RETURN_GOOD; } +getdns_return_t +getdns_context_set_trust_anchors_backoff_time( + getdns_context *context, uint64_t backoff_time) +{ + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; + + context->trust_anchors_backoff_time = backoff_time; + if (context->trust_anchors_source == GETDNS_TASRC_FAILED) + context->trust_anchors_source = GETDNS_TASRC_NONE; + dispatch_updated( context + , GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME); + return GETDNS_RETURN_GOOD; +} + +CONTEXT_GETTER(trust_anchors_backoff_time , uint64_t) + getdns_return_t getdns_context_set_appdata_dir( getdns_context *context, const char *appdata_dir) @@ -5162,26 +5177,36 @@ getdns_context *_getdns_context_get_sys_ctxt( &context->sys_ctxt, 1, context->mf.mf_arg, context->mf.mf.ext.malloc, context->mf.mf.ext.realloc, context->mf.mf.ext.free))) - DEBUG_ANCHOR("Could not create system context: %s\n" + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Could not create system context: %s\n" , getdns_get_errorstr_by_id(r)); #ifndef USE_WINSOCK else if (*context->fchg_resolvconf.fn && (r = getdns_context_set_resolvconf( context->sys_ctxt, context->fchg_resolvconf.fn))) - DEBUG_ANCHOR("Could initialize system context with resolvconf " - "\"%s\": %s\n", context->fchg_resolvconf.fn - , getdns_get_errorstr_by_id(r)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Could not initialize system context with " + "resolvconf \"%s\": %s\n" + , context->fchg_resolvconf.fn + , getdns_get_errorstr_by_id(r)); #endif else if (*context->fchg_hosts.fn && (r = getdns_context_set_hosts( context->sys_ctxt, context->fchg_hosts.fn))) - DEBUG_ANCHOR("Could initialize system context with hosts " - "\"%s\": %s\n", context->fchg_resolvconf.fn - , getdns_get_errorstr_by_id(r)); + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Could not initialize system context with " + "hosts \"%s\": %s\n" + , context->fchg_hosts.fn + , getdns_get_errorstr_by_id(r)); else if ((r = getdns_context_set_eventloop( context->sys_ctxt, loop))) - DEBUG_ANCHOR("Could not configure %ssynchronous loop " + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Could not configure %ssynchronous loop " "with system context: %s\n" , ( loop == &context->sync_eventloop.loop ? "" : "a" ) @@ -5189,7 +5214,9 @@ getdns_context *_getdns_context_get_sys_ctxt( else if ((r = getdns_context_set_resolution_type( context->sys_ctxt, GETDNS_RESOLUTION_STUB))) - DEBUG_ANCHOR("Could not configure system context for " + _getdns_log(&context->log + , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR + , "Could not configure system context for " "stub resolver: %s\n" , getdns_get_errorstr_by_id(r)); else @@ -5213,15 +5240,7 @@ getdns_context_set_tls_ca_path(getdns_context *context, const char *tls_ca_path) return GETDNS_RETURN_GOOD; } -getdns_return_t -getdns_context_get_tls_ca_path(getdns_context *context, const char **tls_ca_path) -{ - if (!context || !tls_ca_path) - return GETDNS_RETURN_INVALID_PARAMETER; - - *tls_ca_path = context->tls_ca_path; - return GETDNS_RETURN_GOOD; -} +CONTEXT_GETTER(tls_ca_path , const char *) getdns_return_t getdns_context_set_tls_ca_file(getdns_context *context, const char *tls_ca_file) @@ -5236,15 +5255,7 @@ getdns_context_set_tls_ca_file(getdns_context *context, const char *tls_ca_file) return GETDNS_RETURN_GOOD; } -getdns_return_t -getdns_context_get_tls_ca_file(getdns_context *context, const char **tls_ca_file) -{ - if (!context || !tls_ca_file) - return GETDNS_RETURN_INVALID_PARAMETER; - - *tls_ca_file = context->tls_ca_file; - return GETDNS_RETURN_GOOD; -} +CONTEXT_GETTER(tls_ca_file , const char *) getdns_return_t getdns_context_set_tls_cipher_list( @@ -5264,14 +5275,43 @@ getdns_context_set_tls_cipher_list( getdns_return_t getdns_context_get_tls_cipher_list( - getdns_context *context, const char **tls_cipher_list) + const getdns_context *context, const char **tls_cipher_list) { if (!context || !tls_cipher_list) return GETDNS_RETURN_INVALID_PARAMETER; *tls_cipher_list = context->tls_cipher_list ? context->tls_cipher_list - : _getdns_tls_context_default_cipher_list; + : _getdns_tls_context_get_default_cipher_list(); + return GETDNS_RETURN_GOOD; +} + +getdns_return_t +getdns_context_set_tls_ciphersuites( + getdns_context *context, const char *tls_ciphersuites) +{ + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; + if (context->tls_ciphersuites) + GETDNS_FREE(context->mf, context->tls_ciphersuites); + context->tls_ciphersuites = tls_ciphersuites + ? _getdns_strdup(&context->mf, tls_ciphersuites) + : NULL; + + dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES); + return GETDNS_RETURN_GOOD; +} + +getdns_return_t +getdns_context_get_tls_ciphersuites( + const getdns_context *context, const char **tls_ciphersuites) +{ + if (!context || !tls_ciphersuites) + return GETDNS_RETURN_INVALID_PARAMETER; + + *tls_ciphersuites = context->tls_ciphersuites + ? context->tls_ciphersuites + : _getdns_tls_context_get_default_cipher_suites(); return GETDNS_RETURN_GOOD; } @@ -5296,14 +5336,32 @@ getdns_context_set_tls_curves_list( #endif } +CONTEXT_GETTER(tls_curves_list , const char *) + getdns_return_t -getdns_context_get_tls_curves_list( - getdns_context *context, const char **tls_curves_list) +getdns_context_set_tls_min_version( + getdns_context *context, getdns_tls_version_t tls_min_version) { - if (!context || !tls_curves_list) + if (!context) return GETDNS_RETURN_INVALID_PARAMETER; - *tls_curves_list = context->tls_curves_list; + context->tls_min_version = tls_min_version; + dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_MIN_VERSION); return GETDNS_RETURN_GOOD; } +CONTEXT_GETTER(tls_min_version , getdns_tls_version_t) + +getdns_return_t +getdns_context_set_tls_max_version( + getdns_context *context, getdns_tls_version_t tls_max_version) +{ + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; + context->tls_max_version = tls_max_version; + dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_MAX_VERSION); + return GETDNS_RETURN_GOOD; +} + +CONTEXT_GETTER(tls_max_version , getdns_tls_version_t) + /* context.c */ diff --git a/src/context.h b/src/context.h index 61e7fc5d..10031014 100644 --- a/src/context.h +++ b/src/context.h @@ -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: */ typedef struct sha256_pin { - char pin[SHA256_DIGEST_LENGTH]; + uint8_t pin[SHA256_DIGEST_LENGTH]; struct sha256_pin *next; } sha256_pin_t; @@ -207,9 +207,15 @@ typedef struct getdns_upstream { getdns_tls_hs_state_t tls_hs_state; getdns_auth_state_t tls_auth_state; unsigned tls_fallback_ok : 1; + + /* TLS settings */ char *tls_cipher_list; + char *tls_ciphersuites; 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]; sha256_pin_t *tls_pubkey_pinset; @@ -264,7 +270,7 @@ typedef struct getdns_upstreams { size_t count; size_t current_udp; size_t current_stateful; - uint16_t max_backoff_value; + uint16_t max_backoff_value; uint16_t tls_backoff_time; uint16_t tls_connection_retries; getdns_log_config log; @@ -342,6 +348,8 @@ struct getdns_context { char *trust_anchors_url; char *trust_anchors_verify_CA; char *trust_anchors_verify_email; + uint64_t trust_anchors_backoff_time; + uint64_t trust_anchors_backoff_expiry; _getdns_ksks root_ksk; @@ -351,7 +359,10 @@ struct getdns_context { char *tls_ca_path; char *tls_ca_file; char *tls_cipher_list; + char *tls_ciphersuites; char *tls_curves_list; + getdns_tls_version_t tls_min_version; + getdns_tls_version_t tls_max_version; getdns_upstreams *upstreams; 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_min; /* Derived minimum auth allowed*/ uint8_t round_robin_upstreams; - uint16_t max_backoff_value; + uint16_t max_backoff_value; uint16_t tls_backoff_time; uint16_t tls_connection_retries; @@ -434,6 +445,7 @@ struct getdns_context { getdns_dict *header; getdns_dict *add_opt_parameters; unsigned add_warning_for_bad_dns : 1; + unsigned dnssec : 1; unsigned dnssec_return_all_statuses : 1; unsigned dnssec_return_full_validation_chain : 1; unsigned dnssec_return_only_secure : 1; @@ -491,11 +503,38 @@ struct getdns_context { #endif /* HAVE_MDNS_SUPPORT */ }; /* getdns_context */ -void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system, - getdns_loglevel_type level, const char *fmt, ...); +static inline int _getdns_check_log(const getdns_log_config *log, + 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, - getdns_loglevel_type level, const char *fmt, ...); +static inline void _getdns_log(const getdns_log_config *log, + 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 **/ @@ -552,8 +591,9 @@ void _getdns_upstreams_dereference(getdns_upstreams *upstreams); void _getdns_upstream_shutdown(getdns_upstream *upstream); -FILE *_getdns_context_get_priv_fp(getdns_context *context, const char *fn); -uint8_t *_getdns_context_get_priv_file(getdns_context *context, +FILE *_getdns_context_get_priv_fp( + 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); int _getdns_context_write_priv_file(getdns_context *context, diff --git a/src/dict.c b/src/dict.c index 0c86cd0f..d2ce53a9 100644 --- a/src/dict.c +++ b/src/dict.c @@ -434,7 +434,7 @@ getdns_dict_create_with_memory_functions(void *(*malloc)(size_t), /*-------------------------- getdns_dict_create_with_context */ struct getdns_dict * -getdns_dict_create_with_context(struct getdns_context *context) +getdns_dict_create_with_context(const getdns_context *context) { if (context) return getdns_dict_create_with_extended_memory_functions( @@ -655,7 +655,8 @@ getdns_dict_set_bindata( /*---------------------------------------- getdns_dict_set_bindata */ 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_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, "resolution_type") == 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 */ 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_full_validation_chain") == 0 || strcmp(item->node.key, "dnssec_return_only_secure") == 0 || diff --git a/src/dnssec.c b/src/dnssec.c index 4e0f2af3..2be6096e 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -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_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 *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 * 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, getdns_network_req *netreq) { @@ -850,7 +850,7 @@ static void add_pkt2val_chain(struct mem_funcs *mf, * checked eventually. * 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, const uint8_t *qname, uint16_t qtype, uint16_t qclass, 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). */ #define VAL_RRSET_SPC_SZ 256 -static int _getdns_verify_rrsig(struct mem_funcs *mf, - _getdns_rrset *rrset, _getdns_rrsig_iter *rrsig, _getdns_rrtype_iter *key, const uint8_t **nc_name) +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) { int r; 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 * 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, - _getdns_rrtype_iter *dnskey, _getdns_rrset *rrset, const uint8_t **nc_name) +static int dnskey_signed_rrset(const struct mem_funcs *mf, time_t now, + uint32_t skew, _getdns_rrtype_iter *dnskey, _getdns_rrset *rrset, + const uint8_t **nc_name) { _getdns_rrsig_iter rrsig_spc, *rrsig; _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. */ -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) { _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; } -static int find_nsec_covering_name( - struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey, +static int find_nsec_covering_name(const struct mem_funcs *mf, + time_t now, uint32_t skew, _getdns_rrset *dnskey, _getdns_rrset *rrset, const uint8_t *name, int *opt_out); /* Returns whether a dnskey for keyset signed rrset. */ -static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew, - _getdns_rrset *keyset, _getdns_rrset *rrset) +static int a_key_signed_rrset(const struct mem_funcs *mf, time_t now, + uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset) { _getdns_rrtype_iter dnskey_spc, *dnskey; 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 * 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) { _getdns_rrtype_iter dnskey_spc, *dnskey; @@ -2112,8 +2114,8 @@ static int nsec3_covers_name( } } -static int find_nsec_covering_name( - struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey, +static int find_nsec_covering_name(const struct mem_funcs *mf, time_t now, + uint32_t skew, _getdns_rrset *dnskey, _getdns_rrset *rrset, const uint8_t *name, int *opt_out) { _getdns_rrset_iter i_spc, *i; @@ -2215,7 +2217,7 @@ static int find_nsec_covering_name( } 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, 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) */ 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 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. */ 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) { int s, keytag; @@ -2606,7 +2608,7 @@ static int chain_node_get_trusted_keys( *keys = ta; return GETDNS_DNSSEC_SECURE; } - /* ta is parent's ZSK */ + /* ta is parent's ZSK proving insecurity below this node? */ if ((keytag = key_proves_nonexistance( mf, now, skew, ta, &node->ds, &opt_out))) { node->ds_signer = keytag; @@ -2621,12 +2623,18 @@ static int chain_node_get_trusted_keys( * key_proves_nonexistance() will set opt_out also for * these conditions. */ - return opt_out ? GETDNS_DNSSEC_INSECURE - : GETDNS_DNSSEC_SECURE; - } - if ((keytag = a_key_signed_rrset_no_wc( + if (opt_out) + return GETDNS_DNSSEC_INSECURE; + + /* If this is not an insecurity proof, + * continue searching one label up. + */ + + /* ta is parent's ZSK authenticating DS? */ + } else if ((keytag = a_key_signed_rrset_no_wc( mf, now, skew, ta, &node->ds))) { node->ds_signer = keytag; + /* DS should authenticate the DNSKEY rrset now */ if ((keytag = ds_authenticates_keys( mf, now, skew, &node->ds, &node->dnskey))) { *keys = &node->dnskey; @@ -2635,6 +2643,7 @@ static int chain_node_get_trusted_keys( ? GETDNS_DNSSEC_INSECURE : GETDNS_DNSSEC_SECURE; } + /* DS without DNSKEY rrset == BOGUS */ return GETDNS_DNSSEC_BOGUS; } } 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 * 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) { _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 * anchors in tas in turn. The best outcome counts. */ -static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew, - chain_head *head, _getdns_rrset_iter *tas) +static int chain_head_validate(const struct mem_funcs *mf, time_t now, + uint32_t skew, chain_head *head, _getdns_rrset_iter *tas) { _getdns_rrset_iter *i; _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 * 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) { int s = GETDNS_DNSSEC_INDETERMINATE, t; @@ -3280,7 +3289,6 @@ static void check_chain_complete(chain_head *chain) } else if (_getdns_bogus(dnsreq)) { _getdns_rrsig_iter rrsig_spc; - DEBUG_ANCHOR("Request was bogus!\n"); if ((head = chain) && (node = _to_the_root(head->parent)) /* The root DNSKEY rrset */ @@ -3293,13 +3301,15 @@ static void check_chain_complete(chain_head *chain) && _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) { - uint64_t now = 0; + uint64_t now_ms = 0; dnsreq->waiting_for_ta = 1; _getdns_context_equip_with_anchor( - context, &now); + context, &now_ms); if (context->trust_anchors_source == GETDNS_TASRC_XML) { @@ -3307,9 +3317,19 @@ static void check_chain_complete(chain_head *chain) check_chain_complete(chain); return; } - _getdns_start_fetching_ta( - context, dnsreq->loop); - + if (context->trust_anchors_source == + 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 && context->trust_anchors_source == GETDNS_TASRC_FETCHING) { @@ -3464,7 +3484,7 @@ void _getdns_ta_notify_dnsreqs(getdns_context *context) getdns_network_req *netreq, **netreq_p; int r = GETDNS_RETURN_GOOD; - (void) _getdns_context_prepare_for_resolution(context); + (void) _getdns_context_prepare_for_resolution(context); *dnsreq_p = dnsreq->ta_notify; 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, 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_validate_dnssec2(getdns_list *records_to_validate, - getdns_list *support_records, - getdns_list *trust_anchors, +getdns_validate_dnssec2(const getdns_list *records_to_validate, + const getdns_list *support_records, + const getdns_list *trust_anchors, time_t now, uint32_t skew) { 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); int r = GETDNS_RETURN_MEMORY_ERROR; - struct mem_funcs *mf; + const struct mem_funcs *mf; size_t i; getdns_dict *reply; @@ -3766,9 +3786,9 @@ exit_free_support: getdns_return_t -getdns_validate_dnssec(getdns_list *records_to_validate, - getdns_list *support_records, - getdns_list *trust_anchors) +getdns_validate_dnssec(const getdns_list *records_to_validate, + const getdns_list *support_records, + const getdns_list *trust_anchors) { return getdns_validate_dnssec2(records_to_validate, support_records, trust_anchors, time(NULL), 0); diff --git a/src/general.c b/src/general.c index 3e50124d..cb923187 100644 --- a/src/general.c +++ b/src/general.c @@ -218,12 +218,14 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) && !dns_req->avoid_dnssec_roadblocks && (dns_req->dnssec_return_status || dns_req->dnssec_return_only_secure || + dns_req->dnssec || dns_req->dnssec_return_all_statuses )) #endif || ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING && (dns_req->dnssec_return_status || dns_req->dnssec_return_only_secure || + dns_req->dnssec || dns_req->dnssec_return_all_statuses) && _getdns_bogus(dns_req)) )) { @@ -241,7 +243,6 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) #if defined(REQ_DEBUG) && REQ_DEBUG debug_req("getting validation chain for ", *dns_req->netreqs); #endif - DEBUG_ANCHOR("Valchain lookup\n"); _getdns_get_validation_chain(dns_req); } else _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 || dns_req->dnssec_return_status || dns_req->dnssec_return_only_secure + || dns_req->dnssec || dns_req->dnssec_return_all_statuses || dns_req->dnssec_return_validation_chain) { #endif @@ -492,7 +494,7 @@ extformatcmp(const void *a, const void *b) /*---------------------------------------- validate_extensions */ 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 @@ -503,6 +505,7 @@ validate_extensions(struct getdns_dict * extensions) static getdns_extension_format extformats[] = { {"add_opt_parameters" , t_dict, 1}, {"add_warning_for_bad_dns" , t_int , 1}, + {"dnssec" , t_int , 1}, {"dnssec_return_all_statuses" , t_int , 1}, {"dnssec_return_full_validation_chain", t_int , 1}, {"dnssec_return_only_secure" , t_int , 1}, @@ -555,7 +558,7 @@ validate_extensions(struct getdns_dict * extensions) static getdns_return_t 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, 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); 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) - _getdns_start_fetching_ta(context, loop); + _getdns_start_fetching_ta(context, loop, &now_ms); else if (context->trust_anchors_source == GETDNS_TASRC_NONE) { _getdns_context_equip_with_anchor(context, &now_ms); 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_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, 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_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_dict *my_extensions = extensions; + getdns_dict *my_extensions = NULL; getdns_return_t r; uint32_t value; getdns_network_req *netreq = NULL; - if (!my_extensions) { + if (!extensions) { if (!(my_extensions=getdns_dict_create_with_context(context))) return GETDNS_RETURN_MEMORY_ERROR; } 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))) 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))) return r; 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); if (netreq && transaction_id) *transaction_id = netreq->owner->trans_id; - if (my_extensions != extensions) + if (my_extensions) getdns_dict_destroy(my_extensions); return r; @@ -752,7 +760,7 @@ _getdns_address_loop(getdns_context *context, getdns_eventloop *loop, getdns_return_t _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) { struct getdns_bindata *address_data; @@ -842,7 +850,7 @@ _getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop, getdns_return_t _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_return_t r; @@ -859,7 +867,7 @@ _getdns_service_loop(getdns_context *context, getdns_eventloop *loop, */ getdns_return_t 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, getdns_callback_t callbackfn) { @@ -881,7 +889,7 @@ getdns_general(getdns_context *context, */ getdns_return_t 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) { if (!context) return GETDNS_RETURN_INVALID_PARAMETER; @@ -896,7 +904,7 @@ getdns_address(getdns_context *context, */ getdns_return_t 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) { if (!context) return GETDNS_RETURN_INVALID_PARAMETER; @@ -910,7 +918,7 @@ getdns_hostname(getdns_context *context, */ getdns_return_t 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) { if (!context) return GETDNS_RETURN_INVALID_PARAMETER; diff --git a/src/general.h b/src/general.h index e0860c78..f99c1b46 100644 --- a/src/general.h +++ b/src/general.h @@ -63,25 +63,25 @@ int _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms); getdns_return_t _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, getdns_callback_t callbackfn, internal_cb_t internal_cb); getdns_return_t _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, getdns_callback_t callbackfn); getdns_return_t _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, getdns_callback_t callbackfn); getdns_return_t _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, getdns_callback_t callbackfn); diff --git a/src/getdns/getdns.h.in b/src/getdns/getdns.h.in index 23e59cf4..5e4873b5 100644 --- a/src/getdns/getdns.h.in +++ b/src/getdns/getdns.h.in @@ -416,6 +416,7 @@ typedef enum getdns_callback_type_t { #define GETDNS_RRTYPE_CDNSKEY 60 #define GETDNS_RRTYPE_OPENPGPKEY 61 #define GETDNS_RRTYPE_CSYNC 62 +#define GETDNS_RRTYPE_ZONEMD 63 #define GETDNS_RRTYPE_SPF 99 #define GETDNS_RRTYPE_UINFO 100 #define GETDNS_RRTYPE_UID 101 @@ -743,7 +744,7 @@ getdns_list *getdns_list_create(); * used to create and initialize the list. * @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 @@ -863,7 +864,7 @@ getdns_dict *getdns_dict_create(); * used to create and initialize the dict. * @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 @@ -1030,9 +1031,9 @@ getdns_return_t getdns_general(getdns_context *context, const char *name, uint16_t request_type, - getdns_dict *extensions, + const getdns_dict *extensions, 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 @@ -1048,9 +1049,9 @@ getdns_general(getdns_context *context, getdns_return_t getdns_address(getdns_context *context, const char *name, - getdns_dict *extensions, + const getdns_dict *extensions, 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 @@ -1065,10 +1066,10 @@ getdns_address(getdns_context *context, */ getdns_return_t getdns_hostname(getdns_context *context, - getdns_dict *address, - getdns_dict *extensions, + 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); /** * retrieve a service assigned to a DNS name @@ -1084,9 +1085,9 @@ getdns_hostname(getdns_context *context, getdns_return_t getdns_service(getdns_context *context, const char *name, - getdns_dict *extensions, + const getdns_dict *extensions, 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, const char *name, uint16_t request_type, - getdns_dict *extensions, + const getdns_dict *extensions, getdns_dict **response); /** @@ -1216,7 +1217,7 @@ getdns_general_sync(getdns_context *context, getdns_return_t getdns_address_sync(getdns_context *context, const char *name, - getdns_dict *extensions, + const getdns_dict *extensions, getdns_dict **response); /** @@ -1230,8 +1231,8 @@ getdns_address_sync(getdns_context *context, */ getdns_return_t getdns_hostname_sync(getdns_context *context, - getdns_dict *address, - getdns_dict *extensions, + const getdns_dict *address, + const getdns_dict *extensions, getdns_dict **response); /** @@ -1246,7 +1247,7 @@ getdns_hostname_sync(getdns_context *context, getdns_return_t getdns_service_sync(getdns_context *context, const char *name, - getdns_dict *extensions, + const getdns_dict *extensions, getdns_dict **response); /** @} @@ -1341,9 +1342,8 @@ char *getdns_convert_alabel_to_ulabel(const char *alabel); * depending on the validation status. */ getdns_return_t -getdns_validate_dnssec(getdns_list *to_validate, - getdns_list *support_records, - getdns_list *trust_anchors); +getdns_validate_dnssec(const getdns_list *to_validate, + const getdns_list *support_records, const getdns_list *trust_anchors); /** * 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_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 @@ -1812,9 +1812,11 @@ getdns_context_set_extended_memory_functions(getdns_context *context, * GETDNS_RESOLUTION_STUB. * - all_context (a dict) with names for all the other settings in * context. + * The application is responsible for cleaning up the returned dictionary + * object with getdns_dict_destroy. */ getdns_dict* -getdns_context_get_api_information(getdns_context* context); +getdns_context_get_api_information(const getdns_context *context); /** @} */ diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 34282643..a11b52ea 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -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_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_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. */ getdns_return_t -getdns_context_set_eventloop(getdns_context* context, +getdns_context_set_eventloop(getdns_context *context, 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 */ getdns_return_t -getdns_context_get_eventloop(getdns_context* context, +getdns_context_get_eventloop(const getdns_context *context, getdns_eventloop **eventloop); /** @@ -548,8 +557,18 @@ typedef enum getdns_loglevel_type { #define GETDNS_LOG_INFO_TEXT "Informational 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_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, getdns_loglevel_type, const char *, va_list ap); @@ -694,6 +713,22 @@ getdns_return_t getdns_context_set_trust_anchors_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 * with the values from the given resolv.conf file. @@ -755,6 +790,18 @@ getdns_return_t getdns_context_set_tls_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. * @see getdns_context_get_tls_curves_list @@ -768,6 +815,80 @@ getdns_return_t getdns_context_set_tls_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. * @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. */ getdns_return_t -getdns_context_get_resolution_type(getdns_context *context, - getdns_resolution_t* value); +getdns_context_get_resolution_type(const getdns_context *context, + getdns_resolution_t *value); /** * 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. */ getdns_return_t -getdns_context_get_namespaces(getdns_context *context, - size_t* namespace_count, getdns_namespace_t **namespaces); +getdns_context_get_namespaces(const getdns_context *context, + size_t *namespace_count, getdns_namespace_t **namespaces); /** * 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. */ getdns_return_t -getdns_context_get_dns_transport(getdns_context *context, - getdns_transport_t* value); +getdns_context_get_dns_transport(const getdns_context *context, + getdns_transport_t *value); /** * 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. */ getdns_return_t -getdns_context_get_dns_transport_list(getdns_context *context, - size_t* transport_count, getdns_transport_list_t **transports); +getdns_context_get_dns_transport_list(const getdns_context *context, + size_t *transport_count, getdns_transport_list_t **transports); /** * 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. */ getdns_return_t -getdns_context_get_limit_outstanding_queries(getdns_context *context, - uint16_t* limit); +getdns_context_get_limit_outstanding_queries(const getdns_context *context, + uint16_t *limit); /** * 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. */ 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 @@ -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. */ 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. @@ -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. */ getdns_return_t -getdns_context_get_follow_redirects(getdns_context *context, - getdns_redirects_t* value); +getdns_context_get_follow_redirects(const getdns_context *context, + getdns_redirects_t *value); /** * 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 */ 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); /** @@ -912,8 +1034,8 @@ getdns_context_get_dns_root_servers(getdns_context *context, * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. */ getdns_return_t -getdns_context_get_append_name(getdns_context *context, - getdns_append_name_t* value); +getdns_context_get_append_name(const getdns_context *context, + getdns_append_name_t *value); /** * 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 */ 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. @@ -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 */ 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); /** @@ -958,8 +1080,8 @@ getdns_context_get_dnssec_trust_anchors(getdns_context *context, * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. */ getdns_return_t -getdns_context_get_dnssec_allowed_skew(getdns_context *context, - uint32_t* value); +getdns_context_get_dnssec_allowed_skew(const getdns_context *context, + uint32_t *value); /** * 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 */ 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); /** @@ -990,8 +1112,8 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context, * @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL. */ getdns_return_t -getdns_context_get_edns_maximum_udp_payload_size(getdns_context *context, - uint16_t* value); +getdns_context_get_edns_maximum_udp_payload_size(const getdns_context *context, + uint16_t *value); /** * 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. */ getdns_return_t -getdns_context_get_edns_extended_rcode(getdns_context *context, - uint8_t* value); +getdns_context_get_edns_extended_rcode(const getdns_context *context, + uint8_t *value); /** * 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. */ 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 @@ -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. */ 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 @@ -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. */ 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. @@ -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. */ 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. @@ -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. */ getdns_return_t -getdns_context_get_tls_authentication(getdns_context *context, - getdns_tls_authentication_t* value); +getdns_context_get_tls_authentication(const getdns_context *context, + getdns_tls_authentication_t *value); /** * 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. */ getdns_return_t -getdns_context_get_round_robin_upstreams(getdns_context *context, - uint8_t* value); +getdns_context_get_round_robin_upstreams(const getdns_context *context, + uint8_t *value); /** * 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. */ getdns_return_t -getdns_context_get_tls_backoff_time(getdns_context *context, - uint16_t* value); +getdns_context_get_tls_backoff_time(const getdns_context *context, + uint16_t *value); /** * 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. */ getdns_return_t -getdns_context_get_tls_connection_retries(getdns_context *context, - uint16_t* value); +getdns_context_get_tls_connection_retries(const getdns_context *context, + uint16_t *value); /** * 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. */ 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 *)); @@ -1184,7 +1309,7 @@ getdns_context_get_update_callback(getdns_context *context, void **userarg, */ getdns_return_t 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 @@ -1203,7 +1328,7 @@ getdns_context_get_trust_anchors_url( */ getdns_return_t 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 @@ -1220,7 +1345,21 @@ getdns_context_get_trust_anchors_verify_CA( */ getdns_return_t 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 @@ -1233,7 +1372,8 @@ getdns_context_get_trust_anchors_verify_email( * @return GETDNS_RETURN_GOOD when successful and error code otherwise. */ 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 @@ -1246,7 +1386,8 @@ getdns_context_get_resolvconf(getdns_context *context, const char **resolvconf); * @return GETDNS_RETURN_GOOD when successful and error code otherwise. */ 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 @@ -1260,7 +1401,8 @@ getdns_context_get_hosts(getdns_context *context, const char **hosts); * @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL. */ 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. @@ -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. */ 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. @@ -1285,7 +1428,20 @@ getdns_context_get_tls_ca_file(getdns_context *context, const char **tls_ca_file */ getdns_return_t 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. @@ -1300,7 +1456,7 @@ getdns_context_get_tls_cipher_list( */ getdns_return_t 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 */ 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 @@ -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 */ 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. */ getdns_return_t -getdns_validate_dnssec2(getdns_list *to_validate, - getdns_list *support_records, - getdns_list *trust_anchors, +getdns_validate_dnssec2(const getdns_list *to_validate, + const getdns_list *support_records, + const getdns_list *trust_anchors, 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 * @return a dict created from ctx, or NULL if the string did not match. */ -getdns_dict* getdns_pubkey_pin_create_from_string( - getdns_context* context, - const char* str); +getdns_dict *getdns_pubkey_pin_create_from_string( + const getdns_context *context, + 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. */ getdns_return_t getdns_pubkey_pinset_sanity_check( - const getdns_list* pinset, - getdns_list* errorlist); + const getdns_list *pinset, + getdns_list *errorlist); /** @} */ @@ -2155,7 +2313,7 @@ getdns_context_set_listen_addresses( */ getdns_return_t 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 * 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 @@ -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 * future versions of getdns. */ -uint32_t getdns_context_get_num_pending_requests(getdns_context* context, - struct timeval* next_timeout); +uint32_t getdns_context_get_num_pending_requests(const getdns_context *context, + struct timeval *next_timeout); /** * 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_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); /** @} diff --git a/src/gldns/compare.sh b/src/gldns/compare.sh index 415c6bcc..86207bb9 100755 --- a/src/gldns/compare.sh +++ b/src/gldns/compare.sh @@ -3,7 +3,7 @@ # Meant to be run from this directory rm -fr 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.c sbuffer.c for f in sldns/*.[ch] diff --git a/src/gldns/gbuffer.h b/src/gldns/gbuffer.h index 7aa5a1b8..e04aa23a 100644 --- a/src/gldns/gbuffer.h +++ b/src/gldns/gbuffer.h @@ -130,7 +130,7 @@ struct gldns_buffer /** If the buffer is fixed it cannot be resized */ 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 * with the amount that would have been written in consecutive * 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->_position <= buffer->_limit || buffer->_vfixed); 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 diff --git a/src/gldns/import.sh b/src/gldns/import.sh index 88fcfff4..b9f3cfdd 100755 --- a/src/gldns/import.sh +++ b/src/gldns/import.sh @@ -16,8 +16,8 @@ then mv sbuffer.h gbuffer.h mv sbuffer.c gbuffer.c else - svn co http://unbound.net/svn/trunk/sldns/ - for f in sldns/*.[ch] + svn co https://nlnetlabs.nl/svn/unbound/trunk/sldns/ + for f in ldns/*.[ch] do sed -e 's/sldns_/gldns_/g' \ -e 's/LDNS_/GLDNS_/g' \ diff --git a/src/gldns/parseutil.h b/src/gldns/parseutil.h index a044c4de..1546e8be 100644 --- a/src/gldns/parseutil.h +++ b/src/gldns/parseutil.h @@ -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 * with respect to now using serial arithmetics (rfc1982). * 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. * * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) diff --git a/src/gldns/rrdef.c b/src/gldns/rrdef.c index 91739232..9f27a5a1 100644 --- a/src/gldns/rrdef.c +++ b/src/gldns/rrdef.c @@ -150,6 +150,9 @@ static const gldns_rdf_type type_openpgpkey_wireformat[] = { static const gldns_rdf_type type_csync_wireformat[] = { 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 */ static const gldns_rdf_type type_nsec3_wireformat[] = { /* 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 }, /* 52 */ {GLDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, - /*53 */ -#ifdef DRAFT_RRTYPES + /* 53 */ {GLDNS_RR_TYPE_SMIMEA, "SMIMEA", 4, 4, type_tlsa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, -#else -{GLDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, -#endif + /* 54 */ {GLDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, /* 55 * 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 }, /* 62 */ {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, "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 }, diff --git a/src/gldns/rrdef.h b/src/gldns/rrdef.h index f7aaf866..a11984b3 100644 --- a/src/gldns/rrdef.h +++ b/src/gldns/rrdef.h @@ -182,9 +182,7 @@ enum gldns_enum_rr_type GLDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */ GLDNS_RR_TYPE_NSEC3PARAMS = 51, GLDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */ - GLDNS_RR_TYPE_SMIMEA = 53, /* draft-ietf-dane-smime, TLSA-like but may - be extended */ - + GLDNS_RR_TYPE_SMIMEA = 53, /* RFC 8162 */ GLDNS_RR_TYPE_HIP = 55, /* RFC 5205 */ /** draft-reid-dnsext-zs */ @@ -197,6 +195,7 @@ enum gldns_enum_rr_type GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */ GLDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ + GLDNS_RR_TYPE_ZONEMD = 63, /* draft-wessels-dns-zone-digest */ GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ diff --git a/src/gnutls/tls-internal.h b/src/gnutls/tls-internal.h index 1fafe550..4f7f24f8 100644 --- a/src/gnutls/tls-internal.h +++ b/src/gnutls/tls-internal.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, NLnet Labs + * Copyright (c) 2018-2019, NLnet Labs * All rights reserved. * * 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_CONN_CURVES_LIST 0 +typedef struct getdns_log_config getdns_log_config; typedef struct _getdns_tls_context { struct mem_funcs* mfs; char* cipher_list; + char* cipher_suites; 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_path; + const getdns_log_config* log; } _getdns_tls_context; typedef struct _getdns_tls_connection { @@ -70,10 +74,14 @@ typedef struct _getdns_tls_connection { _getdns_tls_context* ctx; struct mem_funcs* mfs; char* cipher_list; + char* cipher_suites; char* curve_list; + gnutls_protocol_t min_tls; + gnutls_protocol_t max_tls; dane_query_t dane_query; dane_state_t dane_state; char* tlsa; + const getdns_log_config* log; } _getdns_tls_connection; typedef struct _getdns_tls_session { diff --git a/src/gnutls/tls.c b/src/gnutls/tls.c index a9e96241..304fbda9 100644 --- a/src/gnutls/tls.c +++ b/src/gnutls/tls.c @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, NLnet Labs + * Copyright (c) 2018-2019, NLnet Labs * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,17 +43,27 @@ /* * 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. */ -char const * const _getdns_tls_context_default_cipher_list = - "NONE:+AES-256-GCM:+AES-128-GCM:+CHACHA20-POLY1305:" - "+ECDHE-RSA:+ECDHE-ECDSA:+SIGN-RSA-SHA384:+AEAD:" - "+COMP-ALL:+VERS-TLS-ALL:+CURVE-ALL"; +static char const * const _getdns_tls_context_default_cipher_list = + "+ECDHE-RSA:+ECDHE-ECDSA:+AEAD"; + +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 = "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) { char* res; @@ -92,6 +102,13 @@ static int set_connection_ciphers(_getdns_tls_connection* conn) char* pri = NULL; 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) pri = getdns_priappend(conn->mfs, pri, conn->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); else if (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); + 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 res = gnutls_set_default_priority(conn->tls); GETDNS_FREE(*conn->mfs, pri); + return res; } @@ -142,6 +186,17 @@ static getdns_return_t get_gnu_mac_algorithm(int algorithm, gnutls_mac_algorithm 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) { _getdns_tls_x509* res; @@ -158,7 +213,7 @@ void _getdns_tls_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; @@ -166,10 +221,11 @@ _getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs) return NULL; res->mfs = mfs; - res->min_proto_1_2 = false; - res->cipher_list = res->curve_list = NULL; + res->cipher_list = res->cipher_suites = res->curve_list = NULL; + res->min_tls = res->max_tls = 0; res->ca_trust_file = NULL; res->ca_trust_path = NULL; + res->log = log; 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_file); GETDNS_FREE(*mfs, ctx->curve_list); + GETDNS_FREE(*mfs, ctx->cipher_suites); GETDNS_FREE(*mfs, ctx->cipher_list); GETDNS_FREE(*mfs, ctx); return GETDNS_RETURN_GOOD; @@ -192,12 +249,18 @@ void _getdns_tls_context_pinset_init(_getdns_tls_context* 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) return GETDNS_RETURN_INVALID_PARAMETER; - ctx->min_proto_1_2 = true; - return GETDNS_RETURN_NOT_IMPLEMENTED; + ctx->min_tls = _getdns_tls_version2gnutls_version(min); + 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) @@ -213,6 +276,24 @@ getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, co 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) { if (!ctx) @@ -235,7 +316,7 @@ getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char* 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; @@ -250,11 +331,12 @@ _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdn res->mfs = mfs; res->cred = NULL; res->tls = NULL; - res->cipher_list = NULL; - res->curve_list = NULL; + res->cipher_list = res->cipher_suites = res->curve_list = NULL; + res->min_tls = res->max_tls = 0; res->dane_state = NULL; res->dane_query = NULL; res->tlsa = NULL; + res->log = log; if (gnutls_certificate_allocate_credentials(&res->cred) != GNUTLS_E_SUCCESS) 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) goto failed; - if (set_connection_ciphers(res) != GNUTLS_E_SUCCESS) + if (set_connection_ciphers(res) != GNUTLS_E_SUCCESS) { + goto failed; + } if (gnutls_credentials_set(res->tls, GNUTLS_CRD_CERTIFICATE, res->cred) != GNUTLS_E_SUCCESS) goto failed; 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); GETDNS_FREE(*mfs, conn->tlsa); GETDNS_FREE(*mfs, conn->curve_list); + GETDNS_FREE(*mfs, conn->cipher_suites); GETDNS_FREE(*mfs, conn->cipher_list); GETDNS_FREE(*mfs, conn); return GETDNS_RETURN_GOOD; @@ -321,6 +406,15 @@ getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn) 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) { 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; } +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) { 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); 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; } else diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols index ccbff42a..b8b6cffe 100644 --- a/src/libgetdns.symbols +++ b/src/libgetdns.symbols @@ -36,9 +36,13 @@ getdns_context_get_tls_backoff_time getdns_context_get_tls_ca_file getdns_context_get_tls_ca_path getdns_context_get_tls_cipher_list +getdns_context_get_tls_ciphersuites getdns_context_get_tls_connection_retries 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_trust_anchors_backoff_time getdns_context_get_trust_anchors_url getdns_context_get_trust_anchors_verify_CA 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_path getdns_context_set_tls_cipher_list +getdns_context_set_tls_ciphersuites getdns_context_set_tls_connection_retries 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_trust_anchors_backoff_time getdns_context_set_trust_anchors_url getdns_context_set_trust_anchors_verify_CA getdns_context_set_trust_anchors_verify_email diff --git a/src/list.c b/src/list.c index c7bd476b..555a847f 100644 --- a/src/list.c +++ b/src/list.c @@ -418,7 +418,7 @@ getdns_list_create_with_memory_functions(void *(*malloc)(size_t), /*-------------------------- getdns_list_create_with_context */ struct getdns_list * -getdns_list_create_with_context(struct getdns_context *context) +getdns_list_create_with_context(const getdns_context *context) { if (context) return getdns_list_create_with_extended_memory_functions( diff --git a/src/mk-const-info.c.sh b/src/mk-const-info.c.sh index 3a47c103..26c2f626 100755 --- a/src/mk-const-info.c.sh +++ b/src/mk-const-info.c.sh @@ -14,7 +14,7 @@ cat > const-info.c << END_OF_HEAD static struct const_info consts_info[] = { { -1, NULL, "/* */" }, 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 }; @@ -49,7 +49,7 @@ getdns_get_errorstr_by_id(uint16_t err) static struct const_name_info consts_name_info[] = { 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 }; diff --git a/src/mk-symfiles.sh b/src/mk-symfiles.sh index 099181e6..26424e27 100755 --- a/src/mk-symfiles.sh +++ b/src/mk-symfiles.sh @@ -3,7 +3,7 @@ write_symbols() { OUTPUT=$1 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 } diff --git a/src/openssl/keyraw-internal.c b/src/openssl/keyraw-internal.c index b8077049..6dab968a 100644 --- a/src/openssl/keyraw-internal.c +++ b/src/openssl/keyraw-internal.c @@ -20,6 +20,9 @@ #include #include #include +#ifdef HAVE_OPENSSL_CONF_H +# include +#endif #ifdef HAVE_OPENSSL_ENGINE_H # include #endif @@ -38,6 +41,16 @@ #ifdef USE_GOST /** 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; int @@ -97,6 +110,7 @@ void gldns_key_EVP_unload_gost(void) gldns_gost_engine = NULL; } } +#endif /* ifndef OPENSSL_NO_ENGINE */ #endif /* USE_GOST */ DSA * diff --git a/src/openssl/pubkey-pinning-internal.c b/src/openssl/pubkey-pinning-internal.c index 5ef02db2..fd8ad6fe 100644 --- a/src/openssl/pubkey-pinning-internal.c +++ b/src/openssl/pubkey-pinning-internal.c @@ -58,7 +58,7 @@ #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 #endif @@ -106,7 +106,7 @@ _get_ssl_getdns_upstream_idx(X509_STORE *store) { static volatile int idx = -1; if (idx < 0) { -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); #else X509_STORE_lock(store); @@ -114,7 +114,7 @@ _get_ssl_getdns_upstream_idx(X509_STORE *store) if (idx < 0) idx = SSL_get_ex_new_index(0, "associated getdns upstream", NULL,NULL,NULL); -#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +#if OPENSSL_VERSION_NUMBER < 0x10100000 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); #else X509_STORE_unlock(store); @@ -123,27 +123,6 @@ _get_ssl_getdns_upstream_idx(X509_STORE *store) 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_associate_upstream_with_connection(_getdns_tls_connection *conn, getdns_upstream *upstream) @@ -151,7 +130,7 @@ _getdns_associate_upstream_with_connection(_getdns_tls_connection *conn, if (!conn || !conn->ssl) 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(); #else 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))*/ } -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 */ diff --git a/src/openssl/pubkey-pinning-internal.h b/src/openssl/pubkey-pinning-internal.h index 3313dffd..fc2511d0 100644 --- a/src/openssl/pubkey-pinning-internal.h +++ b/src/openssl/pubkey-pinning-internal.h @@ -36,16 +36,7 @@ #include -/* internal functions for associating X.509 verification processes in - * 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); +getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size); #endif /* pubkey-pinning-internal.h */ diff --git a/src/openssl/tls-internal.h b/src/openssl/tls-internal.h index 06f95bda..e640150d 100644 --- a/src/openssl/tls-internal.h +++ b/src/openssl/tls-internal.h @@ -55,13 +55,16 @@ #define GETDNS_TLS_MAX_DIGEST_LENGTH (EVP_MAX_MD_SIZE) typedef struct sha256_pin sha256_pin_t; +typedef struct getdns_log_config getdns_log_config; typedef struct _getdns_tls_context { SSL_CTX* ssl; + const getdns_log_config* log; } _getdns_tls_context; typedef struct _getdns_tls_connection { SSL* ssl; + const getdns_log_config* log; #if defined(USE_DANESSL) const char* auth_name; sha256_pin_t* pinset; diff --git a/src/openssl/tls.c b/src/openssl/tls.c index ba1648f1..33e37a4c 100644 --- a/src/openssl/tls.c +++ b/src/openssl/tls.c @@ -46,6 +46,7 @@ #include "debug.h" #include "context.h" +#include "const-info.h" #ifdef USE_DANESSL # include "ssl_dane/danessl.h" @@ -62,33 +63,20 @@ #endif /* Cipher suites recommended in RFC7525. */ -char const * const _getdns_tls_context_default_cipher_list = - "TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:" - "TLS13-CHACHA20-POLY1305-SHA256:EECDH+AESGCM:EECDH+CHACHA20"; +static char const * const _getdns_tls_context_default_cipher_list = +#ifndef HAVE_SSL_CTX_SET_CIPHERSUITES + "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 = "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) { # if defined(STUB_DEBUG) && STUB_DEBUG @@ -156,23 +144,63 @@ static const EVP_MD* get_digester(int algorithm) 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 /* For windows, the CA trust store is not read by openssl. Add code to open the trust store using wincrypt API and add the root certs into openssl trust store */ static int -add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) +add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx, const getdns_log_config* log) { HCERTSTORE hSystemStore; PCCERT_CONTEXT pTargetCert = NULL; - DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, - "Adding Windows certificates from system root store to CA store"); + _getdns_log(log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_DEBUG + , "%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 TODO: dynamically update CA trust changes as they are available */ - if (!tls_ctx) - return 0; + assert(tls_ctx); /* 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, 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; } 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; + } /* failure if the CA store is empty or the call fails */ if ((pTargetCert = CertEnumCertificatesInStore( - hSystemStore, pTargetCert)) == 0) { - DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, - "CA certificate store for Windows is empty."); - return 0; + hSystemStore, pTargetCert)) == 0) { + _getdns_log(log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_NOTICE + , "%s: %s\n", STUB_DEBUG_SETUP_TLS + , "CA certificate store for Windows is empty."); + return 0; } /* iterate over the windows cert store and add to openssl store */ do @@ -207,9 +243,13 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) pTargetCert->cbCertEncoded); if (!cert1) { /* return error if a cert fails */ - DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, - "Unable to parse certificate in memory", - ERR_get_error(), ERR_error_string(ERR_get_error(), NULL)); + _getdns_log(log + , GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR, + , "%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; } else { @@ -221,9 +261,16 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) * certificate is already in the store. */ if(ERR_GET_LIB(error) != ERR_LIB_X509 || ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { - DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, - "Error adding certificate", ERR_get_error(), - ERR_error_string(ERR_get_error(), NULL)); + _getdns_log(log + , GETDNS_LOG_SYS_STUB + , 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); return 0; } @@ -238,12 +285,18 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) CertFreeCertificateContext(pTargetCert); if (hSystemStore) { - if (!CertCloseStore( - hSystemStore, 0)) + if (!CertCloseStore(hSystemStore, 0)) { + _getdns_log(log + , GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR + , "%s: %s\n", STUB_DEBUG_SETUP_TLS + , "Could not CertCloseStore()"); return 0; + } } - DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__, - "Completed adding Windows certificates to CA store successfully"); + _getdns_log(log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_INFO + , "%s: %s\n", STUB_DEBUG_SETUP_TLS + , "Completed adding Windows certificates to CA store successfully") + ; return 1; } #endif @@ -265,13 +318,15 @@ void _getdns_tls_init() #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; if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_context))) return NULL; + res->log = log; + /* Create client context, use TLS v1.2 only for now */ # ifdef HAVE_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()); # endif 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); 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) { int osr; - (void) osr; #if defined(HAVE_SSL_CTX_DANE_ENABLE) 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) osr = DANESSL_CTX_init(ctx->ssl); - DEBUG_STUB("%s %-35s: DEBUG: DANESSL_CTX_init() -> %d\n", - STUB_DEBUG_SETUP_TLS, __FUNC__, osr); #else #error Must have either DANE SSL or OpenSSL v1.1. #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) 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; + } + 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; #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; + 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; #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) { if (!ctx || !ctx->ssl) @@ -334,8 +453,60 @@ getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, co if (!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_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; } @@ -345,10 +516,29 @@ getdns_return_t _getdns_tls_context_set_curves_list(_getdns_tls_context* ctx, co return GETDNS_RETURN_INVALID_PARAMETER; #if HAVE_TLS_CTX_CURVES_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; + } #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 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) return GETDNS_RETURN_INVALID_PARAMETER; - if ((file || path) && - SSL_CTX_load_verify_locations(ctx->ssl, file, path)) + if (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 */ + } #ifndef USE_WINSOCK else if (SSL_CTX_set_default_verify_paths(ctx->ssl)) 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 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; #endif /* USE_WINSOCK */ 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; @@ -392,6 +615,8 @@ _getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdn return NULL; } + res->log = log; + /* Connection is a client. */ 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; #ifdef USE_DANESSL -# if defined(STUB_DEBUG) && STUB_DEBUG - _stub_debug_print_openssl_errors(); -# endif DANESSL_cleanup(conn->ssl); #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) { if (!conn || !conn->ssl) @@ -436,8 +716,53 @@ getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* c if (!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_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; } @@ -447,10 +772,29 @@ getdns_return_t _getdns_tls_connection_set_curves_list(_getdns_tls_connection* c return GETDNS_RETURN_INVALID_PARAMETER; #if HAVE_TLS_CONN_CURVES_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; + } #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 return GETDNS_RETURN_GOOD; } diff --git a/src/openssl/val_secalgo.c b/src/openssl/val_secalgo.c index 03fc96f2..c7158d82 100644 --- a/src/openssl/val_secalgo.c +++ b/src/openssl/val_secalgo.c @@ -77,6 +77,23 @@ int fake_dsa = 0; /** fake SHA1 support for unit tests */ 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 */ size_t nsec3_hash_algo_size_supported(int id) @@ -96,7 +113,13 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, { switch(algo) { 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); +#endif return 1; default: return 0; @@ -106,7 +129,13 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, void 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); +#endif } /** @@ -165,12 +194,24 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len, switch(algo) { #if defined(HAVE_EVP_SHA1) && defined(USE_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); +#endif return 1; #endif #ifdef HAVE_EVP_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); +#endif return 1; #endif #ifdef USE_GOST @@ -181,7 +222,13 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len, #endif #ifdef USE_ECDSA 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); +#endif return 1; #endif 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 /** * Setup DSA key digest in DER encoding ... diff --git a/src/pubkey-pinning.c b/src/pubkey-pinning.c index 983888fa..543d892e 100644 --- a/src/pubkey-pinning.c +++ b/src/pubkey-pinning.c @@ -51,6 +51,7 @@ #include #include "context.h" #include "util-internal.h" +#include "gldns/parseutil.h" #include "pubkey-pinning.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 no longer needed. */ -getdns_dict* getdns_pubkey_pin_create_from_string( - getdns_context* context, - const char* str) +getdns_dict *getdns_pubkey_pin_create_from_string( + const getdns_context *context, const char *str) { size_t i; uint8_t buf[SHA256_DIGEST_LENGTH]; 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 */ 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_get_pubkey_pinset_list(getdns_context *ctx, +_getdns_get_pubkey_pinset_list(const getdns_context *ctx, const sha256_pin_t *pinset_in, getdns_list **pinset_list) { @@ -289,5 +289,3 @@ _getdns_get_pubkey_pinset_list(getdns_context *ctx, getdns_list_destroy(out); return r; } - -/* pubkey-pinning.c */ diff --git a/src/pubkey-pinning.h b/src/pubkey-pinning.h index b94f58af..c60a7eca 100644 --- a/src/pubkey-pinning.h +++ b/src/pubkey-pinning.h @@ -34,17 +34,11 @@ #ifndef 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" -/** - ** 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 */ getdns_return_t _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 */ 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, getdns_list **pinset_list); @@ -62,7 +56,5 @@ getdns_return_t _getdns_associate_upstream_with_connection(_getdns_tls_connection *conn, getdns_upstream *upstream); -getdns_dict* getdns_pubkey_pin_create_from_string(getdns_context* context, const char* str); - #endif /* pubkey-pinning.h */ diff --git a/src/request-internal.c b/src/request-internal.c index c0f347af..eedea35c 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -93,7 +93,7 @@ getdns_dict *no_dnssec_checking_disabled_opportunistic = &no_dnssec_checking_disabled_opportunistic_spc; 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; 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, uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit, 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; getdns_dict *option; @@ -475,6 +475,9 @@ _getdns_network_req_add_tsig(getdns_network_req *req) void _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_rdf_iter rdf_spc, *rdf; 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 + 10, gldns_read_uint16(req->response + 10) + 1); +#endif } void @@ -649,9 +653,12 @@ static const uint8_t no_suffixes[] = { 1, 0 }; /* create a new dns req to be submitted */ getdns_dns_req * _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) { + int dnssec = is_extension_set( + extensions, "dnssec", + context->dnssec); int dnssec_return_status = is_extension_set( extensions, "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", context->dnssec_roadblock_avoidance); #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_validation_chain || dnssec_return_full_validation_chain @@ -726,6 +733,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, int opportunistic = 0; if (extensions == no_dnssec_checking_disabled_opportunistic) { + dnssec = 0; dnssec_return_status = 0; dnssec_return_only_secure = 0; dnssec_return_all_statuses = 0; @@ -906,6 +914,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->context = context; result->loop = loop; result->trans_id = (uint64_t) (intptr_t) result; + result->dnssec = dnssec; result->dnssec_return_status = dnssec_return_status; result->dnssec_return_only_secure = dnssec_return_only_secure; result->dnssec_return_all_statuses = dnssec_return_all_statuses; diff --git a/src/rr-dict.c b/src/rr-dict.c index ab0c2b82..79fb7bcc 100644 --- a/src/rr-dict.c +++ b/src/rr-dict.c @@ -613,6 +613,11 @@ static _getdns_rdata_def csync_rdata[] = { { "serial" , GETDNS_RDF_I4 , NULL }, { "flags" , GETDNS_RDF_I2 , 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[] = { { "text" , GETDNS_RDF_S_M , NULL }}; static _getdns_rdata_def nid_rdata[] = { @@ -723,9 +728,9 @@ static _getdns_rr_def _getdns_rr_defs[] = { { "TALINK", talink_rdata, ALEN( talink_rdata) }, { "CDS", ds_rdata, ALEN( ds_rdata) }, { "CDNSKEY", dnskey_rdata, ALEN( dnskey_rdata) }, - { "OPENPGPKEY", openpgpkey_rdata, ALEN(openpgpkey_rdata) }, /* 61 - */ - { "CSYNC", csync_rdata, ALEN( csync_rdata) }, /* - 62 */ - { NULL, NULL, 0 }, + { "OPENPGPKEY", openpgpkey_rdata, ALEN(openpgpkey_rdata) }, + { "CSYNC", csync_rdata, ALEN( csync_rdata) }, + { "ZONEMD", zonemd_rdata, ALEN( zonemd_rdata) }, /* - 63 */ { NULL, NULL, 0 }, { NULL, NULL, 0 }, { NULL, NULL, 0 }, diff --git a/src/server.c b/src/server.c index a6d4008e..3736a6f2 100644 --- a/src/server.c +++ b/src/server.c @@ -287,8 +287,8 @@ _getdns_cancel_reply(getdns_context *context, connection *conn) } getdns_return_t -getdns_reply( - getdns_context *context, getdns_dict *reply, getdns_transaction_t request_id) +getdns_reply(getdns_context *context, + const getdns_dict *reply, getdns_transaction_t request_id) { /* TODO: Check request_id at context->outbound_requests */ connection *conn = (connection *)(intptr_t)request_id; diff --git a/src/stub.c b/src/stub.c index b1e3772b..29929613 100644 --- a/src/stub.c +++ b/src/stub.c @@ -822,19 +822,45 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) getdns_context *context = dnsreq->context; if (context->tls_ctx == 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) return NULL; -#if HAVE_TLS_CONN_CURVES_LIST + + getdns_return_t r = GETDNS_RETURN_GOOD; + if (upstream->tls_curves_list) - _getdns_tls_connection_set_curves_list(tls, upstream->tls_curves_list); -#endif + r = _getdns_tls_connection_set_curves_list(tls, upstream->tls_curves_list); + 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 */ - if (_getdns_associate_upstream_with_connection(tls, upstream) != GETDNS_RETURN_GOOD) { - _getdns_tls_connection_free(&context->my_mf, tls); + if (!r) + 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; } + 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 authentication on other upstreams first. This is non-optimal and but avoids 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; } } - 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); @@ -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 && upstreams->upstreams[i].conn_retry_time < now) { 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", upstreams->upstreams[i].addr_str, upstreams->upstreams[i].transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"); @@ -2070,9 +2086,9 @@ upstream_find_for_netreq(getdns_network_req *netreq) return fd; } /* Handle better, will give generic error*/ - DEBUG_STUB("%s %-35s: MSG: %p No valid upstream! \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq); - _getdns_context_log(netreq->owner->context, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR, - " *FAILURE* no valid transports or upstreams available!\n"); + _getdns_log(&netreq->owner->context->log + , GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR + , " *FAILURE* no valid transports or upstreams available!\n"); return -1; } diff --git a/src/sync.c b/src/sync.c index e592e7d1..bcf66e6f 100644 --- a/src/sync.c +++ b/src/sync.c @@ -164,7 +164,7 @@ getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type, getdns_return_t 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_return_t r; @@ -190,7 +190,7 @@ getdns_general_sync(getdns_context *context, const char *name, getdns_return_t 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_return_t r; @@ -215,8 +215,8 @@ getdns_address_sync(getdns_context *context, const char *name, } getdns_return_t -getdns_hostname_sync(getdns_context *context, getdns_dict *address, - getdns_dict *extensions, getdns_dict **response) +getdns_hostname_sync(getdns_context *context, const getdns_dict *address, + const getdns_dict *extensions, getdns_dict **response) { getdns_sync_data data; getdns_return_t r; @@ -242,7 +242,7 @@ getdns_hostname_sync(getdns_context *context, getdns_dict *address, getdns_return_t 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_return_t r; diff --git a/src/test/check_getdns_address.h b/src/test/check_getdns_address.h index f898bdd8..a4eaad71 100644 --- a/src/test/check_getdns_address.h +++ b/src/test/check_getdns_address.h @@ -178,7 +178,7 @@ { /* * name = "localhost" name should be resolved from host file - * expect: NOERROR/NODATA response: + * expect: NOERROR response: * status = GETDNS_RESPSTATUS_GOOD * rcode = 0 * ancount = 1 (number of records in ANSWER section) @@ -192,7 +192,7 @@ CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; - ASSERT_RC(getdns_address(context, "localhost", NULL, + ASSERT_RC(getdns_address(context, "localhost.", NULL, &fn_ref, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_address()"); diff --git a/src/test/check_getdns_address_sync.h b/src/test/check_getdns_address_sync.h index f9e6b97d..c5c4ae92 100644 --- a/src/test/check_getdns_address_sync.h +++ b/src/test/check_getdns_address_sync.h @@ -127,7 +127,7 @@ 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()"); EXTRACT_LOCAL_RESPONSE; @@ -147,7 +147,7 @@ /* * name = "willem.getdnsapi.net" need to replace this with domain from unbound zone * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD + * status = GETDNS_RESPSTATUS_NO_DATA * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ @@ -162,6 +162,7 @@ EXTRACT_RESPONSE; assert_noerror(&ex_response); + assert_nodata(&ex_response); //assert_soa_in_authority(&ex_response); CONTEXT_DESTROY; diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c index af894be5..9816f8ff 100644 --- a/src/test/check_getdns_common.c +++ b/src/test/check_getdns_common.c @@ -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 * 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) == 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) { 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\""); 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), GETDNS_RETURN_GOOD, "Failed to extract \"answer\" 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) { - size_t length; + size_t length = 0; + char *resp_str = ""; ASSERT_RC(getdns_list_get_length(ex_response->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); } /* diff --git a/src/test/check_getdns_common.h b/src/test/check_getdns_common.h index 6fb3b555..c9691b59 100644 --- a/src/test/check_getdns_common.h +++ b/src/test/check_getdns_common.h @@ -41,6 +41,7 @@ struct extracted_response { uint32_t top_answer_type; + struct getdns_dict *response; struct getdns_bindata *top_canonical_name; struct getdns_list *just_address_answers; struct getdns_list *replies_full; diff --git a/src/test/check_getdns_context_set_dns_transport.h b/src/test/check_getdns_context_set_dns_transport.h index ef847636..07dce329 100644 --- a/src/test/check_getdns_context_set_dns_transport.h +++ b/src/test/check_getdns_context_set_dns_transport.h @@ -264,8 +264,6 @@ GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()"); 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()"); - 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), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -292,17 +290,14 @@ struct getdns_dict *extensions = getdns_dict_create(); /* - * Not all servers in the path to large.getdnsapi.net seem to support - * TCP consistently. Many (root) servers are anycasted which decreases - * 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. + * Not all root servers seem to support TCP reliably. To mitigate, + * we put our faith in k.root-servers.net. */ struct getdns_list *root_servers = 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; uint32_t status; @@ -319,7 +314,9 @@ /* Re-do over TCP */ ASSERT_RC(getdns_dict_set_int(extensions,"return_call_reporting", GETDNS_EXTENSION_TRUE), 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()"); 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()"); ASSERT_RC(getdns_list_get_bindata(root_servers2, 0, &answer), GETDNS_RETURN_GOOD, "Return code from getdns_list_get_bindata()"); - ck_assert_msg(strncmp((char *)answer->data, (char *)nlnetlabs_root.data, 4) == 0, - "Expected answer data to be 185.49.141.37"); + ck_assert_msg(strncmp((char *)answer->data, (char *)k6_root.data, 16) == 0, + "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), GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()"); ASSERT_RC(getdns_context_set_edns_maximum_udp_payload_size(context, 512), diff --git a/src/test/check_getdns_general.h b/src/test/check_getdns_general.h index f073cd86..23bb7e77 100644 --- a/src/test/check_getdns_general.h +++ b/src/test/check_getdns_general.h @@ -146,7 +146,7 @@ * name = "google.com" * request_type = 0 (minimum valid RRTYPE) * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD + * status = GETDNS_RESPSTATUS_NO_NAME * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ @@ -180,7 +180,7 @@ * name = "google.com" * request_type = 65279 (maximum unassigned RRTYPE) * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD + * status = GETDNS_RESPSTATUS_NO_NAME * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ @@ -322,7 +322,7 @@ * name = "willem.getdnsapi.net" and unbound zone * request_type = GETDNS_RRTYPE_MX * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD + * status = GETDNS_RESPSTATUS_NO_NAME * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ diff --git a/src/test/check_getdns_general_sync.h b/src/test/check_getdns_general_sync.h index 5386ff53..52eacaff 100644 --- a/src/test/check_getdns_general_sync.h +++ b/src/test/check_getdns_general_sync.h @@ -128,7 +128,7 @@ * name = "google.com" * request_type = 0 (minimum valid RRTYPE) * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD + * status = GETDNS_RESPSTATUS_NO_NAME * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ @@ -155,7 +155,7 @@ * name = "google.com" * request_type = 65279 (maximum unassigned RRTYPE) * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD + * status = GETDNS_RESPSTATUS_NO_NAME * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ @@ -269,7 +269,7 @@ * name = "willem.getdnsapi.net" an unbound zone (as in no MX) * request_type = GETDNS_RRTYPE_MX * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD + * status = GETDNS_RESPSTATUS_NO_NAME * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ diff --git a/src/test/tpkg/290-transports.tpkg/290-transports.test b/src/test/tpkg/290-transports.tpkg/290-transports.test index ce3730e2..c66ac5c5 100644 --- a/src/test/tpkg/290-transports.tpkg/290-transports.test +++ b/src/test/tpkg/290-transports.tpkg/290-transports.test @@ -10,8 +10,8 @@ then else HAVE_SSL_HN_AUTH=0 fi -SERVER_IP="8.8.8.8" -SERVER_IPv6="2001:4860:4860::8888" +SERVER_IP="64.6.64.6" +SERVER_IPv6="2620:74:1b::1:1" SERVER_IP_TSIG="185.49.141.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 ]] then - NUM_GOOD_QUERIES=9 + NUM_GOOD_QUERIES=8 GOOD_QUERIES=( "-s -A getdnsapi.net -l U @${SERVER_IP} +edns_cookies" "U" "-" "-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 -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} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S" - "-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-") + "-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" "-") else - NUM_GOOD_QUERIES=7 + NUM_GOOD_QUERIES=6 GOOD_QUERIES=( "-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 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 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 -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-") + "-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" "-") fi #"-s -A getdnsapi.net -l L -m @${TLS_SERVER_SS_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_SS_KEY}\"" "L" "S" diff --git a/src/test/tpkg/run-one.sh b/src/test/tpkg/run-one.sh index 4791cb4a..d8032e04 100755 --- a/src/test/tpkg/run-one.sh +++ b/src/test/tpkg/run-one.sh @@ -3,8 +3,9 @@ export SRCDIR=`dirname $0` . `dirname $0`/setup-env.sh -# pass a single test name as the first parameter (without .tpgk extension) -ONE_TEST=$1 +# pass a single test name as the first parameter +ONE_TEST=${1%/} +ONE_TEST=${ONE_TEST%.tpkg} shift "${TPKG}" $* exe ${SRCDIR}/${ONE_TEST}.tpkg diff --git a/src/tls.h b/src/tls.h index 4f65bf64..aacf4257 100644 --- a/src/tls.h +++ b/src/tls.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, NLnet Labs + * Copyright (c) 2018-2019, NLnet Labs * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,10 +57,11 @@ void _getdns_tls_init(); /** * 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. */ -_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. @@ -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); /** - * 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 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_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. @@ -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); +/** + * 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. * @@ -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 ctx the context. * @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. */ -_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. @@ -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); +/** + * 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. * @@ -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); +/** + * 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. * @@ -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); -/** - * Default context cipher list. - */ -const char* const _getdns_tls_context_default_cipher_list; - #endif /* _GETDNS_TLS_H */ diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 3102ce1a..25f27d60 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -183,6 +183,7 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\ntsig spec: [:]:\n"); fprintf(out, "\nextensions:\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_only_secure\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; FILE *fh; int int_value; + int got_rrtype = 0; + int got_calltype = 0; + int got_qname = 0; for (i = 1; i < argc; i++) { arg = argv[i]; if ((t = get_rrtype(arg)) >= 0) { request_type = t; + got_rrtype = 1; continue; } else if (arg[0] == '+') { @@ -653,6 +658,7 @@ getdns_return_t parse_args(int argc, char **argv) continue; } else if (arg[0] != '-') { + got_qname = 1; name = arg; continue; } @@ -666,6 +672,7 @@ getdns_return_t parse_args(int argc, char **argv) break; case 'A': calltype = ADDRESS; + got_calltype = 1; break; case 'b': if (c[1] != 0 || ++i >= argc || !*argv[i]) { @@ -739,9 +746,11 @@ getdns_return_t parse_args(int argc, char **argv) break; case 'G': calltype = GENERAL; + got_calltype = 1; break; case 'H': calltype = HOSTNAME; + got_calltype = 1; break; case 'h': print_usage(stdout, argv[0]); @@ -870,6 +879,7 @@ getdns_return_t parse_args(int argc, char **argv) break; case 'S': calltype = SERVICE; + got_calltype = 1; break; case 't': if (c[1] != 0 || ++i >= argc || !*argv[i]) { @@ -1093,6 +1103,9 @@ getdns_return_t parse_args(int argc, char **argv) } next: ; } + if (!got_calltype && !got_rrtype && got_qname) { + calltype = ADDRESS; + } if (r) return r; if (pubkey_pinset && upstream_count) { diff --git a/src/types-internal.h b/src/types-internal.h index a97b1719..12489e9c 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -299,6 +299,7 @@ typedef struct getdns_dns_req { unsigned suffix_appended : 1; /* request extensions */ + unsigned dnssec : 1; unsigned dnssec_return_status : 1; unsigned dnssec_return_only_secure : 1; unsigned dnssec_return_all_statuses : 1; @@ -431,7 +432,8 @@ extern getdns_dict *no_dnssec_checking_disabled_opportunistic; /* dns request utils */ 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); diff --git a/src/util-internal.c b/src/util-internal.c index a1cc11c5..a592b90d 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -54,7 +54,8 @@ 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; if (!result) { @@ -710,7 +711,7 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, else goto error; /* 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 */ if (getdns_dict_set_int(result, "answer_type", GETDNS_NAMETYPE_DNS)) goto error; @@ -1119,9 +1120,11 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) int rrsigs_in_answer = 0; getdns_dict *reply; 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; _srvs srvs = { 0, 0, NULL }; + _getdns_rrset_spc answer_spc; /* info (bools) about dns_req */ 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))) 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_all_statuses #ifdef DNSSEC_ROADBLOCK_AVOIDANCE @@ -1192,16 +1196,18 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) _getdns_network_validate_tsig(netreq); nreplies++; - if (netreq->dnssec_status == GETDNS_DNSSEC_SECURE) - nsecure++; - else if (netreq->dnssec_status != GETDNS_DNSSEC_BOGUS) - ninsecure++; - - if (dnssec_return_status && - netreq->dnssec_status == GETDNS_DNSSEC_BOGUS) - nbogus++; - - + switch (netreq->dnssec_status) { + case GETDNS_DNSSEC_SECURE : nsecure++; + break; + case GETDNS_DNSSEC_INSECURE : ninsecure++; + break; + case GETDNS_DNSSEC_INDETERMINATE: nindeterminate++; + ninsecure++; + break; + case GETDNS_DNSSEC_BOGUS : if (dnssec_return_status) + nbogus++; + break; + } if (! completed_request->dnssec_return_all_statuses && ! completed_request->dnssec_return_validation_chain) { 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 && netreq->dnssec_status != GETDNS_DNSSEC_SECURE) continue; + else if (completed_request->dnssec && + netreq->dnssec_status == GETDNS_DNSSEC_INDETERMINATE) + continue; else if (netreq->tsig_status == GETDNS_DNSSEC_BOGUS) continue; } @@ -1227,8 +1236,8 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) /* TODO: Check instead if canonical_name for request_type * is in the answer section. */ - if (GLDNS_RCODE_NOERROR == - GLDNS_RCODE_WIRE(netreq->response)) + if (_getdns_rrset_answer(&answer_spc, netreq->response + , netreq->response_len)) nanswers++; 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, completed_request->request_timed_out || 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 : - 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 : nanswers == 0 ? GETDNS_RESPSTATUS_NO_NAME : GETDNS_RESPSTATUS_GOOD)) @@ -1442,7 +1456,7 @@ _getdns_validate_dname(const char* 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_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; 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); } -uint8_t *_getdns_list2wire( - getdns_list *l, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf) +uint8_t *_getdns_list2wire(const getdns_list *l, + uint8_t *buf, size_t *buf_len, const struct mem_funcs *mf) { gldns_buffer gbuf; size_t sz; @@ -1557,8 +1571,8 @@ uint8_t *_getdns_list2wire( return buf; } -uint8_t *_getdns_reply2wire( - getdns_dict *r, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf) +uint8_t *_getdns_reply2wire(const getdns_dict *r, + uint8_t *buf, size_t *buf_len, const struct mem_funcs *mf) { gldns_buffer gbuf; size_t sz; @@ -1578,7 +1592,7 @@ uint8_t *_getdns_reply2wire( 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_dict *rr_dict; diff --git a/src/util-internal.h b/src/util-internal.h index 3d768de1..8a1a6d82 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -147,17 +147,18 @@ _getdns_rr_iter2rr_dict_canonical( struct mem_funcs *mf, _getdns_rr_iter *i, uint32_t *orig_ttl); 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); -uint8_t *_getdns_list2wire( - getdns_list *l, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf); +uint8_t *_getdns_list2wire(const getdns_list *l, + uint8_t *buf, size_t *buf_len, const struct mem_funcs *mf); -uint8_t *_getdns_reply2wire( - getdns_dict *r, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf); +uint8_t *_getdns_reply2wire(const getdns_dict *r, + 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); /** diff --git a/src/util/orig-headers/rbtree.h b/src/util/orig-headers/rbtree.h index dfcf09ac..2768c2c5 100644 --- a/src/util/orig-headers/rbtree.h +++ b/src/util/orig-headers/rbtree.h @@ -143,7 +143,7 @@ int rbtree_find_less_equal(rbtree_type *rbtree, const void *key, * @param rbtree: tree * @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 diff --git a/src/util/rbtree.c b/src/util/rbtree.c index f031c9a1..ff4e3e46 100644 --- a/src/util/rbtree.c +++ b/src/util/rbtree.c @@ -546,7 +546,7 @@ rbtree_find_less_equal(rbtree_type *rbtree, const void *key, * */ rbnode_type * -rbtree_first (rbtree_type *rbtree) +rbtree_first (const rbtree_type *rbtree) { rbnode_type *node;