From 5c6f03632613aaa3b29972844b16ff0b11f8f8d8 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 21 Jul 2016 20:25:31 +0200 Subject: [PATCH 001/249] Further updates --- project-doc/release-procedure.txt | 139 +++++++++++++----------------- 1 file changed, 61 insertions(+), 78 deletions(-) diff --git a/project-doc/release-procedure.txt b/project-doc/release-procedure.txt index 6438a4cf..3222a85b 100644 --- a/project-doc/release-procedure.txt +++ b/project-doc/release-procedure.txt @@ -1,61 +1,52 @@ -High level release procedure that we follow to make a formal release for the -getdns API project. This is a recipe - if you have a better way to do it then -update this document and share it with us. +High level release procedure for formal release for the getdns API project. -- code freeze - confirm with core team that all commits are in, from this point forward - only bug fixes should be committed to the release branch, once the release - is cut nothing should be committed to the release branch (make a new release) +1) Git branching for a release + -- Confirm with core team (preferably via email) that all commits to be included + in the release are in the develop branch. Development for the next release can + continue on develop. + -- Create a release branch. We use the pattern "release/v1.0.0-b3" for naming + release branches. This branch is used for testing + and bug fixing while preparing the release (which can take several days + if there are un-foreseen issues). Note that from this point forward _only_ + bug fixes for this release should be committed to the release branch. + -- Once the release is published there should be no further commits on that + release branch. -- create a release branch - in git repository named for the release, e.g. "release/v1.0.0-b3" - we do this because folks may want to continue to work in the develop branch - and be free to commit changes without injuring the release process. Since - building and testing binaries for a release takes a few days we don't want to - force changes to queue up. - - One might argue that a release can be cut more quickly, however there are - inevitably little tweaks that need to be made that get uncovered as a result - of the binary builds - these tweaks need to be included in the souces for - this release so building the source tarball can't be done until all of the - binaries have been built and tested. - -- clone repo release branch to a clean local repo - this should be a brand spanking new directory - don't try to shortcut it and - use a working directory with lots of cruft - crap will find its way into the - release and embarass you: +2) Prepare the release + -- Clone the upstream to a _new_ local directory. (Do NOT re-use and + existing working copy as this can lead to issues). # git clone -b v1.0.0-b3 https://github.com/getdnsapi/getdns.git getdns-1.0.0-b3 -- update files to reflect release number/date - ./README.md - ./ChangeLog - ./configure.ac - - Watch for and change values: - - AC_INIT - - RELEASE_CANDIDATE - - GETDNS_NUMERIC_VERSION - - API_VERSION and API_NUMERUC_VERSION - - read section "Library version" and - update GETDNS_LIBVERSION carefully! + -- Update several files to reflect release number/date + ./README.md + ./ChangeLog + ./configure.ac + - Check and change the values for: + - AC_INIT + - RELEASE_CANDIDATE + - GETDNS_NUMERIC_VERSION + - API_VERSION and API_NUMERUC_VERSION + - read the section "Library version" and update GETDNS_LIBVERSION carefully! - # autoreconf -fi + # autoreconf -fi - commit these changes to the release branch + Commit these changes to the release branch - # git commit -a -m "release number and date updates" - # git push + # git commit -a -m "release number and date updates" + # git push -- Do the unit tests on as many different systems as you can. They must all - be able to fulfill all requirements. So they have libidn, libev, libuv, libevent, - latest libunbound, latest openssl (at least 1.0.2) lastest clang compiler - (for static analysis), latest valigrind. Then run: +3) Test + The unit and tpkg tests should be run on all the supported platforms. They must all + be able to fulfil all requirements. So they must have libidn, libev, libuv, libevent, + latest libunbound, latest openssl (at least 1.0.2) latest clang compiler + (for static analysis), latest valgrind. The tests can be run using: - # ${GETDNS_SRCDIR}/src/test/tpkg/run-all.sh + # ${GETDNS_SRCDIR}/src/test/tpkg/run-all.sh - and evaluate the results. + and evaluating the results. -- build and sign source distribution tarball: +4) Build and sign source distribution tarball # rm -fr * # git reset --hard # git submodule update --init @@ -64,47 +55,39 @@ update this document and share it with us. # ./configure # make pub - - test the resulting tar by building it and running the regression tests - on as many different systems as you can. + The resulting tarball must be built, installed and tested on all the supported + platforms. Be sure to use a user that was NOT used for the build, this will uncover + any issues related to absolute paths in the build -- install on each target platform - - make sure and use a user that was NOT used for the build, this will uncover - any silliness related to absolute paths in the build +5) Fix any problems + -- If a build breaks or an install fails then commit fixes to the release branch. + Then re-run steps 3 and 4 for all supported platforms using the new code. -- if a build breaks or an install fails then commit fixes to the relase branch - - rebuild EVERY binary using the changed release branch +6) Merge branch changes back into master/develop + -- If this is a production release - then the release branch must be merged into master + Sign the merge tag if possible. + -- Now the release is ready, all the relevant commits on the release branch + should also be merged back into develop. -- merge branch changes back into master +7) Create the tarball + # make clean + # make pub + This generates getdns-1.0.0-b3.tar.gz + checksums + signatures. -- once all binaries are built and tested clean, create source tar ball +8) Upload source tarball and checksums and signatures to the getdnsapi.net site - you may need to run this as root to permit the chown - # make clean - # make pub - generates getdns-1.0.0-b3.tar.gz + checksums + signatures + # scp getdns-1.0.0-b3.tar.gz* getdnsapi.net:/usr/local/www/apache24/data/dist -- upload source tarball and checsums and signatures to the getdnsapi.net site +9) Create and push signed tags to github - # scp getdns-1.0.0-b3.tar.gz* getdnsapi.net:/usr/local/www/apache24/data/dist + # git -s v1.0.0-b3 + # git push --tags -- Create and push signed tags to github +10) Update getdnsapi.net web site + - Create an entry the the 'Checksum' page using the content of ChangeLog + - Create a new 'News' entry - # git -s v1.0.0-b3 - # git push --tags - -- update getdnsapi.net web site - - create a getdns-1.0.0-b3.tar.gz.changelog and - getdns-1.0.0-b3.tar.gz.html in - /usr/local/www/apache24/data/dist - with the content of ChangeLog - and the release announcement respectively. - - Edit /usr/local/www/apache24/build_site.py. - Change latest entry and create a new news_item entry. - - rebuild website - # cd /usr/local/www/apache24 - # ./build_site.py - -- announce message to +11) Announce the release to the lists (make sure to sign the emails) users@getdnsapi.net, spec@getdnsapi.net and maintainers@nlnetlabs.nl From 0432fe37c45ac4f0ca31d150a2759cfe63c1bce7 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 21 Jul 2016 19:24:18 +0200 Subject: [PATCH 002/249] Tinker with upstream keepalive --- src/context.c | 2 ++ src/context.h | 1 + src/stub.c | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/context.c b/src/context.c index 847fb041..5439a7a9 100644 --- a/src/context.c +++ b/src/context.c @@ -711,6 +711,7 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) upstream->responses_received = 0; upstream->responses_timeouts = 0; upstream->keepalive_timeout = 0; + upstream->keepalive_shutdown = 0; /* Now TLS stuff*/ upstream->tls_auth_state = GETDNS_AUTH_NONE; @@ -836,6 +837,7 @@ upstream_init(getdns_upstream *upstream, upstream->queries_sent = 0; upstream->responses_received = 0; upstream->responses_timeouts = 0; + upstream->keepalive_shutdown = 0; upstream->keepalive_timeout = 0; upstream->to_retry = 2; upstream->back_off = 1; diff --git a/src/context.h b/src/context.h index 84a2c40c..c2e91f3d 100644 --- a/src/context.h +++ b/src/context.h @@ -148,6 +148,7 @@ typedef struct getdns_upstream { size_t queries_sent; size_t responses_received; size_t responses_timeouts; + size_t keepalive_shutdown; uint64_t keepalive_timeout; /* Management of outstanding requests on stateful transports */ diff --git a/src/stub.c b/src/stub.c index 2b6f9c36..54fb4b76 100644 --- a/src/stub.c +++ b/src/stub.c @@ -342,9 +342,17 @@ process_keepalive( /* Use server sent value unless the client specified a shorter one. Convert to ms first (wire value has units of 100ms) */ uint64_t server_keepalive = ((uint64_t)gldns_read_uint16(position))*100; + DEBUG_STUB("%s %-35s: FD: %d Server Keepalive recived: %d ms\n", + STUB_DEBUG_READ, __FUNCTION__, upstream->fd, + (int)server_keepalive); if (netreq->owner->context->idle_timeout < server_keepalive) upstream->keepalive_timeout = netreq->owner->context->idle_timeout; else { + if (server_keepalive == 0) { + /* This means the server wants us to shut the connection (sending no + more queries). */ + upstream->keepalive_shutdown = 1; + } upstream->keepalive_timeout = server_keepalive; DEBUG_STUB("%s %-35s: FD: %d Server Keepalive used: %d ms\n", STUB_DEBUG_READ, __FUNCTION__, upstream->fd, @@ -1551,8 +1559,11 @@ upstream_working_ok(getdns_upstream *upstream) static int upstream_active(getdns_upstream *upstream) { - return ((upstream->conn_state == GETDNS_CONN_SETUP || - upstream->conn_state == GETDNS_CONN_OPEN) ? 1 : 0); + if ((upstream->conn_state == GETDNS_CONN_SETUP || + upstream->conn_state == GETDNS_CONN_OPEN) && + upstream->keepalive_shutdown == 0) + return 1; + return 0; } static int From a1461d51eceedbd6cfa7567fa1659be4724ed876 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 5 Aug 2016 14:10:55 +0100 Subject: [PATCH 003/249] Add abbreviated logging mode for daemon --- configure.ac | 9 +++++++++ src/context.c | 37 ++++++++++++++++++++++++------------- src/context.h | 3 +++ src/debug.h | 8 ++++++++ src/stub.c | 15 ++++++++++++--- src/types-internal.h | 11 +++++++++++ 6 files changed, 67 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 73150114..efcf7ce0 100644 --- a/configure.ac +++ b/configure.ac @@ -144,6 +144,7 @@ ACX_ARG_RPATH AC_ARG_ENABLE(debug-sched, AC_HELP_STRING([--enable-debug-sched], [Enable scheduling debugging messages])) AC_ARG_ENABLE(debug-stub, AC_HELP_STRING([--enable-debug-stub], [Enable stub debugging messages])) +AC_ARG_ENABLE(debug-daemon, AC_HELP_STRING([--enable-debug-daemon], [Enable daemon debugging messages])) AC_ARG_ENABLE(debug-sec, AC_HELP_STRING([--enable-debug-sec], [Enable dnssec debugging messages])) AC_ARG_ENABLE(debug-server, AC_HELP_STRING([--enable-debug-server], [Enable server debugging messages])) AC_ARG_ENABLE(all-debugging, AC_HELP_STRING([--enable-all-debugging], [Enable scheduling, stub and dnssec debugging])) @@ -151,6 +152,7 @@ case "$enable_all_debugging" in yes) enable_debug_sched=yes enable_debug_stub=yes + enable_debug_daemon=yes enable_debug_sec=yes enable_debug_server=yes ;; @@ -171,6 +173,13 @@ case "$enable_debug_stub" in no|*) ;; esac +case "$enable_debug_daemon" in + yes) + AC_DEFINE_UNQUOTED([DAEMON_DEBUG], [1], [Define this to enable printing of daemon debugging messages.]) + ;; + no|*) + ;; +esac case "$enable_debug_sec" in yes) AC_DEFINE_UNQUOTED([SEC_DEBUG], [1], [Define this to enable printing of dnssec debugging messages.]) diff --git a/src/context.c b/src/context.c index 5439a7a9..1c851e64 100644 --- a/src/context.c +++ b/src/context.c @@ -224,6 +224,14 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) } #endif +static uint8_t* +upstream_addr(getdns_upstream *upstream) +{ + return upstream->addr.ss_family == AF_INET + ? (void *)&((struct sockaddr_in*)&upstream->addr)->sin_addr + : (void *)&((struct sockaddr_in6*)&upstream->addr)->sin6_addr; +} + static void destroy_local_host(_getdns_rbnode_t * node, void *arg) { getdns_context *context = (getdns_context *)arg; @@ -683,11 +691,17 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) if (upstream->tls_auth_state != GETDNS_AUTH_NONE) upstream->past_tls_auth_state = upstream->tls_auth_state; - DEBUG_STUB("%s %-35s: FD: %d Upstream Stats: Resp=%d,Timeouts=%d,Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Auth=%d\n", - STUB_DEBUG_CLEANUP, __FUNCTION__, upstream->fd, - (int)upstream->total_responses, (int)upstream->total_timeouts, - (int)upstream->conn_completed, (int)upstream->conn_setup_failed, - (int)upstream->conn_shutdowns, upstream->past_tls_auth_state); +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + DEBUG_DAEMON("%s Upstream %s : Connection closed: Connection stats - Resp=%d,Timeouts=%d,Keepalive(ms)=%d,Auth=%s\n", + STUB_DEBUG_DAEMON, upstream->addr_str, + (int)upstream->responses_received, (int)upstream->responses_timeouts, + (int)upstream->keepalive_timeout, getdns_auth_str_array[upstream->tls_auth_state]); + DEBUG_DAEMON("%s Upstream %s : Connection closed: Upstream stats - Resp=%d,Timeouts=%d,Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Auth=%s\n", + STUB_DEBUG_DAEMON, upstream->addr_str, + (int)upstream->total_responses, (int)upstream->total_timeouts, + (int)upstream->conn_completed, (int)upstream->conn_setup_failed, + (int)upstream->conn_shutdowns, getdns_auth_str_array[upstream->tls_auth_state]); +#endif /* Back off connections that never got up service at all (probably no TCP service or incompatible TLS version/cipher). @@ -829,6 +843,10 @@ upstream_init(getdns_upstream *upstream, upstream->addr_len = ai->ai_addrlen; (void) memcpy(&upstream->addr, ai->ai_addr, ai->ai_addrlen); +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + inet_ntop(upstream->addr.ss_family, upstream_addr(upstream), + upstream->addr_str, INET6_ADDRSTRLEN); +#endif /* How is this upstream doing? */ upstream->conn_setup_failed = 0; @@ -2831,15 +2849,8 @@ getdns_cancel_callback(getdns_context *context, return r; } /* getdns_cancel_callback */ -#ifndef STUB_NATIVE_DNSSEC -static uint8_t* -upstream_addr(getdns_upstream *upstream) -{ - return upstream->addr.ss_family == AF_INET - ? (void *)&((struct sockaddr_in*)&upstream->addr)->sin_addr - : (void *)&((struct sockaddr_in6*)&upstream->addr)->sin6_addr; -} +#ifndef STUB_NATIVE_DNSSEC static in_port_t upstream_port(getdns_upstream *upstream) { diff --git a/src/context.h b/src/context.h index c2e91f3d..9caf458d 100644 --- a/src/context.h +++ b/src/context.h @@ -124,6 +124,9 @@ typedef struct getdns_upstream { socklen_t addr_len; struct sockaddr_storage addr; +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + char addr_str[INET6_ADDRSTRLEN]; +#endif /* How is this upstream doing over UDP? */ int to_retry; diff --git a/src/debug.h b/src/debug.h index 91051435..643b198d 100644 --- a/src/debug.h +++ b/src/debug.h @@ -45,6 +45,7 @@ #define STUB_DEBUG_READ "------- READ: " #define STUB_DEBUG_WRITE "------- WRITE: " #define STUB_DEBUG_CLEANUP "--- CLEANUP: " +#define STUB_DEBUG_DAEMON "GETDNS_DAEMON: " #define DEBUG_ON(...) do { \ struct timeval tv; \ @@ -88,6 +89,13 @@ #define DEBUG_STUB(...) DEBUG_OFF(__VA_ARGS__) #endif +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG +#include +#define DEBUG_DAEMON(...) DEBUG_ON(__VA_ARGS__) +#else +#define DEBUG_DAEMON(...) DEBUG_OFF(__VA_ARGS__) +#endif + #if defined(SEC_DEBUG) && SEC_DEBUG #include #define DEBUG_SEC(...) DEBUG_ON(__VA_ARGS__) diff --git a/src/stub.c b/src/stub.c index 54fb4b76..74f25d39 100644 --- a/src/stub.c +++ b/src/stub.c @@ -522,9 +522,14 @@ upstream_failed(getdns_upstream *upstream, int during_setup) if (during_setup) { /* Reset timeout on setup failure to trigger fallback handling.*/ GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); - GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd, TIMEOUT_FOREVER, - getdns_eventloop_event_init(&upstream->event, upstream, - NULL, upstream_write_cb, NULL)); + /* Need this check because if the setup failed because the interface is + not up we get -1 and then a seg fault. Found when using IPv6 address + but IPv6 interface not enabled.*/ + if (upstream->fd != -1) { + GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd, TIMEOUT_FOREVER, + getdns_eventloop_event_init(&upstream->event, upstream, + NULL, upstream_write_cb, NULL)); + } /* Special case if failure was due to authentication issues since this upstream could be used oppotunistically with no problem.*/ if (!(upstream->transport == GETDNS_TRANSPORT_TLS && @@ -1739,6 +1744,10 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, return -1; /* Nothing to do*/ } +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + DEBUG_DAEMON("%s Upstream %s : Connection initialised\n", + STUB_DEBUG_DAEMON, upstream->addr_str); +#endif return fd; } diff --git a/src/types-internal.h b/src/types-internal.h index f6c3cf5b..5f67f7cd 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -63,6 +63,17 @@ typedef enum getdns_auth_state { GETDNS_AUTH_OK, /* Tried and worked (Strict) */ } getdns_auth_state_t; +#define GETDNS_STR_AUTH_NONE "N/A" +#define GETDNS_STR_AUTH_FAILED "Failed or not tried" +#define GETDNS_STR_AUTH_OK "Success" + +static char* +getdns_auth_str_array[] = { + GETDNS_STR_AUTH_NONE, + GETDNS_STR_AUTH_FAILED, + GETDNS_STR_AUTH_OK +}; + struct getdns_context; struct getdns_upstreams; struct getdns_upstream; From fdbefa17ecc10aa735776a87b02d1e6ac9013865 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 5 Aug 2016 17:25:27 +0100 Subject: [PATCH 004/249] Add timer for back off on upstream (use 1 hr). Reset as new upstream when re-instated. --- src/context.c | 38 ++++++++++++++++++++++++++++---------- src/context.h | 2 ++ src/stub.c | 14 +++++++++++--- src/types-internal.h | 4 ++-- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/context.c b/src/context.c index 1c851e64..5e120317 100644 --- a/src/context.c +++ b/src/context.c @@ -84,6 +84,9 @@ typedef unsigned short in_port_t; #define GETDNS_STR_PORT_ZERO "0" #define GETDNS_STR_PORT_DNS "53" #define GETDNS_STR_PORT_DNS_OVER_TLS "853" +/* How long to wait in seconds before re-trying a connection based backed-off + upstream. Using 1 hour for all transports - based on RFC7858 value for for TLS.*/ +#define BACKOFF_RETRY 3600 void *plain_mem_funcs_user_arg = MF_PLAIN; @@ -692,15 +695,16 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) upstream->past_tls_auth_state = upstream->tls_auth_state; #if defined(DAEMON_DEBUG) && DAEMON_DEBUG - DEBUG_DAEMON("%s Upstream %s : Connection closed: Connection stats - Resp=%d,Timeouts=%d,Keepalive(ms)=%d,Auth=%s\n", + DEBUG_DAEMON("%s %s : Conn closed: Conn stats - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->responses_received, (int)upstream->responses_timeouts, - (int)upstream->keepalive_timeout, getdns_auth_str_array[upstream->tls_auth_state]); - DEBUG_DAEMON("%s Upstream %s : Connection closed: Upstream stats - Resp=%d,Timeouts=%d,Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Auth=%s\n", + getdns_auth_str_array[upstream->tls_auth_state], (int)upstream->keepalive_timeout); + DEBUG_DAEMON("%s %s : Upstream stats - Resp=%d,Timeouts=%d,Auth=%s,Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->total_responses, (int)upstream->total_timeouts, - (int)upstream->conn_completed, (int)upstream->conn_setup_failed, - (int)upstream->conn_shutdowns, getdns_auth_str_array[upstream->tls_auth_state]); + getdns_auth_str_array[upstream->tls_auth_state], + (int)upstream->conn_completed, (int)upstream->conn_setup_failed, + (int)upstream->conn_shutdowns, (int)upstream->conn_backoffs); #endif /* Back off connections that never got up service at all (probably no @@ -716,10 +720,18 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) (upstream->conn_completed >= GETDNS_CONN_ATTEMPTS && upstream->total_responses == 0 && upstream->total_timeouts > GETDNS_TRANSPORT_FAIL_MULT)) { - DEBUG_STUB("%s %-35s: FD: %d BACKING OFF THIS UPSTREAM! \n", - STUB_DEBUG_CLEANUP, __FUNCTION__, upstream->fd); upstream->conn_state = GETDNS_CONN_BACKOFF; - } + upstream->conn_retry_time = time(NULL) + BACKOFF_RETRY; + upstream->total_responses = 0; + upstream->total_timeouts = 0; + upstream->conn_completed = 0; + upstream->conn_setup_failed = 0; + upstream->conn_shutdowns = 0; + upstream->conn_backoffs++; + DEBUG_DAEMON("%s %s : !Backing off this upstream - will retry as new upstream at %s\n", + STUB_DEBUG_DAEMON, upstream->addr_str, + asctime(gmtime(&upstream->conn_retry_time))); + } // Reset per connection counters upstream->queries_sent = 0; upstream->responses_received = 0; @@ -848,15 +860,21 @@ upstream_init(getdns_upstream *upstream, upstream->addr_str, INET6_ADDRSTRLEN); #endif - /* How is this upstream doing? */ - upstream->conn_setup_failed = 0; + /* How is this upstream doing on connections? */ + upstream->conn_completed = 0; upstream->conn_shutdowns = 0; + upstream->conn_setup_failed = 0; + upstream->conn_retry_time = 0; + upstream->conn_backoffs = 0; + upstream->total_responses = 0; + upstream->total_timeouts = 0; upstream->conn_state = GETDNS_CONN_CLOSED; upstream->queries_sent = 0; upstream->responses_received = 0; upstream->responses_timeouts = 0; upstream->keepalive_shutdown = 0; upstream->keepalive_timeout = 0; + /* How is this upstream doing on UDP? */ upstream->to_retry = 2; upstream->back_off = 1; diff --git a/src/context.h b/src/context.h index 9caf458d..8d192d39 100644 --- a/src/context.h +++ b/src/context.h @@ -143,6 +143,8 @@ typedef struct getdns_upstream { size_t conn_completed; size_t conn_shutdowns; size_t conn_setup_failed; + time_t conn_retry_time; + size_t conn_backoffs; size_t total_responses; size_t total_timeouts; getdns_auth_state_t past_tls_auth_state; diff --git a/src/stub.c b/src/stub.c index 74f25d39..5fd5e9d4 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1626,12 +1626,20 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra getdns_upstream *upstream = NULL; getdns_upstreams *upstreams = netreq->owner->upstreams; size_t i; + time_t now = time(NULL); if (!upstreams->count) return NULL; - /* [TLS1]TODO: Add check to re-instate backed-off upstreams after X amount - of time*/ + /* A check to re-instate backed-off upstreams after X amount of time*/ + for (i = 0; i < upstreams->count; i++) { + if (upstreams->upstreams[i].conn_state == GETDNS_CONN_BACKOFF && + upstreams->upstreams[i].conn_retry_time < now) { + upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED; + DEBUG_DAEMON("%s %s : Re-instating upstream\n", + STUB_DEBUG_DAEMON, upstreams->upstreams[i].addr_str); + } + } /* First find if an open upstream has the correct properties and use that*/ for (i = 0; i < upstreams->count; i++) { @@ -1745,7 +1753,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, /* Nothing to do*/ } #if defined(DAEMON_DEBUG) && DAEMON_DEBUG - DEBUG_DAEMON("%s Upstream %s : Connection initialised\n", + DEBUG_DAEMON("%s %s : Conn init\n", STUB_DEBUG_DAEMON, upstream->addr_str); #endif return fd; diff --git a/src/types-internal.h b/src/types-internal.h index 5f67f7cd..bd1f993c 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -63,8 +63,8 @@ typedef enum getdns_auth_state { GETDNS_AUTH_OK, /* Tried and worked (Strict) */ } getdns_auth_state_t; -#define GETDNS_STR_AUTH_NONE "N/A" -#define GETDNS_STR_AUTH_FAILED "Failed or not tried" +#define GETDNS_STR_AUTH_NONE "None" +#define GETDNS_STR_AUTH_FAILED "Failed" #define GETDNS_STR_AUTH_OK "Success" static char* From 6f9bfffe9f3461287889f4e97f8e08e4201830c1 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Mon, 8 Aug 2016 16:12:33 +0100 Subject: [PATCH 005/249] Catch another error path for failed connections --- src/stub.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/stub.c b/src/stub.c index 5fd5e9d4..bef5bf9d 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1764,21 +1764,28 @@ upstream_find_for_transport(getdns_network_req *netreq, getdns_transport_list_t transport, int *fd) { - /* [TLS1]TODO: Don't currently loop over upstreams here as UDP will timeout - and stateful will fallback. But there is a case where connect returns -1 - that we need to deal with!!!! so add a while loop to test fd*/ getdns_upstream *upstream = NULL; + + /* UDP always returns an upstream, the only reason this will fail is if + no socket is available, in which case that is an error.*/ if (transport == GETDNS_TRANSPORT_UDP) { upstream = upstream_select(netreq); + *fd = upstream_connect(upstream, transport, netreq->owner); + return upstream; } - else - upstream = upstream_select_stateful(netreq, transport); - if (!upstream) - return NULL; - *fd = upstream_connect(upstream, transport, netreq->owner); - DEBUG_STUB("%s %-35s: FD: %d Connecting to upstream: %p No: %d\n", + else { + /* For stateful transport we should keep trying until all our transports + are exhausted/backed-off (no upstream)*/ + do { + upstream = upstream_select_stateful(netreq, transport); + if (!upstream) + return NULL; + *fd = upstream_connect(upstream, transport, netreq->owner); + } while (*fd == -1); + DEBUG_STUB("%s %-35s: FD: %d Connecting to upstream: %p No: %d\n", STUB_DEBUG_SETUP, __FUNCTION__, *fd, upstream, (int)(upstream - netreq->owner->context->upstreams->upstreams)); + } return upstream; } From f156f2f24ae1140ce875a0a4b262a463057cc151 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Mon, 8 Aug 2016 17:07:46 +0100 Subject: [PATCH 006/249] Had to change some preprocessor checks to get all the options to compile --- src/context.c | 28 +++++++++++++--------------- src/dnssec.c | 2 ++ src/stub.c | 4 +++- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/context.c b/src/context.c index 5e120317..58abcd77 100644 --- a/src/context.c +++ b/src/context.c @@ -227,6 +227,7 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) } #endif +#if !defined(STUB_NATIVE_DNSSEC) || (defined(DAEMON_DEBUG) && DAEMON_DEBUG) static uint8_t* upstream_addr(getdns_upstream *upstream) { @@ -234,6 +235,16 @@ upstream_addr(getdns_upstream *upstream) ? (void *)&((struct sockaddr_in*)&upstream->addr)->sin_addr : (void *)&((struct sockaddr_in6*)&upstream->addr)->sin6_addr; } +#endif + + +static in_port_t +upstream_port(getdns_upstream *upstream) +{ + return ntohs(upstream->addr.ss_family == AF_INET + ? ((struct sockaddr_in *)&upstream->addr)->sin_port + : ((struct sockaddr_in6*)&upstream->addr)->sin6_port); +} static void destroy_local_host(_getdns_rbnode_t * node, void *arg) { @@ -728,9 +739,11 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) upstream->conn_setup_failed = 0; upstream->conn_shutdowns = 0; upstream->conn_backoffs++; +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG DEBUG_DAEMON("%s %s : !Backing off this upstream - will retry as new upstream at %s\n", STUB_DEBUG_DAEMON, upstream->addr_str, asctime(gmtime(&upstream->conn_retry_time))); +#endif } // Reset per connection counters upstream->queries_sent = 0; @@ -2869,13 +2882,6 @@ getdns_cancel_callback(getdns_context *context, #ifndef STUB_NATIVE_DNSSEC -static in_port_t -upstream_port(getdns_upstream *upstream) -{ - return ntohs(upstream->addr.ss_family == AF_INET - ? ((struct sockaddr_in *)&upstream->addr)->sin_port - : ((struct sockaddr_in6*)&upstream->addr)->sin6_port); -} static uint32_t * upstream_scope_id(getdns_upstream *upstream) @@ -3371,14 +3377,6 @@ getdns_context_get_eventloop(getdns_context *context, getdns_eventloop **loop) return GETDNS_RETURN_GOOD; } -static in_port_t -upstream_port(getdns_upstream *upstream) -{ - return ntohs(upstream->addr.ss_family == AF_INET - ? ((struct sockaddr_in *)&upstream->addr)->sin_port - : ((struct sockaddr_in6*)&upstream->addr)->sin6_port); -} - static getdns_dict* _get_context_settings(getdns_context* context) { diff --git a/src/dnssec.c b/src/dnssec.c index f567b96b..6152782a 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -2687,6 +2687,7 @@ static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew, * evaluated by processing each head in turn. The worst outcome per network request * is the dnssec status for that network request. */ +#ifdef STUB_NATIVE_DNSSEC static void chain_set_netreq_dnssec_status(chain_head *chain, _getdns_rrset_iter *tas) { chain_head *head; @@ -2723,6 +2724,7 @@ static void chain_set_netreq_dnssec_status(chain_head *chain, _getdns_rrset_iter } } } +#endif /* The DNSSEC status of all heads for a chain structure is evaluated by * processing each head in turn. The worst outcome is the dnssec status for diff --git a/src/stub.c b/src/stub.c index bef5bf9d..e496d61d 100644 --- a/src/stub.c +++ b/src/stub.c @@ -342,7 +342,7 @@ process_keepalive( /* Use server sent value unless the client specified a shorter one. Convert to ms first (wire value has units of 100ms) */ uint64_t server_keepalive = ((uint64_t)gldns_read_uint16(position))*100; - DEBUG_STUB("%s %-35s: FD: %d Server Keepalive recived: %d ms\n", + DEBUG_STUB("%s %-35s: FD: %d Server Keepalive recieved: %d ms\n", STUB_DEBUG_READ, __FUNCTION__, upstream->fd, (int)server_keepalive); if (netreq->owner->context->idle_timeout < server_keepalive) @@ -1636,8 +1636,10 @@ 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; +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG DEBUG_DAEMON("%s %s : Re-instating upstream\n", STUB_DEBUG_DAEMON, upstreams->upstreams[i].addr_str); +#endif } } From c84ff93e4f7337069a4c0f50bc78f93543a924f6 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 25 Aug 2016 12:40:02 +0200 Subject: [PATCH 007/249] Anticipate Mac OS X glibtoolize --- src/test/tpkg/setup-env.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/tpkg/setup-env.sh b/src/test/tpkg/setup-env.sh index ad43c879..18cdfbeb 100755 --- a/src/test/tpkg/setup-env.sh +++ b/src/test/tpkg/setup-env.sh @@ -13,7 +13,7 @@ then fi if [ ! -f "${SRCROOT}/libtool" ] then - (cd "${SRCROOT}"; libtoolize -fic) + (cd "${SRCROOT}"; (glibtoolize -fic || libtoolize -fic)) fi if [ ! -f "${SRCROOT}/configure" ] then From 47e718eeb88a1cef6f732c9df3009f1cd071d341 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 13 Oct 2016 23:04:50 +0200 Subject: [PATCH 008/249] OpenSSL 1.1 support --- configure.ac | 1 + src/context.c | 9 +++++++++ src/gldns/keyraw.c | 39 +++++++++++++++++++++++++++++++++++++++ src/gldns/rrdef.h | 2 +- src/gldns/wire2str.h | 18 +++++++++--------- src/pubkey-pinning.c | 12 ++++++++---- src/types-internal.h | 7 ------- src/util/val_secalgo.c | 10 ++++++---- 8 files changed, 73 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index efcf7ce0..031c618e 100644 --- a/configure.ac +++ b/configure.ac @@ -255,6 +255,7 @@ else fi AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method]) AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [ AC_INCLUDES_DEFAULT diff --git a/src/context.c b/src/context.c index 58abcd77..ff172499 100644 --- a/src/context.c +++ b/src/context.c @@ -693,6 +693,15 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams) GETDNS_FREE(upstreams->mf, upstreams); } +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG +static char* +getdns_auth_str_array[] = { + GETDNS_STR_AUTH_NONE, + GETDNS_STR_AUTH_FAILED, + GETDNS_STR_AUTH_OK +}; +#endif + void _getdns_upstream_shutdown(getdns_upstream *upstream) { diff --git a/src/gldns/keyraw.c b/src/gldns/keyraw.c index 7a27e7f0..9e6adcb2 100644 --- a/src/gldns/keyraw.c +++ b/src/gldns/keyraw.c @@ -23,6 +23,15 @@ #ifdef HAVE_OPENSSL_ENGINE_H # include #endif +#ifdef HAVE_OPENSSL_BN_H +#include +#endif +#ifdef HAVE_OPENSSL_RSA_H +#include +#endif +#ifdef HAVE_OPENSSL_DSA_H +#include +#endif #endif /* HAVE_SSL */ size_t @@ -215,6 +224,7 @@ gldns_key_buf2dsa_raw(unsigned char* key, size_t len) BN_free(Y); return NULL; } +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #ifndef S_SPLINT_S dsa->p = P; dsa->q = Q; @@ -222,6 +232,25 @@ gldns_key_buf2dsa_raw(unsigned char* key, size_t len) dsa->pub_key = Y; #endif /* splint */ +#else /* OPENSSL_VERSION_NUMBER */ + if (!DSA_set0_pqg(dsa, P, Q, G)) { + /* QPG not yet attached, need to free */ + BN_free(Q); + BN_free(P); + BN_free(G); + + DSA_free(dsa); + BN_free(Y); + return NULL; + } + if (!DSA_set0_key(dsa, Y, NULL)) { + /* QPG attached, cleaned up by DSA_fre() */ + DSA_free(dsa); + BN_free(Y); + return NULL; + } +#endif + return dsa; } @@ -273,11 +302,21 @@ gldns_key_buf2rsa_raw(unsigned char* key, size_t len) BN_free(modulus); return NULL; } +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #ifndef S_SPLINT_S rsa->n = modulus; rsa->e = exponent; #endif /* splint */ +#else /* OPENSSL_VERSION_NUMBER */ + if (!RSA_set0_key(rsa, modulus, exponent, NULL)) { + BN_free(exponent); + BN_free(modulus); + RSA_free(rsa); + return NULL; + } +#endif + return rsa; } diff --git a/src/gldns/rrdef.h b/src/gldns/rrdef.h index b13580ea..f00fa33c 100644 --- a/src/gldns/rrdef.h +++ b/src/gldns/rrdef.h @@ -195,7 +195,7 @@ enum gldns_enum_rr_type GLDNS_RR_TYPE_TALINK = 58, GLDNS_RR_TYPE_CDS = 59, /** RFC 7344 */ GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */ - GLDNS_RR_TYPE_OPENPGPKEY = 61, /* draft-ietf-dane-openpgpkey */ + GLDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ diff --git a/src/gldns/wire2str.h b/src/gldns/wire2str.h index 050fb8e7..a4409991 100644 --- a/src/gldns/wire2str.h +++ b/src/gldns/wire2str.h @@ -118,7 +118,7 @@ int gldns_str_print(char** str, size_t* slen, const char* format, ...) * @param str_len: the size of the string buffer. If more is needed, it'll * silently truncate the output to fit in the buffer. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_pkt_buf(uint8_t* data, size_t data_len, char* str, size_t str_len); @@ -351,7 +351,7 @@ int gldns_wire2str_edns_option_code_print(char** str, size_t* str_len, * @param str_len: the size of the string buffer. If more is needed, it'll * silently truncate the output to fit in the buffer. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str, size_t str_len); @@ -369,7 +369,7 @@ int gldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str, * @param str_len: the size of the string buffer. If more is needed, it'll * silently truncate the output to fit in the buffer. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str, size_t str_len); @@ -389,7 +389,7 @@ int gldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str, * @param str_len: the size of the string buffer. If more is needed, it'll * silently truncate the output to fit in the buffer. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len, char* str, size_t str_len); @@ -406,7 +406,7 @@ int gldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len, * silently truncate the output to fit in the buffer. * @param rrtype: rr type of the data * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, size_t str_len, uint16_t rrtype); @@ -417,7 +417,7 @@ int gldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, * @param str: the string to write to. * @param len: length of str. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len); @@ -427,7 +427,7 @@ int gldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len); * @param str: the string to write to. * @param len: length of str. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len); @@ -437,7 +437,7 @@ int gldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len); * @param str: the string to write to. * @param len: length of str. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rcode_buf(int rcode, char* str, size_t len); @@ -448,7 +448,7 @@ int gldns_wire2str_rcode_buf(int rcode, char* str, size_t len); * @param str: the string to write to. * @param len: length of string. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_dname_buf(uint8_t* dname, size_t dname_len, char* str, size_t len); diff --git a/src/pubkey-pinning.c b/src/pubkey-pinning.c index 8a2250d8..32497608 100644 --- a/src/pubkey-pinning.c +++ b/src/pubkey-pinning.c @@ -56,6 +56,10 @@ #include "context.h" #include "util-internal.h" +#ifndef X509_STORE_CTX_get0_untrusted +#define X509_STORE_CTX_get0_untrusted(store) store->untrusted +#endif + /* we only support sha256 at the moment. adding support for another digest is more complex than just adding another entry here. in particular, you'll probably need a match for a particular cert @@ -314,11 +318,11 @@ _get_ssl_getdns_upstream_idx() { static volatile int idx = -1; if (idx < 0) { - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + /* CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); */ if (idx < 0) idx = SSL_get_ex_new_index(0, "associated getdns upstream", NULL,NULL,NULL); - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + /* CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); */ } return idx; } @@ -383,7 +387,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, /* TODO: how do we handle raw public keys? */ - for (i = 0; i < sk_X509_num(store->untrusted); i++) { + for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++) { if (i > 0) { /* TODO: how do we ensure that the certificates in * each stage appropriately sign the previous one? @@ -392,7 +396,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, return GETDNS_RETURN_GENERIC_ERROR; } - x = sk_X509_value(store->untrusted, i); + 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, __FUNCTION__, i); diff --git a/src/types-internal.h b/src/types-internal.h index bd1f993c..b9d229e6 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -67,13 +67,6 @@ typedef enum getdns_auth_state { #define GETDNS_STR_AUTH_FAILED "Failed" #define GETDNS_STR_AUTH_OK "Success" -static char* -getdns_auth_str_array[] = { - GETDNS_STR_AUTH_NONE, - GETDNS_STR_AUTH_FAILED, - GETDNS_STR_AUTH_OK -}; - struct getdns_context; struct getdns_upstreams; struct getdns_upstream; diff --git a/src/util/val_secalgo.c b/src/util/val_secalgo.c index edbf538b..a27e7807 100644 --- a/src/util/val_secalgo.c +++ b/src/util/val_secalgo.c @@ -590,7 +590,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, log_err("EVP_MD_CTX_new: malloc failure"); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); - else if(docrypto_free) CRYPTO_free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); return 0; } if(EVP_VerifyInit(ctx, digest_type) == 0) { @@ -598,7 +598,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); - else if(docrypto_free) CRYPTO_free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); return 0; } if(EVP_VerifyUpdate(ctx, (unsigned char*)gldns_buffer_begin(buf), @@ -607,7 +607,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); - else if(docrypto_free) CRYPTO_free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); return 0; } @@ -621,7 +621,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_PKEY_free(evp_key); if(dofree) free(sigblock); - else if(docrypto_free) CRYPTO_free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); if(res == 1) { return 1; @@ -1359,6 +1359,7 @@ _getdns_dnskey_algo_id_is_supported(int id) } } +#ifdef USE_DSA static char * _verify_nettle_dsa(gldns_buffer* buf, unsigned char* sigblock, unsigned int sigblock_len, unsigned char* key, unsigned int keylen) @@ -1446,6 +1447,7 @@ _verify_nettle_dsa(gldns_buffer* buf, unsigned char* sigblock, else return NULL; } +#endif /* USE_DSA */ static char * _verify_nettle_rsa(gldns_buffer* buf, unsigned int digest_size, char* sigblock, From 3f965e68c021d3e6bbf17053c4a1af87a744a9c1 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 14 Oct 2016 12:02:23 +0200 Subject: [PATCH 009/249] Stubby is getdns_query with a different name --- Makefile.in | 19 ++++++++++++++----- configure.ac | 24 ++++++++++++++++++++---- src/Makefile.in | 3 +++ src/tools/Makefile.in | 14 ++++++++++++-- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/Makefile.in b/Makefile.in index b0a478a2..2ccf05b5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -44,7 +44,7 @@ libdir = @libdir@ srcdir = @srcdir@ INSTALL = @INSTALL@ -all : default @GETDNS_QUERY@ +all : default @GETDNS_QUERY@ @STUBBY@ everything: default cd src/test && $(MAKE) @@ -52,7 +52,7 @@ everything: default default: cd src && $(MAKE) $@ -install: all getdns.pc getdns_ext_event.pc @INSTALL_GETDNS_QUERY@ +install: all getdns.pc getdns_ext_event.pc @INSTALL_GETDNS_QUERY@ @INSTALL_STUBBY@ $(INSTALL) -m 755 -d $(DESTDIR)$(docdir) $(INSTALL) -m 644 $(srcdir)/AUTHORS $(DESTDIR)$(docdir) $(INSTALL) -m 644 $(srcdir)/ChangeLog $(DESTDIR)$(docdir) @@ -87,7 +87,7 @@ install: all getdns.pc getdns_ext_event.pc @INSTALL_GETDNS_QUERY@ @echo "*** at package installation time from the post-install script." @echo "***" -uninstall: @UNINSTALL_GETDNS_QUERY@ +uninstall: @UNINSTALL_GETDNS_QUERY@ @UNINSTALL_STUBBY@ rm -rf $(DESTDIR)$(docdir) cd doc && $(MAKE) $@ cd src && $(MAKE) $@ @@ -104,6 +104,9 @@ test: getdns_query: cd src && $(MAKE) $@ +stubby: + cd src && $(MAKE) $@ + scratchpad: cd src && $(MAKE) $@ @@ -111,10 +114,16 @@ pad: scratchpad src/test/scratchpad || ./libtool exec gdb src/test/scratchpad install-getdns_query: - cd src/tools && $(MAKE) install + cd src/tools && $(MAKE) $@ uninstall-getdns_query: - cd src/tools && $(MAKE) uninstall + cd src/tools && $(MAKE) $@ + +install-stubby: + cd src/tools && $(MAKE) $@ + +uninstall-stubby: + cd src/tools && $(MAKE) $@ clean: cd src && $(MAKE) $@ diff --git a/configure.ac b/configure.ac index 031c618e..1cfca246 100644 --- a/configure.ac +++ b/configure.ac @@ -913,6 +913,26 @@ else INSTALL_GETDNS_QUERY="install-getdns_query" UNINSTALL_GETDNS_QUERY="uninstall-getdns_query" fi +AC_SUBST(GETDNS_QUERY) +AC_SUBST(INSTALL_GETDNS_QUERY) +AC_SUBST(UNINSTALL_GETDNS_QUERY) + +AC_ARG_WITH(stubby, AS_HELP_STRING([--without-stubby], + [Do not compile and install stubby, the (stub) resolver daemon]), + [], [withval="yes"]) +if test x_$withval = x_no; then + STUBBY="" + INSTALL_STUBBY="" + UNINSTALL_STUBBY="" +else + STUBBY="stubby" + INSTALL_STUBBY="install-stubby" + UNINSTALL_STUBBY="uninstall-stubby" +fi +AC_SUBST(STUBBY) +AC_SUBST(INSTALL_STUBBY) +AC_SUBST(UNINSTALL_STUBBY) + AC_ARG_WITH(fd-setsize, AS_HELP_STRING([--with-fd-setsize=size], [Set maximum file descriptor number that can be used by select]), [], [withval="no"]) @@ -925,10 +945,6 @@ case "$withval" in ;; esac -AC_SUBST(GETDNS_QUERY) -AC_SUBST(INSTALL_GETDNS_QUERY) -AC_SUBST(UNINSTALL_GETDNS_QUERY) - AC_CONFIG_FILES([Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile src/tools/Makefile doc/Makefile getdns.pc getdns_ext_event.pc]) if [ test -n "$DOXYGEN" ] then AC_CONFIG_FILES([src/Doxyfile]) diff --git a/src/Makefile.in b/src/Makefile.in index ecfcf082..763e22da 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -159,6 +159,9 @@ test: all getdns_query: all cd tools && $(MAKE) $@ +stubby: all + cd tools && $(MAKE) $@ + scratchpad: all cd test && $(MAKE) $@ diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index ae2c6080..9f1bb75f 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -67,13 +67,23 @@ $(ALL_OBJS): getdns_query: getdns_query.lo $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS) -install: getdns_query +stubby: getdns_query + ln -s getdns_query stubby + +install-getdns_query: getdns_query $(INSTALL) -m 755 -d $(DESTDIR)$(bindir) $(LIBTOOL) --mode=install cp getdns_query $(DESTDIR)$(bindir) -uninstall: +uninstall-getdns_query: $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/getdns_query +install-stubby: getdns_query + $(INSTALL) -m 755 -d $(DESTDIR)$(bindir) + $(LIBTOOL) --mode=install cp getdns_query $(DESTDIR)$(bindir)/stubby + +uninstall-stubby: + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/stubby + clean: rm -f *.o *.lo $(PROGRAMS) rm -rf .libs From 58b5ead67aa44fe25535fa9073fcadc1f5ff0056 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 14 Oct 2016 08:24:25 -0500 Subject: [PATCH 010/249] Make stubby act as stubby --- src/tools/getdns_query.c | 153 +++++++++++++++++++++++++++------------ 1 file changed, 107 insertions(+), 46 deletions(-) diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 7acc77d9..abd91471 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -48,6 +48,12 @@ typedef unsigned short in_port_t; #define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\"" +static int i_am_stubby = 0; +static const char *default_stubby_config = +"{ resolution_type: GETDNS_RESOLUTION_STUB" +", listen_addresses: [ { 127.0.0.1:53 } ]" +"}"; +static int clear_listen_list_on_arg = 0; static int quiet = 0; static int batch_mode = 0; static char *query_file = NULL; @@ -469,6 +475,48 @@ static void parse_config(const char *config_str) } } +int parse_config_file(const char *fn, int report_open_failure) +{ + FILE *fh; + char *config_file = NULL; + long config_file_sz; + + if (!(fh = fopen(fn, "r"))) { + if (report_open_failure) + fprintf( stderr, "Could not open \"%s\": %s\n" + , fn, strerror(errno)); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (fseek(fh, 0,SEEK_END) == -1) { + perror("fseek"); + fclose(fh); + return GETDNS_RETURN_GENERIC_ERROR; + } + config_file_sz = ftell(fh); + if (config_file_sz <= 0) { + /* Empty config is no config */ + fclose(fh); + return GETDNS_RETURN_GOOD; + } + if (!(config_file = malloc(config_file_sz + 1))){ + fclose(fh); + fprintf(stderr, "Could not allocate memory for \"%s\"\n", fn); + return GETDNS_RETURN_MEMORY_ERROR; + } + rewind(fh); + if (fread(config_file, 1, config_file_sz, fh) != config_file_sz) { + fprintf( stderr, "An error occurred while reading \"%s\": %s\n" + , fn, strerror(errno)); + fclose(fh); + return GETDNS_RETURN_MEMORY_ERROR; + } + config_file[config_file_sz] = 0; + fclose(fh); + parse_config(config_file); + free(config_file); + return GETDNS_RETURN_GOOD; +} + getdns_return_t parse_args(int argc, char **argv) { getdns_return_t r = GETDNS_RETURN_GOOD; @@ -483,8 +531,6 @@ getdns_return_t parse_args(int argc, char **argv) getdns_bindata bindata; size_t upstream_count = 0; FILE *fh; - char *config_file = NULL; - long config_file_sz; for (i = 1; i < argc; i++) { arg = argv[i]; @@ -595,42 +641,7 @@ getdns_return_t parse_args(int argc, char **argv) "after -C\n"); return GETDNS_RETURN_GENERIC_ERROR; } - if (!(fh = fopen(argv[i], "r"))) { - fprintf(stderr, "Could not open \"%s\"" - ": %s\n",argv[i], strerror(errno)); - return GETDNS_RETURN_GENERIC_ERROR; - } - if (fseek(fh, 0,SEEK_END) == -1) { - perror("fseek"); - fclose(fh); - return GETDNS_RETURN_GENERIC_ERROR; - } - config_file_sz = ftell(fh); - if (config_file_sz <= 0) { - /* Empty config is no config */ - fclose(fh); - break; - } - if (!(config_file=malloc(config_file_sz + 1))){ - fclose(fh); - fprintf(stderr, "Could not allocate me" - "mory for \"%s\"\n", argv[i]); - return GETDNS_RETURN_MEMORY_ERROR; - } - rewind(fh); - if (fread(config_file, 1, config_file_sz, fh) - != config_file_sz) { - fprintf(stderr, "An error occurred whil" - "e reading \"%s\": %s\n",argv[i], - strerror(errno)); - fclose(fh); - return GETDNS_RETURN_MEMORY_ERROR; - } - config_file[config_file_sz] = 0; - fclose(fh); - parse_config(config_file); - free(config_file); - config_file = NULL; + (void) parse_config_file(argv[i], 1); break; case 'D': (void) getdns_context_set_edns_do_bit(context, 1); @@ -927,17 +938,23 @@ getdns_return_t parse_args(int argc, char **argv) "expected after -z\n"); return GETDNS_RETURN_GENERIC_ERROR; } - if (argv[i][0] == '-' && argv[i][1] == '\0') { + if (clear_listen_list_on_arg || + (argv[i][0] == '-' && argv[i][1] == '\0')) { if (listen_list && !listen_dict) getdns_list_destroy( listen_list); listen_list = NULL; listen_count = 0; - touched_listen_list = 1; - DEBUG_SERVER("Clear listen list\n"); - break; + if (!clear_listen_list_on_arg) { + touched_listen_list = 1; + DEBUG_SERVER("Clear listen list\n"); + break; + } else if (listen_dict) { + getdns_dict_destroy(listen_dict); + listen_dict = NULL; + } + clear_listen_list_on_arg = 0; } - if ((r = getdns_str2dict(argv[i], &downstream))) fprintf(stderr, "Could not convert \"%s\" to " "an IP dict: %s\n", argv[i], @@ -1002,7 +1019,24 @@ next: ; if (print_api_info) { getdns_dict *api_information = getdns_context_get_api_information(context); - char *api_information_str = + char *api_information_str; + + if (listen_dict && !getdns_dict_get_list( + listen_dict, "listen_list", &listen_list)) { + + (void) getdns_dict_set_list(api_information, + "listen_addresses", listen_list); + } else if (listen_list) { + (void) getdns_dict_set_list(api_information, + "listen_addresses", listen_list); + + } else if ((listen_list = getdns_list_create())) { + (void) getdns_dict_set_list(api_information, + "listen_addresses", listen_list); + getdns_list_destroy(listen_list); + listen_list = NULL; + } + api_information_str = getdns_pretty_print_dict(api_information); fprintf(stdout, "%s\n", api_information_str); free(api_information_str); @@ -1531,7 +1565,17 @@ error: int main(int argc, char **argv) { + char home_stubby_conf_fn[1024]; getdns_return_t r; +#ifndef USE_WINSOCK + char *prg_name = strrchr(argv[0], '/'); +#else + char *prg_name = strrchr(argv[0], '\\'); +#endif + prg_name = prg_name ? prg_name + 1 : argv[0]; + + i_am_stubby = strcasecmp(prg_name, "stubby") == 0 + || strcasecmp(prg_name, "lt-stubby") == 0; name = the_root; if ((r = getdns_context_create(&context, 1))) { @@ -1546,8 +1590,20 @@ main(int argc, char **argv) r = GETDNS_RETURN_MEMORY_ERROR; goto done_destroy_context; } + if (i_am_stubby) { + (void) parse_config(default_stubby_config); + (void) parse_config_file("/etc/stubby.conf", 0); + if (snprintf( home_stubby_conf_fn, sizeof(home_stubby_conf_fn) + , "%s/.stubby.conf", getenv("HOME") + ) < sizeof(home_stubby_conf_fn)) { + + (void) parse_config_file(home_stubby_conf_fn, 0); + } + clear_listen_list_on_arg = 1; + } if ((r = parse_args(argc, argv))) goto done_destroy_context; + clear_listen_list_on_arg = 0; if (query_file) { fp = fopen(query_file, "rt"); @@ -1564,8 +1620,10 @@ main(int argc, char **argv) assert(loop); } if (listen_count && (r = getdns_context_set_listen_addresses( - context, incoming_request_handler, listen_list))) + context, incoming_request_handler, listen_list))) { + perror("error: Could not bind on given addresses"); goto done_destroy_context; + } /* Make the call */ if (interactive) { @@ -1606,7 +1664,10 @@ done_destroy_context: return 0; else if (r == CONTINUE_ERROR) return 1; - fprintf(stdout, "\nAll done.\n"); + + if (!i_am_stubby || !r) { + fprintf(stdout, "\nAll done.\n"); + } return r; } From 3d356bd35e2a218be95b5e328779db6b27046045 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 14 Oct 2016 09:51:17 -0500 Subject: [PATCH 011/249] Stubby runs in background by default --- src/tools/getdns_query.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index abd91471..665c9ee1 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -54,6 +54,7 @@ static const char *default_stubby_config = ", listen_addresses: [ { 127.0.0.1:53 } ]" "}"; static int clear_listen_list_on_arg = 0; +static int run_in_foreground = 0; static int quiet = 0; static int batch_mode = 0; static char *query_file = NULL; @@ -203,6 +204,8 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-e \tSet idle timeout in miliseconds\n"); fprintf(out, "\t-F \tread the queries from the specified file\n"); fprintf(out, "\t-f \tRead DNSSEC trust anchors from \n"); + if (i_am_stubby) + fprintf(out, "\t-g\tRun stubby in foreground\n"); fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-H\thostname lookup. ( must be an IP address; is ignored)\n"); fprintf(out, "\t-h\tPrint this help\n"); @@ -983,6 +986,10 @@ getdns_return_t parse_args(int argc, char **argv) } break; default: + if (i_am_stubby && *c == 'g') { + run_in_foreground = 1; + break; + } fprintf(stderr, "Unknown option " "\"%c\"\n", *c); for (i = 0; i < argc; i++) @@ -1642,7 +1649,25 @@ main(int argc, char **argv) } else if (listen_count) { assert(loop); - loop->vmt->run(loop); + if (i_am_stubby && !run_in_foreground) { + pid_t pid = fork(); + if (pid == -1) { + perror("Could not fork of stubby daemon\n"); + r = GETDNS_RETURN_GENERIC_ERROR; + + } else if (pid) { + FILE *fh = fopen("/var/rub/stubby.pid", "w"); + if (! fh) + fh = fopen("/tmp/stubby.pid", "w"); + if (fh) { + fprintf(fh, "%d", (int)pid); + fclose(fh); + batch_mode = 0; + } + } else + loop->vmt->run(loop); + } else + loop->vmt->run(loop); } else r = do_the_call(); @@ -1665,10 +1690,8 @@ done_destroy_context: else if (r == CONTINUE_ERROR) return 1; - if (!i_am_stubby || !r) { + if (!i_am_stubby) fprintf(stdout, "\nAll done.\n"); - } + return r; } - - From ec04dc21ee02a289f85be75f25080a069d5c5a83 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 14 Oct 2016 10:14:38 -0500 Subject: [PATCH 012/249] Stubby defaults in help text --- src/tools/getdns_query.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 665c9ee1..51da2d94 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -199,13 +199,17 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t\tRead settings from config file \n"); fprintf(out, "\t\tThe getdns context will be configured with these settings\n"); fprintf(out, "\t\tThe file must be in json dict format.\n"); + if (i_am_stubby) { + fprintf(out, "\t\tBy default, configuration is first read from"); + fprintf(out, "\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\""); + } fprintf(out, "\t-D\tSet edns0 do bit\n"); fprintf(out, "\t-d\tclear edns0 do bit\n"); fprintf(out, "\t-e \tSet idle timeout in miliseconds\n"); fprintf(out, "\t-F \tread the queries from the specified file\n"); fprintf(out, "\t-f \tRead DNSSEC trust anchors from \n"); if (i_am_stubby) - fprintf(out, "\t-g\tRun stubby in foreground\n"); + fprintf(out, "\t-g\tRun stubby in foreground (default is background)\n"); fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-H\thostname lookup. ( must be an IP address; is ignored)\n"); fprintf(out, "\t-h\tPrint this help\n"); @@ -221,9 +225,11 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-p\tPretty print response dict\n"); fprintf(out, "\t-P \tPad TLS queries to a multiple of blocksize\n"); fprintf(out, "\t-q\tQuiet mode - don't print response\n"); - fprintf(out, "\t-r\tSet recursing resolution type\n"); + fprintf( out, "\t-r\tSet recursing resolution type%s\n" + , i_am_stubby ? "(default = stub)" : ""); fprintf(out, "\t-R \tRead root hints from \n"); - fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n"); + fprintf(out, "\t-s\tSet stub resolution type%s\n" + , i_am_stubby ? "" : "(default = recursing)" ); fprintf(out, "\t-S\tservice lookup ( is ignored)\n"); fprintf(out, "\t-t \tSet timeout in miliseconds\n"); fprintf(out, "\t-x\tDo not follow redirects\n"); @@ -248,6 +254,8 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t\tListen for DNS requests on the given IP address\n"); fprintf(out, "\t\t is in the same format as upstreams.\n"); fprintf(out, "\t\tThis option can be given more than once.\n"); + if (i_am_stubby) + fprintf(out, "\t\t(default is to listen on 127.0.0.1:53)\n"); } static getdns_return_t validate_chain(getdns_dict *response) From 0fa8152bb6f186ccf47212645619503e6e97a63e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 15 Oct 2016 06:07:33 -0500 Subject: [PATCH 013/249] Bump version to alpha 2 -a2 (with dash) to be semver format compliant --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1cfca246..e6f8f1ab 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/pkg.m4) AC_INIT([getdns], [1.1.0], [users@getdnsapi.net], [], [https://getdnsapi.net]) -AC_SUBST(RELEASE_CANDIDATE, [a1]) +AC_SUBST(RELEASE_CANDIDATE, [-a2]) # Set current date from system if not set AC_ARG_WITH([current-date], From 838375fe66e707e584b991132cd7d15904f31b2e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 16 Oct 2016 05:32:05 -0500 Subject: [PATCH 014/249] Run stubby in foreground by default --- src/tools/getdns_query.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 51da2d94..9ec3beb4 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -54,7 +54,7 @@ static const char *default_stubby_config = ", listen_addresses: [ { 127.0.0.1:53 } ]" "}"; static int clear_listen_list_on_arg = 0; -static int run_in_foreground = 0; +static int run_in_foreground = 1; static int quiet = 0; static int batch_mode = 0; static char *query_file = NULL; @@ -209,7 +209,7 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-F \tread the queries from the specified file\n"); fprintf(out, "\t-f \tRead DNSSEC trust anchors from \n"); if (i_am_stubby) - fprintf(out, "\t-g\tRun stubby in foreground (default is background)\n"); + fprintf(out, "\t-g\tRun stubby in background (default is foreground)\n"); fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-H\thostname lookup. ( must be an IP address; is ignored)\n"); fprintf(out, "\t-h\tPrint this help\n"); @@ -995,7 +995,7 @@ getdns_return_t parse_args(int argc, char **argv) break; default: if (i_am_stubby && *c == 'g') { - run_in_foreground = 1; + run_in_foreground = 0; break; } fprintf(stderr, "Unknown option " From 05fb6edfcb6a5d5470bc92038941640f5337322c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 16 Oct 2016 05:39:04 -0500 Subject: [PATCH 015/249] Linking to allow running stubby from src/tools --- src/tools/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index 9f1bb75f..b1a25720 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -67,8 +67,8 @@ $(ALL_OBJS): getdns_query: getdns_query.lo $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS) -stubby: getdns_query - ln -s getdns_query stubby +stubby: getdns_query.lo + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS) install-getdns_query: getdns_query $(INSTALL) -m 755 -d $(DESTDIR)$(bindir) From 732844eeaa1e3a82b7cb200b333567e81034f7ab Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 16 Oct 2016 09:46:02 -0500 Subject: [PATCH 016/249] Correct default config --- src/tools/getdns_query.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 9ec3beb4..dc148e35 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -51,7 +51,7 @@ typedef unsigned short in_port_t; static int i_am_stubby = 0; static const char *default_stubby_config = "{ resolution_type: GETDNS_RESOLUTION_STUB" -", listen_addresses: [ { 127.0.0.1:53 } ]" +", listen_addresses: [ 127.0.0.1@53, 0::1@53 ]" "}"; static int clear_listen_list_on_arg = 0; static int run_in_foreground = 1; From bc70b2941673173379612797b7108d892f14192b Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 19 Oct 2016 07:30:31 -0500 Subject: [PATCH 017/249] Stubby release --- ChangeLog | 7 +++++++ src/convert.c | 1 - src/tools/getdns_query.c | 17 +++++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1adfe0b6..c7397ee2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +* 2016-10-19: Version 1.1.0-a2 + * Improved TLS connection management + * OpenSSL 1.1 support + * Stubby, Server version of getdns_query that by default listens + on 127.0.0.1 and ::1 and reads config from /etc/stubby.conf + and $HOME/.stubby.conf + * 2016-07-14: Version 1.1.0a1 * Conversion functions from text strings to getdns native types: getdns_str2dict(), getdns_str2list(), getdns_str2bindata() and diff --git a/src/convert.c b/src/convert.c index f0b4251d..24dbbf03 100644 --- a/src/convert.c +++ b/src/convert.c @@ -830,7 +830,6 @@ _getdns_reply_dict2wire( } } remove_dnssec = !getdns_dict_get_int(reply, "/header/do", &n) && n == 0; - DEBUG_SERVER("remove_dnssec: %d\n", remove_dnssec); if (!getdns_dict_get_list(reply, "answer", §ion)) { for ( n = 0, i = 0 diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index dc148e35..48a4d721 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -51,6 +51,7 @@ typedef unsigned short in_port_t; static int i_am_stubby = 0; static const char *default_stubby_config = "{ resolution_type: GETDNS_RESOLUTION_STUB" +", idle_timeout: 10000" ", listen_addresses: [ 127.0.0.1@53, 0::1@53 ]" "}"; static int clear_listen_list_on_arg = 0; @@ -1328,9 +1329,21 @@ static void request_cb( getdns_return_t r = GETDNS_RETURN_GOOD; uint32_t n, rcode, dnssec_status; +#if defined(SERVER_DEBUG) && SERVER_DEBUG + getdns_bindata *qname; + char *qname_str, *unknown_qname = ""; + + if (getdns_dict_get_bindata(msg->request, "/question/qname", &qname) + || getdns_convert_dns_name_to_fqdn(qname, &qname_str)) + qname_str = unknown_qname; + DEBUG_SERVER("reply for: %p %"PRIu64" %d (edns0: %d, do: %d, ad: %d," - " cd: %d)\n", msg, transaction_id, (int)callback_type, - msg->has_edns0, msg->do_bit, msg->ad_bit, msg->cd_bit); + " cd: %d, qname: %s)\n", msg, transaction_id, (int)callback_type, + msg->has_edns0, msg->do_bit, msg->ad_bit, msg->cd_bit, qname_str); + + if (qname_str != unknown_qname) + free(qname_str); +#endif assert(msg); #if 0 From a0ae9130cc815dd8b82362de6ff5a89330aa5c39 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 21 Oct 2016 14:18:24 +0100 Subject: [PATCH 018/249] Fix issue with session re-use making authentication appear to fail --- src/context.c | 15 +++++++++------ src/context.h | 3 ++- src/stub.c | 25 ++++++++++++++++++++----- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/context.c b/src/context.c index ff172499..9adcc8f5 100644 --- a/src/context.c +++ b/src/context.c @@ -710,19 +710,20 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) /* Update total stats for the upstream.*/ upstream->total_responses+=upstream->responses_received; upstream->total_timeouts+=upstream->responses_timeouts; - /* Pick up the auth state if it is of interest*/ - if (upstream->tls_auth_state != GETDNS_AUTH_NONE) - upstream->past_tls_auth_state = upstream->tls_auth_state; - + /* Need the last auth state when using session resumption*/ + upstream->last_tls_auth_state = upstream->tls_auth_state; + /* Keep track of the best auth state this upstream has had*/ + if (upstream->tls_auth_state > upstream->best_tls_auth_state) + upstream->best_tls_auth_state = upstream->tls_auth_state; #if defined(DAEMON_DEBUG) && DAEMON_DEBUG DEBUG_DAEMON("%s %s : Conn closed: Conn stats - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->responses_received, (int)upstream->responses_timeouts, getdns_auth_str_array[upstream->tls_auth_state], (int)upstream->keepalive_timeout); - DEBUG_DAEMON("%s %s : Upstream stats - Resp=%d,Timeouts=%d,Auth=%s,Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", + DEBUG_DAEMON("%s %s : Upstream stats - Resp=%d,Timeouts=%d,Best_auth=%s,Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->total_responses, (int)upstream->total_timeouts, - getdns_auth_str_array[upstream->tls_auth_state], + getdns_auth_str_array[upstream->best_tls_auth_state], (int)upstream->conn_completed, (int)upstream->conn_setup_failed, (int)upstream->conn_shutdowns, (int)upstream->conn_backoffs); #endif @@ -908,6 +909,8 @@ upstream_init(getdns_upstream *upstream, upstream->tls_hs_state = GETDNS_HS_NONE; upstream->tls_auth_name[0] = '\0'; upstream->tls_auth_state = GETDNS_AUTH_NONE; + upstream->last_tls_auth_state = GETDNS_AUTH_NONE; + upstream->best_tls_auth_state = GETDNS_AUTH_NONE; upstream->tls_pubkey_pinset = NULL; upstream->loop = NULL; (void) getdns_eventloop_event_init( diff --git a/src/context.h b/src/context.h index 8d192d39..41e7a830 100644 --- a/src/context.h +++ b/src/context.h @@ -147,7 +147,8 @@ typedef struct getdns_upstream { size_t conn_backoffs; size_t total_responses; size_t total_timeouts; - getdns_auth_state_t past_tls_auth_state; + getdns_auth_state_t best_tls_auth_state; + getdns_auth_state_t last_tls_auth_state; /* These are per connection. */ getdns_conn_state_t conn_state; size_t queries_sent; diff --git a/src/stub.c b/src/stub.c index e496d61d..bb18f68b 100644 --- a/src/stub.c +++ b/src/stub.c @@ -954,6 +954,20 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) SSL_set_connect_state(ssl); (void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + + /* Session resumption. There are trade-offs here. Want to do it when + possible only if we have the right type of connection. Note a change + to the upstream auth info creates a new upstream so never re-uses.*/ + if (upstream->tls_session != NULL) { + if ((upstream->tls_fallback_ok == 0 && + upstream->last_tls_auth_state == GETDNS_AUTH_OK) || + upstream->tls_fallback_ok == 1) { + SSL_set_session(ssl, upstream->tls_session); + DEBUG_STUB("%s %-35s: Attempting session re-use\n", STUB_DEBUG_SETUP_TLS, + __FUNCTION__); + } + } + return ssl; } @@ -995,6 +1009,9 @@ tls_do_handshake(getdns_upstream *upstream) upstream->tls_hs_state = GETDNS_HS_DONE; upstream->conn_state = GETDNS_CONN_OPEN; upstream->conn_completed++; + /* A re-used session is not verified so need to fix up state in that case */ + if (SSL_session_reused(upstream->tls_obj)) + upstream->tls_auth_state = upstream->last_tls_auth_state; DEBUG_STUB("%s %-35s: FD: %d Handshake succeeded with auth state %d. Session is %s.\n", STUB_DEBUG_SETUP_TLS, __FUNCTION__, upstream->fd, upstream->tls_auth_state, SSL_session_reused(upstream->tls_obj) ?"re-used":"new"); @@ -1598,8 +1615,8 @@ upstream_valid(getdns_upstream *upstream, /* We need to check past authentication history to see if this is usable for TLS.*/ if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED) return 1; - return ((upstream->past_tls_auth_state == GETDNS_AUTH_OK || - upstream->past_tls_auth_state == GETDNS_AUTH_NONE) ? 1 : 0); + return ((upstream->best_tls_auth_state == GETDNS_AUTH_OK || + upstream->best_tls_auth_state == GETDNS_AUTH_NONE) ? 1 : 0); } static int @@ -1654,7 +1671,7 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra upstreams we may have no valid upstream at all (in contrast to UDP). This will be better communicated to the user when we have better error codes*/ for (i = 0; i < upstreams->count; i++) { - DEBUG_STUB("%s %-35s: Testing %d %d\n", STUB_DEBUG_SETUP, + DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP, __FUNCTION__, (int)i, (int)upstreams->upstreams[i].conn_state); if (upstream_valid(&upstreams->upstreams[i], transport, netreq)) { upstream = &upstreams->upstreams[i]; @@ -1744,8 +1761,6 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, close(fd); return -1; } - if (upstream->tls_session != NULL) - SSL_set_session(upstream->tls_obj, upstream->tls_session); upstream->tls_hs_state = GETDNS_HS_WRITE; } upstream->conn_state = GETDNS_CONN_SETUP; From cbe451274ba798284a3bef53751fe17b37327140 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 25 Oct 2016 11:09:37 +0200 Subject: [PATCH 019/249] Bump version --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e6f8f1ab..cbee6fa7 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/pkg.m4) AC_INIT([getdns], [1.1.0], [users@getdnsapi.net], [], [https://getdnsapi.net]) -AC_SUBST(RELEASE_CANDIDATE, [-a2]) +AC_SUBST(RELEASE_CANDIDATE, [-alpha3]) # Set current date from system if not set AC_ARG_WITH([current-date], From 4ea4f68467572810494a608ca678d475636d4d85 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 26 Oct 2016 15:29:07 +0200 Subject: [PATCH 020/249] Get_suffix, no '\0' in returned strings Resolves issue #203 --- src/context.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/context.c b/src/context.c index a93e6f14..8186bf21 100644 --- a/src/context.c +++ b/src/context.c @@ -3698,8 +3698,7 @@ getdns_context_get_suffix(getdns_context *context, getdns_list **value) r = GETDNS_RETURN_GENERIC_ERROR; break; } - if ((r = _getdns_list_append_const_bindata( - list, strlen(name) + 1, name))) + if ((r = _getdns_list_append_string(list, name))) break; dname += dname_len; dname_len = *dname++; From 3fa34dcfcad984a9d4a287a31b20b00a7ca80d4b Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 26 Oct 2016 15:52:22 +0200 Subject: [PATCH 021/249] Mention the actual missing dependencies --- configure.ac | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index b2c066a2..d6b396f9 100644 --- a/configure.ac +++ b/configure.ac @@ -552,10 +552,16 @@ fi # Checks for libraries. found_all_libs=1 +MISSING_DEPS="" +MISSING_SEP="" if test $my_with_libidn = 1 then AC_MSG_NOTICE([Checking for dependency libidn]) - AC_CHECK_LIB([idn], [idna_to_ascii_8z], [], [found_all_libs=0]) + AC_CHECK_LIB([idn], [idna_to_ascii_8z], [], [ + MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libidn" + MISSING_SEP=", " + found_all_libs=0 + ]) fi AC_ARG_ENABLE(unbound-event-api, AC_HELP_STRING([--disable-unbound-event-api], [Disable usage of libunbounds event API])) @@ -584,12 +590,16 @@ then ]) fi AC_CHECK_FUNCS([ub_ctx_set_stub]) - ], [found_all_libs=0]) + ], [ + MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libunbound" + MISSING_SEP=", " + found_all_libs=0 + ]) fi if test $found_all_libs = 0 then - AC_MSG_ERROR([One more dependencies is missing]) + AC_MSG_ERROR([Missing dependencies: $MISSING_DEPS]) fi AC_PATH_PROG([DOXYGEN], [doxygen]) From 393b24fe894312605801141718b3e6f5195cf1bd Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 26 Oct 2016 14:32:35 +0000 Subject: [PATCH 022/249] pthread-based locking for arc4random --- configure.ac | 2 +- src/compat/arc4_lock.c | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index b2c066a2..90a27d04 100644 --- a/configure.ac +++ b/configure.ac @@ -644,7 +644,7 @@ CHECK_CFLAGS="" PKG_CHECK_MODULES([CHECK],[check >= 0.9.6],[CHECK_GETDNS="check_getdns"],[ AC_SEARCH_LIBS([floor], [m]) AC_SEARCH_LIBS([timer_create], [rt]) -AC_SEARCH_LIBS([pthread_create], [pthread]) +AC_SEARCH_LIBS([pthread_create], [pthread], [AC_DEFINE([HAVE_PTHREADS], [1], [Define if pthreads exist.])]) AC_SEARCH_LIBS([srunner_create],[check check_pic],[ CHECK_GETDNS="check_getdns" CHECK_LIBS="$LIBS"],[ diff --git a/src/compat/arc4_lock.c b/src/compat/arc4_lock.c index 44662841..facf9575 100644 --- a/src/compat/arc4_lock.c +++ b/src/compat/arc4_lock.c @@ -34,6 +34,23 @@ #include "config.h" #define LOCKRET(func) func +#ifdef HAVE_PTHREADS +#include "pthread.h" + +static pthread_mutex_t arc_lock = PTHREAD_MUTEX_INITIALIZER; + +void _ARC4_LOCK(void) +{ + pthread_mutex_lock(&arc_lock); +} + +void _ARC4_UNLOCK(void) +{ + pthread_mutex_unlock(&arc_lock); +} + +#else +/* XXX - add windows-(or at least non pthread) specific lock routines here */ void _ARC4_LOCK(void) { } @@ -41,4 +58,4 @@ void _ARC4_LOCK(void) void _ARC4_UNLOCK(void) { } - +#endif From db6cee94fa537bff05f6a01a92b3cbb322adc4dc Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 26 Oct 2016 15:47:44 +0000 Subject: [PATCH 023/249] Fix HAVE_PTHREADS define in configure.ac --- configure.ac | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 90a27d04..e8a1650b 100644 --- a/configure.ac +++ b/configure.ac @@ -644,7 +644,7 @@ CHECK_CFLAGS="" PKG_CHECK_MODULES([CHECK],[check >= 0.9.6],[CHECK_GETDNS="check_getdns"],[ AC_SEARCH_LIBS([floor], [m]) AC_SEARCH_LIBS([timer_create], [rt]) -AC_SEARCH_LIBS([pthread_create], [pthread], [AC_DEFINE([HAVE_PTHREADS], [1], [Define if pthreads exist.])]) +AC_SEARCH_LIBS([pthread_create], [pthread]) AC_SEARCH_LIBS([srunner_create],[check check_pic],[ CHECK_GETDNS="check_getdns" CHECK_LIBS="$LIBS"],[ @@ -924,6 +924,10 @@ if [ test -n "$DOXYGEN" ] fi +#---- check for pthreads library +AC_SEARCH_LIBS([pthread_mutex_init],[pthread],[AC_DEFINE([HAVE_PTHREADS], [1], [Have pthreads library])], [AC_MSG_WARN([pthreads not available])]) + + dnl ----- dnl ----- Start of "Things needed for gldns" section dnl ----- From bb3d741f7a4513458d5f110a2748ee5f24e1b6de Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 13 Oct 2016 23:04:50 +0200 Subject: [PATCH 024/249] OpenSSL 1.1 support --- configure.ac | 1 + src/context.c | 9 +++++++++ src/gldns/keyraw.c | 39 +++++++++++++++++++++++++++++++++++++++ src/gldns/rrdef.h | 2 +- src/gldns/wire2str.h | 18 +++++++++--------- src/pubkey-pinning.c | 12 ++++++++---- src/util/val_secalgo.c | 10 ++++++---- 7 files changed, 73 insertions(+), 18 deletions(-) diff --git a/configure.ac b/configure.ac index d6b396f9..aa39c47c 100644 --- a/configure.ac +++ b/configure.ac @@ -245,6 +245,7 @@ else fi AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method]) AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [ AC_INCLUDES_DEFAULT diff --git a/src/context.c b/src/context.c index 8186bf21..8893191e 100644 --- a/src/context.c +++ b/src/context.c @@ -672,6 +672,15 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams) GETDNS_FREE(upstreams->mf, upstreams); } +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG +static char* +getdns_auth_str_array[] = { + GETDNS_STR_AUTH_NONE, + GETDNS_STR_AUTH_FAILED, + GETDNS_STR_AUTH_OK +}; +#endif + void _getdns_upstream_shutdown(getdns_upstream *upstream) { diff --git a/src/gldns/keyraw.c b/src/gldns/keyraw.c index 7a27e7f0..9e6adcb2 100644 --- a/src/gldns/keyraw.c +++ b/src/gldns/keyraw.c @@ -23,6 +23,15 @@ #ifdef HAVE_OPENSSL_ENGINE_H # include #endif +#ifdef HAVE_OPENSSL_BN_H +#include +#endif +#ifdef HAVE_OPENSSL_RSA_H +#include +#endif +#ifdef HAVE_OPENSSL_DSA_H +#include +#endif #endif /* HAVE_SSL */ size_t @@ -215,6 +224,7 @@ gldns_key_buf2dsa_raw(unsigned char* key, size_t len) BN_free(Y); return NULL; } +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #ifndef S_SPLINT_S dsa->p = P; dsa->q = Q; @@ -222,6 +232,25 @@ gldns_key_buf2dsa_raw(unsigned char* key, size_t len) dsa->pub_key = Y; #endif /* splint */ +#else /* OPENSSL_VERSION_NUMBER */ + if (!DSA_set0_pqg(dsa, P, Q, G)) { + /* QPG not yet attached, need to free */ + BN_free(Q); + BN_free(P); + BN_free(G); + + DSA_free(dsa); + BN_free(Y); + return NULL; + } + if (!DSA_set0_key(dsa, Y, NULL)) { + /* QPG attached, cleaned up by DSA_fre() */ + DSA_free(dsa); + BN_free(Y); + return NULL; + } +#endif + return dsa; } @@ -273,11 +302,21 @@ gldns_key_buf2rsa_raw(unsigned char* key, size_t len) BN_free(modulus); return NULL; } +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #ifndef S_SPLINT_S rsa->n = modulus; rsa->e = exponent; #endif /* splint */ +#else /* OPENSSL_VERSION_NUMBER */ + if (!RSA_set0_key(rsa, modulus, exponent, NULL)) { + BN_free(exponent); + BN_free(modulus); + RSA_free(rsa); + return NULL; + } +#endif + return rsa; } diff --git a/src/gldns/rrdef.h b/src/gldns/rrdef.h index b13580ea..f00fa33c 100644 --- a/src/gldns/rrdef.h +++ b/src/gldns/rrdef.h @@ -195,7 +195,7 @@ enum gldns_enum_rr_type GLDNS_RR_TYPE_TALINK = 58, GLDNS_RR_TYPE_CDS = 59, /** RFC 7344 */ GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */ - GLDNS_RR_TYPE_OPENPGPKEY = 61, /* draft-ietf-dane-openpgpkey */ + GLDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ diff --git a/src/gldns/wire2str.h b/src/gldns/wire2str.h index 050fb8e7..a4409991 100644 --- a/src/gldns/wire2str.h +++ b/src/gldns/wire2str.h @@ -118,7 +118,7 @@ int gldns_str_print(char** str, size_t* slen, const char* format, ...) * @param str_len: the size of the string buffer. If more is needed, it'll * silently truncate the output to fit in the buffer. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_pkt_buf(uint8_t* data, size_t data_len, char* str, size_t str_len); @@ -351,7 +351,7 @@ int gldns_wire2str_edns_option_code_print(char** str, size_t* str_len, * @param str_len: the size of the string buffer. If more is needed, it'll * silently truncate the output to fit in the buffer. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str, size_t str_len); @@ -369,7 +369,7 @@ int gldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str, * @param str_len: the size of the string buffer. If more is needed, it'll * silently truncate the output to fit in the buffer. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str, size_t str_len); @@ -389,7 +389,7 @@ int gldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str, * @param str_len: the size of the string buffer. If more is needed, it'll * silently truncate the output to fit in the buffer. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len, char* str, size_t str_len); @@ -406,7 +406,7 @@ int gldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len, * silently truncate the output to fit in the buffer. * @param rrtype: rr type of the data * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, size_t str_len, uint16_t rrtype); @@ -417,7 +417,7 @@ int gldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, * @param str: the string to write to. * @param len: length of str. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len); @@ -427,7 +427,7 @@ int gldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len); * @param str: the string to write to. * @param len: length of str. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len); @@ -437,7 +437,7 @@ int gldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len); * @param str: the string to write to. * @param len: length of str. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_rcode_buf(int rcode, char* str, size_t len); @@ -448,7 +448,7 @@ int gldns_wire2str_rcode_buf(int rcode, char* str, size_t len); * @param str: the string to write to. * @param len: length of string. * @return the number of characters for this element, excluding zerobyte. - * Is larger than str_len if output was truncated. + * Is larger or equal than str_len if output was truncated. */ int gldns_wire2str_dname_buf(uint8_t* dname, size_t dname_len, char* str, size_t len); diff --git a/src/pubkey-pinning.c b/src/pubkey-pinning.c index 8a2250d8..32497608 100644 --- a/src/pubkey-pinning.c +++ b/src/pubkey-pinning.c @@ -56,6 +56,10 @@ #include "context.h" #include "util-internal.h" +#ifndef X509_STORE_CTX_get0_untrusted +#define X509_STORE_CTX_get0_untrusted(store) store->untrusted +#endif + /* we only support sha256 at the moment. adding support for another digest is more complex than just adding another entry here. in particular, you'll probably need a match for a particular cert @@ -314,11 +318,11 @@ _get_ssl_getdns_upstream_idx() { static volatile int idx = -1; if (idx < 0) { - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + /* CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); */ if (idx < 0) idx = SSL_get_ex_new_index(0, "associated getdns upstream", NULL,NULL,NULL); - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + /* CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); */ } return idx; } @@ -383,7 +387,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, /* TODO: how do we handle raw public keys? */ - for (i = 0; i < sk_X509_num(store->untrusted); i++) { + for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++) { if (i > 0) { /* TODO: how do we ensure that the certificates in * each stage appropriately sign the previous one? @@ -392,7 +396,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, return GETDNS_RETURN_GENERIC_ERROR; } - x = sk_X509_value(store->untrusted, i); + 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, __FUNCTION__, i); diff --git a/src/util/val_secalgo.c b/src/util/val_secalgo.c index edbf538b..a27e7807 100644 --- a/src/util/val_secalgo.c +++ b/src/util/val_secalgo.c @@ -590,7 +590,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, log_err("EVP_MD_CTX_new: malloc failure"); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); - else if(docrypto_free) CRYPTO_free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); return 0; } if(EVP_VerifyInit(ctx, digest_type) == 0) { @@ -598,7 +598,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); - else if(docrypto_free) CRYPTO_free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); return 0; } if(EVP_VerifyUpdate(ctx, (unsigned char*)gldns_buffer_begin(buf), @@ -607,7 +607,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); - else if(docrypto_free) CRYPTO_free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); return 0; } @@ -621,7 +621,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_PKEY_free(evp_key); if(dofree) free(sigblock); - else if(docrypto_free) CRYPTO_free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); if(res == 1) { return 1; @@ -1359,6 +1359,7 @@ _getdns_dnskey_algo_id_is_supported(int id) } } +#ifdef USE_DSA static char * _verify_nettle_dsa(gldns_buffer* buf, unsigned char* sigblock, unsigned int sigblock_len, unsigned char* key, unsigned int keylen) @@ -1446,6 +1447,7 @@ _verify_nettle_dsa(gldns_buffer* buf, unsigned char* sigblock, else return NULL; } +#endif /* USE_DSA */ static char * _verify_nettle_rsa(gldns_buffer* buf, unsigned int digest_size, char* sigblock, From 72788cb172624a96c2849481d61852940af8dc12 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 31 Oct 2016 11:04:36 +0100 Subject: [PATCH 025/249] OpenSSL 1.1.0 version of CRYPTO_w_lock in pinning Thanks volkommenheit --- src/pubkey-pinning.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/pubkey-pinning.c b/src/pubkey-pinning.c index 32497608..7d286691 100644 --- a/src/pubkey-pinning.c +++ b/src/pubkey-pinning.c @@ -56,7 +56,7 @@ #include "context.h" #include "util-internal.h" -#ifndef X509_STORE_CTX_get0_untrusted +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #define X509_STORE_CTX_get0_untrusted(store) store->untrusted #endif @@ -314,15 +314,27 @@ _getdns_get_pubkey_pinset_list(getdns_context *ctx, see doc/HOWTO/proxy_certificates.txt as an example */ static int -_get_ssl_getdns_upstream_idx() +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) +_get_ssl_getdns_upstream_idx(void) +#else +_get_ssl_getdns_upstream_idx(X509_STORE *store) +#endif { static volatile int idx = -1; if (idx < 0) { - /* CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); */ +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); +#else + X509_STORE_lock(store); +#endif if (idx < 0) idx = SSL_get_ex_new_index(0, "associated getdns upstream", NULL,NULL,NULL); - /* CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); */ +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); +#else + X509_STORE_unlock(store); +#endif } return idx; } @@ -330,7 +342,11 @@ _get_ssl_getdns_upstream_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; @@ -348,7 +364,11 @@ getdns_return_t _getdns_associate_upstream_with_SSL(SSL *ssl, getdns_upstream *upstream) { +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) int uidx = _get_ssl_getdns_upstream_idx(); +#else + int uidx = _get_ssl_getdns_upstream_idx(SSL_CTX_get_cert_store(SSL_get_SSL_CTX(ssl))); +#endif if (SSL_set_ex_data(ssl, uidx, upstream)) return GETDNS_RETURN_GOOD; else From f66bb6a81273d29915b9a779d1778434fb071e7d Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 31 Oct 2016 11:22:16 +0100 Subject: [PATCH 026/249] Ignore stubby ;) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0f4482ef..7bbbdebd 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ src/test/check_getdns_ev src/test/scratchpad src/test/scratchpad.c src/tools/getdns_query +src/tools/stubby doc/*.3 src/getdns/getdns.h *.log From 6e5b62c5554cd39f3316f3344e5a2b6112929689 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 31 Oct 2016 13:36:05 +0100 Subject: [PATCH 027/249] Allow conventional IPv6 address/port parsing from getdns_query --- src/test/getdns_str2dict.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/test/getdns_str2dict.c b/src/test/getdns_str2dict.c index 28323d9d..f80df99e 100644 --- a/src/test/getdns_str2dict.c +++ b/src/test/getdns_str2dict.c @@ -33,6 +33,7 @@ #include "list.h" /* For _getdns_list_create_from_mf() */ #include "dict.h" /* For _getdns_dict_create_from_mf() */ #include /* For bsearch */ +#include /* For isspace */ static struct mem_funcs _getdns_plain_mem_funcs = { MF_PLAIN, .mf.pln = { malloc, realloc, free } @@ -102,7 +103,7 @@ static int _gldns_b64_pton(char const *src, uint8_t *target, size_t targsize) } static getdns_dict * -_getdns_ipaddr_dict_mf(struct mem_funcs *mf, char *ipstr) +_getdns_ipaddr_dict_mf(struct mem_funcs *mf, const char *ipstr) { getdns_dict *r = _getdns_dict_create_with_mf(mf); char *s = strchr(ipstr, '%'), *scope_id_str = ""; @@ -645,6 +646,17 @@ getdns_str2dict(const char *str, getdns_dict **dict) getdns_item item; getdns_return_t r; + while (*str && isspace(*str)) + str++; + + if (*str != '{') { + getdns_dict *dict_r = _getdns_ipaddr_dict_mf( + &_getdns_plain_mem_funcs, str); + if (dict_r) { + *dict = dict_r; + return GETDNS_RETURN_GOOD; + } + } if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item))) return r; From bc9ebd5ae21c03290e8b6764f047363901e644e7 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 31 Oct 2016 13:47:22 +0100 Subject: [PATCH 028/249] RFC3986 IPv6 address/port parsing for str2dict Resolves issue #215, but does not deal with RFC3986 formatted IPv6 addresses in config files yet. --- src/convert.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/convert.c b/src/convert.c index 24dbbf03..28e5e30f 100644 --- a/src/convert.c +++ b/src/convert.c @@ -1065,7 +1065,7 @@ getdns_msg_dict2str_scan( } static getdns_dict * -_getdns_ipaddr_dict_mf(struct mem_funcs *mf, char *ipstr) +_getdns_ipaddr_dict_mf(struct mem_funcs *mf, const char *ipstr) { getdns_dict *r = _getdns_dict_create_with_mf(mf); char *s = strchr(ipstr, '%'), *scope_id_str = ""; @@ -1606,6 +1606,21 @@ getdns_str2dict(const char *str, getdns_dict **dict) getdns_item item; getdns_return_t r; + if (!str || !dict) + return GETDNS_RETURN_INVALID_PARAMETER; + + while (*str && isspace(*str)) + str++; + + if (*str != '{') { + getdns_dict *dict_r = _getdns_ipaddr_dict_mf( + &_getdns_plain_mem_funcs, str); + + if (dict_r) { + *dict = dict_r; + return GETDNS_RETURN_GOOD; + } + } if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item))) return r; @@ -1663,6 +1678,9 @@ getdns_str2list(const char *str, getdns_list **list) getdns_item item; getdns_return_t r; + if (!str || !list) + return GETDNS_RETURN_INVALID_PARAMETER; + if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item))) return r; @@ -1680,6 +1698,9 @@ getdns_str2bindata(const char *str, getdns_bindata **bindata) getdns_item item; getdns_return_t r; + if (!str || !bindata) + return GETDNS_RETURN_INVALID_PARAMETER; + if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item))) return r; @@ -1697,6 +1718,9 @@ getdns_str2int(const char *str, uint32_t *value) getdns_item item; getdns_return_t r; + if (!str || !value) + return GETDNS_RETURN_INVALID_PARAMETER; + if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item))) return r; From 4bf93de12b3628eadb1a6fe3e898f0f35e82c1f0 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 2 Nov 2016 13:40:02 +0100 Subject: [PATCH 029/249] More conventional function prototypes for servers --- src/context.c | 2 +- src/getdns/getdns_extra.h.in | 27 ++++++++++++++++----------- src/server.c | 25 +++++++++++++++++++------ src/tools/getdns_query.c | 23 ++++++++++++++--------- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/context.c b/src/context.c index e849dbd8..b8492380 100644 --- a/src/context.c +++ b/src/context.c @@ -1487,7 +1487,7 @@ getdns_context_destroy(struct getdns_context *context) cancel_outstanding_requests(context, 1); /* Destroy listening addresses */ - (void) getdns_context_set_listen_addresses(context, NULL, NULL); + (void) getdns_context_set_listen_addresses(context, NULL, NULL, NULL); /* This needs to be done before cleaning the extension, because there * might be an idle_timeout schedules, which will not get unscheduled diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 9c973a5e..5abf39e7 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -1030,9 +1030,11 @@ getdns_context_config(getdns_context *context, const getdns_dict *config_dict); * The user defined request handler that will be called on incoming requests. */ typedef void (*getdns_request_handler_t)( - getdns_context *context, - getdns_dict *request, - getdns_transaction_t request_id + getdns_context *context, + getdns_callback_type_t callback_type, + getdns_dict *request, + void *userarg, + getdns_transaction_t request_id ); /** @@ -1041,6 +1043,11 @@ typedef void (*getdns_request_handler_t)( * * @param context The context managing the eventloop that needs to be run to * start serving. + * @param listen_addresses A list of address dicts or bindatas that will be + * listened on for DNS requests. Both UDP and TCP + * transports will be used. + * @param userarg A user defined argument that will be passed to the handler + * untouched. * @param handler The user defined request handler that will be called with the * request received in reply dict format. To reply to this request * the function has to construct a response (or modify the request) @@ -1050,9 +1057,6 @@ typedef void (*getdns_request_handler_t)( * not answered by the function, by not calling getdns_reply() this * will cause a memory leak. The user most use getdns_reply() * with NULL as the response to not answer/cancel a request. - * @param listen_addresses A list of address dicts or bindatas that will be - * listened on for DNS requests. Both UDP and TCP - * transports will be used. * @return GETDNS_RETURN_GOOD on success or an error code on failure. * On failure, the current set of listening addresses is left in place. * Also, if there is overlap in listening_addresses between the active set @@ -1061,8 +1065,9 @@ typedef void (*getdns_request_handler_t)( * DNS transactions will remain. */ getdns_return_t -getdns_context_set_listen_addresses(getdns_context *context, - getdns_request_handler_t handler, const getdns_list *listen_addresses); +getdns_context_set_listen_addresses( + getdns_context *context, const getdns_list *listen_addresses, + void *userarg, getdns_request_handler_t handler); /** * Answer the request associated with a request_id that is received by a @@ -1070,11 +1075,11 @@ getdns_context_set_listen_addresses(getdns_context *context, * * @param context The context managing the eventloop that needs to be run to * listen for and answer requests. - * @param request_id The identifier that links this response with the - * received request. * @param reply The answer in getdns reply dict or response dict format. * When NULL is given as reply, the request is not answered * but all associated state is deleted. + * @param request_id The identifier that links this response with the + * received request. * @return GETDNS_RETURN_GOOD on success or an error code on failure. * On fatal failure (no retry strategy possible) the user still needs to * cancel the request by recalling getdns_reply() but with NULL as response, @@ -1082,7 +1087,7 @@ getdns_context_set_listen_addresses(getdns_context *context, */ getdns_return_t getdns_reply(getdns_context *context, - getdns_transaction_t request_id, getdns_dict *reply); + getdns_dict *reply, getdns_transaction_t request_id); /** @} diff --git a/src/server.c b/src/server.c index 9e4caa76..d8fb83cb 100644 --- a/src/server.c +++ b/src/server.c @@ -65,6 +65,7 @@ struct listener { */ struct listen_set { getdns_context *context; + void *userarg; getdns_request_handler_t handler; _getdns_rbtree_t connections_set; @@ -231,7 +232,7 @@ _getdns_cancel_reply(getdns_context *context, connection *conn) getdns_return_t getdns_reply( - getdns_context *context, getdns_transaction_t request_id, getdns_dict *reply) + getdns_context *context, getdns_dict *reply, getdns_transaction_t request_id) { /* TODO: Check request_id at context->outbound_requests */ connection *conn = (connection *)(intptr_t)request_id; @@ -400,9 +401,14 @@ static void tcp_read_cb(void *userarg) else { conn->to_answer++; + /* TODO: wish list item: + * (void) getdns_dict_set_int64( + * request_dict, "request_id", intptr_t)conn); + */ /* Call request handler */ conn->super.l->set->handler( - conn->super.l->set->context, request_dict, (intptr_t)conn); + conn->super.l->set->context, GETDNS_CALLBACK_COMPLETE, + request_dict, conn->super.l->set->userarg, (intptr_t)conn); conn->read_pos = conn->read_buf; conn->to_read = 2; @@ -618,8 +624,14 @@ static void udp_read_cb(void *userarg) conn->prev_next = &l->connections; l->connections = conn; + /* TODO: wish list item: + * (void) getdns_dict_set_int64( + * request_dict, "request_id", (intptr_t)conn); + */ /* Call request handler */ - l->set->handler(l->set->context, request_dict, (intptr_t)conn); + l->set->handler(l->set->context, GETDNS_CALLBACK_COMPLETE, + request_dict, l->set->userarg, (intptr_t)conn); + return; } GETDNS_FREE(*mf, conn); @@ -765,9 +777,9 @@ ptr_cmp(const void *a, const void *b) return a == b ? 0 : (a < b ? -1 : 1); } -getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, - getdns_request_handler_t request_handler, - const getdns_list *listen_addresses) +getdns_return_t getdns_context_set_listen_addresses( + getdns_context *context, const getdns_list *listen_addresses, + void *userarg, getdns_request_handler_t request_handler) { static const getdns_transport_list_t listen_transports[] = { GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP }; @@ -830,6 +842,7 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, new_set->context = context; new_set->handler = request_handler; + new_set->userarg = userarg; new_set->count = new_set_count * n_transports; (void) memset(new_set->items, 0, sizeof(listener) * new_set_count * n_transports); diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 48a4d721..fe93b544 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -1182,7 +1182,8 @@ getdns_return_t do_the_call(void) getdns_eventloop *loop = NULL; FILE *fp; static void incoming_request_handler(getdns_context *context, - getdns_dict *request, getdns_transaction_t request_id); + getdns_callback_type_t callback_type, getdns_dict *request, + void *userarg, getdns_transaction_t request_id); void read_line_cb(void *userarg) @@ -1199,7 +1200,7 @@ void read_line_cb(void *userarg) loop->vmt->clear(loop, read_line_ev); if (listen_count) (void) getdns_context_set_listen_addresses( - context, NULL, NULL); + context, NULL, NULL, NULL); return; } if (query_file) @@ -1229,7 +1230,7 @@ void read_line_cb(void *userarg) r = parse_args(linec, linev); if (!r && touched_listen_list) { r = getdns_context_set_listen_addresses( - context, incoming_request_handler, listen_list); + context, listen_list, NULL, incoming_request_handler); } if ((r || (r = do_the_call())) && (r != CONTINUE && r != CONTINUE_ERROR)) @@ -1406,11 +1407,11 @@ static void request_cb( else if (n == 0) SERVFAIL("Recursion not available", 0, msg, &response); - if ((r = getdns_reply(context, msg->request_id, response))) { + if ((r = getdns_reply(context, response, msg->request_id))) { fprintf(stderr, "Could not reply: %s\n", getdns_get_errorstr_by_id(r)); /* Cancel reply */ - (void) getdns_reply(context, msg->request_id, NULL); + (void) getdns_reply(context, NULL, msg->request_id); } if (msg) { getdns_dict_destroy(msg->request); @@ -1421,7 +1422,8 @@ static void request_cb( } static void incoming_request_handler(getdns_context *context, - getdns_dict *request, getdns_transaction_t request_id) + getdns_callback_type_t callback_type, getdns_dict *request, + void *userarg, getdns_transaction_t request_id) { getdns_bindata *qname; char *qname_str = NULL; @@ -1440,6 +1442,9 @@ static void incoming_request_handler(getdns_context *context, getdns_dict *rr; uint32_t rr_type; + (void)callback_type; + (void)userarg; + if (!query_extensions_spc && !(query_extensions_spc = getdns_dict_create())) fprintf(stderr, "Could not create query extensions space\n"); @@ -1567,11 +1572,11 @@ error: free(request_str); } while(0); #endif - if ((r = getdns_reply(context, request_id, response))) { + if ((r = getdns_reply(context, response, request_id))) { fprintf(stderr, "Could not reply: %s\n", getdns_get_errorstr_by_id(r)); /* Cancel reply */ - getdns_reply(context, request_id, NULL); + getdns_reply(context, NULL, request_id); } if (msg) { if (msg->request) @@ -1648,7 +1653,7 @@ main(int argc, char **argv) assert(loop); } if (listen_count && (r = getdns_context_set_listen_addresses( - context, incoming_request_handler, listen_list))) { + context, listen_list, NULL, incoming_request_handler))) { perror("error: Could not bind on given addresses"); goto done_destroy_context; } From c54a22d95b9ca3ee1cffc19204029b8072997fb4 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 2 Nov 2016 13:43:09 +0100 Subject: [PATCH 030/249] Binary API changed --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 8a456a8c..bf442574 100644 --- a/configure.ac +++ b/configure.ac @@ -47,7 +47,7 @@ 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, [0x0100A100]) +AC_SUBST(GETDNS_NUMERIC_VERSION, [0x0100A300]) 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" @@ -78,9 +78,9 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRE # getdns-0.5.1 had libversion 4:1:3 (but should have been getdns-0.6.0) # getdns-0.9.0 had libversion 5:0:4 # getdns-1.0.0 will have libversion 5:1:4 -# getdns-1.1.0 will have libversion 6:0:5 +# getdns-1.1.0 will have libversion 6:0:0 # -GETDNS_LIBVERSION=6:0:5 +GETDNS_LIBVERSION=6:0:0 AC_SUBST(GETDNS_COMPILATION_COMMENT) AC_SUBST(GETDNS_LIBVERSION) From ef80f463c2d1f4f76dc1eb5a15baca3114758aa4 Mon Sep 17 00:00:00 2001 From: wtoorop Date: Thu, 3 Nov 2016 14:19:49 +0100 Subject: [PATCH 031/249] Update README.md Properly format MS-Windows build instructions. Thanks Christian Huitema --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 623a786f..1b5a4807 100644 --- a/README.md +++ b/README.md @@ -261,29 +261,30 @@ The build has been tested using the following: 32 bit only Mingw: [Mingw(3.21.0) and Msys 1.0](http://www.mingw.org/) on Windows 8.1 32 bit build on a 64 bit Mingw [Download latest from: http://mingw-w64.org/doku.php/download/mingw-builds and http://msys2.github.io/]. IMPORTANT: Install tested ONLY on the "x86_64" for 64-bit installer of msys2. -Dependencies: +#### Dependencies: The following dependencies are -openssl-1.0.2e -libidn +* openssl-1.0.2j +* libidn -Instructions to build openssl-1.0.2e: +Instructions to build openssl-1.0.2j: Open the mingw32_shell.bat from msys2 in order to build: If necessary, install the following using pacman: -pacman -S pkg-config libtool automake -pacman -S autoconf automake-wrapper - tar -xvf openssl-1.0.2e.tar -cd openssl-1.0.2e/ -./Configure --prefix=${LOCALDESTDIR} --openssldir=${LOCALDESTDIR}/etc/ssl --libdir=lib shared zlib-dynamic mingw -make -make install + pacman -S pkg-config libtool automake + pacman -S autoconf automake-wrapper + + tar -xvf openssl-1.0.2j.tar + cd openssl-1.0.2j/ + ./Configure --prefix=${LOCALDESTDIR} --openssldir=${LOCALDESTDIR}/etc/ssl --libdir=lib shared zlib-dynamic mingw + make + make install To configure: ./configure --enable-stub-only --with-trust-anchor="c:\\\MinGW\\\msys\\\1.0\\\etc\\\unbound\\\getdns-root.key" --with-ssl= --with-getdns_query - The trust anchor is also installed by unbound on c:\program Files (X86)\unbound\root.key and can be referenced from there + The trust anchor is also installed by unbound on `c:\program Files (X86)\unbound\root.key` and can be referenced from there or anywhere else that the user chooses to configure it. After configuring, do a `make` and `make install` to build getdns for Windows. From 57e2a18f94718479d82c52f11a000bb5c9f5fcd3 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 3 Nov 2016 15:35:53 +0100 Subject: [PATCH 032/249] Minor fixes to make it compile on Windows again --- src/server.c | 15 +++++++++++++-- src/tools/getdns_query.c | 11 ++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/server.c b/src/server.c index d8fb83cb..597994bf 100644 --- a/src/server.c +++ b/src/server.c @@ -26,7 +26,14 @@ */ #include "config.h" + +#ifndef USE_WINSOCK #include +#else +#include +#include +#endif + #include "getdns/getdns_extra.h" #include "context.h" #include "types-internal.h" @@ -269,7 +276,7 @@ getdns_reply( else if (conn->l->transport == GETDNS_TRANSPORT_UDP) { listener *l = conn->l; - if (conn->l->fd >= 0 && sendto(conn->l->fd, buf, len, 0, + if (conn->l->fd >= 0 && sendto(conn->l->fd, (void *)buf, len, 0, (struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) { /* IO error, cleanup this listener */ loop->vmt->clear(loop, &conn->l->event); @@ -532,7 +539,7 @@ static void udp_read_cb(void *userarg) conn->l = l; conn->addrlen = sizeof(conn->remote_in); - if ((len = recvfrom(l->fd, buf, sizeof(buf), 0, + if ((len = recvfrom(l->fd, (void *)buf, sizeof(buf), 0, (struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) { /* IO error, cleanup this listener. */ loop->vmt->clear(loop, &l->event); @@ -704,7 +711,11 @@ static void remove_listeners(listen_set *set) static getdns_return_t add_listeners(listen_set *set) { +#ifdef USE_WINSOCK + static const char enable = 1; +#else static const int enable = 1; +#endif struct mem_funcs *mf; getdns_eventloop *loop; diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index fe93b544..92a27337 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -55,7 +55,9 @@ static const char *default_stubby_config = ", listen_addresses: [ 127.0.0.1@53, 0::1@53 ]" "}"; static int clear_listen_list_on_arg = 0; +#ifndef GETDNS_ON_WINDOWS static int run_in_foreground = 1; +#endif static int quiet = 0; static int batch_mode = 0; static char *query_file = NULL; @@ -209,8 +211,10 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-e \tSet idle timeout in miliseconds\n"); fprintf(out, "\t-F \tread the queries from the specified file\n"); fprintf(out, "\t-f \tRead DNSSEC trust anchors from \n"); +#ifndef GETDNS_ON_WINDOWS if (i_am_stubby) fprintf(out, "\t-g\tRun stubby in background (default is foreground)\n"); +#endif fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-H\thostname lookup. ( must be an IP address; is ignored)\n"); fprintf(out, "\t-h\tPrint this help\n"); @@ -995,10 +999,12 @@ getdns_return_t parse_args(int argc, char **argv) } break; default: +#ifndef GETDNS_ON_WINDOWS if (i_am_stubby && *c == 'g') { run_in_foreground = 0; break; } +#endif fprintf(stderr, "Unknown option " "\"%c\"\n", *c); for (i = 0; i < argc; i++) @@ -1608,7 +1614,8 @@ main(int argc, char **argv) prg_name = prg_name ? prg_name + 1 : argv[0]; i_am_stubby = strcasecmp(prg_name, "stubby") == 0 - || strcasecmp(prg_name, "lt-stubby") == 0; + || strcasecmp(prg_name, "lt-stubby") == 0 + || strcasecmp(prg_name, "stubby.exe") == 0; name = the_root; if ((r = getdns_context_create(&context, 1))) { @@ -1675,6 +1682,7 @@ main(int argc, char **argv) } else if (listen_count) { assert(loop); +#ifndef GETDNS_ON_WINDOWS if (i_am_stubby && !run_in_foreground) { pid_t pid = fork(); if (pid == -1) { @@ -1693,6 +1701,7 @@ main(int argc, char **argv) } else loop->vmt->run(loop); } else +#endif loop->vmt->run(loop); } else r = do_the_call(); From b857e3d7f1b3b2b7089890fdac6563a51d26bb0c Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Tue, 8 Nov 2016 11:46:29 +0000 Subject: [PATCH 033/249] call SSL_library_init() just once and lock with mutexes --- src/context.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/context.c b/src/context.c index 8893191e..27ef5114 100644 --- a/src/context.c +++ b/src/context.c @@ -62,6 +62,11 @@ typedef unsigned short in_port_t; #include #include +#ifdef HAVE_PTHREADS +#include +#endif +#include + #include "config.h" #ifdef HAVE_LIBUNBOUND #include @@ -85,6 +90,11 @@ typedef unsigned short in_port_t; #define GETDNS_STR_PORT_DNS "53" #define GETDNS_STR_PORT_DNS_OVER_TLS "853" +#ifdef HAVE_PTHREADS +static pthread_mutex_t ssl_init_lock = PTHREAD_MUTEX_INITIALIZER; +#endif +static bool ssl_init=false; + void *plain_mem_funcs_user_arg = MF_PLAIN; typedef struct host_name_addrs { @@ -1306,8 +1316,21 @@ getdns_context_create_with_extended_memory_functions( /* Unbound needs SSL to be init'ed this early when TLS is used. However we * don't know that till later so we will have to do this every time. */ - if ((set_from_os & 2) == 0) +#ifdef HAVE_PTHREADS + pthread_mutex_lock(&ssl_init_lock); +#else + /* XXX implement Windows-style lock here */ +#endif + /* Only initialise SSL once and ideally in a thread-safe manner */ + if (ssl_init == false) { SSL_library_init(); + ssl_init = true; + } +#ifdef HAVE_PTHREADS + pthread_mutex_unlock(&ssl_init_lock); +#else + /* XXX implement Windows-style unlock here */ +#endif #ifdef HAVE_LIBUNBOUND result->unbound_ctx = NULL; From 1593129b8577481d0706f98a0ea2477b1a4ef89f Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Wed, 9 Nov 2016 16:41:40 +0000 Subject: [PATCH 034/249] Fix mishandling of auth state for name mismatch --- src/stub.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/stub.c b/src/stub.c index bb18f68b..d73798f4 100644 --- a/src/stub.c +++ b/src/stub.c @@ -830,6 +830,8 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) getdns_upstream *upstream; getdns_return_t pinset_ret = GETDNS_RETURN_GOOD; upstream = _getdns_upstream_from_x509_store(ctx); + if (!upstream) + return 0; #if defined(STUB_DEBUG) && STUB_DEBUG || defined(X509_V_ERR_HOSTNAME_MISMATCH) int err = X509_STORE_CTX_get_error(ctx); @@ -841,10 +843,11 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) #ifdef X509_V_ERR_HOSTNAME_MISMATCH /*Report if error is hostname mismatch*/ - if (upstream && upstream->tls_fallback_ok && err == X509_V_ERR_HOSTNAME_MISMATCH) { - DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n", - STUB_DEBUG_SETUP_TLS, __FUNCTION__, upstream->fd); + if (err == X509_V_ERR_HOSTNAME_MISMATCH) { upstream->tls_auth_state = GETDNS_AUTH_FAILED; + if (upstream->tls_fallback_ok) + DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n", + STUB_DEBUG_SETUP_TLS, __FUNCTION__, upstream->fd); } #else /* if we weren't built against OpenSSL with hostname matching we @@ -853,7 +856,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) if (upstream->tls_auth_name[0]) upstream->tls_auth_state = GETDNS_AUTH_FAILED; #endif - if (upstream && upstream->tls_pubkey_pinset) + if (upstream->tls_pubkey_pinset) pinset_ret = _getdns_verify_pinset_match(upstream->tls_pubkey_pinset, ctx); if (pinset_ret != GETDNS_RETURN_GOOD) { @@ -871,7 +874,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) upstream->tls_auth_state = GETDNS_AUTH_OK; /* If fallback is allowed, proceed regardless of what the auth error is (might not be hostname or pinset related) */ - return (upstream && upstream->tls_fallback_ok) ? 1 : preverify_ok; + return (upstream->tls_fallback_ok) ? 1 : preverify_ok; } static SSL* From c2bcd1ca729cc32baf0922f18e0648a672f8844a Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 12 Nov 2016 14:31:27 +0900 Subject: [PATCH 035/249] Line up OPT rdata names with add_opt_parameters --- src/request-internal.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/request-internal.c b/src/request-internal.c index 141f977a..180d0633 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -755,17 +755,26 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, edns_do_bit = context->edns_do_bit; if (have_add_opt_parameters) { - if (!getdns_dict_get_int(add_opt_parameters, + if (getdns_dict_get_int(add_opt_parameters, "maximum_udp_payload_size", - &get_edns_maximum_udp_payload_size)) + &get_edns_maximum_udp_payload_size)) { + if (!getdns_dict_get_int( + add_opt_parameters, "udp_payload_size", + &get_edns_maximum_udp_payload_size)) + edns_maximum_udp_payload_size = + get_edns_maximum_udp_payload_size; + } else edns_maximum_udp_payload_size = get_edns_maximum_udp_payload_size; + (void) getdns_dict_get_int(add_opt_parameters, "extended_rcode", &edns_extended_rcode); (void) getdns_dict_get_int(add_opt_parameters, "version", &edns_version); - (void) getdns_dict_get_int(add_opt_parameters, - "do_bit", &edns_do_bit); + if (getdns_dict_get_int(add_opt_parameters, + "do_bit", &edns_do_bit)) + (void) getdns_dict_get_int( + add_opt_parameters, "do", &edns_do_bit); } } if (have_add_opt_parameters && getdns_dict_get_list( From 73165b235fb42f1e0ea0482ab5760a68768b4f05 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 12 Nov 2016 16:53:21 +0900 Subject: [PATCH 036/249] Allow public key pins higher in the chain than the EE cert This resolves an old TODO; we'd never tested pinning any certs higher than the end-entity cert before. --- src/pubkey-pinning.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/pubkey-pinning.c b/src/pubkey-pinning.c index 7d286691..25966a63 100644 --- a/src/pubkey-pinning.c +++ b/src/pubkey-pinning.c @@ -382,10 +382,10 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, X509_STORE_CTX *store) { getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR; - X509 *x; + X509 *x, *prev; int i, len; unsigned char raw[4096]; - unsigned char *next = raw; + unsigned char *next; unsigned char buf[sizeof(pinset->pin)]; const sha256_pin_t *p; @@ -408,13 +408,6 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, /* TODO: how do we handle raw public keys? */ for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++) { - if (i > 0) { - /* TODO: how do we ensure that the certificates in - * each stage appropriately sign the previous one? - * for now, to be safe, we only examine the end-entity - * cert: */ - return GETDNS_RETURN_GENERIC_ERROR; - } x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i); #if defined(STUB_DEBUG) && STUB_DEBUG @@ -423,6 +416,24 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, 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, __FUNCTION__, i, 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, __FUNCTION__, i-1, prev, i); + return GETDNS_RETURN_GENERIC_ERROR; + } + } + /* digest the cert with sha256 */ len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL); if (len > sizeof(raw)) { @@ -430,6 +441,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, STUB_DEBUG_SETUP_TLS, __FUNCTION__, 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", @@ -447,6 +459,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, } else DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n", STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, p); + prev = x; } return ret; From b0e5f87984fc827d7ea93957862fb366a3ddbb19 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Sun, 13 Nov 2016 13:14:03 +0900 Subject: [PATCH 037/249] Minor logging updates --- src/context.c | 8 ++++++-- src/stub.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/context.c b/src/context.c index b8492380..121c536a 100644 --- a/src/context.c +++ b/src/context.c @@ -720,12 +720,16 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->responses_received, (int)upstream->responses_timeouts, getdns_auth_str_array[upstream->tls_auth_state], (int)upstream->keepalive_timeout); - DEBUG_DAEMON("%s %s : Upstream stats - Resp=%d,Timeouts=%d,Best_auth=%s,Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", + DEBUG_DAEMON("%s %s : Upstream stats - Resp=%d,Timeouts=%d,Best_auth=%s,Conns=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->total_responses, (int)upstream->total_timeouts, getdns_auth_str_array[upstream->best_tls_auth_state], - (int)upstream->conn_completed, (int)upstream->conn_setup_failed, + (int)upstream->conn_completed); + DEBUG_DAEMON("%s %s : Upstream stats - Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", + STUB_DEBUG_DAEMON, upstream->addr_str, + (int)upstream->conn_setup_failed, (int)upstream->conn_shutdowns, (int)upstream->conn_backoffs); + #endif /* Back off connections that never got up service at all (probably no diff --git a/src/stub.c b/src/stub.c index d73798f4..2527ed61 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1523,7 +1523,7 @@ upstream_write_cb(void *userarg) /* Fall through */ case STUB_SETUP_ERROR: /* Could not complete the set up. Need to fallback.*/ - DEBUG_STUB("%s %-35s: MSG: %p ERROR = %d\n", STUB_DEBUG_WRITE, + DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE, __FUNCTION__, ((getdns_network_req *)userarg), q); upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1)); /* Fall through */ From 1ba2e5bf4de515c7f02c679cce692fe5364b117a Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Sun, 20 Nov 2016 11:19:08 +0000 Subject: [PATCH 038/249] Add stubby to readme. Add transport to stubby log. --- README.md | 21 +++++++++++++++++++-- src/context.c | 11 +++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1b5a4807..c1a8bae4 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Traditional access to DNS data from applications has several limitations: * Sophisticated uses of the DNS (things like IDNA and DNSSEC validation) require considerable application work, possibly by application developers with little experience with the vagaries of DNS. +getdns also provides a prototype DNS Privacy enabled client called 'stubby' - see below for more details. + ## Motivation for providing the API The developers are of the opinion that DNSSEC offers a unique global infrastructure for establishing and enhancing cryptographic trust relations. With the development of this API we intend to offer application developers a modern and flexible interface that enables end-to-end trust in the DNS architecture, and which will inspire application developers to implement innovative security solutions in their applications. @@ -73,9 +75,13 @@ If you want to make use of the configuration files that utilise a JSON-like form before building. -If you want to use the getdns_query command line wrapper script for testing or to enable getdns as a daemon then you must build it using +As well as building the getdns library 2 other tools are installed by default by the above process: + +* getdns_query: a command line test script wrapper for getdns +* stubby: a DNS Privacy enabled client + +Note: If you only want to build stubby, then use the `--enable-stub-only` and `--without-libidn` options when running 'configure'. - # make getdns_query ## Minimizing dependencies @@ -91,6 +97,17 @@ The implementation works with a variety of event loops, each built as a separate * [libuv](https://github.com/joyent/libuv) * [libev](http://software.schmorp.de/pkg/libev.html) +## Stubby + +* Stubby is a prototype implementation of a DNS Privacy enabled stub resolver. Feedback is welcome! +* A default configuration file is available here uses a 'Strict' privacy usage profile using some of the available test DNS Privacy servers to resolve queries. Note these servers are test servers that offer no service guarantees. An alternative file can be specified with the '-C' flag +* If you would like minimal logging output from Stubby (which servers are used and connection level statistics) then also use the '--enable-debug-daemon' flag when running 'configure'. + +To use stubby +* Start stubby from the command line +* Test it by doing, for example, 'dig @127.0.0.1 www.example.com' +* Alter the default DNS resolvers on your system to point at localhost (127.0.0.1, ::1) + ## Regression Tests A suite of regression tests are included with the library, if you make changes or just diff --git a/src/context.c b/src/context.c index 121c536a..1d9a046b 100644 --- a/src/context.c +++ b/src/context.c @@ -720,16 +720,15 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->responses_received, (int)upstream->responses_timeouts, getdns_auth_str_array[upstream->tls_auth_state], (int)upstream->keepalive_timeout); - DEBUG_DAEMON("%s %s : Upstream stats - Resp=%d,Timeouts=%d,Best_auth=%s,Conns=%d\n", + DEBUG_DAEMON("%s %s : Upstream stats - Resp=%d,Timeouts=%d,Transport=%s,Best_auth=%s\n", STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->total_responses, (int)upstream->total_timeouts, - getdns_auth_str_array[upstream->best_tls_auth_state], - (int)upstream->conn_completed); - DEBUG_DAEMON("%s %s : Upstream stats - Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", + (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "UDP/TCP"), + getdns_auth_str_array[upstream->best_tls_auth_state]); + DEBUG_DAEMON("%s %s : Upstream stats - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, - (int)upstream->conn_setup_failed, + (int)upstream->conn_completed, (int)upstream->conn_setup_failed, (int)upstream->conn_shutdowns, (int)upstream->conn_backoffs); - #endif /* Back off connections that never got up service at all (probably no From 0d13ae6d72e59e42b6905f98b57089e31817e7fd Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Sun, 4 Dec 2016 17:26:38 -0800 Subject: [PATCH 039/249] Fixing several issues in function set_os_defaults_windows that prevent working on Windows. --- src/context.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/context.c b/src/context.c index 8893191e..010b1685 100644 --- a/src/context.c +++ b/src/context.c @@ -929,6 +929,7 @@ set_os_defaults_windows(struct getdns_context *context) getdns_upstream *upstream; size_t length; int s; + uint32_t info_err = 0; if (context->fchg_resolvconf == NULL) { context->fchg_resolvconf = @@ -961,15 +962,16 @@ set_os_defaults_windows(struct getdns_context *context) if (info == NULL) return GETDNS_RETURN_GENERIC_ERROR; - if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) { + if ((info_err = GetNetworkParams(info, &buflen)) == ERROR_BUFFER_OVERFLOW) { free(info); info = (FIXED_INFO *)malloc(buflen); if (info == NULL) return GETDNS_RETURN_GENERIC_ERROR; + info_err = GetNetworkParams(info, &buflen); } - if (GetNetworkParams(info, &buflen) == NO_ERROR) { - ptr = info->DnsServerList.Next; + if (info_err == NO_ERROR) { + ptr = &info->DnsServerList; *domain = 0; while (ptr) { for (size_t i = 0; i < GETDNS_UPSTREAM_TRANSPORTS; i++) { @@ -986,11 +988,12 @@ set_os_defaults_windows(struct getdns_context *context) freeaddrinfo(result); } ptr = ptr->Next; - } - free(info); } + if (info != NULL) + free(info); + suffix = getdns_list_create_with_context(context); if (get_dns_suffix_windows(suffix, domain)) { From 576e38977f746fc5aa8af2127d37ce12e7a419db Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Mon, 5 Dec 2016 18:05:04 +0000 Subject: [PATCH 040/249] More logging changes to stubby to correctly report profile, transport and stats for TCP and UDP when used as fallbacks. Reporting UDP stats every 100 responses or timeouts to give user some indication UDP is being used. --- src/context.c | 12 ++++++++---- src/context.h | 2 ++ src/stub.c | 24 ++++++++++++++++++++---- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/context.c b/src/context.c index 1d9a046b..8b8413f8 100644 --- a/src/context.c +++ b/src/context.c @@ -716,17 +716,19 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) if (upstream->tls_auth_state > upstream->best_tls_auth_state) upstream->best_tls_auth_state = upstream->tls_auth_state; #if defined(DAEMON_DEBUG) && DAEMON_DEBUG - DEBUG_DAEMON("%s %s : Conn closed: Conn stats - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n", + DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, + (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"), (int)upstream->responses_received, (int)upstream->responses_timeouts, getdns_auth_str_array[upstream->tls_auth_state], (int)upstream->keepalive_timeout); - DEBUG_DAEMON("%s %s : Upstream stats - Resp=%d,Timeouts=%d,Transport=%s,Best_auth=%s\n", + DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n", STUB_DEBUG_DAEMON, upstream->addr_str, + (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"), (int)upstream->total_responses, (int)upstream->total_timeouts, - (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "UDP/TCP"), getdns_auth_str_array[upstream->best_tls_auth_state]); - DEBUG_DAEMON("%s %s : Upstream stats - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", + DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, + (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"), (int)upstream->conn_completed, (int)upstream->conn_setup_failed, (int)upstream->conn_shutdowns, (int)upstream->conn_backoffs); #endif @@ -903,6 +905,8 @@ upstream_init(getdns_upstream *upstream, /* How is this upstream doing on UDP? */ upstream->to_retry = 2; upstream->back_off = 1; + upstream->udp_responses = 0; + upstream->udp_timeouts = 0; /* For sharing a socket to this upstream with TCP */ upstream->fd = -1; diff --git a/src/context.h b/src/context.h index 41e7a830..fdf8066e 100644 --- a/src/context.h +++ b/src/context.h @@ -131,6 +131,8 @@ typedef struct getdns_upstream { /* How is this upstream doing over UDP? */ int to_retry; int back_off; + size_t udp_responses; + size_t udp_timeouts; /* For stateful upstreams, need to share the connection and track the activity on the connection */ diff --git a/src/stub.c b/src/stub.c index 2527ed61..83ab992c 100644 --- a/src/stub.c +++ b/src/stub.c @@ -571,6 +571,13 @@ stub_timeout_cb(void *userarg) /* Handle upstream*/ if (netreq->fd >= 0) { close(netreq->fd); + netreq->upstream->udp_timeouts++; +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + if (netreq->upstream->udp_timeouts % 100 == 0) + DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n", + STUB_DEBUG_DAEMON, netreq->upstream->addr_str, + (int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts); +#endif stub_next_upstream(netreq); } else { netreq->upstream->responses_timeouts++; @@ -1305,6 +1312,13 @@ stub_udp_read_cb(void *userarg) dnsreq->upstreams->current_udp = 0; netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->state = NET_REQ_FINISHED; + upstream->udp_responses++; +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + if (upstream->udp_responses % 100 == 0) + DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n", + STUB_DEBUG_DAEMON, upstream->addr_str, + (int)upstream->udp_responses, (int)upstream->udp_timeouts); +#endif _getdns_check_dns_req_complete(dnsreq); } @@ -1767,15 +1781,16 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, upstream->tls_hs_state = GETDNS_HS_WRITE; } upstream->conn_state = GETDNS_CONN_SETUP; +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + DEBUG_DAEMON("%s %s : Conn init : Transport= %s - Profile=%s\n", STUB_DEBUG_DAEMON, + upstream->addr_str, transport == GETDNS_TRANSPORT_TLS ? "TLS":"TCP", + dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict"); +#endif break; default: return -1; /* Nothing to do*/ } -#if defined(DAEMON_DEBUG) && DAEMON_DEBUG - DEBUG_DAEMON("%s %s : Conn init\n", - STUB_DEBUG_DAEMON, upstream->addr_str); -#endif return fd; } @@ -1841,6 +1856,7 @@ fallback_on_write(getdns_network_req *netreq) /* Deal with UDP one day*/ DEBUG_STUB("%s %-35s: MSG: %p FALLING BACK \n", STUB_DEBUG_SCHEDULE, __FUNCTION__, netreq); + DEBUG_DAEMON("%s Falling back...\n", STUB_DEBUG_DAEMON); /* Try to find a fallback transport*/ getdns_return_t result = _getdns_submit_stub_request(netreq); From dee33f53b65e03dd3d31da781863867e9d03bb7a Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Mon, 5 Dec 2016 11:38:59 -0800 Subject: [PATCH 041/249] Reminder of changes required by the Windows port. This solves the issues 228, 229, 230 and 232. --- src/compat/arc4random.c | 11 +++++ src/compat/gettimeofday.c | 73 +++++++++++++++++++++++++++++++ src/extension/default_eventloop.c | 16 +++---- src/stub.c | 41 +++++++++++++++-- 4 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 src/compat/gettimeofday.c diff --git a/src/compat/arc4random.c b/src/compat/arc4random.c index 2c78818f..bd5f6e3a 100644 --- a/src/compat/arc4random.c +++ b/src/compat/arc4random.c @@ -38,6 +38,9 @@ #ifndef GETDNS_ON_WINDOWS #include #endif +#if defined(GETDNS_ON_WINDOWS) && !defined(MAP_INHERIT_ZERO) +#define explicit_bzero(rnd, rnd_size) memset(rnd, 0, rnd_size) +#endif #define KEYSTREAM_ONLY #include "chacha_private.h" @@ -136,7 +139,15 @@ _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) { diff --git a/src/compat/gettimeofday.c b/src/compat/gettimeofday.c new file mode 100644 index 00000000..d8fe91bc --- /dev/null +++ b/src/compat/gettimeofday.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Christian Huitema + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * 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. + */ + + /* + * Numerous places in the code make reference to the Unix/Linux + * "gettimeofday()" function, which is not available in the standard + * windows libraries. This code provides a compatible implementation. + */ +#include "config.h" + +#ifdef GETDNS_ON_WINDOWS +int gettimeofday(struct timeval* tv, struct timezone* tz) +{ + FILETIME ft; + uint64_t now = 0; + + /* + * The GetSystemTimeAsFileTime API returns the number + * of 100-nanosecond intervals since January 1, 1601 (UTC), + * in FILETIME format. + */ + GetSystemTimeAsFileTime(&ft); + + /* + * Convert to plain 64 bit format, without making + * assumptions about the FILETIME structure alignment. + */ + now |= ft.dwHighDateTime; + now <<= 32; + now |= ft.dwLowDateTime; + /* + * Convert units from 100ns to 1us + */ + now /= 10; + /* + * Account for microseconds elapsed between 1601 and 1970. + */ + now -= 11644473600000000ULL; + + if (tv != NULL) + { + uint64_t sec = now / 1000000; + uint64_t usec = now % 1000000; + + tv->tv_sec = (long)sec; + tv->tv_usec = (long)usec; + } + + if (tz != NULL) + { + /* + * TODO: implement a timezone retrieval function. + * Not urgent, since the GetDNS code always set this parameter to NULL. + */ + return -1; + } + + return 0; +} +#endif /* GETDNS_ON_WINDOWS */ \ No newline at end of file diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 10efff59..2f9856dd 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -25,6 +25,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "Config.h" + #include "extension/default_eventloop.h" #include "debug.h" @@ -32,7 +34,7 @@ static uint64_t get_now_plus(uint64_t amount) { struct timeval tv; uint64_t now; - + if (gettimeofday(&tv, NULL)) { perror("gettimeofday() failed"); exit(EXIT_FAILURE); @@ -81,8 +83,7 @@ default_eventloop_schedule(getdns_eventloop *loop, #endif default_loop->fd_events[fd] = event; default_loop->fd_timeout_times[fd] = get_now_plus(timeout); - event->ev = (void *) (intptr_t) fd + 1; - + event->ev = (void *)(intptr_t)(fd + 1); DEBUG_SCHED( "scheduled read/write at %d\n", fd); return GETDNS_RETURN_GOOD; } @@ -101,9 +102,8 @@ default_eventloop_schedule(getdns_eventloop *loop, for (i = 0; i < MAX_TIMEOUTS; i++) { if (default_loop->timeout_events[i] == NULL) { default_loop->timeout_events[i] = event; - default_loop->timeout_times[i] = get_now_plus(timeout); - event->ev = (void *) (intptr_t) i + 1; - + default_loop->timeout_times[i] = get_now_plus(timeout); + event->ev = (void *)(intptr_t)(i + 1); DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); return GETDNS_RETURN_GOOD; } @@ -219,8 +219,8 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) tv.tv_sec = 0; tv.tv_usec = 0; } else { - tv.tv_sec = (timeout - now) / 1000000; - tv.tv_usec = (timeout - now) % 1000000; + tv.tv_sec = (long)((timeout - now) / 1000000); + tv.tv_usec = (long)((timeout - now) % 1000000); } if (select(max_fd + 1, &readfds, &writefds, NULL, (timeout == ((uint64_t)-1) ? NULL : &tv)) < 0) { diff --git a/src/stub.c b/src/stub.c index 4aa14dae..8232e288 100644 --- a/src/stub.c +++ b/src/stub.c @@ -399,7 +399,11 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) upstream->addr_len) == -1) { if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK) return fd; +#ifdef USE_WINSOCK + closesocket(fd); +#else close(fd); +#endif return -1; } return fd; @@ -541,7 +545,13 @@ void _getdns_cancel_stub_request(getdns_network_req *netreq) { stub_cleanup(netreq); - if (netreq->fd >= 0) close(netreq->fd); + if (netreq->fd >= 0) { +#ifdef USE_WINSOCK + closesocket(netreq->fd); +#else + close(netreq->fd); +#endif + } } /* May be needed in future for better UDP error handling?*/ @@ -564,7 +574,12 @@ stub_timeout_cb(void *userarg) STUB_DEBUG_CLEANUP, __FUNCTION__, netreq); stub_next_upstream(netreq); stub_cleanup(netreq); - if (netreq->fd >= 0) close(netreq->fd); + if (netreq->fd >= 0) +#ifdef USE_WINSOCK + closesocket(netreq->fd); +#else + close(netreq->fd); +#endif netreq->state = NET_REQ_TIMED_OUT; if (netreq->owner->user_callback) { netreq->debug_end_time = _getdns_get_time_as_uintt64(); @@ -807,8 +822,13 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) /* Coming back from an earlier unfinished write or handshake. * Try to send remaining data */ +#ifdef USE_WINSOCK + written = send(fd, tcp->write_buf + tcp->written, + tcp->write_buf_len - tcp->written, 0); +#else written = write(fd, tcp->write_buf + tcp->written, tcp->write_buf_len - tcp->written); +#endif if (written == -1) { if (_getdns_EWOULDBLOCK) return STUB_TCP_WOULDBLOCK; @@ -1257,10 +1277,10 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp, static uint64_t _getdns_get_time_as_uintt64() { - + struct timeval tv; uint64_t now; - + if (gettimeofday(&tv, NULL)) { return 0; } @@ -1268,6 +1288,7 @@ _getdns_get_time_as_uintt64() { return now; } + /**************************/ /* UDP callback functions */ /**************************/ @@ -1305,7 +1326,11 @@ stub_udp_read_cb(void *userarg) upstream, netreq->response, read)) return; /* Client cookie didn't match? */ +#ifdef USE_WINSOCK + closesocket(netreq->fd); +#else close(netreq->fd); +#endif while (GLDNS_TC_WIRE(netreq->response)) { DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ, __FUNCTION__, netreq); @@ -1369,7 +1394,11 @@ stub_udp_write_cb(void *userarg) netreq->fd, (const void *)netreq->query, pkt_len, 0, (struct sockaddr *)&netreq->upstream->addr, netreq->upstream->addr_len)) { +#ifdef USE_WINSOCK + closesocket(netreq->fd); +#else close(netreq->fd); +#endif return; } GETDNS_SCHEDULE_EVENT( @@ -1706,7 +1735,11 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, if (fd == -1) return -1; upstream->tls_obj = tls_create_object(dnsreq, fd, upstream); if (upstream->tls_obj == NULL) { +#ifdef USE_WINSOCK + closesocket(fd); +#else close(fd); +#endif return -1; } From 471e8725e2611031e2a53dd30c7fda65e793f359 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Tue, 6 Dec 2016 14:44:40 +0000 Subject: [PATCH 042/249] Change the default profile for Stubby to use TLS then UDP/TCP - this will only try over TLS a few times before backing off to clear text - but makes the default for Stubby opportunistic privacy (Willem - WDYT?) Also use padding and ECS privacy by default for Stubby. More debugging to help users when there are failures or fallbacks. Also remove a few help options from Stubby that don't apply Add -v to output version on getdns_query/stubby --- src/context.c | 2 +- src/stub.c | 11 +++++++--- src/tools/getdns_query.c | 46 ++++++++++++++++++++++++++++------------ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/context.c b/src/context.c index 8b8413f8..d0fb6b39 100644 --- a/src/context.c +++ b/src/context.c @@ -755,7 +755,7 @@ _getdns_upstream_shutdown(getdns_upstream *upstream) upstream->conn_shutdowns = 0; upstream->conn_backoffs++; #if defined(DAEMON_DEBUG) && DAEMON_DEBUG - DEBUG_DAEMON("%s %s : !Backing off this upstream - will retry as new upstream at %s\n", + DEBUG_DAEMON("%s %s : !Backing off this upstream - Will retry as new upstream at %s", STUB_DEBUG_DAEMON, upstream->addr_str, asctime(gmtime(&upstream->conn_retry_time))); #endif diff --git a/src/stub.c b/src/stub.c index 83ab992c..ef74beb8 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1314,7 +1314,8 @@ stub_udp_read_cb(void *userarg) netreq->state = NET_REQ_FINISHED; upstream->udp_responses++; #if defined(DAEMON_DEBUG) && DAEMON_DEBUG - if (upstream->udp_responses % 100 == 0) + if (upstream->udp_responses == 1 || + upstream->udp_responses % 100 == 0) DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n", STUB_DEBUG_DAEMON, upstream->addr_str, (int)upstream->udp_responses, (int)upstream->udp_timeouts); @@ -1545,6 +1546,9 @@ upstream_write_cb(void *userarg) case STUB_NO_AUTH: /* Cleaning up after connection or auth check failure. Need to fallback. */ stub_cleanup(netreq); + DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - *Failure*\n", + STUB_DEBUG_DAEMON, upstream->addr_str, + (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP")); if (fallback_on_write(netreq) == STUB_TCP_ERROR) { /* TODO: Need new state to report transport unavailable*/ netreq->state = NET_REQ_FINISHED; @@ -1782,7 +1786,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, } upstream->conn_state = GETDNS_CONN_SETUP; #if defined(DAEMON_DEBUG) && DAEMON_DEBUG - DEBUG_DAEMON("%s %s : Conn init : Transport= %s - Profile=%s\n", STUB_DEBUG_DAEMON, + DEBUG_DAEMON("%s %s : Conn init : Transport=%s - Profile=%s\n", STUB_DEBUG_DAEMON, upstream->addr_str, transport == GETDNS_TRANSPORT_TLS ? "TLS":"TCP", dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict"); #endif @@ -1843,6 +1847,8 @@ upstream_find_for_netreq(getdns_network_req *netreq) } /* Handle better, will give generic error*/ DEBUG_STUB("%s %-35s: MSG: %p No valid upstream! \n", STUB_DEBUG_SCHEDULE, __FUNCTION__, netreq); + DEBUG_DAEMON("%s *FAILURE* no valid transports or upstreams available!\n", + STUB_DEBUG_DAEMON); return -1; } @@ -1856,7 +1862,6 @@ fallback_on_write(getdns_network_req *netreq) /* Deal with UDP one day*/ DEBUG_STUB("%s %-35s: MSG: %p FALLING BACK \n", STUB_DEBUG_SCHEDULE, __FUNCTION__, netreq); - DEBUG_DAEMON("%s Falling back...\n", STUB_DEBUG_DAEMON); /* Try to find a fallback transport*/ getdns_return_t result = _getdns_submit_stub_request(netreq); diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 92a27337..089f005e 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -51,8 +51,11 @@ typedef unsigned short in_port_t; static int i_am_stubby = 0; static const char *default_stubby_config = "{ resolution_type: GETDNS_RESOLUTION_STUB" +", dns_transport_list: [ GETDNS_TRANSPORT_TLS, GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP ]" ", idle_timeout: 10000" ", listen_addresses: [ 127.0.0.1@53, 0::1@53 ]" +", tls_query_padding_blocksize: 256" +", edns_client_subnet_private : 1" "}"; static int clear_listen_list_on_arg = 0; #ifndef GETDNS_ON_WINDOWS @@ -161,13 +164,19 @@ print_usage(FILE *out, const char *progname) { fprintf(out, "usage: %s [