mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'develop'
This commit is contained in:
commit
21155d5aa9
|
@ -9,3 +9,6 @@
|
|||
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
|
||||
|
|
29
ChangeLog
29
ChangeLog
|
@ -1,3 +1,32 @@
|
|||
* 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, whith 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
|
||||
|
|
20
Makefile.in
20
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
|
||||
cd src/tools && $(MAKE) $@
|
||||
|
||||
uninstall-getdns_server_mon:
|
||||
cd src/tools && $(MAKE) $@
|
||||
|
||||
install-stubby:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
|
@ -204,12 +213,14 @@ $(distdir):
|
|||
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
|
||||
cp $(srcdir)/configure.ac $(distdir)
|
||||
cp $(srcdir)/configure $(distdir)
|
||||
cp $(srcdir)/AUTHORS $(distdir)
|
||||
|
@ -258,12 +269,15 @@ $(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)/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
|
||||
|
|
11
README.md
11
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. (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,8 +99,8 @@ 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
|
||||
|
||||
|
|
118
configure.ac
118
configure.ac
|
@ -36,7 +36,7 @@ sinclude(./m4/acx_getaddrinfo.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.4.0], [team@getdnsapi.net], [getdns], [https://getdnsapi.net])
|
||||
|
||||
# Autoconf 2.70 will have set up runstatedir. 2.69 is frequently (Debian)
|
||||
# patched to do the same, but frequently (MacOS) not. So add a with option
|
||||
|
@ -62,11 +62,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, [0x01040000])
|
||||
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.2$RELEASE_CANDIDATE"], [Stubby package string])
|
||||
|
||||
# Library version
|
||||
# ---------------
|
||||
|
@ -99,9 +101,10 @@ 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-1.3.0 had libversion 9:0:3
|
||||
# getdns-1.4.0 has libversion 10:0:0
|
||||
#
|
||||
GETDNS_LIBVERSION=9:0:3
|
||||
GETDNS_LIBVERSION=10:0:0
|
||||
|
||||
AC_SUBST(GETDNS_COMPILATION_COMMENT)
|
||||
AC_SUBST(GETDNS_LIBVERSION)
|
||||
|
@ -408,8 +411,8 @@ fi
|
|||
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method 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 SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version SSL_CTX_dane_enable SSL_dane_enable SSL_dane_tlsa_add X509_check_host])
|
||||
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], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
#include <openssl/err.h>
|
||||
|
@ -431,6 +434,28 @@ AC_INCLUDES_DEFAULT
|
|||
])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether we need to compile/link DANE support])
|
||||
DANESSL_XTRA_OBJS=""
|
||||
AC_LANG_PUSH(C)
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([
|
||||
[#include <openssl/opensslv.h>]
|
||||
[#if OPENSSL_VERSION_NUMBER < 0x1000000fL]
|
||||
[#error "OpenSSL 1.0.0 or higher required for DANE library"]
|
||||
[#elif defined(HAVE_SSL_DANE_ENABLE)]
|
||||
[#error "OpenSSL has native DANE support"]
|
||||
[#elif defined(LIBRESSL_VERSION_NUMBER)]
|
||||
[#error "dane_ssl library does not work with LibreSSL"]
|
||||
[#endif]
|
||||
],[[]])],
|
||||
[
|
||||
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"
|
||||
],
|
||||
[AC_MSG_RESULT([no])])
|
||||
AC_LANG_POP(C)
|
||||
AC_SUBST(DANESSL_XTRA_OBJS)
|
||||
|
||||
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
|
||||
case "$enable_sha1" in
|
||||
|
@ -763,6 +788,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 +851,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"
|
||||
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 +1230,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]),
|
||||
|
|
|
@ -47,6 +47,7 @@ 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@
|
||||
|
||||
|
@ -96,7 +97,9 @@ JSMN_OBJ=jsmn.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
|
||||
|
@ -133,6 +136,9 @@ $(JSMN_OBJ):
|
|||
$(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 $@
|
||||
|
||||
|
@ -197,8 +203,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 +232,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,7 +271,7 @@ 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" -Iyxml -Iutil/auxiliary -I../stubby/src *.c gldns/*.c compat/*.c util/*.c jsmn/*.c yxml/*.c ssl_dane/danessl.c extension/*.c ../stubby/src/*.c | \
|
||||
sed -e "s? $$blddir/? ?g" \
|
||||
-e 's? gldns/? $$(srcdir)/gldns/?g' \
|
||||
-e 's? compat/? $$(srcdir)/compat/?g' \
|
||||
|
@ -263,6 +279,7 @@ depend:
|
|||
-e 's? util/? $$(srcdir)/util/?g' \
|
||||
-e 's? jsmn/? $$(srcdir)/jsmn/?g' \
|
||||
-e 's? yxml/? $$(srcdir)/yxml/?g' \
|
||||
-e 's? ssl_dane/? $$(srcdir)/ssl_dane/?g' \
|
||||
-e 's? extension/? $$(srcdir)/extension/?g' \
|
||||
-e 's? \.\./stubby/? $$(stubbysrcdir)/?g' \
|
||||
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
|
||||
|
@ -311,7 +328,7 @@ context.lo context.o: $(srcdir)/context.c \
|
|||
$(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)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h $(srcdir)/ssl_dane/danessl.h
|
||||
convert.lo convert.o: $(srcdir)/convert.c \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
@ -323,7 +340,7 @@ convert.lo convert.o: $(srcdir)/convert.c \
|
|||
$(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)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h
|
||||
dict.lo dict.o: $(srcdir)/dict.c \
|
||||
config.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
|
@ -450,7 +467,7 @@ stub.lo stub.o: $(srcdir)/stub.c \
|
|||
$(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)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h $(srcdir)/ssl_dane/danessl.h
|
||||
sync.lo sync.o: $(srcdir)/sync.c \
|
||||
getdns/getdns.h \
|
||||
config.h \
|
||||
|
@ -557,6 +574,7 @@ val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \
|
|||
$(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h
|
||||
jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
|
||||
yxml.lo yxml.o: $(srcdir)/yxml/yxml.c $(srcdir)/yxml/yxml.h
|
||||
danessl.lo danessl.o: $(srcdir)/ssl_dane/danessl.c $(srcdir)/ssl_dane/danessl.h
|
||||
libev.lo libev.o: $(srcdir)/extension/libev.c \
|
||||
config.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
|
|
|
@ -92,6 +92,7 @@ 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 },
|
||||
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
|
||||
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
|
||||
{ 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
|
||||
|
@ -189,6 +190,7 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_CONTEXT_CODE_TLS_CA_PATH", 631 },
|
||||
{ "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_QUERY_PADDING_BLOCKSIZE", 620 },
|
||||
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", 625 },
|
||||
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA", 626 },
|
||||
|
|
137
src/context.c
137
src/context.c
|
@ -59,6 +59,7 @@ typedef unsigned short in_port_t;
|
|||
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
@ -89,6 +90,9 @@ typedef unsigned short in_port_t;
|
|||
#include "list.h"
|
||||
#include "dict.h"
|
||||
#include "pubkey-pinning.h"
|
||||
#ifdef USE_DANESSL
|
||||
# include "ssl_dane/danessl.h"
|
||||
#endif
|
||||
|
||||
#define GETDNS_PORT_ZERO 0
|
||||
#define GETDNS_PORT_DNS 53
|
||||
|
@ -681,6 +685,27 @@ upstreams_create(getdns_context *context, size_t size)
|
|||
return r;
|
||||
}
|
||||
|
||||
|
||||
#if defined(USE_DANESSL) && defined(STUB_DEBUG) && STUB_DEBUG
|
||||
static void _stub_debug_print_openssl_errors(void)
|
||||
{
|
||||
unsigned long err;
|
||||
char buffer[1024];
|
||||
const char *file;
|
||||
const char *data;
|
||||
int line;
|
||||
int flags;
|
||||
|
||||
while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
|
||||
ERR_error_string_n(err, buffer, sizeof(buffer));
|
||||
if (flags & ERR_TXT_STRING)
|
||||
DEBUG_STUB("DEBUG OpenSSL Error: %s:%s:%d:%s\n", buffer, file, line, data);
|
||||
else
|
||||
DEBUG_STUB("DEBUG OpenSSL Error: %s:%s:%d\n", buffer, file, line);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
_getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
||||
{
|
||||
|
@ -722,6 +747,12 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
|||
|
||||
if (upstream->tls_obj != NULL) {
|
||||
SSL_shutdown(upstream->tls_obj);
|
||||
#ifdef USE_DANESSL
|
||||
# if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
_stub_debug_print_openssl_errors();
|
||||
# endif
|
||||
DANESSL_cleanup(upstream->tls_obj);
|
||||
#endif
|
||||
SSL_free(upstream->tls_obj);
|
||||
}
|
||||
if (upstream->fd != -1)
|
||||
|
@ -738,6 +769,8 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
|||
upstream->tls_pubkey_pinset = NULL;
|
||||
if (upstream->tls_cipher_list)
|
||||
GETDNS_FREE(upstreams->mf, upstream->tls_cipher_list);
|
||||
if (upstream->tls_curves_list)
|
||||
GETDNS_FREE(upstreams->mf, upstream->tls_curves_list);
|
||||
}
|
||||
GETDNS_FREE(upstreams->mf, upstreams);
|
||||
}
|
||||
|
@ -779,8 +812,9 @@ upstream_backoff(getdns_upstream *upstream) {
|
|||
upstream->conn_shutdowns = 0;
|
||||
upstream->conn_backoffs++;
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
|
||||
"%-40s : !Backing off this upstream - Will retry again in %ds at %s",
|
||||
"%-40s : Upstream : !Backing off %s on this upstream - Will retry again in %ds at %s",
|
||||
upstream->addr_str,
|
||||
upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP",
|
||||
upstream->conn_backoff_interval,
|
||||
asctime(gmtime(&upstream->conn_retry_time)));
|
||||
}
|
||||
|
@ -832,6 +866,12 @@ _getdns_upstream_reset(getdns_upstream *upstream)
|
|||
}
|
||||
if (upstream->tls_obj != NULL) {
|
||||
SSL_shutdown(upstream->tls_obj);
|
||||
#ifdef USE_DANESSL
|
||||
# if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
_stub_debug_print_openssl_errors();
|
||||
# endif
|
||||
DANESSL_cleanup(upstream->tls_obj);
|
||||
#endif
|
||||
SSL_free(upstream->tls_obj);
|
||||
upstream->tls_obj = NULL;
|
||||
}
|
||||
|
@ -1011,6 +1051,7 @@ upstream_init(getdns_upstream *upstream,
|
|||
upstream->responses_timeouts = 0;
|
||||
upstream->keepalive_shutdown = 0;
|
||||
upstream->keepalive_timeout = 0;
|
||||
upstream->server_keepalive_received = 0;
|
||||
/* How is this upstream doing on UDP? */
|
||||
upstream->to_retry = 1;
|
||||
upstream->back_off = 1;
|
||||
|
@ -1022,6 +1063,7 @@ upstream_init(getdns_upstream *upstream,
|
|||
upstream->tls_obj = NULL;
|
||||
upstream->tls_session = NULL;
|
||||
upstream->tls_cipher_list = NULL;
|
||||
upstream->tls_curves_list = NULL;
|
||||
upstream->transport = GETDNS_TRANSPORT_TCP;
|
||||
upstream->tls_hs_state = GETDNS_HS_NONE;
|
||||
upstream->tls_auth_name[0] = '\0';
|
||||
|
@ -1535,6 +1577,7 @@ getdns_context_create_with_extended_memory_functions(
|
|||
result->tls_ca_path = NULL;
|
||||
result->tls_ca_file = NULL;
|
||||
result->tls_cipher_list = NULL;
|
||||
result->tls_curves_list = NULL;
|
||||
|
||||
(void) memset(&result->root_ksk, 0, sizeof(result->root_ksk));
|
||||
|
||||
|
@ -1636,6 +1679,9 @@ getdns_context_create_with_extended_memory_functions(
|
|||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
OpenSSL_add_all_algorithms();
|
||||
SSL_library_init();
|
||||
# ifdef USE_DANESSL
|
||||
(void) DANESSL_library_init();
|
||||
# endif
|
||||
#else
|
||||
OPENSSL_init_crypto( OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
|
@ -1805,6 +1851,8 @@ getdns_context_destroy(struct getdns_context *context)
|
|||
GETDNS_FREE(context->mf, context->tls_ca_file);
|
||||
if (context->tls_cipher_list)
|
||||
GETDNS_FREE(context->mf, context->tls_cipher_list);
|
||||
if (context->tls_curves_list)
|
||||
GETDNS_FREE(context->mf, context->tls_curves_list);
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
|
@ -2996,6 +3044,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
if (dict && getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) {
|
||||
getdns_list *pubkey_pinset = NULL;
|
||||
getdns_bindata *tls_cipher_list = NULL;
|
||||
getdns_bindata *tls_curves_list = NULL;
|
||||
|
||||
if ((r = getdns_dict_get_bindata(
|
||||
dict, "tls_auth_name", &tls_auth_name)) == GETDNS_RETURN_GOOD) {
|
||||
|
@ -3007,6 +3056,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
* into account, should not
|
||||
* be larger than 1024 bytes.
|
||||
*/
|
||||
freeaddrinfo(ai);
|
||||
goto invalid_parameter;
|
||||
}
|
||||
memcpy(upstream->tls_auth_name,
|
||||
|
@ -3022,8 +3072,10 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
r = _getdns_get_pubkey_pinset_from_list(pubkey_pinset,
|
||||
&(upstreams->mf),
|
||||
&(upstream->tls_pubkey_pinset));
|
||||
if (r != GETDNS_RETURN_GOOD)
|
||||
if (r != GETDNS_RETURN_GOOD) {
|
||||
freeaddrinfo(ai);
|
||||
goto invalid_parameter;
|
||||
}
|
||||
}
|
||||
(void) getdns_dict_get_bindata(
|
||||
dict, "tls_cipher_list", &tls_cipher_list);
|
||||
|
@ -3031,6 +3083,19 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
? _getdns_strdup2(&upstreams->mf
|
||||
, tls_cipher_list)
|
||||
: NULL;
|
||||
(void) getdns_dict_get_bindata(
|
||||
dict, "tls_curves_list", &tls_curves_list);
|
||||
if (tls_curves_list) {
|
||||
#if defined(HAVE_DECL_SSL_SET1_CURVES_LIST) && HAVE_DECL_SSL_SET1_CURVES_LIST
|
||||
upstream->tls_curves_list =
|
||||
_getdns_strdup2(&upstreams->mf
|
||||
, tls_curves_list);
|
||||
#else
|
||||
freeaddrinfo(ai);
|
||||
goto not_implemented;
|
||||
#endif
|
||||
} else
|
||||
upstream->tls_curves_list = NULL;
|
||||
}
|
||||
if ((upstream->tsig_alg = tsig_alg)) {
|
||||
if (tsig_name) {
|
||||
|
@ -3068,6 +3133,11 @@ invalid_parameter:
|
|||
error:
|
||||
_getdns_upstreams_dereference(upstreams);
|
||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||
#if !defined(HAVE_DECL_SSL_SET1_CURVES_LIST) || !HAVE_DECL_SSL_SET1_CURVES_LIST
|
||||
not_implemented:
|
||||
_getdns_upstreams_dereference(upstreams);
|
||||
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
} /* getdns_context_set_upstream_recursive_servers */
|
||||
|
||||
|
||||
|
@ -3608,6 +3678,12 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
|
|||
context->tls_cipher_list ? context->tls_cipher_list
|
||||
: _getdns_default_tls_cipher_list))
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
|
||||
# if defined(HAVE_DECL_SSL_CTX_SET1_CURVES_LIST) && HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
|
||||
if (context->tls_curves_list &&
|
||||
!SSL_CTX_set1_curves_list(context->tls_ctx, context->tls_curves_list))
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
# endif
|
||||
/* For strict authentication, we must have local root certs available
|
||||
Set up is done only when the tls_ctx is created (per getdns_context)*/
|
||||
if ((context->tls_ca_file || context->tls_ca_path) &&
|
||||
|
@ -3622,6 +3698,25 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
|
|||
if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
}
|
||||
# if defined(HAVE_SSL_CTX_DANE_ENABLE)
|
||||
# if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
int osr =
|
||||
# else
|
||||
(void)
|
||||
# endif
|
||||
SSL_CTX_dane_enable(context->tls_ctx);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: SSL_CTX_dane_enable() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
# elif defined(USE_DANESSL)
|
||||
# if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
int osr =
|
||||
# else
|
||||
(void)
|
||||
# endif
|
||||
DANESSL_CTX_init(context->tls_ctx);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_CTX_init() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
# endif
|
||||
#else /* HAVE_TLS_v1_2 */
|
||||
if (tls_only_is_in_transports_list(context) == 1)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
|
@ -3924,6 +4019,8 @@ _get_context_settings(getdns_context* context)
|
|||
(void) getdns_dict_util_set_string(result, "tls_ca_file", str_value);
|
||||
if (!getdns_context_get_tls_cipher_list(context, &str_value) && str_value)
|
||||
(void) getdns_dict_util_set_string(result, "tls_cipher_list", str_value);
|
||||
if (!getdns_context_get_tls_curves_list(context, &str_value) && str_value)
|
||||
(void) getdns_dict_util_set_string(result, "tls_curves_list", str_value);
|
||||
|
||||
/* Default settings for extensions */
|
||||
(void)getdns_dict_set_int(
|
||||
|
@ -4513,6 +4610,11 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context,
|
|||
d, "tls_cipher_list",
|
||||
upstream->tls_cipher_list);
|
||||
}
|
||||
if (upstream->tls_curves_list) {
|
||||
(void) getdns_dict_util_set_string(
|
||||
d, "tls_curves_list",
|
||||
upstream->tls_curves_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!r)
|
||||
|
@ -4722,6 +4824,7 @@ _getdns_context_config_setting(getdns_context *context,
|
|||
CONTEXT_SETTING_STRING(tls_ca_path)
|
||||
CONTEXT_SETTING_STRING(tls_ca_file)
|
||||
CONTEXT_SETTING_STRING(tls_cipher_list)
|
||||
CONTEXT_SETTING_STRING(tls_curves_list)
|
||||
|
||||
/**************************************/
|
||||
/**** ****/
|
||||
|
@ -5301,5 +5404,35 @@ getdns_context_get_tls_cipher_list(
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_curves_list(
|
||||
getdns_context *context, const char *tls_curves_list)
|
||||
{
|
||||
if (!context)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
#if defined(HAVE_DECL_SSL_CTX_SET1_CURVES_LIST) && HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
|
||||
if (context->tls_curves_list)
|
||||
GETDNS_FREE(context->mf, context->tls_curves_list);
|
||||
context->tls_curves_list = tls_curves_list
|
||||
? _getdns_strdup(&context->mf, tls_curves_list)
|
||||
: NULL;
|
||||
|
||||
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
#else
|
||||
(void)tls_curves_list;
|
||||
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_curves_list(
|
||||
getdns_context *context, const char **tls_curves_list)
|
||||
{
|
||||
if (!context || !tls_curves_list)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
*tls_curves_list = context->tls_curves_list;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
/* context.c */
|
||||
|
|
|
@ -193,6 +193,7 @@ 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;
|
||||
|
@ -206,6 +207,7 @@ typedef struct getdns_upstream {
|
|||
getdns_auth_state_t tls_auth_state;
|
||||
unsigned tls_fallback_ok : 1;
|
||||
char *tls_cipher_list;
|
||||
char *tls_curves_list;
|
||||
/* Auth credentials*/
|
||||
char tls_auth_name[256];
|
||||
sha256_pin_t *tls_pubkey_pinset;
|
||||
|
@ -347,6 +349,7 @@ struct getdns_context {
|
|||
char *tls_ca_path;
|
||||
char *tls_ca_file;
|
||||
char *tls_cipher_list;
|
||||
char *tls_curves_list;
|
||||
|
||||
getdns_upstreams *upstreams;
|
||||
uint16_t limit_outstanding_queries;
|
||||
|
|
102
src/convert.c
102
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
43
src/dnssec.c
43
src/dnssec.c
|
@ -1755,6 +1755,26 @@ static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Returns whether a dnskey for keyset signed a non wildcard rrset. */
|
||||
static int a_key_signed_rrset_no_wc(struct mem_funcs *mf, time_t now,
|
||||
uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset)
|
||||
{
|
||||
_getdns_rrtype_iter dnskey_spc, *dnskey;
|
||||
const uint8_t *nc_name;
|
||||
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)) && !nc_name)
|
||||
return keytag;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_nsec_covering_name(
|
||||
struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey,
|
||||
_getdns_rrset *rrset, const uint8_t *name, int *opt_out);
|
||||
|
@ -2110,7 +2130,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 +2195,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);
|
||||
|
@ -2297,7 +2319,8 @@ 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))) {
|
||||
|
||||
debug_sec_print_rrset("NSEC NODATA proof for: ", rrset);
|
||||
return keytag;
|
||||
|
@ -2353,7 +2376,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,7 +2460,8 @@ 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
|
||||
|
@ -2493,7 +2517,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)))
|
||||
|
@ -2545,7 +2569,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;
|
||||
|
@ -2563,7 +2587,8 @@ static int chain_node_get_trusted_keys(
|
|||
return GETDNS_DNSSEC_INSECURE;
|
||||
}
|
||||
|
||||
if ((keytag = a_key_signed_rrset(mf,now,skew,ta,&node->ds))) {
|
||||
if ((keytag = a_key_signed_rrset_no_wc(
|
||||
mf, now, skew, ta, &node->ds))) {
|
||||
node->ds_signer = keytag;
|
||||
if ((keytag = ds_authenticates_keys(
|
||||
mf, now, skew, &node->ds, &node->dnskey))) {
|
||||
|
@ -2597,7 +2622,7 @@ static int chain_node_get_trusted_keys(
|
|||
}
|
||||
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))){
|
||||
|
|
|
@ -697,6 +697,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;
|
||||
|
|
|
@ -100,6 +100,8 @@ 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"
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
@ -753,6 +755,20 @@ getdns_return_t
|
|||
getdns_context_set_tls_cipher_list(
|
||||
getdns_context *context, const char *cipher_list);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
* Get the current resolution type setting from this context.
|
||||
* @see getdns_context_set_resolution_type
|
||||
|
@ -1272,6 +1288,21 @@ getdns_return_t
|
|||
getdns_context_get_tls_cipher_list(
|
||||
getdns_context *context, const char **cipher_list);
|
||||
|
||||
/**
|
||||
* 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(
|
||||
getdns_context *context, const char **curves_list);
|
||||
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -1541,7 +1548,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 +1700,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) {
|
||||
|
|
|
@ -554,6 +554,12 @@ 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);
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
|
@ -1331,7 +1337,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 +1473,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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -37,6 +37,7 @@ getdns_context_get_tls_ca_file
|
|||
getdns_context_get_tls_ca_path
|
||||
getdns_context_get_tls_cipher_list
|
||||
getdns_context_get_tls_connection_retries
|
||||
getdns_context_get_tls_curves_list
|
||||
getdns_context_get_tls_query_padding_blocksize
|
||||
getdns_context_get_trust_anchors_url
|
||||
getdns_context_get_trust_anchors_verify_CA
|
||||
|
@ -80,6 +81,7 @@ getdns_context_set_tls_ca_file
|
|||
getdns_context_set_tls_ca_path
|
||||
getdns_context_set_tls_cipher_list
|
||||
getdns_context_set_tls_connection_retries
|
||||
getdns_context_set_tls_curves_list
|
||||
getdns_context_set_tls_query_padding_blocksize
|
||||
getdns_context_set_trust_anchors_url
|
||||
getdns_context_set_trust_anchors_verify_CA
|
||||
|
|
|
@ -211,6 +211,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!
|
||||
|
|
196
src/server.c
196
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;
|
||||
}
|
||||
|
@ -317,8 +352,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 +364,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 +410,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 +436,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 +458,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 +559,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 +578,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;
|
||||
}
|
||||
|
@ -730,8 +791,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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit dd093e585a237e0321d303ec35e84c393ef739f4
|
363
src/stub.c
363
src/stub.c
|
@ -55,6 +55,9 @@
|
|||
#include "platform.h"
|
||||
#include "general.h"
|
||||
#include "pubkey-pinning.h"
|
||||
#ifdef USE_DANESSL
|
||||
# include "ssl_dane/danessl.h"
|
||||
#endif
|
||||
|
||||
/* WSA TODO:
|
||||
* STUB_TCP_RETRY added to deal with edge triggered event loops (versus
|
||||
|
@ -341,6 +344,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;
|
||||
|
@ -529,11 +533,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 +580,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);
|
||||
|
@ -827,7 +827,37 @@ tls_requested(getdns_network_req *netreq)
|
|||
1 : 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
#if defined(HAVE_SSL_DANE_ENABLE) || defined(USE_DANESSL)
|
||||
|
||||
static int
|
||||
_getdns_tls_verify_always_ok(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
# if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
char buf[8192];
|
||||
X509 *cert;
|
||||
int err;
|
||||
int depth;
|
||||
|
||||
cert = X509_STORE_CTX_get_current_cert(ctx);
|
||||
err = X509_STORE_CTX_get_error(ctx);
|
||||
depth = X509_STORE_CTX_get_error_depth(ctx);
|
||||
|
||||
if (cert)
|
||||
X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
|
||||
else
|
||||
strcpy(buf, "<unknown>");
|
||||
DEBUG_STUB("DEBUG Cert verify: depth=%d verify=%d err=%d subject=%s errorstr=%s\n", depth, ok, err, buf, X509_verify_cert_error_string(err));
|
||||
# else /* defined(STUB_DEBUG) && STUB_DEBUG */
|
||||
(void)ok;
|
||||
(void)ctx;
|
||||
# endif /* #else defined(STUB_DEBUG) && STUB_DEBUG */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* defined(HAVE_SSL_DANE_ENABLE) || defined(USE_DANESSL) */
|
||||
|
||||
static int
|
||||
tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
getdns_upstream *upstream;
|
||||
|
@ -837,36 +867,22 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|||
return 0;
|
||||
|
||||
int err = X509_STORE_CTX_get_error(ctx);
|
||||
#if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
# 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
|
||||
# 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",
|
||||
"%-40s : Verify failed: 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
|
||||
/* No need to deal with hostname authentication, since this will be
|
||||
* dealt with in the DANE preprocessor paths.
|
||||
*/
|
||||
|
||||
/* Now deal with the pinset validation*/
|
||||
/* Deal with the pinset validation */
|
||||
if (upstream->tls_pubkey_pinset)
|
||||
pinset_ret = _getdns_verify_pinset_match(upstream->tls_pubkey_pinset, ctx);
|
||||
|
||||
|
@ -880,24 +896,9 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|||
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",
|
||||
"%-40s : Conn failed: 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;
|
||||
|
@ -910,6 +911,8 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|||
return (upstream->tls_fallback_ok) ? 1 : preverify_ok;
|
||||
}
|
||||
|
||||
#endif /* #else defined(HAVE_SSL_DANE_ENABLE) || defined(USE_DANESSL) */
|
||||
|
||||
static SSL*
|
||||
tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
||||
{
|
||||
|
@ -925,6 +928,10 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
SSL_free(ssl);
|
||||
return NULL;
|
||||
}
|
||||
#if defined(HAVE_DECL_SSL_SET1_CURVES_LIST) && HAVE_DECL_SSL_SET1_CURVES_LIST
|
||||
if (upstream->tls_curves_list)
|
||||
(void) SSL_set1_curves_list(ssl, upstream->tls_curves_list);
|
||||
#endif
|
||||
/* 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);
|
||||
|
@ -942,13 +949,16 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
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*/
|
||||
#if defined(HAVE_SSL_HN_AUTH)
|
||||
/* Set up native OpenSSL hostname verification
|
||||
* ( doesn't work with USE_DANESSL, but we verify the
|
||||
* name afterwards in such cases )
|
||||
*/
|
||||
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
|
||||
#elif !defined(HAVE_X509_CHECK_HOST)
|
||||
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__);
|
||||
|
@ -956,6 +966,8 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
"%-40s : ERROR: Hostname Authentication not available from TLS library (check library version)\n",
|
||||
upstream->addr_str);
|
||||
upstream->tls_hs_state = GETDNS_HS_FAILED;
|
||||
SSL_free(ssl);
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
@ -970,9 +982,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;
|
||||
SSL_free(ssl);
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
|
@ -992,7 +1009,71 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS,
|
||||
__FUNC__);
|
||||
}
|
||||
#if defined(HAVE_SSL_DANE_ENABLE)
|
||||
int osr;
|
||||
# if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
osr =
|
||||
# else
|
||||
(void)
|
||||
# endif
|
||||
SSL_dane_enable(ssl, *upstream->tls_auth_name ? upstream->tls_auth_name : NULL);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_enable(\"%s\") -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->tls_auth_name, osr);
|
||||
SSL_set_verify(ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok);
|
||||
sha256_pin_t *pin_p;
|
||||
size_t n_pins = 0;
|
||||
for (pin_p = upstream->tls_pubkey_pinset; pin_p; pin_p = pin_p->next) {
|
||||
osr = SSL_dane_tlsa_add(ssl, 2, 1, 1,
|
||||
(unsigned char *)pin_p->pin, SHA256_DIGEST_LENGTH);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_tlsa_add() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
if (osr > 0)
|
||||
++n_pins;
|
||||
osr = SSL_dane_tlsa_add(ssl, 3, 1, 1,
|
||||
(unsigned char *)pin_p->pin, SHA256_DIGEST_LENGTH);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_tlsa_add() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
if (osr > 0)
|
||||
++n_pins;
|
||||
}
|
||||
#elif defined(USE_DANESSL)
|
||||
if (upstream->tls_pubkey_pinset) {
|
||||
const char *auth_names[2] = { upstream->tls_auth_name, NULL };
|
||||
int osr;
|
||||
# if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
osr =
|
||||
# else
|
||||
(void)
|
||||
# endif
|
||||
DANESSL_init(ssl,
|
||||
*upstream->tls_auth_name ? upstream->tls_auth_name : NULL,
|
||||
*upstream->tls_auth_name ? auth_names : NULL
|
||||
);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_init(\"%s\") -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->tls_auth_name, osr);
|
||||
SSL_set_verify(ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok);
|
||||
sha256_pin_t *pin_p;
|
||||
size_t n_pins = 0;
|
||||
for (pin_p = upstream->tls_pubkey_pinset; pin_p; pin_p = pin_p->next) {
|
||||
osr = DANESSL_add_tlsa(ssl, 3, 1, "sha256",
|
||||
(unsigned char *)pin_p->pin, SHA256_DIGEST_LENGTH);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_add_tlsa() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
if (osr > 0)
|
||||
++n_pins;
|
||||
osr = DANESSL_add_tlsa(ssl, 2, 1, "sha256",
|
||||
(unsigned char *)pin_p->pin, SHA256_DIGEST_LENGTH);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_add_tlsa() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
if (osr > 0)
|
||||
++n_pins;
|
||||
}
|
||||
} else {
|
||||
SSL_set_verify(ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok);
|
||||
}
|
||||
#else
|
||||
SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
|
||||
#endif
|
||||
|
||||
SSL_set_connect_state(ssl);
|
||||
(void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
|
||||
|
@ -1009,7 +1090,6 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
__FUNC__);
|
||||
}
|
||||
}
|
||||
|
||||
return ssl;
|
||||
}
|
||||
|
||||
|
@ -1048,16 +1128,120 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
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))
|
||||
upstream->tls_auth_state = upstream->last_tls_auth_state;
|
||||
|
||||
else if (upstream->tls_pubkey_pinset || upstream->tls_auth_name[0]) {
|
||||
X509 *peer_cert = SSL_get_peer_certificate(upstream->tls_obj);
|
||||
long verify_result = SSL_get_verify_result(upstream->tls_obj);
|
||||
|
||||
/* In case of DANESSL use, and a tls_auth_name was given alongside a pinset,
|
||||
* we need to verify auth_name explicitely (otherwise it will not be checked,
|
||||
* because this is not required with DANE with an EE match).
|
||||
* This is not needed with native OpenSSL DANE, because EE name checks have
|
||||
* to be disabled explicitely.
|
||||
*/
|
||||
#if defined(HAVE_X509_CHECK_HOST) && (defined(USE_DANESSL) || !defined(HAVE_SSL_HN_AUTH))
|
||||
int xch;
|
||||
if (peer_cert && verify_result == X509_V_OK
|
||||
&& upstream->tls_auth_name[0]
|
||||
&& (xch = X509_check_host(peer_cert,
|
||||
upstream->tls_auth_name,
|
||||
strlen(upstream->tls_auth_name),
|
||||
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS,
|
||||
NULL)) <= 0)
|
||||
verify_result = X509_V_ERR_HOSTNAME_MISMATCH;
|
||||
#endif
|
||||
upstream->tls_auth_state = peer_cert && verify_result == X509_V_OK
|
||||
? GETDNS_AUTH_OK : GETDNS_AUTH_FAILED;
|
||||
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*" ));
|
||||
|
||||
/* Since we don't have DANE validation yet, DANE validation
|
||||
* failures are always pinset validation failures
|
||||
*/
|
||||
#if defined(HAVE_SSL_DANE_ENABLE)
|
||||
else if (verify_result == X509_V_ERR_DANE_NO_MATCH)
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"Pinset validation failure\n", upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ));
|
||||
#elif defined(USE_DANESSL)
|
||||
else if (verify_result == X509_V_ERR_CERT_UNTRUSTED
|
||||
&& upstream->tls_pubkey_pinset
|
||||
&& !DANESSL_get_match_cert(
|
||||
upstream->tls_obj, NULL, NULL, NULL))
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"Pinset validation failure\n", upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ));
|
||||
#endif
|
||||
else if (verify_result != X509_V_OK)
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"(%d) \"%s\"\n", upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ), verify_result,
|
||||
X509_verify_cert_error_string(verify_result));
|
||||
#if !defined(HAVE_SSL_HN_AUTH) && !defined(HAVE_X509_CHECK_HOST)
|
||||
else if (*upstream->tls_auth_name) {
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"Hostname Authentication not available from TLS "
|
||||
"library (check library version)\n",
|
||||
upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ));
|
||||
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
|
||||
"%-40s : Verify passed : TLS\n",
|
||||
upstream->addr_str);
|
||||
|
||||
X509_free(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");
|
||||
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);
|
||||
|
@ -1409,7 +1593,7 @@ stub_udp_read_cb(void *userarg)
|
|||
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);
|
||||
|
@ -1671,7 +1855,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 +1870,14 @@ 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 = 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->debug_tls_version = SSL_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;
|
||||
|
@ -1826,6 +2012,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)
|
||||
{
|
||||
|
@ -1843,8 +2057,9 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
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);
|
||||
"%-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 +2072,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 +2088,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 +2126,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;
|
||||
}
|
||||
|
||||
|
@ -2081,7 +2306,7 @@ upstream_find_for_netreq(getdns_network_req *netreq)
|
|||
/* Handle better, will give generic error*/
|
||||
DEBUG_STUB("%s %-35s: MSG: %p No valid upstream! \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq);
|
||||
_getdns_context_log(netreq->owner->context, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
|
||||
"*FAILURE* no valid transports or upstreams available!\n");
|
||||
" *FAILURE* no valid transports or upstreams available!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ void handler(getdns_context *context, getdns_callback_type_t callback_type,
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
getdns_context *context = NULL;
|
||||
getdns_list *listeners = NULL;
|
||||
|
@ -92,9 +92,20 @@ int main()
|
|||
uint32_t port1 = 18000;
|
||||
uint32_t port2 = 18000;
|
||||
getdns_return_t r;
|
||||
char listenliststr[1024];
|
||||
char listendictstr[1024];
|
||||
|
||||
if ((r = getdns_str2list("[ 127.0.0.1:18000 ]", &listeners)) ||
|
||||
(r = getdns_str2dict("127.0.0.1:18000", &address2)) ||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s <localhost ipv4>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
(void) snprintf(listenliststr, sizeof(listenliststr),
|
||||
"[ %s:18000 ]", argv[1]);
|
||||
(void) snprintf(listendictstr, sizeof(listendictstr),
|
||||
"%s:18000", argv[1]);
|
||||
|
||||
if ((r = getdns_str2list(listenliststr, &listeners)) ||
|
||||
(r = getdns_str2dict(listendictstr, &address2)) ||
|
||||
(r = getdns_list_get_dict(listeners, 0, &address)) ||
|
||||
(r = getdns_context_create(&context, 0)))
|
||||
fprintf(stderr, "Error initializing: ");
|
||||
|
|
|
@ -4,18 +4,22 @@
|
|||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
LOCALHOST=`${GETDNS_STUB_QUERY} '{namespaces:[GETDNS_NAMESPACE_LOCALNAMES]}' -A localhost. -J \
|
||||
| awk -F: '/\"address_data\".*\"127/{print $2}' \
|
||||
| sed -e 's/^[^"]*"//g' -e 's/"[^"]*$//g'`
|
||||
echo "localhost: $LOCALHOST"
|
||||
|
||||
make && "${BUILDDIR}/build-stub-only/libtool" exec valgrind -v --log-file=valgrind.log --leak-check=full --error-exitcode=1 --track-origins=yes "./${TPKG_NAME}" | (
|
||||
make && "${BUILDDIR}/build-stub-only/libtool" exec valgrind -v --log-file=valgrind.log --leak-check=full --error-exitcode=1 --track-origins=yes "./${TPKG_NAME}" ${LOCALHOST} | (
|
||||
read PORT
|
||||
read PORT2
|
||||
|
||||
${GETDNS_STUB_QUERY} -s -t 1000 @127.0.0.1:$PORT TXT cancel. +return_call_reporting 2>&1 > time_out
|
||||
${GETDNS_STUB_QUERY} -s -t 1000 @${LOCALHOST}:$PORT TXT cancel. +return_call_reporting 2>&1 > time_out
|
||||
|
||||
${GETDNS_STUB_QUERY} -s @127.0.0.1:$PORT TXT test +return_call_reporting 2>&1 > tcp_out
|
||||
${GETDNS_STUB_QUERY} -s @${LOCALHOST}:$PORT TXT test +return_call_reporting 2>&1 > tcp_out
|
||||
|
||||
${GETDNS_STUB_QUERY} -s -U @127.0.0.1:$PORT2 TXT test +return_call_reporting 2>&1 > udp_out
|
||||
${GETDNS_STUB_QUERY} -s -U @${LOCALHOST}:$PORT2 TXT test +return_call_reporting 2>&1 > udp_out
|
||||
|
||||
${GETDNS_STUB_QUERY} -s -q @127.0.0.1:$PORT TXT quit.
|
||||
${GETDNS_STUB_QUERY} -s -q @${LOCALHOST}:$PORT TXT quit.
|
||||
)
|
||||
if grep -q 'definitely lost: [^0]' valgrind.log
|
||||
then
|
||||
|
|
|
@ -107,15 +107,23 @@ void handler(getdns_context *context, getdns_callback_type_t callback_type,
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
getdns_context *context = NULL;
|
||||
getdns_list *listeners = NULL;
|
||||
getdns_dict *address = NULL;
|
||||
uint32_t port = 18000;
|
||||
getdns_return_t r;
|
||||
char listenliststr[1024];
|
||||
|
||||
if ((r = getdns_str2list("[ 127.0.0.1:18000 ]", &listeners)) ||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s <localhost ipv4>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
(void) snprintf(listenliststr, sizeof(listenliststr),
|
||||
"[ %s:18000 ]", argv[1]);
|
||||
|
||||
if ((r = getdns_str2list(listenliststr, &listeners)) ||
|
||||
(r = getdns_list_get_dict(listeners, 0, &address)) ||
|
||||
(r = getdns_context_create(&context, 0)))
|
||||
fprintf(stderr, "Error initializing: ");
|
||||
|
|
|
@ -5,21 +5,27 @@
|
|||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
|
||||
LOCALHOST=`${GETDNS_STUB_QUERY} '{namespaces:[GETDNS_NAMESPACE_LOCALNAMES]}' -A localhost. -J \
|
||||
| awk -F: '/\"address_data\".*\"127/{print $2}' \
|
||||
| sed -e 's/^[^"]*"//g' -e 's/"[^"]*$//g'`
|
||||
echo "localhost: $LOCALHOST"
|
||||
|
||||
QLIMIT=64
|
||||
NQUERIES=`wc "./${TPKG_NAME}.queries"|sed 's/ .*$//g'`
|
||||
NQUERIES=`wc "./${TPKG_NAME}.queries"|sed -e 's/^ *//g' -e 's/ .*$//g'`
|
||||
echo "# queries: $NQUERIES"
|
||||
|
||||
# Test will take NQUERIES / QLIMIT * answer delay
|
||||
# For current parameters this is 1000 / 64 * 0.3 = 4.6875
|
||||
# which is smaller than 5 seconds default query timeout value,
|
||||
# so the test should succeed.
|
||||
|
||||
make && "./${TPKG_NAME}" | (
|
||||
make && "./${TPKG_NAME}" ${LOCALHOST} | (
|
||||
read PORT
|
||||
${GETDNS_STUB_QUERY} @127.0.0.1:$PORT TXT \
|
||||
${GETDNS_STUB_QUERY} @${LOCALHOST}:$PORT TXT \
|
||||
-a -F "./${TPKG_NAME}.queries" \
|
||||
"{limit_outstanding_queries:$QLIMIT}" 2>&1 > out
|
||||
|
||||
${GETDNS_STUB_QUERY} -q @127.0.0.1:$PORT TXT quit.
|
||||
${GETDNS_STUB_QUERY} -q @${LOCALHOST}:$PORT TXT quit.
|
||||
) && grep '"n_requests: [0-9][0-9]*"' out | sed -e 's/^.*n_requests: //g' -e 's/".*$//g' \
|
||||
| awk -vQLIMIT=$QLIMIT -vNQUERIES=$NQUERIES '
|
||||
|
||||
|
|
|
@ -112,15 +112,23 @@ void handler(getdns_context *context, getdns_callback_type_t callback_type,
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
getdns_context *context = NULL;
|
||||
getdns_list *listeners = NULL;
|
||||
getdns_dict *address = NULL;
|
||||
uint32_t port = 18000;
|
||||
getdns_return_t r;
|
||||
char listenliststr[1024];
|
||||
|
||||
if ((r = getdns_str2list("[ 127.0.0.1:18000 ]", &listeners)) ||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s <localhost ipv4>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
(void) snprintf(listenliststr, sizeof(listenliststr),
|
||||
"[ %s:18000 ]", argv[1]);
|
||||
|
||||
if ((r = getdns_str2list(listenliststr, &listeners)) ||
|
||||
(r = getdns_list_get_dict(listeners, 0, &address)) ||
|
||||
(r = getdns_context_create(&context, 0)))
|
||||
fprintf(stderr, "Error initializing: ");
|
||||
|
|
|
@ -5,8 +5,14 @@
|
|||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
|
||||
LOCALHOST=`${GETDNS_STUB_QUERY} '{namespaces:[GETDNS_NAMESPACE_LOCALNAMES]}' -A localhost. -J \
|
||||
| awk -F: '/\"address_data\".*\"127/{print $2}' \
|
||||
| sed -e 's/^[^"]*"//g' -e 's/"[^"]*$//g'`
|
||||
echo "localhost: $LOCALHOST"
|
||||
|
||||
QLIMIT=79
|
||||
NQUERIES=`wc "./${TPKG_NAME}.queries"|sed 's/ .*$//g'`
|
||||
NQUERIES=`wc "./${TPKG_NAME}.queries"|sed -e 's/^ *//g' -e 's/ .*$//g'`
|
||||
echo "# queries: $NQUERIES"
|
||||
|
||||
# This time the query limit is set by setting the maximum open
|
||||
# filedescriptors. We seem to be needing a higher QLIMIT, than
|
||||
|
@ -21,13 +27,13 @@ NQUERIES=`wc "./${TPKG_NAME}.queries"|sed 's/ .*$//g'`
|
|||
# which is smaller than 5 seconds default query timeout value,
|
||||
# so the test should succeed.
|
||||
|
||||
make && "./${TPKG_NAME}" | (
|
||||
make && "./${TPKG_NAME}" ${LOCALHOST}| (
|
||||
read PORT
|
||||
ulimit -n $QLIMIT
|
||||
${GETDNS_STUB_QUERY} @127.0.0.1:$PORT TXT \
|
||||
${GETDNS_STUB_QUERY} @${LOCALHOST}:$PORT TXT \
|
||||
-a -F "./${TPKG_NAME}.queries" 2>&1 > out
|
||||
|
||||
${GETDNS_STUB_QUERY} -q @127.0.0.1:$PORT TXT quit.
|
||||
${GETDNS_STUB_QUERY} -q @${LOCALHOST}:$PORT TXT quit.
|
||||
) && grep '"n_requests: [0-9][0-9]*"' out | sed -e 's/^.*n_requests: //g' -e 's/".*$//g' \
|
||||
| awk -vQLIMIT=$QLIMIT -vNQUERIES=$NQUERIES '
|
||||
|
||||
|
|
|
@ -45,9 +45,9 @@ CFLAGS=-I$(srcdir)/.. -I$(srcdir) -I.. $(cflags) @CFLAGS@ @CPPFLAGS@ $(WPEDANTIC
|
|||
LDFLAGS=-L.. @LDFLAGS@
|
||||
LDLIBS=../libgetdns.la @LIBS@
|
||||
|
||||
ALL_OBJS=getdns_query.lo
|
||||
ALL_OBJS=getdns_query.lo getdns_server_mon.lo
|
||||
|
||||
PROGRAMS=getdns_query
|
||||
PROGRAMS=getdns_query getdns_server_mon
|
||||
|
||||
|
||||
.SUFFIXES: .c .o .a .lo .h
|
||||
|
@ -68,6 +68,9 @@ $(ALL_OBJS):
|
|||
getdns_query: getdns_query.lo
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
getdns_server_mon: getdns_server_mon.lo
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_server_mon.lo $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
stubby:
|
||||
cd .. && $(MAKE) $@
|
||||
|
||||
|
@ -78,6 +81,13 @@ install-getdns_query: getdns_query
|
|||
uninstall-getdns_query:
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/getdns_query
|
||||
|
||||
install-getdns_server_mon: getdns_server_mon
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
|
||||
$(LIBTOOL) --mode=install cp getdns_server_mon $(DESTDIR)$(bindir)
|
||||
|
||||
uninstall-getdns_server_mon:
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/getdns_server_mon
|
||||
|
||||
install-stubby:
|
||||
cd .. && $(MAKE) $@
|
||||
|
||||
|
@ -117,3 +127,10 @@ getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \
|
|||
$(srcdir)/../debug.h \
|
||||
../getdns/getdns.h \
|
||||
../getdns/getdns_extra.h
|
||||
|
||||
# Dependencies for getdns_server_mon
|
||||
getdns_server_mon.lo getdns_server_mon.o: $(srcdir)/getdns_server_mon.c \
|
||||
../config.h \
|
||||
$(srcdir)/../debug.h \
|
||||
../getdns/getdns.h \
|
||||
../getdns/getdns_extra.h
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
= getdns tools
|
||||
|
||||
This directory contains some tools based on `getdns`.
|
||||
|
||||
* `getdns_query` - a command line wrapper for `getdns`.
|
||||
* `getdns_server_mon` - test DNS server function and capabilities.
|
||||
|
||||
== `getdns_query`
|
||||
|
||||
`getdns_query` is a command line wrapper for `getdns` exposing the
|
||||
features of this implementation (both in the official API and the
|
||||
additional API functions).
|
||||
|
||||
=== Usage
|
||||
|
||||
----
|
||||
usage: getdns_query [<option> ...] \
|
||||
[@<upstream> ...] [+<extension> ...] ['{ <settings> }'] [<name>] [<type>]
|
||||
|
||||
default mode: recursive, synchronous resolution of NS record
|
||||
using UDP with TCP fallback
|
||||
|
||||
upstreams: @<ip>[%<scope_id>][@<port>][#<tls port>][~<tls name>][^<tsig spec>]
|
||||
<ip>@<port> may be given as <IPv4>:<port>
|
||||
or '['<IPv6>[%<scope_id>]']':<port> too
|
||||
|
||||
tsig spec: [<algorithm>:]<name>:<secret in Base64>
|
||||
|
||||
extensions:
|
||||
+add_warning_for_bad_dns
|
||||
+dnssec_return_status
|
||||
+dnssec_return_only_secure
|
||||
+dnssec_return_all_statuses
|
||||
+dnssec_return_validation_chain
|
||||
+dnssec_return_full_validation_chain
|
||||
+dnssec_roadblock_avoidance
|
||||
+edns_cookies
|
||||
+return_both_v4_and_v6
|
||||
+return_call_reporting
|
||||
+sit=<cookie> Send along cookie OPT with value <cookie>
|
||||
+specify_class=<class>
|
||||
+0 Clear all extensions
|
||||
|
||||
settings in json dict format (like outputted by -i option).
|
||||
|
||||
options:
|
||||
-a Perform asynchronous resolution (default = synchronous)
|
||||
-A address lookup (<type> is ignored)
|
||||
-B Batch mode. Schedule all messages before processing responses.
|
||||
-b <bufsize> Set edns0 max_udp_payload size
|
||||
-c Send Client Subnet privacy request
|
||||
-C <filename>
|
||||
Read settings from config file <filename>
|
||||
The getdns context will be configured with these settings
|
||||
The file must be in YAML format (with extension of '.yml')
|
||||
or JSON dict format (with extension '.conf')
|
||||
-D Set edns0 do bit
|
||||
-d clear edns0 do bit
|
||||
-e <idle_timeout> Set idle timeout in milliseconds
|
||||
-F <filename> read the queries from the specified file
|
||||
-f <filename> Read DNSSEC trust anchors from <filename>
|
||||
-G general lookup
|
||||
-H hostname lookup. (<name> must be an IP address; <type> is ignored)
|
||||
-h Print this help
|
||||
-i Print api information
|
||||
-I Interactive mode (> 1 queries on same context)
|
||||
-j Output json response dict
|
||||
-J Pretty print json response dict
|
||||
-k Print root trust anchors
|
||||
-K <pin> Pin a public key for TLS connections (can repeat)
|
||||
(should look like 'pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="')
|
||||
-m Set TLS authentication mode to REQUIRED
|
||||
-n Set TLS authentication mode to NONE (default)
|
||||
-o <filename> Set resolver configuration file path
|
||||
(default = /etc/resolv.conf)
|
||||
-p Pretty print response dict (default)
|
||||
-P <blocksize> Pad TLS queries to a multiple of blocksize
|
||||
(special values: 0: no padding, 1: sensible default policy)
|
||||
-q Quiet mode - don't print response
|
||||
-r Set recursing resolution type
|
||||
-R <filename> Read root hints from <filename>
|
||||
-s Set stub resolution type(default = recursing)
|
||||
-S service lookup (<type> is ignored)
|
||||
-t <timeout> Set timeout in milliseconds
|
||||
-v Print getdns release version
|
||||
-V Increase verbosity (may be used more than once)
|
||||
-x Do not follow redirects
|
||||
-X Follow redirects (default)
|
||||
-0 Append suffix to single label first (default)
|
||||
-W Append suffix always
|
||||
-1 Append suffix only to single label after failure
|
||||
-M Append suffix only to multi label name after failure
|
||||
-N Never append a suffix
|
||||
-Z <suffixes> Set suffixes with the given comma separated list
|
||||
-T Set transport to TCP only
|
||||
-O Set transport to TCP only keep connections open
|
||||
-L Set transport to TLS only keep connections open
|
||||
-E Set transport to TLS with TCP fallback only keep connections open
|
||||
-u Set transport to UDP with TCP fallback (default)
|
||||
-U Set transport to UDP only
|
||||
-l <transports> Set transport list. List can contain 1 of each of the characters
|
||||
U T L for UDP, TCP or TLS e.g 'UT' or 'LTU'
|
||||
-z <listen address>
|
||||
Listen for DNS requests on the given IP address
|
||||
<listen address> is in the same format as upstreams.
|
||||
This option can be given more than once.
|
||||
----
|
||||
|
||||
== `getdns_server_mon`
|
||||
|
||||
`getdns_server_mon` is a collection of DNS server tests. The tests examine
|
||||
both server function and server capability.
|
||||
|
||||
`get_server_mon` can optionally be run in Monitoring mode. In this mode,
|
||||
the tool output is modified to enable it to function as a plugin for
|
||||
popular monitoring systems such as https://www.icinga.org[Icinga],
|
||||
http://naemon.github.io/[Naemon], http://www.nagios.org[Nagios],
|
||||
http://www.shinken-monitoring.org/[Shinken], http://sensuapp.org/[Sensu]
|
||||
and others.
|
||||
|
||||
=== Usage
|
||||
|
||||
----
|
||||
Usage: getdns_server_mon [-M] [-E] [(-u|-t|-T)] [-S] [-K <spki-pin>]
|
||||
[-v [-v [-v]]] [-V] @upstream testname [<test args>]
|
||||
-M|--monitoring Make output suitable for monitoring tools
|
||||
-E|--fail-on-dns-errors Fail on DNS error (NXDOMAIN, SERVFAIL)
|
||||
-u|--udp Use UDP transport
|
||||
-t|--tcp Use TCP transport
|
||||
-T|--tls Use TLS transport
|
||||
-S|--strict-usage-profile Use strict profile (require authentication)
|
||||
-K|--spki-pin <spki-pin> SPKI pin for TLS connections (can repeat)
|
||||
-v|--verbose Increase output verbosity
|
||||
-D|--debug Enable debugging output
|
||||
-V|--version Report GetDNS version
|
||||
|
||||
spki-pin: Should look like 'pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="'
|
||||
|
||||
upstream: @<ip>[%<scope_id][@<port>][#<tls_port>][~tls name>][^<tsig spec>]
|
||||
<ip>@<port> may be given as <IPv4>:<port> or
|
||||
'['<IPv6>[%<scope_id>]']':<port>
|
||||
|
||||
tsig spec: [<algorithm>:]<name>:<secret in Base64>
|
||||
|
||||
Tests:
|
||||
lookup [<name> [<type>]] Check lookup on server
|
||||
keepalive <timeout-ms> [<name> [<type>]]
|
||||
Check server support for EDNS0 keepalive in
|
||||
TCP or TLS connections
|
||||
Timeout of 0 is off.
|
||||
OOOR Check whether server delivers responses out of
|
||||
query order on a TCP or TLS connection
|
||||
qname-min Check whether server supports QNAME minimisation
|
||||
rtt [warn-ms,crit-ms] [<name> [<type>]]
|
||||
Check if server round trip time exceeds
|
||||
thresholds (default 250,500)
|
||||
|
||||
dnssec-validate Check whether server does DNSSEC validation
|
||||
|
||||
tls-auth [<name> [<type>]] Check authentication of TLS server
|
||||
If both a SPKI pin and authentication name are
|
||||
provided, both must authenticate for this test
|
||||
to pass.
|
||||
tls-cert-valid [warn-days,crit-days] [<name> [type]]
|
||||
Check server certificate validity, report
|
||||
warning or critical if days to expiry at
|
||||
or below thresholds (default 14,7).
|
||||
tls-padding <blocksize> [<name> [<type>]]
|
||||
Check server support for EDNS0 padding in TLS
|
||||
Special blocksize values are 0 = off,
|
||||
1 = sensible default.
|
||||
tls-1.3 Check whether server supports TLS 1.3
|
||||
|
||||
Enabling monitoring mode ensures output messages and exit statuses conform
|
||||
to the requirements of monitoring plugins (www.monitoring-plugins.org).
|
||||
----
|
||||
|
||||
Note that the server must currently be specified with an IPv4 or an IPv6 address.
|
||||
|
||||
=== The tests
|
||||
|
||||
Several tests take optional name and RR type parameters. If these are not supplied,
|
||||
default values of `getdnsapi.net` and `AAAA` are used. If the lookup returns no
|
||||
answering records, `getdns_server_mon` reports a status of WARNING.
|
||||
|
||||
[cols="1,3a,1" options="header"]
|
||||
|===
|
||||
| Test name | Test description | Default connection type
|
||||
| `lookup`
|
||||
| Check a name lookup succeeds.
|
||||
| UDP with TCP fallback
|
||||
|
||||
| `keepalive`
|
||||
| See if the server supports EDNS0 keepalive in TCP or TLS
|
||||
connections. Specify a non-zero timeout to set the keepalive timeout
|
||||
in milliseconds, or 0 to disable it.
|
||||
| TCP
|
||||
|
||||
| `OOOR`
|
||||
| Out Of Order Responses. See if the server will send responses to
|
||||
multiple queries in a single TCP or TLS connection in a different
|
||||
order to the order of queries.
|
||||
|
||||
This test is currently experimental, and may give false negative results.
|
||||
| TCP
|
||||
|
||||
| `qname-min`
|
||||
| Does the server support QNAME minimisation?
|
||||
| UDP with TCP fallback
|
||||
|
||||
|`rtt`
|
||||
| Check a lookup round trip time exceeds warning and critical levels in milliseconds.
|
||||
If thresholds are not specified, defaults of 500ms (critical) and 250ms (warning) are used.
|
||||
| UDP with TCP fallback
|
||||
|
||||
|`dnssec-validate`
|
||||
| See if the server is doing DNSSEC validation.
|
||||
| UDP with TCP fallback
|
||||
|
||||
|`tls-auth`
|
||||
| Check if a TLS lookup authenticates successfully. You must specify
|
||||
either a SPKI pin, an authentication name, or both. If you supply
|
||||
both, both must authenticate for the test to succeed.
|
||||
| TLS
|
||||
|
||||
|`tls-cert-valid`
|
||||
| Check the server certificate against warning and critical days to
|
||||
expiry. If thresholds are not specified, defaults of 7 days
|
||||
(critical) and 14 days (warning) are used.
|
||||
| TLS
|
||||
|
||||
|`tls-padding`
|
||||
| Does the server support EDNS0 padding? Specify a non-zero blocksize to set
|
||||
the padding. A padding size of 1 specifies padding of a sensible default size.
|
||||
| TLS
|
||||
|
||||
|`tls-1.3`
|
||||
| Does the server support TLS 1.3? To enable this test,
|
||||
`getdns_server_mon` must be compiled with OpenSSL v1.1.1 or later.
|
||||
|
||||
This test is currently experimental, and may give false negative results.
|
||||
| TLS
|
||||
|===
|
||||
=== Exit status
|
||||
|
||||
[cols="^1,^1,3a" options="header"]
|
||||
|===
|
||||
| Numeric value | Service Status | Status Description
|
||||
| 0
|
||||
| OK
|
||||
| The service was functioning properly
|
||||
|
||||
| 1
|
||||
| WARNING
|
||||
| The service fell below a warning threshold
|
||||
|
||||
|2
|
||||
| CRITICAL
|
||||
| The service was not working or fell below a critical threshold
|
||||
|
||||
|3
|
||||
| UNKNOWN | Invalid arguments or an internal low-level failure
|
||||
|===
|
|
@ -57,19 +57,7 @@ getdns_return_t getdns_yaml2dict(const char *, getdns_dict **dict);
|
|||
#define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""
|
||||
|
||||
static int verbosity = 0;
|
||||
static int i_am_stubby = 0;
|
||||
static const char *default_stubby_config =
|
||||
"{ resolution_type: GETDNS_RESOLUTION_STUB"
|
||||
", dns_transport_list: [ GETDNS_TRANSPORT_TLS, GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP ]"
|
||||
", idle_timeout: 10000"
|
||||
", listen_addresses: [ 127.0.0.1@53, 0::1@53 ]"
|
||||
", tls_query_padding_blocksize: 1"
|
||||
", edns_client_subnet_private : 1"
|
||||
"}";
|
||||
static int clear_listen_list_on_arg = 0;
|
||||
#ifndef GETDNS_ON_WINDOWS
|
||||
static int run_in_foreground = 1;
|
||||
#endif
|
||||
static int quiet = 0;
|
||||
static int batch_mode = 0;
|
||||
static char *query_file = NULL;
|
||||
|
@ -95,6 +83,8 @@ static int check_dnssec = 0;
|
|||
static char *resolvconf = NULL;
|
||||
#endif
|
||||
static int print_api_info = 0, print_trust_anchors = 0;
|
||||
static int log_level = 0;
|
||||
static uint64_t log_systems = 0xFFFFFFFFFFFFFFFF;
|
||||
|
||||
static int get_rrtype(const char *t)
|
||||
{
|
||||
|
@ -179,19 +169,14 @@ print_usage(FILE *out, const char *progname)
|
|||
{
|
||||
fprintf(out, "usage: %s [<option> ...] \\\n"
|
||||
"\t[@<upstream> ...] [+<extension> ...] [\'{ <settings> }\'] [<name>] [<type>]\n", progname);
|
||||
if (!i_am_stubby) {
|
||||
fprintf(out, "\ndefault mode: "
|
||||
|
||||
#ifdef HAVE_LIBUNBOUND
|
||||
"recursive"
|
||||
# define DEFAULT_RESOLUTION_TYPE "recursive"
|
||||
#else
|
||||
"stub"
|
||||
# define DEFAULT_RESOLUTION_TYPE "stub"
|
||||
#endif
|
||||
", synchronous resolution of NS record\n\t\tusing UDP with TCP fallback\n");
|
||||
}
|
||||
else {
|
||||
fprintf(out, "\ndefault mode: "
|
||||
"stub, asynchronous resolution \n\t\tusing TLS with UDP then TCP fallback\n");
|
||||
}
|
||||
fprintf(out, "\ndefault mode: " DEFAULT_RESOLUTION_TYPE
|
||||
", synchronous resolution of NS record\n\t\tusing UDP with TCP fallback\n");
|
||||
fprintf(out, "\nupstreams: @<ip>[%%<scope_id>][@<port>][#<tls port>][~<tls name>][^<tsig spec>]");
|
||||
fprintf(out, "\n <ip>@<port> may be given as <IPv4>:<port>");
|
||||
fprintf(out, "\n or \'[\'<IPv6>[%%<scope_id>]\']\':<port> too\n");
|
||||
|
@ -216,12 +201,9 @@ print_usage(FILE *out, const char *progname)
|
|||
fprintf(out, "\t+0\t\t\tClear all extensions\n");
|
||||
fprintf(out, "\nsettings in json dict format (like outputted by -i option).\n");
|
||||
fprintf(out, "\noptions:\n");
|
||||
if (!i_am_stubby) {
|
||||
fprintf(out, "\t-a\tPerform asynchronous resolution "
|
||||
"(default = synchronous)\n");
|
||||
fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n");
|
||||
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
|
||||
}
|
||||
fprintf(out, "\t-a\tPerform asynchronous resolution (default = synchronous)\n");
|
||||
fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n");
|
||||
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
|
||||
fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n");
|
||||
fprintf(out, "\t-c\tSend Client Subnet privacy request\n");
|
||||
fprintf(out, "\t-C\t<filename>\n");
|
||||
|
@ -229,28 +211,16 @@ print_usage(FILE *out, const char *progname)
|
|||
fprintf(out, "\t\tThe getdns context will be configured with these settings\n");
|
||||
fprintf(out, "\t\tThe file must be in YAML format (with extension of '.yml')\n");
|
||||
fprintf(out, "\t\tor JSON dict format (with extension '.conf')\n");
|
||||
if (i_am_stubby) {
|
||||
fprintf(out, "\t\tBy default, configuration is first read from");
|
||||
fprintf(out, "\n\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\"\n");
|
||||
}
|
||||
fprintf(out, "\t-D\tSet edns0 do bit\n");
|
||||
fprintf(out, "\t-d\tclear edns0 do bit\n");
|
||||
fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in milliseconds\n");
|
||||
if (!i_am_stubby)
|
||||
fprintf(out, "\t-F <filename>\tread the queries from the specified file\n");
|
||||
fprintf(out, "\t-F <filename>\tread the queries from the specified file\n");
|
||||
fprintf(out, "\t-f <filename>\tRead DNSSEC trust anchors from <filename>\n");
|
||||
#ifndef GETDNS_ON_WINDOWS
|
||||
if (i_am_stubby)
|
||||
fprintf(out, "\t-g\tRun stubby in background (default is foreground)\n");
|
||||
#endif
|
||||
if (!i_am_stubby) {
|
||||
fprintf(out, "\t-G\tgeneral lookup\n");
|
||||
fprintf(out, "\t-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n");
|
||||
}
|
||||
fprintf(out, "\t-G\tgeneral lookup\n");
|
||||
fprintf(out, "\t-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n");
|
||||
fprintf(out, "\t-h\tPrint this help\n");
|
||||
fprintf(out, "\t-i\tPrint api information\n");
|
||||
if (!i_am_stubby)
|
||||
fprintf(out, "\t-I\tInteractive mode (> 1 queries on same context)\n");
|
||||
fprintf(out, "\t-I\tInteractive mode (> 1 queries on same context)\n");
|
||||
fprintf(out, "\t-j\tOutput json response dict\n");
|
||||
fprintf(out, "\t-J\tPretty print json response dict\n");
|
||||
fprintf(out, "\t-k\tPrint root trust anchors\n");
|
||||
|
@ -266,19 +236,21 @@ print_usage(FILE *out, const char *progname)
|
|||
fprintf(out, "\t-P <blocksize>\tPad TLS queries to a multiple of blocksize\n"
|
||||
"\t\t(special values: 0: no padding, 1: sensible default policy)\n");
|
||||
fprintf(out, "\t-q\tQuiet mode - don't print response\n");
|
||||
fprintf( out, "\t-r\tSet recursing resolution type%s\n"
|
||||
, i_am_stubby ? "(default = stub)" : "");
|
||||
fprintf( out, "\t-r\tSet recursing resolution type (default = "
|
||||
DEFAULT_RESOLUTION_TYPE ")\n");
|
||||
fprintf(out, "\t-R <filename>\tRead root hints from <filename>\n");
|
||||
fprintf(out, "\t-s\tSet stub resolution type%s\n"
|
||||
, i_am_stubby ? "" : "(default = recursing)" );
|
||||
if (!i_am_stubby)
|
||||
fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n");
|
||||
fprintf(out, "\t-s\tSet stub resolution type (default = "
|
||||
DEFAULT_RESOLUTION_TYPE ")\n");
|
||||
fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n");
|
||||
fprintf(out, "\t-t <timeout>\tSet timeout in milliseconds\n");
|
||||
fprintf(out, "\t-v\tPrint getdns release version\n");
|
||||
fprintf(out, "\t-V\tIncrease verbosity (may be used more than once)\n");
|
||||
fprintf(out, "\t-x\tDo not follow redirects\n");
|
||||
fprintf(out, "\t-X\tFollow redirects (default)\n");
|
||||
|
||||
fprintf(out, "\t-y <log level>\tPrint log messages with"
|
||||
"severity <= <log level> (default = 0)\n");
|
||||
fprintf(out, "\t-Y <log systems>\tBitwise or'ed set of systems for "
|
||||
" which to print log messages (default == -1 (= all))\n");
|
||||
fprintf(out, "\t-0\tAppend suffix to single label first (default)\n");
|
||||
fprintf(out, "\t-W\tAppend suffix always\n");
|
||||
fprintf(out, "\t-1\tAppend suffix only to single label after failure\n");
|
||||
|
@ -298,8 +270,6 @@ print_usage(FILE *out, const char *progname)
|
|||
fprintf(out, "\t\tListen for DNS requests on the given IP address\n");
|
||||
fprintf(out, "\t\t<listen address> is in the same format as upstreams.\n");
|
||||
fprintf(out, "\t\tThis option can be given more than once.\n");
|
||||
if (i_am_stubby)
|
||||
fprintf(out, "\t\t(default is to listen on 127.0.0.1:53)\n");
|
||||
}
|
||||
|
||||
static getdns_return_t validate_chain(getdns_dict *response)
|
||||
|
@ -609,6 +579,7 @@ getdns_return_t parse_args(int argc, char **argv)
|
|||
getdns_bindata bindata;
|
||||
size_t upstream_count = 0;
|
||||
FILE *fh;
|
||||
int int_value;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
arg = argv[i];
|
||||
|
@ -927,17 +898,49 @@ getdns_return_t parse_args(int argc, char **argv)
|
|||
getdns_context_set_follow_redirects(
|
||||
context, GETDNS_REDIRECTS_FOLLOW);
|
||||
break;
|
||||
case 'y':
|
||||
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
|
||||
fprintf(stderr, "log level expected "
|
||||
"after -y\n");
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
int_value = strtol(argv[i], &endptr, 10);
|
||||
if (*endptr || int_value < 0) {
|
||||
fprintf(stderr, "positive "
|
||||
"numeric log level expected "
|
||||
"after -y\n");
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
} else
|
||||
log_level = int_value;
|
||||
goto next;
|
||||
|
||||
case 'Y':
|
||||
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
|
||||
fprintf(stderr, "log systems expected "
|
||||
"after -y\n");
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
int_value = strtol(argv[i], &endptr, 10);
|
||||
if (*endptr || int_value < 0) {
|
||||
fprintf(stderr, "positive "
|
||||
"numeric log systems expected "
|
||||
"after -Y\n");
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
} else
|
||||
log_systems = (uint64_t)int_value;
|
||||
goto next;
|
||||
|
||||
case 'e':
|
||||
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
|
||||
fprintf(stderr, "idle timeout expected "
|
||||
"after -t\n");
|
||||
"after -e\n");
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
timeout = strtol(argv[i], &endptr, 10);
|
||||
if (*endptr || timeout < 0) {
|
||||
fprintf(stderr, "positive "
|
||||
"numeric idle timeout expected "
|
||||
"after -t\n");
|
||||
"after -e\n");
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
getdns_context_set_idle_timeout(
|
||||
|
@ -1081,12 +1084,6 @@ getdns_return_t parse_args(int argc, char **argv)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
#ifndef GETDNS_ON_WINDOWS
|
||||
if (i_am_stubby && *c == 'g') {
|
||||
run_in_foreground = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
fprintf(stderr, "Unknown option "
|
||||
"\"%c\"\n", *c);
|
||||
for (i = 0; i < argc; i++)
|
||||
|
@ -1616,7 +1613,43 @@ static void incoming_request_handler(getdns_context *context,
|
|||
fprintf(stderr, "Could set class from query: %s\n",
|
||||
getdns_get_errorstr_by_id(r));
|
||||
|
||||
else if ((r = getdns_general(context, qname_str, qtype,
|
||||
else if (qtype == GETDNS_RRTYPE_TXT && qclass == GETDNS_RRCLASS_CH &&
|
||||
strcasecmp(qname_str, "version.bind.") == 0) {
|
||||
const char *getdns_query_version = "getdns_query " GETDNS_VERSION;
|
||||
char getdns_version[100] = "getdns ";
|
||||
char getdns_api_version[100] = "getdns API ";
|
||||
|
||||
response = request;
|
||||
(void) getdns_dict_set_bindata(response, "/answer/0/name", qname);
|
||||
(void) getdns_dict_set_int(response, "/answer/0/type", qtype);
|
||||
(void) getdns_dict_set_int(response, "/answer/0/class", qclass);
|
||||
(void) getdns_dict_set_int(response, "/answer/0/ttl", 0);
|
||||
(void) getdns_dict_util_set_string(response,
|
||||
"/answer/0/rdata/txt_strings/0", getdns_query_version);
|
||||
|
||||
(void) getdns_dict_set_bindata(response, "/answer/1/name", qname);
|
||||
(void) getdns_dict_set_int(response, "/answer/1/type", qtype);
|
||||
(void) getdns_dict_set_int(response, "/answer/1/class", qclass);
|
||||
(void) getdns_dict_set_int(response, "/answer/1/ttl", 0);
|
||||
(void) strncat(getdns_version + 7,
|
||||
getdns_get_version(), sizeof(getdns_version) - 8);
|
||||
(void) getdns_dict_util_set_string(response,
|
||||
"/answer/1/rdata/txt_strings/0",getdns_version);
|
||||
|
||||
(void) getdns_dict_set_bindata(response, "/answer/2/name", qname);
|
||||
(void) getdns_dict_set_int(response, "/answer/2/type", qtype);
|
||||
(void) getdns_dict_set_int(response, "/answer/2/class", qclass);
|
||||
(void) getdns_dict_set_int(response, "/answer/2/ttl", 0);
|
||||
(void) strncat(getdns_api_version + 11,
|
||||
getdns_get_api_version(), sizeof(getdns_api_version) - 12);
|
||||
(void) getdns_dict_util_set_string(response,
|
||||
"/answer/2/rdata/txt_strings/0",getdns_api_version);
|
||||
|
||||
(void) getdns_dict_set_int(response, "/header/ancount", 3);
|
||||
|
||||
goto answer_request;
|
||||
|
||||
} else if ((r = getdns_general(context, qname_str, qtype,
|
||||
qext, msg, &transaction_id, request_cb)))
|
||||
fprintf(stderr, "Could not schedule query: %s\n",
|
||||
getdns_get_errorstr_by_id(r));
|
||||
|
@ -1627,9 +1660,8 @@ static void incoming_request_handler(getdns_context *context,
|
|||
return;
|
||||
}
|
||||
error:
|
||||
if (qname_str)
|
||||
free(qname_str);
|
||||
servfail(msg, &response);
|
||||
answer_request:
|
||||
#if defined(SERVER_DEBUG) && SERVER_DEBUG
|
||||
do {
|
||||
char *request_str = getdns_pretty_print_dict(request);
|
||||
|
@ -1646,16 +1678,20 @@ error:
|
|||
/* Cancel reply */
|
||||
getdns_reply(context, NULL, request_id);
|
||||
}
|
||||
if (response && response != request)
|
||||
getdns_dict_destroy(response);
|
||||
|
||||
if (qname_str)
|
||||
free(qname_str);
|
||||
|
||||
if (msg) {
|
||||
if (msg->request)
|
||||
getdns_dict_destroy(msg->request);
|
||||
free(msg);
|
||||
}
|
||||
if (response)
|
||||
getdns_dict_destroy(response);
|
||||
}
|
||||
|
||||
static void stubby_log(void *userarg, uint64_t system,
|
||||
static void _getdns_query_log(void *userarg, uint64_t system,
|
||||
getdns_loglevel_type level, const char *fmt, va_list ap)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
@ -1664,16 +1700,10 @@ static void stubby_log(void *userarg, uint64_t system,
|
|||
#ifdef GETDNS_ON_WINDOWS
|
||||
time_t tsec;
|
||||
|
||||
if (!verbosity)
|
||||
return;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
tsec = (time_t) tv.tv_sec;
|
||||
gmtime_s(&tm, (const time_t *) &tsec);
|
||||
#else
|
||||
if (!verbosity)
|
||||
return;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
gmtime_r(&tv.tv_sec, &tm);
|
||||
#endif
|
||||
|
@ -1695,18 +1725,7 @@ static void stubby_log(void *userarg, uint64_t system,
|
|||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char home_stubby_conf_fn[1024];
|
||||
getdns_return_t r;
|
||||
#ifndef USE_WINSOCK
|
||||
char *prg_name = strrchr(argv[0], '/');
|
||||
#else
|
||||
char *prg_name = strrchr(argv[0], '\\');
|
||||
#endif
|
||||
prg_name = prg_name ? prg_name + 1 : argv[0];
|
||||
|
||||
i_am_stubby = strcasecmp(prg_name, "stubby") == 0
|
||||
|| strcasecmp(prg_name, "lt-stubby") == 0
|
||||
|| strcasecmp(prg_name, "stubby.exe") == 0;
|
||||
|
||||
name = the_root;
|
||||
if ((r = getdns_context_create(&context, 1))) {
|
||||
|
@ -1721,22 +1740,6 @@ main(int argc, char **argv)
|
|||
r = GETDNS_RETURN_MEMORY_ERROR;
|
||||
goto done_destroy_context;
|
||||
}
|
||||
if (i_am_stubby) {
|
||||
int n_chars = snprintf( home_stubby_conf_fn
|
||||
, sizeof(home_stubby_conf_fn)
|
||||
, "%s/.stubby.conf"
|
||||
, getenv("HOME")
|
||||
);
|
||||
(void) parse_config(default_stubby_config, 0);
|
||||
(void) parse_config_file("/etc/stubby.conf", 0);
|
||||
if (n_chars > 0 && n_chars < (int)sizeof(home_stubby_conf_fn)){
|
||||
(void) parse_config_file(home_stubby_conf_fn, 0);
|
||||
}
|
||||
clear_listen_list_on_arg = 1;
|
||||
}
|
||||
(void) getdns_context_set_logfunc(context, NULL,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, stubby_log);
|
||||
|
||||
if ((r = parse_args(argc, argv)) && r != CONTINUE)
|
||||
goto done_destroy_context;
|
||||
#ifndef USE_WINSOCK
|
||||
|
@ -1749,6 +1752,9 @@ main(int argc, char **argv)
|
|||
goto done_destroy_context;
|
||||
}
|
||||
#endif
|
||||
(void) getdns_context_set_logfunc(context, NULL,
|
||||
log_systems, log_level, _getdns_query_log);
|
||||
|
||||
if (print_api_info) {
|
||||
getdns_dict *api_information =
|
||||
getdns_context_get_api_information(context);
|
||||
|
@ -1863,7 +1869,7 @@ done_destroy_context:
|
|||
else if (r == CONTINUE_ERROR)
|
||||
return 1;
|
||||
|
||||
if (!i_am_stubby && verbosity)
|
||||
if (verbosity)
|
||||
fprintf(stdout, "\nAll done.\n");
|
||||
|
||||
return r ? r
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -242,6 +242,7 @@ typedef struct getdns_network_req
|
|||
uint64_t debug_end_time;
|
||||
getdns_auth_state_t debug_tls_auth_status;
|
||||
getdns_bindata debug_tls_peer_cert;
|
||||
const char *debug_tls_version;
|
||||
size_t debug_udp;
|
||||
|
||||
/* When more space is needed for the wire_data response than is
|
||||
|
|
|
@ -880,6 +880,10 @@ _getdns_create_call_reporting_dict(
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if (getdns_dict_set_int( netreq_debug, "server_keepalive_received", netreq->upstream->server_keepalive_received)) {
|
||||
getdns_dict_destroy(netreq_debug);
|
||||
return NULL;
|
||||
}
|
||||
/* The running totals are only updated when a connection is closed.
|
||||
Since it is open as we have just used it, calcualte the value on the fly */
|
||||
if (getdns_dict_set_int( netreq_debug, "responses_on_this_connection",
|
||||
|
@ -916,6 +920,12 @@ _getdns_create_call_reporting_dict(
|
|||
getdns_dict_destroy(netreq_debug);
|
||||
return NULL;
|
||||
}
|
||||
if (getdns_dict_util_set_string(netreq_debug, "tls_version",
|
||||
netreq->debug_tls_version)){
|
||||
|
||||
getdns_dict_destroy(netreq_debug);
|
||||
return NULL;
|
||||
}
|
||||
if (getdns_dict_set_bindata(netreq_debug, "tls_peer_cert",
|
||||
&netreq->debug_tls_peer_cert)) {
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ static int
|
|||
setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
|
||||
{
|
||||
/* convert from two BIGNUMs in the rdata buffer, to ASN notation.
|
||||
* ASN preable: 30440220 <R 32bytefor256> 0220 <S 32bytefor256>
|
||||
* ASN preamble: 30440220 <R 32bytefor256> 0220 <S 32bytefor256>
|
||||
* the '20' is the length of that field (=bnsize).
|
||||
i * the '44' is the total remaining length.
|
||||
* if negative, start with leading zero.
|
||||
|
|
2
stubby
2
stubby
|
@ -1 +1 @@
|
|||
Subproject commit f0b330454b95a07106af33b1869b7cd18cfaebf2
|
||||
Subproject commit 1a6acd642c7dc9a04cf092e1a3837c5636d4b465
|
Loading…
Reference in New Issue