mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'develop' into feature/cmake
This commit is contained in:
commit
1d712cfa45
|
@ -39,6 +39,7 @@ src/test/check_getdns_ev
|
|||
src/test/scratchpad
|
||||
src/test/scratchpad.c
|
||||
src/tools/getdns_query
|
||||
src/tools/getdns_server_mon
|
||||
src/stubby
|
||||
doc/*.3
|
||||
src/getdns/getdns.h
|
||||
|
|
|
@ -4,8 +4,13 @@
|
|||
branch = getdns
|
||||
[submodule "src/yxml"]
|
||||
path = src/yxml
|
||||
url = git://g.blicky.net/yxml.git
|
||||
url = https://github.com/getdnsapi/yxml.git
|
||||
branch = master
|
||||
[submodule "stubby"]
|
||||
path = stubby
|
||||
url = https://github.com/getdnsapi/stubby.git
|
||||
branch = develop
|
||||
[submodule "src/ssl_dane"]
|
||||
path = src/ssl_dane
|
||||
url = https://github.com/getdnsapi/ssl_dane
|
||||
branch = getdns
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
sudo: false
|
||||
dist: xenial
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
|
@ -6,6 +7,7 @@ compiler:
|
|||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libssl-dev
|
||||
- libunbound-dev
|
||||
- libidn11-dev
|
||||
- libyaml-dev
|
||||
|
|
138
ChangeLog
138
ChangeLog
|
@ -1,3 +1,135 @@
|
|||
* 2019-04-03: Version 1.5.2
|
||||
* PR #424: Two small trust anchor fetcher fixes
|
||||
Thanks Maciej S. Szmigiero
|
||||
* Issue #422: Enable server side and update client side TCP Fast
|
||||
Open implementation. Thanks Craig Andrews
|
||||
* Issue #423: Fix insecure delegation detection while scheduling.
|
||||
Thanks Charles Milette
|
||||
* Issue #419: Escape backslashed when printing in JSON format.
|
||||
Thanks boB Rudis
|
||||
* Use GnuTLS instead of OpenSSL for TLS with the --with-gnutls
|
||||
option to configure. libcrypto (from OpenSSL) still needed
|
||||
for Zero configuration DNSSEC.
|
||||
* DOA rr-type
|
||||
* AMTRELAY rr-type
|
||||
|
||||
* 2019-01-11: Version 1.5.1
|
||||
* Introduce proof of concept GnuTLS implementation. Incomplete support
|
||||
for Trust Anchor validation. Requires GnuTLS DANE library. Currently
|
||||
untested with GnuTLS prior to 3.5.19, so configure demands a minumum
|
||||
version of 3.5.0.
|
||||
* Be consistent and always fail connection setup if setting ciphers/curves/
|
||||
TLS version/cipher suites fails.
|
||||
* Refactor OpenSSL usage into modules under src/openssl.
|
||||
Drop support for LibreSSL and versions of OpenSSL prior to 1.0.2.
|
||||
* PR #414: remove TLS13 ciphers from cipher_list, but
|
||||
only when SSL_CTX_set_ciphersuites is available.
|
||||
Thanks Bruno Pagani
|
||||
* Issue #415: Filter out #defines etc. when creating
|
||||
symbols file. Thanks Zero King
|
||||
|
||||
* 2018-12-21: Version 1.5.0
|
||||
* RFE getdnsapi/stubby#121 log re-instantiating TLS
|
||||
upstreams (because they reached tls_backoff_time) at
|
||||
log level 4 (WARNING)
|
||||
* GETDNS_RESPSTATUS_NO_NAME for NODATA answers too
|
||||
* ZONEMD rr-type
|
||||
* getdns_query queries for addresses when a query name
|
||||
without a type is given.
|
||||
* RFE #408: Fetching of trust anchors will be retried
|
||||
after failure, after a certain backoff time. The time
|
||||
can be configured with
|
||||
getdns_context_set_trust_anchors_backoff_time().
|
||||
* RFE #408: A "dnssec" extension that requires DNSSEC
|
||||
verification. When this extension is set, Indeterminate
|
||||
DNSSEC status will not be returned.
|
||||
* Issue #410: Unspecified ownership of get_api_information()
|
||||
* Fix for DNSSEC bug in finding most specific key when
|
||||
trust anchor proves non-existance of one of the labels
|
||||
along the authentication chain other than the non-
|
||||
existance of a DS record on a zonecut.
|
||||
* Enhancement getdnsapi/stubby#56 & getdnsapi/stubby#130:
|
||||
Configurable minimum and maximum TLS versions with
|
||||
getdns_context_set_tls_min_version() and
|
||||
getdns_context_set_tls_max_version() functions and
|
||||
tls_min_version and tls_max_version configuration parameters
|
||||
for upstreams.
|
||||
* Configurable TLS1.3 ciphersuites with the
|
||||
getdns_context_set_tls_ciphersuites() function and
|
||||
tls_ciphersuites config parameter for upstreams.
|
||||
* Bugfix in upstream string configurations: tls_cipher_list and
|
||||
tls_curve_list
|
||||
* Bugfix finding signer for validating NSEC and NSEC3s, which
|
||||
caused trouble with the partly tracing DNSSEC from the root
|
||||
up, introduced in 1.4.2. Thanks Philip Homburg
|
||||
|
||||
* 2018-05-11: Version 1.4.2
|
||||
* Bugfix getdnsapi/stubby#87: Detect and ignore duplicate certs
|
||||
in the Windows root CA store.
|
||||
* PR #397: No TCP sendto without TCP_FASTOPEN
|
||||
Thanks Emery Hemingway
|
||||
* Bugfix getdnsapi/stubby#106: Core dump when printing certain
|
||||
configuration. Thanks Han Vinke
|
||||
* Bugfix getdnsapi/stubby#99: Partly trace DNSSEC from the root
|
||||
up (for tld and sld), to find insecure delegations quicker.
|
||||
Thanks UniverseXXX
|
||||
* Bugfix: Allow NSEC spans starting from (unexpanded) wildcards
|
||||
Bug was introduced when dealing with CVE-2017-15105
|
||||
* Bugfix getdnsapi/stubby#46: Don't assume trailing zero with
|
||||
string bindata's. Thanks Lonnie Abelbeck
|
||||
* Bugfix #394: Update src/compat/getentropy_linux.c in order to
|
||||
handle ENOSYS (not implemented) fallback.
|
||||
Thanks Brent Blood
|
||||
* Bugfix #395: Clarify that libidn2 dependency is for version 2.0.0
|
||||
or higher. Thanks mire3212
|
||||
|
||||
* 2018-03-12: Version 1.4.1
|
||||
* Bugfix #388: Prevent fallback to an earlier tries upstream within a
|
||||
single query. Thanks Robert Groenenberg
|
||||
* PR #387: Compile with OpenSSL with deprecated APIs disabled.
|
||||
Thanks Rosen Penev
|
||||
* PR #386: UDP failover improvements:
|
||||
- When all UDP upstreams fail, retry them (more or less) equally
|
||||
- Limit maximum UDP backoff (default to 1000)
|
||||
This is configurable with the --with-max-udp-backoff configure
|
||||
option.
|
||||
Thanks Robert Groenenberg
|
||||
* Bugfix: Find zonecut with DS queries (instead of SOA queries).
|
||||
Thanks Elmer Lastdrager
|
||||
* Bugfix #385: Verifying insecure NODATA answers (broken since 1.2.1).
|
||||
Thanks hanvinke
|
||||
* PR #384: Fix minor spelling and formatting. Thanks dkg.
|
||||
* Bugfix #382: Parallel install of getdns_query and getdns_server_mon
|
||||
|
||||
* 2018-02-21: Version 1.4.0
|
||||
* .so revision bump to please fedora packaging system.
|
||||
Thanks Paul Wouters
|
||||
* Specify the supported curves with getdns_context_set_tls_curves_list()
|
||||
An upstream specific list of supported curves may also be given
|
||||
with the tls_curves_list setting in the upstream dict with
|
||||
getdns_context_set_upstream_recursive_servers()
|
||||
* New tool getdns_server_mon for checking upstream recursive
|
||||
resolver's capabilities.
|
||||
* Improved handling of opportunistic back-off. If other transports
|
||||
are working, don’t forcibly promote failed upstreams just wait for
|
||||
the re-try timer.
|
||||
* Hostname authentication with libressl
|
||||
Thanks Norbert Copones
|
||||
* Security bugfix in response to CVE-2017-15105. Although getdns was
|
||||
not vulnerable for this specific issue, as a precaution code has been
|
||||
adapted so that signatures of DNSKEYs, DSs, NSECs and NSEC3s can not
|
||||
be wildcard expansions when used with DNSSEC proofs. Only direct
|
||||
queries for those types are allowed to be wildcard expansions.
|
||||
* Bugfix PR#379: Miscelleneous double free or corruption, and corrupted
|
||||
memory double linked list detected issue, with serving functionality.
|
||||
Thanks maddie and Bruno Pagani
|
||||
* Security Bugfix PR#293: Check sha256 pinset's
|
||||
with OpenSSL native DANE functions for OpenSSL >= 1.1.0
|
||||
with Viktor Dukhovni's danessl library for OpenSSL >= 1.0.0
|
||||
don't allow for authentication exceptions (like self-signed
|
||||
certificates) otherwise. Thanks Viktor Dukhovni
|
||||
* libidn2 support. Thanks Paul Wouters
|
||||
|
||||
* 2017-12-21: Version 1.3.0
|
||||
* Bugfix #300: Detect dnsmasq and skip unit test that fails with it.
|
||||
Thanks Tim Rühsen and Konomi Kitten
|
||||
|
@ -206,7 +338,7 @@
|
|||
Allow misshing "address_type" in address dicts.
|
||||
* TLS session resumption
|
||||
* -C <config file> option to getdns_query to configure context
|
||||
from a json like formated file. The output of -i (print API
|
||||
from a json like formatted file. The output of -i (print API
|
||||
information) can be used as config file directly.
|
||||
Settings may also be given in this format as arguments of
|
||||
the getdns_query command directly.
|
||||
|
@ -355,7 +487,7 @@
|
|||
* 2015-09-04: Version 0.3.2
|
||||
* Fix returned upstreams list by getdns_context_get_api_information()
|
||||
* Fix some autoconf issues when srcdir != builddir
|
||||
* Fix remove build date from manpage version for reproducable builds
|
||||
* Fix remove build date from manpage version for reproducible builds
|
||||
* Fix transport fallback issues plus transport fallback unit test script
|
||||
* Fix string bindata's need not contain trailing zero byte
|
||||
* --enable-stub-only configure option for stub only operation.
|
||||
|
@ -508,7 +640,7 @@
|
|||
* Build from separate build directory
|
||||
* Anticipate libunbound not returning the answer packet
|
||||
* Pretty print bindata's representing IP addresses
|
||||
* Anticipate absense of implicit DSO linking
|
||||
* Anticipate absence of implicit DSO linking
|
||||
* Mention getdns specific options to configure in INSTALL
|
||||
Thanks Paul Hoffman
|
||||
* Mac OSX package built instructions for generic user in README.md
|
||||
|
|
40
Makefile.in
40
Makefile.in
|
@ -44,7 +44,7 @@ libdir = @libdir@
|
|||
srcdir = @srcdir@
|
||||
INSTALL = @INSTALL@
|
||||
|
||||
all : default @GETDNS_QUERY@
|
||||
all : default @GETDNS_QUERY@ @GETDNS_SERVER_MON@
|
||||
|
||||
everything: default
|
||||
cd src/test && $(MAKE)
|
||||
|
@ -55,7 +55,7 @@ default:
|
|||
install-lib:
|
||||
cd src && $(MAKE) install
|
||||
|
||||
install: getdns.pc getdns_ext_event.pc install-lib @INSTALL_GETDNS_QUERY@
|
||||
install: getdns.pc getdns_ext_event.pc install-lib @INSTALL_GETDNS_QUERY@ @INSTALL_GETDNS_SERVER_MON@
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
|
||||
$(INSTALL) -m 644 $(srcdir)/AUTHORS $(DESTDIR)$(docdir)
|
||||
$(INSTALL) -m 644 $(srcdir)/ChangeLog $(DESTDIR)$(docdir)
|
||||
|
@ -93,7 +93,7 @@ install: getdns.pc getdns_ext_event.pc install-lib @INSTALL_GETDNS_QUERY@
|
|||
@echo "*** trust anchor management keeping it up-to-date."
|
||||
@echo "***"
|
||||
|
||||
uninstall: @UNINSTALL_GETDNS_QUERY@
|
||||
uninstall: @UNINSTALL_GETDNS_QUERY@ @UNINSTALL_GETDNS_SERVER_MON@
|
||||
rm -rf $(DESTDIR)$(docdir)
|
||||
cd doc && $(MAKE) $@
|
||||
cd src && $(MAKE) $@
|
||||
|
@ -110,6 +110,9 @@ test: default
|
|||
getdns_query: default
|
||||
cd src/tools && $(MAKE) $@
|
||||
|
||||
getdns_server_mon: default
|
||||
cd src/tools && $(MAKE) $@
|
||||
|
||||
stubby:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
|
@ -125,6 +128,12 @@ install-getdns_query: install-lib
|
|||
uninstall-getdns_query:
|
||||
cd src/tools && $(MAKE) $@
|
||||
|
||||
install-getdns_server_mon: install-lib @INSTALL_GETDNS_QUERY@
|
||||
cd src/tools && $(MAKE) $@
|
||||
|
||||
uninstall-getdns_server_mon:
|
||||
cd src/tools && $(MAKE) $@
|
||||
|
||||
install-stubby:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
|
@ -156,7 +165,7 @@ distclean:
|
|||
rm -f m4/ltoptions.m4
|
||||
rm -f m4/ltsugar.m4
|
||||
rm -f m4/ltversion.m4
|
||||
rm -f $(distdir).tar.gz $(distdir).tar.gz.sha256
|
||||
rm -f $(distdir).tar.gz $(distdir).tar.gz.sha256 $(distdir).tar.gz.sha1
|
||||
rm -f $(distdir).tar.gz.md5 $(distdir).tar.gz.asc
|
||||
|
||||
megaclean:
|
||||
|
@ -168,11 +177,14 @@ autoclean: megaclean
|
|||
|
||||
dist: $(distdir).tar.gz
|
||||
|
||||
pub: $(distdir).tar.gz.sha256 $(distdir).tar.gz.md5 $(distdir).tar.gz.asc
|
||||
pub: $(distdir).tar.gz.sha256 $(distdir).tar.gz.md5 $(distdir).tar.gz.asc $(distdir).tar.gz.sha1
|
||||
|
||||
$(distdir).tar.gz.sha256: $(distdir).tar.gz
|
||||
openssl sha256 $(distdir).tar.gz >$@
|
||||
|
||||
$(distdir).tar.gz.sha1: $(distdir).tar.gz
|
||||
openssl sha1 $(distdir).tar.gz >$@
|
||||
|
||||
$(distdir).tar.gz.md5: $(distdir).tar.gz
|
||||
openssl md5 $(distdir).tar.gz >$@
|
||||
|
||||
|
@ -201,15 +213,22 @@ $(distdir):
|
|||
mkdir -p $(distdir)/src/compat
|
||||
mkdir -p $(distdir)/src/util
|
||||
mkdir -p $(distdir)/src/gldns
|
||||
mkdir -p $(distdir)/src/tls/validator
|
||||
mkdir -p $(distdir)/src/gnutls
|
||||
mkdir -p $(distdir)/src/openssl
|
||||
mkdir -p $(distdir)/src/tools
|
||||
mkdir -p $(distdir)/src/jsmn
|
||||
mkdir -p $(distdir)/src/yxml
|
||||
mkdir -p $(distdir)/src/ssl_dane
|
||||
mkdir -p $(distdir)/doc
|
||||
mkdir -p $(distdir)/spec
|
||||
mkdir -p $(distdir)/spec/example
|
||||
mkdir -p $(distdir)/stubby
|
||||
mkdir -p $(distdir)/stubby/src
|
||||
mkdir -p $(distdir)/stubby/src/yaml
|
||||
mkdir -p $(distdir)/stubby/doc
|
||||
mkdir -p $(distdir)/stubby/systemd
|
||||
mkdir -p $(distdir)/stubby/contrib/upstart
|
||||
cp $(srcdir)/configure.ac $(distdir)
|
||||
cp $(srcdir)/configure $(distdir)
|
||||
cp $(srcdir)/AUTHORS $(distdir)
|
||||
|
@ -244,6 +263,10 @@ $(distdir):
|
|||
cp -r $(srcdir)/src/util/orig-headers $(distdir)/src/util
|
||||
cp -r $(srcdir)/src/util/auxiliary $(distdir)/src/util
|
||||
cp $(srcdir)/src/gldns/*.[ch] $(distdir)/src/gldns
|
||||
cp $(srcdir)/src/tls/*.[ch] $(distdir)/src/tls
|
||||
cp $(srcdir)/src/tls/validator/*.[ch] $(distdir)/src/tls/validator
|
||||
cp $(srcdir)/src/gnutls/*.[ch] $(distdir)/src/gnutls
|
||||
cp $(srcdir)/src/openssl/*.[ch] $(distdir)/src/openssl
|
||||
cp $(srcdir)/doc/Makefile.in $(distdir)/doc
|
||||
cp $(srcdir)/doc/*.in $(distdir)/doc
|
||||
cp $(srcdir)/doc/manpgaltnames $(distdir)/doc
|
||||
|
@ -258,12 +281,19 @@ $(distdir):
|
|||
cp $(srcdir)/stubby/src/yaml/*.[ch] $(distdir)/stubby/src/yaml
|
||||
cp $(srcdir)/stubby/COPYING $(distdir)/stubby
|
||||
cp $(srcdir)/stubby/README.md $(distdir)/stubby
|
||||
cp $(srcdir)/stubby/doc/stubby.1.in $(distdir)/stubby/doc
|
||||
cp $(srcdir)/stubby/systemd/README.md $(distdir)/stubby/systemd
|
||||
cp $(srcdir)/stubby/systemd/stubby.conf $(distdir)/stubby/systemd
|
||||
cp $(srcdir)/stubby/systemd/stubby.service $(distdir)/stubby/systemd
|
||||
cp $(srcdir)/stubby/contrib/upstart/stubby.conf $(distdir)/stubby/contrib/upstart
|
||||
cp $(srcdir)/src/jsmn/*.[ch] $(distdir)/src/jsmn
|
||||
cp $(srcdir)/src/jsmn/LICENSE $(distdir)/src/jsmn
|
||||
cp $(srcdir)/src/jsmn/README.md $(distdir)/src/jsmn
|
||||
cp $(srcdir)/src/yxml/*.[ch] $(distdir)/src/yxml
|
||||
cp $(srcdir)/src/yxml/COPYING $(distdir)/src/yxml
|
||||
cp $(srcdir)/src/yxml/yxml.pod $(distdir)/src/yxml
|
||||
cp $(srcdir)/src/ssl_dane/danessl.[ch] $(distdir)/src/ssl_dane
|
||||
cp $(srcdir)/src/ssl_dane/README.md $(distdir)/src/ssl_dane
|
||||
rm -f $(distdir)/Makefile $(distdir)/src/Makefile $(distdir)/src/getdns/getdns.h $(distdir)/spec/example/Makefile $(distdir)/src/test/Makefile $(distdir)/doc/Makefile $(distdir)/src/config.h
|
||||
|
||||
distcheck: $(distdir).tar.gz
|
||||
|
|
17
README.md
17
README.md
|
@ -70,13 +70,13 @@ If you are installing from packages, you have to install the library and also th
|
|||
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. (Note that the libidn version means the conversions between A-labels and U-labels may permit conversion of formally invalid labels under IDNA2008.)
|
||||
* [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1 or 2 (from version 2.0.0 and higher). (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.
|
||||
|
||||
For example, to build on a recent version of Ubuntu, you would need the following packages:
|
||||
|
||||
# apt install build-essential libunbound-dev libidn11-dev libssl-dev libtool m4 autoconf
|
||||
# apt install build-essential libunbound-dev libidn2-dev libssl-dev libtool m4 autoconf
|
||||
|
||||
If you are building from git, you need to do the following before building:
|
||||
|
||||
|
@ -87,10 +87,11 @@ If you are building from git, you need to do the following before building:
|
|||
# autoreconf -fi
|
||||
|
||||
|
||||
As well as building the getdns library two other tools may be installed:
|
||||
As well as building the getdns library three other tools may be installed:
|
||||
|
||||
* getdns_query: a command line test script wrapper for getdns
|
||||
* stubby: an experimental DNS Privacy enabled client
|
||||
* getdns_server_mon: test DNS server function and capabilities
|
||||
|
||||
Note: If you only want to build stubby, then use the `--with-stubby` option when running 'configure'.
|
||||
|
||||
|
@ -98,15 +99,15 @@ Note: If you only want to build stubby, then use the `--with-stubby` option when
|
|||
## Minimizing dependencies
|
||||
|
||||
* 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.
|
||||
* 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` and `--without-libidn2` options to configure.
|
||||
* When `--enable-stub-only`, `--without-libidn` and `--without-libidn2` options are used, getdns has only one dependency left, which is OpenSSL.
|
||||
|
||||
## Extensions and Event loop dependencies
|
||||
|
||||
The implementation works with a variety of event loops, each built as a separate shared library. See [this Doxygen page](https://getdnsapi.net/doxygen/group__eventloops.html) and [this man page](https://getdnsapi.net/documentation/manpages/#ASYNCHRONOUS USE) for more details.
|
||||
|
||||
* [libevent](http://libevent.org). Note: the examples *require* this and should work with either libevent 1.x or 2.x. 2.x is preferred.
|
||||
* [libuv](https://github.com/joyent/libuv)
|
||||
* [libuv](https://libuv.org/)
|
||||
* [libev](http://software.schmorp.de/pkg/libev.html)
|
||||
|
||||
## Stubby
|
||||
|
@ -133,9 +134,9 @@ format. Note that this is different than the format of BIND.keys.
|
|||
|
||||
When the root trust anchor is not installed in the default location and a DNSSEC query is done, getdns will try to use the trust anchors published here: http://data.iana.org/root-anchors/root-anchors.xml .
|
||||
It will validate these anchors with the ICANN Certificate Authority certificate following the procedure described in [RFC7958].
|
||||
The `root-anchors.xml` and `root-anchors.p7s` S/MIME signature will be cached in the `$HOME/.getdns` directory.
|
||||
The `root-anchors.xml` and `root-anchors.p7s` S/MIME signature will be cached in the `$HOME/.getdns` directory on Unixes, and the `%appdata%\getdns` directory on Windows.
|
||||
|
||||
When using trust-anchors from the `root-anchors.xml` file, getdns will track the keys in the root DNSKEY rrset and store a copy in $HOME/.getdns/root.key.
|
||||
When using trust-anchors from the `root-anchors.xml` file, getdns will track the keys in the root DNSKEY rrset and store a copy in `$HOME/.getdns/root.key` on Unixes, and `%appdata%\getdns\root.key` on Windows.
|
||||
Only when the KSK DNSKEY's change, a new version of `root-anchors.xml` is tried to be retrieved from [data.iana.org](https://data.iana.org/root-anchors/).
|
||||
|
||||
A installed trust-anchor from the default location (`/etc/unbound/getdns-root.key`) that fails to validate the root DNSKEY RRset, will also trigger the "Zero configuration DNSSEC" procedure described above.
|
||||
|
|
333
configure.ac
333
configure.ac
|
@ -33,10 +33,11 @@ AC_PREREQ([2.68])
|
|||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
sinclude(./m4/acx_openssl.m4)
|
||||
sinclude(./m4/acx_getaddrinfo.m4)
|
||||
sinclude(./m4/ac_lib_nettle.m4)
|
||||
sinclude(./m4/ax_check_compile_flag.m4)
|
||||
sinclude(./m4/pkg.m4)
|
||||
|
||||
AC_INIT([getdns], [1.3.0], [team@getdnsapi.net], [getdns], [https://getdnsapi.net])
|
||||
AC_INIT([getdns], [1.5.2], [team@getdnsapi.net], [getdns], [https://getdnsapi.net])
|
||||
|
||||
# Autoconf 2.70 will have set up runstatedir. 2.69 is frequently (Debian)
|
||||
# patched to do the same, but frequently (MacOS) not. So add a with option
|
||||
|
@ -49,10 +50,11 @@ AC_ARG_WITH([piddir],
|
|||
[with_piddir=${default_piddir}])
|
||||
AC_SUBST([runstatedir], [$with_piddir])
|
||||
|
||||
# Dont forget to put a dash in front of the release candidate!!!
|
||||
# Don't forget to put a dash in front of the release candidate!!!
|
||||
# That is how it is done with semantic versioning!
|
||||
#
|
||||
AC_SUBST(RELEASE_CANDIDATE, [])
|
||||
AC_SUBST(STUBBY_RELEASE_CANDIDATE, [])
|
||||
|
||||
# Set current date from system if not set
|
||||
AC_ARG_WITH([current-date],
|
||||
|
@ -62,11 +64,13 @@ AC_ARG_WITH([current-date],
|
|||
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
|
||||
|
||||
AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
|
||||
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01030000])
|
||||
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01050200])
|
||||
AC_SUBST(API_VERSION, ["December 2015"])
|
||||
AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
|
||||
GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
|
||||
|
||||
AC_DEFINE_UNQUOTED([STUBBY_PACKAGE], ["stubby"], [Stubby package])
|
||||
AC_DEFINE_UNQUOTED([STUBBY_PACKAGE_STRING], ["0.2.6$STUBBY_RELEASE_CANDIDATE"], [Stubby package string])
|
||||
|
||||
# Library version
|
||||
# ---------------
|
||||
|
@ -99,9 +103,14 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRE
|
|||
# getdns-1.1.3 had libversion 7:1:1
|
||||
# getdns-1.2.0 had libversion 8:0:2
|
||||
# getdns-1.2.1 had libversion 8:1:2
|
||||
# getdns-1.3.0 has libversion 9:0:3
|
||||
#
|
||||
GETDNS_LIBVERSION=9:0:3
|
||||
# getdns-1.3.0 had libversion 9:0:3
|
||||
# getdns-1.4.0 had libversion 10:0:0
|
||||
# getdns-1.4.1 had libversion 10:1:0
|
||||
# getdns-1.4.2 had libversion 10:2:0
|
||||
# getdns-1.5.0 had libversion 11:0:1
|
||||
# getdns-1.5.1 had libversion 11:1:1
|
||||
# getdns-1.5.2 has libversion 11:2:1
|
||||
GETDNS_LIBVERSION=11:2:1
|
||||
|
||||
AC_SUBST(GETDNS_COMPILATION_COMMENT)
|
||||
AC_SUBST(GETDNS_LIBVERSION)
|
||||
|
@ -294,13 +303,31 @@ if test "x$enable_tcp_fastopen" = xno; then
|
|||
AC_MSG_WARN([TCP Fast Open is disabled])
|
||||
else
|
||||
case `uname` in
|
||||
Linux) AC_CHECK_DECL([MSG_FASTOPEN], [AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])],
|
||||
[AC_MSG_WARN([TCP Fast Open is not available, continuing without])], [#include <sys/socket.h>])
|
||||
;;
|
||||
Darwin) AC_CHECK_DECL([CONNECT_RESUME_ON_READ_WRITE], [AC_DEFINE_UNQUOTED([USE_OSX_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])],
|
||||
[AC_MSG_WARN([TCP Fast Open is not available, continuing without])], [#include <sys/socket.h>])
|
||||
;;
|
||||
*) AC_MSG_WARN([TCP Fast Open is not available, continuing without])
|
||||
*)
|
||||
AC_CHECK_HEADERS([sys/socket.h netinet/tcp.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_DECL([TCP_FASTOPEN], [
|
||||
AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])
|
||||
AC_CHECK_DECLS([TCP_FASTOPEN,MSG_FASTOPEN,TCP_FASTOPEN_CONNECT], [], [], [AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
# include <netinet/tcp.h>
|
||||
#endif
|
||||
])
|
||||
], [
|
||||
AC_MSG_WARN([TCP Fast Open is not available, continuing without])
|
||||
], [AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
# include <netinet/tcp.h>
|
||||
#endif
|
||||
])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
@ -374,6 +401,10 @@ no)
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_WITH(max-udp-backoff, AS_HELP_STRING([--with-max-udp-backoff=<number of queries>],
|
||||
[Set the maximum number of messages that can be sent to other upstreams before the upstream which has previously timed out will be tried again. (defaults to 1000)]),, [withval="1000"])
|
||||
AC_DEFINE_UNQUOTED([UDP_MAX_BACKOFF], [$withval], [Maximum number of queries an failed UDP upstream passes before it will retry])
|
||||
|
||||
#---- check for pthreads library
|
||||
AC_ARG_WITH(libpthread, AS_HELP_STRING([--without-libpthread],
|
||||
[Disable libpthread (default is autodetect)]),
|
||||
|
@ -391,25 +422,113 @@ yes)
|
|||
esac
|
||||
|
||||
USE_NSS="no"
|
||||
dnl AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path],
|
||||
dnl [use libnss instead of openssl, installed at path.]),
|
||||
dnl [
|
||||
dnl USE_NSS="yes"
|
||||
dnl AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto])
|
||||
dnl if test "$withval" != "" -a "$withval" != "yes"; then
|
||||
dnl CPPFLAGS="$CPPFLAGS -I$withval/include/nss3"
|
||||
dnl LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
dnl ACX_RUNTIME_PATH_ADD([$withval/lib])
|
||||
dnl CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS"
|
||||
dnl else
|
||||
dnl CPPFLAGS="$CPPFLAGS -I/usr/include/nss3"
|
||||
dnl CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
|
||||
dnl fi
|
||||
dnl LIBS="$LIBS -lnss3 -lnspr4"
|
||||
dnl SSLLIB=""
|
||||
dnl ]
|
||||
dnl )
|
||||
|
||||
# libnettle
|
||||
USE_NETTLE="no"
|
||||
dnl AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path],
|
||||
dnl [use libnettle as crypto library, installed at path.]),
|
||||
dnl [
|
||||
dnl USE_NETTLE="yes"
|
||||
dnl AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
|
||||
dnl AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT])
|
||||
dnl if test "$withval" != "" -a "$withval" != "yes"; then
|
||||
dnl CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
|
||||
dnl LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
dnl ACX_RUNTIME_PATH_ADD([$withval/lib])
|
||||
dnl else
|
||||
dnl CPPFLAGS="$CPPFLAGS -I/usr/include/nettle"
|
||||
dnl fi
|
||||
dnl LIBS="$LIBS -lhogweed -lnettle -lgmp"
|
||||
dnl SSLLIB=""
|
||||
dnl ]
|
||||
dnl )
|
||||
|
||||
# Which TLS and crypto libs to use.
|
||||
AC_ARG_WITH([gnutls],
|
||||
[AS_HELP_STRING([--with-gnutls],
|
||||
[use GnuTLS instead of OpenSSL])],
|
||||
[
|
||||
PKG_CHECK_MODULES([libgnutls], [gnutls >= 3.5.0])
|
||||
PKG_CHECK_MODULES([libgnutlsdane], [gnutls-dane >= 3.5.0])
|
||||
LIBS="$libgnutls_LIBS $libgnutlsdane_LIBS $LIBS"
|
||||
CFLAGS="$libgnutls_CFLAGS $libgnutlsdane_CFLAGS $CFLAGS"
|
||||
AC_SUBST([TLSDIR], 'gnutls')
|
||||
AC_DEFINE([USE_GNUTLS], [1], [Use the GnuTLS library])
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
|
||||
AX_LIB_NETTLE(yes)
|
||||
USE_NETTLE="yes"
|
||||
AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
|
||||
AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT])
|
||||
fi
|
||||
# Zero configuration DNSSEC we still need libcrypto
|
||||
AC_CHECK_HEADERS([openssl/x509.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_LIB([crypto], [X509_STORE_new], [
|
||||
AC_DEFINE_UNQUOTED([HAVE_LIBCRYPTO], [2], [Define to 1 if you have the `crypto' library (-lcrypto).]) dnl
|
||||
LIBS="-lcrypto $LIBS"
|
||||
], [
|
||||
AC_MSG_ERROR([libcrypto still needed for Zero configuration DNSSEC])
|
||||
])
|
||||
],
|
||||
[
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
ACX_WITH_SSL
|
||||
fi
|
||||
ACX_LIB_SSL
|
||||
AC_SUBST([TLSDIR], 'openssl')
|
||||
|
||||
# Verify OpenSSL is at least version 1.0.2.
|
||||
# We also check it's not LibreSSL, but that's a little later, not here.
|
||||
AC_CHECK_FUNCS([X509_check_host SSL_dane_enable])
|
||||
if test "x$ac_cv_func_X509_check_host" != xyes; then
|
||||
AC_MSG_ERROR([getdns requires OpenSSL version 1.0.2 or later])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether we need to compile/link DANE support])
|
||||
DANESSL_XTRA_OBJS=""
|
||||
if test "x$ac_cv_func_SSL_dane_enable" = xyes; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([USE_DANESSL], [1], [Define this to use DANE functions from the ssl_dane/danessl library.])
|
||||
DANESSL_XTRA_OBJS="danessl.lo"
|
||||
fi
|
||||
AC_SUBST(DANESSL_XTRA_OBJS)
|
||||
])
|
||||
|
||||
|
||||
# openssl
|
||||
if test $USE_NSS = "no"; then
|
||||
ACX_WITH_SSL_OPTIONAL
|
||||
ACX_LIB_SSL
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no" ; then
|
||||
AC_MSG_CHECKING([for LibreSSL])
|
||||
if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_LIBRESSL], [1], [Define if we have LibreSSL])
|
||||
# libressl provides these compat functions, but they may also be
|
||||
# declared by the OS in libc. See if they have been declared.
|
||||
AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform])
|
||||
AC_MSG_ERROR([getdns does not support LibreSSL])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/conf.h openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version])
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify OpenSSL_version_num OpenSSL_version SSL_CTX_dane_enable SSL_dane_enable SSL_dane_tlsa_add X509_check_host X509_get_notAfter X509_get0_notAfter SSL_CTX_set_ciphersuites SSL_set_ciphersuites OPENSSL_init_crypto DSA_set0_pqg DSA_set0_key RSA_set0_key])
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set1_curves_list,SSL_set1_curves_list,SSL_set_min_proto_version,SSL_get_min_proto_version], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
|
@ -431,7 +550,6 @@ AC_INCLUDES_DEFAULT
|
|||
])
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
|
||||
case "$enable_sha1" in
|
||||
no)
|
||||
|
@ -550,7 +668,7 @@ AC_MSG_RESULT($ac_cv_c_gost_works)
|
|||
|
||||
AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support]))
|
||||
use_gost="no"
|
||||
if test $USE_NSS = "no"; then
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
case "$enable_gost" in
|
||||
no)
|
||||
;;
|
||||
|
@ -564,7 +682,7 @@ case "$enable_gost" in
|
|||
fi
|
||||
;;
|
||||
esac
|
||||
fi dnl !USE_NSS
|
||||
fi dnl !USE_NSS && !USE_NETTLE
|
||||
|
||||
AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support]))
|
||||
use_ecdsa="no"
|
||||
|
@ -572,7 +690,7 @@ case "$enable_ecdsa" in
|
|||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no"; then
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
|
||||
|
@ -604,10 +722,34 @@ case "$enable_dsa" in
|
|||
;;
|
||||
*) dnl default
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_FUNC(DSA_SIG_new, [
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
AC_CHECK_TYPE(DSA_SIG*, [
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
|
||||
fi ], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
# include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_RAND_H
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_CONF_H
|
||||
#include <openssl/conf.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
])
|
||||
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
|
||||
fi ])
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -617,15 +759,40 @@ case "$enable_ed25519" in
|
|||
no)
|
||||
;;
|
||||
*)
|
||||
if test "$USE_NSS" = "no" -a "$USE_NETTLE" = "no"; then
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_DECLS([NID_ED25519], [
|
||||
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
|
||||
use_ed25519="yes"
|
||||
], [ if test "x$enable_ed25519" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED25519 and you used --enable-ed25519.])
|
||||
fi ], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
if test $USE_NETTLE = "yes"; then
|
||||
AC_CHECK_HEADERS([nettle/eddsa.h], use_ed25519="yes",, [AC_INCLUDES_DEFAULT])
|
||||
fi
|
||||
if test $use_ed25519 = "yes"; then
|
||||
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(ed448, AC_HELP_STRING([--disable-ed448], [Disable ED448 support]))
|
||||
use_ed448="no"
|
||||
case "$enable_ed448" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_DECLS([NID_ED448], [
|
||||
use_ed448="yes"
|
||||
], [ if test "x$enable_ed448" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED448 and you used --enable-ed448.])
|
||||
fi ], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
if test $use_ed448 = "yes"; then
|
||||
AC_DEFINE_UNQUOTED([USE_ED448], [1], [Define this to enable ED448 support.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -651,8 +818,8 @@ case "$enable_edns_cookies" in
|
|||
no)
|
||||
;;
|
||||
yes|*)
|
||||
if test "x_$HAVE_SSL" != "x_yes"; then
|
||||
AC_MSG_ERROR([edns cookies need openssl libcrypto which is not available, please rerun with --disable-edns-cookies])
|
||||
if test "x_$HAVE_SSL" != "x_yes" -a $USE_NETTLE = "no"; then
|
||||
AC_MSG_ERROR([edns cookies needs crypto library which is not available, please rerun with --disable-edns-cookies])
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([EDNS_COOKIES], [1], [Define this to enable the experimental edns cookies.])
|
||||
;;
|
||||
|
@ -763,6 +930,39 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
my_with_libidn2=1
|
||||
AC_ARG_WITH(libidn2, AS_HELP_STRING([--with-libidn2=pathname],
|
||||
[path to libidn2 (default: search /usr/local ..)]),
|
||||
[], [withval="yes"])
|
||||
if test x_$withval = x_yes; then
|
||||
for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
|
||||
if test -f "$dir/include/idn2.h"; then
|
||||
CFLAGS="$CFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
AC_MSG_NOTICE([Found libidn2 in $dir])
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/include/idn2/idn2.h"; then
|
||||
CFLAGS="$CFLAGS -I$dir/include/idn2"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
AC_MSG_NOTICE([Found libidn2 in $dir])
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -f "/usr/include/idn2/idn2.h"; then
|
||||
CFLAGS="$CFLAGS -I/usr/include/idn2"
|
||||
#LDFLAGS="$LDFLAGS -L/usr/lib"
|
||||
AC_MSG_NOTICE([Found libidn2 in /usr])
|
||||
fi
|
||||
else
|
||||
if test x_$withval != x_no; then
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
else
|
||||
my_with_libidn2=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $my_with_libunbound = 1
|
||||
then
|
||||
# find libunbound
|
||||
|
@ -793,15 +993,37 @@ fi
|
|||
found_all_libs=1
|
||||
MISSING_DEPS=""
|
||||
MISSING_SEP=""
|
||||
if test $my_with_libidn = 1
|
||||
|
||||
working_libidn2=0
|
||||
if test $my_with_libidn2 = 1
|
||||
then
|
||||
AC_MSG_NOTICE([Checking for dependency libidn])
|
||||
AC_CHECK_LIB([idn], [idna_to_ascii_8z], [], [
|
||||
MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libidn"
|
||||
AC_MSG_NOTICE([Checking for dependency libidn2])
|
||||
AC_CHECK_LIB([idn2], [idn2_to_unicode_8z8z], [
|
||||
working_libidn2=1
|
||||
LIBS="-lidn2 $LIBS"
|
||||
AC_DEFINE_UNQUOTED([HAVE_LIBIDN2], [1], [Define to 1 if you have the `idn2' library (-lidn).]) dnl `
|
||||
], [
|
||||
MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libidn2 (version 2.0.0 or higher)"
|
||||
MISSING_SEP=", "
|
||||
found_all_libs=0
|
||||
])
|
||||
fi
|
||||
if test $working_libidn2 = 0
|
||||
then
|
||||
if test $my_with_libidn = 1
|
||||
then
|
||||
AC_MSG_NOTICE([Checking for dependency libidn])
|
||||
AC_CHECK_LIB([idn], [idna_to_ascii_8z], [], [
|
||||
MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libidn"
|
||||
MISSING_SEP=", "
|
||||
found_all_libs=0
|
||||
])
|
||||
else
|
||||
if test $my_with_libidn2 = 1
|
||||
then
|
||||
found_all_libs=0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(unbound-event-api, AC_HELP_STRING([--disable-unbound-event-api], [Disable usage of libunbounds event API]))
|
||||
case "$enable_unbound_event_api" in
|
||||
|
@ -1150,6 +1372,22 @@ AC_SUBST(GETDNS_QUERY)
|
|||
AC_SUBST(INSTALL_GETDNS_QUERY)
|
||||
AC_SUBST(UNINSTALL_GETDNS_QUERY)
|
||||
|
||||
AC_ARG_WITH(getdns_server_mon, AS_HELP_STRING([--without-getdns_server_mon],
|
||||
[Do not compile and install the getdns_server_mon tool]),
|
||||
[], [withval="yes"])
|
||||
if test x_$withval = x_no; then
|
||||
GETDNS_SERVER_MON=""
|
||||
INSTALL_GETDNS_SERVER_MON=""
|
||||
UNINSTALL_GETDNS_SERVER_MON=""
|
||||
else
|
||||
GETDNS_SERVER_MON="getdns_server_mon"
|
||||
INSTALL_GETDNS_SERVER_MON="install-getdns_server_mon"
|
||||
UNINSTALL_GETDNS_SERVER_MON="uninstall-getdns_server_mon"
|
||||
fi
|
||||
AC_SUBST(GETDNS_SERVER_MON)
|
||||
AC_SUBST(INSTALL_GETDNS_SERVER_MON)
|
||||
AC_SUBST(UNINSTALL_GETDNS_SERVER_MON)
|
||||
|
||||
stubby_with_yaml=0
|
||||
AC_ARG_WITH(stubby, AS_HELP_STRING([--with-stubby],
|
||||
[Compile and install stubby, the (stub) resolver daemon]),
|
||||
|
@ -1303,9 +1541,20 @@ CFLAGS="$CFLAGS $LIBBSD_CFLAGS"
|
|||
],[
|
||||
AC_MSG_WARN([libbsd not found or usable; using embedded code instead])
|
||||
])
|
||||
AC_CHECK_DECLS([inet_pton,inet_ntop,strlcpy,arc4random,arc4random_uniform])
|
||||
AC_REPLACE_FUNCS(inet_pton)
|
||||
AC_REPLACE_FUNCS(inet_ntop)
|
||||
AC_CHECK_DECLS([inet_pton,inet_ntop,strlcpy,arc4random,arc4random_uniform], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
AS_IF([test "x$ac_cv_have_decl_inet_pton" = xyes],
|
||||
[],
|
||||
[AC_REPLACE_FUNCS(inet_pton)]
|
||||
)
|
||||
AS_IF([test "x$ac_cv_have_decl_inet_ntop" = xyes],
|
||||
[],
|
||||
[AC_REPLACE_FUNCS(inet_ntop)]
|
||||
)
|
||||
AC_REPLACE_FUNCS(strlcpy)
|
||||
AC_REPLACE_FUNCS(arc4random)
|
||||
AC_REPLACE_FUNCS(arc4random_uniform)
|
||||
|
@ -1373,7 +1622,7 @@ AH_BOTTOM([
|
|||
|
||||
#ifdef GETDNS_ON_WINDOWS
|
||||
/* On windows it is allowed to increase the FD_SETSIZE
|
||||
* (and nescessary to make our custom eventloop work)
|
||||
* (and necessary to make our custom eventloop work)
|
||||
* See: https://support.microsoft.com/en-us/kb/111855
|
||||
*/
|
||||
# ifndef FD_SETSIZE
|
||||
|
@ -1509,6 +1758,10 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
|
|||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
@ -1529,10 +1782,6 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
|
|||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_lib_nettle.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_LIB_NETTLE([yes|no|auto])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Searches for the 'nettle' library with the --with... option.
|
||||
#
|
||||
# If found, define HAVE_NETTLE and macro NETTLE_LIBS. Also defines
|
||||
# NETTLE_WITH_<algo> for the algorithms found available. Possible
|
||||
# algorithms: AES ARCTWO BLOWFISH CAST128 DES DES3 SERPENT TWOFISH MD2 MD4
|
||||
# MD5 SHA1 SHA256.
|
||||
#
|
||||
# The argument is used if no --with...-nettle option is set. Value "yes"
|
||||
# requires the configuration by default. Value "no" does not require it by
|
||||
# default. Value "auto" configures the library only if available.
|
||||
#
|
||||
# See also AX_LIB_BEECRYPT, AX_LIB_CRYPTO, and AX_LIB_GCRYPT.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2009 Fabien Coelho <autoconf.archive@coelho.net>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 10
|
||||
|
||||
# AX_CHECK_NETTLE_ALGO([name],[function])
|
||||
AC_DEFUN([AX_CHECK_NETTLE_ALGO],[
|
||||
AC_CHECK_LIB([nettle], [nettle_$2],
|
||||
AC_DEFINE([NETTLE_WITH_$1],[1],[Algorithm $1 in nettle library]))
|
||||
])
|
||||
|
||||
# AX_LIB_NETTLE([yes|no|auto])
|
||||
AC_DEFUN([AX_LIB_NETTLE],[
|
||||
AC_MSG_CHECKING([whether nettle is enabled])
|
||||
AC_ARG_WITH([nettle],
|
||||
AC_HELP_STRING([--with-nettle], [Require nettle library (required with GnuTLS)]),[
|
||||
AC_MSG_RESULT([$withval])
|
||||
ax_with_nettle=$withval
|
||||
],[
|
||||
AC_MSG_RESULT([$1])
|
||||
ax_with_nettle=$1
|
||||
])
|
||||
if test "$ax_with_nettle" = "yes" -o "$ax_with_nettle" = "auto" ; then
|
||||
AC_CHECK_HEADERS([nettle/nettle-meta.h],[
|
||||
AC_CHECK_LIB([nettle],[nettle_base64_encode_final],[
|
||||
AC_DEFINE([HAVE_NETTLE],[1],[Nettle library is available])
|
||||
HAVE_NETTLE=1
|
||||
AC_SUBST([NETTLE_LIBS],[-lnettle])
|
||||
# ciphers
|
||||
AX_CHECK_NETTLE_ALGO([AES],[aes_encrypt])
|
||||
AX_CHECK_NETTLE_ALGO([ARCTWO],[arctwo_encrypt])
|
||||
AX_CHECK_NETTLE_ALGO([BLOWFISH],[blowfish_encrypt])
|
||||
AX_CHECK_NETTLE_ALGO([CAST128],[cast128_encrypt])
|
||||
AX_CHECK_NETTLE_ALGO([DES],[des_encrypt])
|
||||
AX_CHECK_NETTLE_ALGO([DES3],[des3_encrypt])
|
||||
AX_CHECK_NETTLE_ALGO([SERPENT],[serpent_encrypt])
|
||||
AX_CHECK_NETTLE_ALGO([TWOFISH],[twofish_encrypt])
|
||||
# digests
|
||||
AX_CHECK_NETTLE_ALGO([MD2],[md2_digest])
|
||||
AX_CHECK_NETTLE_ALGO([MD4],[md4_digest])
|
||||
AX_CHECK_NETTLE_ALGO([MD5],[md5_digest])
|
||||
AX_CHECK_NETTLE_ALGO([SHA1],[sha1_digest])
|
||||
AX_CHECK_NETTLE_ALGO([SHA256],[sha256_digest])
|
||||
])
|
||||
])
|
||||
# complain only if explicitly required
|
||||
if test "$ax_with_nettle" = "yes" -a "x$HAVE_NETTLE" = "x" ; then
|
||||
AC_MSG_ERROR([cannot configure required nettle library])
|
||||
fi
|
||||
fi
|
||||
])
|
|
@ -53,9 +53,9 @@ Local configuration via API or local file (e.g. /etc/getdns.conf, ~/.getdnsrc)
|
|||
- max TTL/TTL override (separate for pos/neg cache entries)
|
||||
- inclusions (use cache for specified domains) (maybe over-eng)
|
||||
- exceptions (avoid ache for specified domains) (maybe over-eng)
|
||||
- persistant vs. transitory cache
|
||||
- persistent vs. transitory cache
|
||||
|
||||
- cache data store via Berkely db to allow for persistance
|
||||
- cache data store via Berkely db to allow for persistence
|
||||
|
||||
- negative cache TTL derived from SOA
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
Some notes about packages and maintainers.
|
||||
|
||||
For Homebrew, created and maintained by ilovezfs
|
||||
https://github.com/Homebrew/homebrew-core/Formula/getdns.rb
|
||||
https://github.com/Homebrew/homebrew-core/Formula/stubby.rb
|
||||
|
||||
For Arch, created and maintained by Bruno Pagani (ArchangeGabriel)
|
||||
|
||||
For OpenWRT, created and maintained by David Mora (iamperson347)
|
||||
https://github.com/openwrt/packages/tree/master/libs/getdns
|
||||
https://github.com/openwrt/packages/tree/master/net/stubby
|
||||
|
||||
For AstLinux Project, created and maintained by Lonnie Abelbeck (abelbeck)
|
||||
https://github.com/astlinux-project/astlinux/tree/master/package/getdns
|
||||
|
||||
For Genode, created and maintained by Emery Hemingway (ehmry)
|
||||
https://github.com/genodelabs/genode/blob/master/repos/ports/ports/getdns.port
|
|
@ -31,7 +31,7 @@ void callback(getdns_context *context,
|
|||
assert( callback_type == GETDNS_CALLBACK_COMPLETE );
|
||||
|
||||
if ((r = getdns_dict_get_list(response, "/replies_tree/0/answer", &answer)))
|
||||
fprintf(stderr, "Could not get \"answer\" section from first reply in the reponse");
|
||||
fprintf(stderr, "Could not get \"answer\" section from first reply in the response");
|
||||
|
||||
else if ((r = getdns_list_get_length(answer, &n_answers)))
|
||||
fprintf(stderr, "Could not get replies_tree\'s length");
|
||||
|
|
|
@ -35,7 +35,7 @@ void callback(getdns_context *context,
|
|||
assert( callback_type == GETDNS_CALLBACK_COMPLETE );
|
||||
|
||||
if ((r = getdns_dict_get_int(response, "status", &status)))
|
||||
fprintf(stderr, "Could not get \"status\" from reponse");
|
||||
fprintf(stderr, "Could not get \"status\" from response");
|
||||
|
||||
else if (status != GETDNS_RESPSTATUS_GOOD)
|
||||
fprintf(stderr, "The search had no results, and a return value of %"PRIu32".\n", status);
|
||||
|
|
|
@ -31,7 +31,7 @@ void callback(getdns_context *context,
|
|||
assert( callback_type == GETDNS_CALLBACK_COMPLETE );
|
||||
|
||||
if ((r = getdns_dict_get_list(response, "replies_tree", &replies_tree)))
|
||||
fprintf(stderr, "Could not get \"replies_tree\" from reponse");
|
||||
fprintf(stderr, "Could not get \"replies_tree\" from response");
|
||||
|
||||
else if ((r = getdns_list_get_length(replies_tree, &n_replies)))
|
||||
fprintf(stderr, "Could not get replies_tree\'s length");
|
||||
|
|
|
@ -173,7 +173,7 @@ extensions. See <a href="#Extensions">the section below</a> for information on h
|
|||
the extensions used for a request.</p>
|
||||
|
||||
<p class=define><code><b>*userarg</b></code></p>
|
||||
<p class=descrip>A void* that is passed to the function, which the funciton
|
||||
<p class=descrip>A void* that is passed to the function, which the function
|
||||
returns to the callback function untouched. <code>userarg</code> can be used by the callback
|
||||
function for any user-specific data needed. This can be NULL.</p>
|
||||
|
||||
|
@ -1507,7 +1507,7 @@ function.</p>
|
|||
<span class="n">assert</span><span class="p">(</span> <span class="n">callback_type</span> <span class="o">==</span> <span class="n">GETDNS_CALLBACK_COMPLETE</span> <span class="p">);</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">((</span><span class="n">r</span> <span class="o">=</span> <span class="n">getdns_dict_get_int</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="s">"status"</span><span class="p">,</span> <span class="o">&</span><span class="n">status</span><span class="p">)))</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Could not get </span><span class="se">\"</span><span class="s">status</span><span class="se">\"</span><span class="s"> from reponse"</span><span class="p">);</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Could not get </span><span class="se">\"</span><span class="s">status</span><span class="se">\"</span><span class="s"> from response"</span><span class="p">);</span>
|
||||
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="n">GETDNS_RESPSTATUS_GOOD</span><span class="p">)</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"The search had no results, and a return value of %"</span><span class="n">PRIu32</span><span class="s">".</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">status</span><span class="p">);</span>
|
||||
|
@ -1622,7 +1622,7 @@ their TTLs.</p>
|
|||
<span class="n">assert</span><span class="p">(</span> <span class="n">callback_type</span> <span class="o">==</span> <span class="n">GETDNS_CALLBACK_COMPLETE</span> <span class="p">);</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">((</span><span class="n">r</span> <span class="o">=</span> <span class="n">getdns_dict_get_list</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="s">"replies_tree"</span><span class="p">,</span> <span class="o">&</span><span class="n">replies_tree</span><span class="p">)))</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Could not get </span><span class="se">\"</span><span class="s">replies_tree</span><span class="se">\"</span><span class="s"> from reponse"</span><span class="p">);</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Could not get </span><span class="se">\"</span><span class="s">replies_tree</span><span class="se">\"</span><span class="s"> from response"</span><span class="p">);</span>
|
||||
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="p">((</span><span class="n">r</span> <span class="o">=</span> <span class="n">getdns_list_get_length</span><span class="p">(</span><span class="n">replies_tree</span><span class="p">,</span> <span class="o">&</span><span class="n">n_replies</span><span class="p">)))</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Could not get replies_tree</span><span class="se">\'</span><span class="s">s length"</span><span class="p">);</span>
|
||||
|
@ -1854,7 +1854,7 @@ as it is for the synchronous example, it is just done in <code>main()</code>.</p
|
|||
<span class="n">assert</span><span class="p">(</span> <span class="n">callback_type</span> <span class="o">==</span> <span class="n">GETDNS_CALLBACK_COMPLETE</span> <span class="p">);</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">((</span><span class="n">r</span> <span class="o">=</span> <span class="n">getdns_dict_get_list</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="s">"/replies_tree/0/answer"</span><span class="p">,</span> <span class="o">&</span><span class="n">answer</span><span class="p">)))</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Could not get </span><span class="se">\"</span><span class="s">answer</span><span class="se">\"</span><span class="s"> section from first reply in the reponse"</span><span class="p">);</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Could not get </span><span class="se">\"</span><span class="s">answer</span><span class="se">\"</span><span class="s"> section from first reply in the response"</span><span class="p">);</span>
|
||||
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="p">((</span><span class="n">r</span> <span class="o">=</span> <span class="n">getdns_list_get_length</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span> <span class="o">&</span><span class="n">n_answers</span><span class="p">)))</span>
|
||||
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Could not get replies_tree</span><span class="se">\'</span><span class="s">s length"</span><span class="p">);</span>
|
||||
|
|
258
src/Makefile.in
258
src/Makefile.in
|
@ -47,15 +47,17 @@ have_libuv = @have_libuv@
|
|||
have_libev = @have_libev@
|
||||
# datarootdir is here to please some checkers
|
||||
datarootdir=@datarootdir@
|
||||
mandir=@mandir@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
srcdir = @srcdir@
|
||||
tlsdir = @TLSDIR@
|
||||
stubbysrcdir = $(srcdir)/../stubby
|
||||
LIBTOOL = ../libtool
|
||||
|
||||
CC=@CC@
|
||||
CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary -I$(stubbysrcdir)/src @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS)
|
||||
CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary -I$(srcdir)/tls -I$(srcdir)/$(tlsdir) -I$(stubbysrcdir)/src @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS)
|
||||
WPEDANTICFLAG=@WPEDANTICFLAG@
|
||||
WNOERRORFLAG=@WNOERRORFLAG@
|
||||
LDFLAGS=@LDFLAGS@ @LIBS@
|
||||
|
@ -77,9 +79,9 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
|
|||
DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo
|
||||
|
||||
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
|
||||
list.lo request-internal.lo platform.lo pubkey-pinning.lo rr-dict.lo \
|
||||
list.lo request-internal.lo platform.lo rr-dict.lo \
|
||||
rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \
|
||||
mdns.lo
|
||||
mdns.lo pubkey-pinning.lo
|
||||
|
||||
GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
|
||||
str2wire.lo
|
||||
|
@ -90,13 +92,17 @@ LIBOBJDIR=
|
|||
LIBOBJS=@LIBOBJS@
|
||||
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
|
||||
|
||||
UTIL_OBJ=rbtree.lo val_secalgo.lo lruhash.lo lookup3.lo locks.lo
|
||||
UTIL_OBJ=rbtree.lo lruhash.lo lookup3.lo locks.lo
|
||||
|
||||
JSMN_OBJ=jsmn.lo
|
||||
TLS_OBJ=tls.lo pubkey-pinning-internal.lo keyraw-internal.lo
|
||||
TLS_COMMON_OBJ=val_secalgo.lo anchor-internal.lo
|
||||
YXML_OBJ=yxml.lo
|
||||
|
||||
YAML_OBJ=convert_yaml_to_json.lo
|
||||
GETDNS_XTRA_OBJS=@GETDNS_XTRA_OBJS@
|
||||
DANESSL_OBJ=danessl.lo
|
||||
|
||||
GETDNS_XTRA_OBJS=@GETDNS_XTRA_OBJS@ @DANESSL_XTRA_OBJS@
|
||||
STUBBY_XTRA_OBJS=@STUBBY_XTRA_OBJS@
|
||||
|
||||
EXTENSION_OBJ=$(DEFAULT_EVENTLOOP_OBJ) libevent.lo libev.lo
|
||||
|
@ -130,9 +136,18 @@ $(UTIL_OBJ):
|
|||
$(JSMN_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@
|
||||
|
||||
$(TLS_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$(tlsdir)/$(@:.lo=.c) -o $@
|
||||
|
||||
$(TLS_COMMON_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/tls/$(@:.lo=.c) -o $@
|
||||
|
||||
$(YAML_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(stubbysrcdir)/src/yaml/$(@:.lo=.c) -o $@
|
||||
|
||||
$(DANESSL_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WNOERRORFLAG) -c $(srcdir)/ssl_dane/$(@:.lo=.c) -o $@
|
||||
|
||||
$(YXML_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -I$(srcdir)/yxml -DYXML_GETDNS -Wno-unused-parameter -c $(srcdir)/yxml/$(@:.lo=.c) -o $@
|
||||
|
||||
|
@ -188,8 +203,8 @@ libgetdns_ext_uv.la: libgetdns.la libuv.lo
|
|||
libgetdns_ext_ev.la: libgetdns.la libev.lo
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols
|
||||
|
||||
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS)
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
|
||||
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(TLS_OBJ) $(TLS_COMMON_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS)
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(TLS_OBJ) $(TLS_COMMON_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
|
||||
|
||||
test: default
|
||||
cd test && $(MAKE) $@
|
||||
|
@ -197,8 +212,14 @@ test: default
|
|||
getdns_query: default
|
||||
cd tools && $(MAKE) $@
|
||||
|
||||
getdns_server_mon: default
|
||||
cd tools && $(MAKE) $@
|
||||
|
||||
stubby.1: $(stubbysrcdir)/doc/stubby.1.in
|
||||
sed -e "s|@ETCDIR@|$(stubbyconfdir)|g" $(stubbysrcdir)/doc/stubby.1.in > $@
|
||||
|
||||
stubby.lo: $(stubbysrcdir)/src/stubby.c
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -DSTUBBYCONFDIR=\"$(sysconfdir)/stubby\" -DRUNSTATEDIR=\"$(runstatedir)\" -c $< -o $@
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -DSTUBBYCONFDIR='"$(sysconfdir)/stubby"' -DRUNSTATEDIR='"$(runstatedir)"' -c $(stubbysrcdir)/src/stubby.c -o $@
|
||||
|
||||
stubby: stubby.lo libgetdns.la $(STUBBY_XTRA_OBJS)
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ stubby.lo $(STUBBY_XTRA_OBJS) $(STUBBY_LDFLAGS) libgetdns.la
|
||||
|
@ -220,14 +241,18 @@ install-stubby-files-windows: stubby.yml.windows
|
|||
test -f $(DESTDIR)$(stubbyconfdir)/stubby.yml || \
|
||||
$(INSTALL_DATA) stubby.yml.windows $(DESTDIR)$(stubbyconfdir)/stubby.yml
|
||||
|
||||
install-stubby: stubby install-stubby-files-@HOSTOS@
|
||||
install-stubby: stubby stubby.1 install-stubby-files-@HOSTOS@
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
|
||||
$(LIBTOOL) --mode=install cp stubby $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(runstatedir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1
|
||||
$(INSTALL) -m 644 stubby\.1 $(DESTDIR)$(mandir)/man1
|
||||
|
||||
uninstall-stubby:
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/stubby
|
||||
rm -f $(DESTDIR)$(sbindir)/stubby-setdns-macos.sh
|
||||
rm -f $(DESTDIR)$(mandir)/man1/stubby.1
|
||||
|
||||
scratchpad: default
|
||||
cd test && $(MAKE) $@
|
||||
|
@ -255,13 +280,15 @@ Makefile: $(srcdir)/Makefile.in ../config.status
|
|||
depend:
|
||||
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
|
||||
|
||||
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -Iyxml -Iutil/auxiliary -I../stubby/src *.c gldns/*.c compat/*.c util/*.c jsmn/*.c yxml/*.c extension/*.c ../stubby/src/*.c | \
|
||||
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -Itls -I$(tlsdir) -Iyxml -Iutil/auxiliary -I../stubby/src *.c gldns/*.c compat/*.c util/*.c jsmn/*.c $(tlsdir)/*.c yxml/*.c extension/*.c ../stubby/src/*.c | \
|
||||
sed -e "s? $$blddir/? ?g" \
|
||||
-e 's? gldns/? $$(srcdir)/gldns/?g' \
|
||||
-e 's? compat/? $$(srcdir)/compat/?g' \
|
||||
-e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?g' \
|
||||
-e 's? util/? $$(srcdir)/util/?g' \
|
||||
-e 's? jsmn/? $$(srcdir)/jsmn/?g' \
|
||||
-e 's? tls/? $$(srcdir)/tls/?g' \
|
||||
-e 's? $(tlsdir)/? $$(srcdir)/$$(tlsdir)/?g' \
|
||||
-e 's? yxml/? $$(srcdir)/yxml/?g' \
|
||||
-e 's? extension/? $$(srcdir)/extension/?g' \
|
||||
-e 's? \.\./stubby/? $$(stubbysrcdir)/?g' \
|
||||
|
@ -283,35 +310,31 @@ FORCE:
|
|||
|
||||
# Dependencies for gldns, utils, the extensions and compat functions
|
||||
anchor.lo anchor.o: $(srcdir)/anchor.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/anchor.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/anchor.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/yxml/yxml.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/yxml/yxml.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/str2wire.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h \
|
||||
$(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
const-info.lo const-info.o: $(srcdir)/const-info.c \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/const-info.h
|
||||
context.lo context.o: $(srcdir)/context.c \
|
||||
config.h \
|
||||
$(srcdir)/anchor.h \
|
||||
config.h $(srcdir)/anchor.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/debug.h \
|
||||
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/dnssec.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
|
||||
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/tls.h \
|
||||
$(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h $(srcdir)/const-info.h
|
||||
convert.lo convert.o: $(srcdir)/convert.c \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
@ -319,11 +342,9 @@ convert.lo convert.o: $(srcdir)/convert.c \
|
|||
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
|
||||
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
|
||||
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \
|
||||
$(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(stubbysrcdir)/src/yaml/convert_yaml_to_json.h $(srcdir)/convert.h
|
||||
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h \
|
||||
$(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h
|
||||
dict.lo dict.o: $(srcdir)/dict.c \
|
||||
config.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
|
@ -331,76 +352,62 @@ dict.lo dict.o: $(srcdir)/dict.c \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/parseutil.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/parseutil.h
|
||||
dnssec.lo dnssec.o: $(srcdir)/dnssec.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/context.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h \
|
||||
$(srcdir)/util/orig-headers/val_secalgo.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h \
|
||||
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h \
|
||||
$(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h $(srcdir)/gldns/gbuffer.h
|
||||
general.lo general.o: $(srcdir)/general.c \
|
||||
config.h \
|
||||
$(srcdir)/general.h \
|
||||
config.h $(srcdir)/general.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
|
||||
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
|
||||
$(srcdir)/dict.h $(srcdir)/mdns.h $(srcdir)/platform.h
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h $(srcdir)/mdns.h
|
||||
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h \
|
||||
config.h \
|
||||
$(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/list.h $(srcdir)/dict.h
|
||||
config.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/list.h $(srcdir)/dict.h
|
||||
mdns.lo mdns.o: $(srcdir)/mdns.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/context.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/context.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h \
|
||||
$(srcdir)/platform.h $(srcdir)/mdns.h $(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.h \
|
||||
$(srcdir)/util/orig-headers/lookup3.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/general.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/mdns.h
|
||||
platform.lo platform.o: $(srcdir)/platform.c $(srcdir)/platform.h \
|
||||
config.h
|
||||
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/context.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/pubkey-pinning.h $(srcdir)/tls/pubkey-pinning-internal.h
|
||||
request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
|
||||
config.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
|
@ -408,11 +415,9 @@ request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/dict.h $(srcdir)/convert.h $(srcdir)/general.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h $(srcdir)/general.h
|
||||
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
@ -420,10 +425,8 @@ rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h \
|
||||
$(srcdir)/dict.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h \
|
||||
$(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/dict.h
|
||||
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
@ -434,35 +437,30 @@ server.lo server.o: $(srcdir)/server.c \
|
|||
getdns/getdns.h \
|
||||
$(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
stub.lo stub.o: $(srcdir)/stub.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/stub.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/stub.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h \
|
||||
$(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
|
||||
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/anchor.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/anchor.h \
|
||||
$(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h \
|
||||
$(srcdir)/pubkey-pinning.h
|
||||
sync.lo sync.o: $(srcdir)/sync.c \
|
||||
getdns/getdns.h \
|
||||
config.h \
|
||||
$(srcdir)/context.h \
|
||||
config.h $(srcdir)/context.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
|
||||
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
@ -475,16 +473,15 @@ util-internal.lo util-internal.o: $(srcdir)/util-internal.c \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
|
||||
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
|
||||
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/str2wire.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h
|
||||
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h \
|
||||
$(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \
|
||||
$(srcdir)/gldns/rrdef.h
|
||||
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/gbuffer.h
|
||||
keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/rrdef.h
|
||||
parse.lo parse.o: $(srcdir)/gldns/parse.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h
|
||||
|
@ -501,7 +498,8 @@ str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \
|
|||
wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h \
|
||||
$(srcdir)/$(tlsdir)/keyraw-internal.h
|
||||
arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \
|
||||
config.h
|
||||
arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \
|
||||
|
@ -531,8 +529,8 @@ strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \
|
|||
strptime.lo strptime.o: $(srcdir)/compat/strptime.c \
|
||||
config.h
|
||||
locks.lo locks.o: $(srcdir)/util/locks.c \
|
||||
config.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h
|
||||
config.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h
|
||||
lookup3.lo lookup3.o: $(srcdir)/util/lookup3.c \
|
||||
config.h \
|
||||
$(srcdir)/util/auxiliary/util/storage/lookup3.h $(srcdir)/util/lookup3.h \
|
||||
|
@ -547,15 +545,30 @@ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \
|
|||
$(srcdir)/util/auxiliary/log.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h \
|
||||
$(srcdir)/util/auxiliary/fptr_wlist.h $(srcdir)/util/auxiliary/util/fptr_wlist.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h
|
||||
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \
|
||||
config.h \
|
||||
$(srcdir)/util/auxiliary/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/auxiliary/validator/val_secalgo.h $(srcdir)/util/val_secalgo.h \
|
||||
$(srcdir)/util/orig-headers/val_secalgo.h $(srcdir)/util/auxiliary/validator/val_nsec3.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/auxiliary/sldns/rrdef.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \
|
||||
$(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h
|
||||
jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
|
||||
keyraw-internal.lo keyraw-internal.o: $(srcdir)/$(tlsdir)/keyraw-internal.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/rrdef.h
|
||||
pubkey-pinning-internal.lo pubkey-pinning-internal.o: $(srcdir)/$(tlsdir)/pubkey-pinning-internal.c \
|
||||
config.h $(srcdir)/debug.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/context.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/tls/pubkey-pinning-internal.h
|
||||
tls.lo tls.o: $(srcdir)/$(tlsdir)/tls.c \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/context.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/const-info.h $(srcdir)/tls.h
|
||||
yxml.lo yxml.o: $(srcdir)/yxml/yxml.c $(srcdir)/yxml/yxml.h
|
||||
libev.lo libev.o: $(srcdir)/extension/libev.c \
|
||||
config.h \
|
||||
|
@ -570,8 +583,8 @@ libevent.lo libevent.o: $(srcdir)/extension/libevent.c \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h
|
||||
libuv.lo libuv.o: $(srcdir)/extension/libuv.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/types-internal.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h
|
||||
|
@ -582,13 +595,12 @@ poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/platform.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h \
|
||||
$(srcdir)/platform.h $(srcdir)/debug.h
|
||||
select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/types-internal.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/platform.h \
|
||||
|
|
615
src/anchor.c
615
src/anchor.c
|
@ -33,9 +33,6 @@
|
|||
#include "debug.h"
|
||||
#include "anchor.h"
|
||||
#include <fcntl.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include <strings.h>
|
||||
#include <time.h>
|
||||
#include "types-internal.h"
|
||||
|
@ -52,141 +49,6 @@
|
|||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
|
||||
/* get key usage out of its extension, returns 0 if no key_usage extension */
|
||||
static unsigned long
|
||||
_getdns_get_usage_of_ex(X509* cert)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
ASN1_BIT_STRING* s;
|
||||
|
||||
if((s=X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL))) {
|
||||
if(s->length > 0) {
|
||||
val = s->data[0];
|
||||
if(s->length > 1)
|
||||
val |= s->data[1] << 8;
|
||||
}
|
||||
ASN1_BIT_STRING_free(s);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/** get valid signers from the list of signers in the signature */
|
||||
static STACK_OF(X509)*
|
||||
_getdns_get_valid_signers(PKCS7* p7, const char* p7signer)
|
||||
{
|
||||
int i;
|
||||
STACK_OF(X509)* validsigners = sk_X509_new_null();
|
||||
STACK_OF(X509)* signers = PKCS7_get0_signers(p7, NULL, 0);
|
||||
unsigned long usage = 0;
|
||||
if(!validsigners) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed to allocated validsigners\n"
|
||||
, __FUNC__);
|
||||
sk_X509_free(signers);
|
||||
return NULL;
|
||||
}
|
||||
if(!signers) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed to allocated signers\n"
|
||||
, __FUNC__);
|
||||
sk_X509_free(validsigners);
|
||||
return NULL;
|
||||
}
|
||||
for(i=0; i<sk_X509_num(signers); i++) {
|
||||
char buf[1024];
|
||||
X509_NAME* nm = X509_get_subject_name(
|
||||
sk_X509_value(signers, i));
|
||||
if(!nm) {
|
||||
DEBUG_ANCHOR("%s(): cert %d has no subject name\n"
|
||||
, __FUNC__, i);
|
||||
continue;
|
||||
}
|
||||
if(!p7signer || strcmp(p7signer, "")==0) {
|
||||
/* there is no name to check, return all records */
|
||||
DEBUG_ANCHOR("%s(): did not check commonName of signer\n"
|
||||
, __FUNC__);
|
||||
} else {
|
||||
if(!X509_NAME_get_text_by_NID(nm,
|
||||
NID_pkcs9_emailAddress,
|
||||
buf, (int)sizeof(buf))) {
|
||||
DEBUG_ANCHOR("%s(): removed cert with no name\n"
|
||||
, __FUNC__);
|
||||
continue; /* no name, no use */
|
||||
}
|
||||
if(strcmp(buf, p7signer) != 0) {
|
||||
DEBUG_ANCHOR("%s(): removed cert with wrong name\n"
|
||||
, __FUNC__);
|
||||
continue; /* wrong name, skip it */
|
||||
}
|
||||
}
|
||||
|
||||
/* check that the key usage allows digital signatures
|
||||
* (the p7s) */
|
||||
usage = _getdns_get_usage_of_ex(sk_X509_value(signers, i));
|
||||
if(!(usage & KU_DIGITAL_SIGNATURE)) {
|
||||
DEBUG_ANCHOR("%s(): removed cert with no key usage "
|
||||
"Digital Signature allowed\n"
|
||||
, __FUNC__);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we like this cert, add it to our list of valid
|
||||
* signers certificates */
|
||||
sk_X509_push(validsigners, sk_X509_value(signers, i));
|
||||
}
|
||||
sk_X509_free(signers);
|
||||
return validsigners;
|
||||
}
|
||||
|
||||
static int
|
||||
_getdns_verify_p7sig(BIO* data, BIO* p7s, X509_STORE *store, const char* p7signer)
|
||||
{
|
||||
PKCS7* p7;
|
||||
STACK_OF(X509)* validsigners;
|
||||
int secure = 0;
|
||||
#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
|
||||
X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new();
|
||||
if(!param) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed to allocated param\n"
|
||||
, __FUNC__);
|
||||
return 0;
|
||||
}
|
||||
/* do the selfcheck on the root certificate; it checks that the
|
||||
* input is valid */
|
||||
X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CHECK_SS_SIGNATURE);
|
||||
X509_STORE_set1_param(store, param);
|
||||
X509_VERIFY_PARAM_free(param);
|
||||
#endif
|
||||
(void)BIO_reset(p7s);
|
||||
(void)BIO_reset(data);
|
||||
|
||||
/* convert p7s to p7 (the signature) */
|
||||
p7 = d2i_PKCS7_bio(p7s, NULL);
|
||||
if(!p7) {
|
||||
DEBUG_ANCHOR("ERROR %s(): could not parse p7s signature file\n"
|
||||
, __FUNC__);
|
||||
return 0;
|
||||
}
|
||||
/* check what is in the Subject name of the certificates,
|
||||
* and build a stack that contains only the right certificates */
|
||||
validsigners = _getdns_get_valid_signers(p7, p7signer);
|
||||
if(!validsigners) {
|
||||
PKCS7_free(p7);
|
||||
return 0;
|
||||
}
|
||||
if(PKCS7_verify(p7, validsigners, store, data, NULL, PKCS7_NOINTERN) == 1) {
|
||||
secure = 1;
|
||||
}
|
||||
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
|
||||
else {
|
||||
DEBUG_ANCHOR("ERROR %s(): the PKCS7 signature did not verify\n"
|
||||
, __FUNC__);
|
||||
ERR_print_errors_cb(_getdns_ERR_print_errors_cb_f, NULL);
|
||||
}
|
||||
#endif
|
||||
sk_X509_free(validsigners);
|
||||
PKCS7_free(p7);
|
||||
return secure;
|
||||
}
|
||||
|
||||
typedef struct ta_iter {
|
||||
uint8_t yxml_buf[4096];
|
||||
yxml_t x;
|
||||
|
@ -206,6 +68,15 @@ typedef struct ta_iter {
|
|||
char digest[2048];
|
||||
} ta_iter;
|
||||
|
||||
static void strcpytrunc(char* dst, const char* src, size_t dstsize)
|
||||
{
|
||||
size_t to_copy = strlen(src);
|
||||
if (to_copy >= dstsize)
|
||||
to_copy = dstsize -1;
|
||||
memcpy(dst, src, to_copy);
|
||||
dst[to_copy] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* XML convert DateTime element to time_t.
|
||||
* [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
|
||||
|
@ -213,7 +84,7 @@ typedef struct ta_iter {
|
|||
* @param str: the string
|
||||
* @return a time_t representation or 0 on failure.
|
||||
*/
|
||||
static time_t
|
||||
time_t
|
||||
_getdns_xml_convertdate(const char* str)
|
||||
{
|
||||
time_t t = 0;
|
||||
|
@ -328,8 +199,8 @@ static ta_iter *ta_iter_next(ta_iter *ta)
|
|||
|
||||
else if (level == 0 && cur) {
|
||||
/* <Zone> content ready */
|
||||
(void) strncpy( ta->zone, value
|
||||
, sizeof(ta->zone));
|
||||
strcpytrunc( ta->zone, value
|
||||
, sizeof(ta->zone));
|
||||
|
||||
/* Reset to start of <TrustAnchor> */
|
||||
cur = NULL;
|
||||
|
@ -504,20 +375,20 @@ static ta_iter *ta_iter_next(ta_iter *ta)
|
|||
DEBUG_ANCHOR("elem end: %s\n", value);
|
||||
switch (elem_type) {
|
||||
case KEYTAG:
|
||||
(void) strncpy( ta->keytag, value
|
||||
, sizeof(ta->keytag));
|
||||
strcpytrunc( ta->keytag, value
|
||||
, sizeof(ta->keytag));
|
||||
break;
|
||||
case ALGORITHM:
|
||||
(void) strncpy( ta->algorithm, value
|
||||
, sizeof(ta->algorithm));
|
||||
strcpytrunc( ta->algorithm, value
|
||||
, sizeof(ta->algorithm));
|
||||
break;
|
||||
case DIGESTTYPE:
|
||||
(void) strncpy( ta->digesttype, value
|
||||
, sizeof(ta->digesttype));
|
||||
strcpytrunc( ta->digesttype, value
|
||||
, sizeof(ta->digesttype));
|
||||
break;
|
||||
case DIGEST:
|
||||
(void) strncpy( ta->digest, value
|
||||
, sizeof(ta->digest));
|
||||
strcpytrunc( ta->digest, value
|
||||
, sizeof(ta->digest));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -558,7 +429,7 @@ static ta_iter *ta_iter_init(ta_iter *ta, const char *doc, size_t doc_len)
|
|||
return ta_iter_next(ta);
|
||||
}
|
||||
|
||||
static uint16_t _getdns_parse_xml_trust_anchors_buf(
|
||||
uint16_t _getdns_parse_xml_trust_anchors_buf(
|
||||
gldns_buffer *gbuf, uint64_t *now_ms, char *xml_data, size_t xml_len)
|
||||
{
|
||||
ta_iter ta_spc, *ta;
|
||||
|
@ -647,200 +518,6 @@ static uint16_t _getdns_parse_xml_trust_anchors_buf(
|
|||
return ta_count;
|
||||
}
|
||||
|
||||
static uint8_t *tas_validate(struct mem_funcs *mf,
|
||||
const getdns_bindata *xml_bd, const getdns_bindata *p7s_bd,
|
||||
const getdns_bindata *crt_bd, const char *p7signer,
|
||||
uint64_t *now_ms, uint8_t *tas, size_t *tas_len)
|
||||
{
|
||||
BIO *xml = NULL, *p7s = NULL, *crt = NULL;
|
||||
X509 *x = NULL;
|
||||
X509_STORE *store = NULL;
|
||||
uint8_t *success = NULL;
|
||||
|
||||
if (!(xml = BIO_new_mem_buf(xml_bd->data, xml_bd->size)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating xml BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(p7s = BIO_new_mem_buf(p7s_bd->data, p7s_bd->size)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating p7s BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(crt = BIO_new_mem_buf(crt_bd->data, crt_bd->size)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating crt BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Parsing builtin certificate\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(store = X509_STORE_new()))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating store\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!X509_STORE_add_cert(store, x))
|
||||
DEBUG_ANCHOR("ERROR %s(): Adding certificate to store\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (_getdns_verify_p7sig(xml, p7s, store, p7signer)) {
|
||||
gldns_buffer gbuf;
|
||||
|
||||
gldns_buffer_init_vfixed_frm_data(&gbuf, tas, *tas_len);
|
||||
|
||||
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms,
|
||||
(char *)xml_bd->data, xml_bd->size))
|
||||
DEBUG_ANCHOR("Failed to parse trust anchor XML data");
|
||||
|
||||
else if (gldns_buffer_position(&gbuf) > *tas_len) {
|
||||
*tas_len = gldns_buffer_position(&gbuf);
|
||||
if ((success = GETDNS_XMALLOC(*mf, uint8_t, *tas_len))) {
|
||||
gldns_buffer_init_frm_data(&gbuf, success, *tas_len);
|
||||
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf,
|
||||
now_ms, (char *)xml_bd->data, xml_bd->size)) {
|
||||
|
||||
DEBUG_ANCHOR("Failed to re-parse trust"
|
||||
" anchor XML data\n");
|
||||
GETDNS_FREE(*mf, success);
|
||||
success = NULL;
|
||||
}
|
||||
} else
|
||||
DEBUG_ANCHOR("Could not allocate space for "
|
||||
"trust anchors\n");
|
||||
} else {
|
||||
success = tas;
|
||||
*tas_len = gldns_buffer_position(&gbuf);
|
||||
}
|
||||
} else {
|
||||
DEBUG_ANCHOR("Verifying trust-anchors failed!\n");
|
||||
}
|
||||
if (store) X509_STORE_free(store);
|
||||
if (x) X509_free(x);
|
||||
if (crt) BIO_free(crt);
|
||||
if (xml) BIO_free(xml);
|
||||
if (p7s) BIO_free(p7s);
|
||||
return success;
|
||||
}
|
||||
|
||||
void _getdns_context_equip_with_anchor(
|
||||
getdns_context *context, uint64_t *now_ms)
|
||||
{
|
||||
uint8_t xml_spc[4096], *xml_data = NULL;
|
||||
uint8_t p7s_spc[4096], *p7s_data = NULL;
|
||||
size_t xml_len, p7s_len;
|
||||
const char *verify_email = NULL;
|
||||
const char *verify_CA = NULL;
|
||||
getdns_return_t r;
|
||||
|
||||
BIO *xml = NULL, *p7s = NULL, *crt = NULL;
|
||||
X509 *x = NULL;
|
||||
X509_STORE *store = NULL;
|
||||
|
||||
if ((r = getdns_context_get_trust_anchors_verify_CA(
|
||||
context, &verify_CA)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify"
|
||||
" CA: \"%s\"\n", __FUNC__
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
|
||||
else if (!verify_CA || !*verify_CA)
|
||||
DEBUG_ANCHOR("NOTICE: Trust anchor verification explicitely "
|
||||
"disabled by empty verify CA\n");
|
||||
|
||||
else if ((r = getdns_context_get_trust_anchors_verify_email(
|
||||
context, &verify_email)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify email "
|
||||
"address: \"%s\"\n", __FUNC__
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
|
||||
else if (!verify_email || !*verify_email)
|
||||
DEBUG_ANCHOR("NOTICE: Trust anchor verification explicitely "
|
||||
"disabled by empty verify email\n");
|
||||
|
||||
else if (!(xml_data = _getdns_context_get_priv_file(context,
|
||||
"root-anchors.xml", xml_spc, sizeof(xml_spc), &xml_len)))
|
||||
DEBUG_ANCHOR("DEBUG %s(): root-anchors.xml not present\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(p7s_data = _getdns_context_get_priv_file(context,
|
||||
"root-anchors.p7s", p7s_spc, sizeof(p7s_spc), &p7s_len)))
|
||||
DEBUG_ANCHOR("DEBUG %s(): root-anchors.p7s not present\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(xml = BIO_new_mem_buf(xml_data, xml_len)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating xml BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(p7s = BIO_new_mem_buf(p7s_data, p7s_len)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating p7s BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(crt = BIO_new_mem_buf((void *)verify_CA, -1)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating crt BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Parsing builtin certificate\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(store = X509_STORE_new()))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating store\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!X509_STORE_add_cert(store, x))
|
||||
DEBUG_ANCHOR("ERROR %s(): Adding certificate to store\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (_getdns_verify_p7sig(xml, p7s, store, verify_email)) {
|
||||
uint8_t ta_spc[sizeof(context->trust_anchors_spc)];
|
||||
size_t ta_len;
|
||||
uint8_t *ta = NULL;
|
||||
gldns_buffer gbuf;
|
||||
|
||||
gldns_buffer_init_vfixed_frm_data(
|
||||
&gbuf, ta_spc, sizeof(ta_spc));
|
||||
|
||||
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms,
|
||||
(char *)xml_data, xml_len))
|
||||
DEBUG_ANCHOR("Failed to parse trust anchor XML data");
|
||||
else if ((ta_len = gldns_buffer_position(&gbuf)) > sizeof(ta_spc)) {
|
||||
if ((ta = GETDNS_XMALLOC(context->mf, uint8_t, ta_len))) {
|
||||
gldns_buffer_init_frm_data(&gbuf, ta,
|
||||
gldns_buffer_position(&gbuf));
|
||||
if (!_getdns_parse_xml_trust_anchors_buf(
|
||||
&gbuf, now_ms, (char *)xml_data, xml_len)) {
|
||||
DEBUG_ANCHOR("Failed to re-parse trust"
|
||||
" anchor XML data");
|
||||
GETDNS_FREE(context->mf, ta);
|
||||
} else {
|
||||
context->trust_anchors = ta;
|
||||
context->trust_anchors_len = ta_len;
|
||||
context->trust_anchors_source = GETDNS_TASRC_XML;
|
||||
_getdns_ta_notify_dnsreqs(context);
|
||||
}
|
||||
} else
|
||||
DEBUG_ANCHOR("Could not allocate space for XML file");
|
||||
} else {
|
||||
(void)memcpy(context->trust_anchors_spc, ta_spc, ta_len);
|
||||
context->trust_anchors = context->trust_anchors_spc;
|
||||
context->trust_anchors_len = ta_len;
|
||||
context->trust_anchors_source = GETDNS_TASRC_XML;
|
||||
_getdns_ta_notify_dnsreqs(context);
|
||||
}
|
||||
DEBUG_ANCHOR("ta: %p, ta_len: %d\n",
|
||||
(void *)context->trust_anchors, (int)context->trust_anchors_len);
|
||||
|
||||
} else {
|
||||
DEBUG_ANCHOR("Verifying trust-anchors failed!\n");
|
||||
}
|
||||
if (store) X509_STORE_free(store);
|
||||
if (x) X509_free(x);
|
||||
if (crt) BIO_free(crt);
|
||||
if (xml) BIO_free(xml);
|
||||
if (p7s) BIO_free(p7s);
|
||||
if (xml_data && xml_data != xml_spc)
|
||||
GETDNS_FREE(context->mf, xml_data);
|
||||
if (p7s_data && p7s_data != p7s_spc)
|
||||
GETDNS_FREE(context->mf, p7s_data);
|
||||
}
|
||||
|
||||
static const char tas_write_p7s_buf[] =
|
||||
"GET %s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
|
@ -855,10 +532,8 @@ static const char tas_write_xml_p7s_buf[] =
|
|||
"\r\n";
|
||||
|
||||
|
||||
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
|
||||
static inline const char * rt_str(uint16_t rt)
|
||||
{ return rt == GETDNS_RRTYPE_A ? "A" : rt == GETDNS_RRTYPE_AAAA ? "AAAA" : "?"; }
|
||||
#endif
|
||||
|
||||
static int tas_busy(tas_connection *a)
|
||||
{
|
||||
|
@ -905,7 +580,8 @@ static void tas_success(getdns_context *context, tas_connection *a)
|
|||
tas_cleanup(context, a);
|
||||
tas_cleanup(context, other);
|
||||
|
||||
DEBUG_ANCHOR("Successfully fetched new trust anchors\n");
|
||||
_getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
|
||||
, "Successfully fetched new trust anchors\n");
|
||||
context->trust_anchors_source = GETDNS_TASRC_XML;
|
||||
_getdns_ta_notify_dnsreqs(context);
|
||||
}
|
||||
|
@ -913,20 +589,26 @@ static void tas_success(getdns_context *context, tas_connection *a)
|
|||
static void tas_fail(getdns_context *context, tas_connection *a)
|
||||
{
|
||||
tas_connection *other = &context->a == a ? &context->aaaa : &context->a;
|
||||
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
|
||||
uint16_t rt = &context->a == a ? GETDNS_RRTYPE_A : GETDNS_RRTYPE_AAAA;
|
||||
uint16_t ort = rt == GETDNS_RRTYPE_A ? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A;
|
||||
#endif
|
||||
|
||||
tas_cleanup(context, a);
|
||||
|
||||
if (!tas_busy(other)) {
|
||||
DEBUG_ANCHOR("Fatal error fetching trust anchor: "
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Fatal error fetching trust anchor: "
|
||||
"%s connection failed too\n", rt_str(rt));
|
||||
context->trust_anchors_source = GETDNS_TASRC_FAILED;
|
||||
context->trust_anchors_backoff_expiry =
|
||||
_getdns_get_now_ms() + context->trust_anchors_backoff_time;
|
||||
_getdns_ta_notify_dnsreqs(context);
|
||||
} else
|
||||
DEBUG_ANCHOR("%s connection failed, waiting for %s\n"
|
||||
, rt_str(rt), rt_str(ort));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
|
||||
, "%s connection failed, waiting for %s\n"
|
||||
, rt_str(rt)
|
||||
, rt_str( rt == GETDNS_RRTYPE_A
|
||||
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A));
|
||||
}
|
||||
|
||||
static void tas_connect(getdns_context *context, tas_connection *a);
|
||||
|
@ -958,7 +640,9 @@ static void tas_timeout_cb(void *userarg)
|
|||
a = &context->a;
|
||||
else a = &context->aaaa;
|
||||
|
||||
DEBUG_ANCHOR("Trust anchor fetch timeout\n");
|
||||
_getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
|
||||
, "Trust anchor fetch timeout\n");
|
||||
|
||||
GETDNS_CLEAR_EVENT(a->loop, &a->event);
|
||||
tas_next(context, a);
|
||||
}
|
||||
|
@ -974,7 +658,9 @@ static void tas_reconnect_cb(void *userarg)
|
|||
a = &context->a;
|
||||
else a = &context->aaaa;
|
||||
|
||||
DEBUG_ANCHOR("Waiting for second document timeout. Reconnecting...\n");
|
||||
_getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
|
||||
, "Waiting for second document timeout. Reconnecting...\n");
|
||||
|
||||
GETDNS_CLEAR_EVENT(a->loop, &a->event);
|
||||
close(a->fd);
|
||||
a->fd = -1;
|
||||
|
@ -989,8 +675,6 @@ static void tas_read_cb(void *userarg);
|
|||
static void tas_write_cb(void *userarg);
|
||||
static void tas_doc_read(getdns_context *context, tas_connection *a)
|
||||
{
|
||||
DEBUG_ANCHOR("doc (size: %d)\n", (int)a->tcp.read_buf_len);
|
||||
|
||||
assert(a->tcp.read_pos == a->tcp.read_buf + a->tcp.read_buf_len);
|
||||
assert(context);
|
||||
|
||||
|
@ -1019,20 +703,22 @@ static void tas_doc_read(getdns_context *context, tas_connection *a)
|
|||
|
||||
if ((r = getdns_context_get_trust_anchors_verify_CA(
|
||||
context, (const char **)&verify_CA.data)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify"
|
||||
" CA: \"%s\"\n", __FUNC__
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Cannot get trust anchor verify CA: "
|
||||
"\"%s\"\n", getdns_get_errorstr_by_id(r));
|
||||
|
||||
else if (!(verify_CA.size = strlen((const char *)verify_CA.data)))
|
||||
; /* pass */
|
||||
|
||||
else if ((r = getdns_context_get_trust_anchors_verify_email(
|
||||
context, &verify_email)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify"
|
||||
" email address: \"%s\"\n", __FUNC__
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Cannot get trust anchor verify email: "
|
||||
"\"%s\"\n", getdns_get_errorstr_by_id(r));
|
||||
|
||||
else if (!(tas = tas_validate(&context->mf, &a->xml, &p7s_bd,
|
||||
else if (!(tas = _getdns_tas_validate(&context->mf, &a->xml, &p7s_bd,
|
||||
&verify_CA, verify_email, &now_ms, tas, &tas_len)))
|
||||
; /* pass */
|
||||
|
||||
|
@ -1064,7 +750,7 @@ static void tas_doc_read(getdns_context *context, tas_connection *a)
|
|||
a->tcp.read_pos = a->tcp.read_buf;
|
||||
a->tcp.to_read = sizeof(context->tas_hdr_spc);
|
||||
}
|
||||
GETDNS_SCHEDULE_EVENT(a->loop, a->fd, 50,
|
||||
GETDNS_SCHEDULE_EVENT(a->loop, a->fd, 2000,
|
||||
getdns_eventloop_event_init(&a->event, a->req->owner,
|
||||
tas_read_cb, NULL, tas_reconnect_cb));
|
||||
return;
|
||||
|
@ -1155,7 +841,11 @@ static void tas_read_cb(void *userarg)
|
|||
DEBUG_ANCHOR("i: %d, n: %d, doc_len: %d\n"
|
||||
, (int)i, (int)n, doc_len);
|
||||
if (!doc)
|
||||
DEBUG_ANCHOR("Memory error");
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR
|
||||
, GETDNS_LOG_ERR
|
||||
, "Memory error while reading "
|
||||
"trust anchor\n");
|
||||
else {
|
||||
ssize_t surplus = n - i;
|
||||
|
||||
|
@ -1202,7 +892,11 @@ static void tas_read_cb(void *userarg)
|
|||
} else if (_getdns_socketerror_wants_retry())
|
||||
return;
|
||||
|
||||
DEBUG_ANCHOR("Read error: %d %s\n", (int)n, _getdns_errnostr());
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Error while receiving trust anchor: %s\n"
|
||||
, _getdns_errnostr());
|
||||
|
||||
GETDNS_CLEAR_EVENT(a->loop, &a->event);
|
||||
tas_next(context, a);
|
||||
}
|
||||
|
@ -1252,7 +946,9 @@ static void tas_write_cb(void *userarg)
|
|||
} else if (_getdns_socketerror_wants_retry())
|
||||
return;
|
||||
|
||||
DEBUG_ANCHOR("Write error: %s\n", _getdns_errnostr());
|
||||
_getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Error while sending to trust anchor site: %s\n"
|
||||
, _getdns_errnostr());
|
||||
GETDNS_CLEAR_EVENT(a->loop, &a->event);
|
||||
tas_next(context, a);
|
||||
}
|
||||
|
@ -1291,9 +987,7 @@ static getdns_return_t _getdns_get_tas_url_hostname(
|
|||
|
||||
static void tas_connect(getdns_context *context, tas_connection *a)
|
||||
{
|
||||
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
|
||||
char a_buf[40];
|
||||
#endif
|
||||
int r;
|
||||
|
||||
#ifdef HAVE_FCNTL
|
||||
|
@ -1309,15 +1003,19 @@ static void tas_connect(getdns_context *context, tas_connection *a)
|
|||
tas_next(context, a);
|
||||
return;
|
||||
}
|
||||
DEBUG_ANCHOR("Initiating connection to %s\n"
|
||||
, inet_ntop(( a->req->request_type == GETDNS_RRTYPE_A
|
||||
? AF_INET : AF_INET6)
|
||||
, a->rr->rr_i.rr_type + 10, a_buf, sizeof(a_buf)));
|
||||
|
||||
_getdns_log( &context->log, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
|
||||
, "Setting op connection to: %s\n"
|
||||
, inet_ntop( ( a->req->request_type == GETDNS_RRTYPE_A
|
||||
? AF_INET : AF_INET6)
|
||||
, a->rr->rr_i.rr_type + 10
|
||||
, a_buf, sizeof(a_buf)));
|
||||
|
||||
if ((a->fd = socket(( a->req->request_type == GETDNS_RRTYPE_A
|
||||
? AF_INET : AF_INET6), SOCK_STREAM, IPPROTO_TCP)) == -1) {
|
||||
DEBUG_ANCHOR("Error creating socket: %s\n",
|
||||
_getdns_errnostr());
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Error creating socket: %s\n", _getdns_errnostr());
|
||||
tas_next(context, a);
|
||||
return;
|
||||
}
|
||||
|
@ -1368,9 +1066,11 @@ static void tas_connect(getdns_context *context, tas_connection *a)
|
|||
}
|
||||
if ((R = _getdns_get_tas_url_hostname(
|
||||
context, tas_hostname, &path))) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Could not get_tas_url_hostname"
|
||||
": \"%s\"", __FUNC__
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Cannot get hostname from trust anchor "
|
||||
"url: \"%s\"\n"
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
goto error;
|
||||
}
|
||||
hostname_len = strlen(tas_hostname);
|
||||
|
@ -1378,22 +1078,26 @@ static void tas_connect(getdns_context *context, tas_connection *a)
|
|||
tas_hostname[--hostname_len] = '\0';
|
||||
path_len = strlen(path);
|
||||
if (path_len < 4) {
|
||||
DEBUG_ANCHOR("ERROR %s(): path of tas_url \"%s\" too "
|
||||
"small\n", __FUNC__, path);
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Trust anchor path \"%s\" too small\n"
|
||||
, path);
|
||||
goto error;
|
||||
}
|
||||
if (a->state == TAS_RETRY_GET_PS7) {
|
||||
buf_sz = sizeof(tas_write_p7s_buf)
|
||||
+ 1 * (hostname_len - 2) + 1 * (path_len - 2) + 1;
|
||||
+ 1 * (hostname_len - 2) + 1 * (path_len - 2);
|
||||
fmt = tas_write_p7s_buf;
|
||||
} else {
|
||||
buf_sz = sizeof(tas_write_xml_p7s_buf)
|
||||
+ 2 * (hostname_len - 2) + 2 * (path_len - 2) + 1;
|
||||
+ 2 * (hostname_len - 2) + 2 * (path_len - 2);
|
||||
fmt = tas_write_xml_p7s_buf;
|
||||
}
|
||||
if (!(write_buf = GETDNS_XMALLOC(context->mf, char, buf_sz))) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Could not allocate write "
|
||||
"buffer\n", __FUNC__);
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Cannot allocate write buffer for "
|
||||
"sending to trust anchor host\n");
|
||||
goto error;
|
||||
}
|
||||
if (a->state == TAS_RETRY_GET_PS7) {
|
||||
|
@ -1427,8 +1131,10 @@ static void tas_connect(getdns_context *context, tas_connection *a)
|
|||
DEBUG_ANCHOR("Scheduled write with event\n");
|
||||
return;
|
||||
} else
|
||||
DEBUG_ANCHOR("Connect error: %s\n", _getdns_errnostr());
|
||||
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Error connecting to trust anchor host: %s\n "
|
||||
, _getdns_errnostr());
|
||||
error:
|
||||
tas_next(context, a);
|
||||
}
|
||||
|
@ -1442,7 +1148,10 @@ static void tas_happy_eyeballs_cb(void *userarg)
|
|||
if (tas_fetching(&context->aaaa))
|
||||
return;
|
||||
else {
|
||||
DEBUG_ANCHOR("AAAA came too late, clearing Happy Eyeballs timer\n");
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
|
||||
, "Too late reception of AAAA for trust anchor "
|
||||
"host for Happy Eyeballs\n");
|
||||
GETDNS_CLEAR_EVENT(context->a.loop, &context->a.event);
|
||||
tas_connect(context, &context->a);
|
||||
}
|
||||
|
@ -1461,28 +1170,31 @@ static void _tas_hostname_lookup_cb(getdns_dns_req *dnsreq)
|
|||
&a->rrset_spc, a->req->response, a->req->response_len);
|
||||
|
||||
if (!a->rrset) {
|
||||
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
|
||||
char tas_hostname[256] = "<no hostname>";
|
||||
(void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL);
|
||||
DEBUG_ANCHOR("%s lookup for %s returned no response\n"
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
|
||||
, "%s lookup for %s returned no response\n"
|
||||
, rt_str(a->req->request_type), tas_hostname);
|
||||
#endif
|
||||
|
||||
} else if (a->req->response_len < dnsreq->name_len + 12 ||
|
||||
!_getdns_dname_equal(a->req->response + 12, dnsreq->name) ||
|
||||
a->rrset->rr_type != a->req->request_type) {
|
||||
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
|
||||
char tas_hostname[256] = "<no hostname>";
|
||||
(void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL);
|
||||
DEBUG_ANCHOR("%s lookup for %s returned wrong response\n"
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
|
||||
, "%s lookup for %s returned wrong response\n"
|
||||
, rt_str(a->req->request_type), tas_hostname);
|
||||
#endif
|
||||
|
||||
} else if (!(a->rr = _getdns_rrtype_iter_init(&a->rr_spc, a->rrset))) {
|
||||
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
|
||||
char tas_hostname[256] = "<no hostname>";
|
||||
(void) _getdns_get_tas_url_hostname(context, tas_hostname, NULL);
|
||||
DEBUG_ANCHOR("%s lookup for %s returned no addresses\n"
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
|
||||
, "%s lookup for %s returned no addresses\n"
|
||||
, rt_str(a->req->request_type), tas_hostname);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
tas_connection *other = a == &context->a ? &context->aaaa
|
||||
: &context->a;
|
||||
|
@ -1492,8 +1204,9 @@ static void _tas_hostname_lookup_cb(getdns_dns_req *dnsreq)
|
|||
; /* pass */
|
||||
|
||||
else if (a == &context->a && tas_busy(other)) {
|
||||
DEBUG_ANCHOR("Postponing connection initiation: "
|
||||
"Happy Eyeballs\n");
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
|
||||
, "Waiting 25ms for AAAA to arrive\n");
|
||||
GETDNS_SCHEDULE_EVENT(a->loop, a->fd, 25,
|
||||
getdns_eventloop_event_init(&a->event,
|
||||
a->req->owner, NULL, NULL, tas_happy_eyeballs_cb));
|
||||
|
@ -1510,7 +1223,8 @@ static void _tas_hostname_lookup_cb(getdns_dns_req *dnsreq)
|
|||
tas_fail(context, a);
|
||||
}
|
||||
|
||||
void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop)
|
||||
void _getdns_start_fetching_ta(
|
||||
getdns_context *context, getdns_eventloop *loop, uint64_t *now_ms)
|
||||
{
|
||||
getdns_return_t r;
|
||||
size_t scheduled;
|
||||
|
@ -1519,38 +1233,47 @@ void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop)
|
|||
const char *verify_email;
|
||||
|
||||
if ((r = _getdns_get_tas_url_hostname(context, tas_hostname, NULL))) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Could not get_tas_url_hostname"
|
||||
": \"%s\"", __FUNC__
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Cannot get hostname from trust anchor url: "
|
||||
"\"%s\"\n", getdns_get_errorstr_by_id(r));
|
||||
return;
|
||||
|
||||
} else if ((r = getdns_context_get_trust_anchors_verify_CA(
|
||||
context, &verify_CA))) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Could not get verify CA"
|
||||
": \"%s\"", __FUNC__
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Cannot get trust anchor verify CA: \"%s\"\n"
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
return;
|
||||
|
||||
} else if (!verify_CA || !*verify_CA) {
|
||||
DEBUG_ANCHOR("NOTICE: Trust anchor fetching explicitely "
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
|
||||
, "Trust anchor verification explicitly "
|
||||
"disabled by empty verify CA\n");
|
||||
return;
|
||||
|
||||
} else if ((r = getdns_context_get_trust_anchors_verify_email(
|
||||
context, &verify_email))) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Could not get verify email address"
|
||||
": \"%s\"", __FUNC__
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Cannot get trust anchor verify email: \"%s\"\n"
|
||||
, getdns_get_errorstr_by_id(r));
|
||||
return;
|
||||
|
||||
} else if (!verify_email || !*verify_email) {
|
||||
DEBUG_ANCHOR("NOTICE: Trust anchor fetching explicitely "
|
||||
"disabled by empty verify email address\n");
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
|
||||
, "Trust anchor verification explicitly "
|
||||
"disabled by empty verify email\n");
|
||||
return;
|
||||
|
||||
} else if (!_getdns_context_can_write_appdata(context)) {
|
||||
DEBUG_ANCHOR("NOTICE %s(): Not fetching TA, because "
|
||||
"non writeable appdata directory\n", __FUNC__);
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
|
||||
, "Not fetching TA, because "
|
||||
"non writeable appdata directory\n");
|
||||
return;
|
||||
}
|
||||
DEBUG_ANCHOR("Hostname: %s\n", tas_hostname);
|
||||
|
@ -1558,35 +1281,44 @@ void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop)
|
|||
loop == &context->sync_eventloop.loop ? "" : "a");
|
||||
|
||||
scheduled = 0;
|
||||
#if 1
|
||||
context->a.state = TAS_LOOKUP_ADDRESSES;
|
||||
if ((r = _getdns_general_loop(context, loop,
|
||||
tas_hostname, GETDNS_RRTYPE_A,
|
||||
no_dnssec_checking_disabled_opportunistic,
|
||||
context, &context->a.req, NULL, _tas_hostname_lookup_cb))) {
|
||||
DEBUG_ANCHOR("Error scheduling A lookup for %s: %s\n"
|
||||
, tas_hostname, getdns_get_errorstr_by_id(r));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
|
||||
, "Error scheduling A lookup for %s: %s\n"
|
||||
, tas_hostname, getdns_get_errorstr_by_id(r));
|
||||
} else
|
||||
scheduled += 1;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
context->aaaa.state = TAS_LOOKUP_ADDRESSES;
|
||||
if ((r = _getdns_general_loop(context, loop,
|
||||
tas_hostname, GETDNS_RRTYPE_AAAA,
|
||||
no_dnssec_checking_disabled_opportunistic,
|
||||
context, &context->aaaa.req, NULL, _tas_hostname_lookup_cb))) {
|
||||
DEBUG_ANCHOR("Error scheduling AAAA lookup for %s: %s\n"
|
||||
, tas_hostname, getdns_get_errorstr_by_id(r));
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
|
||||
, "Error scheduling AAAA lookup for %s: %s\n"
|
||||
, tas_hostname, getdns_get_errorstr_by_id(r));
|
||||
} else
|
||||
scheduled += 1;
|
||||
#endif
|
||||
|
||||
if (!scheduled) {
|
||||
DEBUG_ANCHOR("Fatal error fetching trust anchor: Unable to "
|
||||
"schedule address requests for %s\n"
|
||||
, tas_hostname);
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_WARNING
|
||||
, "Error scheduling address lookups for %s\n"
|
||||
, tas_hostname);
|
||||
|
||||
context->trust_anchors_source = GETDNS_TASRC_FAILED;
|
||||
if (now_ms) {
|
||||
if (*now_ms == 0) *now_ms = _getdns_get_now_ms();
|
||||
context->trust_anchors_backoff_expiry =
|
||||
*now_ms + context->trust_anchors_backoff_time;
|
||||
} else
|
||||
context->trust_anchors_backoff_expiry =
|
||||
_getdns_get_now_ms() + context->trust_anchors_backoff_time;
|
||||
_getdns_ta_notify_dnsreqs(context);
|
||||
} else
|
||||
context->trust_anchors_source = GETDNS_TASRC_FETCHING;
|
||||
|
@ -1703,7 +1435,10 @@ static void _getdns_context_read_root_ksk(getdns_context *context)
|
|||
buf_sz *= 2;
|
||||
}
|
||||
if (!(buf = GETDNS_XMALLOC(context->mf, uint8_t, buf_sz))) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Memory error\n", __FUNC__);
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Error allocating memory to read "
|
||||
"root.key\n");
|
||||
break;;
|
||||
}
|
||||
ptr = buf;
|
||||
|
@ -1788,8 +1523,10 @@ _getdns_context_update_root_ksk(
|
|||
break;
|
||||
}
|
||||
if (str_buf != str_spc) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Buffer size determination "
|
||||
"error\n", __FUNC__);
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Error determining buffer size for root "
|
||||
"KSK\n");
|
||||
if (str_buf)
|
||||
GETDNS_FREE(context->mf, str_buf);
|
||||
|
||||
|
@ -1797,11 +1534,13 @@ _getdns_context_update_root_ksk(
|
|||
}
|
||||
if (!(str_pos = str_buf = GETDNS_XMALLOC( context->mf, char,
|
||||
(str_sz = sizeof(str_spc) - remaining) + 1))) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Memory error\n", __FUNC__);
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
|
||||
, "Error allocating memory to read "
|
||||
"root KSK\n");
|
||||
return;
|
||||
}
|
||||
remaining = str_sz + 1;
|
||||
DEBUG_ANCHOR("Retrying with buf size: %d\n", remaining);
|
||||
};
|
||||
|
||||
/* Write presentation format DNSKEY rrset to "root.key" file */
|
||||
|
@ -1876,17 +1615,21 @@ _getdns_context_update_root_ksk(
|
|||
break;
|
||||
}
|
||||
if (!ta) {
|
||||
DEBUG_ANCHOR("NOTICE %s(): Key with id %d "
|
||||
"*not* found in TA.\n"
|
||||
"\"root-anchors.xml\" need "
|
||||
"updating.\n", __FUNC__
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR
|
||||
, GETDNS_LOG_NOTICE
|
||||
, "Key with id %d not found in TA; "
|
||||
"\"root-anchors.xml\" needs to be "
|
||||
"updated.\n"
|
||||
, context->root_ksk.ids[i]);
|
||||
context->trust_anchors_source =
|
||||
GETDNS_TASRC_XML_UPDATE;
|
||||
break;
|
||||
}
|
||||
DEBUG_ANCHOR("DEBUG %s(): Key with id %d found in TA\n"
|
||||
, __FUNC__, context->root_ksk.ids[i]);
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
|
||||
, "Key with id %d found in TA\n"
|
||||
, context->root_ksk.ids[i]);
|
||||
}
|
||||
}
|
||||
if (str_buf && str_buf != str_spc)
|
||||
|
|
26
src/anchor.h
26
src/anchor.h
|
@ -39,9 +39,33 @@
|
|||
#include <time.h>
|
||||
#include "rr-iter.h"
|
||||
|
||||
#include "types-internal.h"
|
||||
|
||||
/**
|
||||
** Internal functions, implemented in anchor-internal.c.
|
||||
**/
|
||||
void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms);
|
||||
|
||||
void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop);
|
||||
uint8_t *_getdns_tas_validate(struct mem_funcs *mf,
|
||||
const getdns_bindata *xml_bd, const getdns_bindata *p7s_bd,
|
||||
const getdns_bindata *crt_bd, const char *p7signer,
|
||||
uint64_t *now_ms, uint8_t *tas, size_t *tas_len);
|
||||
|
||||
|
||||
/**
|
||||
** anchor.c functions used by anchor-internal.c.
|
||||
**/
|
||||
time_t _getdns_xml_convertdate(const char* str);
|
||||
|
||||
uint16_t _getdns_parse_xml_trust_anchors_buf(gldns_buffer *gbuf, uint64_t *now_ms, char *xml_data, size_t xml_len);
|
||||
|
||||
/**
|
||||
** Public interface.
|
||||
**/
|
||||
void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms);
|
||||
|
||||
void _getdns_start_fetching_ta(
|
||||
getdns_context *context, getdns_eventloop *loop, uint64_t *now_ms);
|
||||
|
||||
#define MAX_KSKS 16
|
||||
#define RRSIG_RDATA_LEN 16
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
#else /* !__GNUC__ */
|
||||
#define inline
|
||||
#endif /* !__GNUC__ */
|
||||
#ifndef MAP_ANON
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
|
||||
#define KEYSZ 32
|
||||
#define IVSZ 8
|
||||
|
@ -71,6 +74,72 @@ static struct {
|
|||
|
||||
static inline void _rs_rekey(u_char *dat, size_t datlen);
|
||||
|
||||
/*
|
||||
* Basic sanity checking; wish we could do better.
|
||||
*/
|
||||
static int
|
||||
fallback_gotdata(char *buf, size_t len)
|
||||
{
|
||||
char any_set = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
any_set |= buf[i];
|
||||
if (any_set == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fallback for getentropy in case libc returns failure */
|
||||
static int
|
||||
fallback_getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
int fd, flags;
|
||||
int save_errno = errno;
|
||||
|
||||
start:
|
||||
|
||||
flags = O_RDONLY;
|
||||
#ifdef O_NOFOLLOW
|
||||
flags |= O_NOFOLLOW;
|
||||
#endif
|
||||
#ifdef O_CLOEXEC
|
||||
flags |= O_CLOEXEC;
|
||||
#endif
|
||||
fd = open("/dev/urandom", flags, 0);
|
||||
if (fd == -1) {
|
||||
if (errno == EINTR)
|
||||
goto start;
|
||||
goto nodevrandom;
|
||||
}
|
||||
#ifndef O_CLOEXEC
|
||||
# ifdef HAVE_FCNTL
|
||||
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
# endif
|
||||
#endif
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char*)buf + i, wanted);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
if (fallback_gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_rs_init(u_char *buf, size_t n)
|
||||
{
|
||||
|
@ -102,6 +171,9 @@ _rs_init(u_char *buf, size_t n)
|
|||
if(!rsx)
|
||||
abort();
|
||||
#endif
|
||||
/* Pleast older clang scan-build */
|
||||
if (!buf)
|
||||
buf = rsx->rs_buf;
|
||||
}
|
||||
|
||||
chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
|
||||
|
@ -114,14 +186,14 @@ _rs_stir(void)
|
|||
u_char rnd[KEYSZ + IVSZ];
|
||||
|
||||
if (getentropy(rnd, sizeof rnd) == -1) {
|
||||
if(errno != ENOSYS ||
|
||||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
|
||||
#ifdef SIGKILL
|
||||
raise(SIGKILL);
|
||||
raise(SIGKILL);
|
||||
#else
|
||||
#ifdef GETDNS_ON_WINDOWS
|
||||
DebugBreak();
|
||||
#endif
|
||||
exit(9); /* windows */
|
||||
exit(9); /* windows */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!rs)
|
||||
|
@ -131,9 +203,6 @@ _rs_stir(void)
|
|||
explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
|
||||
|
||||
/* invalidate rs_buf */
|
||||
#ifdef GETDNS_ON_WINDOWS
|
||||
_Analysis_assume_(rs != NULL);
|
||||
#endif
|
||||
rs->rs_have = 0;
|
||||
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
|
||||
|
||||
|
@ -145,15 +214,7 @@ _rs_stir_if_needed(size_t len)
|
|||
{
|
||||
#ifndef MAP_INHERIT_ZERO
|
||||
static pid_t _rs_pid = 0;
|
||||
#ifdef GETDNS_ON_WINDOWS
|
||||
/*
|
||||
* TODO: if compiling for the Windows Runtime, use GetCurrentProcessId(),
|
||||
* but this requires linking with kernel32.lib
|
||||
*/
|
||||
pid_t pid = _getpid();
|
||||
#else
|
||||
pid_t pid = getpid();
|
||||
#endif
|
||||
|
||||
/* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */
|
||||
if (_rs_pid == 0 || _rs_pid != pid) {
|
||||
|
@ -164,9 +225,6 @@ _rs_stir_if_needed(size_t len)
|
|||
#endif
|
||||
if (!rs || rs->rs_count <= len)
|
||||
_rs_stir();
|
||||
#ifdef GETDNS_ON_WINDOWS
|
||||
_Analysis_assume_(rs != NULL);
|
||||
#endif
|
||||
if (rs->rs_count <= len)
|
||||
rs->rs_count = 0;
|
||||
else
|
||||
|
|
|
@ -39,7 +39,7 @@ arc4random_uniform(uint32_t upper_bound)
|
|||
return 0;
|
||||
|
||||
/* 2**32 % x == (2**32 - x) % x */
|
||||
min = ((uint32_t)(-(int32_t)upper_bound)) % upper_bound;
|
||||
min = -upper_bound % upper_bound;
|
||||
|
||||
/*
|
||||
* This could theoretically loop forever but each retry has
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
#include <sys/auxv.h>
|
||||
#endif
|
||||
#include <sys/vfs.h>
|
||||
#ifndef MAP_ANON
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
|
||||
#define REPEAT 5
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
@ -94,7 +97,7 @@ int getentropy(void *buf, size_t len);
|
|||
extern int main(int, char *argv[]);
|
||||
#endif
|
||||
static int gotdata(char *buf, size_t len);
|
||||
#ifdef SYS_getrandom
|
||||
#if defined(SYS_getrandom) && defined(__NR_getrandom)
|
||||
static int getentropy_getrandom(void *buf, size_t len);
|
||||
#endif
|
||||
static int getentropy_urandom(void *buf, size_t len);
|
||||
|
@ -113,7 +116,7 @@ getentropy(void *buf, size_t len)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef SYS_getrandom
|
||||
#if defined(SYS_getrandom) && defined(__NR_getrandom)
|
||||
/*
|
||||
* Try descriptor-less getrandom()
|
||||
*/
|
||||
|
@ -209,7 +212,7 @@ gotdata(char *buf, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SYS_getrandom
|
||||
#if defined(SYS_getrandom) && defined(__NR_getrandom)
|
||||
static int
|
||||
getentropy_getrandom(void *buf, size_t len)
|
||||
{
|
||||
|
|
|
@ -92,6 +92,12 @@ static struct const_info consts_info[] = {
|
|||
{ 631, "GETDNS_CONTEXT_CODE_TLS_CA_PATH", GETDNS_CONTEXT_CODE_TLS_CA_PATH_TEXT },
|
||||
{ 632, "GETDNS_CONTEXT_CODE_TLS_CA_FILE", GETDNS_CONTEXT_CODE_TLS_CA_FILE_TEXT },
|
||||
{ 633, "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT },
|
||||
{ 634, "GETDNS_CONTEXT_CODE_TLS_CURVES_LIST", GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT },
|
||||
{ 635, "GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES", GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES_TEXT },
|
||||
{ 636, "GETDNS_CONTEXT_CODE_TLS_MIN_VERSION", GETDNS_CONTEXT_CODE_TLS_MIN_VERSION_TEXT },
|
||||
{ 637, "GETDNS_CONTEXT_CODE_TLS_MAX_VERSION", GETDNS_CONTEXT_CODE_TLS_MAX_VERSION_TEXT },
|
||||
{ 638, "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME", GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME_TEXT },
|
||||
{ 699, "GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE", GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE_TEXT },
|
||||
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
|
||||
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
|
||||
{ 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
|
||||
|
@ -113,7 +119,16 @@ static struct const_info consts_info[] = {
|
|||
{ 1202, "GETDNS_TRANSPORT_TLS", GETDNS_TRANSPORT_TLS_TEXT },
|
||||
{ 1300, "GETDNS_AUTHENTICATION_NONE", GETDNS_AUTHENTICATION_NONE_TEXT },
|
||||
{ 1301, "GETDNS_AUTHENTICATION_REQUIRED", GETDNS_AUTHENTICATION_REQUIRED_TEXT },
|
||||
{ 4096, "GETDNS_LOG_UPSTREAM_STATS", GETDNS_LOG_UPSTREAM_STATS_TEXT },
|
||||
{ 1400, "GETDNS_SSL3", GETDNS_SSL3_TEXT },
|
||||
{ 1401, "GETDNS_TLS1", GETDNS_TLS1_TEXT },
|
||||
{ 1402, "GETDNS_TLS1_1", GETDNS_TLS1_1_TEXT },
|
||||
{ 1403, "GETDNS_TLS1_2", GETDNS_TLS1_2_TEXT },
|
||||
{ 1404, "GETDNS_TLS1_3", GETDNS_TLS1_3_TEXT },
|
||||
{ 8192, "GETDNS_LOG_SYS_STUB", GETDNS_LOG_SYS_STUB_TEXT },
|
||||
{ 12288, "GETDNS_LOG_UPSTREAM_STATS", GETDNS_LOG_UPSTREAM_STATS_TEXT },
|
||||
{ 16384, "GETDNS_LOG_SYS_RECURSING", GETDNS_LOG_SYS_RECURSING_TEXT },
|
||||
{ 24576, "GETDNS_LOG_SYS_RESOLVING", GETDNS_LOG_SYS_RESOLVING_TEXT },
|
||||
{ 32768, "GETDNS_LOG_SYS_ANCHOR", GETDNS_LOG_SYS_ANCHOR_TEXT },
|
||||
};
|
||||
|
||||
static int const_info_cmp(const void *a, const void *b)
|
||||
|
@ -175,6 +190,7 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_CONTEXT_CODE_HOSTS", 630 },
|
||||
{ "GETDNS_CONTEXT_CODE_IDLE_TIMEOUT", 617 },
|
||||
{ "GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES", 606 },
|
||||
{ "GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE", 699 },
|
||||
{ "GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS", 615 },
|
||||
{ "GETDNS_CONTEXT_CODE_NAMESPACES", 600 },
|
||||
{ "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", 621 },
|
||||
|
@ -187,9 +203,14 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_CA_FILE", 632 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_CA_PATH", 631 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES", 635 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", 633 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_CURVES_LIST", 634 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_MAX_VERSION", 637 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_MIN_VERSION", 636 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
|
||||
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME", 638 },
|
||||
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", 625 },
|
||||
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA", 626 },
|
||||
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL", 627 },
|
||||
|
@ -208,7 +229,11 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_LOG_ERR", 3 },
|
||||
{ "GETDNS_LOG_INFO", 6 },
|
||||
{ "GETDNS_LOG_NOTICE", 5 },
|
||||
{ "GETDNS_LOG_UPSTREAM_STATS", 4096 },
|
||||
{ "GETDNS_LOG_SYS_ANCHOR", 32768 },
|
||||
{ "GETDNS_LOG_SYS_RECURSING", 16384 },
|
||||
{ "GETDNS_LOG_SYS_RESOLVING", 24576 },
|
||||
{ "GETDNS_LOG_SYS_STUB", 8192 },
|
||||
{ "GETDNS_LOG_UPSTREAM_STATS", 12288 },
|
||||
{ "GETDNS_LOG_WARNING", 4 },
|
||||
{ "GETDNS_NAMESPACE_DNS", 500 },
|
||||
{ "GETDNS_NAMESPACE_LOCALNAMES", 501 },
|
||||
|
@ -275,8 +300,10 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_RRCLASS_IN", 1 },
|
||||
{ "GETDNS_RRCLASS_NONE", 254 },
|
||||
{ "GETDNS_RRTYPE_A", 1 },
|
||||
{ "GETDNS_RRTYPE_A6", 38 },
|
||||
{ "GETDNS_RRTYPE_AAAA", 28 },
|
||||
{ "GETDNS_RRTYPE_AFSDB", 18 },
|
||||
{ "GETDNS_RRTYPE_AMTRELAY", 260 },
|
||||
{ "GETDNS_RRTYPE_ANY", 255 },
|
||||
{ "GETDNS_RRTYPE_APL", 42 },
|
||||
{ "GETDNS_RRTYPE_ATMA", 34 },
|
||||
|
@ -295,6 +322,8 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_RRTYPE_DOA", 259 },
|
||||
{ "GETDNS_RRTYPE_DS", 43 },
|
||||
{ "GETDNS_RRTYPE_EID", 31 },
|
||||
{ "GETDNS_RRTYPE_EUI48", 108 },
|
||||
{ "GETDNS_RRTYPE_EUI64", 109 },
|
||||
{ "GETDNS_RRTYPE_GID", 102 },
|
||||
{ "GETDNS_RRTYPE_GPOS", 27 },
|
||||
{ "GETDNS_RRTYPE_HINFO", 13 },
|
||||
|
@ -304,6 +333,8 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_RRTYPE_IXFR", 251 },
|
||||
{ "GETDNS_RRTYPE_KEY", 25 },
|
||||
{ "GETDNS_RRTYPE_KX", 36 },
|
||||
{ "GETDNS_RRTYPE_L32", 105 },
|
||||
{ "GETDNS_RRTYPE_L64", 106 },
|
||||
{ "GETDNS_RRTYPE_LOC", 29 },
|
||||
{ "GETDNS_RRTYPE_LP", 107 },
|
||||
{ "GETDNS_RRTYPE_MAILA", 254 },
|
||||
|
@ -323,6 +354,8 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_RRTYPE_NSAP", 22 },
|
||||
{ "GETDNS_RRTYPE_NSAP_PTR", 23 },
|
||||
{ "GETDNS_RRTYPE_NSEC", 47 },
|
||||
{ "GETDNS_RRTYPE_NSEC3", 50 },
|
||||
{ "GETDNS_RRTYPE_NSEC3PARAM", 51 },
|
||||
{ "GETDNS_RRTYPE_NULL", 10 },
|
||||
{ "GETDNS_RRTYPE_NXT", 30 },
|
||||
{ "GETDNS_RRTYPE_OPENPGPKEY", 61 },
|
||||
|
@ -351,6 +384,13 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_RRTYPE_UNSPEC", 103 },
|
||||
{ "GETDNS_RRTYPE_URI", 256 },
|
||||
{ "GETDNS_RRTYPE_WKS", 11 },
|
||||
{ "GETDNS_RRTYPE_X25", 19 },
|
||||
{ "GETDNS_RRTYPE_ZONEMD", 63 },
|
||||
{ "GETDNS_SSL3", 1400 },
|
||||
{ "GETDNS_TLS1", 1401 },
|
||||
{ "GETDNS_TLS1_1", 1402 },
|
||||
{ "GETDNS_TLS1_2", 1403 },
|
||||
{ "GETDNS_TLS1_3", 1404 },
|
||||
{ "GETDNS_TRANSPORT_TCP", 1201 },
|
||||
{ "GETDNS_TRANSPORT_TCP_ONLY", 542 },
|
||||
{ "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", 543 },
|
||||
|
|
|
@ -39,6 +39,14 @@
|
|||
#ifndef CONST_INFO_H_
|
||||
#define CONST_INFO_H_
|
||||
|
||||
#include "getdns/getdns.h"
|
||||
#include "getdns/getdns_extra.h"
|
||||
|
||||
#ifndef GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE
|
||||
#define GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE 699
|
||||
#define GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE_TEXT "Change related to getdns_context_set_max_backoff_value"
|
||||
#endif
|
||||
|
||||
struct const_info {
|
||||
int code;
|
||||
const char *name;
|
||||
|
|
1291
src/context.c
1291
src/context.c
File diff suppressed because it is too large
Load Diff
|
@ -50,6 +50,7 @@
|
|||
#endif
|
||||
#include "rr-iter.h"
|
||||
#include "anchor.h"
|
||||
#include "tls.h"
|
||||
|
||||
struct getdns_dns_req;
|
||||
struct ub_ctx;
|
||||
|
@ -127,7 +128,7 @@ const getdns_tsig_info *_getdns_get_tsig_info(getdns_tsig_algo tsig_alg);
|
|||
|
||||
/* for doing public key pinning of TLS-capable upstreams: */
|
||||
typedef struct sha256_pin {
|
||||
char pin[SHA256_DIGEST_LENGTH];
|
||||
uint8_t pin[SHA256_DIGEST_LENGTH];
|
||||
struct sha256_pin *next;
|
||||
} sha256_pin_t;
|
||||
|
||||
|
@ -193,20 +194,30 @@ typedef struct getdns_upstream {
|
|||
size_t responses_timeouts;
|
||||
size_t keepalive_shutdown;
|
||||
uint64_t keepalive_timeout;
|
||||
int server_keepalive_received;
|
||||
|
||||
/* Management of outstanding requests on stateful transports */
|
||||
getdns_network_req *write_queue;
|
||||
getdns_network_req *write_queue_last;
|
||||
_getdns_rbtree_t netreq_by_query_id;
|
||||
|
||||
/* TLS specific connection handling*/
|
||||
SSL* tls_obj;
|
||||
SSL_SESSION* tls_session;
|
||||
/* TCP specific connection handling*/
|
||||
unsigned tfo_use_sendto : 1;
|
||||
/* TLS specific connection handling*/
|
||||
unsigned tls_fallback_ok : 1;
|
||||
_getdns_tls_connection* tls_obj;
|
||||
_getdns_tls_session* tls_session;
|
||||
getdns_tls_hs_state_t tls_hs_state;
|
||||
getdns_auth_state_t tls_auth_state;
|
||||
unsigned tls_fallback_ok : 1;
|
||||
|
||||
/* TLS settings */
|
||||
char *tls_cipher_list;
|
||||
/* Auth credentials*/
|
||||
char *tls_ciphersuites;
|
||||
char *tls_curves_list;
|
||||
getdns_tls_version_t tls_min_version;
|
||||
getdns_tls_version_t tls_max_version;
|
||||
|
||||
/* Auth credentials */
|
||||
char tls_auth_name[256];
|
||||
sha256_pin_t *tls_pubkey_pinset;
|
||||
|
||||
|
@ -261,6 +272,7 @@ typedef struct getdns_upstreams {
|
|||
size_t count;
|
||||
size_t current_udp;
|
||||
size_t current_stateful;
|
||||
uint16_t max_backoff_value;
|
||||
uint16_t tls_backoff_time;
|
||||
uint16_t tls_connection_retries;
|
||||
getdns_log_config log;
|
||||
|
@ -338,6 +350,8 @@ struct getdns_context {
|
|||
char *trust_anchors_url;
|
||||
char *trust_anchors_verify_CA;
|
||||
char *trust_anchors_verify_email;
|
||||
uint64_t trust_anchors_backoff_time;
|
||||
uint64_t trust_anchors_backoff_expiry;
|
||||
|
||||
_getdns_ksks root_ksk;
|
||||
|
||||
|
@ -347,6 +361,10 @@ struct getdns_context {
|
|||
char *tls_ca_path;
|
||||
char *tls_ca_file;
|
||||
char *tls_cipher_list;
|
||||
char *tls_ciphersuites;
|
||||
char *tls_curves_list;
|
||||
getdns_tls_version_t tls_min_version;
|
||||
getdns_tls_version_t tls_max_version;
|
||||
|
||||
getdns_upstreams *upstreams;
|
||||
uint16_t limit_outstanding_queries;
|
||||
|
@ -354,6 +372,7 @@ struct getdns_context {
|
|||
getdns_tls_authentication_t tls_auth; /* What user requested for TLS*/
|
||||
getdns_tls_authentication_t tls_auth_min; /* Derived minimum auth allowed*/
|
||||
uint8_t round_robin_upstreams;
|
||||
uint16_t max_backoff_value;
|
||||
uint16_t tls_backoff_time;
|
||||
uint16_t tls_connection_retries;
|
||||
|
||||
|
@ -366,7 +385,7 @@ struct getdns_context {
|
|||
int edns_maximum_udp_payload_size; /* -1 is unset */
|
||||
uint8_t edns_client_subnet_private;
|
||||
uint16_t tls_query_padding_blocksize;
|
||||
SSL_CTX* tls_ctx;
|
||||
_getdns_tls_context* tls_ctx;
|
||||
|
||||
getdns_update_callback update_callback;
|
||||
getdns_update_callback2 update_callback2;
|
||||
|
@ -428,6 +447,7 @@ struct getdns_context {
|
|||
getdns_dict *header;
|
||||
getdns_dict *add_opt_parameters;
|
||||
unsigned add_warning_for_bad_dns : 1;
|
||||
unsigned dnssec : 1;
|
||||
unsigned dnssec_return_all_statuses : 1;
|
||||
unsigned dnssec_return_full_validation_chain : 1;
|
||||
unsigned dnssec_return_only_secure : 1;
|
||||
|
@ -485,11 +505,38 @@ struct getdns_context {
|
|||
#endif /* HAVE_MDNS_SUPPORT */
|
||||
}; /* getdns_context */
|
||||
|
||||
void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system,
|
||||
getdns_loglevel_type level, const char *fmt, ...);
|
||||
static inline int _getdns_check_log(const getdns_log_config *log,
|
||||
uint64_t system, getdns_loglevel_type level)
|
||||
{ assert(log)
|
||||
; return log->func && (log->system & system) && level <= log->level; }
|
||||
|
||||
void _getdns_context_log(getdns_context *context, uint64_t system,
|
||||
getdns_loglevel_type level, const char *fmt, ...);
|
||||
static inline void _getdns_log(const getdns_log_config *log,
|
||||
uint64_t system, getdns_loglevel_type level, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (!_getdns_check_log(log, system, level))
|
||||
return;
|
||||
|
||||
va_start(args, fmt);
|
||||
log->func(log->userarg, system, level, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static inline void _getdns_upstream_log(const getdns_upstream *up,
|
||||
uint64_t system, getdns_loglevel_type level, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (!up || !up->upstreams
|
||||
|| !_getdns_check_log(&up->upstreams->log, system, level))
|
||||
return;
|
||||
|
||||
va_start(args, fmt);
|
||||
up->upstreams->log.func(
|
||||
up->upstreams->log.userarg, system, level, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
/** internal functions **/
|
||||
|
@ -546,8 +593,9 @@ void _getdns_upstreams_dereference(getdns_upstreams *upstreams);
|
|||
|
||||
void _getdns_upstream_shutdown(getdns_upstream *upstream);
|
||||
|
||||
FILE *_getdns_context_get_priv_fp(getdns_context *context, const char *fn);
|
||||
uint8_t *_getdns_context_get_priv_file(getdns_context *context,
|
||||
FILE *_getdns_context_get_priv_fp(
|
||||
const getdns_context *context, const char *fn);
|
||||
uint8_t *_getdns_context_get_priv_file(const getdns_context *context,
|
||||
const char *fn, uint8_t *buf, size_t buf_len, size_t *file_sz);
|
||||
|
||||
int _getdns_context_write_priv_file(getdns_context *context,
|
||||
|
|
104
src/convert.c
104
src/convert.c
|
@ -39,7 +39,9 @@
|
|||
#ifndef USE_WINSOCK
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBIDN
|
||||
#if defined(HAVE_LIBIDN2)
|
||||
#include <idn2.h>
|
||||
#elif defined(HAVE_LIBIDN)
|
||||
#include <stringprep.h>
|
||||
#include <idna.h>
|
||||
#endif
|
||||
|
@ -54,7 +56,9 @@
|
|||
#include "dict.h"
|
||||
#include "list.h"
|
||||
#include "jsmn/jsmn.h"
|
||||
#ifdef USE_YAML_CONFIG
|
||||
#include "yaml/convert_yaml_to_json.h"
|
||||
#endif
|
||||
#include "convert.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -113,48 +117,43 @@ getdns_convert_fqdn_to_dns_name(
|
|||
char *
|
||||
getdns_convert_ulabel_to_alabel(const char *ulabel)
|
||||
{
|
||||
#ifdef HAVE_LIBIDN
|
||||
int ret;
|
||||
char *buf;
|
||||
char *prepped;
|
||||
char *prepped2;
|
||||
#if defined(HAVE_LIBIDN2)
|
||||
uint8_t *alabel;
|
||||
|
||||
if (ulabel == NULL)
|
||||
return 0;
|
||||
prepped2 = malloc(BUFSIZ);
|
||||
if(!prepped2)
|
||||
return 0;
|
||||
setlocale(LC_ALL, "");
|
||||
if ((prepped = stringprep_locale_to_utf8(ulabel)) == 0) {
|
||||
/* convert to utf8 fails, which it can, but continue anyway */
|
||||
if(strlen(ulabel)+1 > BUFSIZ) {
|
||||
free(prepped2);
|
||||
return 0;
|
||||
}
|
||||
memcpy(prepped2, ulabel, strlen(ulabel)+1);
|
||||
} else {
|
||||
if(strlen(prepped)+1 > BUFSIZ) {
|
||||
free(prepped);
|
||||
free(prepped2);
|
||||
return 0;
|
||||
}
|
||||
memcpy(prepped2, prepped, strlen(prepped)+1);
|
||||
free(prepped);
|
||||
}
|
||||
if ((ret = stringprep(prepped2, BUFSIZ, 0, stringprep_nameprep)) != STRINGPREP_OK) {
|
||||
free(prepped2);
|
||||
return 0;
|
||||
}
|
||||
if ((ret = idna_to_ascii_8z(prepped2, &buf, 0)) != IDNA_SUCCESS) {
|
||||
free(prepped2);
|
||||
return 0;
|
||||
}
|
||||
free(prepped2);
|
||||
return buf;
|
||||
if (!ulabel) return NULL;
|
||||
|
||||
if (idn2_lookup_u8((uint8_t *)ulabel, &alabel, IDN2_TRANSITIONAL) == IDN2_OK)
|
||||
return (char *)alabel;
|
||||
|
||||
#elif defined(HAVE_LIBIDN)
|
||||
char *alabel;
|
||||
char *prepped;
|
||||
char prepped2[BUFSIZ];
|
||||
|
||||
if (!ulabel) return NULL;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
if ((prepped = stringprep_locale_to_utf8(ulabel))) {
|
||||
if(strlen(prepped)+1 > BUFSIZ) {
|
||||
free(prepped);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(prepped2, prepped, strlen(prepped)+1);
|
||||
free(prepped);
|
||||
|
||||
/* convert to utf8 fails, which it can, but continue anyway */
|
||||
} else if (strlen(ulabel)+1 > BUFSIZ)
|
||||
return NULL;
|
||||
else
|
||||
memcpy(prepped2, ulabel, strlen(ulabel)+1);
|
||||
|
||||
if (stringprep(prepped2, BUFSIZ, 0, stringprep_nameprep) == STRINGPREP_OK
|
||||
&& idna_to_ascii_8z(prepped2, &alabel, 0) == IDNA_SUCCESS)
|
||||
return alabel;
|
||||
#else
|
||||
(void)ulabel;
|
||||
return NULL;
|
||||
(void)ulabel;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*---------------------------------------- getdns_convert_alabel_to_ulabel */
|
||||
|
@ -171,20 +170,21 @@ getdns_convert_ulabel_to_alabel(const char *ulabel)
|
|||
char *
|
||||
getdns_convert_alabel_to_ulabel(const char *alabel)
|
||||
{
|
||||
#ifdef HAVE_LIBIDN
|
||||
int ret; /* just in case we might want to use it someday */
|
||||
char *buf;
|
||||
#if defined(HAVE_LIBIDN2) || defined(HAVE_LIBIDN)
|
||||
char *ulabel;
|
||||
|
||||
if (alabel == NULL)
|
||||
return 0;
|
||||
if ((ret = idna_to_unicode_8z8z(alabel, &buf, 0)) != IDNA_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
if (!alabel) return NULL;
|
||||
|
||||
# if defined(HAVE_LIBIDN2)
|
||||
if (idn2_to_unicode_8z8z(alabel, &ulabel, 0) == IDN2_OK)
|
||||
# else
|
||||
if (idna_to_unicode_8z8z(alabel, &ulabel, 0) == IDNA_SUCCESS)
|
||||
# endif
|
||||
return ulabel;
|
||||
#else
|
||||
(void)alabel;
|
||||
return NULL;
|
||||
(void)alabel;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1670,7 +1670,7 @@ getdns_str2dict(const char *str, getdns_dict **dict)
|
|||
if (!str || !dict)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
while (*str && isspace(*str))
|
||||
while (*str && isspace((unsigned char)*str))
|
||||
str++;
|
||||
|
||||
if (*str != '{') {
|
||||
|
|
57
src/dict.c
57
src/dict.c
|
@ -434,7 +434,7 @@ getdns_dict_create_with_memory_functions(void *(*malloc)(size_t),
|
|||
|
||||
/*-------------------------- getdns_dict_create_with_context */
|
||||
struct getdns_dict *
|
||||
getdns_dict_create_with_context(struct getdns_context *context)
|
||||
getdns_dict_create_with_context(const getdns_context *context)
|
||||
{
|
||||
if (context)
|
||||
return getdns_dict_create_with_extended_memory_functions(
|
||||
|
@ -655,7 +655,8 @@ getdns_dict_set_bindata(
|
|||
|
||||
/*---------------------------------------- getdns_dict_set_bindata */
|
||||
getdns_return_t
|
||||
getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value)
|
||||
getdns_dict_util_set_string(getdns_dict *dict,
|
||||
const char *name, const char *value)
|
||||
{
|
||||
getdns_item *item;
|
||||
getdns_bindata *newbindata;
|
||||
|
@ -737,21 +738,16 @@ getdns_pp_base64(gldns_buffer *buf, getdns_bindata *bindata)
|
|||
{
|
||||
size_t p = gldns_buffer_position(buf);
|
||||
size_t base64str_sz;
|
||||
char *target;
|
||||
size_t avail;
|
||||
|
||||
if (gldns_buffer_printf(buf, " <bindata of ") < 0)
|
||||
return -1;
|
||||
|
||||
base64str_sz = gldns_b64_ntop_calculate_size(bindata->size);
|
||||
target = (char *)gldns_buffer_current(buf);
|
||||
avail = gldns_buffer_remaining(buf);
|
||||
if (avail >= base64str_sz)
|
||||
gldns_buffer_skip(buf, gldns_b64_ntop(
|
||||
bindata->data, bindata->size,
|
||||
target, base64str_sz));
|
||||
else
|
||||
gldns_buffer_skip(buf, base64str_sz);
|
||||
if (!gldns_buffer_reserve(buf, base64str_sz))
|
||||
return -1;
|
||||
|
||||
gldns_buffer_skip(buf, gldns_b64_ntop(bindata->data, bindata->size,
|
||||
(char *)gldns_buffer_current(buf), base64str_sz));
|
||||
|
||||
if (gldns_buffer_printf(buf, ">") < 0)
|
||||
return -1;
|
||||
|
@ -786,13 +782,37 @@ getdns_pp_bindata(gldns_buffer *buf, getdns_bindata *bindata,
|
|||
|
||||
if (bindata->size > 0 && i == bindata->size) { /* all printable? */
|
||||
|
||||
if (json)
|
||||
(void)snprintf(spc, sizeof(spc), "\"%%.%ds\"", (int)i);
|
||||
else
|
||||
if (json) {
|
||||
const uint8_t *s = bindata->data;
|
||||
const uint8_t *e = s + bindata->size;
|
||||
const uint8_t *b;
|
||||
|
||||
if (!gldns_buffer_reserve(buf, (e - s) + 2))
|
||||
return -1;
|
||||
gldns_buffer_write_u8(buf, '"');
|
||||
for (;;) {
|
||||
for ( b = s
|
||||
; b < e && *b != '\\' && *b != '"'
|
||||
; b++)
|
||||
; /* pass */
|
||||
if (b == e)
|
||||
break;
|
||||
if (!gldns_buffer_reserve(buf, (b - s) + 3))
|
||||
return -1;
|
||||
gldns_buffer_write(buf, s, b - s);
|
||||
gldns_buffer_write_u8(buf, '\\');
|
||||
gldns_buffer_write_u8(buf, *b);
|
||||
s = b + 1;
|
||||
}
|
||||
if (s < e)
|
||||
gldns_buffer_write(buf, s, e - s);
|
||||
gldns_buffer_write_u8(buf, '"');
|
||||
} else {
|
||||
(void)snprintf(spc, sizeof(spc), "of \"%%.%ds\"%s>",
|
||||
(int)(i > 32 ? 32 : i), (i > 32 ? "..." : ""));
|
||||
if (gldns_buffer_printf(buf, spc, bindata->data) < 0)
|
||||
return -1;
|
||||
if (gldns_buffer_printf(buf, spc, bindata->data) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else if (bindata->size > 1 && /* null terminated printable */
|
||||
i == bindata->size - 1 && bindata->data[i] == 0) {
|
||||
|
@ -1083,9 +1103,12 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent,
|
|||
strcmp(item->node.key, "transport") == 0 ||
|
||||
strcmp(item->node.key, "resolution_type") == 0 ||
|
||||
strcmp(item->node.key, "tls_authentication") == 0 ||
|
||||
strcmp(item->node.key, "tls_min_version") == 0 ||
|
||||
strcmp(item->node.key, "tls_max_version") == 0 ||
|
||||
|
||||
/* extensions */
|
||||
strcmp(item->node.key, "add_warning_for_bad_dns") == 0 ||
|
||||
strcmp(item->node.key, "dnssec") == 0 ||
|
||||
strcmp(item->node.key, "dnssec_return_all_statuses") == 0 ||
|
||||
strcmp(item->node.key, "dnssec_return_full_validation_chain") == 0 ||
|
||||
strcmp(item->node.key, "dnssec_return_only_secure") == 0 ||
|
||||
|
|
596
src/dnssec.c
596
src/dnssec.c
|
@ -79,8 +79,8 @@
|
|||
/* Outline of operations in this file
|
||||
* ==================================
|
||||
*
|
||||
* Data structure to represent the delegation/referal hierarchy
|
||||
* ------------------------------------------------------------
|
||||
* Data structure to represent the delegation/referral hierarchy
|
||||
* -------------------------------------------------------------
|
||||
* Both the "dnssec_return_validation_chain" extension, and the
|
||||
* getdns_validate_dnssec() function use the same structs to represent the
|
||||
* involved pieces of the DNS in a hierarchical manner.
|
||||
|
@ -134,7 +134,7 @@
|
|||
* in a _getdns_rrset, and the rrsig_iter to iterate over the RRSIGs covering
|
||||
* the RRs in the _getdns_rrset.
|
||||
*
|
||||
* The _getdns_rrsets are already equiped with name/rr_class and rr_type when
|
||||
* The _getdns_rrsets are already equipped with name/rr_class and rr_type when
|
||||
* constructing the linked list of chain_nodes up to the root for a chain_head.
|
||||
* They are substantiated with the wireformat packets that are returned with
|
||||
* the queries that were sheduled in the context of the
|
||||
|
@ -146,7 +146,7 @@
|
|||
* of non-existance.
|
||||
*
|
||||
* The getdns_validate_dnssec() function, after it constructed the chain_heads
|
||||
* hierarchy, creates an artifical packet for the support records and equips
|
||||
* hierarchy, creates an artificial packet for the support records and equips
|
||||
* all the ds and dnskey _getdns_rrsets on the chain_nodes with this packet.
|
||||
*
|
||||
* The _getdns_rrset + support function and data types are defined in section:
|
||||
|
@ -178,7 +178,7 @@
|
|||
* "DNSSEC Validation".
|
||||
*
|
||||
* Many functions are of key verification boolean return type; e.g.
|
||||
* key_proves_non_existance(), ds_authenticates_keys(), a_key_signed_rrset()
|
||||
* key_proves_nonexistance(), ds_authenticates_keys(), a_key_signed_rrset()
|
||||
* These will return the keytag identifying the key that was used to
|
||||
* authenticate + 0x10000 to allow keytag 0.
|
||||
*
|
||||
|
@ -194,7 +194,6 @@
|
|||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <openssl/sha.h>
|
||||
#include "getdns/getdns.h"
|
||||
#include "context.h"
|
||||
#include "util-internal.h"
|
||||
|
@ -210,6 +209,7 @@
|
|||
#include "list.h"
|
||||
#include "util/val_secalgo.h"
|
||||
#include "anchor.h"
|
||||
#include "tls.h"
|
||||
|
||||
#define SIGNATURE_VERIFIED 0x10000
|
||||
#define NSEC3_ITERATION_COUNT_HIGH 0x20000
|
||||
|
@ -244,13 +244,16 @@ static inline int _dname_equal(const uint8_t *left, const uint8_t *right)
|
|||
static int _dname_is_parent(
|
||||
const uint8_t * const parent, const uint8_t *subdomain)
|
||||
{
|
||||
while (*subdomain) {
|
||||
if (*parent == 0)
|
||||
return 1;
|
||||
|
||||
else while (*subdomain) {
|
||||
if (_dname_equal(parent, subdomain))
|
||||
return 1;
|
||||
|
||||
subdomain += *subdomain + 1;
|
||||
}
|
||||
return *parent == 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t *_dname_label_copy(uint8_t *dst, const uint8_t *src, size_t dst_len)
|
||||
|
@ -506,8 +509,6 @@ struct chain_node {
|
|||
getdns_network_req *ds_req;
|
||||
int ds_signer;
|
||||
|
||||
getdns_network_req *soa_req;
|
||||
|
||||
chain_head *chains;
|
||||
};
|
||||
|
||||
|
@ -521,9 +522,8 @@ struct chain_node {
|
|||
static void val_chain_sched(chain_head *head, const uint8_t *dname);
|
||||
static void val_chain_sched_ds(chain_head *head, const uint8_t *dname);
|
||||
static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig);
|
||||
static void val_chain_sched_soa(chain_head *head, const uint8_t *dname);
|
||||
|
||||
static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
|
||||
static chain_head *add_rrset2val_chain(const struct mem_funcs *mf,
|
||||
chain_head **chain_p, _getdns_rrset *rrset, getdns_network_req *netreq)
|
||||
{
|
||||
chain_head *head;
|
||||
|
@ -663,7 +663,6 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
|
|||
node->dnskey.sections = head->rrset.sections;
|
||||
node->ds_req = NULL;
|
||||
node->dnskey_req = NULL;
|
||||
node->soa_req = NULL;
|
||||
node->ds_signer = -1;
|
||||
node->dnskey_signer = -1;
|
||||
|
||||
|
@ -675,6 +674,24 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
|
|||
if (!(node[-1].parent = max_node))
|
||||
val_chain_sched(head, (uint8_t *)"\0");
|
||||
|
||||
/* For an NSEC or NSEC3 query, stop at that. If it is valid it will
|
||||
* have a signature which will be chased.
|
||||
*/
|
||||
if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC ||
|
||||
head->rrset.rr_type == GETDNS_RRTYPE_NSEC3)
|
||||
return head;
|
||||
|
||||
/* Otherwise, schedule key lookups for the tld and sld too. */
|
||||
if (!max_node) {
|
||||
if (head->node_count > 1)
|
||||
val_chain_sched(head, node[-2].ds.name);
|
||||
if (head->node_count > 2)
|
||||
val_chain_sched(head, node[-3].ds.name);
|
||||
} else if ((max_labels == 1 || max_labels == 2) && head->node_count > 0)
|
||||
val_chain_sched(head, node[-1].ds.name);
|
||||
if (max_labels == 1 && head->node_count > 1)
|
||||
val_chain_sched(head, node[-2].ds.name);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
|
@ -771,7 +788,7 @@ static int is_synthesized_cname(_getdns_rrset *cname)
|
|||
* When a SOA query was successful, a query for DS will follow for that
|
||||
* owner name.
|
||||
*/
|
||||
static void add_pkt2val_chain(struct mem_funcs *mf,
|
||||
static void add_pkt2val_chain(const struct mem_funcs *mf,
|
||||
chain_head **chain_p, uint8_t *pkt, size_t pkt_len,
|
||||
getdns_network_req *netreq)
|
||||
{
|
||||
|
@ -822,9 +839,9 @@ static void add_pkt2val_chain(struct mem_funcs *mf,
|
|||
if (rrset->rr_type == GETDNS_RRTYPE_SOA)
|
||||
val_chain_sched_ds(head, rrset->name);
|
||||
else if (rrset->rr_type == GETDNS_RRTYPE_CNAME)
|
||||
val_chain_sched_soa(head, rrset->name + *rrset->name + 1);
|
||||
val_chain_sched_ds(head, rrset->name + *rrset->name + 1);
|
||||
else
|
||||
val_chain_sched_soa(head, rrset->name);
|
||||
val_chain_sched_ds(head, rrset->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -833,11 +850,16 @@ static void add_pkt2val_chain(struct mem_funcs *mf,
|
|||
* checked eventually.
|
||||
* But only if we know the question of course...
|
||||
*/
|
||||
static void add_question2val_chain(struct mem_funcs *mf,
|
||||
static void add_question2val_chain(const struct mem_funcs *mf,
|
||||
chain_head **chain_p, uint8_t *pkt, size_t pkt_len,
|
||||
const uint8_t *qname, uint16_t qtype, uint16_t qclass,
|
||||
getdns_network_req *netreq)
|
||||
{
|
||||
_getdns_rrset_iter *i, i_spc;
|
||||
_getdns_rrset *rrset;
|
||||
_getdns_rrsig_iter rrsig_spc;
|
||||
size_t n_soas;
|
||||
|
||||
_getdns_rrset_spc q_rrset;
|
||||
chain_head *head;
|
||||
|
||||
|
@ -863,9 +885,29 @@ static void add_question2val_chain(struct mem_funcs *mf,
|
|||
debug_sec_print_rrset("Adding NX rrset: ", &q_rrset.rrset);
|
||||
head = add_rrset2val_chain(mf, chain_p, &q_rrset.rrset, netreq);
|
||||
|
||||
/* On empty packet, find SOA (zonecut) for the qname */
|
||||
if (head && GLDNS_ANCOUNT(pkt) == 0 && GLDNS_NSCOUNT(pkt) == 0)
|
||||
val_chain_sched_soa(head, q_rrset.rrset.name);
|
||||
/* Insecure SOA indicating a zonecut in the authority section?
|
||||
* Then schedule a DS query at the zonecut for insecure proof.
|
||||
*/
|
||||
n_soas = 0;
|
||||
for ( i = _getdns_rrset_iter_init(&i_spc, pkt, pkt_len
|
||||
, SECTION_AUTHORITY)
|
||||
; i ; i = _getdns_rrset_iter_next(i)) {
|
||||
rrset = _getdns_rrset_iter_value(i);
|
||||
debug_sec_print_rrset("rrset: ", rrset);
|
||||
|
||||
if (rrset->rr_type != GETDNS_RRTYPE_SOA)
|
||||
continue;
|
||||
|
||||
n_soas += 1;
|
||||
|
||||
if (_getdns_rrsig_iter_init(&rrsig_spc, rrset))
|
||||
continue;
|
||||
|
||||
val_chain_sched_ds(head, rrset->name);
|
||||
}
|
||||
/* No answer and no SOA indicating a zonecut? Find zonecut */
|
||||
if (n_soas == 0)
|
||||
val_chain_sched_ds(head, q_rrset.rrset.name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -887,55 +929,6 @@ static getdns_dict *CD_extension(getdns_dns_req *dnsreq)
|
|||
}
|
||||
|
||||
static void check_chain_complete(chain_head *chain);
|
||||
static void val_chain_node_soa_cb(getdns_dns_req *dnsreq);
|
||||
static void val_chain_sched_soa_node(chain_node *node)
|
||||
{
|
||||
getdns_context *context;
|
||||
getdns_eventloop *loop;
|
||||
char name[1024];
|
||||
|
||||
context = node->chains->netreq->owner->context;
|
||||
loop = node->chains->netreq->owner->loop;
|
||||
|
||||
if (!gldns_wire2str_dname_buf(
|
||||
(UNCONST_UINT8_p)node->ds.name, 256, name, sizeof(name)))
|
||||
return;
|
||||
|
||||
DEBUG_SEC("schedule SOA lookup for %s\n", name);
|
||||
|
||||
node->lock++;
|
||||
if (! node->soa_req &&
|
||||
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_SOA,
|
||||
CD_extension(node->chains->netreq->owner), node, &node->soa_req,
|
||||
NULL, val_chain_node_soa_cb))
|
||||
|
||||
node->soa_req = NULL;
|
||||
|
||||
if (node->lock) node->lock--;
|
||||
}
|
||||
|
||||
/* A SOA lookup is scheduled as a last resort. No signatures were found and
|
||||
* no SOA in the authority section. If a SOA query returns an actual SOA
|
||||
* answer, then a DS/DNSKEY lookup will follow the acquire the link of the
|
||||
* authentication chain.
|
||||
*/
|
||||
static void val_chain_sched_soa(chain_head *head, const uint8_t *dname)
|
||||
{
|
||||
chain_node *node;
|
||||
|
||||
if (!head->netreq)
|
||||
return;
|
||||
|
||||
if (!*dname)
|
||||
return;
|
||||
|
||||
for ( node = head->parent
|
||||
; node && !_dname_equal(dname, node->ds.name)
|
||||
; node = node->parent);
|
||||
|
||||
if (node)
|
||||
val_chain_sched_soa_node(node);
|
||||
}
|
||||
|
||||
static chain_head *_dnskey_query(const chain_node *node)
|
||||
{
|
||||
|
@ -1079,6 +1072,105 @@ static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig)
|
|||
val_chain_sched_signer_node(head->parent, rrsig);
|
||||
}
|
||||
|
||||
/* Cancel all DS and DNSKEY for subdomains of parent_dname,
|
||||
* and also the DNSKEY query at the parent_dname
|
||||
*/
|
||||
static void cancel_requests_for_subdomains_of(
|
||||
chain_head *head, const uint8_t *parent_dname)
|
||||
{
|
||||
chain_head *next;
|
||||
chain_node *node;
|
||||
size_t node_count;
|
||||
|
||||
while (head) {
|
||||
next = head->next;
|
||||
|
||||
if (!_dname_is_parent(parent_dname, head->rrset.name)) {
|
||||
head = next;
|
||||
continue;
|
||||
}
|
||||
for ( node_count = head->node_count, node = head->parent
|
||||
; node_count
|
||||
; node_count--, node = node->parent ) {
|
||||
|
||||
if (!_getdns_netreq_finished(node->dnskey_req)) {
|
||||
_getdns_context_cancel_request(
|
||||
node->dnskey_req->owner);
|
||||
node->dnskey_req = NULL;
|
||||
}
|
||||
|
||||
if (_dname_equal(parent_dname, node->ds.name))
|
||||
break;
|
||||
|
||||
if (!_getdns_netreq_finished(node->ds_req)) {
|
||||
_getdns_context_cancel_request(
|
||||
node->ds_req->owner);
|
||||
node->ds_req = NULL;
|
||||
}
|
||||
}
|
||||
head = next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int nsec3_matches_name(_getdns_rrset *nsec3, const uint8_t *name);
|
||||
static int nsec3_covers_name(
|
||||
_getdns_rrset *nsec3, const uint8_t *name, int *opt_out);
|
||||
|
||||
static int insecure_delegation(_getdns_rrset *ds_rrset)
|
||||
{
|
||||
_getdns_rrset nsec_rrset;
|
||||
_getdns_rrtype_iter *rr, rr_spc;
|
||||
_getdns_rrsig_iter rrsig_spc;
|
||||
_getdns_rdf_iter bitmap_spc, *bitmap;
|
||||
_getdns_rrset_iter *i, i_spc;
|
||||
|
||||
/* For NSEC, an insecure delegation is a NODATA proof for DS */
|
||||
nsec_rrset = *ds_rrset;
|
||||
nsec_rrset.rr_type = GETDNS_RRTYPE_NSEC;
|
||||
if (!_getdns_rrsig_iter_init(&rrsig_spc, &nsec_rrset))
|
||||
; /* pass */
|
||||
else for ( rr = _getdns_rrtype_iter_init(&rr_spc, &nsec_rrset)
|
||||
; rr ; rr = _getdns_rrtype_iter_next(rr)) {
|
||||
|
||||
if ((bitmap = _getdns_rdf_iter_init_at( &bitmap_spc
|
||||
, &rr->rr_i, 1))
|
||||
&& bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
|
||||
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_DS)
|
||||
&& _getdns_rrsig_iter_init(&rrsig_spc, &nsec_rrset))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For NSEC3 it is either a NODATA proof with a delegation,
|
||||
or a NSEC3 opt-out coverage */
|
||||
for ( i = _getdns_rrset_iter_init(&i_spc, ds_rrset->pkt
|
||||
, ds_rrset->pkt_len
|
||||
, SECTION_NO_ADDITIONAL)
|
||||
; i ; i = _getdns_rrset_iter_next(i)) {
|
||||
_getdns_rrset *nsec3_rrset = _getdns_rrset_iter_value(i);
|
||||
int opt_out;
|
||||
|
||||
if ( !nsec3_rrset
|
||||
|| nsec3_rrset->rr_type != GETDNS_RRTYPE_NSEC3
|
||||
||!(rr = _getdns_rrtype_iter_init(&rr_spc, nsec3_rrset)))
|
||||
continue;
|
||||
|
||||
if (!nsec3_covers_name(nsec3_rrset, ds_rrset->name, &opt_out))
|
||||
continue;
|
||||
|
||||
if (nsec3_matches_name(nsec3_rrset, ds_rrset->name)) {
|
||||
bitmap = _getdns_rdf_iter_init_at( &bitmap_spc
|
||||
, &rr->rr_i, 5);
|
||||
return bitmap
|
||||
&& bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
|
||||
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_DS);
|
||||
}
|
||||
else if (opt_out)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void val_chain_node_cb(getdns_dns_req *dnsreq)
|
||||
{
|
||||
chain_node *node = (chain_node *)dnsreq->user_pointer;
|
||||
|
@ -1120,58 +1212,27 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq)
|
|||
n_signers++;
|
||||
}
|
||||
}
|
||||
if (netreq->request_type == GETDNS_RRTYPE_DS && n_signers == 0)
|
||||
if (netreq->request_type != GETDNS_RRTYPE_DS)
|
||||
; /* pass */
|
||||
else if (n_signers) {
|
||||
_getdns_rrtype_iter ds_spc;
|
||||
|
||||
if (_getdns_rrtype_iter_init(&ds_spc, &node->ds))
|
||||
; /* pass */
|
||||
|
||||
else if (insecure_delegation(&node->ds)) {
|
||||
debug_sec_print_rrset("Insecure delegation. "
|
||||
"Canceling requests below ", &node->ds);
|
||||
cancel_requests_for_subdomains_of(
|
||||
node->chains, node->ds.name);
|
||||
} else {
|
||||
debug_sec_print_rrset("No DS at ", &node->ds);
|
||||
}
|
||||
} else {
|
||||
/* No signed DS and no signed proof of non-existance.
|
||||
* Search further up the tree...
|
||||
*/
|
||||
val_chain_sched_soa_node(node->parent);
|
||||
|
||||
if (node->lock) node->lock--;
|
||||
check_chain_complete(node->chains);
|
||||
}
|
||||
|
||||
|
||||
static void val_chain_node_soa_cb(getdns_dns_req *dnsreq)
|
||||
{
|
||||
chain_node *node = (chain_node *)dnsreq->user_pointer;
|
||||
getdns_network_req *netreq = dnsreq->netreqs[0];
|
||||
_getdns_rrset_iter i_spc, *i;
|
||||
_getdns_rrset *rrset;
|
||||
|
||||
/* A SOA query is always scheduled with a node as the user argument.
|
||||
*/
|
||||
assert(node != NULL);
|
||||
|
||||
for ( i = _getdns_rrset_iter_init(&i_spc, netreq->response
|
||||
, netreq->response_len
|
||||
, SECTION_ANSWER)
|
||||
; i
|
||||
; i = _getdns_rrset_iter_next(i)) {
|
||||
|
||||
rrset = _getdns_rrset_iter_value(i);
|
||||
if (rrset->rr_type != GETDNS_RRTYPE_SOA)
|
||||
continue;
|
||||
|
||||
while (node &&
|
||||
! _dname_equal(node->ds.name, rrset->name))
|
||||
node = node->parent;
|
||||
|
||||
if (node) {
|
||||
node->lock++;
|
||||
val_chain_sched_ds_node(node);
|
||||
} else {
|
||||
/* SOA for a different name */
|
||||
node = (chain_node *)dnsreq->user_pointer;
|
||||
if (node->parent) {
|
||||
node->lock++;
|
||||
val_chain_sched_soa_node(node->parent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!i && node->parent) {
|
||||
node->lock++;
|
||||
val_chain_sched_soa_node(node->parent);
|
||||
val_chain_sched_ds_node(node->parent);
|
||||
}
|
||||
if (node->lock) node->lock--;
|
||||
check_chain_complete(node->chains);
|
||||
|
@ -1368,8 +1429,9 @@ static int _rr_iter_rdata_cmp(const void *a, const void *b)
|
|||
* nc_name will be set to the next closer (within rrset->name).
|
||||
*/
|
||||
#define VAL_RRSET_SPC_SZ 256
|
||||
static int _getdns_verify_rrsig(struct mem_funcs *mf,
|
||||
_getdns_rrset *rrset, _getdns_rrsig_iter *rrsig, _getdns_rrtype_iter *key, const uint8_t **nc_name)
|
||||
static int _getdns_verify_rrsig(const struct mem_funcs *mf,
|
||||
_getdns_rrset *rrset, _getdns_rrsig_iter *rrsig, _getdns_rrtype_iter *key,
|
||||
const uint8_t **nc_name)
|
||||
{
|
||||
int r;
|
||||
int to_skip;
|
||||
|
@ -1587,12 +1649,12 @@ static uint8_t *_getdns_nsec3_hash_label(uint8_t *label, size_t label_len,
|
|||
(void)memcpy(dst, salt + 1, *salt);
|
||||
dst += *salt;
|
||||
|
||||
(void)SHA1(buf, dst - buf, md);
|
||||
_getdns_tls_sha1(buf, dst - buf, md);
|
||||
if (iterations) {
|
||||
(void)memcpy(buf + SHA_DIGEST_LENGTH, salt + 1, *salt);
|
||||
while (iterations--) {
|
||||
(void)memcpy(buf, md, SHA_DIGEST_LENGTH);
|
||||
SHA1(buf, SHA_DIGEST_LENGTH + *salt, md);
|
||||
_getdns_tls_sha1(buf, SHA_DIGEST_LENGTH + *salt, md);
|
||||
}
|
||||
}
|
||||
*label = gldns_b32_ntop_extended_hex(
|
||||
|
@ -1687,8 +1749,9 @@ static int check_dates(time_t now, int32_t skew, int32_t exp, int32_t inc)
|
|||
/* Returns whether dnskey signed rrset. If the rrset was a valid wildcard
|
||||
* expansion, nc_name will point to the next closer part of the name in rrset.
|
||||
*/
|
||||
static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
_getdns_rrtype_iter *dnskey, _getdns_rrset *rrset, const uint8_t **nc_name)
|
||||
static int dnskey_signed_rrset(const struct mem_funcs *mf, time_t now,
|
||||
uint32_t skew, _getdns_rrtype_iter *dnskey, _getdns_rrset *rrset,
|
||||
const uint8_t **nc_name)
|
||||
{
|
||||
_getdns_rrsig_iter rrsig_spc, *rrsig;
|
||||
_getdns_rdf_iter rdf_spc, *rdf;
|
||||
|
@ -1755,16 +1818,46 @@ static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int find_nsec_covering_name(
|
||||
struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey,
|
||||
/* Returns whether a dnskey for keyset signed a non wildcard rrset. */
|
||||
static int a_key_signed_rrset_no_wc(const struct mem_funcs *mf, time_t now,
|
||||
uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset)
|
||||
{
|
||||
_getdns_rrtype_iter dnskey_spc, *dnskey;
|
||||
const uint8_t *nc_name; /* Initialized by dnskey_signed_rrset() */
|
||||
int keytag;
|
||||
|
||||
assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
|
||||
|
||||
for ( dnskey = _getdns_rrtype_iter_init(&dnskey_spc, keyset)
|
||||
; dnskey ; dnskey = _getdns_rrtype_iter_next(dnskey) ) {
|
||||
|
||||
if (!(keytag = dnskey_signed_rrset(mf, now, skew,
|
||||
dnskey, rrset, &nc_name)))
|
||||
continue;
|
||||
|
||||
if (!nc_name) /* Not a wildcard, then success! */
|
||||
return keytag;
|
||||
|
||||
/* Not a wildcard expansion, but the wildcard name itself. */
|
||||
if (rrset->rr_type == GETDNS_RRTYPE_NSEC &&
|
||||
rrset->name[0] == 1 && rrset->name[1] == '*' &&
|
||||
nc_name == rrset->name)
|
||||
return keytag;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_nsec_covering_name(const struct mem_funcs *mf,
|
||||
time_t now, uint32_t skew, _getdns_rrset *dnskey,
|
||||
_getdns_rrset *rrset, const uint8_t *name, int *opt_out);
|
||||
|
||||
/* Returns whether a dnskey for keyset signed rrset. */
|
||||
static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
_getdns_rrset *keyset, _getdns_rrset *rrset)
|
||||
static int a_key_signed_rrset(const struct mem_funcs *mf, time_t now,
|
||||
uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset)
|
||||
{
|
||||
_getdns_rrtype_iter dnskey_spc, *dnskey;
|
||||
const uint8_t *nc_name;
|
||||
const uint8_t *nc_name; /* Initialized by dnskey_signed_rrset() */
|
||||
|
||||
int keytag;
|
||||
|
||||
assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
|
||||
|
@ -1783,7 +1876,8 @@ static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
|
|||
* There is no more specific!
|
||||
*/
|
||||
if (rrset->rr_type == GETDNS_RRTYPE_NSEC &&
|
||||
rrset->name[0] == 1 && rrset->name[1] == '*')
|
||||
rrset->name[0] == 1 && rrset->name[1] == '*' &&
|
||||
nc_name == rrset->name)
|
||||
return keytag;
|
||||
|
||||
debug_sec_print_rrset("wildcard expanded to: ", rrset);
|
||||
|
@ -1800,13 +1894,13 @@ static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
|
|||
/* Returns whether a DS in ds_set matches a dnskey in dnskey_set which in turn
|
||||
* signed the dnskey set.
|
||||
*/
|
||||
static int ds_authenticates_keys(struct mem_funcs *mf,
|
||||
static int ds_authenticates_keys(const struct mem_funcs *mf,
|
||||
time_t now, uint32_t skew, _getdns_rrset *ds_set, _getdns_rrset *dnskey_set)
|
||||
{
|
||||
_getdns_rrtype_iter dnskey_spc, *dnskey;
|
||||
_getdns_rrtype_iter ds_spc, *ds;
|
||||
uint16_t keytag;
|
||||
const uint8_t *nc_name;
|
||||
const uint8_t *nc_name; /* Initialized by dnskey_signed_rrset() */
|
||||
size_t valid_dsses = 0, supported_dsses = 0;
|
||||
uint8_t max_supported_digest = 0;
|
||||
int max_supported_result = 0;
|
||||
|
@ -2085,8 +2179,8 @@ static int nsec3_covers_name(
|
|||
}
|
||||
}
|
||||
|
||||
static int find_nsec_covering_name(
|
||||
struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey,
|
||||
static int find_nsec_covering_name(const struct mem_funcs *mf, time_t now,
|
||||
uint32_t skew, _getdns_rrset *dnskey,
|
||||
_getdns_rrset *rrset, const uint8_t *name, int *opt_out)
|
||||
{
|
||||
_getdns_rrset_iter i_spc, *i;
|
||||
|
@ -2110,7 +2204,8 @@ static int find_nsec_covering_name(
|
|||
&& (bitmap = _getdns_rdf_iter_init_at(
|
||||
&bitmap_spc, &nsec_rr->rr_i, 5))
|
||||
|
||||
&& (keytag = a_key_signed_rrset(mf, now, skew, dnskey, n))
|
||||
&& (keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, dnskey, n))
|
||||
&& ( keytag & NSEC3_ITERATION_COUNT_HIGH
|
||||
|
||||
|| ( nsec3_covers_name(n, name, opt_out)
|
||||
|
@ -2174,7 +2269,8 @@ static int find_nsec_covering_name(
|
|||
)
|
||||
)
|
||||
|
||||
&& (keytag = a_key_signed_rrset(mf,now,skew, dnskey, n))) {
|
||||
&& (keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, dnskey, n))) {
|
||||
|
||||
debug_sec_print_rrset("NSEC: ", n);
|
||||
debug_sec_print_dname("covered: ", name);
|
||||
|
@ -2186,7 +2282,7 @@ static int find_nsec_covering_name(
|
|||
}
|
||||
|
||||
static int nsec3_find_next_closer(
|
||||
struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
const struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
_getdns_rrset *dnskey, _getdns_rrset *rrset,
|
||||
const uint8_t *nc_name, int *opt_out)
|
||||
{
|
||||
|
@ -2238,7 +2334,7 @@ static int nsec3_find_next_closer(
|
|||
* verifying key: it returns keytag + NSEC3_ITERATION_COUNT_HIGH (0x20000)
|
||||
*/
|
||||
static int key_proves_nonexistance(
|
||||
struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
const struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
_getdns_rrset *keyset, _getdns_rrset *rrset, int *opt_out)
|
||||
{
|
||||
_getdns_rrset nsec_rrset, *cover, *ce;
|
||||
|
@ -2251,6 +2347,7 @@ static int key_proves_nonexistance(
|
|||
|
||||
assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
|
||||
|
||||
debug_sec_print_rrset("Commencing NX proof for: ", rrset);
|
||||
if (opt_out)
|
||||
*opt_out = 0;
|
||||
|
||||
|
@ -2297,7 +2394,16 @@ static int key_proves_nonexistance(
|
|||
|| bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
|
||||
|
||||
/* And a valid signature please */
|
||||
&& (keytag = a_key_signed_rrset(mf,now,skew,keyset,&nsec_rrset))) {
|
||||
&& (keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, keyset, &nsec_rrset))) {
|
||||
|
||||
/* Flag an insecure delegation via opt_out.
|
||||
* See usage of key_proves_nonexistance() from
|
||||
* chain_node_get_trusted_keys() for explanation.
|
||||
*/
|
||||
if (opt_out && rrset->rr_type == GETDNS_RRTYPE_DS)
|
||||
*opt_out = bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
|
||||
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA);
|
||||
|
||||
debug_sec_print_rrset("NSEC NODATA proof for: ", rrset);
|
||||
return keytag;
|
||||
|
@ -2353,7 +2459,7 @@ static int key_proves_nonexistance(
|
|||
)
|
||||
|
||||
/* And a valid signature please (as always) */
|
||||
|| !(keytag = a_key_signed_rrset(
|
||||
|| !(keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, keyset, cover)))
|
||||
continue;
|
||||
|
||||
|
@ -2437,12 +2543,22 @@ static int key_proves_nonexistance(
|
|||
|| bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
|
||||
|
||||
/* It must have a valid signature */
|
||||
&& (keytag = a_key_signed_rrset(mf, now, skew, keyset, ce))
|
||||
&& (keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, keyset, ce))
|
||||
|
||||
/* The qname must match the NSEC3 */
|
||||
&& ( keytag & NSEC3_ITERATION_COUNT_HIGH
|
||||
|| nsec3_matches_name(ce, rrset->name))) {
|
||||
|
||||
/* Flag an insecure delegation via opt_out.
|
||||
* See usage of key_proves_nonexistance() from
|
||||
* chain_node_get_trusted_keys() for explanation.
|
||||
*/
|
||||
if (opt_out && rrset->rr_type == GETDNS_RRTYPE_DS)
|
||||
*opt_out =
|
||||
bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
|
||||
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA);
|
||||
|
||||
debug_sec_print_rrset("NSEC3 No Data for: ", rrset);
|
||||
return keytag;
|
||||
}
|
||||
|
@ -2493,7 +2609,7 @@ static int key_proves_nonexistance(
|
|||
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA)
|
||||
)
|
||||
|
||||
|| !(keytag = a_key_signed_rrset(
|
||||
|| !(keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, keyset, ce))
|
||||
|| ( !(keytag & NSEC3_ITERATION_COUNT_HIGH)
|
||||
&& !nsec3_matches_name(ce, ce_name)))
|
||||
|
@ -2522,10 +2638,11 @@ static int key_proves_nonexistance(
|
|||
* non-existence of a DS along the path is proofed, and SECURE otherwise.
|
||||
*/
|
||||
static int chain_node_get_trusted_keys(
|
||||
struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
const struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
chain_node *node, _getdns_rrset *ta, _getdns_rrset **keys)
|
||||
{
|
||||
int s, keytag;
|
||||
int opt_out;
|
||||
|
||||
/* Ascend up to the root */
|
||||
if (! node)
|
||||
|
@ -2545,7 +2662,7 @@ static int chain_node_get_trusted_keys(
|
|||
} else if (ta->rr_type == GETDNS_RRTYPE_DNSKEY) {
|
||||
|
||||
/* ta is KSK */
|
||||
if ((keytag = a_key_signed_rrset(
|
||||
if ((keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, ta, &node->dnskey))) {
|
||||
*keys = &node->dnskey;
|
||||
node->dnskey_signer = keytag;
|
||||
|
@ -2556,15 +2673,33 @@ static int chain_node_get_trusted_keys(
|
|||
*keys = ta;
|
||||
return GETDNS_DNSSEC_SECURE;
|
||||
}
|
||||
/* ta is parent's ZSK */
|
||||
/* ta is parent's ZSK proving insecurity below this node? */
|
||||
if ((keytag = key_proves_nonexistance(
|
||||
mf, now, skew, ta, &node->ds, NULL))) {
|
||||
mf, now, skew, ta, &node->ds, &opt_out))) {
|
||||
node->ds_signer = keytag;
|
||||
return GETDNS_DNSSEC_INSECURE;
|
||||
}
|
||||
|
||||
if ((keytag = a_key_signed_rrset(mf,now,skew,ta,&node->ds))) {
|
||||
/* When the proof is in an opt_out span, result will
|
||||
* be INSECURE regardless the purpose of the searched
|
||||
* for key.
|
||||
*
|
||||
* Otherwise, INSECURE only when this is a zonecut.
|
||||
* i.e. a NODATA proof, with the NS bit and no SOA bit.
|
||||
*
|
||||
* key_proves_nonexistance() will set opt_out also for
|
||||
* these conditions.
|
||||
*/
|
||||
if (opt_out)
|
||||
return GETDNS_DNSSEC_INSECURE;
|
||||
|
||||
/* If this is not an insecurity proof,
|
||||
* continue searching one label up.
|
||||
*/
|
||||
|
||||
/* ta is parent's ZSK authenticating DS? */
|
||||
} else if ((keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, ta, &node->ds))) {
|
||||
node->ds_signer = keytag;
|
||||
/* DS should authenticate the DNSKEY rrset now */
|
||||
if ((keytag = ds_authenticates_keys(
|
||||
mf, now, skew, &node->ds, &node->dnskey))) {
|
||||
*keys = &node->dnskey;
|
||||
|
@ -2573,6 +2708,7 @@ static int chain_node_get_trusted_keys(
|
|||
? GETDNS_DNSSEC_INSECURE
|
||||
: GETDNS_DNSSEC_SECURE;
|
||||
}
|
||||
/* DS without DNSKEY rrset == BOGUS */
|
||||
return GETDNS_DNSSEC_BOGUS;
|
||||
}
|
||||
} else
|
||||
|
@ -2590,14 +2726,26 @@ static int chain_node_get_trusted_keys(
|
|||
/* keys is an authenticated dnskey rrset always now (i.e. ZSK) */
|
||||
ta = *keys;
|
||||
/* Back down to the head */
|
||||
/*************************/
|
||||
if ((keytag = key_proves_nonexistance(
|
||||
mf, now, skew, ta, &node->ds, NULL))) {
|
||||
mf, now, skew, ta, &node->ds, &opt_out))) {
|
||||
node->ds_signer = keytag;
|
||||
return GETDNS_DNSSEC_INSECURE;
|
||||
|
||||
/* When the proof is in an opt_out span, result will be
|
||||
* INSECURE regardless the purpose of the searched for key.
|
||||
*
|
||||
* Otherwise, INSECURE only when this is a zonecut.
|
||||
* i.e. a NODATA proof, with the NS bit, but no SOA bit.
|
||||
*
|
||||
* key_proves_nonexistance() will set opt_out also for these
|
||||
* conditions. (NODATA of DS with NS bit and wihout SOA bit)
|
||||
*/
|
||||
return opt_out ? GETDNS_DNSSEC_INSECURE
|
||||
: GETDNS_DNSSEC_SECURE;
|
||||
}
|
||||
if (key_matches_signer(ta, &node->ds)) {
|
||||
|
||||
if ((node->ds_signer = a_key_signed_rrset(
|
||||
if ((node->ds_signer = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, ta, &node->ds))
|
||||
&& (keytag = ds_authenticates_keys(
|
||||
mf, now, skew, &node->ds, &node->dnskey))){
|
||||
|
@ -2633,22 +2781,64 @@ static int chain_node_get_trusted_keys(
|
|||
* For this first a secure keyset is looked up, with which the keyset is
|
||||
* evaluated.
|
||||
*/
|
||||
static int chain_head_validate_with_ta(struct mem_funcs *mf,
|
||||
static int chain_head_validate_with_ta(const struct mem_funcs *mf,
|
||||
time_t now, uint32_t skew, chain_head *head, _getdns_rrset *ta)
|
||||
{
|
||||
_getdns_rrset *keys;
|
||||
int s, keytag, opt_out;
|
||||
|
||||
debug_sec_print_rrset("validating ", &head->rrset);
|
||||
debug_sec_print_rrset("with trust anchor ", ta);
|
||||
_getdns_rrtype_iter nsec_spc, *nsec_rr;
|
||||
_getdns_rdf_iter bitmap_spc, *bitmap;
|
||||
chain_node *parent;
|
||||
|
||||
debug_sec_print_rrset("Validating ", &head->rrset);
|
||||
debug_sec_print_rrset("\twith trust anchor ", ta);
|
||||
|
||||
/* A DS is never at the apex */
|
||||
if ( head->rrset.rr_type == GETDNS_RRTYPE_DS
|
||||
&& head->parent->parent)
|
||||
parent = head->parent->parent;
|
||||
|
||||
/* Only at the apex, a NSEC is signed with a DNSKEY with the same
|
||||
* owner name. All other are signed by the parent domain or higher.
|
||||
* Besides a shortcut, choosing to search for a trusted key from the
|
||||
* parent is essential for NSECs at a delagation point! (which would
|
||||
* otherwise turn out BOGUS).
|
||||
*/
|
||||
else if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC
|
||||
&& head->parent->parent
|
||||
&& (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, &head->rrset))
|
||||
&& (bitmap = _getdns_rdf_iter_init_at(
|
||||
&bitmap_spc, &nsec_rr->rr_i, 1))
|
||||
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
|
||||
parent = head->parent->parent;
|
||||
|
||||
/* NSEC3 is always signed by the parent domain!
|
||||
* ( the ownername of the NSEC3 itself is not in the original zone!
|
||||
* so a search for a trusted key at that name gives either INSECURE
|
||||
* (with opt-out) or BOGUS! )
|
||||
*/
|
||||
else if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC3
|
||||
&& head->parent->parent)
|
||||
parent = head->parent->parent;
|
||||
else
|
||||
parent = head->parent;
|
||||
|
||||
if ((s = chain_node_get_trusted_keys(
|
||||
mf, now, skew, head->parent, ta, &keys)) != GETDNS_DNSSEC_SECURE)
|
||||
mf, now, skew, parent, ta, &keys)) != GETDNS_DNSSEC_SECURE) {
|
||||
debug_sec_print_rrset("Could not get trusted keys "
|
||||
"for validating ", &head->rrset);
|
||||
DEBUG_SEC("\tstatus: %d\n", (int)s);
|
||||
return s;
|
||||
}
|
||||
debug_sec_print_rrset("Validating ", &head->rrset);
|
||||
debug_sec_print_rrset("\twith keys ", keys);
|
||||
|
||||
if (_getdns_rrset_has_rrs(&head->rrset)) {
|
||||
if ((keytag = a_key_signed_rrset(
|
||||
mf, now, skew, keys, &head->rrset))) {
|
||||
DEBUG_SEC("Key %d proved\n", (int)keytag);
|
||||
debug_sec_print_rrset("\tSECURE: ", &head->rrset);
|
||||
head->signer = keytag;
|
||||
return GETDNS_DNSSEC_SECURE;
|
||||
|
||||
|
@ -2657,23 +2847,29 @@ static int chain_head_validate_with_ta(struct mem_funcs *mf,
|
|||
skew, keys, &head->rrset, &opt_out))
|
||||
&& opt_out) {
|
||||
|
||||
DEBUG_SEC("Key %d proved (optout)\n", (int)keytag);
|
||||
debug_sec_print_rrset("\tINSECURE: ", &head->rrset);
|
||||
head->signer = keytag;
|
||||
return GETDNS_DNSSEC_INSECURE;
|
||||
}
|
||||
} else if ((keytag = key_proves_nonexistance(mf, now, skew,
|
||||
keys, &head->rrset, &opt_out))) {
|
||||
DEBUG_SEC("Key %d proved (NX)\n", (int)keytag);
|
||||
debug_sec_print_rrset("\tSECURE: ", &head->rrset);
|
||||
head->signer = keytag;
|
||||
return opt_out || (keytag & NSEC3_ITERATION_COUNT_HIGH)
|
||||
? GETDNS_DNSSEC_INSECURE : GETDNS_DNSSEC_SECURE;
|
||||
}
|
||||
debug_sec_print_rrset("BOGUS: ", &head->rrset);
|
||||
debug_sec_print_rrset("\twith trust anchor: ", ta);
|
||||
return GETDNS_DNSSEC_BOGUS;
|
||||
}
|
||||
|
||||
/* The DNSSEC status of the rrset in head is evaluated by trying the trust
|
||||
* anchors in tas in turn. The best outcome counts.
|
||||
*/
|
||||
static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew,
|
||||
chain_head *head, _getdns_rrset_iter *tas)
|
||||
static int chain_head_validate(const struct mem_funcs *mf, time_t now,
|
||||
uint32_t skew, chain_head *head, _getdns_rrset_iter *tas)
|
||||
{
|
||||
_getdns_rrset_iter *i;
|
||||
_getdns_rrset *ta, dnskey_ta, ds_ta;
|
||||
|
@ -2822,7 +3018,7 @@ static void chain_clear_netreq_dnssec_status(chain_head *chain)
|
|||
* processing each head in turn. The worst outcome is the dnssec status for
|
||||
* the whole.
|
||||
*/
|
||||
static int chain_validate_dnssec(struct mem_funcs *mf,
|
||||
static int chain_validate_dnssec(const struct mem_funcs *mf,
|
||||
time_t now, uint32_t skew, chain_head *chain, _getdns_rrset_iter *tas)
|
||||
{
|
||||
int s = GETDNS_DNSSEC_INDETERMINATE, t;
|
||||
|
@ -2877,9 +3073,6 @@ static size_t count_outstanding_requests(chain_head *head)
|
|||
|
||||
if (!_getdns_netreq_finished(node->ds_req))
|
||||
count++;
|
||||
|
||||
if (!_getdns_netreq_finished(node->soa_req))
|
||||
count++;
|
||||
}
|
||||
return count + count_outstanding_requests(head->next);
|
||||
}
|
||||
|
@ -3161,7 +3354,6 @@ static void check_chain_complete(chain_head *chain)
|
|||
|
||||
} else if (_getdns_bogus(dnsreq)) {
|
||||
_getdns_rrsig_iter rrsig_spc;
|
||||
DEBUG_ANCHOR("Request was bogus!\n");
|
||||
|
||||
if ((head = chain) && (node = _to_the_root(head->parent))
|
||||
/* The root DNSKEY rrset */
|
||||
|
@ -3174,13 +3366,15 @@ static void check_chain_complete(chain_head *chain)
|
|||
&& _getdns_rrsig_iter_init(&rrsig_spc, &node->dnskey)
|
||||
){
|
||||
|
||||
DEBUG_ANCHOR("root DNSKEY set was bogus!\n");
|
||||
_getdns_log( &context->log
|
||||
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_NOTICE
|
||||
, "root DNSKEY set was bogus!\n");
|
||||
if (!dnsreq->waiting_for_ta) {
|
||||
uint64_t now = 0;
|
||||
uint64_t now_ms = 0;
|
||||
|
||||
dnsreq->waiting_for_ta = 1;
|
||||
_getdns_context_equip_with_anchor(
|
||||
context, &now);
|
||||
context, &now_ms);
|
||||
|
||||
if (context->trust_anchors_source
|
||||
== GETDNS_TASRC_XML) {
|
||||
|
@ -3188,9 +3382,19 @@ static void check_chain_complete(chain_head *chain)
|
|||
check_chain_complete(chain);
|
||||
return;
|
||||
}
|
||||
_getdns_start_fetching_ta(
|
||||
context, dnsreq->loop);
|
||||
|
||||
if (context->trust_anchors_source ==
|
||||
GETDNS_TASRC_FAILED
|
||||
&& 0 == _getdns_ms_until_expiry2(
|
||||
context->trust_anchors_backoff_expiry,
|
||||
&now_ms)) {
|
||||
context->trust_anchors_source =
|
||||
GETDNS_TASRC_NONE;
|
||||
}
|
||||
if (context->trust_anchors_source
|
||||
!= GETDNS_TASRC_FAILED) {
|
||||
_getdns_start_fetching_ta(
|
||||
context, dnsreq->loop, &now_ms);
|
||||
}
|
||||
if (dnsreq->waiting_for_ta &&
|
||||
context->trust_anchors_source
|
||||
== GETDNS_TASRC_FETCHING) {
|
||||
|
@ -3345,7 +3549,7 @@ void _getdns_ta_notify_dnsreqs(getdns_context *context)
|
|||
getdns_network_req *netreq, **netreq_p;
|
||||
int r = GETDNS_RETURN_GOOD;
|
||||
|
||||
(void) _getdns_context_prepare_for_resolution(context);
|
||||
(void) _getdns_context_prepare_for_resolution(context);
|
||||
|
||||
*dnsreq_p = dnsreq->ta_notify;
|
||||
for ( netreq_p = dnsreq->netreqs
|
||||
|
@ -3365,37 +3569,7 @@ void _getdns_ta_notify_dnsreqs(getdns_context *context)
|
|||
|
||||
void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq)
|
||||
{
|
||||
chain_head *head = dnsreq->chain, *next;
|
||||
chain_node *node;
|
||||
size_t node_count;
|
||||
|
||||
while (head) {
|
||||
next = head->next;
|
||||
|
||||
for ( node_count = head->node_count, node = head->parent
|
||||
; node_count
|
||||
; node_count--, node = node->parent ) {
|
||||
|
||||
if (!_getdns_netreq_finished(node->dnskey_req)) {
|
||||
_getdns_context_cancel_request(
|
||||
node->dnskey_req->owner);
|
||||
node->dnskey_req = NULL;
|
||||
}
|
||||
|
||||
if (!_getdns_netreq_finished(node->ds_req)) {
|
||||
_getdns_context_cancel_request(
|
||||
node->ds_req->owner);
|
||||
node->ds_req = NULL;
|
||||
}
|
||||
|
||||
if (!_getdns_netreq_finished(node->soa_req)) {
|
||||
_getdns_context_cancel_request(
|
||||
node->soa_req->owner);
|
||||
node->soa_req = NULL;
|
||||
}
|
||||
}
|
||||
head = next;
|
||||
}
|
||||
cancel_requests_for_subdomains_of(dnsreq->chain, (uint8_t *)"\0");
|
||||
dnsreq->request_timed_out = 1;
|
||||
check_chain_complete(dnsreq->chain);
|
||||
}
|
||||
|
@ -3432,10 +3606,6 @@ void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
|
|||
if (node->ds_req)
|
||||
_getdns_context_cancel_request(
|
||||
node->ds_req->owner);
|
||||
|
||||
if (node->soa_req)
|
||||
_getdns_context_cancel_request(
|
||||
node->soa_req->owner);
|
||||
}
|
||||
GETDNS_FREE(head->my_mf, head);
|
||||
head = next;
|
||||
|
@ -3504,7 +3674,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
|
|||
*****************************************************************************/
|
||||
|
||||
|
||||
static int wire_validate_dnssec(struct mem_funcs *mf,
|
||||
static int wire_validate_dnssec(const struct mem_funcs *mf,
|
||||
time_t now, uint32_t skew, uint8_t *to_val, size_t to_val_len,
|
||||
uint8_t *support, size_t support_len, uint8_t *tas, size_t tas_len)
|
||||
{
|
||||
|
@ -3586,9 +3756,9 @@ static int wire_validate_dnssec(struct mem_funcs *mf,
|
|||
*
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_validate_dnssec2(getdns_list *records_to_validate,
|
||||
getdns_list *support_records,
|
||||
getdns_list *trust_anchors,
|
||||
getdns_validate_dnssec2(const getdns_list *records_to_validate,
|
||||
const getdns_list *support_records,
|
||||
const getdns_list *trust_anchors,
|
||||
time_t now, uint32_t skew)
|
||||
{
|
||||
uint8_t to_val_buf[4096], *to_val,
|
||||
|
@ -3600,7 +3770,7 @@ getdns_validate_dnssec2(getdns_list *records_to_validate,
|
|||
tas_len = sizeof(tas_buf);
|
||||
|
||||
int r = GETDNS_RETURN_MEMORY_ERROR;
|
||||
struct mem_funcs *mf;
|
||||
const struct mem_funcs *mf;
|
||||
|
||||
size_t i;
|
||||
getdns_dict *reply;
|
||||
|
@ -3681,9 +3851,9 @@ exit_free_support:
|
|||
|
||||
|
||||
getdns_return_t
|
||||
getdns_validate_dnssec(getdns_list *records_to_validate,
|
||||
getdns_list *support_records,
|
||||
getdns_list *trust_anchors)
|
||||
getdns_validate_dnssec(const getdns_list *records_to_validate,
|
||||
const getdns_list *support_records,
|
||||
const getdns_list *trust_anchors)
|
||||
{
|
||||
return getdns_validate_dnssec2(records_to_validate, support_records,
|
||||
trust_anchors, time(NULL), 0);
|
||||
|
|
|
@ -218,12 +218,14 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
|||
&& !dns_req->avoid_dnssec_roadblocks
|
||||
&& (dns_req->dnssec_return_status ||
|
||||
dns_req->dnssec_return_only_secure ||
|
||||
dns_req->dnssec ||
|
||||
dns_req->dnssec_return_all_statuses
|
||||
))
|
||||
#endif
|
||||
|| ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
||||
&& (dns_req->dnssec_return_status ||
|
||||
dns_req->dnssec_return_only_secure ||
|
||||
dns_req->dnssec ||
|
||||
dns_req->dnssec_return_all_statuses)
|
||||
&& _getdns_bogus(dns_req))
|
||||
)) {
|
||||
|
@ -241,7 +243,6 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
|||
#if defined(REQ_DEBUG) && REQ_DEBUG
|
||||
debug_req("getting validation chain for ", *dns_req->netreqs);
|
||||
#endif
|
||||
DEBUG_ANCHOR("Valchain lookup\n");
|
||||
_getdns_get_validation_chain(dns_req);
|
||||
} else
|
||||
_getdns_call_user_callback(
|
||||
|
@ -250,10 +251,18 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
|||
|
||||
#ifdef HAVE_LIBUNBOUND
|
||||
#ifdef HAVE_UNBOUND_EVENT_API
|
||||
#if UNBOUND_VERSION_MAJOR > 1 || (UNBOUND_VERSION_MAJOR == 1 && UNBOUND_VERSION_MINOR >= 8)
|
||||
static void
|
||||
ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len,
|
||||
int sec, char* why_bogus, int was_ratelimited)
|
||||
{
|
||||
(void) was_ratelimited;
|
||||
#else
|
||||
static void
|
||||
ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len,
|
||||
int sec, char* why_bogus)
|
||||
{
|
||||
#endif
|
||||
getdns_network_req *netreq = (getdns_network_req *) arg;
|
||||
getdns_dns_req *dns_req = netreq->owner;
|
||||
|
||||
|
@ -423,6 +432,7 @@ _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms)
|
|||
if ( context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
||||
|| dns_req->dnssec_return_status
|
||||
|| dns_req->dnssec_return_only_secure
|
||||
|| dns_req->dnssec
|
||||
|| dns_req->dnssec_return_all_statuses
|
||||
|| dns_req->dnssec_return_validation_chain) {
|
||||
#endif
|
||||
|
@ -492,7 +502,7 @@ extformatcmp(const void *a, const void *b)
|
|||
|
||||
/*---------------------------------------- validate_extensions */
|
||||
static getdns_return_t
|
||||
validate_extensions(struct getdns_dict * extensions)
|
||||
validate_extensions(const getdns_dict * extensions)
|
||||
{
|
||||
/**
|
||||
* this is a comprehensive list of extensions and their data types
|
||||
|
@ -503,6 +513,7 @@ validate_extensions(struct getdns_dict * extensions)
|
|||
static getdns_extension_format extformats[] = {
|
||||
{"add_opt_parameters" , t_dict, 1},
|
||||
{"add_warning_for_bad_dns" , t_int , 1},
|
||||
{"dnssec" , t_int , 1},
|
||||
{"dnssec_return_all_statuses" , t_int , 1},
|
||||
{"dnssec_return_full_validation_chain", t_int , 1},
|
||||
{"dnssec_return_only_secure" , t_int , 1},
|
||||
|
@ -555,7 +566,7 @@ validate_extensions(struct getdns_dict * extensions)
|
|||
|
||||
static getdns_return_t
|
||||
getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
|
||||
const char *name, uint16_t request_type, getdns_dict *extensions,
|
||||
const char *name, uint16_t request_type, const getdns_dict *extensions,
|
||||
void *userarg, getdns_network_req **return_netreq_p,
|
||||
getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces)
|
||||
{
|
||||
|
@ -591,13 +602,18 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
|
|||
_getdns_context_track_outbound_request(req);
|
||||
|
||||
if (req->dnssec_extension_set) {
|
||||
if (context->trust_anchors_source == GETDNS_TASRC_FAILED
|
||||
&& _getdns_ms_until_expiry2(
|
||||
context->trust_anchors_backoff_expiry, &now_ms) == 0) {
|
||||
context->trust_anchors_source = GETDNS_TASRC_NONE;
|
||||
}
|
||||
if (context->trust_anchors_source == GETDNS_TASRC_XML_UPDATE)
|
||||
_getdns_start_fetching_ta(context, loop);
|
||||
_getdns_start_fetching_ta(context, loop, &now_ms);
|
||||
|
||||
else if (context->trust_anchors_source == GETDNS_TASRC_NONE) {
|
||||
_getdns_context_equip_with_anchor(context, &now_ms);
|
||||
if (context->trust_anchors_source == GETDNS_TASRC_NONE) {
|
||||
_getdns_start_fetching_ta(context, loop);
|
||||
_getdns_start_fetching_ta(context, loop, &now_ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -697,6 +713,8 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
|
|||
/* clean up the request */
|
||||
_getdns_context_clear_outbound_request(req);
|
||||
_getdns_dns_req_free(req);
|
||||
if (return_netreq_p)
|
||||
*return_netreq_p = NULL;
|
||||
return r;
|
||||
}
|
||||
return GETDNS_RETURN_GOOD;
|
||||
|
@ -704,7 +722,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
|
|||
|
||||
getdns_return_t
|
||||
_getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
|
||||
const char *name, uint16_t request_type, getdns_dict *extensions,
|
||||
const char *name, uint16_t request_type, const getdns_dict *extensions,
|
||||
void *userarg, getdns_network_req **netreq_p,
|
||||
getdns_callback_t callback, internal_cb_t internal_cb)
|
||||
{
|
||||
|
@ -716,33 +734,33 @@ _getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
|
|||
|
||||
getdns_return_t
|
||||
_getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
|
||||
const char *name, getdns_dict *extensions, void *userarg,
|
||||
const char *name, const getdns_dict *extensions, void *userarg,
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callback)
|
||||
{
|
||||
getdns_dict *my_extensions = extensions;
|
||||
getdns_dict *my_extensions = NULL;
|
||||
getdns_return_t r;
|
||||
uint32_t value;
|
||||
getdns_network_req *netreq = NULL;
|
||||
|
||||
if (!my_extensions) {
|
||||
if (!extensions) {
|
||||
if (!(my_extensions=getdns_dict_create_with_context(context)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
} else if (
|
||||
getdns_dict_get_int(my_extensions, "return_both_v4_and_v6", &value)
|
||||
getdns_dict_get_int(extensions, "return_both_v4_and_v6", &value)
|
||||
&& (r = _getdns_dict_copy(extensions, &my_extensions)))
|
||||
return r;
|
||||
|
||||
if (my_extensions != extensions && (r = getdns_dict_set_int(
|
||||
if (my_extensions && (r = getdns_dict_set_int(
|
||||
my_extensions, "return_both_v4_and_v6", GETDNS_EXTENSION_TRUE)))
|
||||
return r;
|
||||
|
||||
r = getdns_general_ns(context, loop,
|
||||
name, GETDNS_RRTYPE_AAAA, my_extensions,
|
||||
name, GETDNS_RRTYPE_AAAA, my_extensions ? my_extensions : extensions,
|
||||
userarg, &netreq, callback, NULL, 1);
|
||||
if (netreq && transaction_id)
|
||||
*transaction_id = netreq->owner->trans_id;
|
||||
|
||||
if (my_extensions != extensions)
|
||||
if (my_extensions)
|
||||
getdns_dict_destroy(my_extensions);
|
||||
|
||||
return r;
|
||||
|
@ -750,7 +768,7 @@ _getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
|
|||
|
||||
getdns_return_t
|
||||
_getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
|
||||
getdns_dict *address, getdns_dict *extensions, void *userarg,
|
||||
const getdns_dict *address, const getdns_dict *extensions, void *userarg,
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callback)
|
||||
{
|
||||
struct getdns_bindata *address_data;
|
||||
|
@ -840,7 +858,7 @@ _getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
|
|||
|
||||
getdns_return_t
|
||||
_getdns_service_loop(getdns_context *context, getdns_eventloop *loop,
|
||||
const char *name, getdns_dict *extensions, void *userarg,
|
||||
const char *name, const getdns_dict *extensions, void *userarg,
|
||||
getdns_transaction_t * transaction_id, getdns_callback_t callback)
|
||||
{
|
||||
getdns_return_t r;
|
||||
|
@ -857,7 +875,7 @@ _getdns_service_loop(getdns_context *context, getdns_eventloop *loop,
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_general(getdns_context *context,
|
||||
const char *name, uint16_t request_type, getdns_dict *extensions,
|
||||
const char *name, uint16_t request_type, const getdns_dict *extensions,
|
||||
void *userarg, getdns_transaction_t * transaction_id,
|
||||
getdns_callback_t callbackfn)
|
||||
{
|
||||
|
@ -879,7 +897,7 @@ getdns_general(getdns_context *context,
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_address(getdns_context *context,
|
||||
const char *name, getdns_dict *extensions, void *userarg,
|
||||
const char *name, const getdns_dict *extensions, void *userarg,
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn)
|
||||
{
|
||||
if (!context) return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
@ -894,7 +912,7 @@ getdns_address(getdns_context *context,
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_hostname(getdns_context *context,
|
||||
getdns_dict *address, getdns_dict *extensions, void *userarg,
|
||||
const getdns_dict *address, const getdns_dict *extensions, void *userarg,
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn)
|
||||
{
|
||||
if (!context) return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
@ -908,7 +926,7 @@ getdns_hostname(getdns_context *context,
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_service(getdns_context *context,
|
||||
const char *name, getdns_dict *extensions, void *userarg,
|
||||
const char *name, const getdns_dict *extensions, void *userarg,
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn)
|
||||
{
|
||||
if (!context) return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
|
|
@ -63,25 +63,25 @@ int _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms);
|
|||
|
||||
getdns_return_t
|
||||
_getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
|
||||
const char *name, uint16_t request_type, getdns_dict *extensions,
|
||||
const char *name, uint16_t request_type, const getdns_dict *extensions,
|
||||
void *userarg, getdns_network_req **netreq_p,
|
||||
getdns_callback_t callbackfn, internal_cb_t internal_cb);
|
||||
|
||||
getdns_return_t
|
||||
_getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
|
||||
const char *name, getdns_dict *extensions,
|
||||
const char *name, const getdns_dict *extensions,
|
||||
void *userarg, getdns_transaction_t *transaction_id,
|
||||
getdns_callback_t callbackfn);
|
||||
|
||||
getdns_return_t
|
||||
_getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
|
||||
getdns_dict *address, getdns_dict *extensions,
|
||||
const getdns_dict *address, const getdns_dict *extensions,
|
||||
void *userarg, getdns_transaction_t *transaction_id,
|
||||
getdns_callback_t callbackfn);
|
||||
|
||||
getdns_return_t
|
||||
_getdns_service_loop(getdns_context *context, getdns_eventloop *loop,
|
||||
const char *name, getdns_dict *extensions,
|
||||
const char *name, const getdns_dict *extensions,
|
||||
void *userarg, getdns_transaction_t *transaction_id,
|
||||
getdns_callback_t callbackfn);
|
||||
|
||||
|
|
|
@ -416,6 +416,7 @@ typedef enum getdns_callback_type_t {
|
|||
#define GETDNS_RRTYPE_CDNSKEY 60
|
||||
#define GETDNS_RRTYPE_OPENPGPKEY 61
|
||||
#define GETDNS_RRTYPE_CSYNC 62
|
||||
#define GETDNS_RRTYPE_ZONEMD 63
|
||||
#define GETDNS_RRTYPE_SPF 99
|
||||
#define GETDNS_RRTYPE_UINFO 100
|
||||
#define GETDNS_RRTYPE_UID 101
|
||||
|
@ -438,6 +439,7 @@ typedef enum getdns_callback_type_t {
|
|||
#define GETDNS_RRTYPE_CAA 257
|
||||
#define GETDNS_RRTYPE_AVC 258
|
||||
#define GETDNS_RRTYPE_DOA 259
|
||||
#define GETDNS_RRTYPE_AMTRELAY 260
|
||||
#define GETDNS_RRTYPE_TA 32768
|
||||
#define GETDNS_RRTYPE_DLV 32769
|
||||
/** @}
|
||||
|
@ -743,7 +745,7 @@ getdns_list *getdns_list_create();
|
|||
* used to create and initialize the list.
|
||||
* @return pointer to an allocated list, NULL if insufficient memory
|
||||
*/
|
||||
getdns_list *getdns_list_create_with_context(getdns_context *context);
|
||||
getdns_list *getdns_list_create_with_context(const getdns_context *context);
|
||||
|
||||
/**
|
||||
* create a new list with no items, creating and initializing it with the
|
||||
|
@ -863,7 +865,7 @@ getdns_dict *getdns_dict_create();
|
|||
* used to create and initialize the dict.
|
||||
* @return pointer to an allocated dict, NULL if insufficient memory
|
||||
*/
|
||||
getdns_dict *getdns_dict_create_with_context(getdns_context *context);
|
||||
getdns_dict *getdns_dict_create_with_context(const getdns_context *context);
|
||||
|
||||
/**
|
||||
* create a new dict with no items, creating and initializing it with the
|
||||
|
@ -1030,9 +1032,9 @@ getdns_return_t
|
|||
getdns_general(getdns_context *context,
|
||||
const char *name,
|
||||
uint16_t request_type,
|
||||
getdns_dict *extensions,
|
||||
const getdns_dict *extensions,
|
||||
void *userarg,
|
||||
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn);
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn);
|
||||
|
||||
/**
|
||||
* retrieve address assigned to a DNS name
|
||||
|
@ -1048,9 +1050,9 @@ getdns_general(getdns_context *context,
|
|||
getdns_return_t
|
||||
getdns_address(getdns_context *context,
|
||||
const char *name,
|
||||
getdns_dict *extensions,
|
||||
const getdns_dict *extensions,
|
||||
void *userarg,
|
||||
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn);
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn);
|
||||
|
||||
/**
|
||||
* retrieve hostname assigned to an IP address
|
||||
|
@ -1065,10 +1067,10 @@ getdns_address(getdns_context *context,
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_hostname(getdns_context *context,
|
||||
getdns_dict *address,
|
||||
getdns_dict *extensions,
|
||||
const getdns_dict *address,
|
||||
const getdns_dict *extensions,
|
||||
void *userarg,
|
||||
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn);
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn);
|
||||
|
||||
/**
|
||||
* retrieve a service assigned to a DNS name
|
||||
|
@ -1084,9 +1086,9 @@ getdns_hostname(getdns_context *context,
|
|||
getdns_return_t
|
||||
getdns_service(getdns_context *context,
|
||||
const char *name,
|
||||
getdns_dict *extensions,
|
||||
const getdns_dict *extensions,
|
||||
void *userarg,
|
||||
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn);
|
||||
getdns_transaction_t *transaction_id, getdns_callback_t callbackfn);
|
||||
/** @}
|
||||
*/
|
||||
|
||||
|
@ -1201,7 +1203,7 @@ getdns_return_t
|
|||
getdns_general_sync(getdns_context *context,
|
||||
const char *name,
|
||||
uint16_t request_type,
|
||||
getdns_dict *extensions,
|
||||
const getdns_dict *extensions,
|
||||
getdns_dict **response);
|
||||
|
||||
/**
|
||||
|
@ -1216,7 +1218,7 @@ getdns_general_sync(getdns_context *context,
|
|||
getdns_return_t
|
||||
getdns_address_sync(getdns_context *context,
|
||||
const char *name,
|
||||
getdns_dict *extensions,
|
||||
const getdns_dict *extensions,
|
||||
getdns_dict **response);
|
||||
|
||||
/**
|
||||
|
@ -1230,8 +1232,8 @@ getdns_address_sync(getdns_context *context,
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_hostname_sync(getdns_context *context,
|
||||
getdns_dict *address,
|
||||
getdns_dict *extensions,
|
||||
const getdns_dict *address,
|
||||
const getdns_dict *extensions,
|
||||
getdns_dict **response);
|
||||
|
||||
/**
|
||||
|
@ -1246,7 +1248,7 @@ getdns_hostname_sync(getdns_context *context,
|
|||
getdns_return_t
|
||||
getdns_service_sync(getdns_context *context,
|
||||
const char *name,
|
||||
getdns_dict *extensions,
|
||||
const getdns_dict *extensions,
|
||||
getdns_dict **response);
|
||||
|
||||
/** @}
|
||||
|
@ -1341,9 +1343,8 @@ char *getdns_convert_alabel_to_ulabel(const char *alabel);
|
|||
* depending on the validation status.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_validate_dnssec(getdns_list *to_validate,
|
||||
getdns_list *support_records,
|
||||
getdns_list *trust_anchors);
|
||||
getdns_validate_dnssec(const getdns_list *to_validate,
|
||||
const getdns_list *support_records, const getdns_list *trust_anchors);
|
||||
|
||||
/**
|
||||
* Get the default list of trust anchor records that is used by the library
|
||||
|
@ -1392,7 +1393,7 @@ char *getdns_display_ip_address(const getdns_bindata
|
|||
* @param value The callback function that will be called when any context is
|
||||
* changed. A update callback function can be deregistered by
|
||||
* passing NULL.
|
||||
* @return GETDNS_RETURN_GOOD when succesful.
|
||||
* @return GETDNS_RETURN_GOOD when successful.
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
|
@ -1444,7 +1445,7 @@ getdns_context_set_resolution_type(getdns_context *context,
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_namespaces(getdns_context *context,
|
||||
size_t namespace_count, getdns_namespace_t *namespaces);
|
||||
size_t namespace_count, const getdns_namespace_t *namespaces);
|
||||
|
||||
/**
|
||||
* Specifies what transport are used for DNS lookups. The default is
|
||||
|
@ -1812,9 +1813,11 @@ getdns_context_set_extended_memory_functions(getdns_context *context,
|
|||
* GETDNS_RESOLUTION_STUB.
|
||||
* - all_context (a dict) with names for all the other settings in
|
||||
* context.
|
||||
* The application is responsible for cleaning up the returned dictionary
|
||||
* object with getdns_dict_destroy.
|
||||
*/
|
||||
getdns_dict*
|
||||
getdns_context_get_api_information(getdns_context* context);
|
||||
getdns_context_get_api_information(const getdns_context *context);
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
|
|
@ -100,6 +100,17 @@ extern "C" {
|
|||
#define GETDNS_CONTEXT_CODE_TLS_CA_FILE_TEXT "Change related to getdns_context_set_tls_ca_file"
|
||||
#define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST 633
|
||||
#define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT "Change related to getdns_context_set_tls_cipher_list"
|
||||
#define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST 634
|
||||
#define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT "Change related to getdns_context_set_tls_curves_list"
|
||||
#define GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES 635
|
||||
#define GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES_TEXT "Change related to getdns_context_set_tls_ciphersuites"
|
||||
#define GETDNS_CONTEXT_CODE_TLS_MIN_VERSION 636
|
||||
#define GETDNS_CONTEXT_CODE_TLS_MIN_VERSION_TEXT "Change related to getdns_context_set_tls_min_version"
|
||||
#define GETDNS_CONTEXT_CODE_TLS_MAX_VERSION 637
|
||||
#define GETDNS_CONTEXT_CODE_TLS_MAX_VERSION_TEXT "Change related to getdns_context_set_tls_max_version"
|
||||
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME 638
|
||||
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_trust_anchors_backoff_time"
|
||||
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
@ -350,7 +361,7 @@ struct getdns_eventloop_vmt {
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or eventloop were NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_eventloop(getdns_context* context,
|
||||
getdns_context_set_eventloop(getdns_context *context,
|
||||
getdns_eventloop *eventloop);
|
||||
|
||||
/**
|
||||
|
@ -366,7 +377,7 @@ getdns_context_set_eventloop(getdns_context* context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or evenloop were NULL
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_eventloop(getdns_context* context,
|
||||
getdns_context_get_eventloop(const getdns_context *context,
|
||||
getdns_eventloop **eventloop);
|
||||
|
||||
/**
|
||||
|
@ -546,8 +557,18 @@ typedef enum getdns_loglevel_type {
|
|||
#define GETDNS_LOG_INFO_TEXT "Informational message"
|
||||
#define GETDNS_LOG_DEBUG_TEXT "Debug-level message"
|
||||
|
||||
#define GETDNS_LOG_UPSTREAM_STATS 4096
|
||||
#define GETDNS_LOG_UPSTREAM_STATS 0x3000
|
||||
#define GETDNS_LOG_UPSTREAM_STATS_TEXT "Log messages about upstream statistics"
|
||||
#define GETDNS_LOG_SYS_STUB 0x2000
|
||||
#define GETDNS_LOG_SYS_STUB_TEXT "Log messages about stub resolving"
|
||||
#define GETDNS_LOG_SYS_RECURSING 0x4000
|
||||
#define GETDNS_LOG_SYS_RECURSING_TEXT "Log messages about recursive resolving"
|
||||
#define GETDNS_LOG_SYS_RESOLVING 0x6000
|
||||
#define GETDNS_LOG_SYS_RESOLVING_TEXT "Log messages about resolving"
|
||||
#define GETDNS_LOG_SYS_ANCHOR 0x8000
|
||||
#define GETDNS_LOG_SYS_ANCHOR_TEXT "Log messages about fetching trust anchors"
|
||||
|
||||
|
||||
|
||||
typedef void (*getdns_logfunc_type) (void *userarg, uint64_t log_systems,
|
||||
getdns_loglevel_type, const char *, va_list ap);
|
||||
|
@ -589,7 +610,7 @@ getdns_context_set_logfunc(getdns_context *context, void *userarg,
|
|||
* to be created if it does not exist. When NULL is
|
||||
* given, the default location is used which is
|
||||
* ${HOME}/.getdns/ on Unix line systems (Linux, BSD's,
|
||||
* MacOS), and %AppData%\getnds\ on Windows.
|
||||
* MacOS), and %AppData%\getdns\ on Windows.
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
|
@ -692,13 +713,29 @@ getdns_return_t
|
|||
getdns_context_set_trust_anchors_verify_email(
|
||||
getdns_context *context, const char *verify_email);
|
||||
|
||||
/**
|
||||
* Configure the amount of milliseconds the trust anchors should not be tried
|
||||
* to be fetched after failure. Default is 2500 which is two and a half seconds.
|
||||
* Setting the trust anchors backoff time will cause fetching to be retried
|
||||
* immediatly.
|
||||
* @see getdns_context_get_trust_anchors_backoff_time
|
||||
* @param context The context to configure
|
||||
* @param value Number of milliseconds before fetch trust anchors
|
||||
* will be retried.
|
||||
* @return GETDNS_RETURN_GOOD on success
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_trust_anchors_backoff_time(
|
||||
getdns_context *context, uint64_t value);
|
||||
|
||||
/**
|
||||
* Initialized the context's upstream recursive servers and suffixes
|
||||
* with the values from the given resolv.conf file.
|
||||
* @see getdns_context_get_resolvconf
|
||||
* @see getdns_context_set_hosts
|
||||
* @param[in] context The context to configure
|
||||
* @param[in] resolvonf Defaults to /etc/resolv.conf
|
||||
* @param[in] resolvconf Defaults to /etc/resolv.conf
|
||||
* @return GETDNS_RETURN_GOOD when successful and error code otherwise.
|
||||
*/
|
||||
getdns_return_t
|
||||
|
@ -753,6 +790,105 @@ getdns_return_t
|
|||
getdns_context_set_tls_cipher_list(
|
||||
getdns_context *context, const char *cipher_list);
|
||||
|
||||
/**
|
||||
* Configure the available TLS1.3 ciphersuites for authenticated TLS upstreams.
|
||||
* @see getdns_context_get_tls_ciphersuites
|
||||
* @param[in] context The context to configure
|
||||
* @param[in] ciphersuites The cipher list
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_ciphersuites(
|
||||
getdns_context *context, const char *ciphersuites);
|
||||
|
||||
/**
|
||||
* Sets the supported curves TLS upstreams.
|
||||
* @see getdns_context_get_tls_curves_list
|
||||
* @param[in] context The context to configure
|
||||
* @param[in] curves_list The string is a colon separated list of curve
|
||||
* NIDs or names, for example "P-521:P-384:P-256".
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_curves_list(
|
||||
getdns_context *context, const char *curves_list);
|
||||
|
||||
typedef enum getdns_tls_version_t {
|
||||
GETDNS_SSL3 = 1400,
|
||||
GETDNS_TLS1 = 1401,
|
||||
GETDNS_TLS1_1 = 1402,
|
||||
GETDNS_TLS1_2 = 1403,
|
||||
GETDNS_TLS1_3 = 1404
|
||||
} getdns_tls_version_t;
|
||||
|
||||
#define GETDNS_SSL3_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
|
||||
#define GETDNS_TLS1_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
|
||||
#define GETDNS_TLS1_1_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
|
||||
#define GETDNS_TLS1_2_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
|
||||
#define GETDNS_TLS1_3_TEXT "See getdns_context_(set|get)_tls_(min|max)_version()"
|
||||
|
||||
/**
|
||||
* Configure context for minimum supported TLS version.
|
||||
* @see getdns_context_set_tls_max_version
|
||||
* @see getdns_context_get_tls_min_version
|
||||
* @param context The context to configure
|
||||
* @param min_version is one of GETDNS_SSL3, GETDNS_TLS1, GETDNS_TLS1_1,
|
||||
* GETDNS_TLS1_2, GETDNS_TLS1_3
|
||||
* @return GETDNS_RETURN_GOOD on success
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null or value has an
|
||||
* invalid value.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_min_version(
|
||||
getdns_context *context, getdns_tls_version_t min_version);
|
||||
|
||||
/**
|
||||
* Get configured minimum supported TLS version.
|
||||
* @see getdns_context_get_tls_max_version
|
||||
* @see getdns_context_set_tls_min_version
|
||||
* @param context The context to configure
|
||||
* @param min_version is one of GETDNS_SSL3, GETDNS_TLS1, GETDNS_TLS1_1,
|
||||
* GETDNS_TLS1_2, GETDNS_TLS1_3
|
||||
* @return GETDNS_RETURN_GOOD on success
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null or value has an
|
||||
* invalid value.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_min_version(
|
||||
const getdns_context *context, getdns_tls_version_t *min_version);
|
||||
|
||||
/**
|
||||
* Configure context for maximum supported TLS version.
|
||||
* @see getdns_context_set_tls_min_version
|
||||
* @see getdns_context_get_tls_max_version
|
||||
* @param context The context to configure
|
||||
* @param max_version is one of GETDNS_SSL3, GETDNS_TLS1, GETDNS_TLS1_1,
|
||||
* GETDNS_TLS1_2, GETDNS_TLS1_3
|
||||
* @return GETDNS_RETURN_GOOD on success
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null or value has an
|
||||
* invalid value.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_max_version(
|
||||
getdns_context *context, getdns_tls_version_t max_version);
|
||||
|
||||
/**
|
||||
* Get configured maximum supported TLS version.
|
||||
* @see getdns_context_get_tls_min_version
|
||||
* @see getdns_context_set_tls_max_version
|
||||
* @param context The context to configure
|
||||
* @param max_version is one of GETDNS_SSL3, GETDNS_TLS1, GETDNS_TLS1_1,
|
||||
* GETDNS_TLS1_2, GETDNS_TLS1_3
|
||||
* @return GETDNS_RETURN_GOOD on success
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null or value has an
|
||||
* invalid value.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_max_version(
|
||||
const getdns_context *context, getdns_tls_version_t *max_version);
|
||||
|
||||
/**
|
||||
* Get the current resolution type setting from this context.
|
||||
* @see getdns_context_set_resolution_type
|
||||
|
@ -764,8 +900,8 @@ getdns_context_set_tls_cipher_list(
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_resolution_type(getdns_context *context,
|
||||
getdns_resolution_t* value);
|
||||
getdns_context_get_resolution_type(const getdns_context *context,
|
||||
getdns_resolution_t *value);
|
||||
|
||||
/**
|
||||
* Get a copy of the namespaces list setting from this context.
|
||||
|
@ -779,8 +915,8 @@ getdns_context_get_resolution_type(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_namespaces(getdns_context *context,
|
||||
size_t* namespace_count, getdns_namespace_t **namespaces);
|
||||
getdns_context_get_namespaces(const getdns_context *context,
|
||||
size_t *namespace_count, getdns_namespace_t **namespaces);
|
||||
|
||||
/**
|
||||
* Get what transports are used for DNS lookups.
|
||||
|
@ -793,8 +929,8 @@ getdns_context_get_namespaces(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_dns_transport(getdns_context *context,
|
||||
getdns_transport_t* value);
|
||||
getdns_context_get_dns_transport(const getdns_context *context,
|
||||
getdns_transport_t *value);
|
||||
|
||||
/**
|
||||
* Get a copy of the transports list setting from this context.
|
||||
|
@ -809,20 +945,20 @@ getdns_context_get_dns_transport(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when any of the arguments was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_dns_transport_list(getdns_context *context,
|
||||
size_t* transport_count, getdns_transport_list_t **transports);
|
||||
getdns_context_get_dns_transport_list(const getdns_context *context,
|
||||
size_t *transport_count, getdns_transport_list_t **transports);
|
||||
|
||||
/**
|
||||
* Get the current limit for oustanding queries setting from this context.
|
||||
* Get the current limit for outstanding queries setting from this context.
|
||||
* @see getdns_context_set_limit_outstanding_queries
|
||||
* @param[in] context The context from which to get the setting
|
||||
* @param[out] limit The current limit for oustanding queries
|
||||
* @param[out] limit The current limit for outstanding queries
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or limit was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_limit_outstanding_queries(getdns_context *context,
|
||||
uint16_t* limit);
|
||||
getdns_context_get_limit_outstanding_queries(const getdns_context *context,
|
||||
uint16_t *limit);
|
||||
|
||||
/**
|
||||
* Get the current number of milliseconds the API will wait for request
|
||||
|
@ -835,7 +971,7 @@ getdns_context_get_limit_outstanding_queries(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or limit was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_timeout(getdns_context *context, uint64_t* timeout);
|
||||
getdns_context_get_timeout(const getdns_context *context, uint64_t *timeout);
|
||||
|
||||
/**
|
||||
* Get the current number of milliseconds the API will leave an idle TCP or TLS
|
||||
|
@ -849,7 +985,8 @@ getdns_context_get_timeout(getdns_context *context, uint64_t* timeout);
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or timeout was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_idle_timeout(getdns_context *context, uint64_t* timeout);
|
||||
getdns_context_get_idle_timeout(
|
||||
const getdns_context *context, uint64_t *timeout);
|
||||
|
||||
/**
|
||||
* Get the setting that says whether or not DNS queries follow redirects.
|
||||
|
@ -861,8 +998,8 @@ getdns_context_get_idle_timeout(getdns_context *context, uint64_t* timeout);
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_follow_redirects(getdns_context *context,
|
||||
getdns_redirects_t* value);
|
||||
getdns_context_get_follow_redirects(const getdns_context *context,
|
||||
getdns_redirects_t *value);
|
||||
|
||||
/**
|
||||
* Get a copy of the list of addresses in use for looking up top-level domains
|
||||
|
@ -879,7 +1016,7 @@ getdns_context_get_follow_redirects(getdns_context *context,
|
|||
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_dns_root_servers(getdns_context *context,
|
||||
getdns_context_get_dns_root_servers(const getdns_context *context,
|
||||
getdns_list **addresses);
|
||||
|
||||
/**
|
||||
|
@ -897,8 +1034,8 @@ getdns_context_get_dns_root_servers(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_append_name(getdns_context *context,
|
||||
getdns_append_name_t* value);
|
||||
getdns_context_get_append_name(const getdns_context *context,
|
||||
getdns_append_name_t *value);
|
||||
|
||||
/**
|
||||
* Get a copy of the list of suffixes to be appended based on the value off the
|
||||
|
@ -914,7 +1051,7 @@ getdns_context_get_append_name(getdns_context *context,
|
|||
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_suffix(getdns_context *context, getdns_list **value);
|
||||
getdns_context_get_suffix(const getdns_context *context, getdns_list **value);
|
||||
|
||||
/**
|
||||
* Get a copy of the list of DNSSEC trust anchors in use by context.
|
||||
|
@ -929,7 +1066,7 @@ getdns_context_get_suffix(getdns_context *context, getdns_list **value);
|
|||
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_dnssec_trust_anchors(getdns_context *context,
|
||||
getdns_context_get_dnssec_trust_anchors(const getdns_context *context,
|
||||
getdns_list **value);
|
||||
|
||||
/**
|
||||
|
@ -943,8 +1080,8 @@ getdns_context_get_dnssec_trust_anchors(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_dnssec_allowed_skew(getdns_context *context,
|
||||
uint32_t* value);
|
||||
getdns_context_get_dnssec_allowed_skew(const getdns_context *context,
|
||||
uint32_t *value);
|
||||
|
||||
/**
|
||||
* Get a copy of the list of upstream that will be targeted in stub resolution
|
||||
|
@ -960,7 +1097,7 @@ getdns_context_get_dnssec_allowed_skew(getdns_context *context,
|
|||
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_upstream_recursive_servers(getdns_context *context,
|
||||
getdns_context_get_upstream_recursive_servers(const getdns_context *context,
|
||||
getdns_list **upstream_list);
|
||||
|
||||
/**
|
||||
|
@ -975,8 +1112,8 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_edns_maximum_udp_payload_size(getdns_context *context,
|
||||
uint16_t* value);
|
||||
getdns_context_get_edns_maximum_udp_payload_size(const getdns_context *context,
|
||||
uint16_t *value);
|
||||
|
||||
/**
|
||||
* Get the rcode advertised in an EDNS0 OPT record setting from context
|
||||
|
@ -987,8 +1124,8 @@ getdns_context_get_edns_maximum_udp_payload_size(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_edns_extended_rcode(getdns_context *context,
|
||||
uint8_t* value);
|
||||
getdns_context_get_edns_extended_rcode(const getdns_context *context,
|
||||
uint8_t *value);
|
||||
|
||||
/**
|
||||
* Get the version advertised in an EDNS0 OPT record setting from context
|
||||
|
@ -999,7 +1136,7 @@ getdns_context_get_edns_extended_rcode(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_edns_version(getdns_context *context, uint8_t* value);
|
||||
getdns_context_get_edns_version(const getdns_context *context, uint8_t *value);
|
||||
|
||||
/**
|
||||
* Get the DO bit advertised in an EDNS0 OPT record setting from context
|
||||
|
@ -1011,7 +1148,7 @@ getdns_context_get_edns_version(getdns_context *context, uint8_t* value);
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value);
|
||||
getdns_context_get_edns_do_bit(const getdns_context *context, uint8_t *value);
|
||||
|
||||
/**
|
||||
* Get whether queries with this context will have the EDNS Client Subnet
|
||||
|
@ -1024,7 +1161,8 @@ getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value);
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t* value);
|
||||
getdns_context_get_edns_client_subnet_private(const getdns_context *context,
|
||||
uint8_t *value);
|
||||
|
||||
/**
|
||||
* Get the blocksize that will be used to pad outgoing queries over TLS.
|
||||
|
@ -1036,10 +1174,11 @@ getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t*
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t* value);
|
||||
getdns_context_get_tls_query_padding_blocksize(
|
||||
const getdns_context *context, uint16_t *value);
|
||||
|
||||
/**
|
||||
* Get whether the upstream needs to be authenticated whith DNS over TLS.
|
||||
* Get whether the upstream needs to be authenticated with DNS over TLS.
|
||||
* @see getdns_context_set_tls_authentication
|
||||
* @see authvaulesandtext
|
||||
* @param[in] context The context from which to get the setting
|
||||
|
@ -1054,21 +1193,21 @@ getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_authentication(getdns_context *context,
|
||||
getdns_tls_authentication_t* value);
|
||||
getdns_context_get_tls_authentication(const getdns_context *context,
|
||||
getdns_tls_authentication_t *value);
|
||||
|
||||
/**
|
||||
* Get whether the context is configured to round robin queries over the available
|
||||
* upstreams.
|
||||
* @see getdns_context_get_round_robin_upstreams
|
||||
* @see getdns_context_set_round_robin_upstreams
|
||||
* @param[in] context The context from which to get the setting
|
||||
* @param[out] value 1 if the setting is on, 0 otherwise
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_round_robin_upstreams(getdns_context *context,
|
||||
uint8_t* value);
|
||||
getdns_context_get_round_robin_upstreams(const getdns_context *context,
|
||||
uint8_t *value);
|
||||
|
||||
/**
|
||||
* Get the amount of seconds a TLS connection should not be tried with
|
||||
|
@ -1082,8 +1221,8 @@ getdns_context_get_round_robin_upstreams(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_backoff_time(getdns_context *context,
|
||||
uint16_t* value);
|
||||
getdns_context_get_tls_backoff_time(const getdns_context *context,
|
||||
uint16_t *value);
|
||||
|
||||
/**
|
||||
* Get the number of times getdns retries to setup DNS over TLS with a
|
||||
|
@ -1097,8 +1236,8 @@ getdns_context_get_tls_backoff_time(getdns_context *context,
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context or value was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_connection_retries(getdns_context *context,
|
||||
uint16_t* value);
|
||||
getdns_context_get_tls_connection_retries(const getdns_context *context,
|
||||
uint16_t *value);
|
||||
|
||||
/**
|
||||
* Get the currently registered callback function and user defined argument
|
||||
|
@ -1115,7 +1254,8 @@ getdns_context_get_tls_connection_retries(getdns_context *context,
|
|||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_update_callback(getdns_context *context, void **userarg,
|
||||
getdns_context_get_update_callback(const getdns_context *context,
|
||||
void **userarg,
|
||||
void (**value) (getdns_context *, getdns_context_code_t, void *));
|
||||
|
||||
|
||||
|
@ -1169,7 +1309,7 @@ getdns_context_get_update_callback(getdns_context *context, void **userarg,
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_trust_anchors_url(
|
||||
getdns_context *context, const char **url);
|
||||
const getdns_context *context, const char **url);
|
||||
|
||||
/**
|
||||
* Gets the public certificate for the Certificate Authority with which to
|
||||
|
@ -1188,7 +1328,7 @@ getdns_context_get_trust_anchors_url(
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_trust_anchors_verify_CA(
|
||||
getdns_context *context, const char **verify_CA);
|
||||
const getdns_context *context, const char **verify_CA);
|
||||
|
||||
/**
|
||||
* Gets the email address for the Subject of the signer's certificate from the
|
||||
|
@ -1205,7 +1345,21 @@ getdns_context_get_trust_anchors_verify_CA(
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_trust_anchors_verify_email(
|
||||
getdns_context *context, const char **verify_email);
|
||||
const getdns_context *context, const char **verify_email);
|
||||
|
||||
/**
|
||||
* Get the amount of milliseconds the trust anchors will not be tried to be
|
||||
* fetched after failure.
|
||||
* @see getdns_context_set_trust_anchors_backoff_time
|
||||
* @param context The context to configure
|
||||
* @param value Number of milliseconds before fetch trust anchors
|
||||
* will be retried.
|
||||
* @return GETDNS_RETURN_GOOD on success
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if context is null.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_trust_anchors_backoff_time(
|
||||
const getdns_context *context, uint64_t *value);
|
||||
|
||||
/**
|
||||
* Get the value with which the context's upstream recursive servers
|
||||
|
@ -1213,12 +1367,13 @@ getdns_context_get_trust_anchors_verify_email(
|
|||
* @see getdns_context_set_resolvconf
|
||||
* @see getdns_context_get_hosts
|
||||
* @param[in] context The context to configure
|
||||
* @param[out] resolvonf NULL if the context was not initialized with a
|
||||
* @param[out] resolvconf NULL if the context was not initialized with a
|
||||
* resolv.conf file.
|
||||
* @return GETDNS_RETURN_GOOD when successful and error code otherwise.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_resolvconf(getdns_context *context, const char **resolvconf);
|
||||
getdns_context_get_resolvconf(
|
||||
const getdns_context *context, const char **resolvconf);
|
||||
|
||||
/**
|
||||
* Get the value with which the context's GETDNS_NAMESPACE_LOCALNAMES namespace
|
||||
|
@ -1231,7 +1386,8 @@ getdns_context_get_resolvconf(getdns_context *context, const char **resolvconf);
|
|||
* @return GETDNS_RETURN_GOOD when successful and error code otherwise.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_hosts(getdns_context *context, const char **hosts);
|
||||
getdns_context_get_hosts(
|
||||
const getdns_context *context, const char **hosts);
|
||||
|
||||
/**
|
||||
* Get the location of the directory for CA certificates for verification
|
||||
|
@ -1245,7 +1401,8 @@ getdns_context_get_hosts(getdns_context *context, const char **hosts);
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_ca_path(getdns_context *context, const char **tls_ca_path);
|
||||
getdns_context_get_tls_ca_path(
|
||||
const getdns_context *context, const char **tls_ca_path);
|
||||
|
||||
/**
|
||||
* Get the file location with CA certificates for verification purposes.
|
||||
|
@ -1258,7 +1415,8 @@ getdns_context_get_tls_ca_path(getdns_context *context, const char **tls_ca_path
|
|||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_ca_file(getdns_context *context, const char **tls_ca_file);
|
||||
getdns_context_get_tls_ca_file(
|
||||
const getdns_context *context, const char **tls_ca_file);
|
||||
|
||||
/**
|
||||
* Get the list of available ciphers for authenticated TLS upstreams.
|
||||
|
@ -1270,8 +1428,35 @@ getdns_context_get_tls_ca_file(getdns_context *context, const char **tls_ca_file
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_cipher_list(
|
||||
getdns_context *context, const char **cipher_list);
|
||||
const getdns_context *context, const char **cipher_list);
|
||||
|
||||
/**
|
||||
* Get the configured available TLS1.3 ciphersuited for authenticated TLS
|
||||
* upstreams.
|
||||
* @see getdns_context_set_tls_ciphersuites
|
||||
* @param[in] context The context configure
|
||||
* @param[out] ciphersuites The cipher list
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_ciphersuites(
|
||||
const getdns_context *context, const char **ciphersuites);
|
||||
|
||||
/**
|
||||
* Get the supported curves list if one has been set earlier.
|
||||
* @see getdns_context_set_tls_curves_list
|
||||
* @param[in] context The configured context
|
||||
* @param[out] curves_list The string is a colon separated list of curve
|
||||
* NIDs or names, for example "P-521:P-384:P-256",
|
||||
* when one has been configured on the context,
|
||||
* or NULL when none has been set before.
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_curves_list(
|
||||
const getdns_context *context, const char **curves_list);
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
@ -1328,7 +1513,7 @@ uint32_t getdns_get_api_version_number(void);
|
|||
|
||||
/**
|
||||
* Returns a text describing the getdns error code, or NULL when the error
|
||||
* code is unkown.
|
||||
* code is unknown.
|
||||
* @param err The error code for which to return the describing text
|
||||
* @return The describing text for the error code. The string is in library
|
||||
* space and the caller must *not* free this.
|
||||
|
@ -1359,7 +1544,8 @@ const char *getdns_get_errorstr_by_id(uint16_t err);
|
|||
* @return GETDNS_RETURN_MEMORY_ERROR when the copy could not be allocated
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value);
|
||||
getdns_dict_util_set_string(
|
||||
getdns_dict *dict, const char *name, const char *value);
|
||||
|
||||
/**
|
||||
* Get the string associated with the speicifed name. The string should not
|
||||
|
@ -1372,7 +1558,8 @@ getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value);
|
|||
* @return GETDNS_RETURN_NO_SUCH_DICT_NAME if dict is invalid or name does not exist
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result);
|
||||
getdns_dict_util_get_string(
|
||||
const getdns_dict * dict, const char *name, char **result);
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
@ -1413,9 +1600,9 @@ getdns_dict_util_get_string(getdns_dict * dict, char *name, char **result);
|
|||
* return code.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_validate_dnssec2(getdns_list *to_validate,
|
||||
getdns_list *support_records,
|
||||
getdns_list *trust_anchors,
|
||||
getdns_validate_dnssec2(const getdns_list *to_validate,
|
||||
const getdns_list *support_records,
|
||||
const getdns_list *trust_anchors,
|
||||
time_t validation_time, uint32_t skew);
|
||||
|
||||
|
||||
|
@ -1458,9 +1645,9 @@ getdns_validate_dnssec2(getdns_list *to_validate,
|
|||
* @param str the pinning string to parse
|
||||
* @return a dict created from ctx, or NULL if the string did not match.
|
||||
*/
|
||||
getdns_dict* getdns_pubkey_pin_create_from_string(
|
||||
getdns_context* context,
|
||||
const char* str);
|
||||
getdns_dict *getdns_pubkey_pin_create_from_string(
|
||||
const getdns_context *context,
|
||||
const char *str);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1477,8 +1664,8 @@ getdns_dict* getdns_pubkey_pin_create_from_string(
|
|||
* @return GETDNS_RETURN_GOOD if the pinset passes the sanity check.
|
||||
*/
|
||||
getdns_return_t getdns_pubkey_pinset_sanity_check(
|
||||
const getdns_list* pinset,
|
||||
getdns_list* errorlist);
|
||||
const getdns_list *pinset,
|
||||
getdns_list *errorlist);
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
@ -1685,7 +1872,7 @@ getdns_rr_dict2wire_buf(
|
|||
* the buffer and point right after the just written RR.
|
||||
* @param wire_sz On input the size of the wire buffer,
|
||||
* On output the amount of wireformat needed for the
|
||||
* wireformat will have been substracted from wire_sz.
|
||||
* wireformat will have been subtracted from wire_sz.
|
||||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
* GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
|
||||
* small. The function will pretend that it had written beyond the end
|
||||
|
@ -1777,7 +1964,7 @@ getdns_rr_dict2str_buf(
|
|||
* the buffer and point right after the just written RR.
|
||||
* @param str_len On input the size of the str buffer,
|
||||
* On output the number of characters needed for the
|
||||
* string will have been substracted from strlen.
|
||||
* string will have been subtracted from strlen.
|
||||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
* GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
|
||||
* small. The function will pretend that it had written beyond the end
|
||||
|
@ -1856,7 +2043,7 @@ getdns_msg_dict2wire_buf(
|
|||
* the buffer and point right after the just written RR.
|
||||
* @param wire_sz On input the size of the wire buffer,
|
||||
* On output the amount of wireformat needed for the
|
||||
* wireformat will have been substracted from wire_sz.
|
||||
* wireformat will have been subtracted from wire_sz.
|
||||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
* GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
|
||||
* small. The function will pretend that it had written beyond the end
|
||||
|
@ -1948,7 +2135,7 @@ getdns_msg_dict2str_buf(
|
|||
* the buffer and point right after the just written RR.
|
||||
* @param str_len On input the size of the str buffer,
|
||||
* On output the number of characters needed for the
|
||||
* string will have been substracted from strlen.
|
||||
* string will have been subtracted from strlen.
|
||||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
* GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
|
||||
* small. The function will pretend that it had written beyond the end
|
||||
|
@ -2100,7 +2287,7 @@ typedef void (*getdns_request_handler_t)(
|
|||
* On failure, the current set of listening addresses is left in place.
|
||||
* Also, if there is overlap in listening_addresses between the active set
|
||||
* and the newly given set, the ones in the active set will remain in their
|
||||
* current condition and will not be closed and reopened, also all assoicated
|
||||
* current condition and will not be closed and reopened, also all associated
|
||||
* DNS transactions will remain.
|
||||
*/
|
||||
getdns_return_t
|
||||
|
@ -2126,7 +2313,7 @@ getdns_context_set_listen_addresses(
|
|||
*/
|
||||
getdns_return_t
|
||||
getdns_reply(getdns_context *context,
|
||||
getdns_dict *reply, getdns_transaction_t request_id);
|
||||
const getdns_dict *reply, getdns_transaction_t request_id);
|
||||
|
||||
|
||||
/** @}
|
||||
|
@ -2150,7 +2337,7 @@ getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen);
|
|||
* WARNING! Do not use this function. This function will be removed in
|
||||
* future versions of getdns.
|
||||
*/
|
||||
getdns_return_t getdns_context_process_async(getdns_context* context);
|
||||
getdns_return_t getdns_context_process_async(getdns_context *context);
|
||||
|
||||
/**
|
||||
* Return the number of pending requests and the point of time of the next
|
||||
|
@ -2158,8 +2345,8 @@ getdns_return_t getdns_context_process_async(getdns_context* context);
|
|||
* WARNING! Do not use this function. This function will be removed in
|
||||
* future versions of getdns.
|
||||
*/
|
||||
uint32_t getdns_context_get_num_pending_requests(getdns_context* context,
|
||||
struct timeval* next_timeout);
|
||||
uint32_t getdns_context_get_num_pending_requests(const getdns_context *context,
|
||||
struct timeval *next_timeout);
|
||||
|
||||
/**
|
||||
* Detach the eventloop from the context. Resets the context with the default
|
||||
|
@ -2184,7 +2371,7 @@ getdns_context_detach_eventloop(getdns_context *context);
|
|||
* @return GETDNS_RETURN_GOOD on success
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if context is NULL
|
||||
*/
|
||||
getdns_return_t getdns_context_set_use_threads(getdns_context* context,
|
||||
getdns_return_t getdns_context_set_use_threads(getdns_context *context,
|
||||
int use_threads);
|
||||
|
||||
/** @}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Meant to be run from this directory
|
||||
rm -fr gldns
|
||||
mkdir gldns
|
||||
svn co http://unbound.net/svn/trunk/sldns/
|
||||
svn co https://nlnetlabs.nl/svn/unbound/trunk/sldns/
|
||||
mv gbuffer.h sbuffer.h
|
||||
mv gbuffer.c sbuffer.c
|
||||
for f in sldns/*.[ch]
|
||||
|
|
|
@ -106,6 +106,8 @@ int
|
|||
gldns_buffer_reserve(gldns_buffer *buffer, size_t amount)
|
||||
{
|
||||
gldns_buffer_invariant(buffer);
|
||||
if (buffer->_vfixed)
|
||||
return 1;
|
||||
assert(!buffer->_fixed);
|
||||
if (buffer->_capacity < buffer->_position + amount) {
|
||||
size_t new_capacity = buffer->_capacity * 3 / 2;
|
||||
|
|
|
@ -130,7 +130,7 @@ struct gldns_buffer
|
|||
/** If the buffer is fixed it cannot be resized */
|
||||
unsigned _fixed : 1;
|
||||
|
||||
/** If the buffer is vfixed, no more than capacity bytes willl be
|
||||
/** If the buffer is vfixed, no more than capacity bytes will be
|
||||
* written to _data, however the _position counter will be updated
|
||||
* with the amount that would have been written in consecutive
|
||||
* writes. This allows for a modus operandi in which a sequence is
|
||||
|
@ -160,7 +160,7 @@ gldns_buffer_invariant(gldns_buffer *buffer)
|
|||
assert(buffer != NULL);
|
||||
assert(buffer->_position <= buffer->_limit || buffer->_vfixed);
|
||||
assert(buffer->_limit <= buffer->_capacity);
|
||||
assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0));
|
||||
assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0 && buffer->_limit == 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -497,7 +497,7 @@ gldns_buffer_set_at(gldns_buffer *buffer, size_t at, int c, size_t count)
|
|||
* writes count bytes of data to the current position of the buffer
|
||||
* \param[in] buffer the buffer
|
||||
* \param[in] data the data to write
|
||||
* \param[in] count the lenght of the data to write
|
||||
* \param[in] count the length of the data to write
|
||||
*/
|
||||
INLINE void
|
||||
gldns_buffer_write(gldns_buffer *buffer, const void *data, size_t count)
|
||||
|
|
|
@ -16,7 +16,7 @@ then
|
|||
mv sbuffer.h gbuffer.h
|
||||
mv sbuffer.c gbuffer.c
|
||||
else
|
||||
svn co http://unbound.net/svn/trunk/ldns/
|
||||
svn co https://nlnetlabs.nl/svn/unbound/trunk/sldns/
|
||||
for f in ldns/*.[ch]
|
||||
do
|
||||
sed -e 's/sldns_/gldns_/g' \
|
||||
|
@ -27,5 +27,5 @@ else
|
|||
done
|
||||
mv sbuffer.h gbuffer.h
|
||||
mv sbuffer.c gbuffer.c
|
||||
rm -r ldns
|
||||
rm -fr sldns
|
||||
fi
|
||||
|
|
|
@ -14,26 +14,6 @@
|
|||
#include "gldns/keyraw.h"
|
||||
#include "gldns/rrdef.h"
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md5.h>
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
# include <openssl/engine.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_BN_H
|
||||
#include <openssl/bn.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_RSA_H
|
||||
#include <openssl/rsa.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_DSA_H
|
||||
#include <openssl/dsa.h>
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
size_t
|
||||
gldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
|
||||
const size_t len, int alg)
|
||||
|
@ -89,6 +69,14 @@ gldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
|
|||
return 256;
|
||||
case GLDNS_ECDSAP384SHA384:
|
||||
return 384;
|
||||
#endif
|
||||
#ifdef USE_ED25519
|
||||
case GLDNS_ED25519:
|
||||
return 256;
|
||||
#endif
|
||||
#ifdef USE_ED448
|
||||
case GLDNS_ED448:
|
||||
return 456;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
|
@ -118,312 +106,3 @@ uint16_t gldns_calc_keytag_raw(const uint8_t* key, size_t keysize)
|
|||
return (uint16_t) (ac32 & 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef USE_GOST
|
||||
/** store GOST engine reference loaded into OpenSSL library */
|
||||
ENGINE* gldns_gost_engine = NULL;
|
||||
|
||||
int
|
||||
gldns_key_EVP_load_gost_id(void)
|
||||
{
|
||||
static int gost_id = 0;
|
||||
const EVP_PKEY_ASN1_METHOD* meth;
|
||||
ENGINE* e;
|
||||
|
||||
if(gost_id) return gost_id;
|
||||
|
||||
/* see if configuration loaded gost implementation from other engine*/
|
||||
meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
|
||||
if(meth) {
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
|
||||
/* see if engine can be loaded already */
|
||||
e = ENGINE_by_id("gost");
|
||||
if(!e) {
|
||||
/* load it ourself, in case statically linked */
|
||||
ENGINE_load_builtin_engines();
|
||||
ENGINE_load_dynamic();
|
||||
e = ENGINE_by_id("gost");
|
||||
}
|
||||
if(!e) {
|
||||
/* no gost engine in openssl */
|
||||
return 0;
|
||||
}
|
||||
if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
|
||||
if(!meth) {
|
||||
/* algo not found */
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
/* Note: do not ENGINE_finish and ENGINE_free the acquired engine
|
||||
* on some platforms this frees up the meth and unloads gost stuff */
|
||||
gldns_gost_engine = e;
|
||||
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
|
||||
void gldns_key_EVP_unload_gost(void)
|
||||
{
|
||||
if(gldns_gost_engine) {
|
||||
ENGINE_finish(gldns_gost_engine);
|
||||
ENGINE_free(gldns_gost_engine);
|
||||
gldns_gost_engine = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* USE_GOST */
|
||||
|
||||
DSA *
|
||||
gldns_key_buf2dsa_raw(unsigned char* key, size_t len)
|
||||
{
|
||||
uint8_t T;
|
||||
uint16_t length;
|
||||
uint16_t offset;
|
||||
DSA *dsa;
|
||||
BIGNUM *Q; BIGNUM *P;
|
||||
BIGNUM *G; BIGNUM *Y;
|
||||
|
||||
if(len == 0)
|
||||
return NULL;
|
||||
T = (uint8_t)key[0];
|
||||
length = (64 + T * 8);
|
||||
offset = 1;
|
||||
|
||||
if (T > 8) {
|
||||
return NULL;
|
||||
}
|
||||
if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
|
||||
return NULL;
|
||||
|
||||
Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
|
||||
offset += SHA_DIGEST_LENGTH;
|
||||
|
||||
P = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
offset += length;
|
||||
|
||||
G = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
offset += length;
|
||||
|
||||
Y = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
|
||||
/* create the key and set its properties */
|
||||
if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
|
||||
BN_free(Q);
|
||||
BN_free(P);
|
||||
BN_free(G);
|
||||
BN_free(Y);
|
||||
return NULL;
|
||||
}
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
#ifndef S_SPLINT_S
|
||||
dsa->p = P;
|
||||
dsa->q = Q;
|
||||
dsa->g = G;
|
||||
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;
|
||||
}
|
||||
|
||||
RSA *
|
||||
gldns_key_buf2rsa_raw(unsigned char* key, size_t len)
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t exp;
|
||||
uint16_t int16;
|
||||
RSA *rsa;
|
||||
BIGNUM *modulus;
|
||||
BIGNUM *exponent;
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
if (key[0] == 0) {
|
||||
if(len < 3)
|
||||
return NULL;
|
||||
memmove(&int16, key+1, 2);
|
||||
exp = ntohs(int16);
|
||||
offset = 3;
|
||||
} else {
|
||||
exp = key[0];
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
/* key length at least one */
|
||||
if(len < (size_t)offset + exp + 1)
|
||||
return NULL;
|
||||
|
||||
/* Exponent */
|
||||
exponent = BN_new();
|
||||
if(!exponent) return NULL;
|
||||
(void) BN_bin2bn(key+offset, (int)exp, exponent);
|
||||
offset += exp;
|
||||
|
||||
/* Modulus */
|
||||
modulus = BN_new();
|
||||
if(!modulus) {
|
||||
BN_free(exponent);
|
||||
return NULL;
|
||||
}
|
||||
/* length of the buffer must match the key length! */
|
||||
(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
|
||||
|
||||
rsa = RSA_new();
|
||||
if(!rsa) {
|
||||
BN_free(exponent);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef USE_GOST
|
||||
EVP_PKEY*
|
||||
gldns_gost2pkey_raw(unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* prefix header for X509 encoding */
|
||||
uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
|
||||
0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
|
||||
unsigned char encoded[37+64];
|
||||
const unsigned char* pp;
|
||||
if(keylen != 64) {
|
||||
/* key wrong size */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create evp_key */
|
||||
memmove(encoded, asn, 37);
|
||||
memmove(encoded+37, key, 64);
|
||||
pp = (unsigned char*)&encoded[0];
|
||||
|
||||
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
|
||||
}
|
||||
#endif /* USE_GOST */
|
||||
|
||||
#ifdef USE_ECDSA
|
||||
EVP_PKEY*
|
||||
gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
|
||||
{
|
||||
unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
|
||||
const unsigned char* pp = buf;
|
||||
EVP_PKEY *evp_key;
|
||||
EC_KEY *ec;
|
||||
/* check length, which uncompressed must be 2 bignums */
|
||||
if(algo == GLDNS_ECDSAP256SHA256) {
|
||||
if(keylen != 2*256/8) return NULL;
|
||||
ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
} else if(algo == GLDNS_ECDSAP384SHA384) {
|
||||
if(keylen != 2*384/8) return NULL;
|
||||
ec = EC_KEY_new_by_curve_name(NID_secp384r1);
|
||||
} else ec = NULL;
|
||||
if(!ec) return NULL;
|
||||
if(keylen+1 > sizeof(buf)) { /* sanity check */
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
|
||||
* of openssl) for uncompressed data */
|
||||
buf[0] = POINT_CONVERSION_UNCOMPRESSED;
|
||||
memmove(buf+1, key, keylen);
|
||||
if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
evp_key = EVP_PKEY_new();
|
||||
if(!evp_key) {
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
|
||||
EVP_PKEY_free(evp_key);
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ECDSA */
|
||||
|
||||
#ifdef USE_ED25519
|
||||
EVP_PKEY*
|
||||
gldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
|
||||
uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
|
||||
0x70, 0x03, 0x21, 0x00};
|
||||
int pre_len = 12;
|
||||
uint8_t buf[256];
|
||||
EVP_PKEY *evp_key;
|
||||
/* pp gets modified by d2i() */
|
||||
const unsigned char* pp = (unsigned char*)buf;
|
||||
if(keylen != 32 || keylen + pre_len > sizeof(buf))
|
||||
return NULL; /* wrong length */
|
||||
memmove(buf, pre, pre_len);
|
||||
memmove(buf+pre_len, key, keylen);
|
||||
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ED25519 */
|
||||
|
||||
int
|
||||
gldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
|
||||
const EVP_MD* md)
|
||||
{
|
||||
EVP_MD_CTX* ctx;
|
||||
ctx = EVP_MD_CTX_create();
|
||||
if(!ctx)
|
||||
return 0;
|
||||
if(!EVP_DigestInit_ex(ctx, md, NULL) ||
|
||||
!EVP_DigestUpdate(ctx, data, len) ||
|
||||
!EVP_DigestFinal_ex(ctx, dest, NULL)) {
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
return 0;
|
||||
}
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
return 1;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
|
|
@ -20,13 +20,11 @@
|
|||
#ifndef GLDNS_KEYRAW_H
|
||||
#define GLDNS_KEYRAW_H
|
||||
|
||||
#include "keyraw-internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if GLDNS_BUILD_CONFIG_HAVE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/evp.h>
|
||||
#endif /* GLDNS_BUILD_CONFIG_HAVE_SSL */
|
||||
|
||||
/**
|
||||
* get the length of the keydata in bits
|
||||
|
@ -46,74 +44,6 @@ size_t gldns_rr_dnskey_key_size_raw(const unsigned char *keydata,
|
|||
*/
|
||||
uint16_t gldns_calc_keytag_raw(const uint8_t* key, size_t keysize);
|
||||
|
||||
#if GLDNS_BUILD_CONFIG_HAVE_SSL
|
||||
/**
|
||||
* Get the PKEY id for GOST, loads GOST into openssl as a side effect.
|
||||
* Only available if GOST is compiled into the library and openssl.
|
||||
* \return the gost id for EVP_CTX creation.
|
||||
*/
|
||||
int gldns_key_EVP_load_gost_id(void);
|
||||
|
||||
/** Release the engine reference held for the GOST engine. */
|
||||
void gldns_key_EVP_unload_gost(void);
|
||||
|
||||
/**
|
||||
* Like gldns_key_buf2dsa, but uses raw buffer.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return a DSA * structure with the key material
|
||||
*/
|
||||
DSA *gldns_key_buf2dsa_raw(unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with GOST.
|
||||
* \param[in] key data to convert
|
||||
* \param[in] keylen length of the key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_gost2pkey_raw(unsigned char* key, size_t keylen);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ECDSA.
|
||||
* \param[in] key data to convert
|
||||
* \param[in] keylen length of the key data
|
||||
* \param[in] algo precise algorithm to initialize ECC group values.
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
|
||||
|
||||
/**
|
||||
* Like gldns_key_buf2rsa, but uses raw buffer.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return a RSA * structure with the key material
|
||||
*/
|
||||
RSA *gldns_key_buf2rsa_raw(unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ED25519.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_ed255192pkey_raw(const unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Utility function to calculate hash using generic EVP_MD pointer.
|
||||
* \param[in] data the data to hash.
|
||||
* \param[in] len length of data.
|
||||
* \param[out] dest the destination of the hash, must be large enough.
|
||||
* \param[in] md the message digest to use.
|
||||
* \return true if worked, false on failure.
|
||||
*/
|
||||
int gldns_digest_evp(unsigned char* data, unsigned int len,
|
||||
unsigned char* dest, const EVP_MD* md);
|
||||
|
||||
#endif /* GLDNS_BUILD_CONFIG_HAVE_SSL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,14 +33,14 @@ ssize_t
|
|||
gldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr)
|
||||
{
|
||||
int c, prev_c;
|
||||
int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
|
||||
int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
|
||||
int com, quoted;
|
||||
char *t;
|
||||
size_t i;
|
||||
const char *d;
|
||||
const char *del;
|
||||
|
||||
/* standard delimeters */
|
||||
/* standard delimiters */
|
||||
if (!delim) {
|
||||
/* from isspace(3) */
|
||||
del = GLDNS_PARSE_NORMAL;
|
||||
|
@ -244,7 +244,7 @@ gldns_bget_token_par(gldns_buffer *b, char *token, const char *delim,
|
|||
size_t limit, int* par, const char* skipw)
|
||||
{
|
||||
int c, lc;
|
||||
int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
|
||||
int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
|
||||
int com, quoted;
|
||||
char *t;
|
||||
size_t i;
|
||||
|
|
|
@ -103,9 +103,9 @@ ssize_t gldns_bget_token(struct gldns_buffer *b, char *token, const char *delim,
|
|||
* after the keyword + k_del until we hit d_del
|
||||
* \param[in] f file pointer to read from
|
||||
* \param[in] keyword keyword to look for
|
||||
* \param[in] k_del keyword delimeter
|
||||
* \param[in] k_del keyword delimiter
|
||||
* \param[out] data the data found
|
||||
* \param[in] d_del the data delimeter
|
||||
* \param[in] d_del the data delimiter
|
||||
* \param[in] data_limit maximum size the the data buffer
|
||||
* \return the number of character read
|
||||
*/
|
||||
|
@ -116,9 +116,9 @@ ssize_t gldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del,
|
|||
* after the keyword + k_del until we hit d_del
|
||||
* \param[in] f file pointer to read from
|
||||
* \param[in] keyword keyword to look for
|
||||
* \param[in] k_del keyword delimeter
|
||||
* \param[in] k_del keyword delimiter
|
||||
* \param[out] data the data found
|
||||
* \param[in] d_del the data delimeter
|
||||
* \param[in] d_del the data delimiter
|
||||
* \param[in] data_limit maximum size the the data buffer
|
||||
* \param[in] line_nr pointer to an integer containing the current line number (for
|
||||
debugging purposes)
|
||||
|
@ -131,9 +131,9 @@ ssize_t gldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_de
|
|||
* after the keyword + k_del until we hit d_del
|
||||
* \param[in] b buffer pointer to read from
|
||||
* \param[in] keyword keyword to look for
|
||||
* \param[in] k_del keyword delimeter
|
||||
* \param[in] k_del keyword delimiter
|
||||
* \param[out] data the data found
|
||||
* \param[in] d_del the data delimeter
|
||||
* \param[in] d_del the data delimiter
|
||||
* \param[in] data_limit maximum size the the data buffer
|
||||
* \return the number of character read
|
||||
*/
|
||||
|
|
|
@ -165,20 +165,20 @@ gldns_gmtime64_r(int64_t clock, struct tm *result)
|
|||
#endif /* SIZEOF_TIME_T <= 4 */
|
||||
|
||||
static int64_t
|
||||
gldns_serial_arithmitics_time(int32_t time, time_t now)
|
||||
gldns_serial_arithmetics_time(int32_t time, time_t now)
|
||||
{
|
||||
int32_t offset = time - (int32_t) now;
|
||||
return (int64_t) now + offset;
|
||||
}
|
||||
|
||||
struct tm *
|
||||
gldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result)
|
||||
gldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result)
|
||||
{
|
||||
#if SIZEOF_TIME_T <= 4
|
||||
int64_t secs_since_epoch = gldns_serial_arithmitics_time(time, now);
|
||||
int64_t secs_since_epoch = gldns_serial_arithmetics_time(time, now);
|
||||
return gldns_gmtime64_r(secs_since_epoch, result);
|
||||
#else
|
||||
time_t secs_since_epoch = gldns_serial_arithmitics_time(time, now);
|
||||
time_t secs_since_epoch = gldns_serial_arithmetics_time(time, now);
|
||||
return gmtime_r(&secs_since_epoch, result);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -62,13 +62,13 @@ time_t gldns_mktime_from_utc(const struct tm *tm);
|
|||
* fields of RRSIG records.
|
||||
*
|
||||
* \param[in] time number of seconds since epoch (midnight, January 1st, 1970)
|
||||
* to be intepreted as a serial arithmetics number relative to now.
|
||||
* to be interpreted as a serial arithmetics number relative to now.
|
||||
* \param[in] now number of seconds since epoch (midnight, January 1st, 1970)
|
||||
* to which the time value is compared to determine the final value.
|
||||
* \param[out] result the struct with the broken-out time information
|
||||
* \return result on success or NULL on error
|
||||
*/
|
||||
struct tm * gldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result);
|
||||
struct tm * gldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result);
|
||||
|
||||
/**
|
||||
* converts a ttl value (like 5d2h) to a long.
|
||||
|
|
|
@ -150,6 +150,9 @@ static const gldns_rdf_type type_openpgpkey_wireformat[] = {
|
|||
static const gldns_rdf_type type_csync_wireformat[] = {
|
||||
GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_NSEC
|
||||
};
|
||||
static const gldns_rdf_type type_zonemd_wireformat[] = {
|
||||
GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT8, GLDNS_RDF_TYPE_INT8, GLDNS_RDF_TYPE_HEX
|
||||
};
|
||||
/* nsec3 is some vars, followed by same type of data of nsec */
|
||||
static const gldns_rdf_type type_nsec3_wireformat[] = {
|
||||
/* GLDNS_RDF_TYPE_NSEC3_VARS, GLDNS_RDF_TYPE_NSEC3_NEXT_OWNER, GLDNS_RDF_TYPE_NSEC*/
|
||||
|
@ -229,6 +232,15 @@ static const gldns_rdf_type type_caa_wireformat[] = {
|
|||
GLDNS_RDF_TYPE_TAG,
|
||||
GLDNS_RDF_TYPE_LONG_STR
|
||||
};
|
||||
#ifdef DRAFT_RRTYPES
|
||||
static const gldns_rdf_type type_doa_wireformat[] = {
|
||||
GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT8,
|
||||
GLDNS_RDF_TYPE_STR, GLDNS_RDF_TYPE_B64
|
||||
};
|
||||
static const gldns_rdf_type type_amtrelay_wireformat[] = {
|
||||
GLDNS_RDF_TYPE_AMTRELAY
|
||||
};
|
||||
#endif
|
||||
|
||||
/* All RR's defined in 1035 are well known and can thus
|
||||
* be compressed. See RFC3597. These RR's are:
|
||||
|
@ -341,12 +353,9 @@ static gldns_rr_descriptor rdata_field_descriptors[] = {
|
|||
{GLDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 52 */
|
||||
{GLDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/*53 */
|
||||
#ifdef DRAFT_RRTYPES
|
||||
/* 53 */
|
||||
{GLDNS_RR_TYPE_SMIMEA, "SMIMEA", 4, 4, type_tlsa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
#else
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
#endif
|
||||
/* 54 */
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 55
|
||||
* Hip ends with 0 or more Rendezvous Servers represented as dname's.
|
||||
|
@ -375,7 +384,8 @@ static gldns_rr_descriptor rdata_field_descriptors[] = {
|
|||
{GLDNS_RR_TYPE_OPENPGPKEY, "OPENPGPKEY", 1, 1, type_openpgpkey_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 62 */
|
||||
{GLDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 63 */
|
||||
{GLDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
|
@ -607,8 +617,14 @@ static gldns_rr_descriptor rdata_field_descriptors[] = {
|
|||
#ifdef DRAFT_RRTYPES
|
||||
/* 258 */
|
||||
{GLDNS_RR_TYPE_AVC, "AVC", 1, 0, NULL, GLDNS_RDF_TYPE_STR, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 259 */
|
||||
{GLDNS_RR_TYPE_DOA, "DOA", 1, 0, type_doa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 260 */
|
||||
{GLDNS_RR_TYPE_AMTRELAY, "AMTRELAY", 1, 0, type_amtrelay_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
#else
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE258", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE259", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
{GLDNS_RR_TYPE_NULL, "TYPE260", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
|
||||
#endif
|
||||
|
||||
/* split in array, no longer contiguous */
|
||||
|
|
|
@ -38,7 +38,7 @@ extern "C" {
|
|||
#define GLDNS_KEY_REVOKE_KEY 0x0080 /* used to revoke KSK, rfc 5011 */
|
||||
|
||||
/* The first fields are contiguous and can be referenced instantly */
|
||||
#define GLDNS_RDATA_FIELD_DESCRIPTORS_COMMON 259
|
||||
#define GLDNS_RDATA_FIELD_DESCRIPTORS_COMMON 260
|
||||
|
||||
/** lookuptable for rr classes */
|
||||
extern struct gldns_struct_lookup_table* gldns_rr_classes;
|
||||
|
@ -182,9 +182,7 @@ enum gldns_enum_rr_type
|
|||
GLDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */
|
||||
GLDNS_RR_TYPE_NSEC3PARAMS = 51,
|
||||
GLDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
|
||||
GLDNS_RR_TYPE_SMIMEA = 53, /* draft-ietf-dane-smime, TLSA-like but may
|
||||
be extended */
|
||||
|
||||
GLDNS_RR_TYPE_SMIMEA = 53, /* RFC 8162 */
|
||||
GLDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
|
||||
|
||||
/** draft-reid-dnsext-zs */
|
||||
|
@ -197,6 +195,7 @@ enum gldns_enum_rr_type
|
|||
GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */
|
||||
GLDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */
|
||||
GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */
|
||||
GLDNS_RR_TYPE_ZONEMD = 63, /* draft-wessels-dns-zone-digest */
|
||||
|
||||
GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
|
||||
|
||||
|
@ -227,7 +226,8 @@ enum gldns_enum_rr_type
|
|||
GLDNS_RR_TYPE_URI = 256, /* RFC 7553 */
|
||||
GLDNS_RR_TYPE_CAA = 257, /* RFC 6844 */
|
||||
GLDNS_RR_TYPE_AVC = 258,
|
||||
GLDNS_RR_TYPE_DOA = 259,
|
||||
GLDNS_RR_TYPE_DOA = 259, /* draft-durand-doa-over-dns */
|
||||
GLDNS_RR_TYPE_AMTRELAY = 260, /* draft-ietf-mboned-driad-amt-discovery */
|
||||
|
||||
/** DNSSEC Trust Authorities */
|
||||
GLDNS_RR_TYPE_TA = 32768,
|
||||
|
@ -332,13 +332,13 @@ enum gldns_enum_rdf_type
|
|||
GLDNS_RDF_TYPE_NSEC3_NEXT_OWNER,
|
||||
|
||||
/** 4 shorts represented as 4 * 16 bit hex numbers
|
||||
* seperated by colons. For NID and L64.
|
||||
* separated by colons. For NID and L64.
|
||||
*/
|
||||
GLDNS_RDF_TYPE_ILNP64,
|
||||
|
||||
/** 6 * 8 bit hex numbers seperated by dashes. For EUI48. */
|
||||
/** 6 * 8 bit hex numbers separated by dashes. For EUI48. */
|
||||
GLDNS_RDF_TYPE_EUI48,
|
||||
/** 8 * 8 bit hex numbers seperated by dashes. For EUI64. */
|
||||
/** 8 * 8 bit hex numbers separated by dashes. For EUI64. */
|
||||
GLDNS_RDF_TYPE_EUI64,
|
||||
|
||||
/** A non-zero sequence of US-ASCII letters and numbers in lower case.
|
||||
|
@ -352,6 +352,9 @@ enum gldns_enum_rdf_type
|
|||
*/
|
||||
GLDNS_RDF_TYPE_LONG_STR,
|
||||
|
||||
/* draft-ietf-mboned-driad-amt-discovery */
|
||||
GLDNS_RDF_TYPE_AMTRELAY,
|
||||
|
||||
/** TSIG extended 16bit error value */
|
||||
GLDNS_RDF_TYPE_TSIGERROR,
|
||||
|
||||
|
|
|
@ -836,7 +836,7 @@ const char* gldns_get_errorstr_parse(int e)
|
|||
}
|
||||
|
||||
/* Strip whitespace from the start and the end of <line>. */
|
||||
static char *
|
||||
char *
|
||||
gldns_strip_ws(char *line)
|
||||
{
|
||||
char *s = line, *e;
|
||||
|
@ -906,7 +906,7 @@ int gldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
|
|||
*dname_len = 0;
|
||||
return GLDNS_WIREPARSE_ERR_INCLUDE;
|
||||
} else {
|
||||
return gldns_str2wire_rr_buf(line, rr, len, dname_len,
|
||||
int r = gldns_str2wire_rr_buf(line, rr, len, dname_len,
|
||||
parse_state?parse_state->default_ttl:0,
|
||||
(parse_state&&parse_state->origin_len)?
|
||||
parse_state->origin:NULL,
|
||||
|
@ -914,6 +914,13 @@ int gldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
|
|||
(parse_state&&parse_state->prev_rr_len)?
|
||||
parse_state->prev_rr:NULL,
|
||||
parse_state?parse_state->prev_rr_len:0);
|
||||
if(r == GLDNS_WIREPARSE_ERR_OK && (*dname_len) != 0 &&
|
||||
parse_state &&
|
||||
(*dname_len) <= sizeof(parse_state->prev_rr)) {
|
||||
memmove(parse_state->prev_rr, rr, *dname_len);
|
||||
parse_state->prev_rr_len = (*dname_len);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return GLDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
@ -990,6 +997,8 @@ int gldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
|
|||
return gldns_str2wire_hip_buf(str, rd, len);
|
||||
case GLDNS_RDF_TYPE_INT16_DATA:
|
||||
return gldns_str2wire_int16_data_buf(str, rd, len);
|
||||
case GLDNS_RDF_TYPE_AMTRELAY:
|
||||
return gldns_str2wire_amtrelay_buf(str, rd, len);
|
||||
case GLDNS_RDF_TYPE_UNKNOWN:
|
||||
case GLDNS_RDF_TYPE_SERVICE:
|
||||
return GLDNS_WIREPARSE_ERR_NOT_IMPL;
|
||||
|
@ -1218,6 +1227,17 @@ int gldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len)
|
|||
return GLDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
||||
/** see if the string ends, or ends in whitespace */
|
||||
static int
|
||||
gldns_is_last_of_string(const char* str)
|
||||
{
|
||||
if(*str == 0) return 1;
|
||||
while(isspace((unsigned char)*str))
|
||||
str++;
|
||||
if(*str == 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
{
|
||||
const char* s = str;
|
||||
|
@ -1227,7 +1247,7 @@ int gldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
|
|||
s++;
|
||||
continue;
|
||||
}
|
||||
if(dlen == 0 && *s == '0' && *(s+1) == 0) {
|
||||
if(dlen == 0 && *s == '0' && gldns_is_last_of_string(s+1)) {
|
||||
*len = 0;
|
||||
return GLDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
@ -1541,7 +1561,7 @@ int gldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len)
|
|||
s = strtod(my_str, &my_str);
|
||||
}
|
||||
|
||||
/* skip blanks before norterness */
|
||||
/* skip blanks before northerness */
|
||||
while (isblank((unsigned char) *my_str)) {
|
||||
my_str++;
|
||||
}
|
||||
|
@ -1693,12 +1713,15 @@ int gldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len)
|
|||
struct protoent *p = getprotobyname(token);
|
||||
have_proto = 1;
|
||||
if(p) rd[0] = (uint8_t)p->p_proto;
|
||||
else if(strcasecmp(token, "tcp")==0) rd[0]=6;
|
||||
else if(strcasecmp(token, "udp")==0) rd[0]=17;
|
||||
else rd[0] = (uint8_t)atoi(token);
|
||||
(void)strlcpy(proto_str, token, sizeof(proto_str));
|
||||
} else {
|
||||
int serv_port;
|
||||
struct servent *serv = getservbyname(token, proto_str);
|
||||
if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port);
|
||||
else if(strcasecmp(token, "domain")==0) serv_port=53;
|
||||
else {
|
||||
serv_port = atoi(token);
|
||||
if(serv_port == 0 && strcmp(token, "0") != 0) {
|
||||
|
@ -2097,3 +2120,77 @@ int gldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len)
|
|||
*len = ((size_t)n)+2;
|
||||
return GLDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
||||
int gldns_str2wire_amtrelay_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
{
|
||||
size_t relay_len = 0;
|
||||
int s;
|
||||
uint8_t relay_type;
|
||||
char token[512];
|
||||
gldns_buffer strbuf;
|
||||
gldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str));
|
||||
|
||||
if(*len < 2)
|
||||
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
/* precedence */
|
||||
if(gldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0)
|
||||
return RET_ERR(GLDNS_WIREPARSE_ERR_INVALID_STR,
|
||||
gldns_buffer_position(&strbuf));
|
||||
rd[0] = (uint8_t)atoi(token);
|
||||
/* discovery_optional */
|
||||
if(gldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0)
|
||||
return RET_ERR(GLDNS_WIREPARSE_ERR_INVALID_STR,
|
||||
gldns_buffer_position(&strbuf));
|
||||
if ((token[0] != '0' && token[0] != '1') || token[1] != 0)
|
||||
return RET_ERR(GLDNS_WIREPARSE_ERR_INVALID_STR,
|
||||
gldns_buffer_position(&strbuf));
|
||||
|
||||
rd[1] = *token == '1' ? 0x80 : 0x00;
|
||||
/* relay_type */
|
||||
if(gldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0)
|
||||
return RET_ERR(GLDNS_WIREPARSE_ERR_INVALID_STR,
|
||||
gldns_buffer_position(&strbuf));
|
||||
relay_type = (uint8_t)atoi(token);
|
||||
if (relay_type > 0x7F)
|
||||
return RET_ERR(GLDNS_WIREPARSE_ERR_INVALID_STR,
|
||||
gldns_buffer_position(&strbuf));
|
||||
rd[1] |= relay_type;
|
||||
|
||||
if (relay_type == 0) {
|
||||
*len = 2;
|
||||
return GLDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
/* relay */
|
||||
if(gldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0)
|
||||
return RET_ERR(GLDNS_WIREPARSE_ERR_INVALID_STR,
|
||||
gldns_buffer_position(&strbuf));
|
||||
if(relay_type == 1) {
|
||||
/* IP4 */
|
||||
relay_len = *len - 2;
|
||||
s = gldns_str2wire_a_buf(token, rd+2, &relay_len);
|
||||
if(s) return RET_ERR_SHIFT(s, gldns_buffer_position(&strbuf));
|
||||
} else if(relay_type == 2) {
|
||||
/* IP6 */
|
||||
relay_len = *len - 2;
|
||||
s = gldns_str2wire_aaaa_buf(token, rd+2, &relay_len);
|
||||
if(s) return RET_ERR_SHIFT(s, gldns_buffer_position(&strbuf));
|
||||
} else if(relay_type == 3) {
|
||||
/* DNAME */
|
||||
relay_len = *len - 2;
|
||||
s = gldns_str2wire_dname_buf(token, rd+2, &relay_len);
|
||||
if(s) return RET_ERR_SHIFT(s, gldns_buffer_position(&strbuf));
|
||||
} else {
|
||||
/* unknown gateway type */
|
||||
return RET_ERR(GLDNS_WIREPARSE_ERR_INVALID_STR,
|
||||
gldns_buffer_position(&strbuf));
|
||||
}
|
||||
/* double check for size */
|
||||
if(*len < 2 + relay_len)
|
||||
return RET_ERR(GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
|
||||
gldns_buffer_position(&strbuf));
|
||||
|
||||
*len = 2 + relay_len;
|
||||
return GLDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -554,6 +554,21 @@ int gldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len);
|
|||
*/
|
||||
int gldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len);
|
||||
|
||||
/**
|
||||
* Convert rdf of type GLDNS_RDF_TYPE_AMTRELAY from string to wireformat.
|
||||
* @param str: the text to convert for this rdata element.
|
||||
* @param rd: rdata buffer for the wireformat.
|
||||
* @param len: length of rd buffer on input, used length on output.
|
||||
* @return 0 on success, error on failure.
|
||||
*/
|
||||
int gldns_str2wire_amtrelay_buf(const char* str, uint8_t* rd, size_t* len);
|
||||
|
||||
/**
|
||||
* Strip whitespace from the start and the end of line.
|
||||
* @param line: modified with 0 to shorten it.
|
||||
* @return new start with spaces skipped.
|
||||
*/
|
||||
char * gldns_strip_ws(char *line);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -255,6 +255,12 @@ int gldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
|
|||
return gldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0);
|
||||
}
|
||||
|
||||
int gldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
|
||||
{
|
||||
/* use arguments as temporary variables */
|
||||
return gldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0);
|
||||
}
|
||||
|
||||
int gldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
|
||||
size_t str_len, uint16_t rrtype)
|
||||
{
|
||||
|
@ -998,6 +1004,9 @@ int gldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
|
|||
return gldns_wire2str_tag_scan(d, dlen, s, slen);
|
||||
case GLDNS_RDF_TYPE_LONG_STR:
|
||||
return gldns_wire2str_long_str_scan(d, dlen, s, slen);
|
||||
case GLDNS_RDF_TYPE_AMTRELAY:
|
||||
return gldns_wire2str_amtrelay_scan(d, dlen, s, slen, pkt,
|
||||
pktlen);
|
||||
case GLDNS_RDF_TYPE_TSIGERROR:
|
||||
return gldns_wire2str_tsigerror_scan(d, dlen, s, slen);
|
||||
}
|
||||
|
@ -1059,7 +1068,11 @@ int gldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
|||
d4 = (*d)[4];
|
||||
d5 = (*d)[5];
|
||||
tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
|
||||
w = gldns_str_print(s, sl, "%"PRIu64, (uint64_t)tsigtime);
|
||||
#ifndef USE_WINSOCK
|
||||
w = gldns_str_print(s, sl, "%llu", (long long)tsigtime);
|
||||
#else
|
||||
w = gldns_str_print(s, sl, "%I64u", (long long)tsigtime);
|
||||
#endif
|
||||
(*d)+=6;
|
||||
(*dl)-=6;
|
||||
return w;
|
||||
|
@ -1331,7 +1344,7 @@ int gldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
|||
if(*dl < 4) return -1;
|
||||
t = gldns_read_uint32(*d);
|
||||
date_buf[15]=0;
|
||||
if(gldns_serial_arithmitics_gmtime_r(t, time(NULL), &tm) &&
|
||||
if(gldns_serial_arithmetics_gmtime_r(t, time(NULL), &tm) &&
|
||||
strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
|
||||
(*d) += 4;
|
||||
(*dl) -= 4;
|
||||
|
@ -1467,6 +1480,10 @@ int gldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
|||
if(protocol && (protocol->p_name != NULL)) {
|
||||
w += gldns_str_print(s, sl, "%s", protocol->p_name);
|
||||
proto_name = protocol->p_name;
|
||||
} else if(protocol_nr == 6) {
|
||||
w += gldns_str_print(s, sl, "tcp");
|
||||
} else if(protocol_nr == 17) {
|
||||
w += gldns_str_print(s, sl, "udp");
|
||||
} else {
|
||||
w += gldns_str_print(s, sl, "%u", (unsigned)protocol_nr);
|
||||
}
|
||||
|
@ -1693,6 +1710,61 @@ int gldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
|||
return w;
|
||||
}
|
||||
|
||||
/* internal scan routine that can modify arguments on failure */
|
||||
static int gldns_wire2str_amtrelay_scan_internal(uint8_t** d, size_t* dl,
|
||||
char** s, size_t* sl, uint8_t* pkt, size_t pktlen)
|
||||
{
|
||||
/* https://www.ietf.org/id/draft-ietf-mboned-driad-amt-discovery-01.txt */
|
||||
uint8_t precedence, discovery_optional, relay_type;
|
||||
int w = 0;
|
||||
|
||||
if(*dl < 2) return -1;
|
||||
precedence = (*d)[0];
|
||||
discovery_optional= (*d)[1] >> 7;
|
||||
relay_type = (*d)[1] % 0x7F;
|
||||
if(relay_type > 3)
|
||||
return -1; /* unknown */
|
||||
(*d)+=2;
|
||||
(*dl)-=2;
|
||||
w += gldns_str_print(s, sl, "%d %d %d ",
|
||||
(int)precedence, (int)discovery_optional, (int)relay_type);
|
||||
|
||||
switch(relay_type) {
|
||||
case 0: /* no relay */
|
||||
break;
|
||||
case 1: /* ip4 */
|
||||
w += gldns_wire2str_a_scan(d, dl, s, sl);
|
||||
break;
|
||||
case 2: /* ip6 */
|
||||
w += gldns_wire2str_aaaa_scan(d, dl, s, sl);
|
||||
break;
|
||||
case 3: /* dname */
|
||||
w += gldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen);
|
||||
break;
|
||||
default: /* unknown */
|
||||
return -1;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
int gldns_wire2str_amtrelay_scan(uint8_t** d, size_t* dl, char** s, size_t* sl,
|
||||
uint8_t* pkt, size_t pktlen)
|
||||
{
|
||||
uint8_t* od = *d;
|
||||
char* os = *s;
|
||||
size_t odl = *dl, osl = *sl;
|
||||
int w=gldns_wire2str_amtrelay_scan_internal(d, dl, s, sl, pkt, pktlen);
|
||||
if(w == -1) {
|
||||
*d = od;
|
||||
*s = os;
|
||||
*dl = odl;
|
||||
*sl = osl;
|
||||
return -1;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
int gldns_wire2str_tsigerror_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
||||
{
|
||||
gldns_lookup_table *lt;
|
||||
|
@ -1742,8 +1814,13 @@ int gldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
|
|||
if(error_code < llq_errors_num)
|
||||
w += gldns_str_print(s, sl, " %s", llq_errors[error_code]);
|
||||
else w += gldns_str_print(s, sl, " error %d", (int)error_code);
|
||||
w += gldns_str_print(s, sl, " id %"PRIx64" lease-life %lu",
|
||||
(uint64_t)llq_id, (unsigned long)lease_life);
|
||||
#ifndef USE_WINSOCK
|
||||
w += gldns_str_print(s, sl, " id %llx lease-life %lu",
|
||||
(unsigned long long)llq_id, (unsigned long)lease_life);
|
||||
#else
|
||||
w += gldns_str_print(s, sl, " id %I64x lease-life %lu",
|
||||
(unsigned long long)llq_id, (unsigned long)lease_life);
|
||||
#endif
|
||||
return w;
|
||||
}
|
||||
|
||||
|
|
|
@ -358,6 +358,22 @@ int gldns_wire2str_edns_option_code_print(char** str, size_t* str_len,
|
|||
int gldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str,
|
||||
size_t str_len);
|
||||
|
||||
/**
|
||||
* Convert question RR to string presentation format, on one line. User buffer.
|
||||
* @param rr: wireformat RR data
|
||||
* @param rr_len: length of the rr wire data.
|
||||
* @param str: the string buffer to write to.
|
||||
* If you pass NULL as the str, the return value of the function is
|
||||
* the str_len you need for the entire packet. It does not include
|
||||
* the 0 byte at the end.
|
||||
* @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 or equal than str_len if output was truncated.
|
||||
*/
|
||||
int gldns_wire2str_rrquestion_buf(uint8_t* rr, size_t rr_len, char* str,
|
||||
size_t str_len);
|
||||
|
||||
/**
|
||||
* 3597 printout of an RR in unknown rr format.
|
||||
* There are more format and comment options available for printout
|
||||
|
@ -900,6 +916,21 @@ int gldns_wire2str_tag_scan(uint8_t** data, size_t* data_len, char** str,
|
|||
int gldns_wire2str_long_str_scan(uint8_t** data, size_t* data_len, char** str,
|
||||
size_t* str_len);
|
||||
|
||||
/**
|
||||
* Scan wireformat AMTRELAY field to string, with user buffers.
|
||||
* It shifts the arguments to move along (see gldns_wire2str_pkt_scan).
|
||||
* @param data: wireformat data.
|
||||
* @param data_len: length of data buffer.
|
||||
* @param str: string buffer.
|
||||
* @param str_len: length of string buffer.
|
||||
* @param pkt: packet for decompression, if NULL no decompression.
|
||||
* @param pktlen: length of packet buffer.
|
||||
* @return number of characters (except null) needed to print.
|
||||
* Can return -1 on failure.
|
||||
*/
|
||||
int gldns_wire2str_amtrelay_scan(uint8_t** data, size_t* data_len, char** str,
|
||||
size_t* str_len, uint8_t* pkt, size_t pktlen);
|
||||
|
||||
/**
|
||||
* Print EDNS LLQ option data to string. User buffers, moves string pointers.
|
||||
* @param str: string buffer.
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* keyraw.c - raw key operations and conversions - OpenSSL version
|
||||
*
|
||||
* (c) NLnet Labs, 2004-2008
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Implementation of raw DNSKEY functions (work on wire rdata).
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "gldns/keyraw.h"
|
||||
#include "gldns/rrdef.h"
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* keyraw.h -- raw key and signature access and conversion - OpenSSL
|
||||
*
|
||||
* Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* See LICENSE for the license.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* raw key and signature access and conversion
|
||||
*
|
||||
* Since those functions heavily rely op cryptographic operations,
|
||||
* this module is dependent on openssl.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLDNS_KEYRAW_INTERNAL_H
|
||||
#define GLDNS_KEYRAW_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GLDNS_KEYRAW_INTERNAL_H */
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
*
|
||||
* /brief functions for dealing with pubkey pinsets
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 ACLU
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "context.h"
|
||||
#include <nettle/base64.h>
|
||||
|
||||
#include "types-internal.h"
|
||||
|
||||
#include "pubkey-pinning.h"
|
||||
|
||||
/**
|
||||
** Interfaces from pubkey-pinning.h
|
||||
**/
|
||||
|
||||
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size)
|
||||
{
|
||||
struct base64_decode_ctx ctx;
|
||||
uint8_t* lim = res + res_size;
|
||||
|
||||
base64_decode_init(&ctx);
|
||||
|
||||
for(; *str != '\0' && res < lim; ++str) {
|
||||
int r = base64_decode_single(&ctx, res, *str);
|
||||
if (r == -1 )
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
res += r;
|
||||
}
|
||||
return (res == lim) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
*
|
||||
* \file tls-internal.h
|
||||
* @brief getdns TLS implementation-specific items
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018-2019, NLnet Labs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _GETDNS_TLS_INTERNAL_H
|
||||
#define _GETDNS_TLS_INTERNAL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <gnutls/dane.h>
|
||||
|
||||
#include "getdns/getdns.h"
|
||||
|
||||
#define SHA_DIGEST_LENGTH 20
|
||||
#define SHA224_DIGEST_LENGTH 28
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#define SHA384_DIGEST_LENGTH 48
|
||||
#define SHA512_DIGEST_LENGTH 64
|
||||
|
||||
#define GETDNS_TLS_MAX_DIGEST_LENGTH (SHA512_DIGEST_LENGTH)
|
||||
|
||||
#define HAVE_TLS_CTX_CURVES_LIST 0
|
||||
#define HAVE_TLS_CONN_CURVES_LIST 0
|
||||
|
||||
/* Forward declare type. */
|
||||
struct getdns_log_config;
|
||||
|
||||
typedef struct _getdns_tls_context {
|
||||
struct mem_funcs* mfs;
|
||||
char* cipher_list;
|
||||
char* cipher_suites;
|
||||
char* curve_list;
|
||||
gnutls_protocol_t min_tls;
|
||||
gnutls_protocol_t max_tls;
|
||||
char* ca_trust_file;
|
||||
char* ca_trust_path;
|
||||
const struct getdns_log_config* log;
|
||||
} _getdns_tls_context;
|
||||
|
||||
typedef struct _getdns_tls_connection {
|
||||
gnutls_session_t tls;
|
||||
gnutls_certificate_credentials_t cred;
|
||||
int shutdown;
|
||||
_getdns_tls_context* ctx;
|
||||
struct mem_funcs* mfs;
|
||||
char* cipher_list;
|
||||
char* cipher_suites;
|
||||
char* curve_list;
|
||||
gnutls_protocol_t min_tls;
|
||||
gnutls_protocol_t max_tls;
|
||||
dane_query_t dane_query;
|
||||
dane_state_t dane_state;
|
||||
char* tlsa;
|
||||
const struct getdns_log_config* log;
|
||||
} _getdns_tls_connection;
|
||||
|
||||
typedef struct _getdns_tls_session {
|
||||
gnutls_datum_t tls;
|
||||
} _getdns_tls_session;
|
||||
|
||||
typedef struct _getdns_tls_x509
|
||||
{
|
||||
gnutls_datum_t tls;
|
||||
} _getdns_tls_x509;
|
||||
|
||||
typedef struct _getdns_tls_hmac
|
||||
{
|
||||
gnutls_hmac_hd_t tls;
|
||||
unsigned int md_len;
|
||||
} _getdns_tls_hmac;
|
||||
|
||||
#endif /* _GETDNS_TLS_INTERNAL_H */
|
|
@ -0,0 +1,903 @@
|
|||
/**
|
||||
*
|
||||
* \file tls.c
|
||||
* @brief getdns TLS functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018-2019, NLnet Labs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <gnutls/x509.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "context.h"
|
||||
|
||||
#include "tls.h"
|
||||
|
||||
/*
|
||||
* Cipher suites recommended in RFC7525.
|
||||
*
|
||||
* The following strings generate a list with the same ciphers that are
|
||||
* generated by the equivalent string in the OpenSSL version of this file.
|
||||
*/
|
||||
static char const * const _getdns_tls_context_default_cipher_list =
|
||||
"+ECDHE-RSA:+ECDHE-ECDSA:+AEAD";
|
||||
|
||||
static char const * const _getdns_tls_context_default_cipher_suites =
|
||||
"+AES-256-GCM:+AES-128-GCM:+CHACHA20-POLY1305";
|
||||
|
||||
static char const * const _getdns_tls_connection_opportunistic_cipher_list =
|
||||
"NORMAL";
|
||||
|
||||
static char const * const _getdns_tls_priorities[] = {
|
||||
NULL, /* No protocol */
|
||||
NULL, /* SSL3 - no available keyword. */
|
||||
"+VERS-TLS1.0", /* TLS1.0 */
|
||||
"+VERS-TLS1.1", /* TLS1.1 */
|
||||
"+VERS-TLS1.2", /* TLS1.2 */
|
||||
"+VERS-TLS1.3", /* TLS1.3 */
|
||||
};
|
||||
|
||||
static char* getdns_strdup(struct mem_funcs* mfs, const char* s)
|
||||
{
|
||||
char* res;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
res = GETDNS_XMALLOC(*mfs, char, strlen(s) + 1);
|
||||
if (!res)
|
||||
return NULL;
|
||||
strcpy(res, s);
|
||||
return res;
|
||||
}
|
||||
|
||||
static char* getdns_priappend(struct mem_funcs* mfs, char* s1, const char* s2)
|
||||
{
|
||||
char* res;
|
||||
|
||||
if (!s1)
|
||||
return getdns_strdup(mfs, s2);
|
||||
if (!s2)
|
||||
return s1;
|
||||
|
||||
res = GETDNS_XMALLOC(*mfs, char, strlen(s1) + strlen(s2) + 2);
|
||||
if (!res)
|
||||
return NULL;
|
||||
strcpy(res, s1);
|
||||
strcat(res, ":");
|
||||
strcat(res, s2);
|
||||
GETDNS_FREE(*mfs, s1);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int set_connection_ciphers(_getdns_tls_connection* conn)
|
||||
{
|
||||
char* pri = NULL;
|
||||
int res;
|
||||
|
||||
pri = getdns_priappend(conn->mfs, pri, "NONE:+COMP-ALL:+SIGN-RSA-SHA384");
|
||||
|
||||
if (conn->cipher_suites)
|
||||
pri = getdns_priappend(conn->mfs, pri, conn->cipher_suites);
|
||||
else if (conn->ctx->cipher_suites)
|
||||
pri = getdns_priappend(conn->mfs, pri, conn->ctx->cipher_suites);
|
||||
|
||||
if (conn->cipher_list)
|
||||
pri = getdns_priappend(conn->mfs, pri, conn->cipher_list);
|
||||
else if (conn->ctx->cipher_list)
|
||||
pri = getdns_priappend(conn->mfs, pri, conn->ctx->cipher_list);
|
||||
|
||||
if (conn->curve_list)
|
||||
pri = getdns_priappend(conn->mfs, pri, conn->curve_list);
|
||||
else if (conn->ctx->curve_list)
|
||||
pri = getdns_priappend(conn->mfs, pri, conn->ctx->curve_list);
|
||||
else
|
||||
pri = getdns_priappend(conn->mfs, pri, "+CURVE-ALL");
|
||||
|
||||
gnutls_protocol_t min = conn->min_tls;
|
||||
gnutls_protocol_t max = conn->max_tls;
|
||||
if (!min) min = conn->ctx->min_tls;
|
||||
if (!max) max = conn->ctx->max_tls;
|
||||
|
||||
if (!min && !max) {
|
||||
pri = getdns_priappend(conn->mfs, pri, "+VERS-TLS-ALL");
|
||||
} else {
|
||||
if (!max) max = GNUTLS_TLS_VERSION_MAX;
|
||||
|
||||
for (gnutls_protocol_t i = min; i <= max; ++i)
|
||||
pri = getdns_priappend(conn->mfs, pri, _getdns_tls_priorities[i]);
|
||||
}
|
||||
|
||||
if (pri) {
|
||||
res = gnutls_priority_set_direct(conn->tls, pri, NULL);
|
||||
if (res != GNUTLS_E_SUCCESS) {
|
||||
_getdns_log(conn->log
|
||||
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
|
||||
, "%s: %s %s (%s)\n"
|
||||
, STUB_DEBUG_SETUP_TLS
|
||||
, "Error configuring TLS connection with "
|
||||
, pri
|
||||
, gnutls_strerror(res));
|
||||
}
|
||||
}
|
||||
else
|
||||
res = gnutls_set_default_priority(conn->tls);
|
||||
GETDNS_FREE(*conn->mfs, pri);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static getdns_return_t error_may_want_read_write(_getdns_tls_connection* conn, int err)
|
||||
{
|
||||
switch (err) {
|
||||
case GNUTLS_E_INTERRUPTED:
|
||||
case GNUTLS_E_AGAIN:
|
||||
case GNUTLS_E_WARNING_ALERT_RECEIVED:
|
||||
case GNUTLS_E_GOT_APPLICATION_DATA:
|
||||
if (gnutls_record_get_direction(conn->tls) == 0)
|
||||
return GETDNS_RETURN_TLS_WANT_READ;
|
||||
else
|
||||
return GETDNS_RETURN_TLS_WANT_WRITE;
|
||||
|
||||
default:
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static getdns_return_t get_gnu_mac_algorithm(int algorithm, gnutls_mac_algorithm_t* gnualg)
|
||||
{
|
||||
switch (algorithm) {
|
||||
case GETDNS_HMAC_MD5 : *gnualg = GNUTLS_MAC_MD5 ; break;
|
||||
case GETDNS_HMAC_SHA1 : *gnualg = GNUTLS_MAC_SHA1 ; break;
|
||||
case GETDNS_HMAC_SHA224: *gnualg = GNUTLS_MAC_SHA224; break;
|
||||
case GETDNS_HMAC_SHA256: *gnualg = GNUTLS_MAC_SHA256; break;
|
||||
case GETDNS_HMAC_SHA384: *gnualg = GNUTLS_MAC_SHA384; break;
|
||||
case GETDNS_HMAC_SHA512: *gnualg = GNUTLS_MAC_SHA512; break;
|
||||
default : return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static gnutls_protocol_t _getdns_tls_version2gnutls_version(getdns_tls_version_t v)
|
||||
{
|
||||
switch (v) {
|
||||
case GETDNS_SSL3 : return GNUTLS_SSL3;
|
||||
case GETDNS_TLS1 : return GNUTLS_TLS1;
|
||||
case GETDNS_TLS1_1: return GNUTLS_TLS1_1;
|
||||
case GETDNS_TLS1_2: return GNUTLS_TLS1_2;
|
||||
#if GNUTLS_VERSION_NUMBER >= 0x030605
|
||||
case GETDNS_TLS1_3: return GNUTLS_TLS1_3;
|
||||
#endif
|
||||
default : return GNUTLS_TLS_VERSION_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static _getdns_tls_x509* _getdns_tls_x509_new(struct mem_funcs* mfs, gnutls_datum_t cert)
|
||||
{
|
||||
_getdns_tls_x509* res;
|
||||
|
||||
res = GETDNS_MALLOC(*mfs, _getdns_tls_x509);
|
||||
if (res)
|
||||
res->tls = cert;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void _getdns_tls_init()
|
||||
{
|
||||
gnutls_global_init();
|
||||
}
|
||||
|
||||
_getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs, const getdns_log_config* log)
|
||||
{
|
||||
_getdns_tls_context* res;
|
||||
|
||||
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_context)))
|
||||
return NULL;
|
||||
|
||||
res->mfs = mfs;
|
||||
res->cipher_list = res->cipher_suites = res->curve_list = NULL;
|
||||
res->min_tls = res->max_tls = 0;
|
||||
res->ca_trust_file = NULL;
|
||||
res->ca_trust_path = NULL;
|
||||
res->log = log;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_context_free(struct mem_funcs* mfs, _getdns_tls_context* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
GETDNS_FREE(*mfs, ctx->ca_trust_path);
|
||||
GETDNS_FREE(*mfs, ctx->ca_trust_file);
|
||||
GETDNS_FREE(*mfs, ctx->curve_list);
|
||||
GETDNS_FREE(*mfs, ctx->cipher_suites);
|
||||
GETDNS_FREE(*mfs, ctx->cipher_list);
|
||||
GETDNS_FREE(*mfs, ctx);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx)
|
||||
{
|
||||
(void) ctx;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_context_set_min_max_tls_version(_getdns_tls_context* ctx, getdns_tls_version_t min, getdns_tls_version_t max)
|
||||
{
|
||||
if (!ctx)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
ctx->min_tls = _getdns_tls_version2gnutls_version(min);
|
||||
ctx->max_tls = _getdns_tls_version2gnutls_version(max);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
const char* _getdns_tls_context_get_default_cipher_list()
|
||||
{
|
||||
return _getdns_tls_context_default_cipher_list;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list)
|
||||
{
|
||||
if (!ctx)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (!list)
|
||||
list = _getdns_tls_context_default_cipher_list;
|
||||
|
||||
GETDNS_FREE(*ctx->mfs, ctx->cipher_list);
|
||||
ctx->cipher_list = getdns_strdup(ctx->mfs, list);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
const char* _getdns_tls_context_get_default_cipher_suites()
|
||||
{
|
||||
return _getdns_tls_context_default_cipher_suites;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_context_set_cipher_suites(_getdns_tls_context* ctx, const char* list)
|
||||
{
|
||||
if (!ctx)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (!list)
|
||||
list = _getdns_tls_context_default_cipher_suites;
|
||||
|
||||
GETDNS_FREE(*ctx->mfs, ctx->cipher_suites);
|
||||
ctx->cipher_suites = getdns_strdup(ctx->mfs, list);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_context_set_curves_list(_getdns_tls_context* ctx, const char* list)
|
||||
{
|
||||
if (!ctx)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
GETDNS_FREE(*ctx->mfs, ctx->curve_list);
|
||||
ctx->curve_list = getdns_strdup(ctx->mfs, list);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char* file, const char* path)
|
||||
{
|
||||
if (!ctx)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
GETDNS_FREE(*ctx->mfs, ctx->ca_trust_file);
|
||||
ctx->ca_trust_file = getdns_strdup(ctx->mfs, file);
|
||||
GETDNS_FREE(*ctx->mfs, ctx->ca_trust_path);
|
||||
ctx->ca_trust_path = getdns_strdup(ctx->mfs, path);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
_getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd, const getdns_log_config* log)
|
||||
{
|
||||
_getdns_tls_connection* res;
|
||||
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_connection)))
|
||||
return NULL;
|
||||
|
||||
res->shutdown = 0;
|
||||
res->ctx = ctx;
|
||||
res->mfs = mfs;
|
||||
res->cred = NULL;
|
||||
res->tls = NULL;
|
||||
res->cipher_list = res->cipher_suites = res->curve_list = NULL;
|
||||
res->min_tls = res->max_tls = 0;
|
||||
res->dane_state = NULL;
|
||||
res->dane_query = NULL;
|
||||
res->tlsa = NULL;
|
||||
res->log = log;
|
||||
|
||||
if (gnutls_certificate_allocate_credentials(&res->cred) != GNUTLS_E_SUCCESS)
|
||||
goto failed;
|
||||
|
||||
if (!ctx->ca_trust_file && !ctx->ca_trust_path)
|
||||
gnutls_certificate_set_x509_system_trust(res->cred);
|
||||
else {
|
||||
if (ctx->ca_trust_file)
|
||||
gnutls_certificate_set_x509_trust_file(res->cred, ctx->ca_trust_file, GNUTLS_X509_FMT_PEM);
|
||||
if (ctx->ca_trust_path)
|
||||
gnutls_certificate_set_x509_trust_dir(res->cred, ctx->ca_trust_path, GNUTLS_X509_FMT_PEM);
|
||||
}
|
||||
|
||||
if (gnutls_init(&res->tls, GNUTLS_CLIENT | GNUTLS_NONBLOCK) != GNUTLS_E_SUCCESS)
|
||||
goto failed;
|
||||
if (set_connection_ciphers(res) != GNUTLS_E_SUCCESS) {
|
||||
|
||||
goto failed;
|
||||
}
|
||||
if (gnutls_credentials_set(res->tls, GNUTLS_CRD_CERTIFICATE, res->cred) != GNUTLS_E_SUCCESS)
|
||||
goto failed;
|
||||
if (dane_state_init(&res->dane_state, DANE_F_IGNORE_DNSSEC) != DANE_E_SUCCESS)
|
||||
goto failed;
|
||||
|
||||
gnutls_transport_set_int(res->tls, fd);
|
||||
return res;
|
||||
|
||||
failed:
|
||||
_getdns_tls_connection_free(mfs, res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_free(struct mem_funcs* mfs, _getdns_tls_connection* conn)
|
||||
{
|
||||
if (!conn || !conn->tls)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (conn->dane_query)
|
||||
dane_query_deinit(conn->dane_query);
|
||||
if (conn->dane_state)
|
||||
dane_state_deinit(conn->dane_state);
|
||||
if (conn->tls)
|
||||
gnutls_deinit(conn->tls);
|
||||
if (conn->cred)
|
||||
gnutls_certificate_free_credentials(conn->cred);
|
||||
GETDNS_FREE(*mfs, conn->tlsa);
|
||||
GETDNS_FREE(*mfs, conn->curve_list);
|
||||
GETDNS_FREE(*mfs, conn->cipher_suites);
|
||||
GETDNS_FREE(*mfs, conn->cipher_list);
|
||||
GETDNS_FREE(*mfs, conn);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn)
|
||||
{
|
||||
if (!conn || !conn->tls)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (conn->shutdown == 0) {
|
||||
gnutls_bye(conn->tls, GNUTLS_SHUT_WR);
|
||||
conn->shutdown++;
|
||||
} else {
|
||||
gnutls_bye(conn->tls, GNUTLS_SHUT_RDWR);
|
||||
conn->shutdown++;
|
||||
}
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_set_min_max_tls_version(_getdns_tls_connection* conn, getdns_tls_version_t min, getdns_tls_version_t max)
|
||||
{
|
||||
if (!conn)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
conn->min_tls = _getdns_tls_version2gnutls_version(min);
|
||||
conn->max_tls = _getdns_tls_version2gnutls_version(max);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list)
|
||||
{
|
||||
if (!conn || !conn->tls)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (!list)
|
||||
list = _getdns_tls_connection_opportunistic_cipher_list;
|
||||
|
||||
GETDNS_FREE(*conn->mfs, conn->cipher_list);
|
||||
conn->cipher_list = getdns_strdup(conn->mfs, list);
|
||||
if (set_connection_ciphers(conn) == GNUTLS_E_SUCCESS)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
else
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_set_cipher_suites(_getdns_tls_connection* conn, const char* list)
|
||||
{
|
||||
if (!conn || !conn->tls)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
GETDNS_FREE(*conn->mfs, conn->cipher_list);
|
||||
conn->cipher_suites = getdns_strdup(conn->mfs, list);
|
||||
if (set_connection_ciphers(conn) == GNUTLS_E_SUCCESS)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
else
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_set_curves_list(_getdns_tls_connection* conn, const char* list)
|
||||
{
|
||||
if (!conn || !conn->tls)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
GETDNS_FREE(*conn->mfs, conn->curve_list);
|
||||
conn->curve_list = getdns_strdup(conn->mfs, list);
|
||||
if (set_connection_ciphers(conn) == GNUTLS_E_SUCCESS)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
else
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_set_session(_getdns_tls_connection* conn, _getdns_tls_session* s)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!conn || !conn->tls || !s)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
r = gnutls_session_set_data(conn->tls, s->tls.data, s->tls.size);
|
||||
if (r != GNUTLS_E_SUCCESS)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
_getdns_tls_session* _getdns_tls_connection_get_session(struct mem_funcs* mfs, _getdns_tls_connection* conn)
|
||||
{
|
||||
_getdns_tls_session* res;
|
||||
int r;
|
||||
|
||||
if (!conn || !conn->tls)
|
||||
return NULL;
|
||||
|
||||
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_session)))
|
||||
return NULL;
|
||||
|
||||
r = gnutls_session_get_data2(conn->tls, &res->tls);
|
||||
if (r != GNUTLS_E_SUCCESS) {
|
||||
GETDNS_FREE(*mfs, res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const char* _getdns_tls_connection_get_version(_getdns_tls_connection* conn)
|
||||
{
|
||||
if (!conn || !conn->tls)
|
||||
return NULL;
|
||||
|
||||
return gnutls_protocol_get_name(gnutls_protocol_get_version(conn->tls));
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_do_handshake(_getdns_tls_connection* conn)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!conn || !conn->tls)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
r = gnutls_handshake(conn->tls);
|
||||
if (r == GNUTLS_E_SUCCESS) {
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
else
|
||||
return error_may_want_read_write(conn, r);
|
||||
}
|
||||
|
||||
_getdns_tls_x509* _getdns_tls_connection_get_peer_certificate(struct mem_funcs* mfs, _getdns_tls_connection* conn)
|
||||
{
|
||||
const gnutls_datum_t *cert_list;
|
||||
unsigned int cert_list_size;
|
||||
|
||||
if (!conn || !conn->tls)
|
||||
return NULL;
|
||||
|
||||
cert_list = gnutls_certificate_get_peers(conn->tls, &cert_list_size);
|
||||
if (cert_list == NULL)
|
||||
return NULL;
|
||||
|
||||
return _getdns_tls_x509_new(mfs, *cert_list);
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_is_session_reused(_getdns_tls_connection* conn)
|
||||
{
|
||||
if (!conn || !conn->tls)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (gnutls_session_is_resumed(conn->tls) != 0)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
else
|
||||
return GETDNS_RETURN_TLS_CONNECTION_FRESH;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_setup_hostname_auth(_getdns_tls_connection* conn, const char* auth_name)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!conn || !conn->tls || !auth_name)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
r = gnutls_server_name_set(conn->tls, GNUTLS_NAME_DNS, auth_name, strlen(auth_name));
|
||||
if (r != GNUTLS_E_SUCCESS)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
gnutls_session_set_verify_cert(conn->tls, auth_name, 0);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_set_host_pinset(_getdns_tls_connection* conn, const char* auth_name, const sha256_pin_t* pinset)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!conn || !conn->tls || !auth_name)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
size_t npins = 0;
|
||||
for (const sha256_pin_t* pin = pinset; pin; pin = pin->next)
|
||||
npins++;
|
||||
|
||||
GETDNS_FREE(*conn->mfs, conn->tlsa);
|
||||
conn->tlsa = GETDNS_XMALLOC(*conn->mfs, char, npins * (SHA256_DIGEST_LENGTH + 3) * 2);
|
||||
if (!conn->tlsa)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
char** dane_data = GETDNS_XMALLOC(*conn->mfs, char*, npins * 2 + 1);
|
||||
if (!dane_data)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
int* dane_data_len = GETDNS_XMALLOC(*conn->mfs, int, npins * 2 + 1);
|
||||
if (!dane_data_len) {
|
||||
GETDNS_FREE(*conn->mfs, dane_data);
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
char** dane_p = dane_data;
|
||||
int* dane_len_p = dane_data_len;
|
||||
char* p = conn->tlsa;
|
||||
for (const sha256_pin_t* pin = pinset; pin; pin = pin->next) {
|
||||
*dane_p++ = p;
|
||||
*dane_len_p++ = SHA256_DIGEST_LENGTH + 3;
|
||||
p[0] = DANE_CERT_USAGE_LOCAL_CA;
|
||||
p[1] = DANE_CERT_PK;
|
||||
p[2] = DANE_MATCH_SHA2_256;
|
||||
memcpy(&p[3], pin->pin, SHA256_DIGEST_LENGTH);
|
||||
p += SHA256_DIGEST_LENGTH + 3;
|
||||
|
||||
*dane_p++ = p;
|
||||
*dane_len_p++ = SHA256_DIGEST_LENGTH + 3;
|
||||
p[0] = DANE_CERT_USAGE_LOCAL_EE;
|
||||
p[1] = DANE_CERT_PK;
|
||||
p[2] = DANE_MATCH_SHA2_256;
|
||||
memcpy(&p[3], pin->pin, SHA256_DIGEST_LENGTH);
|
||||
p += SHA256_DIGEST_LENGTH + 3;
|
||||
}
|
||||
*dane_p = NULL;
|
||||
|
||||
if (conn->dane_query)
|
||||
dane_query_deinit(conn->dane_query);
|
||||
r = dane_raw_tlsa(conn->dane_state, &conn->dane_query, dane_data, dane_data_len, 0, 0);
|
||||
GETDNS_FREE(*conn->mfs, dane_data_len);
|
||||
GETDNS_FREE(*conn->mfs, dane_data);
|
||||
|
||||
return (r == DANE_E_SUCCESS) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_certificate_verify(_getdns_tls_connection* conn, long* errnum, const char** errmsg)
|
||||
{
|
||||
if (!conn || !conn->tls)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
/* If no pinset, no DANE info to check. */
|
||||
if (!conn->dane_query)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
|
||||
/* Most of the internals of dane_verify_session_crt() */
|
||||
|
||||
const gnutls_datum_t* cert_list;
|
||||
unsigned int cert_list_size = 0;
|
||||
unsigned int type;
|
||||
int ret;
|
||||
const gnutls_datum_t* cl;
|
||||
gnutls_datum_t* new_cert_list = NULL;
|
||||
int clsize;
|
||||
unsigned int verify;
|
||||
|
||||
cert_list = gnutls_certificate_get_peers(conn->tls, &cert_list_size);
|
||||
if (cert_list_size == 0) {
|
||||
*errnum = 1;
|
||||
*errmsg = "No peer certificate";
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
cl = cert_list;
|
||||
|
||||
type = gnutls_certificate_type_get(conn->tls);
|
||||
|
||||
/* this list may be incomplete, try to get the self-signed CA if any */
|
||||
if (cert_list_size > 0) {
|
||||
gnutls_x509_crt_t crt, ca;
|
||||
gnutls_certificate_credentials_t sc;
|
||||
|
||||
ret = gnutls_x509_crt_init(&crt);
|
||||
if (ret < 0)
|
||||
goto failsafe;
|
||||
|
||||
ret = gnutls_x509_crt_import(crt, &cert_list[cert_list_size-1], GNUTLS_X509_FMT_DER);
|
||||
if (ret < 0) {
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
goto failsafe;
|
||||
}
|
||||
|
||||
/* if it is already self signed continue normally */
|
||||
ret = gnutls_x509_crt_check_issuer(crt, crt);
|
||||
if (ret != 0) {
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
goto failsafe;
|
||||
}
|
||||
|
||||
/* chain does not finish in a self signed cert, try to obtain the issuer */
|
||||
ret = gnutls_credentials_get(conn->tls, GNUTLS_CRD_CERTIFICATE, (void**)&sc);
|
||||
if (ret < 0) {
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
goto failsafe;
|
||||
}
|
||||
|
||||
ret = gnutls_certificate_get_issuer(sc, crt, &ca, 0);
|
||||
if (ret < 0) {
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
goto failsafe;
|
||||
}
|
||||
|
||||
/* make the new list */
|
||||
new_cert_list = GETDNS_XMALLOC(*conn->mfs, gnutls_datum_t, cert_list_size + 1);
|
||||
if (new_cert_list == NULL) {
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
goto failsafe;
|
||||
}
|
||||
|
||||
memcpy(new_cert_list, cert_list, cert_list_size*sizeof(gnutls_datum_t));
|
||||
cl = new_cert_list;
|
||||
|
||||
ret = gnutls_x509_crt_export2(ca, GNUTLS_X509_FMT_DER, &new_cert_list[cert_list_size]);
|
||||
if (ret < 0) {
|
||||
GETDNS_FREE(*conn->mfs, new_cert_list);
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
goto failsafe;
|
||||
}
|
||||
}
|
||||
|
||||
failsafe:
|
||||
|
||||
clsize = cert_list_size;
|
||||
if (cl == new_cert_list)
|
||||
clsize += 1;
|
||||
|
||||
ret = dane_verify_crt_raw(conn->dane_state, cl, clsize, type, conn->dane_query, 0, 0, &verify);
|
||||
|
||||
if (new_cert_list) {
|
||||
gnutls_free(new_cert_list[cert_list_size].data);
|
||||
GETDNS_FREE(*conn->mfs, new_cert_list);
|
||||
}
|
||||
|
||||
if (ret != DANE_E_SUCCESS)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
if (verify != 0) {
|
||||
if (verify & DANE_VERIFY_CERT_DIFFERS) {
|
||||
*errnum = 3;
|
||||
*errmsg = "Pinset validation: Certificate differs";
|
||||
} else if (verify & DANE_VERIFY_CA_CONSTRAINTS_VIOLATED) {
|
||||
*errnum = 2;
|
||||
*errmsg = "Pinset validation: CA constraints violated";
|
||||
} else {
|
||||
*errnum = 4;
|
||||
*errmsg = "Pinset validation: Unknown DANE info";
|
||||
}
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
|
||||
getdns_return_t _getdns_tls_connection_read(_getdns_tls_connection* conn, uint8_t* buf, size_t to_read, size_t* read)
|
||||
{
|
||||
ssize_t sread;
|
||||
|
||||
if (!conn || !conn->tls || !read)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
sread = gnutls_record_recv(conn->tls, buf, to_read);
|
||||
if (sread < 0)
|
||||
return error_may_want_read_write(conn, sread);
|
||||
|
||||
*read = sread;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_write(_getdns_tls_connection* conn, uint8_t* buf, size_t to_write, size_t* written)
|
||||
{
|
||||
int swritten;
|
||||
|
||||
if (!conn || !conn->tls || !written)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
swritten = gnutls_record_send(conn->tls, buf, to_write);
|
||||
if (swritten < 0)
|
||||
return error_may_want_read_write(conn, swritten);
|
||||
|
||||
*written = swritten;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_session_free(struct mem_funcs* mfs, _getdns_tls_session* s)
|
||||
{
|
||||
if (!s)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
GETDNS_FREE(*mfs, s);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_get_api_information(getdns_dict* dict)
|
||||
{
|
||||
if (! getdns_dict_set_int(
|
||||
dict, "gnutls_version_number", GNUTLS_VERSION_NUMBER)
|
||||
|
||||
&& ! getdns_dict_util_set_string(
|
||||
dict, "gnutls_version_string", GNUTLS_VERSION)
|
||||
)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
void _getdns_tls_x509_free(struct mem_funcs* mfs, _getdns_tls_x509* cert)
|
||||
{
|
||||
if (cert)
|
||||
GETDNS_FREE(*mfs, cert);
|
||||
}
|
||||
|
||||
int _getdns_tls_x509_to_der(struct mem_funcs* mfs, _getdns_tls_x509* cert, getdns_bindata* bindata)
|
||||
{
|
||||
gnutls_x509_crt_t crt;
|
||||
size_t s;
|
||||
|
||||
if (!cert || gnutls_x509_crt_init(&crt) != GNUTLS_E_SUCCESS)
|
||||
return 0;
|
||||
|
||||
gnutls_x509_crt_import(crt, &cert->tls, GNUTLS_X509_FMT_DER);
|
||||
gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL, &s);
|
||||
|
||||
if (!bindata) {
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
return s;
|
||||
}
|
||||
|
||||
bindata->data = GETDNS_XMALLOC(*mfs, uint8_t, s);
|
||||
if (!bindata->data) {
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, bindata->data, &s);
|
||||
bindata->size = s;
|
||||
gnutls_x509_crt_deinit(crt);
|
||||
return s;
|
||||
}
|
||||
|
||||
unsigned char* _getdns_tls_hmac_hash(struct mem_funcs* mfs, int algorithm, const void* key, size_t key_size, const void* data, size_t data_size, size_t* output_size)
|
||||
{
|
||||
gnutls_mac_algorithm_t alg;
|
||||
unsigned int md_len;
|
||||
unsigned char* res;
|
||||
|
||||
if (get_gnu_mac_algorithm(algorithm, &alg) != GETDNS_RETURN_GOOD)
|
||||
return NULL;
|
||||
|
||||
md_len = gnutls_hmac_get_len(alg);
|
||||
res = (unsigned char*) GETDNS_XMALLOC(*mfs, unsigned char, md_len);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
(void) gnutls_hmac_fast(alg, key, key_size, data, data_size, res);
|
||||
|
||||
if (output_size)
|
||||
*output_size = md_len;
|
||||
return res;
|
||||
}
|
||||
|
||||
_getdns_tls_hmac* _getdns_tls_hmac_new(struct mem_funcs* mfs, int algorithm, const void* key, size_t key_size)
|
||||
{
|
||||
gnutls_mac_algorithm_t alg;
|
||||
_getdns_tls_hmac* res;
|
||||
|
||||
if (get_gnu_mac_algorithm(algorithm, &alg) != GETDNS_RETURN_GOOD)
|
||||
return NULL;
|
||||
|
||||
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_hmac)))
|
||||
return NULL;
|
||||
|
||||
if (gnutls_hmac_init(&res->tls, alg, key, key_size) < 0) {
|
||||
GETDNS_FREE(*mfs, res);
|
||||
return NULL;
|
||||
}
|
||||
res->md_len = gnutls_hmac_get_len(alg);
|
||||
return res;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_hmac_add(_getdns_tls_hmac* h, const void* data, size_t data_size)
|
||||
{
|
||||
if (!h || !h->tls || !data)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (gnutls_hmac(h->tls, data, data_size) < 0)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
else
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
unsigned char* _getdns_tls_hmac_end(struct mem_funcs* mfs, _getdns_tls_hmac* h, size_t* output_size)
|
||||
{
|
||||
unsigned char* res;
|
||||
|
||||
if (!h || !h->tls)
|
||||
return NULL;
|
||||
|
||||
res = (unsigned char*) GETDNS_XMALLOC(*mfs, unsigned char, h->md_len);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
gnutls_hmac_deinit(h->tls, res);
|
||||
if (output_size)
|
||||
*output_size = h->md_len;
|
||||
|
||||
GETDNS_FREE(*mfs, h);
|
||||
return res;
|
||||
}
|
||||
|
||||
void _getdns_tls_sha1(const void* data, size_t data_size, unsigned char* buf)
|
||||
{
|
||||
gnutls_hash_fast(GNUTLS_DIG_SHA1, data, data_size, buf);
|
||||
}
|
||||
|
||||
void _getdns_tls_cookie_sha256(uint32_t secret, void* addr, size_t addrlen, unsigned char* buf, size_t* buflen)
|
||||
{
|
||||
gnutls_hash_hd_t digest;
|
||||
|
||||
gnutls_hash_init(&digest, GNUTLS_DIG_SHA256);
|
||||
gnutls_hash(digest, &secret, sizeof(secret));
|
||||
gnutls_hash(digest, addr, addrlen);
|
||||
gnutls_hash_deinit(digest, buf);
|
||||
*buflen = gnutls_hash_get_len(GNUTLS_DIG_SHA256);
|
||||
}
|
||||
|
||||
/* tls.c */
|
|
@ -36,8 +36,13 @@ getdns_context_get_tls_backoff_time
|
|||
getdns_context_get_tls_ca_file
|
||||
getdns_context_get_tls_ca_path
|
||||
getdns_context_get_tls_cipher_list
|
||||
getdns_context_get_tls_ciphersuites
|
||||
getdns_context_get_tls_connection_retries
|
||||
getdns_context_get_tls_curves_list
|
||||
getdns_context_get_tls_max_version
|
||||
getdns_context_get_tls_min_version
|
||||
getdns_context_get_tls_query_padding_blocksize
|
||||
getdns_context_get_trust_anchors_backoff_time
|
||||
getdns_context_get_trust_anchors_url
|
||||
getdns_context_get_trust_anchors_verify_CA
|
||||
getdns_context_get_trust_anchors_verify_email
|
||||
|
@ -79,8 +84,13 @@ getdns_context_set_tls_backoff_time
|
|||
getdns_context_set_tls_ca_file
|
||||
getdns_context_set_tls_ca_path
|
||||
getdns_context_set_tls_cipher_list
|
||||
getdns_context_set_tls_ciphersuites
|
||||
getdns_context_set_tls_connection_retries
|
||||
getdns_context_set_tls_curves_list
|
||||
getdns_context_set_tls_max_version
|
||||
getdns_context_set_tls_min_version
|
||||
getdns_context_set_tls_query_padding_blocksize
|
||||
getdns_context_set_trust_anchors_backoff_time
|
||||
getdns_context_set_trust_anchors_url
|
||||
getdns_context_set_trust_anchors_verify_CA
|
||||
getdns_context_set_trust_anchors_verify_email
|
||||
|
|
|
@ -418,7 +418,7 @@ getdns_list_create_with_memory_functions(void *(*malloc)(size_t),
|
|||
|
||||
/*-------------------------- getdns_list_create_with_context */
|
||||
struct getdns_list *
|
||||
getdns_list_create_with_context(struct getdns_context *context)
|
||||
getdns_list_create_with_context(const getdns_context *context)
|
||||
{
|
||||
if (context)
|
||||
return getdns_list_create_with_extended_memory_functions(
|
||||
|
|
|
@ -1638,7 +1638,7 @@ void _getdns_mdns_context_destroy(struct getdns_context *context)
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO: actualy delete what is required.. */
|
||||
/* TODO: actually delete what is required.. */
|
||||
static void
|
||||
mdns_cleanup(getdns_network_req *netreq)
|
||||
{
|
||||
|
|
|
@ -59,7 +59,7 @@ typedef struct getdns_mdns_known_record
|
|||
* The data part contains:
|
||||
* - 64 bit time stamp
|
||||
* - 32 bit word describing the record size
|
||||
* - 32 bit word describing teh allocated memory size
|
||||
* - 32 bit word describing the allocated memory size
|
||||
* - valid DNS response, including 1 query and N answers, 0 AUTH, 0 AD.
|
||||
* For economy, the names of all answers are encoded using header compression, pointing
|
||||
* to the name in the query, i.e. offset 12 from beginning of message.
|
||||
|
|
|
@ -14,7 +14,7 @@ cat > const-info.c << END_OF_HEAD
|
|||
static struct const_info consts_info[] = {
|
||||
{ -1, NULL, "/* <unknown getdns value> */" },
|
||||
END_OF_HEAD
|
||||
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%7d", $3); consts[key] = $1; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/^#define GETDNS_RRTYPE/ && !/^#define GETDNS_RRCLASS/ && !/^#define GETDNS_OPCODE/ && !/^#define GETDNS_RCODE/ && !/_TEXT/{ key = sprintf("%7d", $3); consts[key] = $2; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%7d", $4); consts[key] = $2; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ "val", \""name"\", "name"_TEXT },"}}' getdns/getdns_extra.h.in getdns/getdns.h.in | sed 's/,,/,/g' >> const-info.c
|
||||
gawk --non-decimal-data '/^[ ]+GETDNS_[A-Z0-9_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%7d", $3); consts[key] = $1; }/^#define GETDNS_[A-Z0-9_]+[ ]+(0[xX][0-9a-fA-F]+|[0-9]+)/ && !/^#define GETDNS_RRTYPE/ && !/^#define GETDNS_RRCLASS/ && !/^#define GETDNS_OPCODE/ && !/^#define GETDNS_RCODE/ && !/_TEXT/{ key = sprintf("%7d", $3); consts[key] = $2; }/^#define GETDNS_[A-Z0-9_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%7d", $4); consts[key] = $2; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ "val", \""name"\", "name"_TEXT },"}}' getdns/getdns_extra.h.in getdns/getdns.h.in const-info.h| sed 's/,,/,/g' >> const-info.c
|
||||
cat >> const-info.c << END_OF_TAIL
|
||||
};
|
||||
|
||||
|
@ -49,7 +49,7 @@ getdns_get_errorstr_by_id(uint16_t err)
|
|||
|
||||
static struct const_name_info consts_name_info[] = {
|
||||
END_OF_TAIL
|
||||
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%d", $3); consts[$1] = key; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/_TEXT/{ key = sprintf("%d", $3); consts[$2] = key; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%d", $4); consts[$2] = key; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ \""val"\", "name" },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in | sed 's/,,/,/g' >> const-info.c
|
||||
gawk --non-decimal-data '/^[ ]+GETDNS_[A-Z0-9_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%d", $3); consts[$1] = key; }/^#define GETDNS_[A-Z0-9_]+[ ]+(0[xX][0-9a-fA-F]+|[0-9]+)/ && !/_TEXT/{ key = sprintf("%d", $3); consts[$2] = key; }/^#define GETDNS_[A-Z0-9_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%d", $4); consts[$2] = key; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ \""val"\", "name" },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in const-info.h| sed 's/,,/,/g' >> const-info.c
|
||||
cat >> const-info.c << END_OF_TAIL
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
write_symbols() {
|
||||
OUTPUT=$1
|
||||
shift
|
||||
grep 'getdns_[0-9a-zA-Z_]*(' $* | grep -v '^#' | grep -v 'INLINE' | grep -v 'getdns_extra\.h\.in: \* if' \
|
||||
grep -h 'getdns_[0-9a-zA-Z_]*(' $* | grep -v '^#' | grep -v 'INLINE' | grep -v '^ \* if' \
|
||||
| sed -e 's/(.*$//g' -e 's/^.*getdns_/getdns_/g' | LC_ALL=C sort | uniq > $OUTPUT
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* keyraw.c - raw key operations and conversions - OpenSSL version
|
||||
*
|
||||
* (c) NLnet Labs, 2004-2008
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Implementation of raw DNSKEY functions (work on wire rdata).
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "gldns/keyraw.h"
|
||||
#include "gldns/rrdef.h"
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md5.h>
|
||||
#ifdef HAVE_OPENSSL_CONF_H
|
||||
# include <openssl/conf.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
# include <openssl/engine.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_BN_H
|
||||
#include <openssl/bn.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_RSA_H
|
||||
#include <openssl/rsa.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_DSA_H
|
||||
#include <openssl/dsa.h>
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef USE_GOST
|
||||
|
||||
/** store GOST engine reference loaded into OpenSSL library */
|
||||
#ifdef OPENSSL_NO_ENGINE
|
||||
int
|
||||
gldns_key_EVP_load_gost_id(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void gldns_key_EVP_unload_gost(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
ENGINE* gldns_gost_engine = NULL;
|
||||
|
||||
int
|
||||
gldns_key_EVP_load_gost_id(void)
|
||||
{
|
||||
static int gost_id = 0;
|
||||
const EVP_PKEY_ASN1_METHOD* meth;
|
||||
ENGINE* e;
|
||||
|
||||
if(gost_id) return gost_id;
|
||||
|
||||
/* see if configuration loaded gost implementation from other engine*/
|
||||
meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
|
||||
if(meth) {
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
|
||||
/* see if engine can be loaded already */
|
||||
e = ENGINE_by_id("gost");
|
||||
if(!e) {
|
||||
/* load it ourself, in case statically linked */
|
||||
ENGINE_load_builtin_engines();
|
||||
ENGINE_load_dynamic();
|
||||
e = ENGINE_by_id("gost");
|
||||
}
|
||||
if(!e) {
|
||||
/* no gost engine in openssl */
|
||||
return 0;
|
||||
}
|
||||
if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
|
||||
if(!meth) {
|
||||
/* algo not found */
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
/* Note: do not ENGINE_finish and ENGINE_free the acquired engine
|
||||
* on some platforms this frees up the meth and unloads gost stuff */
|
||||
gldns_gost_engine = e;
|
||||
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
|
||||
void gldns_key_EVP_unload_gost(void)
|
||||
{
|
||||
if(gldns_gost_engine) {
|
||||
ENGINE_finish(gldns_gost_engine);
|
||||
ENGINE_free(gldns_gost_engine);
|
||||
gldns_gost_engine = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* ifndef OPENSSL_NO_ENGINE */
|
||||
#endif /* USE_GOST */
|
||||
|
||||
DSA *
|
||||
gldns_key_buf2dsa_raw(unsigned char* key, size_t len)
|
||||
{
|
||||
uint8_t T;
|
||||
uint16_t length;
|
||||
uint16_t offset;
|
||||
DSA *dsa;
|
||||
BIGNUM *Q; BIGNUM *P;
|
||||
BIGNUM *G; BIGNUM *Y;
|
||||
|
||||
if(len == 0)
|
||||
return NULL;
|
||||
T = (uint8_t)key[0];
|
||||
length = (64 + T * 8);
|
||||
offset = 1;
|
||||
|
||||
if (T > 8) {
|
||||
return NULL;
|
||||
}
|
||||
if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
|
||||
return NULL;
|
||||
|
||||
Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
|
||||
offset += SHA_DIGEST_LENGTH;
|
||||
|
||||
P = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
offset += length;
|
||||
|
||||
G = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
offset += length;
|
||||
|
||||
Y = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
|
||||
/* create the key and set its properties */
|
||||
if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
|
||||
BN_free(Q);
|
||||
BN_free(P);
|
||||
BN_free(G);
|
||||
BN_free(Y);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(HAVE_DSA_SET0_PQG) && defined(HAVE_DSA_SET0_KEY)
|
||||
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;
|
||||
}
|
||||
#else
|
||||
# ifndef S_SPLINT_S
|
||||
dsa->p = P;
|
||||
dsa->q = Q;
|
||||
dsa->g = G;
|
||||
dsa->pub_key = Y;
|
||||
# endif /* splint */
|
||||
#endif
|
||||
|
||||
return dsa;
|
||||
}
|
||||
|
||||
RSA *
|
||||
gldns_key_buf2rsa_raw(unsigned char* key, size_t len)
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t exp;
|
||||
uint16_t int16;
|
||||
RSA *rsa;
|
||||
BIGNUM *modulus;
|
||||
BIGNUM *exponent;
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
if (key[0] == 0) {
|
||||
if(len < 3)
|
||||
return NULL;
|
||||
memmove(&int16, key+1, 2);
|
||||
exp = ntohs(int16);
|
||||
offset = 3;
|
||||
} else {
|
||||
exp = key[0];
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
/* key length at least one */
|
||||
if(len < (size_t)offset + exp + 1)
|
||||
return NULL;
|
||||
|
||||
/* Exponent */
|
||||
exponent = BN_new();
|
||||
if(!exponent) return NULL;
|
||||
(void) BN_bin2bn(key+offset, (int)exp, exponent);
|
||||
offset += exp;
|
||||
|
||||
/* Modulus */
|
||||
modulus = BN_new();
|
||||
if(!modulus) {
|
||||
BN_free(exponent);
|
||||
return NULL;
|
||||
}
|
||||
/* length of the buffer must match the key length! */
|
||||
(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
|
||||
|
||||
rsa = RSA_new();
|
||||
if(!rsa) {
|
||||
BN_free(exponent);
|
||||
BN_free(modulus);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(HAVE_RSA_SET0_KEY)
|
||||
if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
|
||||
BN_free(exponent);
|
||||
BN_free(modulus);
|
||||
RSA_free(rsa);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
# ifndef S_SPLINT_S
|
||||
rsa->n = modulus;
|
||||
rsa->e = exponent;
|
||||
# endif /* splint */
|
||||
#endif
|
||||
|
||||
return rsa;
|
||||
}
|
||||
|
||||
#ifdef USE_GOST
|
||||
EVP_PKEY*
|
||||
gldns_gost2pkey_raw(unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* prefix header for X509 encoding */
|
||||
uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
|
||||
0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
|
||||
unsigned char encoded[37+64];
|
||||
const unsigned char* pp;
|
||||
if(keylen != 64) {
|
||||
/* key wrong size */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create evp_key */
|
||||
memmove(encoded, asn, 37);
|
||||
memmove(encoded+37, key, 64);
|
||||
pp = (unsigned char*)&encoded[0];
|
||||
|
||||
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
|
||||
}
|
||||
#endif /* USE_GOST */
|
||||
|
||||
#ifdef USE_ECDSA
|
||||
EVP_PKEY*
|
||||
gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
|
||||
{
|
||||
unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
|
||||
const unsigned char* pp = buf;
|
||||
EVP_PKEY *evp_key;
|
||||
EC_KEY *ec;
|
||||
/* check length, which uncompressed must be 2 bignums */
|
||||
if(algo == GLDNS_ECDSAP256SHA256) {
|
||||
if(keylen != 2*256/8) return NULL;
|
||||
ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
} else if(algo == GLDNS_ECDSAP384SHA384) {
|
||||
if(keylen != 2*384/8) return NULL;
|
||||
ec = EC_KEY_new_by_curve_name(NID_secp384r1);
|
||||
} else ec = NULL;
|
||||
if(!ec) return NULL;
|
||||
if(keylen+1 > sizeof(buf)) { /* sanity check */
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
|
||||
* of openssl) for uncompressed data */
|
||||
buf[0] = POINT_CONVERSION_UNCOMPRESSED;
|
||||
memmove(buf+1, key, keylen);
|
||||
if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
evp_key = EVP_PKEY_new();
|
||||
if(!evp_key) {
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
|
||||
EVP_PKEY_free(evp_key);
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ECDSA */
|
||||
|
||||
#ifdef USE_ED25519
|
||||
EVP_PKEY*
|
||||
gldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
|
||||
uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
|
||||
0x70, 0x03, 0x21, 0x00};
|
||||
int pre_len = 12;
|
||||
uint8_t buf[256];
|
||||
EVP_PKEY *evp_key;
|
||||
/* pp gets modified by d2i() */
|
||||
const unsigned char* pp = (unsigned char*)buf;
|
||||
if(keylen != 32 || keylen + pre_len > sizeof(buf))
|
||||
return NULL; /* wrong length */
|
||||
memmove(buf, pre, pre_len);
|
||||
memmove(buf+pre_len, key, keylen);
|
||||
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ED25519 */
|
||||
|
||||
#ifdef USE_ED448
|
||||
EVP_PKEY*
|
||||
gldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
|
||||
uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
|
||||
0x71, 0x03, 0x3a, 0x00};
|
||||
int pre_len = 12;
|
||||
uint8_t buf[256];
|
||||
EVP_PKEY *evp_key;
|
||||
/* pp gets modified by d2i() */
|
||||
const unsigned char* pp = (unsigned char*)buf;
|
||||
if(keylen != 57 || keylen + pre_len > sizeof(buf))
|
||||
return NULL; /* wrong length */
|
||||
memmove(buf, pre, pre_len);
|
||||
memmove(buf+pre_len, key, keylen);
|
||||
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ED448 */
|
||||
|
||||
int
|
||||
gldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
|
||||
const EVP_MD* md)
|
||||
{
|
||||
EVP_MD_CTX* ctx;
|
||||
ctx = EVP_MD_CTX_create();
|
||||
if(!ctx)
|
||||
return 0;
|
||||
if(!EVP_DigestInit_ex(ctx, md, NULL) ||
|
||||
!EVP_DigestUpdate(ctx, data, len) ||
|
||||
!EVP_DigestFinal_ex(ctx, dest, NULL)) {
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
return 0;
|
||||
}
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
return 1;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* keyraw.h -- raw key and signature access and conversion - OpenSSL
|
||||
*
|
||||
* Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* See LICENSE for the license.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* raw key and signature access and conversion
|
||||
*
|
||||
* Since those functions heavily rely op cryptographic operations,
|
||||
* this module is dependent on openssl.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLDNS_KEYRAW_INTERNAL_H
|
||||
#define GLDNS_KEYRAW_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if GLDNS_BUILD_CONFIG_HAVE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/evp.h>
|
||||
|
||||
/**
|
||||
* Get the PKEY id for GOST, loads GOST into openssl as a side effect.
|
||||
* Only available if GOST is compiled into the library and openssl.
|
||||
* \return the gost id for EVP_CTX creation.
|
||||
*/
|
||||
int gldns_key_EVP_load_gost_id(void);
|
||||
|
||||
/** Release the engine reference held for the GOST engine. */
|
||||
void gldns_key_EVP_unload_gost(void);
|
||||
|
||||
/**
|
||||
* Like gldns_key_buf2dsa, but uses raw buffer.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return a DSA * structure with the key material
|
||||
*/
|
||||
DSA *gldns_key_buf2dsa_raw(unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with GOST.
|
||||
* \param[in] key data to convert
|
||||
* \param[in] keylen length of the key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_gost2pkey_raw(unsigned char* key, size_t keylen);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ECDSA.
|
||||
* \param[in] key data to convert
|
||||
* \param[in] keylen length of the key data
|
||||
* \param[in] algo precise algorithm to initialize ECC group values.
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
|
||||
|
||||
/**
|
||||
* Like gldns_key_buf2rsa, but uses raw buffer.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return a RSA * structure with the key material
|
||||
*/
|
||||
RSA *gldns_key_buf2rsa_raw(unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ED25519.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_ed255192pkey_raw(const unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ED448.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_ed4482pkey_raw(const unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Utility function to calculate hash using generic EVP_MD pointer.
|
||||
* \param[in] data the data to hash.
|
||||
* \param[in] len length of data.
|
||||
* \param[out] dest the destination of the hash, must be large enough.
|
||||
* \param[in] md the message digest to use.
|
||||
* \return true if worked, false on failure.
|
||||
*/
|
||||
int gldns_digest_evp(unsigned char* data, unsigned int len,
|
||||
unsigned char* dest, const EVP_MD* md);
|
||||
|
||||
#endif /* GLDNS_BUILD_CONFIG_HAVE_SSL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GLDNS_KEYRAW_INTERNAL_H */
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
*
|
||||
* /brief functions for Public Key Pinning
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015, Daniel Kahn Gillmor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* getdns Public Key Pinning
|
||||
*
|
||||
* a public key pinset is a list of dicts. each dict should have a
|
||||
* "digest" and a "value".
|
||||
*
|
||||
* "digest": a string indicating the type of digest. at the moment, we
|
||||
* only support a "digest" of "sha256".
|
||||
*
|
||||
* "value": a binary representation of the digest provided.
|
||||
*
|
||||
* given a such a pinset, we should be able to validate a chain
|
||||
* properly according to section 2.6 of RFC 7469.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include <getdns/getdns.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <string.h>
|
||||
#include "context.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
#include "pubkey-pinning-internal.h"
|
||||
|
||||
/* 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
|
||||
against all supported algorithms. better to wait on doing that
|
||||
until it is a better-understood problem (i.e. wait until hpkp is
|
||||
updated and follow the guidance in rfc7469bis)
|
||||
*/
|
||||
|
||||
/* b64 turns every 3 octets (or fraction thereof) into 4 octets */
|
||||
#define B64_ENCODED_SHA256_LENGTH (((SHA256_DIGEST_LENGTH + 2)/3) * 4)
|
||||
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size)
|
||||
{
|
||||
BIO *bio = NULL;
|
||||
char inbuf[B64_ENCODED_SHA256_LENGTH + 1];
|
||||
getdns_return_t ret = GETDNS_RETURN_GOOD;
|
||||
|
||||
/* openssl needs a trailing newline to base64 decode */
|
||||
memcpy(inbuf, str, B64_ENCODED_SHA256_LENGTH);
|
||||
inbuf[B64_ENCODED_SHA256_LENGTH] = '\n';
|
||||
|
||||
bio = BIO_push(BIO_new(BIO_f_base64()),
|
||||
BIO_new_mem_buf(inbuf, sizeof(inbuf)));
|
||||
if (BIO_read(bio, res, res_size) != (int) res_size)
|
||||
ret = GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
BIO_free_all(bio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* pubkey-pinning.c */
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
*
|
||||
* \file tls-internal.h
|
||||
* @brief getdns TLS implementation-specific items
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018-2019, NLnet Labs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _GETDNS_TLS_INTERNAL_H
|
||||
#define _GETDNS_TLS_INTERNAL_H
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "getdns/getdns.h"
|
||||
|
||||
#ifndef HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
|
||||
#define HAVE_TLS_CTX_CURVES_LIST 0
|
||||
#else
|
||||
#define HAVE_TLS_CTX_CURVES_LIST (HAVE_DECL_SSL_CTX_SET1_CURVES_LIST)
|
||||
#endif
|
||||
#ifndef HAVE_DECL_SSL_SET1_CURVES_LIST
|
||||
#define HAVE_TLS_CONN_CURVES_LIST 0
|
||||
#else
|
||||
#define HAVE_TLS_CONN_CURVES_LIST (HAVE_DECL_SSL_SET1_CURVES_LIST)
|
||||
#endif
|
||||
|
||||
#define GETDNS_TLS_MAX_DIGEST_LENGTH (EVP_MAX_MD_SIZE)
|
||||
|
||||
/* Forward declare type. */
|
||||
struct sha256_pin;
|
||||
struct getdns_log_config;
|
||||
|
||||
typedef struct _getdns_tls_context {
|
||||
SSL_CTX* ssl;
|
||||
const struct getdns_log_config* log;
|
||||
} _getdns_tls_context;
|
||||
|
||||
typedef struct _getdns_tls_connection {
|
||||
SSL* ssl;
|
||||
const struct getdns_log_config* log;
|
||||
#if defined(USE_DANESSL)
|
||||
const char* auth_name;
|
||||
const struct sha256_pin* pinset;
|
||||
#endif
|
||||
} _getdns_tls_connection;
|
||||
|
||||
typedef struct _getdns_tls_session {
|
||||
SSL_SESSION* ssl;
|
||||
} _getdns_tls_session;
|
||||
|
||||
typedef struct _getdns_tls_x509
|
||||
{
|
||||
X509* ssl;
|
||||
} _getdns_tls_x509;
|
||||
|
||||
typedef struct _getdns_tls_hmac
|
||||
{
|
||||
HMAC_CTX *ctx;
|
||||
#ifndef HAVE_HMAC_CTX_NEW
|
||||
HMAC_CTX ctx_space;
|
||||
#endif
|
||||
} _getdns_tls_hmac;
|
||||
|
||||
#endif /* _GETDNS_TLS_INTERNAL_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -48,17 +48,13 @@
|
|||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include <getdns/getdns.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <string.h>
|
||||
#include "context.h"
|
||||
#include "util-internal.h"
|
||||
#include "gldns/parseutil.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
#define X509_STORE_CTX_get0_untrusted(store) store->untrusted
|
||||
#endif
|
||||
#include "pubkey-pinning.h"
|
||||
#include "pubkey-pinning-internal.h"
|
||||
|
||||
/* we only support sha256 at the moment. adding support for another
|
||||
digest is more complex than just adding another entry here. in
|
||||
|
@ -73,12 +69,10 @@ static const getdns_bindata sha256 = {
|
|||
.data = (uint8_t*)"sha256"
|
||||
};
|
||||
|
||||
|
||||
#define PIN_PREFIX "pin-sha256=\""
|
||||
#define PIN_PREFIX_LENGTH (sizeof(PIN_PREFIX) - 1)
|
||||
/* b64 turns every 3 octets (or fraction thereof) into 4 octets */
|
||||
#define B64_ENCODED_SHA256_LENGTH (((SHA256_DIGEST_LENGTH + 2)/3) * 4)
|
||||
|
||||
/* convert an HPKP-style pin description to an appropriate getdns data
|
||||
structure. An example string is: (with the quotes, without any
|
||||
leading or trailing whitespace):
|
||||
|
@ -92,16 +86,13 @@ static const getdns_bindata sha256 = {
|
|||
It is the caller's responsibility to call getdns_dict_destroy when
|
||||
it is no longer needed.
|
||||
*/
|
||||
getdns_dict* getdns_pubkey_pin_create_from_string(
|
||||
getdns_context* context,
|
||||
const char* str)
|
||||
getdns_dict *getdns_pubkey_pin_create_from_string(
|
||||
const getdns_context *context, const char *str)
|
||||
{
|
||||
BIO *bio = NULL;
|
||||
size_t i;
|
||||
uint8_t buf[SHA256_DIGEST_LENGTH];
|
||||
char inbuf[B64_ENCODED_SHA256_LENGTH + 1];
|
||||
getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf };
|
||||
getdns_dict* out = NULL;
|
||||
getdns_dict *out = NULL;
|
||||
|
||||
/* we only do sha256 right now, make sure this is well-formed */
|
||||
if (!str || strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH))
|
||||
|
@ -119,15 +110,9 @@ getdns_dict* getdns_pubkey_pin_create_from_string(
|
|||
if (str[i++] != '\0')
|
||||
return NULL;
|
||||
|
||||
/* openssl needs a trailing newline to base64 decode */
|
||||
memcpy(inbuf, str + PIN_PREFIX_LENGTH, B64_ENCODED_SHA256_LENGTH);
|
||||
inbuf[B64_ENCODED_SHA256_LENGTH] = '\n';
|
||||
|
||||
bio = BIO_push(BIO_new(BIO_f_base64()),
|
||||
BIO_new_mem_buf(inbuf, sizeof(inbuf)));
|
||||
if (BIO_read(bio, buf, sizeof(buf)) != sizeof(buf))
|
||||
goto fail;
|
||||
|
||||
if (_getdns_decode_base64(str + PIN_PREFIX_LENGTH, buf, sizeof(buf)) != GETDNS_RETURN_GOOD)
|
||||
goto fail;
|
||||
|
||||
if (context)
|
||||
out = getdns_dict_create_with_context(context);
|
||||
else
|
||||
|
@ -141,12 +126,10 @@ getdns_dict* getdns_pubkey_pin_create_from_string(
|
|||
return out;
|
||||
|
||||
fail:
|
||||
BIO_free_all(bio);
|
||||
getdns_dict_destroy(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Test whether a given pinset is reasonable, including:
|
||||
|
||||
* is it well-formed?
|
||||
|
@ -270,7 +253,7 @@ _getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list,
|
|||
}
|
||||
|
||||
getdns_return_t
|
||||
_getdns_get_pubkey_pinset_list(getdns_context *ctx,
|
||||
_getdns_get_pubkey_pinset_list(const getdns_context *ctx,
|
||||
const sha256_pin_t *pinset_in,
|
||||
getdns_list **pinset_list)
|
||||
{
|
||||
|
@ -306,162 +289,3 @@ _getdns_get_pubkey_pinset_list(getdns_context *ctx,
|
|||
getdns_list_destroy(out);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* this should only happen once ever in the life of the library. it's
|
||||
used to associate a getdns_context_t with an SSL_CTX, to be able to
|
||||
do custom verification.
|
||||
|
||||
see doc/HOWTO/proxy_certificates.txt as an example
|
||||
*/
|
||||
static int
|
||||
#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) {
|
||||
#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);
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
|
||||
#else
|
||||
X509_STORE_unlock(store);
|
||||
#endif
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
getdns_upstream*
|
||||
_getdns_upstream_from_x509_store(X509_STORE_CTX *store)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
int uidx = _get_ssl_getdns_upstream_idx();
|
||||
#else
|
||||
int uidx = _get_ssl_getdns_upstream_idx(X509_STORE_CTX_get0_store(store));
|
||||
#endif
|
||||
int sslidx = SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||
const SSL *ssl;
|
||||
|
||||
/* all *_get_ex_data() should return NULL on failure anyway */
|
||||
ssl = X509_STORE_CTX_get_ex_data(store, sslidx);
|
||||
if (ssl)
|
||||
return (getdns_upstream*) SSL_get_ex_data(ssl, uidx);
|
||||
else
|
||||
return NULL;
|
||||
/* TODO: if we want more details about errors somehow, we
|
||||
* might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
_getdns_associate_upstream_with_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
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
/* TODO: if we want more details about errors somehow, we
|
||||
* might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
_getdns_verify_pinset_match(const sha256_pin_t *pinset,
|
||||
X509_STORE_CTX *store)
|
||||
{
|
||||
getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
|
||||
X509 *x, *prev = NULL;
|
||||
int i, len;
|
||||
unsigned char raw[4096];
|
||||
unsigned char *next;
|
||||
unsigned char buf[sizeof(pinset->pin)];
|
||||
const sha256_pin_t *p;
|
||||
|
||||
if (pinset == NULL || store == NULL)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
/* start at the base of the chain (the end-entity cert) and
|
||||
* make sure that some valid element of the chain does match
|
||||
* the pinset. */
|
||||
|
||||
/* Testing with OpenSSL 1.0.1e-1 on debian indicates that
|
||||
* store->untrusted holds the chain offered by the server in
|
||||
* the order that the server offers it. If the server offers
|
||||
* bogus certificates (that is, matching and valid certs that
|
||||
* belong to private keys that the server does not control),
|
||||
* the the verification will succeed (including this pinset
|
||||
* check), but the handshake will fail outside of this
|
||||
* verification. */
|
||||
|
||||
/* TODO: how do we handle raw public keys? */
|
||||
|
||||
for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++, prev = x) {
|
||||
|
||||
x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i);
|
||||
#if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
DEBUG_STUB("%s %-35s: Name of cert: %d ",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, i);
|
||||
X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
if (i > 0) {
|
||||
/* we ensure that "prev" is signed by "x" */
|
||||
EVP_PKEY *pkey = X509_get_pubkey(x);
|
||||
int verified;
|
||||
if (!pkey) {
|
||||
DEBUG_STUB("%s %-35s: Could not get pubkey from cert %d (%p)\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)x);
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
verified = X509_verify(prev, pkey);
|
||||
EVP_PKEY_free(pkey);
|
||||
if (!verified) {
|
||||
DEBUG_STUB("%s %-35s: cert %d (%p) was not signed by cert %d\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, i-1, (void*)prev, i);
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* digest the cert with sha256 */
|
||||
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
|
||||
if (len > (int)sizeof(raw)) {
|
||||
DEBUG_STUB("%s %-35s: Pubkey %d is larger than %"PRIsz" octets\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, i, sizeof(raw));
|
||||
continue;
|
||||
}
|
||||
next = raw;
|
||||
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
|
||||
if (next - raw != len) {
|
||||
DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed %"PRIsz"\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, i, len, next - raw);
|
||||
continue;
|
||||
}
|
||||
SHA256(raw, len, buf);
|
||||
|
||||
/* compare it */
|
||||
for (p = pinset; p; p = p->next)
|
||||
if (0 == memcmp(buf, p->pin, sizeof(p->pin))) {
|
||||
DEBUG_STUB("%s %-35s: Pubkey %d matched pin %p (%"PRIsz")\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p, sizeof(p->pin));
|
||||
return GETDNS_RETURN_GOOD;
|
||||
} else
|
||||
DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* pubkey-pinning.c */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* /brief internal functions for dealing with pubkey pinsets
|
||||
* /brief functions for dealing with pubkey pinsets
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -34,6 +34,10 @@
|
|||
#ifndef PUBKEY_PINNING_H_
|
||||
#define PUBKEY_PINNING_H_
|
||||
|
||||
/* getdns_pubkey_pin_create_from_string() is implemented in pubkey-pinning.c */
|
||||
#include "getdns/getdns_extra.h"
|
||||
|
||||
#include "tls.h"
|
||||
|
||||
/* create and populate a pinset linked list from a getdns_list pinset */
|
||||
getdns_return_t
|
||||
|
@ -44,25 +48,9 @@ _getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list,
|
|||
|
||||
/* create a getdns_list version of the pinset */
|
||||
getdns_return_t
|
||||
_getdns_get_pubkey_pinset_list(getdns_context *ctx,
|
||||
_getdns_get_pubkey_pinset_list(const getdns_context *ctx,
|
||||
const sha256_pin_t *pinset_in,
|
||||
getdns_list **pinset_list);
|
||||
|
||||
|
||||
/* internal functions for associating X.509 verification processes in
|
||||
* OpenSSL with getdns_upstream objects. */
|
||||
|
||||
getdns_upstream*
|
||||
_getdns_upstream_from_x509_store(X509_STORE_CTX *store);
|
||||
|
||||
|
||||
getdns_return_t
|
||||
_getdns_associate_upstream_with_SSL(SSL *ssl,
|
||||
getdns_upstream *upstream);
|
||||
|
||||
getdns_return_t
|
||||
_getdns_verify_pinset_match(const sha256_pin_t *pinset,
|
||||
X509_STORE_CTX *store);
|
||||
|
||||
#endif
|
||||
/* pubkey-pinning.h */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "debug.h"
|
||||
#include "convert.h"
|
||||
#include "general.h"
|
||||
#include "tls.h"
|
||||
|
||||
/* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256
|
||||
* TSIG type (uint16_t) : 2
|
||||
|
@ -54,15 +55,15 @@
|
|||
* Time Signed (uint48_t) : 6
|
||||
* Fudge (uint16_t) : 2
|
||||
* Mac Size (uint16_t) : 2
|
||||
* Mac (variable) : EVP_MAX_MD_SIZE
|
||||
* Mac (variable) : GETDNS_TLS_MAX_DIGEST_LENGTH
|
||||
* Original Id (uint16_t) : 2
|
||||
* Error (uint16_t) : 2
|
||||
* Other Len (uint16_t) : 2
|
||||
* Other Data (nothing) : 0
|
||||
* ---- +
|
||||
* 538 + EVP_MAX_MD_SIZE
|
||||
* 538 + GETDNS_TLS_MAX_DIGEST_LENGTH
|
||||
*/
|
||||
#define MAXIMUM_TSIG_SPACE (538 + EVP_MAX_MD_SIZE)
|
||||
#define MAXIMUM_TSIG_SPACE (538 + GETDNS_TLS_MAX_DIGEST_LENGTH)
|
||||
|
||||
getdns_dict dnssec_ok_checking_disabled_spc = {
|
||||
{ RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
|
||||
|
@ -92,7 +93,7 @@ getdns_dict *no_dnssec_checking_disabled_opportunistic
|
|||
= &no_dnssec_checking_disabled_opportunistic_spc;
|
||||
|
||||
static int
|
||||
is_extension_set(getdns_dict *extensions, const char *name, int default_value)
|
||||
is_extension_set(const getdns_dict *extensions, const char *name, int default_value)
|
||||
{
|
||||
getdns_return_t r;
|
||||
uint32_t value;
|
||||
|
@ -125,7 +126,7 @@ network_req_cleanup(getdns_network_req *net_req)
|
|||
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
||||
if (net_req->debug_tls_peer_cert.size &&
|
||||
net_req->debug_tls_peer_cert.data)
|
||||
OPENSSL_free(net_req->debug_tls_peer_cert.data);
|
||||
GETDNS_FREE(net_req->owner->my_mf, net_req->debug_tls_peer_cert.data);
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
|
@ -134,6 +135,7 @@ netreq_reset(getdns_network_req *net_req)
|
|||
uint8_t *buf;
|
||||
/* variables that need to be reset on reinit
|
||||
*/
|
||||
net_req->first_upstream = NULL;
|
||||
net_req->unbound_id = -1;
|
||||
_getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT);
|
||||
if (net_req->query_id_registered) {
|
||||
|
@ -166,7 +168,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
|||
int with_opt, int edns_maximum_udp_payload_size,
|
||||
uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit,
|
||||
uint16_t opt_options_size, size_t noptions, getdns_list *options,
|
||||
size_t wire_data_sz, size_t max_query_sz, getdns_dict *extensions)
|
||||
size_t wire_data_sz, size_t max_query_sz, const getdns_dict *extensions)
|
||||
{
|
||||
uint8_t *buf;
|
||||
getdns_dict *option;
|
||||
|
@ -211,6 +213,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
|||
net_req->debug_tls_auth_status = GETDNS_AUTH_NONE;
|
||||
net_req->debug_tls_peer_cert.size = 0;
|
||||
net_req->debug_tls_peer_cert.data = NULL;
|
||||
net_req->debug_tls_version = NULL;
|
||||
net_req->debug_udp = 0;
|
||||
|
||||
/* Scheduling, touch only via _getdns_netreq_change_state!
|
||||
|
@ -399,9 +402,8 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
gldns_buffer gbuf;
|
||||
uint16_t arcount;
|
||||
const getdns_tsig_info *tsig_info;
|
||||
uint8_t md_buf[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_len = EVP_MAX_MD_SIZE;
|
||||
const EVP_MD *digester;
|
||||
unsigned char* md_buf;
|
||||
size_t md_len;
|
||||
|
||||
/* Should only be called when in stub mode */
|
||||
assert(req->query);
|
||||
|
@ -434,31 +436,9 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
gldns_buffer_write_u16(&gbuf, 0); /* Error */
|
||||
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
||||
|
||||
switch (upstream->tsig_alg) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return req->response - req->query;
|
||||
}
|
||||
|
||||
(void) HMAC(digester, upstream->tsig_key, upstream->tsig_size,
|
||||
(void *)req->query, gldns_buffer_current(&gbuf) - req->query,
|
||||
md_buf, &md_len);
|
||||
md_buf = _getdns_tls_hmac_hash(&req->owner->my_mf, upstream->tsig_alg, upstream->tsig_key, upstream->tsig_size, (void *)req->query, gldns_buffer_current(&gbuf) - req->query, &md_len);
|
||||
if (!md_buf)
|
||||
return req->response - req->query;
|
||||
|
||||
gldns_buffer_rewind(&gbuf);
|
||||
gldns_buffer_write(&gbuf,
|
||||
|
@ -478,6 +458,8 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
gldns_buffer_write_u16(&gbuf, 0); /* Error */
|
||||
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
||||
|
||||
GETDNS_FREE(req->owner->my_mf, md_buf);
|
||||
|
||||
if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
|
||||
return req->response - req->query;
|
||||
|
||||
|
@ -493,6 +475,9 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
void
|
||||
_getdns_network_validate_tsig(getdns_network_req *req)
|
||||
{
|
||||
#if defined(HAVE_NSS) || defined(HAVE_NETTLE)
|
||||
(void)req;
|
||||
#else
|
||||
_getdns_rr_iter rr_spc, *rr;
|
||||
_getdns_rdf_iter rdf_spc, *rdf;
|
||||
const uint8_t *request_mac;
|
||||
|
@ -504,14 +489,10 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
const uint8_t *response_mac;
|
||||
uint16_t response_mac_len;
|
||||
uint8_t other_len;
|
||||
uint8_t result_mac[EVP_MAX_MD_SIZE];
|
||||
unsigned int result_mac_len = EVP_MAX_MD_SIZE;
|
||||
unsigned char *result_mac;
|
||||
size_t result_mac_len;
|
||||
uint16_t original_id;
|
||||
const EVP_MD *digester;
|
||||
HMAC_CTX *ctx;
|
||||
#ifndef HAVE_HMAC_CTX_NEW
|
||||
HMAC_CTX ctx_space;
|
||||
#endif
|
||||
_getdns_tls_hmac *hmac;
|
||||
|
||||
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__);
|
||||
for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
|
||||
|
@ -618,39 +599,16 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
gldns_read_uint16(req->response + 10) - 1);
|
||||
gldns_write_uint16(req->response, original_id);
|
||||
|
||||
switch (req->upstream->tsig_alg) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return;
|
||||
}
|
||||
#ifdef HAVE_HMAC_CTX_NEW
|
||||
ctx = HMAC_CTX_new();
|
||||
#else
|
||||
ctx = &ctx_space;
|
||||
HMAC_CTX_init(ctx);
|
||||
#endif
|
||||
(void) HMAC_Init_ex(ctx, req->upstream->tsig_key,
|
||||
req->upstream->tsig_size, digester, NULL);
|
||||
(void) HMAC_Update(ctx, request_mac - 2, request_mac_len + 2);
|
||||
(void) HMAC_Update(ctx, req->response, rr->pos - req->response);
|
||||
(void) HMAC_Update(ctx, tsig_vars, gldns_buffer_position(&gbuf));
|
||||
HMAC_Final(ctx, result_mac, &result_mac_len);
|
||||
hmac = _getdns_tls_hmac_new(&req->owner->my_mf, req->upstream->tsig_alg, req->upstream->tsig_key, req->upstream->tsig_size);
|
||||
if (!hmac)
|
||||
return;
|
||||
|
||||
_getdns_tls_hmac_add(hmac, request_mac - 2, request_mac_len + 2);
|
||||
_getdns_tls_hmac_add(hmac, req->response, rr->pos - req->response);
|
||||
_getdns_tls_hmac_add(hmac, tsig_vars, gldns_buffer_position(&gbuf));
|
||||
result_mac = _getdns_tls_hmac_end(&req->owner->my_mf, hmac, &result_mac_len);
|
||||
if (!result_mac)
|
||||
return;
|
||||
|
||||
DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
|
||||
STUB_DEBUG_TSIG, __FUNC__, (int)(result_mac_len));
|
||||
|
@ -658,14 +616,12 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
memcmp(result_mac, response_mac, result_mac_len) == 0)
|
||||
req->tsig_status = GETDNS_DNSSEC_SECURE;
|
||||
|
||||
#ifdef HAVE_HMAC_CTX_FREE
|
||||
HMAC_CTX_free(ctx);
|
||||
#else
|
||||
HMAC_CTX_cleanup(ctx);
|
||||
#endif
|
||||
GETDNS_FREE(req->owner->my_mf, result_mac);
|
||||
|
||||
gldns_write_uint16(req->response, gldns_read_uint16(req->query));
|
||||
gldns_write_uint16(req->response + 10,
|
||||
gldns_read_uint16(req->response + 10) + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -697,9 +653,12 @@ static const uint8_t no_suffixes[] = { 1, 0 };
|
|||
/* create a new dns req to be submitted */
|
||||
getdns_dns_req *
|
||||
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||
const char *name, uint16_t request_type, getdns_dict *extensions,
|
||||
const char *name, uint16_t request_type, const getdns_dict *extensions,
|
||||
uint64_t *now_ms)
|
||||
{
|
||||
int dnssec = is_extension_set(
|
||||
extensions, "dnssec",
|
||||
context->dnssec);
|
||||
int dnssec_return_status = is_extension_set(
|
||||
extensions, "dnssec_return_status",
|
||||
context->dnssec_return_status);
|
||||
|
@ -726,7 +685,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
|| is_extension_set(extensions, "dnssec_roadblock_avoidance",
|
||||
context->dnssec_roadblock_avoidance);
|
||||
#endif
|
||||
int dnssec_extension_set = dnssec_return_status
|
||||
int dnssec_extension_set = dnssec || dnssec_return_status
|
||||
|| dnssec_return_only_secure || dnssec_return_all_statuses
|
||||
|| dnssec_return_validation_chain
|
||||
|| dnssec_return_full_validation_chain
|
||||
|
@ -766,7 +725,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
request_type == GETDNS_RRTYPE_AAAA );
|
||||
/* Reserve for the buffer at least one more byte
|
||||
* (to test for udp overflow) (hence the + 1),
|
||||
* And align on the 8 byte boundry (hence the (x + 7) / 8 * 8)
|
||||
* And align on the 8 byte boundary (hence the (x + 7) / 8 * 8)
|
||||
*/
|
||||
size_t max_query_sz, max_response_sz, netreq_sz, dnsreq_base_sz;
|
||||
uint8_t *region, *suffixes;
|
||||
|
@ -774,6 +733,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
int opportunistic = 0;
|
||||
|
||||
if (extensions == no_dnssec_checking_disabled_opportunistic) {
|
||||
dnssec = 0;
|
||||
dnssec_return_status = 0;
|
||||
dnssec_return_only_secure = 0;
|
||||
dnssec_return_all_statuses = 0;
|
||||
|
@ -954,6 +914,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
result->context = context;
|
||||
result->loop = loop;
|
||||
result->trans_id = (uint64_t) (intptr_t) result;
|
||||
result->dnssec = dnssec;
|
||||
result->dnssec_return_status = dnssec_return_status;
|
||||
result->dnssec_return_only_secure = dnssec_return_only_secure;
|
||||
result->dnssec_return_all_statuses = dnssec_return_all_statuses;
|
||||
|
|
240
src/rr-dict.c
240
src/rr-dict.c
|
@ -431,6 +431,215 @@ static _getdns_rdf_special hip_public_key = {
|
|||
hip_public_key_dict2wire, NULL
|
||||
};
|
||||
|
||||
static const uint8_t *
|
||||
amtrelay_D_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
|
||||
{
|
||||
(void)pkt;
|
||||
return rdf < pkt_end ? rdf + 1 : NULL;
|
||||
}
|
||||
static getdns_return_t
|
||||
amtrelay_D_wire2dict(getdns_dict *dict, const uint8_t *rdf)
|
||||
{
|
||||
return getdns_dict_set_int(dict, "discovery_optional", (*rdf >> 7));
|
||||
}
|
||||
static getdns_return_t
|
||||
amtrelay_D_dict2wire(const getdns_dict *dict,
|
||||
uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
|
||||
{
|
||||
getdns_return_t r;
|
||||
uint32_t value;
|
||||
(void)rdata; /* unused parameter */
|
||||
|
||||
if ((r = getdns_dict_get_int(dict, "discovery_optional", &value)))
|
||||
return r;
|
||||
|
||||
*rdf_len = 1;
|
||||
if (*rdf_len < 1)
|
||||
return GETDNS_RETURN_NEED_MORE_SPACE;
|
||||
|
||||
*rdf_len = 1;
|
||||
*rdf = value ? 0x80 : 0x00;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
static _getdns_rdf_special amtrelay_D = {
|
||||
amtrelay_D_rdf_end,
|
||||
amtrelay_D_wire2dict, NULL,
|
||||
amtrelay_D_dict2wire, NULL
|
||||
};
|
||||
|
||||
static const uint8_t *
|
||||
amtrelay_rtype_rdf_end(
|
||||
const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
|
||||
{
|
||||
(void)pkt; (void)pkt_end;
|
||||
return rdf;
|
||||
}
|
||||
static getdns_return_t
|
||||
amtrelay_rtype_wire2dict(getdns_dict *dict, const uint8_t *rdf)
|
||||
{
|
||||
return getdns_dict_set_int(
|
||||
dict, "replay_type", (rdf[-1] & 0x7F));
|
||||
}
|
||||
static getdns_return_t
|
||||
amtrelay_rtype_dict2wire(
|
||||
const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
|
||||
{
|
||||
getdns_return_t r;
|
||||
uint32_t value;
|
||||
|
||||
if ((r = getdns_dict_get_int(dict, "relay_type", &value)))
|
||||
return r;
|
||||
|
||||
if (rdf - 1 < rdata)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
*rdf_len = 0;
|
||||
rdf[-1] |= (value & 0x7F);
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
static _getdns_rdf_special amtrelay_rtype = {
|
||||
amtrelay_rtype_rdf_end,
|
||||
amtrelay_rtype_wire2dict, NULL,
|
||||
amtrelay_rtype_dict2wire, NULL
|
||||
};
|
||||
|
||||
static const uint8_t *
|
||||
amtrelay_relay_rdf_end(
|
||||
const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
|
||||
{
|
||||
const uint8_t *end;
|
||||
|
||||
if (rdf - 4 < pkt)
|
||||
return NULL;
|
||||
switch (rdf[-1] & 0x7F) {
|
||||
case 0: end = rdf;
|
||||
break;
|
||||
case 1: end = rdf + 4;
|
||||
break;
|
||||
case 2: end = rdf + 16;
|
||||
break;
|
||||
case 3: for (end = rdf; end < pkt_end; end += *end + 1)
|
||||
if ((*end & 0xC0) == 0xC0)
|
||||
end += 2;
|
||||
else if (*end & 0xC0)
|
||||
return NULL;
|
||||
else if (!*end) {
|
||||
end += 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return end <= pkt_end ? end : NULL;
|
||||
}
|
||||
static getdns_return_t
|
||||
amtrelay_relay_equip_const_bindata(
|
||||
const uint8_t *rdf, size_t *size, const uint8_t **data)
|
||||
{
|
||||
*data = rdf;
|
||||
switch (rdf[-1] & 0x7F) {
|
||||
case 0: *size = 0;
|
||||
break;
|
||||
case 1: *size = 4;
|
||||
break;
|
||||
case 2: *size = 16;
|
||||
break;
|
||||
case 3: while (*rdf)
|
||||
if ((*rdf & 0xC0) == 0xC0)
|
||||
rdf += 2;
|
||||
else if (*rdf & 0xC0)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
else
|
||||
rdf += *rdf + 1;
|
||||
*size = rdf + 1 - *data;
|
||||
break;
|
||||
default:
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
amtrelay_relay_wire2dict(getdns_dict *dict, const uint8_t *rdf)
|
||||
{
|
||||
size_t size;
|
||||
const uint8_t *data;
|
||||
|
||||
if (amtrelay_relay_equip_const_bindata(rdf, &size, &data))
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
else if (! size)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
else
|
||||
return _getdns_dict_set_const_bindata(dict, "relay", size, data);
|
||||
}
|
||||
static getdns_return_t
|
||||
amtrelay_relay_2wire(
|
||||
const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
|
||||
{
|
||||
assert(rdf - 1 >= rdata && (rdf[-1] & 0x7F) > 0);
|
||||
|
||||
switch (rdf[-1] & 0x7F) {
|
||||
case 1: if (!value || value->size != 4)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
if (*rdf_len < 4) {
|
||||
*rdf_len = 4;
|
||||
return GETDNS_RETURN_NEED_MORE_SPACE;
|
||||
}
|
||||
*rdf_len = 4;
|
||||
(void)memcpy(rdf, value->data, 4);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
case 2: if (!value || value->size != 16)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
if (*rdf_len < 16) {
|
||||
*rdf_len = 16;
|
||||
return GETDNS_RETURN_NEED_MORE_SPACE;
|
||||
}
|
||||
*rdf_len = 16;
|
||||
(void)memcpy(rdf, value->data, 16);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
case 3: if (!value || value->size == 0)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
/* Assume bindata is a valid dname; garbage in, garbage out */
|
||||
if (*rdf_len < value->size) {
|
||||
*rdf_len = value->size;
|
||||
return GETDNS_RETURN_NEED_MORE_SPACE;
|
||||
}
|
||||
*rdf_len = value->size;
|
||||
(void)memcpy(rdf, value->data, value->size);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
default:
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
static getdns_return_t
|
||||
amtrelay_relay_dict2wire(
|
||||
const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
|
||||
{
|
||||
getdns_return_t r;
|
||||
getdns_bindata *value;
|
||||
|
||||
if (rdf - 1 < rdata)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
else if ((rdf[-1] & 0x7F) == 0) {
|
||||
*rdf_len = 0;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
else if ((r = getdns_dict_get_bindata(dict, "relay", &value)))
|
||||
return r;
|
||||
else
|
||||
return amtrelay_relay_2wire(value, rdata, rdf, rdf_len);
|
||||
}
|
||||
static _getdns_rdf_special amtrelay_relay = {
|
||||
amtrelay_relay_rdf_end,
|
||||
amtrelay_relay_wire2dict, NULL,
|
||||
amtrelay_relay_dict2wire, NULL
|
||||
};
|
||||
|
||||
|
||||
static _getdns_rdata_def a_rdata[] = {
|
||||
{ "ipv4_address" , GETDNS_RDF_A , NULL }};
|
||||
|
@ -613,6 +822,11 @@ static _getdns_rdata_def csync_rdata[] = {
|
|||
{ "serial" , GETDNS_RDF_I4 , NULL },
|
||||
{ "flags" , GETDNS_RDF_I2 , NULL },
|
||||
{ "type_bit_maps" , GETDNS_RDF_X , NULL }};
|
||||
static _getdns_rdata_def zonemd_rdata[] = {
|
||||
{ "serial" , GETDNS_RDF_I4 , NULL },
|
||||
{ "digest_type" , GETDNS_RDF_I1 , NULL },
|
||||
{ "reserved" , GETDNS_RDF_I1 , NULL },
|
||||
{ "digest" , GETDNS_RDF_X , NULL }};
|
||||
static _getdns_rdata_def spf_rdata[] = {
|
||||
{ "text" , GETDNS_RDF_S_M , NULL }};
|
||||
static _getdns_rdata_def nid_rdata[] = {
|
||||
|
@ -660,6 +874,17 @@ static _getdns_rdata_def dlv_rdata[] = {
|
|||
{ "algorithm" , GETDNS_RDF_I1 , NULL },
|
||||
{ "digest_type" , GETDNS_RDF_I1 , NULL },
|
||||
{ "digest" , GETDNS_RDF_X , NULL }};
|
||||
static _getdns_rdata_def doa_rdata[] = {
|
||||
{ "enterprise" , GETDNS_RDF_I4 , NULL },
|
||||
{ "type" , GETDNS_RDF_I4 , NULL },
|
||||
{ "location" , GETDNS_RDF_I1 , NULL },
|
||||
{ "media_type" , GETDNS_RDF_S , NULL },
|
||||
{ "data" , GETDNS_RDF_B , NULL }};
|
||||
static _getdns_rdata_def amtrelay_rdata[] = {
|
||||
{ "precedence" , GETDNS_RDF_I1 , NULL },
|
||||
{ "discovery_optional" , GETDNS_RDF_SPECIAL, &amtrelay_D},
|
||||
{ "relay_type" , GETDNS_RDF_SPECIAL, &amtrelay_rtype },
|
||||
{ "relay" , GETDNS_RDF_SPECIAL, &amtrelay_relay }};
|
||||
|
||||
static _getdns_rr_def _getdns_rr_defs[] = {
|
||||
{ NULL, NULL, 0 },
|
||||
|
@ -723,9 +948,9 @@ static _getdns_rr_def _getdns_rr_defs[] = {
|
|||
{ "TALINK", talink_rdata, ALEN( talink_rdata) },
|
||||
{ "CDS", ds_rdata, ALEN( ds_rdata) },
|
||||
{ "CDNSKEY", dnskey_rdata, ALEN( dnskey_rdata) },
|
||||
{ "OPENPGPKEY", openpgpkey_rdata, ALEN(openpgpkey_rdata) }, /* 61 - */
|
||||
{ "CSYNC", csync_rdata, ALEN( csync_rdata) }, /* - 62 */
|
||||
{ NULL, NULL, 0 },
|
||||
{ "OPENPGPKEY", openpgpkey_rdata, ALEN(openpgpkey_rdata) },
|
||||
{ "CSYNC", csync_rdata, ALEN( csync_rdata) },
|
||||
{ "ZONEMD", zonemd_rdata, ALEN( zonemd_rdata) }, /* - 63 */
|
||||
{ NULL, NULL, 0 },
|
||||
{ NULL, NULL, 0 },
|
||||
{ NULL, NULL, 0 },
|
||||
|
@ -921,7 +1146,8 @@ static _getdns_rr_def _getdns_rr_defs[] = {
|
|||
{ "URI", uri_rdata, ALEN( uri_rdata) }, /* 256 - */
|
||||
{ "CAA", caa_rdata, ALEN( caa_rdata) },
|
||||
{ "AVC", txt_rdata, ALEN( txt_rdata) },
|
||||
{ "DOA", UNKNOWN_RDATA, 0 }, /* - 259 */
|
||||
{ "DOA", doa_rdata, ALEN( doa_rdata) },
|
||||
{ "AMTRELAY", amtrelay_rdata, ALEN( amtrelay_rdata) }, /* - 260 */
|
||||
{ "TA", ds_rdata, ALEN( ds_rdata) }, /* 32768 */
|
||||
{ "DLV", dlv_rdata, ALEN( dlv_rdata) } /* 32769 */
|
||||
};
|
||||
|
@ -929,12 +1155,12 @@ static _getdns_rr_def _getdns_rr_defs[] = {
|
|||
const _getdns_rr_def *
|
||||
_getdns_rr_def_lookup(uint16_t rr_type)
|
||||
{
|
||||
if (rr_type <= 259)
|
||||
if (rr_type <= 260)
|
||||
return &_getdns_rr_defs[rr_type];
|
||||
else if (rr_type == 32768)
|
||||
return &_getdns_rr_defs[260];
|
||||
else if (rr_type == 32769)
|
||||
return &_getdns_rr_defs[261];
|
||||
else if (rr_type == 32769)
|
||||
return &_getdns_rr_defs[262];
|
||||
return _getdns_rr_defs;
|
||||
}
|
||||
|
||||
|
|
236
src/server.c
236
src/server.c
|
@ -34,6 +34,10 @@
|
|||
#include <iphlpapi.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FCNTL)
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "getdns/getdns_extra.h"
|
||||
#include "context.h"
|
||||
#include "types-internal.h"
|
||||
|
@ -118,6 +122,25 @@ typedef struct tcp_connection {
|
|||
size_t to_answer;
|
||||
} tcp_connection;
|
||||
|
||||
/** best effort to set nonblocking */
|
||||
static void
|
||||
getdns_sock_nonblock(int sockfd)
|
||||
{
|
||||
#if defined(HAVE_FCNTL)
|
||||
int flag;
|
||||
if((flag = fcntl(sockfd, F_GETFL)) != -1) {
|
||||
flag |= O_NONBLOCK;
|
||||
if(fcntl(sockfd, F_SETFL, flag) == -1) {
|
||||
/* ignore error, continue blockingly */
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_IOCTLSOCKET)
|
||||
unsigned long on = 1;
|
||||
if(ioctlsocket(sockfd, FIONBIO, &on) != 0) {
|
||||
/* ignore error, continue blockingly */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void free_listen_set_when_done(listen_set *set);
|
||||
static void tcp_connection_destroy(tcp_connection *conn)
|
||||
|
@ -127,22 +150,33 @@ static void tcp_connection_destroy(tcp_connection *conn)
|
|||
|
||||
tcp_to_write *cur, *next;
|
||||
|
||||
if (!(mf = &conn->super.l->set->context->mf))
|
||||
return;
|
||||
|
||||
mf = &conn->super.l->set->context->mf;
|
||||
if (getdns_context_get_eventloop(conn->super.l->set->context, &loop))
|
||||
return;
|
||||
|
||||
if (conn->event.read_cb||conn->event.write_cb||conn->event.timeout_cb)
|
||||
if (conn->event.ev)
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
|
||||
if (conn->fd >= 0)
|
||||
if (conn->event.read_cb||conn->event.write_cb||conn->event.timeout_cb) {
|
||||
conn->event.read_cb = conn->event.write_cb =
|
||||
conn->event.timeout_cb = NULL;
|
||||
}
|
||||
if (conn->fd >= 0) {
|
||||
(void) _getdns_closesocket(conn->fd);
|
||||
GETDNS_FREE(*mf, conn->read_buf);
|
||||
|
||||
for (cur = conn->to_write; cur; cur = next) {
|
||||
next = cur->next;
|
||||
GETDNS_FREE(*mf, cur);
|
||||
conn->fd = -1;
|
||||
}
|
||||
if (conn->read_buf) {
|
||||
GETDNS_FREE(*mf, conn->read_buf);
|
||||
conn->read_buf = conn->read_pos = NULL;
|
||||
conn->to_read = 0;
|
||||
}
|
||||
if ((cur = conn->to_write)) {
|
||||
while (cur) {
|
||||
next = cur->next;
|
||||
GETDNS_FREE(*mf, cur);
|
||||
cur = next;
|
||||
}
|
||||
conn->to_write = NULL;
|
||||
}
|
||||
if (conn->to_answer > 0)
|
||||
return;
|
||||
|
@ -191,15 +225,16 @@ static void tcp_write_cb(void *userarg)
|
|||
(const void *)&to_write->write_buf[to_write->written],
|
||||
to_write->write_buf_len - to_write->written, 0)) == -1) {
|
||||
|
||||
if (_getdns_socketerror_wants_retry())
|
||||
return;
|
||||
|
||||
DEBUG_SERVER("I/O error from send(): %s\n",
|
||||
_getdns_errnostr());
|
||||
|
||||
if (conn->fd != -1) {
|
||||
if (_getdns_socketerror_wants_retry()) {
|
||||
(void) loop->vmt->schedule(loop, conn->fd,
|
||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||
return;
|
||||
}
|
||||
DEBUG_SERVER("I/O error from send(): %s\n",
|
||||
_getdns_errnostr());
|
||||
}
|
||||
/* IO error, close connection */
|
||||
conn->event.read_cb = conn->event.write_cb =
|
||||
conn->event.timeout_cb = NULL;
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
|
@ -220,7 +255,12 @@ _getdns_cancel_reply(getdns_context *context, connection *conn)
|
|||
{
|
||||
struct mem_funcs *mf;
|
||||
|
||||
if (!context || !conn)
|
||||
if (!conn)
|
||||
return;
|
||||
|
||||
if (context && context->server &&
|
||||
_getdns_rbtree_search(&context->server->connections_set, conn)
|
||||
!= &conn->super)
|
||||
return;
|
||||
|
||||
if (conn->l->transport == GETDNS_TRANSPORT_TCP) {
|
||||
|
@ -247,8 +287,8 @@ _getdns_cancel_reply(getdns_context *context, connection *conn)
|
|||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_reply(
|
||||
getdns_context *context, getdns_dict *reply, getdns_transaction_t request_id)
|
||||
getdns_reply(getdns_context *context,
|
||||
const getdns_dict *reply, getdns_transaction_t request_id)
|
||||
{
|
||||
/* TODO: Check request_id at context->outbound_requests */
|
||||
connection *conn = (connection *)(intptr_t)request_id;
|
||||
|
@ -258,13 +298,14 @@ getdns_reply(
|
|||
size_t len;
|
||||
getdns_return_t r;
|
||||
|
||||
if (!context || !conn)
|
||||
if (!conn)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (!context->server)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;;
|
||||
if (!context || !context->server) {
|
||||
if (!context)
|
||||
context = conn->l->set->context;
|
||||
|
||||
if (_getdns_rbtree_search(&context->server->connections_set, conn)
|
||||
} else if (_getdns_rbtree_search(&context->server->connections_set, conn)
|
||||
!= &conn->super)
|
||||
return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
|
||||
|
||||
|
@ -317,8 +358,10 @@ getdns_reply(
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
if (!(to_write = (tcp_to_write *)GETDNS_XMALLOC(
|
||||
*mf, uint8_t, sizeof(tcp_to_write) + len + 2)))
|
||||
*mf, uint8_t, sizeof(tcp_to_write) + len + 2))) {
|
||||
tcp_connection_destroy(conn);
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
to_write->write_buf_len = len + 2;
|
||||
to_write->write_buf[0] = (len >> 8) & 0xFF;
|
||||
|
@ -327,20 +370,27 @@ getdns_reply(
|
|||
to_write->next = NULL;
|
||||
(void) memcpy(to_write->write_buf + 2, buf, len);
|
||||
|
||||
/* Appen to_write to conn->to_write list */
|
||||
/* Append to_write to conn->to_write list */
|
||||
for ( to_write_p = &conn->to_write
|
||||
; *to_write_p
|
||||
; to_write_p = &(*to_write_p)->next)
|
||||
; /* pass */
|
||||
*to_write_p = to_write;
|
||||
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
conn->event.write_cb = tcp_write_cb;
|
||||
if (conn->to_answer > 0)
|
||||
conn->to_answer--;
|
||||
(void) loop->vmt->schedule(loop,
|
||||
conn->fd, DOWNSTREAM_IDLE_TIMEOUT,
|
||||
&conn->event);
|
||||
|
||||
/* When event is scheduled, and doesn't have tcp_write_cb:
|
||||
* reschedule.
|
||||
*/
|
||||
if (conn->event.write_cb == NULL) {
|
||||
if (conn->event.ev)
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
conn->event.write_cb = tcp_write_cb;
|
||||
(void) loop->vmt->schedule(loop,
|
||||
conn->fd, DOWNSTREAM_IDLE_TIMEOUT,
|
||||
&conn->event);
|
||||
}
|
||||
}
|
||||
/* TODO: other transport types */
|
||||
|
||||
|
@ -366,18 +416,19 @@ static void tcp_read_cb(void *userarg)
|
|||
|
||||
/* Reset tcp_connection idle timeout */
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
(void) loop->vmt->schedule(loop, conn->fd,
|
||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||
|
||||
if ((bytes_read = recv(conn->fd,
|
||||
if (conn->fd == -1 ||
|
||||
(bytes_read = recv(conn->fd,
|
||||
(void *)conn->read_pos, conn->to_read, 0)) < 0) {
|
||||
if (_getdns_socketerror_wants_retry())
|
||||
return; /* Come back to do the read later */
|
||||
|
||||
/* IO error, close connection */
|
||||
DEBUG_SERVER("I/O error from recv(): %s\n",
|
||||
_getdns_errnostr());
|
||||
|
||||
if (conn->fd != -1) {
|
||||
if (_getdns_socketerror_wants_retry()) {
|
||||
(void) loop->vmt->schedule(loop, conn->fd,
|
||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||
return; /* Come back to do the read later */
|
||||
}
|
||||
/* IO error, close connection */
|
||||
DEBUG_SERVER("I/O error from recv(): %s\n",
|
||||
_getdns_errnostr());
|
||||
}
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
|
@ -391,9 +442,9 @@ static void tcp_read_cb(void *userarg)
|
|||
conn->to_read -= bytes_read;
|
||||
conn->read_pos += bytes_read;
|
||||
if (conn->to_read)
|
||||
return; /* More to read */
|
||||
; /* Schedule for more reading */
|
||||
|
||||
if (conn->read_pos - conn->read_buf == 2) {
|
||||
else if (conn->read_pos - conn->read_buf == 2) {
|
||||
/* read length of dns msg to read */
|
||||
conn->to_read = (conn->read_buf[0] << 8) | conn->read_buf[1];
|
||||
if (conn->to_read > conn->read_buf_len) {
|
||||
|
@ -413,47 +464,60 @@ static void tcp_read_cb(void *userarg)
|
|||
return;
|
||||
}
|
||||
conn->read_pos = conn->read_buf;
|
||||
return; /* Read DNS message */
|
||||
}
|
||||
if ((r = getdns_wire2msg_dict(conn->read_buf,
|
||||
(conn->read_pos - conn->read_buf), &request_dict)))
|
||||
; /* FROMERR on input, ignore */
|
||||
; /* Schedule for more reading */
|
||||
|
||||
else {
|
||||
conn->to_answer++;
|
||||
} else {
|
||||
/* Ready for reading a new packet */
|
||||
|
||||
/* 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, GETDNS_CALLBACK_COMPLETE,
|
||||
request_dict, conn->super.l->set->userarg, (intptr_t)conn);
|
||||
if (!(r = getdns_wire2msg_dict(conn->read_buf,
|
||||
(conn->read_pos - conn->read_buf), &request_dict))) {
|
||||
|
||||
conn->to_answer++;
|
||||
|
||||
/* TODO: wish list item:
|
||||
* (void) getdns_dict_set_int64(
|
||||
* request_dict, "request_id", intptr_t)conn);
|
||||
*/
|
||||
/* Call request handler */
|
||||
|
||||
conn->to_answer += 1; /* conn removal protection */
|
||||
conn->super.l->set->handler(
|
||||
conn->super.l->set->context,
|
||||
GETDNS_CALLBACK_COMPLETE, request_dict,
|
||||
conn->super.l->set->userarg, (intptr_t)conn);
|
||||
conn->to_answer -= 1; /* conn removal protection */
|
||||
|
||||
if (conn->fd == -1) {
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
conn->read_pos = conn->read_buf;
|
||||
conn->to_read = 2;
|
||||
return; /* Read more requests */
|
||||
; /* Schedule for more reading */
|
||||
}
|
||||
conn->read_pos = conn->read_buf;
|
||||
conn->to_read = 2;
|
||||
/* Read more requests */
|
||||
if (!conn->event.ev) { /* event not scheduled */
|
||||
conn->event.write_cb = conn->to_write ? tcp_write_cb : NULL;
|
||||
(void) loop->vmt->schedule(loop, conn->fd,
|
||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_timeout_cb(void *userarg)
|
||||
{
|
||||
tcp_connection *conn = (tcp_connection *)userarg;
|
||||
getdns_eventloop *loop;
|
||||
|
||||
assert(userarg);
|
||||
|
||||
if (conn->to_answer) {
|
||||
getdns_eventloop *loop;
|
||||
if (getdns_context_get_eventloop(
|
||||
conn->super.l->set->context, &loop))
|
||||
return;
|
||||
|
||||
if (getdns_context_get_eventloop(
|
||||
conn->super.l->set->context, &loop))
|
||||
return;
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
|
||||
loop->vmt->clear(loop, &conn->event);
|
||||
if (conn->to_answer && conn->fd >= 0) {
|
||||
(void) loop->vmt->schedule(loop,
|
||||
conn->fd, DOWNSTREAM_IDLE_TIMEOUT,
|
||||
&conn->event);
|
||||
|
@ -501,8 +565,10 @@ static void tcp_accept_cb(void *userarg)
|
|||
GETDNS_FREE(*mf, conn);
|
||||
return;
|
||||
}
|
||||
getdns_sock_nonblock(conn->fd);
|
||||
if (!(conn->read_buf = malloc(DNS_REQUEST_SZ))) {
|
||||
/* Memory error */
|
||||
(void) _getdns_closesocket(conn->fd);
|
||||
GETDNS_FREE(*mf, conn);
|
||||
return;
|
||||
}
|
||||
|
@ -518,6 +584,7 @@ static void tcp_accept_cb(void *userarg)
|
|||
if (!_getdns_rbtree_insert(
|
||||
&l->set->connections_set, &conn->super.super)) {
|
||||
/* Memory error */
|
||||
(void) _getdns_closesocket(conn->fd);
|
||||
GETDNS_FREE(*mf, conn);
|
||||
return;
|
||||
}
|
||||
|
@ -689,11 +756,16 @@ static void free_listen_set_when_done(listen_set *set)
|
|||
for (i = 0; i < set->count; i++) {
|
||||
listener *l = &set->items[i];
|
||||
|
||||
if (l->fd >= 0)
|
||||
if (l->fd >= 0) {
|
||||
DEBUG_SERVER("Listener %d still listening on %d\n",
|
||||
(int)i, l->fd);
|
||||
return;
|
||||
|
||||
if (l->connections)
|
||||
}
|
||||
if (l->connections) {
|
||||
DEBUG_SERVER("Listener %d still has connections %p\n",
|
||||
(int)i, (void *)l->connections);
|
||||
return;
|
||||
}
|
||||
}
|
||||
GETDNS_FREE(*mf, set);
|
||||
DEBUG_SERVER("Listen set: %p freed\n", (void *)set);
|
||||
|
@ -730,8 +802,17 @@ static void remove_listeners(listen_set *set)
|
|||
|
||||
conn_p = (tcp_connection **)&l->connections;
|
||||
while (*conn_p) {
|
||||
tcp_connection *prev_conn_p = *conn_p;
|
||||
|
||||
loop->vmt->clear(loop, &(*conn_p)->event);
|
||||
tcp_connection_destroy(*conn_p);
|
||||
if (*conn_p && (*conn_p)->to_answer > 0)
|
||||
/* tcp_connection_destroy() updates the pointer to the
|
||||
* connection. For the first connection this is
|
||||
* l->connections. When the connection is not actually
|
||||
* destroyed, the value of *conn_p thus remains the
|
||||
* same. When it is destroyed it is updated.
|
||||
*/
|
||||
if (*conn_p == prev_conn_p)
|
||||
conn_p = (tcp_connection **)
|
||||
&(*conn_p)->super.next;
|
||||
}
|
||||
|
@ -779,9 +860,15 @@ static getdns_return_t add_listeners(listen_set *set)
|
|||
break;
|
||||
|
||||
if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&enable, sizeof(int)) < 0) {
|
||||
&enable, sizeof(enable)) < 0) {
|
||||
; /* Ignore */
|
||||
}
|
||||
#if defined(HAVE_DECL_TCP_FASTOPEN) && HAVE_DECL_TCP_FASTOPEN
|
||||
if (setsockopt(l->fd, IPPROTO_TCP, TCP_FASTOPEN,
|
||||
&enable, sizeof(enable)) < 0) {
|
||||
; /* Ignore */
|
||||
}
|
||||
#endif
|
||||
if (bind(l->fd, (struct sockaddr *)&l->addr,
|
||||
l->addr_len) == -1)
|
||||
/* IO error */
|
||||
|
@ -891,6 +978,7 @@ getdns_return_t getdns_context_set_listen_addresses(
|
|||
|
||||
(void) memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
for (i = 0; !r && i < new_set_count; i++) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit dd093e585a237e0321d303ec35e84c393ef739f4
|
579
src/stub.c
579
src/stub.c
|
@ -39,9 +39,6 @@
|
|||
#define INTERCEPT_COM_DS 0
|
||||
|
||||
#include "debug.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <fcntl.h>
|
||||
#include "stub.h"
|
||||
#include "gldns/gbuffer.h"
|
||||
|
@ -109,7 +106,7 @@ rollover_secret()
|
|||
return;
|
||||
|
||||
/* Remember previous secret, in to keep answering on rollover
|
||||
* boundry with old cookie.
|
||||
* boundary with old cookie.
|
||||
*/
|
||||
prev_secret = secret;
|
||||
secret = arc4random();
|
||||
|
@ -124,10 +121,8 @@ rollover_secret()
|
|||
static void
|
||||
calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
EVP_MD_CTX *mdctx;
|
||||
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_len;
|
||||
unsigned char md_value[GETDNS_TLS_MAX_DIGEST_LENGTH];
|
||||
size_t md_len;
|
||||
size_t i;
|
||||
sa_family_t af = upstream->addr.ss_family;
|
||||
void *sa_addr = ((struct sockaddr*)&upstream->addr)->sa_data;
|
||||
|
@ -135,13 +130,7 @@ calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie)
|
|||
: af == AF_INET ? sizeof(struct sockaddr_in)
|
||||
: 0 ) - sizeof(sa_family_t);
|
||||
|
||||
md = EVP_sha256();
|
||||
mdctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit_ex(mdctx, md, NULL);
|
||||
EVP_DigestUpdate(mdctx, &secret, sizeof(secret));
|
||||
EVP_DigestUpdate(mdctx, sa_addr, addr_len);
|
||||
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
_getdns_tls_cookie_sha256(secret, sa_addr, addr_len, md_value, &md_len);
|
||||
|
||||
(void) memset(cookie, 0, 8);
|
||||
for (i = 0; i < md_len; i++)
|
||||
|
@ -341,6 +330,7 @@ process_keepalive(
|
|||
}
|
||||
return;
|
||||
}
|
||||
upstream->server_keepalive_received = 1;
|
||||
/* 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;
|
||||
|
@ -385,22 +375,24 @@ getdns_sock_nonblock(int sockfd)
|
|||
static int
|
||||
tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
|
||||
{
|
||||
#if defined(TCP_FASTOPEN) || defined(TCP_FASTOPEN_CONNECT)
|
||||
# ifdef USE_WINSOCK
|
||||
static const char enable = 1;
|
||||
# else
|
||||
static const int enable = 1;
|
||||
# endif
|
||||
#endif
|
||||
int fd = -1;
|
||||
|
||||
|
||||
upstream->tfo_use_sendto = 0;
|
||||
DEBUG_STUB("%s %-35s: Creating TCP connection: %p\n", STUB_DEBUG_SETUP,
|
||||
__FUNC__, (void*)upstream);
|
||||
if ((fd = socket(upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
|
||||
return -1;
|
||||
|
||||
getdns_sock_nonblock(fd);
|
||||
/* Note that error detection is different with TFO. Since the handshake
|
||||
doesn't start till the sendto() lack of connection is often delayed until
|
||||
then or even the subsequent event depending on the error and platform.*/
|
||||
#ifdef USE_TCP_FASTOPEN
|
||||
/* Leave the connect to the later call to sendto() if using TCP*/
|
||||
if (transport == GETDNS_TRANSPORT_TCP)
|
||||
return fd;
|
||||
#elif USE_OSX_TCP_FASTOPEN
|
||||
(void)transport;
|
||||
#ifdef USE_OSX_TCP_FASTOPEN
|
||||
sa_endpoints_t endpoints;
|
||||
endpoints.sae_srcif = 0;
|
||||
endpoints.sae_srcaddr = NULL;
|
||||
|
@ -415,9 +407,58 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
|
|||
if (_getdns_socketerror() == _getdns_EINPROGRESS ||
|
||||
_getdns_socketerror() == _getdns_EWOULDBLOCK)
|
||||
return fd;
|
||||
#else
|
||||
|
||||
(void)transport;
|
||||
#endif
|
||||
#else /* USE_OSX_TCP_FASTOPEN */
|
||||
/* Note that error detection is different with TFO. Since the handshake
|
||||
doesn't start till the sendto() lack of connection is often delayed until
|
||||
then or even the subsequent event depending on the error and platform.*/
|
||||
# if defined(HAVE_DECL_TCP_FASTOPEN_CONNECT) && HAVE_DECL_TCP_FASTOPEN_CONNECT
|
||||
if (setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT
|
||||
, (void *)&enable, sizeof(enable)) < 0) {
|
||||
/* runtime fallback to TCP_FASTOPEN option */
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING,
|
||||
"%-40s : Upstream : "
|
||||
"Could not setup TLS capable TFO connect\n",
|
||||
upstream->addr_str);
|
||||
# if defined(HAVE_DECL_TCP_FASTOPEN) && HAVE_DECL_TCP_FASTOPEN
|
||||
/* TCP_FASTOPEN works for TCP only (not TLS) */
|
||||
if (transport != GETDNS_TRANSPORT_TCP)
|
||||
; /* This variant of TFO doesn't work with TLS */
|
||||
else if (setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN
|
||||
, (void *)&enable, sizeof(enable)) >= 0) {
|
||||
|
||||
upstream->tfo_use_sendto = 1;
|
||||
return fd;
|
||||
} else
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING,
|
||||
"%-40s : Upstream : "
|
||||
"Could not fallback to TCP TFO\n",
|
||||
upstream->addr_str);
|
||||
# endif/* HAVE_DECL_TCP_FASTOPEN*/
|
||||
}
|
||||
/* On success regular connect is fine, TFO will happen automagically */
|
||||
# else /* HAVE_DECL_TCP_FASTOPEN_CONNECT */
|
||||
# if defined(HAVE_DECL_TCP_FASTOPEN) && HAVE_DECL_TCP_FASTOPEN
|
||||
/* TCP_FASTOPEN works for TCP only (not TLS) */
|
||||
if (transport != GETDNS_TRANSPORT_TCP)
|
||||
; /* This variant of TFO doesn't work with TLS */
|
||||
else if (setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN
|
||||
, (void *)&enable, sizeof(enable)) >= 0) {
|
||||
|
||||
upstream->tfo_use_sendto = 1;
|
||||
return fd;
|
||||
} else
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING,
|
||||
"%-40s : Upstream : Could not setup TCP TFO\n",
|
||||
upstream->addr_str);
|
||||
|
||||
# endif/* HAVE_DECL_TCP_FASTOPEN*/
|
||||
# endif /* HAVE_DECL_TCP_FASTOPEN_CONNECT */
|
||||
#endif /* USE_OSX_TCP_FASTOPEN */
|
||||
if (connect(fd, (struct sockaddr *)&upstream->addr,
|
||||
upstream->addr_len) == -1) {
|
||||
if (_getdns_socketerror() == _getdns_EINPROGRESS ||
|
||||
|
@ -456,8 +497,13 @@ stub_next_upstream(getdns_network_req *netreq)
|
|||
{
|
||||
getdns_dns_req *dnsreq = netreq->owner;
|
||||
|
||||
if (! --netreq->upstream->to_retry)
|
||||
netreq->upstream->to_retry = -(netreq->upstream->back_off *= 2);
|
||||
if (! --netreq->upstream->to_retry) {
|
||||
/* Limit back_off value to configured maximum */
|
||||
if (netreq->upstream->back_off * 2 > dnsreq->context->max_backoff_value)
|
||||
netreq->upstream->to_retry = -(dnsreq->context->max_backoff_value);
|
||||
else
|
||||
netreq->upstream->to_retry = -(netreq->upstream->back_off *= 2);
|
||||
}
|
||||
|
||||
dnsreq->upstreams->current_udp+=GETDNS_UPSTREAM_TRANSPORTS;
|
||||
if (dnsreq->upstreams->current_udp >= dnsreq->upstreams->count)
|
||||
|
@ -529,11 +575,7 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
|
|||
the queries if there is only one upstream.*/
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
if (during_setup) {
|
||||
/* 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 &&
|
||||
upstream->tls_auth_state == GETDNS_AUTH_FAILED))
|
||||
upstream->conn_setup_failed++;
|
||||
upstream->conn_setup_failed++;
|
||||
} else {
|
||||
upstream->conn_shutdowns++;
|
||||
/* [TLS1]TODO: Re-try these queries if possible.*/
|
||||
|
@ -580,7 +622,7 @@ stub_timeout_cb(void *userarg)
|
|||
netreq->upstream->udp_timeouts++;
|
||||
if (netreq->upstream->udp_timeouts % 100 == 0)
|
||||
_getdns_upstream_log(netreq->upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO,
|
||||
"%-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
|
||||
"%-40s : Upstream : UDP - Resps=%6d, Timeouts =%6d (logged every 100 responses)\n",
|
||||
netreq->upstream->addr_str,
|
||||
(int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts);
|
||||
stub_next_upstream(netreq);
|
||||
|
@ -746,20 +788,24 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
* Lets see how much of it we can write
|
||||
*/
|
||||
/* We use sendto() here which will do both a connect and send */
|
||||
#ifdef USE_TCP_FASTOPEN
|
||||
written = sendto(fd, netreq->query - 2, pkt_len + 2,
|
||||
MSG_FASTOPEN, (struct sockaddr *)&(netreq->upstream->addr),
|
||||
netreq->upstream->addr_len);
|
||||
/* If pipelining we will find that the connection is already up so
|
||||
just fall back to a 'normal' write. */
|
||||
if (written == -1 && _getdns_socketerror() == _getdns_EISCONN)
|
||||
written = write(fd, netreq->query - 2, pkt_len + 2);
|
||||
#else
|
||||
written = sendto(fd, (const char *)(netreq->query - 2),
|
||||
pkt_len + 2, 0,
|
||||
(struct sockaddr *)&(netreq->upstream->addr),
|
||||
netreq->upstream->addr_len);
|
||||
#endif
|
||||
if (netreq->upstream->tfo_use_sendto) {
|
||||
written = sendto(fd, netreq->query - 2, pkt_len + 2,
|
||||
# if defined(HAVE_DECL_MSG_FASTOPEN) && HAVE_DECL_MSG_FASTOPEN
|
||||
MSG_FASTOPEN,
|
||||
# else
|
||||
0,
|
||||
# endif
|
||||
(struct sockaddr *)&(netreq->upstream->addr),
|
||||
netreq->upstream->addr_len);
|
||||
/* If pipelining we will find that the connection is already up so
|
||||
just fall back to a 'normal' write. */
|
||||
if (written == -1
|
||||
&& _getdns_socketerror() == _getdns_EISCONN)
|
||||
written = write(fd, netreq->query - 2
|
||||
, pkt_len + 2);
|
||||
} else
|
||||
written = send(fd, (const char *)(netreq->query - 2)
|
||||
, pkt_len + 2, 0);
|
||||
if ((written == -1 && _getdns_socketerror_wants_retry()) ||
|
||||
(size_t)written < pkt_len + 2) {
|
||||
|
||||
|
@ -827,108 +873,46 @@ tls_requested(getdns_network_req *netreq)
|
|||
1 : 0;
|
||||
}
|
||||
|
||||
int
|
||||
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;
|
||||
|
||||
int err = X509_STORE_CTX_get_error(ctx);
|
||||
#if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
DEBUG_STUB("%s %-35s: FD: %d Verify result: (%d) \"%s\"\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err,
|
||||
X509_verify_cert_error_string(err));
|
||||
#endif
|
||||
if (!preverify_ok && !upstream->tls_fallback_ok)
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
|
||||
"%-40s : Verify failed : Transport=TLS - *Failure* - (%d) \"%s\"\n",
|
||||
upstream->addr_str, err,
|
||||
X509_verify_cert_error_string(err));
|
||||
|
||||
/* First deal with the hostname authentication done by OpenSSL. */
|
||||
#ifdef X509_V_ERR_HOSTNAME_MISMATCH
|
||||
# if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
/*Report if error is hostname mismatch*/
|
||||
if (err == X509_V_ERR_HOSTNAME_MISMATCH && upstream->tls_fallback_ok)
|
||||
DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
|
||||
# endif
|
||||
#else
|
||||
/* if we weren't built against OpenSSL with hostname matching we
|
||||
* could not have matched the hostname, so this would be an automatic
|
||||
* tls_auth_fail if there is a hostname provided*/
|
||||
if (upstream->tls_auth_name[0]) {
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
preverify_ok = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now deal with the pinset validation*/
|
||||
if (upstream->tls_pubkey_pinset)
|
||||
pinset_ret = _getdns_verify_pinset_match(upstream->tls_pubkey_pinset, ctx);
|
||||
|
||||
if (pinset_ret != GETDNS_RETURN_GOOD) {
|
||||
DEBUG_STUB("%s %-35s: FD: %d, WARNING: Pinset validation failure!\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
|
||||
preverify_ok = 0;
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
if (upstream->tls_fallback_ok)
|
||||
DEBUG_STUB("%s %-35s: FD: %d, WARNING: Proceeding even though pinset validation failed!\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
|
||||
else
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
|
||||
"%-40s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n",
|
||||
upstream->addr_str);
|
||||
} else {
|
||||
/* If we _only_ had a pinset and it is good then force succesful
|
||||
authentication when the cert self-signed
|
||||
TODO: We need to check for other error cases here, not blindly accept the cert!! */
|
||||
if ((upstream->tls_pubkey_pinset && upstream->tls_auth_name[0] == '\0') &&
|
||||
(err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
|
||||
err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)) {
|
||||
preverify_ok = 1;
|
||||
DEBUG_STUB("%s %-35s: FD: %d, Allowing self-signed (%d) cert since pins match\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err);
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
|
||||
"%-40s : Verify passed : Transport=TLS - Allowing self-signed cert since pins match\n",
|
||||
upstream->addr_str);
|
||||
}
|
||||
}
|
||||
|
||||
/* If nothing has failed yet and we had credentials, we have succesfully authenticated*/
|
||||
if (preverify_ok == 0)
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
else if (upstream->tls_auth_state == GETDNS_AUTH_NONE &&
|
||||
(upstream->tls_pubkey_pinset || upstream->tls_auth_name[0]))
|
||||
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->tls_fallback_ok) ? 1 : preverify_ok;
|
||||
}
|
||||
|
||||
static SSL*
|
||||
static _getdns_tls_connection*
|
||||
tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
||||
{
|
||||
/* Create SSL instance */
|
||||
/* Create SSL instance and connect with a file descriptor */
|
||||
getdns_context *context = dnsreq->context;
|
||||
if (context->tls_ctx == NULL)
|
||||
return NULL;
|
||||
SSL* ssl = SSL_new(context->tls_ctx);
|
||||
if(!ssl)
|
||||
_getdns_tls_connection* tls = _getdns_tls_connection_new(&context->my_mf, context->tls_ctx, fd, &upstream->upstreams->log);
|
||||
if(!tls)
|
||||
return NULL;
|
||||
/* Connect the SSL object with a file descriptor */
|
||||
if(!SSL_set_fd(ssl,fd)) {
|
||||
SSL_free(ssl);
|
||||
|
||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||
|
||||
if (upstream->tls_curves_list)
|
||||
r = _getdns_tls_connection_set_curves_list(tls, upstream->tls_curves_list);
|
||||
if (!r && upstream->tls_ciphersuites)
|
||||
r = _getdns_tls_connection_set_cipher_suites(tls, upstream->tls_ciphersuites);
|
||||
if (!r)
|
||||
r = _getdns_tls_connection_set_min_max_tls_version(tls, upstream->tls_min_version, upstream->tls_max_version);
|
||||
|
||||
if (!r)
|
||||
{
|
||||
if (upstream->tls_fallback_ok)
|
||||
r = _getdns_tls_connection_set_cipher_list(tls, NULL);
|
||||
else if (upstream->tls_cipher_list)
|
||||
r = _getdns_tls_connection_set_cipher_list(tls, upstream->tls_cipher_list);
|
||||
}
|
||||
|
||||
if (r) {
|
||||
_getdns_tls_connection_free(&upstream->upstreams->mf, tls);
|
||||
upstream->tls_auth_state = GETDNS_AUTH_NONE;
|
||||
return NULL;
|
||||
}
|
||||
/* make sure we'll be able to find the context again when we need it */
|
||||
if (_getdns_associate_upstream_with_SSL(ssl, upstream) != GETDNS_RETURN_GOOD) {
|
||||
SSL_free(ssl);
|
||||
return NULL;
|
||||
|
||||
if (upstream->tls_fallback_ok) {
|
||||
DEBUG_STUB("%s %-35s: WARNING: Using Opportunistic TLS (fallback allowed)!\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
} else {
|
||||
DEBUG_STUB("%s %-35s: Using Strict TLS \n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
}
|
||||
|
||||
/* NOTE: this code will fallback on a given upstream, without trying
|
||||
|
@ -941,24 +925,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
/*Request certificate for the auth_name*/
|
||||
DEBUG_STUB("%s %-35s: Hostname verification requested for: %s\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->tls_auth_name);
|
||||
SSL_set_tlsext_host_name(ssl, upstream->tls_auth_name);
|
||||
#ifdef HAVE_SSL_HN_AUTH
|
||||
/* Set up native OpenSSL hostname verification*/
|
||||
X509_VERIFY_PARAM *param;
|
||||
param = SSL_get0_param(ssl);
|
||||
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
X509_VERIFY_PARAM_set1_host(param, upstream->tls_auth_name, 0);
|
||||
#else
|
||||
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) {
|
||||
DEBUG_STUB("%s %-35s: ERROR: Hostname Authentication not available from TLS library (check library version)\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
|
||||
"%-40s : ERROR: Hostname Authentication not available from TLS library (check library version)\n",
|
||||
upstream->addr_str);
|
||||
upstream->tls_hs_state = GETDNS_HS_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
_getdns_tls_connection_setup_hostname_auth(tls, upstream->tls_auth_name);
|
||||
/* Allow fallback to opportunistic if settings permit it*/
|
||||
if (dnsreq->netreqs[0]->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
|
||||
upstream->tls_fallback_ok = 1;
|
||||
|
@ -970,9 +937,14 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
DEBUG_STUB("%s %-35s: Proceeding with only pubkey pinning authentication\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
} else {
|
||||
DEBUG_STUB("%s %-35s: ERROR: No host name or pubkey pinset provided for TLS authentication\n",
|
||||
DEBUG_STUB("%s %-35s: ERROR:No auth name or pinset provided for this upstream for Strict TLS authentication\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
|
||||
"%-40s : Verify fail: *CONFIG ERROR* - No auth name or pinset provided for this upstream for Strict TLS authentication\n",
|
||||
upstream->addr_str);
|
||||
upstream->tls_hs_state = GETDNS_HS_FAILED;
|
||||
_getdns_tls_connection_free(&upstream->upstreams->mf, tls);
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
|
@ -982,20 +954,8 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
upstream->tls_fallback_ok = 1;
|
||||
}
|
||||
}
|
||||
if (upstream->tls_fallback_ok) {
|
||||
SSL_set_cipher_list(ssl, "DEFAULT");
|
||||
DEBUG_STUB("%s %-35s: WARNING: Using Oppotunistic TLS (fallback allowed)!\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
} else {
|
||||
if (upstream->tls_cipher_list)
|
||||
SSL_set_cipher_list(ssl, upstream->tls_cipher_list);
|
||||
DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS,
|
||||
__FUNC__);
|
||||
}
|
||||
SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
|
||||
|
||||
SSL_set_connect_state(ssl);
|
||||
(void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
|
||||
_getdns_tls_connection_set_host_pinset(tls, upstream->tls_auth_name, upstream->tls_pubkey_pinset);
|
||||
|
||||
/* 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
|
||||
|
@ -1004,13 +964,12 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
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);
|
||||
_getdns_tls_connection_set_session(tls, upstream->tls_session);
|
||||
DEBUG_STUB("%s %-35s: Attempting session re-use\n", STUB_DEBUG_SETUP_TLS,
|
||||
__FUNC__);
|
||||
}
|
||||
}
|
||||
|
||||
return ssl;
|
||||
return tls;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1019,13 +978,10 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SETUP_TLS,
|
||||
__FUNC__, upstream->fd);
|
||||
int r;
|
||||
int want;
|
||||
ERR_clear_error();
|
||||
while ((r = SSL_do_handshake(upstream->tls_obj)) != 1)
|
||||
while ((r = _getdns_tls_connection_do_handshake(upstream->tls_obj)) != GETDNS_RETURN_GOOD)
|
||||
{
|
||||
want = SSL_get_error(upstream->tls_obj, r);
|
||||
switch (want) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
switch (r) {
|
||||
case GETDNS_RETURN_TLS_WANT_READ:
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
upstream->event.read_cb = upstream_read_cb;
|
||||
upstream->event.write_cb = NULL;
|
||||
|
@ -1033,7 +989,7 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
upstream->fd, TIMEOUT_TLS, &upstream->event);
|
||||
upstream->tls_hs_state = GETDNS_HS_READ;
|
||||
return STUB_TCP_RETRY;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
case GETDNS_RETURN_TLS_WANT_WRITE:
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
upstream->event.read_cb = NULL;
|
||||
upstream->event.write_cb = upstream_write_cb;
|
||||
|
@ -1043,24 +999,80 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
return STUB_TCP_RETRY;
|
||||
default:
|
||||
DEBUG_STUB("%s %-35s: FD: %d Handshake failed %d\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd,
|
||||
want);
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, r);
|
||||
return STUB_SETUP_ERROR;
|
||||
}
|
||||
}
|
||||
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))
|
||||
if (!_getdns_tls_connection_is_session_reused(upstream->tls_obj))
|
||||
upstream->tls_auth_state = upstream->last_tls_auth_state;
|
||||
|
||||
else if (upstream->tls_pubkey_pinset || upstream->tls_auth_name[0]) {
|
||||
_getdns_tls_x509* peer_cert = _getdns_tls_connection_get_peer_certificate(&upstream->upstreams->mf, upstream->tls_obj);
|
||||
|
||||
if (!peer_cert) {
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"Remote did not offer certificate\n",
|
||||
upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ));
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
} else {
|
||||
long verify_errno;
|
||||
const char* verify_errmsg;
|
||||
|
||||
if (_getdns_tls_connection_certificate_verify(upstream->tls_obj, &verify_errno, &verify_errmsg)) {
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
if (verify_errno != 0) {
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"(%ld) \"%s\"\n", upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ),
|
||||
verify_errno, verify_errmsg);
|
||||
} else {
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR), "%-40s : Verify failed : TLS - %s - "
|
||||
"%s\n", upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ),
|
||||
verify_errmsg);
|
||||
}
|
||||
} else {
|
||||
upstream->tls_auth_state = GETDNS_AUTH_OK;
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
|
||||
"%-40s : Verify passed : TLS\n",
|
||||
upstream->addr_str);
|
||||
}
|
||||
_getdns_tls_x509_free(&upstream->upstreams->mf, peer_cert);
|
||||
}
|
||||
if (upstream->tls_auth_state == GETDNS_AUTH_FAILED
|
||||
&& !upstream->tls_fallback_ok)
|
||||
return STUB_SETUP_ERROR;
|
||||
}
|
||||
DEBUG_STUB("%s %-35s: FD: %d Handshake succeeded with auth state %s. Session is %s.\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd,
|
||||
_getdns_auth_str(upstream->tls_auth_state),
|
||||
SSL_session_reused(upstream->tls_obj) ?"re-used":"new");
|
||||
_getdns_tls_connection_is_session_reused(upstream->tls_obj) ? "new" : "re-used");
|
||||
upstream->tls_hs_state = GETDNS_HS_DONE;
|
||||
upstream->conn_state = GETDNS_CONN_OPEN;
|
||||
upstream->conn_completed++;
|
||||
if (upstream->tls_session != NULL)
|
||||
SSL_SESSION_free(upstream->tls_session);
|
||||
upstream->tls_session = SSL_get1_session(upstream->tls_obj);
|
||||
_getdns_tls_session_free(&upstream->upstreams->mf, upstream->tls_session);
|
||||
upstream->tls_session = _getdns_tls_connection_get_session(&upstream->upstreams->mf, upstream->tls_obj);
|
||||
/* Reset timeout on success*/
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
upstream->event.read_cb = NULL;
|
||||
|
@ -1098,10 +1110,10 @@ static int
|
|||
stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
||||
struct mem_funcs *mf)
|
||||
{
|
||||
ssize_t read;
|
||||
size_t read;
|
||||
uint8_t *buf;
|
||||
size_t buf_size;
|
||||
SSL* tls_obj = upstream->tls_obj;
|
||||
_getdns_tls_connection* tls_obj = upstream->tls_obj;
|
||||
|
||||
int q = tls_connected(upstream);
|
||||
if (q != 0)
|
||||
|
@ -1117,17 +1129,14 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
tcp->to_read = 2; /* Packet size */
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read);
|
||||
if (read <= 0) {
|
||||
/* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake
|
||||
renegotiation. Need to keep handshake state to do that.*/
|
||||
int want = SSL_get_error(tls_obj, read);
|
||||
if (want == SSL_ERROR_WANT_READ) {
|
||||
return STUB_TCP_RETRY; /* Come back later */
|
||||
} else
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
getdns_return_t r = _getdns_tls_connection_read(tls_obj, tcp->read_pos, tcp->to_read, &read);
|
||||
/* TODO[TLS]: Handle GETDNS_RETURN_TLS_WANT_WRITE which means handshake
|
||||
renegotiation. Need to keep handshake state to do that.*/
|
||||
if (r == GETDNS_RETURN_TLS_WANT_READ)
|
||||
return STUB_TCP_RETRY;
|
||||
else if (r != GETDNS_RETURN_GOOD)
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
tcp->to_read -= read;
|
||||
tcp->read_pos += read;
|
||||
|
||||
|
@ -1158,15 +1167,17 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
|
||||
/* Ready to start reading the packet */
|
||||
tcp->read_pos = tcp->read_buf;
|
||||
read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read);
|
||||
if (read <= 0) {
|
||||
/* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake
|
||||
switch ((int)_getdns_tls_connection_read(tls_obj, tcp->read_pos, tcp->to_read, &read)) {
|
||||
case GETDNS_RETURN_GOOD:
|
||||
break;
|
||||
|
||||
case GETDNS_RETURN_TLS_WANT_READ:
|
||||
return STUB_TCP_RETRY; /* Come back later */
|
||||
|
||||
default:
|
||||
/* TODO[TLS]: Handle GETDNS_RETURN_TLS_WANT_WRITE which means handshake
|
||||
renegotiation. Need to keep handshake state to do that.*/
|
||||
int want = SSL_get_error(tls_obj, read);
|
||||
if (want == SSL_ERROR_WANT_READ) {
|
||||
return STUB_TCP_RETRY; /* read more later */
|
||||
} else
|
||||
return STUB_TCP_ERROR;
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
tcp->to_read -= read;
|
||||
tcp->read_pos += read;
|
||||
|
@ -1181,10 +1192,10 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
getdns_network_req *netreq)
|
||||
{
|
||||
size_t pkt_len;
|
||||
ssize_t written;
|
||||
size_t written;
|
||||
uint16_t query_id;
|
||||
intptr_t query_id_intptr;
|
||||
SSL* tls_obj = upstream->tls_obj;
|
||||
_getdns_tls_connection* tls_obj = upstream->tls_obj;
|
||||
uint16_t padding_sz;
|
||||
|
||||
int q = tls_connected(upstream);
|
||||
|
@ -1259,7 +1270,8 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
* Lets see how much of it we can write */
|
||||
|
||||
/* TODO[TLS]: Handle error cases, partial writes, renegotiation etc. */
|
||||
ERR_clear_error();
|
||||
getdns_return_t r;
|
||||
|
||||
#if INTERCEPT_COM_DS
|
||||
/* Intercept and do not sent out COM DS queries. For debugging
|
||||
* purposes only. Never commit with this turned on.
|
||||
|
@ -1274,25 +1286,16 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
|
||||
debug_req("Intercepting", netreq);
|
||||
written = pkt_len + 2;
|
||||
r = GETDNS_RETURN_GOOD;
|
||||
} else
|
||||
#endif
|
||||
written = SSL_write(tls_obj, netreq->query - 2, pkt_len + 2);
|
||||
if (written <= 0) {
|
||||
/* SSL_write will not do partial writes, because
|
||||
* SSL_MODE_ENABLE_PARTIAL_WRITE is not default,
|
||||
* but the write could fail because of renegotiation.
|
||||
* In that case SSL_get_error() will return
|
||||
* SSL_ERROR_WANT_READ or, SSL_ERROR_WANT_WRITE.
|
||||
* Return for retry in such cases.
|
||||
*/
|
||||
switch (SSL_get_error(tls_obj, written)) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
return STUB_TCP_RETRY;
|
||||
default:
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
}
|
||||
r = _getdns_tls_connection_write(tls_obj, netreq->query - 2, pkt_len + 2, &written);
|
||||
if (r == GETDNS_RETURN_TLS_WANT_READ ||
|
||||
r == GETDNS_RETURN_TLS_WANT_WRITE)
|
||||
return STUB_TCP_RETRY;
|
||||
else if (r != GETDNS_RETURN_GOOD)
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
/* We were able to write everything! Start reading. */
|
||||
return (int) query_id;
|
||||
|
||||
|
@ -1406,10 +1409,11 @@ stub_udp_read_cb(void *userarg)
|
|||
netreq->debug_end_time = _getdns_get_time_as_uintt64();
|
||||
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
|
||||
upstream->udp_responses++;
|
||||
upstream->back_off = 1;
|
||||
if (upstream->udp_responses == 1 ||
|
||||
upstream->udp_responses % 100 == 0)
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO,
|
||||
"%-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
|
||||
"%-40s : Upstream : UDP - Resps=%6d, Timeouts =%6d (logged every 100 responses)\n",
|
||||
upstream->addr_str,
|
||||
(int)upstream->udp_responses, (int)upstream->udp_timeouts);
|
||||
_getdns_check_dns_req_complete(dnsreq);
|
||||
|
@ -1456,7 +1460,7 @@ stub_udp_write_cb(void *userarg)
|
|||
, STUB_DEBUG_WRITE, __FUNC__, (void *)netreq
|
||||
, _getdns_errnostr());
|
||||
else
|
||||
DEBUG_STUB( "%s %-35s: MSG: %p returned: %d, expeced: %d\n"
|
||||
DEBUG_STUB( "%s %-35s: MSG: %p returned: %d, expected: %d\n"
|
||||
, STUB_DEBUG_WRITE, __FUNC__, (void *)netreq
|
||||
, (int)written, (int)pkt_len);
|
||||
#endif
|
||||
|
@ -1625,7 +1629,7 @@ upstream_write_cb(void *userarg)
|
|||
getdns_upstream *upstream = (getdns_upstream *)userarg;
|
||||
getdns_network_req *netreq = upstream->write_queue;
|
||||
int q;
|
||||
X509 *cert;
|
||||
_getdns_tls_x509 *cert;
|
||||
|
||||
if (!netreq) {
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
|
@ -1671,7 +1675,7 @@ upstream_write_cb(void *userarg)
|
|||
/* Cleaning up after connection or auth check failure. Need to fallback. */
|
||||
stub_cleanup(netreq);
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
|
||||
"%-40s : Conn closed : Transport=%s - *Failure*\n",
|
||||
"%-40s : Conn closed: %s - *Failure*\n",
|
||||
upstream->addr_str,
|
||||
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"));
|
||||
if (fallback_on_write(netreq) == STUB_TCP_ERROR) {
|
||||
|
@ -1686,12 +1690,13 @@ upstream_write_cb(void *userarg)
|
|||
remove_from_write_queue(upstream, netreq);
|
||||
|
||||
if (netreq->owner->return_call_reporting &&
|
||||
netreq->upstream->tls_obj &&
|
||||
netreq->debug_tls_peer_cert.data == NULL &&
|
||||
(cert = SSL_get_peer_certificate(netreq->upstream->tls_obj))) {
|
||||
netreq->debug_tls_peer_cert.size = i2d_X509(
|
||||
cert, &netreq->debug_tls_peer_cert.data);
|
||||
X509_free(cert);
|
||||
netreq->upstream->tls_obj) {
|
||||
if (netreq->debug_tls_peer_cert.data == NULL &&
|
||||
(cert = _getdns_tls_connection_get_peer_certificate(&upstream->upstreams->mf, netreq->upstream->tls_obj))) {
|
||||
_getdns_tls_x509_to_der(&upstream->upstreams->mf, cert, &netreq->debug_tls_peer_cert);
|
||||
_getdns_tls_x509_free(&upstream->upstreams->mf, cert);
|
||||
}
|
||||
netreq->debug_tls_version = _getdns_tls_connection_get_version(netreq->upstream->tls_obj);
|
||||
}
|
||||
/* Need this because auth status is reset on connection close */
|
||||
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
|
||||
|
@ -1786,9 +1791,9 @@ upstream_valid(getdns_upstream *upstream,
|
|||
getdns_network_req *netreq,
|
||||
int backoff_ok)
|
||||
{
|
||||
/* Checking upstreams with backoff_ok true will aslo return upstreams
|
||||
/* Checking upstreams with backoff_ok true will also return upstreams
|
||||
that are in a backoff state. Otherwise only use upstreams that have
|
||||
a 'good' connection state. backoff_ok is usefull when no upstreams at all
|
||||
a 'good' connection state. backoff_ok is useful when no upstreams at all
|
||||
are valid, for example when the network connection is down and need to
|
||||
keep trying to connect before failing completely. */
|
||||
if (!(upstream->transport == transport && upstream_usable(upstream, backoff_ok)))
|
||||
|
@ -1826,6 +1831,34 @@ upstream_valid_and_open(getdns_upstream *upstream,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
other_transports_working(getdns_network_req *netreq,
|
||||
getdns_upstreams *upstreams,
|
||||
getdns_transport_list_t transport)
|
||||
{
|
||||
size_t i,j;
|
||||
for (i = 0; i< netreq->transport_count;i++) {
|
||||
if (netreq->transports[i] == transport)
|
||||
continue;
|
||||
if (netreq->transports[i] == GETDNS_TRANSPORT_UDP) {
|
||||
for (j = 0; j < upstreams->count; j+=GETDNS_UPSTREAM_TRANSPORTS) {
|
||||
if (upstreams->upstreams[j].back_off == 1)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (netreq->transports[i] == GETDNS_TRANSPORT_TCP ||
|
||||
netreq->transports[i] == GETDNS_TRANSPORT_TLS) {
|
||||
for (j = 0; j < upstreams->count; j++) {
|
||||
if (netreq->transports[i] == upstreams->upstreams[j].transport &&
|
||||
upstream_valid(&upstreams->upstreams[j], netreq->transports[i],
|
||||
netreq, 0))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static getdns_upstream *
|
||||
upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t transport)
|
||||
{
|
||||
|
@ -1842,9 +1875,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;
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
|
||||
"%-40s : Re-instating upstream\n",
|
||||
upstreams->upstreams[i].addr_str);
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING,
|
||||
"%-40s : Upstream : Re-instating %s for this upstream\n",
|
||||
upstreams->upstreams[i].addr_str,
|
||||
upstreams->upstreams[i].transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1857,12 +1891,13 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
}
|
||||
|
||||
/* OK - Find the next one to use. First check we have at least one valid
|
||||
upstream (not backed-off) because we completely back off failed
|
||||
upstream (not backed-off). Because we completely back off failed
|
||||
upstreams we may have no valid upstream at all (in contrast to UDP).*/
|
||||
i = upstreams->current_stateful;
|
||||
do {
|
||||
DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP,
|
||||
__FUNC__, (int)i, (int)upstreams->upstreams[i].conn_state);
|
||||
DEBUG_STUB("%s %-35s: Testing upstreams %d %d for transport %d \n",
|
||||
STUB_DEBUG_SETUP, __FUNC__, (int)i,
|
||||
(int)upstreams->upstreams[i].conn_state, transport);
|
||||
if (upstream_valid(&upstreams->upstreams[i], transport, netreq, 0)) {
|
||||
upstream = &upstreams->upstreams[i];
|
||||
break;
|
||||
|
@ -1872,7 +1907,15 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
i = 0;
|
||||
} while (i != upstreams->current_stateful);
|
||||
if (!upstream) {
|
||||
/* Oh, oh. We have no valid upstreams. Try to find one that might work so
|
||||
/* Oh, oh. We have no valid upstreams for this transport. */
|
||||
/* If there are other fallback transports that are working, we should
|
||||
use them before forcibly promoting failed upstreams for re-try, since
|
||||
waiting for the the re-try timer to re-instate them is the right thing
|
||||
in this case. */
|
||||
if (other_transports_working(netreq, upstreams, transport))
|
||||
return NULL;
|
||||
|
||||
/* Try to find one that might work so
|
||||
allow backed off upstreams to be considered valid.
|
||||
Don't worry about the policy, just use the one with the least bad
|
||||
stats that still fits the bill (right transport, right authentication)
|
||||
|
@ -1902,8 +1945,9 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
upstream->conn_state = GETDNS_CONN_CLOSED;
|
||||
upstream->conn_backoff_interval = 1;
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
|
||||
"%-40s : No valid upstreams... promoting this backed-off upstream for re-try...\n",
|
||||
upstream->addr_str);
|
||||
"%-40s : Upstream : No valid upstreams for %s... promoting this backed-off upstream for re-try...\n",
|
||||
upstream->addr_str,
|
||||
upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP");
|
||||
return upstream;
|
||||
}
|
||||
|
||||
|
@ -1927,6 +1971,7 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
return upstream;
|
||||
}
|
||||
|
||||
/* Used for UDP only */
|
||||
static getdns_upstream *
|
||||
upstream_select(getdns_network_req *netreq)
|
||||
{
|
||||
|
@ -1936,6 +1981,7 @@ upstream_select(getdns_network_req *netreq)
|
|||
|
||||
if (!upstreams->count)
|
||||
return NULL;
|
||||
|
||||
/* First UPD/TCP upstream is always at i=0 and then start of each upstream block*/
|
||||
/* TODO: Have direct access to sets of upstreams for different transports*/
|
||||
for (i = 0; i < upstreams->count; i+=GETDNS_UPSTREAM_TRANSPORTS)
|
||||
|
@ -1953,14 +1999,18 @@ upstream_select(getdns_network_req *netreq)
|
|||
i = 0;
|
||||
} while (i != upstreams->current_udp);
|
||||
|
||||
/* Select upstream with the lowest back_off value */
|
||||
upstream = upstreams->upstreams;
|
||||
for (i = 0; i < upstreams->count; i+=GETDNS_UPSTREAM_TRANSPORTS)
|
||||
if (upstreams->upstreams[i].back_off <
|
||||
upstream->back_off)
|
||||
if (upstreams->upstreams[i].back_off < upstream->back_off)
|
||||
upstream = &upstreams->upstreams[i];
|
||||
|
||||
if (upstream->back_off > 1)
|
||||
upstream->back_off--;
|
||||
/* Restrict back_off in case no upstream is available to achieve
|
||||
(more or less) round-robin retry on all upstreams. */
|
||||
if (upstream->back_off > 4) {
|
||||
for (i = 0; i < upstreams->count; i+=GETDNS_UPSTREAM_TRANSPORTS)
|
||||
upstreams->upstreams[i].back_off = 2;
|
||||
}
|
||||
upstream->to_retry = 1;
|
||||
upstreams->current_udp = upstream - upstreams->upstreams;
|
||||
return upstream;
|
||||
|
@ -2071,17 +2121,22 @@ upstream_find_for_netreq(getdns_network_req *netreq)
|
|||
return STUB_TRY_AGAIN_LATER;
|
||||
return -1;
|
||||
}
|
||||
if (upstream == netreq->first_upstream)
|
||||
continue;
|
||||
|
||||
netreq->transport_current = i;
|
||||
netreq->upstream = upstream;
|
||||
if (!netreq->first_upstream)
|
||||
netreq->first_upstream = upstream;
|
||||
netreq->keepalive_sent = 0;
|
||||
|
||||
DEBUG_STUB("%s %-35s: MSG: %p found upstream %p with transport %d, fd: %d\n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq, (void *)upstream, (int)netreq->transports[i], fd);
|
||||
return fd;
|
||||
}
|
||||
/* Handle better, will give generic error*/
|
||||
DEBUG_STUB("%s %-35s: MSG: %p No valid upstream! \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq);
|
||||
_getdns_context_log(netreq->owner->context, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
|
||||
"*FAILURE* no valid transports or upstreams available!\n");
|
||||
_getdns_log(&netreq->owner->context->log
|
||||
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
|
||||
, " *FAILURE* no valid transports or upstreams available!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
10
src/sync.c
10
src/sync.c
|
@ -164,7 +164,7 @@ getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type,
|
|||
|
||||
getdns_return_t
|
||||
getdns_general_sync(getdns_context *context, const char *name,
|
||||
uint16_t request_type, getdns_dict *extensions, getdns_dict **response)
|
||||
uint16_t request_type, const getdns_dict *extensions, getdns_dict **response)
|
||||
{
|
||||
getdns_sync_data data;
|
||||
getdns_return_t r;
|
||||
|
@ -190,7 +190,7 @@ getdns_general_sync(getdns_context *context, const char *name,
|
|||
|
||||
getdns_return_t
|
||||
getdns_address_sync(getdns_context *context, const char *name,
|
||||
getdns_dict *extensions, getdns_dict **response)
|
||||
const getdns_dict *extensions, getdns_dict **response)
|
||||
{
|
||||
getdns_sync_data data;
|
||||
getdns_return_t r;
|
||||
|
@ -215,8 +215,8 @@ getdns_address_sync(getdns_context *context, const char *name,
|
|||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_hostname_sync(getdns_context *context, getdns_dict *address,
|
||||
getdns_dict *extensions, getdns_dict **response)
|
||||
getdns_hostname_sync(getdns_context *context, const getdns_dict *address,
|
||||
const getdns_dict *extensions, getdns_dict **response)
|
||||
{
|
||||
getdns_sync_data data;
|
||||
getdns_return_t r;
|
||||
|
@ -242,7 +242,7 @@ getdns_hostname_sync(getdns_context *context, getdns_dict *address,
|
|||
|
||||
getdns_return_t
|
||||
getdns_service_sync(getdns_context *context, const char *name,
|
||||
getdns_dict *extensions, getdns_dict **response)
|
||||
const getdns_dict *extensions, getdns_dict **response)
|
||||
{
|
||||
getdns_sync_data data;
|
||||
getdns_return_t r;
|
||||
|
|
|
@ -178,7 +178,7 @@
|
|||
{
|
||||
/*
|
||||
* name = "localhost" name should be resolved from host file
|
||||
* expect: NOERROR/NODATA response:
|
||||
* expect: NOERROR response:
|
||||
* status = GETDNS_RESPSTATUS_GOOD
|
||||
* rcode = 0
|
||||
* ancount = 1 (number of records in ANSWER section)
|
||||
|
@ -192,7 +192,7 @@
|
|||
CONTEXT_CREATE(TRUE);
|
||||
EVENT_BASE_CREATE;
|
||||
|
||||
ASSERT_RC(getdns_address(context, "localhost", NULL,
|
||||
ASSERT_RC(getdns_address(context, "localhost.", NULL,
|
||||
&fn_ref, &transaction_id, callbackfn),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_address()");
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@
|
|||
|
||||
CONTEXT_CREATE(TRUE);
|
||||
|
||||
ASSERT_RC(getdns_address_sync(context, "localhost", NULL, &response),
|
||||
ASSERT_RC(getdns_address_sync(context, "localhost.", NULL, &response),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()");
|
||||
|
||||
EXTRACT_LOCAL_RESPONSE;
|
||||
|
@ -147,7 +147,7 @@
|
|||
/*
|
||||
* name = "willem.getdnsapi.net" need to replace this with domain from unbound zone
|
||||
* expect: NOERROR/NODATA response:
|
||||
* status = GETDNS_RESPSTATUS_GOOD
|
||||
* status = GETDNS_RESPSTATUS_NO_DATA
|
||||
* rcode = 0
|
||||
* ancount = 0 (number of records in ANSWER section)
|
||||
*/
|
||||
|
@ -162,6 +162,7 @@
|
|||
EXTRACT_RESPONSE;
|
||||
|
||||
assert_noerror(&ex_response);
|
||||
assert_nodata(&ex_response);
|
||||
//assert_soa_in_authority(&ex_response);
|
||||
|
||||
CONTEXT_DESTROY;
|
||||
|
|
|
@ -70,6 +70,7 @@ void extract_response(struct getdns_dict *response, struct extracted_response *e
|
|||
* If it is absent, do not try to decompose the replies_tree, because the
|
||||
* answer most likely came not from DNS.
|
||||
*/
|
||||
ex_response->response = response;
|
||||
have_answer_type = getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type) ==
|
||||
GETDNS_RETURN_GOOD;
|
||||
|
||||
|
@ -159,10 +160,15 @@ void extract_local_response(struct getdns_dict *response, struct extracted_respo
|
|||
void assert_noerror(struct extracted_response *ex_response)
|
||||
{
|
||||
uint32_t rcode;
|
||||
uint32_t ancount = 0;
|
||||
|
||||
ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\"");
|
||||
ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\"");
|
||||
ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode);
|
||||
|
||||
ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount),
|
||||
GETDNS_RETURN_GOOD, "Failed to extract \"ancount\"");
|
||||
|
||||
ASSERT_RC(ex_response->status, ((ancount > 0) ? GETDNS_RESPSTATUS_GOOD : GETDNS_RESPSTATUS_NO_NAME), "Unexpected value for \"status\"");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -181,6 +187,8 @@ void assert_nodata(struct extracted_response *ex_response)
|
|||
ASSERT_RC(getdns_list_get_length(ex_response->answer, &length),
|
||||
GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length");
|
||||
ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length);
|
||||
|
||||
ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_NO_NAME, "Unexpected value for \"status\"");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -233,11 +241,14 @@ void assert_address_in_answer(struct extracted_response *ex_response, int a, int
|
|||
*/
|
||||
void assert_address_in_just_address_answers(struct extracted_response *ex_response)
|
||||
{
|
||||
size_t length;
|
||||
size_t length = 0;
|
||||
char *resp_str = "";
|
||||
ASSERT_RC(getdns_list_get_length(ex_response->just_address_answers, &length),
|
||||
GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\" length");
|
||||
|
||||
ck_assert_msg(length > 0, "Expected \"just_address_answers\" length > 0, got %d", length);
|
||||
|
||||
if (length == 0) resp_str = getdns_pretty_print_dict(ex_response->response);
|
||||
ck_assert_msg(length > 0, "Expected \"just_address_answers\" length > 0, got %d\n%s", length, resp_str);
|
||||
if (length == 0) free(resp_str);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
struct extracted_response {
|
||||
uint32_t top_answer_type;
|
||||
struct getdns_dict *response;
|
||||
struct getdns_bindata *top_canonical_name;
|
||||
struct getdns_list *just_address_answers;
|
||||
struct getdns_list *replies_full;
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
getdns_bindata *version_str = NULL;
|
||||
|
||||
/* Note that stricly this test just establishes that the requested transport
|
||||
and the reported transport are consistent, it does not guarentee which
|
||||
and the reported transport are consistent, it does not guarantee which
|
||||
transport is used on the wire...*/
|
||||
|
||||
CONTEXT_CREATE(TRUE);
|
||||
|
@ -264,8 +264,6 @@
|
|||
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()");
|
||||
ASSERT_RC(getdns_context_set_edns_maximum_udp_payload_size(context, 512),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_edns_maximum_udp_payload_size()");
|
||||
ASSERT_RC(getdns_context_set_timeout(context, 2000),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_edns_maximum_udp_payload_size()");
|
||||
ASSERT_RC(getdns_general_sync(context, "large.getdnsapi.net", GETDNS_RRTYPE_TXT, extensions, &response),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()");
|
||||
|
||||
|
@ -292,17 +290,14 @@
|
|||
struct getdns_dict *extensions = getdns_dict_create();
|
||||
|
||||
/*
|
||||
* Not all servers in the path to large.getdnsapi.net seem to support
|
||||
* TCP consistently. Many (root) servers are anycasted which decreases
|
||||
* reliability of TCP availability (as we've seen in practice).
|
||||
* To mitigate we provide our own root server for which we are sure that
|
||||
* it supports TCP. The .net authoritative server are still out of our
|
||||
* control tough. But because they are managed by a single party I
|
||||
* suspect them to be a bit more reliable.
|
||||
* Not all root servers seem to support TCP reliably. To mitigate,
|
||||
* we put our faith in k.root-servers.net.
|
||||
*/
|
||||
struct getdns_list *root_servers = getdns_list_create();
|
||||
struct getdns_list *root_servers2 = getdns_list_create();
|
||||
struct getdns_bindata nlnetlabs_root = { 4, (void *)"\xB9\x31\x8D\x25" };
|
||||
struct getdns_bindata k4_root = { 4, (void *)"\xC1\x00\x0E\x81" };
|
||||
struct getdns_bindata k6_root = { 16, (void *)
|
||||
"\x20\x01\x07\xFD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" };
|
||||
struct getdns_bindata *answer = NULL;
|
||||
|
||||
uint32_t status;
|
||||
|
@ -319,7 +314,9 @@
|
|||
/* Re-do over TCP */
|
||||
ASSERT_RC(getdns_dict_set_int(extensions,"return_call_reporting", GETDNS_EXTENSION_TRUE),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()");
|
||||
ASSERT_RC(getdns_list_set_bindata(root_servers, 0, &nlnetlabs_root),
|
||||
ASSERT_RC(getdns_list_set_bindata(root_servers, 0, &k6_root),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()");
|
||||
ASSERT_RC(getdns_list_set_bindata(root_servers, 1, &k4_root),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()");
|
||||
|
||||
ASSERT_RC(getdns_context_set_dns_root_servers(context, root_servers),
|
||||
|
@ -328,8 +325,13 @@
|
|||
GETDNS_RETURN_GOOD, "Return code from getdns_context_get_dns_root_servers()");
|
||||
ASSERT_RC(getdns_list_get_bindata(root_servers2, 0, &answer),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_list_get_bindata()");
|
||||
ck_assert_msg(strncmp((char *)answer->data, (char *)nlnetlabs_root.data, 4) == 0,
|
||||
"Expected answer data to be 185.49.141.37");
|
||||
ck_assert_msg(strncmp((char *)answer->data, (char *)k6_root.data, 16) == 0,
|
||||
"Expected answer data to be 2001:7fd::1");
|
||||
ASSERT_RC(getdns_list_get_bindata(root_servers2, 1, &answer),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_list_get_bindata()");
|
||||
ck_assert_msg(strncmp((char *)answer->data, (char *)k4_root.data, 4) == 0,
|
||||
"Expected answer data to be 193.0.14.129");
|
||||
|
||||
ASSERT_RC(getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TCP_ONLY),
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()");
|
||||
ASSERT_RC(getdns_context_set_edns_maximum_udp_payload_size(context, 512),
|
||||
|
|
|
@ -146,7 +146,7 @@
|
|||
* name = "google.com"
|
||||
* request_type = 0 (minimum valid RRTYPE)
|
||||
* expect: NOERROR/NODATA response:
|
||||
* status = GETDNS_RESPSTATUS_GOOD
|
||||
* status = GETDNS_RESPSTATUS_NO_NAME
|
||||
* rcode = 0
|
||||
* ancount = 0 (number of records in ANSWER section)
|
||||
*/
|
||||
|
@ -180,7 +180,7 @@
|
|||
* name = "google.com"
|
||||
* request_type = 65279 (maximum unassigned RRTYPE)
|
||||
* expect: NOERROR/NODATA response:
|
||||
* status = GETDNS_RESPSTATUS_GOOD
|
||||
* status = GETDNS_RESPSTATUS_NO_NAME
|
||||
* rcode = 0
|
||||
* ancount = 0 (number of records in ANSWER section)
|
||||
*/
|
||||
|
@ -322,7 +322,7 @@
|
|||
* name = "willem.getdnsapi.net" and unbound zone
|
||||
* request_type = GETDNS_RRTYPE_MX
|
||||
* expect: NOERROR/NODATA response:
|
||||
* status = GETDNS_RESPSTATUS_GOOD
|
||||
* status = GETDNS_RESPSTATUS_NO_NAME
|
||||
* rcode = 0
|
||||
* ancount = 0 (number of records in ANSWER section)
|
||||
*/
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
* name = "google.com"
|
||||
* request_type = 0 (minimum valid RRTYPE)
|
||||
* expect: NOERROR/NODATA response:
|
||||
* status = GETDNS_RESPSTATUS_GOOD
|
||||
* status = GETDNS_RESPSTATUS_NO_NAME
|
||||
* rcode = 0
|
||||
* ancount = 0 (number of records in ANSWER section)
|
||||
*/
|
||||
|
@ -155,7 +155,7 @@
|
|||
* name = "google.com"
|
||||
* request_type = 65279 (maximum unassigned RRTYPE)
|
||||
* expect: NOERROR/NODATA response:
|
||||
* status = GETDNS_RESPSTATUS_GOOD
|
||||
* status = GETDNS_RESPSTATUS_NO_NAME
|
||||
* rcode = 0
|
||||
* ancount = 0 (number of records in ANSWER section)
|
||||
*/
|
||||
|
@ -269,7 +269,7 @@
|
|||
* name = "willem.getdnsapi.net" an unbound zone (as in no MX)
|
||||
* request_type = GETDNS_RRTYPE_MX
|
||||
* expect: NOERROR/NODATA response:
|
||||
* status = GETDNS_RESPSTATUS_GOOD
|
||||
* status = GETDNS_RESPSTATUS_NO_NAME
|
||||
* rcode = 0
|
||||
* ancount = 0 (number of records in ANSWER section)
|
||||
*/
|
||||
|
|
|
@ -361,7 +361,7 @@
|
|||
struct getdns_context *context = NULL;
|
||||
struct getdns_dict *address = NULL;
|
||||
struct getdns_bindata address_type = { 5, (void *)"IPv4" };
|
||||
struct getdns_bindata address_data = { 4, (void *)"\x01\x01\x01\x01" };
|
||||
struct getdns_bindata address_data = { 4, (void *)"\xb9\x31\x8c\x00" };
|
||||
void* eventloop = NULL;
|
||||
getdns_transaction_t transaction_id = 0;
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@
|
|||
struct getdns_context *context = NULL;
|
||||
struct getdns_dict *address = NULL;
|
||||
struct getdns_bindata address_type = { 5, (void *)"IPv4" };
|
||||
struct getdns_bindata address_data = { 4, (void *)"\x01\x01\x01\x01" };
|
||||
struct getdns_bindata address_data = { 4, (void *)"\xb9\x31\x8c\x00" };
|
||||
struct getdns_dict *response = NULL;
|
||||
|
||||
CONTEXT_CREATE(TRUE);
|
||||
|
|
|
@ -25,4 +25,4 @@ done
|
|||
rm -fr "${BUILDDIR}/build"
|
||||
mkdir "${BUILDDIR}/build"
|
||||
cd "${BUILDDIR}/build"
|
||||
"${SRCROOT}/configure" $* --prefix "${BUILDDIR}/install" --enable-debug-anchor
|
||||
"${SRCROOT}/configure" $* --prefix "${BUILDDIR}/install"
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
cd "${BUILDDIR}/build"
|
||||
make XTRA_CFLAGS='-Werror' -j 4
|
||||
make XTRA_CFLAGS='-g -Werror' -j 4
|
||||
|
|
|
@ -5,4 +5,6 @@
|
|||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
cd "${BUILDDIR}/build"
|
||||
make -j 4 install
|
||||
make -j 4 install \
|
||||
&& echo "export GETDNS_QUERY=\"${BUILDDIR}/build/src/tools/getdns_query\"" \
|
||||
>> ../.tpkg.var.master
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
BaseName: 110-link
|
||||
Version: 1.0
|
||||
Description: Link getdns_query program
|
||||
CreationDate: do dec 10 11:10:11 CET 2015
|
||||
Maintainer: Willem Toorop
|
||||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends: 100-compile.tpkg
|
||||
Help:
|
||||
Pre:
|
||||
Post:
|
||||
Test: 110-link.test
|
||||
AuxFiles:
|
||||
Passed:
|
||||
Failure:
|
|
@ -1,10 +0,0 @@
|
|||
# #-- 110-link.test --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
cd "${BUILDDIR}/build"
|
||||
make -j 4 getdns_query \
|
||||
&& echo "export GETDNS_QUERY=\"${BUILDDIR}/build/src/tools/getdns_query\"" \
|
||||
>> ../.tpkg.var.master
|
|
@ -1,16 +0,0 @@
|
|||
BaseName: 115-install-linked
|
||||
Version: 1.0
|
||||
Description: Install the getdns_query program
|
||||
CreationDate: vr dec 18 10:52:26 CET 2015
|
||||
Maintainer: Willem Toorop
|
||||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends: 110-link.tpkg
|
||||
Help:
|
||||
Pre:
|
||||
Post:
|
||||
Test: 115-install-linked.test
|
||||
AuxFiles:
|
||||
Passed:
|
||||
Failure:
|
|
@ -1,8 +0,0 @@
|
|||
# #-- 115-install-linked.test --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
cd "${BUILDDIR}/build"
|
||||
make -j 4 install-getdns_query
|
|
@ -6,7 +6,7 @@ Maintainer: Willem Toorop
|
|||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends: 110-link.tpkg
|
||||
Depends: 105-install.tpkg
|
||||
Help:
|
||||
Pre:
|
||||
Post:
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
. DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5
|
||||
. DS 20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d
|
||||
|
|
|
@ -6,7 +6,7 @@ Maintainer: Willem Toorop
|
|||
Category:
|
||||
Component:
|
||||
CmdDepends: valgrind
|
||||
Depends: 110-link.tpkg
|
||||
Depends: 105-install.tpkg
|
||||
Help:
|
||||
Pre:
|
||||
Post:
|
||||
|
|
|
@ -6,7 +6,7 @@ Maintainer: Willem Toorop
|
|||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends: 110-link.tpkg
|
||||
Depends: 105-install.tpkg
|
||||
Help:
|
||||
Pre:
|
||||
Post:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
BaseName: 200-stub-only-compile
|
||||
BaseName: 200-stub-only-compile-install
|
||||
Version: 1.0
|
||||
Description: Create builddir and compile stub only
|
||||
CreationDate: do dec 10 11:08:24 CET 2015
|
||||
|
@ -8,9 +8,9 @@ Component:
|
|||
CmdDepends:
|
||||
Depends:
|
||||
Help:
|
||||
Pre: 200-stub-only-compile.pre
|
||||
Post: 200-stub-only-compile.post
|
||||
Test: 200-stub-only-compile.test
|
||||
Pre: 200-stub-only-compile-install.pre
|
||||
Post: 200-stub-only-compile-install.post
|
||||
Test: 200-stub-only-compile-install.test
|
||||
AuxFiles:
|
||||
Passed:
|
||||
Failure:
|
|
@ -25,4 +25,4 @@ done
|
|||
rm -fr "${BUILDDIR}/build-stub-only"
|
||||
mkdir "${BUILDDIR}/build-stub-only"
|
||||
cd "${BUILDDIR}/build-stub-only"
|
||||
"${SRCROOT}/configure" $* --prefix "${BUILDDIR}/install-stub-only" --enable-stub-only
|
||||
"${SRCROOT}/configure" $* --prefix "${BUILDDIR}/install-stub-only" --enable-stub-only --enable-debug-server --enable-debug-anchor
|
|
@ -5,4 +5,6 @@
|
|||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
cd "${BUILDDIR}/build-stub-only"
|
||||
make XTRA_CFLAGS='-Werror' -j 4
|
||||
make XTRA_CFLAGS='-g -Werror' -j 4 install \
|
||||
&& echo "export GETDNS_STUB_QUERY=\"${BUILDDIR}/build-stub-only/src/tools/getdns_query\"" \
|
||||
>> ../.tpkg.var.master
|
|
@ -1,16 +0,0 @@
|
|||
BaseName: 210-stub-only-link
|
||||
Version: 1.0
|
||||
Description: Link getdns_query program
|
||||
CreationDate: do dec 10 11:08:37 CET 2015
|
||||
Maintainer: Willem Toorop
|
||||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends: 200-stub-only-compile.tpkg
|
||||
Help:
|
||||
Pre:
|
||||
Post:
|
||||
Test: 210-stub-only-link.test
|
||||
AuxFiles:
|
||||
Passed:
|
||||
Failure:
|
|
@ -1,10 +0,0 @@
|
|||
# #-- 210-stub-only-link.test --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
cd "${BUILDDIR}/build-stub-only"
|
||||
make -j 4 getdns_query \
|
||||
&& echo "export GETDNS_STUB_QUERY=\"${BUILDDIR}/build-stub-only/src/tools/getdns_query\"" \
|
||||
>> ../.tpkg.var.master
|
|
@ -6,7 +6,7 @@ Maintainer: Willem Toorop
|
|||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends: 210-stub-only-link.tpkg
|
||||
Depends: 200-stub-only-compile-install.tpkg
|
||||
Help:
|
||||
Pre:
|
||||
Post:
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
. DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5
|
|
@ -1,12 +1,12 @@
|
|||
BaseName: 225-stub-only-valgrind-checks
|
||||
Version: 1.0
|
||||
Description: Run valgrind to detect memory leaks
|
||||
Description: Run getdns_query in valgrind + Zero configuration DNSSEC test
|
||||
CreationDate: ma mrt 21 16:24:56 CET 2016
|
||||
Maintainer: Willem Toorop
|
||||
Category:
|
||||
Component:
|
||||
CmdDepends: valgrind
|
||||
Depends: 210-stub-only-link.tpkg
|
||||
Depends: 200-stub-only-compile-install.tpkg
|
||||
Help:
|
||||
Pre:
|
||||
Post:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue