From d59dfb660952a3aed29603ebd59724053f703f3e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 14 Jul 2016 14:33:24 +0200 Subject: [PATCH 001/353] New commits in src/test/jsmn --- src/test/jsmn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/jsmn b/src/test/jsmn index daa17063..49024a6e 160000 --- a/src/test/jsmn +++ b/src/test/jsmn @@ -1 +1 @@ -Subproject commit daa17063c67f0dfe873af25ab6b664641c8cf90c +Subproject commit 49024a6e11739c866bce0e9f3617278b98906ad0 From 22c1eb7f3f5471b8697421c9e2bfe00b9f84fb01 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 14 Jul 2016 20:08:02 +0200 Subject: [PATCH 002/353] Update list of contributors --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 28a4d6ab..b1507f61 100644 --- a/README.md +++ b/README.md @@ -315,6 +315,7 @@ To configure: Contributors ============ +* Claus Assman * Theogene Bucuti * Andrew Cathrow, Verisign Labs * Neil Cook @@ -322,26 +323,34 @@ Contributors * Craig Despeaux, Verisign, Inc. * John Dickinson, Sinodun * Sara Dickinson, Sinodun +* Robert Edmonds * Angelique Finan, Verisign, Inc. +* Simson Garfinkel * Daniel Kahn Gillmor * Neel Goyal, Verisign, Inc. * Bryan Graham, Verisign, Inc. +* Robert Groenenberg * Paul Hoffman * Scott Hollenbeck, Verising, Inc. * Shumon Huque, Verisign Labs +* Jelte Janssen +* Guillem Jover * Shane Kerr * Anthony Kirby * Olaf Kolkman, NLnet Labs * Sanjay Mahurpawar, Verisign, Inc. * Allison Mankin, Verisign, Inc. - Verisign Labs. * Sai Mogali, Verisign, Inc. +* Linus Nordberg * Benno Overeinder, NLnet Labs * Joel Purra +* Tom Pusateri * Prithvi Ranganath, Verisign, Inc. * Rushi Shah, Verisign, Inc. * Vinay Soni, Verisign, Inc. * Melinda Shore, No Mountain Software LLC * Bob Steagall, Verisign, Inc. +* Ondřej Surý * Willem Toorop, NLnet Labs * Gowri Visweswaran, Verisign Labs * Wouter Wijngaards, NLnet Labs From 17670cbf97206b30297b5281b3b6b35333ab5d38 Mon Sep 17 00:00:00 2001 From: Andrew Sullivan Date: Sat, 16 Jul 2016 14:13:34 -0400 Subject: [PATCH 003/353] Reorganise README for a new user to the project. Remove some things that are fixed/altered. --- README.md | 196 +++++++++++++++++++++++++----------------------------- 1 file changed, 89 insertions(+), 107 deletions(-) diff --git a/README.md b/README.md index b1507f61..e3da3df1 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,35 @@ getdns * GitHub: -getdns is an implementation of a modern asynchronous DNS API specification -originally edited by Paul Hoffman. It is intended to make all types of DNS -information easily available to application developers and non-DNS experts. -The project home page at [getdnsapi.net](https://getdnsapi.net) provides -documentation, binary downloads and news regarding the getdns API -implementation. This implementation is licensed under the New BSD License -(BSD-new). +getdns is an implementation of a modern asynchronous DNS API; the specification was originally edited by Paul Hoffman. It is intended to make all types of DNS information easily available to application developers and non-DNS experts. -This file captures the goals and direction of the project and the current state -of the implementation. +## Why you might want getdns -If you are just getting started with the library take a look at the section -below that describes building and handling external dependencies for the -library. Once it is built you should take a look at src/examples to see how -the library is used. +Traditional access to DNS data from applications has several limitations: -## Download +* APIs require applications to have considerable sophistication about DNS data and data types + +* Some kinds of data about the response (notably, the resource record set time to live) is not exposed via any API, so applications need to process raw protocol responses to get such data + +* APIs are often blocking, meaning asynchronous access is not possible without some work + +* 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. + +## 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. + +## License + +This implementation is licensed under the New BSD License (BSD-new). + +Obtaining and getting started with getdns +========================================= +The project home page at [getdnsapi.net](https://getdnsapi.net) provides documentation, binary downloads, and news regarding the getdns API implementation. This file captures the goals and direction of the project and the current state of the implementation. + +If you are just getting started with the library take a look at the section below that describes building and handling external dependencies for the library. Once it is built you should take a look at src/examples to see how the library is used. + +# Download Download the sources from our [github repo](https://github.com/getdnsapi/getdns) or from [getdnsapi.net](https://getdnsapi.net) and verify the download using @@ -29,89 +41,28 @@ the checksums (SHA1 or MD5) or using gpg to verify the signature. Our keys are available from the [pgp keyservers](https://keyserver.pgp.com) * willem@nlnetlabs.nl, key id E5F8F8212F77A498 -* gwiley@verisign.com, key id 9DC3D572A6B73532 -## Mailing lists +# Releases -We have a [getdns users list](https://getdnsapi.net/mailman/listinfo/spec) for this implementation. - -The [getdns-api mailing list](https://getdnsapi.net/mailman/listinfo/spec) -is a good place to engage in discussions regarding the design of the API. - -## 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 way that enables end-to-end trust in the DNS architecture -and will inspire application developers towards innovative security solutions -in their applications. - -## Goals - -The goals of this implementation of the getdns API are: - -* Provide an open source implementation, in C, of the formally described getdns API by getdns API team at -* Initial support for FreeBSD, OSX, Linux (CentOS/RHEL, Ubuntu) via functional "configure" script -* Initial support for Windows 8.1 -* Initial support to include the Android platform -* Include examples and tests as part of the build -* Document code using doxygen -* Leverage github as much as possible for project coordination -* Coding style/standards follow the BSD coding style - -Non-goals (things we will not be doing at least initially) include: -* implementation of the traditional DNS related routines (gethostbyname, etc.) - -## Official and Additional API - -Note that this implementation offers additional functionality to supplement that -in the official getdns API. Some additions are convenient utility functions but other functionality -is experimental prior to be being recommended for inclusion in the official API. -The 'Modules' page in the doxygen documentation provides a guide to both the -official API and the additional functionality. - -## Language Bindings - -In parallel, the team is actively developing bindings for various languages. -For more information, visit the -[wiki](https://github.com/getdnsapi/getdns/wiki/Language-Bindings). - - -Releases -======== Release numbering follows the [Semantic Versioning](http://semver.org/) approach. The code is currently under active development. The following requirements were met as conditions for the present release: * code compiles cleanly on at least the primary target platforms: OSX, RHEL/CentOS Linux, FreeBSD -* examples must compile and run clean -* clearly document supported/unsupported elements of the API +* examples must compile and run cleanly +* there must be clear documentation of supported and unsupported elements of the API +# Building and External Dependencies -Tickets/Bug Reports -=================== -Tickets and bug reports should be reported via the [GitHub issues list](https://github.com/getdnsapi/getdns/issues). - -Additionally, we have a mailing list at users@getdns.net. - - -Building/External Dependencies -============================== - -External dependencies are linked outside the getdns API build tree (we rely on configure to find them). We would like to keep the dependency tree short. -Please refer to section for building on Windows for separate dependency and build instructions. +External dependencies are linked outside the getdns API build tree (we rely on configure to find them). We would like to keep the dependency tree short. Please refer to section for building on Windows for separate dependency and build instructions for that platform. * [libunbound from NLnet Labs](https://unbound.net/) version 1.4.16 or later. -* [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1. +* [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1. (Note that the libidn version means the conversions between A-labels and U-labels may permit conversion of formally invalid labels under IDNA2008.) * [libssl and libcrypto from the OpenSSL Project](https://www.openssl.org/) version 0.9.7 or later. (Note: version 1.0.1 or later is required for TLS support, version 1.0.2 or later is required for TLS hostname authentication) -* Doxygen is used to generate documentation, while this is not technically necessary for the build it makes things a lot more pleasant. +* Doxygen is used to generate documentation; while this is not technically necessary for the build it makes things a lot more pleasant. -You have to install the library and also the library-devel (or -dev) for your -package management system to install the compile time files. If you checked -out our git you need to copy the libtool helper scripts and rebuild configure -with: +If you are installing from packages, you have to install the library and also the library-devel (or -dev) for your package management system to get the the necessary compile time files. If you checked out from git you need to copy the libtool helper scripts and rebuild configure thus: # libtoolize -ci (use glibtoolize for OS X, libtool is installed as glibtool to avoid name conflict on OS X) # autoreconf -fi @@ -126,9 +77,9 @@ If you want to use the getdns_query command line wrapper script for testing or t # make getdns_query -## Minimal dependencies +## Minimizing dependencies -* getdns can be configured for stub resolution mode only with the `--enable-stub-only` option to configure. This removed the dependency on `libunbound`. +* getdns can be configured for stub resolution mode only with the `--enable-stub-only` option to configure. This removes the dependency on `libunbound`. * Currently getdns only offers two helper functions to deal with IDN: `getdns_convert_ulabel_to_alabel` and `getdns_convert_alabel_to_ulabel`. If you do not need these functions, getdns can be configured to compile without them with the `--without-libidn` option to configure. * When both `--enable-stub-only` and `--without-libidn` options are used, getdns has only one dependency left, which is OpenSSL. @@ -140,18 +91,15 @@ 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) -NOTE: The current Windows implementation does not support the above. - ## Regression Tests A suite of regression tests are included with the library, if you make changes or just want to sanity check things on your system take a look at src/test. You will need -to install [libcheck](https://libcheck.github.io/check/). The check library is also available from -many of the package repositories for the more popular operating systems. +to install [libcheck](https://libcheck.github.io/check/). The check library is also available from many of the package repositories for the more popular operating systems. -NOTE: The current Windows implementation does not support the above. +The regression tests do not work with --enable-stub-only. -## DNSSEC +## DNSSEC dependencies For the library to be DNSSEC capable, it needs to know the root trust anchor. The library will try to load the root trust anchor from @@ -167,7 +115,49 @@ execute the following steps as root: # mkdir -p /etc/unbound # unbound-anchor -a /etc/unbound/getdns-root.key -# Unsupported Features +Support +======= + +# Mailing lists + +We have a [getdns users list](https://getdnsapi.net/mailman/listinfo/users) for this implementation. + +The [getdns-api mailing list](https://getdnsapi.net/mailman/listinfo/spec) is a good place to engage in discussions regarding the design of the API. + +# Tickets/Bug Reports + +Tickets and bug reports should be reported via the [GitHub issues list](https://github.com/getdnsapi/getdns/issues). + +Features of this release +======================== + +# Goals + +The goals of this implementation of the getdns API are: + +* Provide an open source implementation, in C, of the formally described getdns API by getdns API team at +* Support FreeBSD, OSX, Linux (CentOS/RHEL, Ubuntu) via functional "configure" script +* Support Windows 8.1 +* Include examples and tests as part of the build +* Document code using doxygen +* Leverage github as much as possible for project coordination +* Follow the BSD coding style/standards + +Non-goals (things we will not be doing at least initially) include: + +* implementation of the traditional DNS related routines (gethostbyname, etc.) + +# Official and Additional API + +Note that this implementation offers additional functionality to supplement that in the official getdns API. Some additions are convenient utility functions but other functionality is experimental prior to be being recommended for inclusion in the official API. The 'Modules' page in the doxygen documentation provides a guide to both the official API and the additional functionality. + +# Language Bindings + +In parallel, the team is actively developing bindings for various languages. +For more information, visit the +[wiki](https://github.com/getdnsapi/getdns/wiki/Language-Bindings). + +# Unsupported getDNS Features The following API calls are documented in getDNS but *not supported* by the implementation at this time: @@ -175,7 +165,7 @@ The following API calls are documented in getDNS but *not supported* by the impl * Detecting changes to resolv.conf and hosts * MDNS, NIS and NetBIOS namespaces (only DNS and LOCALFILES are supported) -## Non-uniform implementation +## Minor omissions The following minor implementation omissions are noted: @@ -189,12 +179,7 @@ Stub mode does not support: # Known Issues -There are a few known issues which we have summarized below - the most recent -and helpful list is being maintained in the git issues list in the repository. -Other known issues are being managed in the git repository issue list. - -* When doing a synchronous lookup with a context that has outstanding asynchronous lookups, the callbacks for the asynchronous lookups might get called as a side effect of the synchronous lookup. - +*the issue that was described here doesn't seem to be open in the issue tracker, and other issues there are not clearly related to this release. Replace this section with a pointer to the issue tracker?* # Supported Platforms @@ -205,7 +190,7 @@ The primary platforms targeted are Linux and FreeBSD, other platform are support * Ubuntu 14.04 * Microsoft Windows 8.1 (initial support for DNSSEC but no TLS provided for version 0.5.1) -We intend to add Android and other platforms to the releases as we have time to port it. +We intend to add Android and other platforms to future releases as we have time to port it. ## Platform Specific Build Reports @@ -220,9 +205,9 @@ If you are using FreeBSD 10 getdns can be intalled via 'pkg install getdns'. ### CentOS/RHEL 6.5 -We rely on the most excellent package manager fpm to build the linux packages which +We rely on the most excellent package manager fpm to build the linux packages, which means that the packaging platform requires ruby 2.1.0. There are other ways to -build the packages, this is simplythe one we chose to use. +build the packages; this is simply the one we chose to use. # cat /etc/redhat-release CentOS release 6.5 (Final) @@ -258,7 +243,7 @@ build the packages, this is simplythe one we chose to use. create dmg A self-compiled version of OpenSSL or the version installed via Homebrew is required. - Note: If using a self-compiled version manual configuration of certificates into /usr/local/etc/openssl/certs is required for TLS authentication to work. + Note: If using a self-compiled version, manual configuration of certificates into /usr/local/etc/openssl/certs is required for TLS authentication to work. #### Homebrew @@ -270,12 +255,9 @@ Note that in order to compile the examples, the `--with-libevent` switch is requ As of the 0.2.0 release, when installing via Homebrew, the trust anchor is expected to be located at `$(brew --prefix)/etc/getdns-root.key`. Additionally, the OpenSSL library installed by Homebrew is linked against. Note that the Homebrew OpenSSL installation clones the Keychain certificates to the default OpenSSL location so TLS certificate authentication should work out of the box. - ### Microsoft Windows 8.1 -This section has some Windows specific build instructions. - -Build tested using the following: +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. From 8c54142790f05e59a566003c28e16452fd290c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jerry=20Lundstr=C3=B6m?= Date: Sun, 17 Jul 2016 11:44:34 +0200 Subject: [PATCH 004/353] Use type and not struct --- src/getdns/getdns_extra.h.in | 4 ++-- src/util-internal.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 752076a9..7e2a16e3 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -399,11 +399,11 @@ const char *getdns_get_errorstr_by_id(uint16_t err); /* dict util */ /* set a string as bindata */ -getdns_return_t getdns_dict_util_set_string(struct getdns_dict * dict, +getdns_return_t getdns_dict_util_set_string(getdns_dict * dict, char *name, const char *value); /* get a string from a dict. the result must be freed if valid */ -getdns_return_t getdns_dict_util_get_string(struct getdns_dict * dict, +getdns_return_t getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result); /** diff --git a/src/util-internal.c b/src/util-internal.c index 47a3fd21..6934958d 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -54,7 +54,7 @@ getdns_return_t -getdns_dict_util_get_string(struct getdns_dict * dict, char *name, char **result) +getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result) { struct getdns_bindata *bindata = NULL; if (!result) { From 3372f6cf2670fe3937152959e7636c435dd26481 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 21 Jul 2016 12:19:39 +0200 Subject: [PATCH 005/353] update release-procedure.txt --- project-doc/release-procedure.txt | 144 +++++++++--------------------- 1 file changed, 43 insertions(+), 101 deletions(-) diff --git a/project-doc/release-procedure.txt b/project-doc/release-procedure.txt index 6ffe4749..6438a4cf 100644 --- a/project-doc/release-procedure.txt +++ b/project-doc/release-procedure.txt @@ -8,8 +8,8 @@ update this document and share it with us. is cut nothing should be committed to the release branch (make a new release) - create a release branch - in git repository named for the release, e.g. "v0.1.2" - we do this because folks may want to continue to work in the master 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. @@ -25,84 +25,47 @@ update this document and share it with us. use a working directory with lots of cruft - crap will find its way into the release and embarass you: - # git clone -b v0.1.2 https://github.com/getdnsapi/getdns.git getdns-0.1.2 + # 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 (AC_INIT) - ./src/Makefile.in (-version-info, follow libtool guidelines) + ./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! - # make clean - # autoreconf + # autoreconf -fi commit these changes to the release branch # git commit -a -m "release number and date updates" # git push -- prepare to build binaries for each target platform - you need to remove libs and headers that might be lingering from previous builds - to avoid accidentally including the wrong headers or linking the wrong libs +- 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: - - create clean local repo + # ${GETDNS_SRCDIR}/src/test/tpkg/run-all.sh -- build source distribution tar + and evaluate the results. + +- build and sign source distribution tarball: + # rm -fr * + # git reset --hard + # git submodule update --init + # autoreconf -fi + # libtoolize -ci # ./configure - # make dist - # openssl sha1 getdns-0.1.2.tar.gz > getdns-0.1.2.tar.gz.sha1 - # openssl md5 getdns-0.1.2.tar.gz > getdns-0.1.2.tar.gz.md5 - # gpg --armor --detach-sig --default-key gwiley@verisign.com getdns-0.1.2.tar.gz + # make pub - test the resulting tar by building it and running the regression tests - -- build CentOS binary - # tar -xzvf getdns-0.1.2.tar.gz - # cd getdns-0.1.2 - # ./configure --with-libevent --prefix=$HOME/build - # make - # make install - # cd ~/build - - fix the libdir path in the *.la files to point to /usr/local/lib - - fix the dependency_libs entry in the *.la files to point to /usr/local/lib - # fpm -x "*.la" -a native -s dir --rpm-sign -t rpm -n getdns -v 0.1.2 -d "unbound" -d "ldns" -d "libevent" -d "libidn" --prefix /usr/local --vendor "Verisign Inc., NLnet Labs" --license "BSD New" --url "http://www.getdnsapi.net" --description "Modern asynchronous API to the DNS" . - - make sure your signing key is in the keyring on the build machine - - contents of ~/.rpmmacros - %_signature gpg - %_gpg_path /root/.gnupg - %_gpg_name A6B73532 - %_gpgbin /usr/bin/gpg - - - name the rpm and checksum files something like this: - getdns-0.1.3-1.CentOS_6_5.x86_64.rpm - getdns-0.1.3-1.CentOS_6_5.x86_64.rpm.sha1 - getdns-0.1.3-1.CentOS_6_5.x86_64.rpm.md5 - - check the signature - - install - - test - -- build OSX binary disk image - - - build code (no additional libraries, note that regression tests will not build) - if you are building a simple binary tar then something like this works - # ./configure --prefix=/Users/gwiley/getdnsox/export - # make - # make install - # tar -C /Users/gwiley/getdnsosx/export -cvf getdns-0.1.2.tar * - - - build code (with libevent) - # ./configure --with-libevent2 - - - run regression tests and verify that alls well - - if you have do do anything even mildly interesting to get the build or install to - work then we either have to add it to the README.md or, preferably, fix it - and update the branch - - Be careful about tool sets loaded on your build hosts. You may have 'solved' - problems while you are working that mask issues with the build for more typical - users - this is why we want to build on hosts that are representative of - our users. + on as many different systems as you can. - install on each target platform - make sure and use a user that was NOT used for the build, this will uncover @@ -114,55 +77,34 @@ update this document and share it with us. - merge branch changes back into master - once all binaries are built and tested clean, create source tar ball - and the actual package for each platform you may need to run this as root to permit the chown # make clean - # make dist - generates getdns-0.1.2.tar.gz + # make pub + generates getdns-1.0.0-b3.tar.gz + checksums + signatures -- sign each binary/source tar using one or more developers keys - - make sure that the keys you use to sign the release are also up to date - on the getdnsapi.net site +- upload source tarball and checsums and signatures to the getdnsapi.net site -- generate checksums for each binary/source tar + # scp getdns-1.0.0-b3.tar.gz* getdnsapi.net:/usr/local/www/apache24/data/dist -- upload source and binaries to the getdnsapi.net site +- Create and push signed tags to github -- create a release in the github repository - - from the main repo choose 'releases' - - choose 'Draft a new release' - - use tag v0.x.y to match the branch being released - - for a release name use v0.x.y - - for description cut/paste the ChangeLog entry - - check the 'pre-release' checkbox (unless this is a production release) + # git -s v1.0.0-b3 + # git push --tags - update getdnsapi.net web site - - push binaries to getdnsapi.net + - 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 - - news entry for the release - /usr/local/www/apache24/data/news.html - - download links and checksums - /usr/local/www/apache24/data/frontpage.html + 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 - # ./build.sh + # cd /usr/local/www/apache24 + # ./build_site.py - announce message to - getdns mailing list - stub-resolvers mailing list - Verisign internal via the matrix - -- update the + users@getdnsapi.net, spec@getdnsapi.net and maintainers@nlnetlabs.nl -List of Build Targets ---------------------- -The naming conventions for each of these build products are specific to the -platform they target. The result is that the naming seems a little inconsistent, -however I felt that it is best to follow naming standards for the platform rather -than try to impose a project specific standard across platforms. - -- source tar: getdns-0.1.2.tar.gz -- OSX binary package: getdns-0.1.2-OSX_10_8.dmg -- RHEL/CentOS: getdns-0.1.0-1.CentOS_6_5.x86_64.rpm -- Debian/Ubuntu: From 96060ed6ae2505b09e318dcc741771cb4fef91d3 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 21 Jul 2016 12:24:41 +0200 Subject: [PATCH 006/353] Update README, credit Andrew --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e3da3df1..623a786f 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ Stub mode does not support: # Known Issues -*the issue that was described here doesn't seem to be open in the issue tracker, and other issues there are not clearly related to this release. Replace this section with a pointer to the issue tracker?* +* None # Supported Platforms @@ -188,7 +188,7 @@ The primary platforms targeted are Linux and FreeBSD, other platform are support * RHEL/CentOS 6.4 * OSX 10.8 * Ubuntu 14.04 -* Microsoft Windows 8.1 (initial support for DNSSEC but no TLS provided for version 0.5.1) +* Microsoft Windows 8.1 We intend to add Android and other platforms to future releases as we have time to port it. @@ -332,6 +332,7 @@ Contributors * Vinay Soni, Verisign, Inc. * Melinda Shore, No Mountain Software LLC * Bob Steagall, Verisign, Inc. +* Andrew Sullivan * Ondřej Surý * Willem Toorop, NLnet Labs * Gowri Visweswaran, Verisign Labs From 5c6f03632613aaa3b29972844b16ff0b11f8f8d8 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 21 Jul 2016 20:25:31 +0200 Subject: [PATCH 007/353] 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 008/353] 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 009/353] 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 010/353] 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 011/353] 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 012/353] 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 013/353] 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 014/353] 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 015/353] 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 016/353] 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 017/353] 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 018/353] 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 019/353] 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 020/353] 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 021/353] 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 022/353] 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 023/353] 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 024/353] 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 025/353] 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 026/353] 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 027/353] 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 028/353] 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 029/353] 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 030/353] 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 031/353] 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 032/353] 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 033/353] 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 034/353] 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 035/353] 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 036/353] 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 037/353] 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 038/353] 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 039/353] 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 040/353] 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 041/353] 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 042/353] 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 043/353] 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 044/353] 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 045/353] 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 046/353] 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 047/353] 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 048/353] 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 [