Merge abstracted TLS API + GnuTLS alternative

Thank you Jim!

Merge branch 'devel/abstract-tls' into develop
This commit is contained in:
Willem Toorop 2019-01-23 12:52:59 +01:00
commit 2206558376
47 changed files with 4686 additions and 2346 deletions

View File

@ -1,4 +1,5 @@
sudo: false sudo: false
dist: xenial
language: c language: c
compiler: compiler:
- gcc - gcc
@ -6,6 +7,7 @@ compiler:
addons: addons:
apt: apt:
packages: packages:
- libssl-dev
- libunbound-dev - libunbound-dev
- libidn11-dev - libidn11-dev
- libyaml-dev - libyaml-dev

View File

@ -1,4 +1,12 @@
* 2019-01-11: Version 1.5.1 * 2019-01-11: Version 1.5.1
* Introduce proof of concept GnuTLS implementation. Incomplete support
for Trust Anchor validation. Requires GnuTLS DANE library. Currently
untested with GnuTLS prior to 3.5.19, so configure demands a minumum
version of 3.5.0.
* Be consistent and always fail connection setup if setting ciphers/curves/
TLS version/cipher suites fails.
* Refactor OpenSSL usage into modules under src/openssl.
Drop support for LibreSSL and versions of OpenSSL prior to 1.0.2.
* PR #414: remove TLS13 ciphers from cipher_list, but * PR #414: remove TLS13 ciphers from cipher_list, but
only when SSL_CTX_set_ciphersuites is available. only when SSL_CTX_set_ciphersuites is available.
Thanks Bruno Pagani Thanks Bruno Pagani

View File

@ -213,6 +213,7 @@ $(distdir):
mkdir -p $(distdir)/src/compat mkdir -p $(distdir)/src/compat
mkdir -p $(distdir)/src/util mkdir -p $(distdir)/src/util
mkdir -p $(distdir)/src/gldns mkdir -p $(distdir)/src/gldns
mkdir -p $(distdir)/src/openssl
mkdir -p $(distdir)/src/tools mkdir -p $(distdir)/src/tools
mkdir -p $(distdir)/src/jsmn mkdir -p $(distdir)/src/jsmn
mkdir -p $(distdir)/src/yxml mkdir -p $(distdir)/src/yxml
@ -266,6 +267,7 @@ $(distdir):
cp $(srcdir)/spec/*.html $(distdir)/spec cp $(srcdir)/spec/*.html $(distdir)/spec
cp $(srcdir)/spec/example/Makefile.in $(distdir)/spec/example cp $(srcdir)/spec/example/Makefile.in $(distdir)/spec/example
cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example
cp $(srcdir)/src/tools/*.[ch] $(distdir)/src/openssl
cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools
cp $(srcdir)/src/tools/*.[ch] $(distdir)/src/tools cp $(srcdir)/src/tools/*.[ch] $(distdir)/src/tools
cp $(srcdir)/stubby/stubby.yml.example $(distdir)/stubby cp $(srcdir)/stubby/stubby.yml.example $(distdir)/stubby

View File

@ -33,6 +33,7 @@ AC_PREREQ([2.68])
AC_CONFIG_MACRO_DIRS([m4]) AC_CONFIG_MACRO_DIRS([m4])
sinclude(./m4/acx_openssl.m4) sinclude(./m4/acx_openssl.m4)
sinclude(./m4/acx_getaddrinfo.m4) sinclude(./m4/acx_getaddrinfo.m4)
sinclude(./m4/ac_lib_nettle.m4)
sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/ax_check_compile_flag.m4)
sinclude(./m4/pkg.m4) sinclude(./m4/pkg.m4)
@ -441,25 +442,65 @@ dnl SSLLIB=""
dnl ] dnl ]
dnl ) dnl )
# Which TLS and crypto libs to use.
AC_ARG_WITH([gnutls],
[AS_HELP_STRING([--with-gnutls],
[use GnuTLS instead of OpenSSL])],
[
PKG_CHECK_MODULES([libgnutls], [gnutls >= 3.5.0])
PKG_CHECK_MODULES([libgnutlsdane], [gnutls-dane >= 3.5.0])
LIBS="$libgnutls_LIBS $libgnutlsdane_LIBS $LIBS"
CFLAGS="$libgnutls_CFLAGS $libgnutlsdane_CFLAGS $CFLAGS"
AC_SUBST([TLSDIR], 'gnutls')
AC_DEFINE([USE_GNUTLS], [1], [Use the GnuTLS library])
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
AX_LIB_NETTLE(yes)
USE_NETTLE="yes"
AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT])
fi
],
[
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
ACX_WITH_SSL
fi
ACX_LIB_SSL
AC_SUBST([TLSDIR], 'openssl')
# Verify OpenSSL is at least version 1.0.2.
# We also check it's not LibreSSL, but that's a little later, not here.
AC_CHECK_FUNCS([X509_check_host SSL_dane_enable])
if test "x$ac_cv_func_X509_check_host" != xyes; then
AC_MSG_ERROR([getdns requires OpenSSL version 1.0.2 or later])
fi
AC_MSG_CHECKING([whether we need to compile/link DANE support])
DANESSL_XTRA_OBJS=""
if test "x$ac_cv_func_SSL_dane_enable" = xyes; then
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
AC_DEFINE([USE_DANESSL], [1], [Define this to use DANE functions from the ssl_dane/danessl library.])
DANESSL_XTRA_OBJS="danessl.lo"
fi
AC_SUBST(DANESSL_XTRA_OBJS)
])
# openssl # openssl
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then if test $USE_NSS = "no" -a $USE_NETTLE = "no" ; then
ACX_WITH_SSL
fi
ACX_LIB_SSL
AC_MSG_CHECKING([for LibreSSL]) AC_MSG_CHECKING([for LibreSSL])
if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_LIBRESSL], [1], [Define if we have LibreSSL]) AC_MSG_ERROR([getdns does not support LibreSSL])
# libressl provides these compat functions, but they may also be
# declared by the OS in libc. See if they have been declared.
AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform])
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
AC_CHECK_HEADERS([openssl/conf.h openssl/ssl.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/conf.h openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version SSL_CTX_dane_enable SSL_dane_enable SSL_dane_tlsa_add X509_check_host X509_get_notAfter X509_get0_notAfter SSL_CTX_set_ciphersuites SSL_set_ciphersuites]) AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify OpenSSL_version_num OpenSSL_version SSL_CTX_dane_enable SSL_dane_enable SSL_dane_tlsa_add X509_check_host X509_get_notAfter X509_get0_notAfter SSL_CTX_set_ciphersuites SSL_set_ciphersuites OPENSSL_init_crypto DSA_set0_pqg DSA_set0_key RSA_set0_key])
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set1_curves_list,SSL_set1_curves_list,SSL_set_min_proto_version,SSL_get_min_proto_version], [], [], [ AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set1_curves_list,SSL_set1_curves_list,SSL_set_min_proto_version,SSL_get_min_proto_version], [], [], [
AC_INCLUDES_DEFAULT AC_INCLUDES_DEFAULT
#ifdef HAVE_OPENSSL_ERR_H #ifdef HAVE_OPENSSL_ERR_H
@ -480,29 +521,7 @@ AC_INCLUDES_DEFAULT
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/evp.h> #include <openssl/evp.h>
]) ])
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])) AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
case "$enable_sha1" in case "$enable_sha1" in
@ -772,8 +791,8 @@ case "$enable_edns_cookies" in
no) no)
;; ;;
yes|*) yes|*)
if test "x_$HAVE_SSL" != "x_yes"; then if test "x_$HAVE_SSL" != "x_yes" -a $USE_NETTLE = "no"; then
AC_MSG_ERROR([edns cookies need openssl libcrypto which is not available, please rerun with --disable-edns-cookies]) AC_MSG_ERROR([edns cookies needs crypto library which is not available, please rerun with --disable-edns-cookies])
fi fi
AC_DEFINE_UNQUOTED([EDNS_COOKIES], [1], [Define this to enable the experimental edns cookies.]) AC_DEFINE_UNQUOTED([EDNS_COOKIES], [1], [Define this to enable the experimental edns cookies.])
;; ;;

80
m4/ax_lib_nettle.m4 Normal file
View File

@ -0,0 +1,80 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_lib_nettle.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_LIB_NETTLE([yes|no|auto])
#
# DESCRIPTION
#
# Searches for the 'nettle' library with the --with... option.
#
# If found, define HAVE_NETTLE and macro NETTLE_LIBS. Also defines
# NETTLE_WITH_<algo> for the algorithms found available. Possible
# algorithms: AES ARCTWO BLOWFISH CAST128 DES DES3 SERPENT TWOFISH MD2 MD4
# MD5 SHA1 SHA256.
#
# The argument is used if no --with...-nettle option is set. Value "yes"
# requires the configuration by default. Value "no" does not require it by
# default. Value "auto" configures the library only if available.
#
# See also AX_LIB_BEECRYPT, AX_LIB_CRYPTO, and AX_LIB_GCRYPT.
#
# LICENSE
#
# Copyright (c) 2009 Fabien Coelho <autoconf.archive@coelho.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 10
# AX_CHECK_NETTLE_ALGO([name],[function])
AC_DEFUN([AX_CHECK_NETTLE_ALGO],[
AC_CHECK_LIB([nettle], [nettle_$2],
AC_DEFINE([NETTLE_WITH_$1],[1],[Algorithm $1 in nettle library]))
])
# AX_LIB_NETTLE([yes|no|auto])
AC_DEFUN([AX_LIB_NETTLE],[
AC_MSG_CHECKING([whether nettle is enabled])
AC_ARG_WITH([nettle],
AC_HELP_STRING([--with-nettle], [Require nettle library (required with GnuTLS)]),[
AC_MSG_RESULT([$withval])
ax_with_nettle=$withval
],[
AC_MSG_RESULT([$1])
ax_with_nettle=$1
])
if test "$ax_with_nettle" = "yes" -o "$ax_with_nettle" = "auto" ; then
AC_CHECK_HEADERS([nettle/nettle-meta.h],[
AC_CHECK_LIB([nettle],[nettle_base64_encode_final],[
AC_DEFINE([HAVE_NETTLE],[1],[Nettle library is available])
HAVE_NETTLE=1
AC_SUBST([NETTLE_LIBS],[-lnettle])
# ciphers
AX_CHECK_NETTLE_ALGO([AES],[aes_encrypt])
AX_CHECK_NETTLE_ALGO([ARCTWO],[arctwo_encrypt])
AX_CHECK_NETTLE_ALGO([BLOWFISH],[blowfish_encrypt])
AX_CHECK_NETTLE_ALGO([CAST128],[cast128_encrypt])
AX_CHECK_NETTLE_ALGO([DES],[des_encrypt])
AX_CHECK_NETTLE_ALGO([DES3],[des3_encrypt])
AX_CHECK_NETTLE_ALGO([SERPENT],[serpent_encrypt])
AX_CHECK_NETTLE_ALGO([TWOFISH],[twofish_encrypt])
# digests
AX_CHECK_NETTLE_ALGO([MD2],[md2_digest])
AX_CHECK_NETTLE_ALGO([MD4],[md4_digest])
AX_CHECK_NETTLE_ALGO([MD5],[md5_digest])
AX_CHECK_NETTLE_ALGO([SHA1],[sha1_digest])
AX_CHECK_NETTLE_ALGO([SHA256],[sha256_digest])
])
])
# complain only if explicitly required
if test "$ax_with_nettle" = "yes" -a "x$HAVE_NETTLE" = "x" ; then
AC_MSG_ERROR([cannot configure required nettle library])
fi
fi
])

View File

@ -52,11 +52,12 @@ INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
srcdir = @srcdir@ srcdir = @srcdir@
tlsdir = @TLSDIR@
stubbysrcdir = $(srcdir)/../stubby stubbysrcdir = $(srcdir)/../stubby
LIBTOOL = ../libtool LIBTOOL = ../libtool
CC=@CC@ CC=@CC@
CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary -I$(stubbysrcdir)/src @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS) CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary -I$(srcdir)/$(tlsdir) -I$(stubbysrcdir)/src @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS)
WPEDANTICFLAG=@WPEDANTICFLAG@ WPEDANTICFLAG=@WPEDANTICFLAG@
WNOERRORFLAG=@WNOERRORFLAG@ WNOERRORFLAG=@WNOERRORFLAG@
LDFLAGS=@LDFLAGS@ @LIBS@ LDFLAGS=@LDFLAGS@ @LIBS@
@ -78,9 +79,9 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \ GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
list.lo request-internal.lo platform.lo pubkey-pinning.lo rr-dict.lo \ list.lo request-internal.lo platform.lo rr-dict.lo \
rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \ rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \
mdns.lo mdns.lo pubkey-pinning.lo
GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \ GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
str2wire.lo str2wire.lo
@ -91,9 +92,10 @@ LIBOBJDIR=
LIBOBJS=@LIBOBJS@ LIBOBJS=@LIBOBJS@
COMPAT_OBJ=$(LIBOBJS:.o=.lo) COMPAT_OBJ=$(LIBOBJS:.o=.lo)
UTIL_OBJ=rbtree.lo val_secalgo.lo lruhash.lo lookup3.lo locks.lo UTIL_OBJ=rbtree.lo lruhash.lo lookup3.lo locks.lo
JSMN_OBJ=jsmn.lo JSMN_OBJ=jsmn.lo
TLS_OBJ=tls.lo pubkey-pinning-internal.lo keyraw-internal.lo val_secalgo.lo anchor-internal.lo
YXML_OBJ=yxml.lo YXML_OBJ=yxml.lo
YAML_OBJ=convert_yaml_to_json.lo YAML_OBJ=convert_yaml_to_json.lo
@ -133,6 +135,9 @@ $(UTIL_OBJ):
$(JSMN_OBJ): $(JSMN_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@ $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@
$(TLS_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$(tlsdir)/$(@:.lo=.c) -o $@
$(YAML_OBJ): $(YAML_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(stubbysrcdir)/src/yaml/$(@:.lo=.c) -o $@ $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(stubbysrcdir)/src/yaml/$(@:.lo=.c) -o $@
@ -194,8 +199,8 @@ libgetdns_ext_uv.la: libgetdns.la libuv.lo
libgetdns_ext_ev.la: libgetdns.la libev.lo libgetdns_ext_ev.la: libgetdns.la libev.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS) libgetdns.la: $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(TLS_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS)
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(TLS_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
test: default test: default
cd test && $(MAKE) $@ cd test && $(MAKE) $@
@ -271,15 +276,15 @@ Makefile: $(srcdir)/Makefile.in ../config.status
depend: depend:
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new ) (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 ssl_dane/danessl.c extension/*.c ../stubby/src/*.c | \ (blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -I$(tlsdir) -Iyxml -Iutil/auxiliary -I../stubby/src *.c gldns/*.c compat/*.c util/*.c jsmn/*.c $(tlsdir)/*.c yxml/*.c extension/*.c ../stubby/src/*.c | \
sed -e "s? $$blddir/? ?g" \ sed -e "s? $$blddir/? ?g" \
-e 's? gldns/? $$(srcdir)/gldns/?g' \ -e 's? gldns/? $$(srcdir)/gldns/?g' \
-e 's? compat/? $$(srcdir)/compat/?g' \ -e 's? compat/? $$(srcdir)/compat/?g' \
-e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?g' \ -e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?g' \
-e 's? util/? $$(srcdir)/util/?g' \ -e 's? util/? $$(srcdir)/util/?g' \
-e 's? jsmn/? $$(srcdir)/jsmn/?g' \ -e 's? jsmn/? $$(srcdir)/jsmn/?g' \
-e 's? $(tlsdir)/? $$(srcdir)/$$(tlsdir)/?g' \
-e 's? yxml/? $$(srcdir)/yxml/?g' \ -e 's? yxml/? $$(srcdir)/yxml/?g' \
-e 's? ssl_dane/? $$(srcdir)/ssl_dane/?g' \
-e 's? extension/? $$(srcdir)/extension/?g' \ -e 's? extension/? $$(srcdir)/extension/?g' \
-e 's? \.\./stubby/? $$(stubbysrcdir)/?g' \ -e 's? \.\./stubby/? $$(stubbysrcdir)/?g' \
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \ -e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
@ -300,124 +305,102 @@ FORCE:
# Dependencies for gldns, utils, the extensions and compat functions # Dependencies for gldns, utils, the extensions and compat functions
anchor.lo anchor.o: $(srcdir)/anchor.c \ anchor.lo anchor.o: $(srcdir)/anchor.c \
config.h \ config.h $(srcdir)/debug.h \
$(srcdir)/debug.h $(srcdir)/anchor.h \ $(srcdir)/anchor.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \ $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/context.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/dnssec.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/yxml/yxml.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/str2wire.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/yxml/yxml.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h \
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/platform.h
$(srcdir)/gldns/keyraw.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/platform.h
const-info.lo const-info.o: $(srcdir)/const-info.c \ const-info.lo const-info.o: $(srcdir)/const-info.c \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/const-info.h $(srcdir)/const-info.h
context.lo context.o: $(srcdir)/context.c \ context.lo context.o: $(srcdir)/context.c \
config.h \ config.h $(srcdir)/anchor.h \
$(srcdir)/anchor.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/debug.h \ $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/tls.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h $(srcdir)/const-info.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)/ssl_dane/danessl.h
convert.lo convert.o: $(srcdir)/convert.c \ convert.lo convert.o: $(srcdir)/convert.c \
config.h \ config.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h \ $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \ $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \ $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/wire2str.h \ $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \ $(srcdir)/debug.h
$(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h dict.lo dict.o: $(srcdir)/dict.c config.h \
dict.lo dict.o: $(srcdir)/dict.c \
config.h \
$(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/dict.h $(srcdir)/list.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/parseutil.h
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/parseutil.h
dnssec.lo dnssec.o: $(srcdir)/dnssec.c \ dnssec.lo dnssec.o: $(srcdir)/dnssec.c \
config.h \ config.h $(srcdir)/debug.h \
$(srcdir)/debug.h \
getdns/getdns.h \ getdns/getdns.h \
$(srcdir)/context.h \ $(srcdir)/context.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h \ $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h $(srcdir)/gldns/gbuffer.h
$(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h \
$(srcdir)/util/orig-headers/val_secalgo.h
general.lo general.o: $(srcdir)/general.c \ general.lo general.o: $(srcdir)/general.c \
config.h \ config.h $(srcdir)/general.h \
$(srcdir)/general.h \
getdns/getdns.h \ getdns/getdns.h \
$(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h $(srcdir)/mdns.h $(srcdir)/debug.h
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
$(srcdir)/dict.h $(srcdir)/mdns.h $(srcdir)/platform.h
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \ list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h \
config.h \ config.h $(srcdir)/context.h \
$(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/list.h $(srcdir)/dict.h
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ mdns.lo mdns.o: $(srcdir)/mdns.c config.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/list.h $(srcdir)/dict.h
mdns.lo mdns.o: $(srcdir)/mdns.c \
config.h \
$(srcdir)/debug.h $(srcdir)/context.h \ $(srcdir)/debug.h $(srcdir)/context.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/general.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/mdns.h
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h \
$(srcdir)/platform.h $(srcdir)/mdns.h $(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.h \
$(srcdir)/util/orig-headers/lookup3.h
platform.lo platform.o: $(srcdir)/platform.c $(srcdir)/platform.h \ platform.lo platform.o: $(srcdir)/platform.c $(srcdir)/platform.h \
config.h config.h
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \ pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \
config.h \ config.h $(srcdir)/debug.h \
$(srcdir)/debug.h \
getdns/getdns.h \ getdns/getdns.h \
$(srcdir)/context.h \ $(srcdir)/context.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/$(tlsdir)/pubkey-pinning-internal.h
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h
request-internal.lo request-internal.o: $(srcdir)/request-internal.c \ request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
config.h \ config.h \
$(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
@ -425,11 +408,9 @@ request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/debug.h $(srcdir)/convert.h $(srcdir)/general.h
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/dict.h $(srcdir)/convert.h $(srcdir)/general.h
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \ rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
config.h \ config.h \
getdns/getdns.h \ getdns/getdns.h \
@ -437,10 +418,8 @@ rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/dict.h
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h \
$(srcdir)/dict.h
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
config.h \ config.h \
getdns/getdns.h \ getdns/getdns.h \
@ -451,12 +430,10 @@ server.lo server.o: $(srcdir)/server.c \
getdns/getdns.h \ getdns/getdns.h \
$(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/debug.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/util-internal.h $(srcdir)/platform.h
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/platform.h stub.lo stub.o: $(srcdir)/stub.c config.h \
stub.lo stub.o: $(srcdir)/stub.c \
config.h \
$(srcdir)/debug.h $(srcdir)/stub.h \ $(srcdir)/debug.h $(srcdir)/stub.h \
getdns/getdns.h \ getdns/getdns.h \
$(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
@ -464,53 +441,45 @@ stub.lo stub.o: $(srcdir)/stub.c \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ $(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/anchor.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \ $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/anchor.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 \ sync.lo sync.o: $(srcdir)/sync.c \
getdns/getdns.h \ getdns/getdns.h \
config.h \ config.h $(srcdir)/context.h \
$(srcdir)/context.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/general.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \ ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \
config.h \ config.h
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h
util-internal.lo util-internal.o: $(srcdir)/util-internal.c \ util-internal.lo util-internal.o: $(srcdir)/util-internal.c \
config.h \ config.h \
getdns/getdns.h \ getdns/getdns.h $(srcdir)/dict.h \
$(srcdir)/dict.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/types-internal.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \ $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \ $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/str2wire.h \ $(srcdir)/gldns/rrdef.h
$(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \ gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \
config.h \ config.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/gbuffer.h
keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \ keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \
config.h \ config.h \
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/rrdef.h
parse.lo parse.o: $(srcdir)/gldns/parse.c \ parse.lo parse.o: $(srcdir)/gldns/parse.c \
config.h \ config.h $(srcdir)/gldns/parse.h \
$(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h
parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c \ parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c \
config.h \ config.h \
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/parseutil.h
rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c \ rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c \
config.h \ config.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/parseutil.h
str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \ str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \
config.h \ config.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h \
@ -518,7 +487,8 @@ str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \
wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c \ wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c \
config.h \ config.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h \
$(srcdir)/$(tlsdir)/keyraw-internal.h
arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \ arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \
config.h config.h
arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \ arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \
@ -548,8 +518,8 @@ strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \
strptime.lo strptime.o: $(srcdir)/compat/strptime.c \ strptime.lo strptime.o: $(srcdir)/compat/strptime.c \
config.h config.h
locks.lo locks.o: $(srcdir)/util/locks.c \ locks.lo locks.o: $(srcdir)/util/locks.c \
config.h \ config.h $(srcdir)/util/locks.h \
$(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h
lookup3.lo lookup3.o: $(srcdir)/util/lookup3.c \ lookup3.lo lookup3.o: $(srcdir)/util/lookup3.c \
config.h \ config.h \
$(srcdir)/util/auxiliary/util/storage/lookup3.h $(srcdir)/util/lookup3.h \ $(srcdir)/util/auxiliary/util/storage/lookup3.h $(srcdir)/util/lookup3.h \
@ -564,17 +534,41 @@ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \
$(srcdir)/util/auxiliary/log.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h \ $(srcdir)/util/auxiliary/log.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h \
$(srcdir)/util/auxiliary/fptr_wlist.h $(srcdir)/util/auxiliary/util/fptr_wlist.h \ $(srcdir)/util/auxiliary/fptr_wlist.h $(srcdir)/util/auxiliary/util/fptr_wlist.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \ jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
anchor-internal.lo anchor-internal.o: $(srcdir)/$(tlsdir)/anchor-internal.c \
config.h $(srcdir)/anchor.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h
keyraw-internal.lo keyraw-internal.o: $(srcdir)/$(tlsdir)/keyraw-internal.c \
config.h \ config.h \
$(srcdir)/util/auxiliary/util/data/packed_rrset.h \ $(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/rrdef.h
$(srcdir)/util/auxiliary/validator/val_secalgo.h $(srcdir)/util/val_secalgo.h \ pubkey-pinning-internal.lo pubkey-pinning-internal.o: $(srcdir)/$(tlsdir)/pubkey-pinning-internal.c $(srcdir)/context.h \
$(srcdir)/util/orig-headers/val_secalgo.h $(srcdir)/util/auxiliary/validator/val_nsec3.h \ getdns/getdns.h \
getdns/getdns_extra.h \
config.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/pubkey-pinning.h
tls.lo tls.o: $(srcdir)/$(tlsdir)/tls.c \
config.h $(srcdir)/debug.h \
$(srcdir)/context.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/tls.h
val_secalgo.lo val_secalgo.o: $(srcdir)/$(tlsdir)/val_secalgo.c \
config.h \
$(srcdir)/util/auxiliary/util/data/packed_rrset.h $(srcdir)/$(tlsdir)/validator/val_secalgo.h \
$(srcdir)/util/val_secalgo.h $(srcdir)/gldns/gbuffer.h $(srcdir)/$(tlsdir)/validator/val_nsec3.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/auxiliary/sldns/rrdef.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/auxiliary/sldns/rrdef.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \
$(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/util/auxiliary/sldns/sbuffer.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 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 \ libev.lo libev.o: $(srcdir)/extension/libev.c \
config.h \ config.h \
$(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
@ -588,8 +582,8 @@ libevent.lo libevent.o: $(srcdir)/extension/libevent.c \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h
libuv.lo libuv.o: $(srcdir)/extension/libuv.c \ libuv.lo libuv.o: $(srcdir)/extension/libuv.c \
config.h \ config.h $(srcdir)/debug.h \
$(srcdir)/debug.h $(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h
@ -600,13 +594,11 @@ poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/platform.h $(srcdir)/debug.h
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/platform.h
select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \ select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \
config.h \ config.h $(srcdir)/debug.h \
$(srcdir)/debug.h $(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/platform.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/platform.h \

View File

@ -33,9 +33,6 @@
#include "debug.h" #include "debug.h"
#include "anchor.h" #include "anchor.h"
#include <fcntl.h> #include <fcntl.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <strings.h> #include <strings.h>
#include <time.h> #include <time.h>
#include "types-internal.h" #include "types-internal.h"
@ -52,141 +49,6 @@
#include "util-internal.h" #include "util-internal.h"
#include "platform.h" #include "platform.h"
/* get key usage out of its extension, returns 0 if no key_usage extension */
static unsigned long
_getdns_get_usage_of_ex(X509* cert)
{
unsigned long val = 0;
ASN1_BIT_STRING* s;
if((s=X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL))) {
if(s->length > 0) {
val = s->data[0];
if(s->length > 1)
val |= s->data[1] << 8;
}
ASN1_BIT_STRING_free(s);
}
return val;
}
/** get valid signers from the list of signers in the signature */
static STACK_OF(X509)*
_getdns_get_valid_signers(PKCS7* p7, const char* p7signer)
{
int i;
STACK_OF(X509)* validsigners = sk_X509_new_null();
STACK_OF(X509)* signers = PKCS7_get0_signers(p7, NULL, 0);
unsigned long usage = 0;
if(!validsigners) {
DEBUG_ANCHOR("ERROR %s(): Failed to allocated validsigners\n"
, __FUNC__);
sk_X509_free(signers);
return NULL;
}
if(!signers) {
DEBUG_ANCHOR("ERROR %s(): Failed to allocated signers\n"
, __FUNC__);
sk_X509_free(validsigners);
return NULL;
}
for(i=0; i<sk_X509_num(signers); i++) {
char buf[1024];
X509_NAME* nm = X509_get_subject_name(
sk_X509_value(signers, i));
if(!nm) {
DEBUG_ANCHOR("%s(): cert %d has no subject name\n"
, __FUNC__, i);
continue;
}
if(!p7signer || strcmp(p7signer, "")==0) {
/* there is no name to check, return all records */
DEBUG_ANCHOR("%s(): did not check commonName of signer\n"
, __FUNC__);
} else {
if(!X509_NAME_get_text_by_NID(nm,
NID_pkcs9_emailAddress,
buf, (int)sizeof(buf))) {
DEBUG_ANCHOR("%s(): removed cert with no name\n"
, __FUNC__);
continue; /* no name, no use */
}
if(strcmp(buf, p7signer) != 0) {
DEBUG_ANCHOR("%s(): removed cert with wrong name\n"
, __FUNC__);
continue; /* wrong name, skip it */
}
}
/* check that the key usage allows digital signatures
* (the p7s) */
usage = _getdns_get_usage_of_ex(sk_X509_value(signers, i));
if(!(usage & KU_DIGITAL_SIGNATURE)) {
DEBUG_ANCHOR("%s(): removed cert with no key usage "
"Digital Signature allowed\n"
, __FUNC__);
continue;
}
/* we like this cert, add it to our list of valid
* signers certificates */
sk_X509_push(validsigners, sk_X509_value(signers, i));
}
sk_X509_free(signers);
return validsigners;
}
static int
_getdns_verify_p7sig(BIO* data, BIO* p7s, X509_STORE *store, const char* p7signer)
{
PKCS7* p7;
STACK_OF(X509)* validsigners;
int secure = 0;
#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new();
if(!param) {
DEBUG_ANCHOR("ERROR %s(): Failed to allocated param\n"
, __FUNC__);
return 0;
}
/* do the selfcheck on the root certificate; it checks that the
* input is valid */
X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CHECK_SS_SIGNATURE);
X509_STORE_set1_param(store, param);
X509_VERIFY_PARAM_free(param);
#endif
(void)BIO_reset(p7s);
(void)BIO_reset(data);
/* convert p7s to p7 (the signature) */
p7 = d2i_PKCS7_bio(p7s, NULL);
if(!p7) {
DEBUG_ANCHOR("ERROR %s(): could not parse p7s signature file\n"
, __FUNC__);
return 0;
}
/* check what is in the Subject name of the certificates,
* and build a stack that contains only the right certificates */
validsigners = _getdns_get_valid_signers(p7, p7signer);
if(!validsigners) {
PKCS7_free(p7);
return 0;
}
if(PKCS7_verify(p7, validsigners, store, data, NULL, PKCS7_NOINTERN) == 1) {
secure = 1;
}
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
else {
DEBUG_ANCHOR("ERROR %s(): the PKCS7 signature did not verify\n"
, __FUNC__);
ERR_print_errors_cb(_getdns_ERR_print_errors_cb_f, NULL);
}
#endif
sk_X509_free(validsigners);
PKCS7_free(p7);
return secure;
}
typedef struct ta_iter { typedef struct ta_iter {
uint8_t yxml_buf[4096]; uint8_t yxml_buf[4096];
yxml_t x; yxml_t x;
@ -206,6 +68,15 @@ typedef struct ta_iter {
char digest[2048]; char digest[2048];
} ta_iter; } ta_iter;
static void strcpytrunc(char* dst, const char* src, size_t dstsize)
{
size_t to_copy = strlen(src);
if (to_copy >= dstsize)
to_copy = dstsize -1;
memcpy(dst, src, to_copy);
dst[to_copy] = '\0';
}
/** /**
* XML convert DateTime element to time_t. * XML convert DateTime element to time_t.
* [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] * [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
@ -213,7 +84,7 @@ typedef struct ta_iter {
* @param str: the string * @param str: the string
* @return a time_t representation or 0 on failure. * @return a time_t representation or 0 on failure.
*/ */
static time_t time_t
_getdns_xml_convertdate(const char* str) _getdns_xml_convertdate(const char* str)
{ {
time_t t = 0; time_t t = 0;
@ -328,8 +199,8 @@ static ta_iter *ta_iter_next(ta_iter *ta)
else if (level == 0 && cur) { else if (level == 0 && cur) {
/* <Zone> content ready */ /* <Zone> content ready */
(void) strncpy( ta->zone, value strcpytrunc( ta->zone, value
, sizeof(ta->zone)); , sizeof(ta->zone));
/* Reset to start of <TrustAnchor> */ /* Reset to start of <TrustAnchor> */
cur = NULL; cur = NULL;
@ -504,20 +375,20 @@ static ta_iter *ta_iter_next(ta_iter *ta)
DEBUG_ANCHOR("elem end: %s\n", value); DEBUG_ANCHOR("elem end: %s\n", value);
switch (elem_type) { switch (elem_type) {
case KEYTAG: case KEYTAG:
(void) strncpy( ta->keytag, value strcpytrunc( ta->keytag, value
, sizeof(ta->keytag)); , sizeof(ta->keytag));
break; break;
case ALGORITHM: case ALGORITHM:
(void) strncpy( ta->algorithm, value strcpytrunc( ta->algorithm, value
, sizeof(ta->algorithm)); , sizeof(ta->algorithm));
break; break;
case DIGESTTYPE: case DIGESTTYPE:
(void) strncpy( ta->digesttype, value strcpytrunc( ta->digesttype, value
, sizeof(ta->digesttype)); , sizeof(ta->digesttype));
break; break;
case DIGEST: case DIGEST:
(void) strncpy( ta->digest, value strcpytrunc( ta->digest, value
, sizeof(ta->digest)); , sizeof(ta->digest));
break; break;
} }
break; break;
@ -558,7 +429,7 @@ static ta_iter *ta_iter_init(ta_iter *ta, const char *doc, size_t doc_len)
return ta_iter_next(ta); return ta_iter_next(ta);
} }
static uint16_t _getdns_parse_xml_trust_anchors_buf( uint16_t _getdns_parse_xml_trust_anchors_buf(
gldns_buffer *gbuf, uint64_t *now_ms, char *xml_data, size_t xml_len) gldns_buffer *gbuf, uint64_t *now_ms, char *xml_data, size_t xml_len)
{ {
ta_iter ta_spc, *ta; ta_iter ta_spc, *ta;
@ -647,226 +518,6 @@ static uint16_t _getdns_parse_xml_trust_anchors_buf(
return ta_count; return ta_count;
} }
static uint8_t *tas_validate(struct mem_funcs *mf,
const getdns_bindata *xml_bd, const getdns_bindata *p7s_bd,
const getdns_bindata *crt_bd, const char *p7signer,
uint64_t *now_ms, uint8_t *tas, size_t *tas_len)
{
BIO *xml = NULL, *p7s = NULL, *crt = NULL;
X509 *x = NULL;
X509_STORE *store = NULL;
uint8_t *success = NULL;
if (!(xml = BIO_new_mem_buf(xml_bd->data, xml_bd->size)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating xml BIO\n"
, __FUNC__);
else if (!(p7s = BIO_new_mem_buf(p7s_bd->data, p7s_bd->size)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating p7s BIO\n"
, __FUNC__);
else if (!(crt = BIO_new_mem_buf(crt_bd->data, crt_bd->size)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating crt BIO\n"
, __FUNC__);
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
DEBUG_ANCHOR("ERROR %s(): Parsing builtin certificate\n"
, __FUNC__);
else if (!(store = X509_STORE_new()))
DEBUG_ANCHOR("ERROR %s(): Failed allocating store\n"
, __FUNC__);
else if (!X509_STORE_add_cert(store, x))
DEBUG_ANCHOR("ERROR %s(): Adding certificate to store\n"
, __FUNC__);
else if (_getdns_verify_p7sig(xml, p7s, store, p7signer)) {
gldns_buffer gbuf;
gldns_buffer_init_vfixed_frm_data(&gbuf, tas, *tas_len);
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms,
(char *)xml_bd->data, xml_bd->size))
DEBUG_ANCHOR("Failed to parse trust anchor XML data");
else if (gldns_buffer_position(&gbuf) > *tas_len) {
*tas_len = gldns_buffer_position(&gbuf);
if ((success = GETDNS_XMALLOC(*mf, uint8_t, *tas_len))) {
gldns_buffer_init_frm_data(&gbuf, success, *tas_len);
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf,
now_ms, (char *)xml_bd->data, xml_bd->size)) {
DEBUG_ANCHOR("Failed to re-parse trust"
" anchor XML data\n");
GETDNS_FREE(*mf, success);
success = NULL;
}
} else
DEBUG_ANCHOR("Cannot allocate space for "
"trust anchors\n");
} else {
success = tas;
*tas_len = gldns_buffer_position(&gbuf);
}
} else {
DEBUG_ANCHOR("Verifying trust-anchors failed!\n");
}
if (store) X509_STORE_free(store);
if (x) X509_free(x);
if (crt) BIO_free(crt);
if (xml) BIO_free(xml);
if (p7s) BIO_free(p7s);
return success;
}
void _getdns_context_equip_with_anchor(
getdns_context *context, uint64_t *now_ms)
{
uint8_t xml_spc[4096], *xml_data = NULL;
uint8_t p7s_spc[4096], *p7s_data = NULL;
size_t xml_len, p7s_len;
const char *verify_email = NULL;
const char *verify_CA = NULL;
getdns_return_t r;
BIO *xml = NULL, *p7s = NULL, *crt = NULL;
X509 *x = NULL;
X509_STORE *store = NULL;
if ((r = getdns_context_get_trust_anchors_verify_CA(
context, &verify_CA)))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Cannot get trust anchor verify CA: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
else if (!verify_CA || !*verify_CA)
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "Trust anchor verification explicitly "
"disabled by empty verify CA\n");
else if ((r = getdns_context_get_trust_anchors_verify_email(
context, &verify_email)))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Cannot get trust anchor verify email address: "
"\"%s\"\n", getdns_get_errorstr_by_id(r));
else if (!verify_email || !*verify_email)
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "Trust anchor verification explicitly "
"disabled by empty verify email\n");
else if (!(xml_data = _getdns_context_get_priv_file(context,
"root-anchors.xml", xml_spc, sizeof(xml_spc), &xml_len)))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_DEBUG
, "root-anchors.xml not present\n");
else if (!(p7s_data = _getdns_context_get_priv_file(context,
"root-anchors.p7s", p7s_spc, sizeof(p7s_spc), &p7s_len)))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_INFO
, "root-anchors.xml not present\n");
else if (!(xml = BIO_new_mem_buf(xml_data, xml_len)))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed allocating xml BIO\n");
else if (!(p7s = BIO_new_mem_buf(p7s_data, p7s_len)))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed allocating p7s BIO\n");
else if (!(crt = BIO_new_mem_buf((void *)verify_CA, -1)))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed allocating crt BIO\n");
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Cannot parse builtin certificate\n");
else if (!(store = X509_STORE_new()))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed allocating X509 store\n");
else if (!X509_STORE_add_cert(store, x))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Cannot add certificate to X509 store\n");
else if (_getdns_verify_p7sig(xml, p7s, store, verify_email)) {
uint8_t ta_spc[sizeof(context->trust_anchors_spc)];
size_t ta_len;
uint8_t *ta = NULL;
gldns_buffer gbuf;
gldns_buffer_init_vfixed_frm_data(
&gbuf, ta_spc, sizeof(ta_spc));
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms,
(char *)xml_data, xml_len))
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Failed to parse trust anchor XML data\n");
else if ((ta_len = gldns_buffer_position(&gbuf)) > sizeof(ta_spc)) {
if ((ta = GETDNS_XMALLOC(context->mf, uint8_t, ta_len))) {
gldns_buffer_init_frm_data(&gbuf, ta,
gldns_buffer_position(&gbuf));
if (!_getdns_parse_xml_trust_anchors_buf(
&gbuf, now_ms, (char *)xml_data, xml_len)) {
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR
, GETDNS_LOG_ERR
, "Error re-parsing trust "
"anchor XML data\n");
GETDNS_FREE(context->mf, ta);
} else {
context->trust_anchors = ta;
context->trust_anchors_len = ta_len;
context->trust_anchors_source = GETDNS_TASRC_XML;
_getdns_ta_notify_dnsreqs(context);
}
} else
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR
, GETDNS_LOG_ERR
, "Cannot allocate space for "
"XML file");
} else {
(void)memcpy(context->trust_anchors_spc, ta_spc, ta_len);
context->trust_anchors = context->trust_anchors_spc;
context->trust_anchors_len = ta_len;
context->trust_anchors_source = GETDNS_TASRC_XML;
_getdns_ta_notify_dnsreqs(context);
}
DEBUG_ANCHOR("ta: %p, ta_len: %d\n",
(void *)context->trust_anchors, (int)context->trust_anchors_len);
} else {
_getdns_log( &context->log
, GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_ERR
, "Verifying trust-anchors XML failed!\n");
}
if (store) X509_STORE_free(store);
if (x) X509_free(x);
if (crt) BIO_free(crt);
if (xml) BIO_free(xml);
if (p7s) BIO_free(p7s);
if (xml_data && xml_data != xml_spc)
GETDNS_FREE(context->mf, xml_data);
if (p7s_data && p7s_data != p7s_spc)
GETDNS_FREE(context->mf, p7s_data);
}
static const char tas_write_p7s_buf[] = static const char tas_write_p7s_buf[] =
"GET %s HTTP/1.1\r\n" "GET %s HTTP/1.1\r\n"
"Host: %s\r\n" "Host: %s\r\n"
@ -1067,7 +718,7 @@ static void tas_doc_read(getdns_context *context, tas_connection *a)
, "Cannot get trust anchor verify email: " , "Cannot get trust anchor verify email: "
"\"%s\"\n", getdns_get_errorstr_by_id(r)); "\"%s\"\n", getdns_get_errorstr_by_id(r));
else if (!(tas = tas_validate(&context->mf, &a->xml, &p7s_bd, else if (!(tas = _getdns_tas_validate(&context->mf, &a->xml, &p7s_bd,
&verify_CA, verify_email, &now_ms, tas, &tas_len))) &verify_CA, verify_email, &now_ms, tas, &tas_len)))
; /* pass */ ; /* pass */

View File

@ -39,6 +39,29 @@
#include <time.h> #include <time.h>
#include "rr-iter.h" #include "rr-iter.h"
#include "types-internal.h"
/**
** Internal functions, implemented in anchor-internal.c.
**/
void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms);
uint8_t *_getdns_tas_validate(struct mem_funcs *mf,
const getdns_bindata *xml_bd, const getdns_bindata *p7s_bd,
const getdns_bindata *crt_bd, const char *p7signer,
uint64_t *now_ms, uint8_t *tas, size_t *tas_len);
/**
** anchor.c functions used by anchor-internal.c.
**/
time_t _getdns_xml_convertdate(const char* str);
uint16_t _getdns_parse_xml_trust_anchors_buf(gldns_buffer *gbuf, uint64_t *now_ms, char *xml_data, size_t xml_len);
/**
** Public interface.
**/
void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms); void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms);
void _getdns_start_fetching_ta( void _getdns_start_fetching_ta(

View File

@ -171,6 +171,9 @@ _rs_init(u_char *buf, size_t n)
if(!rsx) if(!rsx)
abort(); abort();
#endif #endif
/* Pleast older clang scan-build */
if (!buf)
buf = rsx->rs_buf;
} }
chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0); chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);

View File

@ -47,20 +47,12 @@
#include <iphlpapi.h> #include <iphlpapi.h>
typedef unsigned short in_port_t; typedef unsigned short in_port_t;
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#include <wincrypt.h> #include <wincrypt.h>
#include <shlobj.h> #include <shlobj.h>
#endif #endif
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -90,10 +82,8 @@ typedef unsigned short in_port_t;
#include "list.h" #include "list.h"
#include "dict.h" #include "dict.h"
#include "pubkey-pinning.h" #include "pubkey-pinning.h"
#ifdef USE_DANESSL
# include "ssl_dane/danessl.h"
#endif
#include "const-info.h" #include "const-info.h"
#include "tls.h"
#define GETDNS_PORT_ZERO 0 #define GETDNS_PORT_ZERO 0
#define GETDNS_PORT_DNS 53 #define GETDNS_PORT_DNS 53
@ -182,124 +172,6 @@ _getdns_strdup2(const struct mem_funcs *mfs, const getdns_bindata *s)
} }
} }
#ifdef USE_WINSOCK
/* For windows, the CA trust store is not read by openssl.
Add code to open the trust store using wincrypt API and add
the root certs into openssl trust store */
static int
add_WIN_cacerts_to_openssl_store(getdns_context *ctxt, SSL_CTX* tls_ctx)
{
HCERTSTORE hSystemStore;
PCCERT_CONTEXT pTargetCert = NULL;
_getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_DEBUG
, "%s: %s\n", STUB_DEBUG_SETUP_TLS,
, "Adding Windows certificates from system root store to CA store")
;
/* load just once per context lifetime for this version of getdns
TODO: dynamically update CA trust changes as they are available */
assert(tls_ctx);
/* Call wincrypt's CertOpenStore to open the CA root store. */
if ((hSystemStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
0,
/* NOTE: mingw does not have this const: replace with 1 << 16 from code
CERT_SYSTEM_STORE_CURRENT_USER, */
1 << 16,
L"root")) == 0)
{
_getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "Could not CertOpenStore()");
return 0;
}
X509_STORE* store = SSL_CTX_get_cert_store(tls_ctx);
if (!store) {
_getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "Could not SSL_CTX_get_cert_store()");
return 0;
}
/* failure if the CA store is empty or the call fails */
if ((pTargetCert = CertEnumCertificatesInStore(
hSystemStore, pTargetCert)) == 0) {
_getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_NOTICE
, "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "CA certificate store for Windows is empty.");
return 0;
}
/* iterate over the windows cert store and add to openssl store */
do
{
X509 *cert1 = d2i_X509(NULL,
(const unsigned char **)&pTargetCert->pbCertEncoded,
pTargetCert->cbCertEncoded);
if (!cert1) {
/* return error if a cert fails */
_getdns_log(&ctxt->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR,
, "%s: %s %d:%s\n"
, STUB_DEBUG_SETUP_TLS
, "Unable to parse certificate in memory"
, ERR_get_error()
, ERR_error_string(ERR_get_error(), NULL));
return 0;
}
else {
/* return error if a cert add to store fails */
if (X509_STORE_add_cert(store, cert1) == 0) {
unsigned long error = ERR_peek_last_error();
/* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
* certificate is already in the store. */
if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
_getdns_log(&ctxt->log
, GETDNS_LOG_SYS_STUB
, GETDNS_LOG_ERR
, "%s: %s %d:%s\n"
, STUB_DEBUG_SETUP_TLS
, "Error adding certificate"
, ERR_get_error()
, ERR_error_string( ERR_get_error()
, NULL)
);
X509_free(cert1);
return 0;
}
}
X509_free(cert1);
}
} while ((pTargetCert = CertEnumCertificatesInStore(
hSystemStore, pTargetCert)) != 0);
/* Clean up memory and quit. */
if (pTargetCert)
CertFreeCertificateContext(pTargetCert);
if (hSystemStore)
{
if (!CertCloseStore(hSystemStore, 0)) {
_getdns_log(&ctxt->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "Could not CertCloseStore()");
return 0;
}
}
_getdns_log(&ctxt->log, GETDNS_LOG_SYS_STUB, GETDNS_LOG_INFO
, "%s: %s\n", STUB_DEBUG_SETUP_TLS
, "Completed adding Windows certificates to CA store successfully")
;
return 1;
}
#endif
static uint8_t* static uint8_t*
upstream_addr(getdns_upstream *upstream) upstream_addr(getdns_upstream *upstream)
{ {
@ -762,14 +634,11 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
} }
} }
if (upstream->tls_session != NULL) if (upstream->tls_session != NULL)
SSL_SESSION_free(upstream->tls_session); _getdns_tls_session_free(&upstreams->mf, upstream->tls_session);
if (upstream->tls_obj != NULL) { if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj); _getdns_tls_connection_shutdown(upstream->tls_obj);
#ifdef USE_DANESSL _getdns_tls_connection_free(&upstreams->mf, upstream->tls_obj);
DANESSL_cleanup(upstream->tls_obj);
#endif
SSL_free(upstream->tls_obj);
} }
if (upstream->fd != -1) if (upstream->fd != -1)
{ {
@ -867,11 +736,8 @@ _getdns_upstream_reset(getdns_upstream *upstream)
upstream->loop, &upstream->event); upstream->loop, &upstream->event);
} }
if (upstream->tls_obj != NULL) { if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj); _getdns_tls_connection_shutdown(upstream->tls_obj);
#ifdef USE_DANESSL _getdns_tls_connection_free(&upstream->upstreams->mf, upstream->tls_obj);
DANESSL_cleanup(upstream->tls_obj);
#endif
SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL; upstream->tls_obj = NULL;
} }
if (upstream->fd != -1) { if (upstream->fd != -1) {
@ -1468,17 +1334,6 @@ static char const * const _getdns_default_trust_anchors_verify_CA =
static char const * const _getdns_default_trust_anchors_verify_email = static char const * const _getdns_default_trust_anchors_verify_email =
"dnssec@iana.org"; "dnssec@iana.org";
static char const * const _getdns_default_tls_cipher_list =
#ifndef HAVE_SSL_CTX_SET_CIPHERSUITES
"TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:"
"TLS13-CHACHA20-POLY1305-SHA256:"
#endif
"EECDH+AESGCM:EECDH+CHACHA20";
static char const * const _getdns_default_tls_ciphersuites =
"TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256";
/* /*
* getdns_context_create * getdns_context_create
* *
@ -1692,18 +1547,7 @@ getdns_context_create_with_extended_memory_functions(
#endif #endif
/* Only initialise SSL once and ideally in a thread-safe manner */ /* Only initialise SSL once and ideally in a thread-safe manner */
if (ssl_init == false) { if (ssl_init == false) {
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) _getdns_tls_init();
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
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
(void)OPENSSL_init_ssl(0, NULL);
#endif
ssl_init = true; ssl_init = true;
} }
#ifdef HAVE_PTHREAD #ifdef HAVE_PTHREAD
@ -1829,7 +1673,7 @@ getdns_context_destroy(struct getdns_context *context)
GETDNS_FREE(context->my_mf, context->dns_transports); GETDNS_FREE(context->my_mf, context->dns_transports);
if (context->tls_ctx) if (context->tls_ctx)
SSL_CTX_free(context->tls_ctx); _getdns_tls_context_free(&context->my_mf, context->tls_ctx);
getdns_list_destroy(context->dns_root_servers); getdns_list_destroy(context->dns_root_servers);
@ -3718,8 +3562,6 @@ getdns_return_t
_getdns_context_prepare_for_resolution(getdns_context *context) _getdns_context_prepare_for_resolution(getdns_context *context)
{ {
getdns_return_t r; getdns_return_t r;
char ssl_err[256];
int osr;
assert(context); assert(context);
if (context->destroying) if (context->destroying)
@ -3741,256 +3583,63 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
} }
if (context->tls_ctx == NULL) { if (context->tls_ctx == NULL) {
#ifdef HAVE_TLS_v1_2 context->tls_ctx = _getdns_tls_context_new(&context->my_mf, &context->log);
/* Create client context, use TLS v1.2 only for now */ if (context->tls_ctx == NULL)
# ifdef HAVE_TLS_CLIENT_METHOD
context->tls_ctx = SSL_CTX_new(TLS_client_method());
# else
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
# endif
if(context->tls_ctx == NULL) {
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error creating TLS context"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
# if defined(HAVE_DECL_SSL_SET_MIN_PROTO_VERSION) \ r = _getdns_tls_context_set_min_max_tls_version(context->tls_ctx, context->tls_min_version, context->tls_max_version);
&& HAVE_DECL_SSL_SET_MIN_PROTO_VERSION if (r) {
if (!SSL_CTX_set_min_proto_version(context->tls_ctx, _getdns_tls_context_free(&context->my_mf, context->tls_ctx);
_getdns_tls_version2openssl_version(
context->tls_min_version))) {
SSL_CTX_free(context->tls_ctx);
context->tls_ctx = NULL; context->tls_ctx = NULL;
ERR_error_string_n( ERR_get_error() return r;
, ssl_err, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"minimum TLS version"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
} }
if (context->tls_max_version
&& !SSL_CTX_set_max_proto_version(context->tls_ctx, /* Be strict and only use the cipher suites recommended in RFC7525
_getdns_tls_version2openssl_version( Unless we later fallback to opportunistic. */
context->tls_max_version))) { r = _getdns_tls_context_set_cipher_list(context->tls_ctx, context->tls_cipher_list);
SSL_CTX_free(context->tls_ctx); if (!r)
r = _getdns_tls_context_set_cipher_suites(context->tls_ctx, context->tls_ciphersuites);
if (!r && context->tls_curves_list)
r = _getdns_tls_context_set_curves_list(context->tls_ctx, context->tls_curves_list);
if (r) {
_getdns_tls_context_free(&context->my_mf, context->tls_ctx);
context->tls_ctx = NULL; context->tls_ctx = NULL;
ERR_error_string_n( ERR_get_error() return r;
, ssl_err, sizeof(ssl_err)); }
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"maximum TLS version"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT; /* For strict authentication, we must have local root certs available
} Set up is done only when the tls_ctx is created (per getdns_context)*/
# else if (_getdns_tls_context_set_ca(context->tls_ctx, context->tls_ca_file, context->tls_ca_path)) {
# ifndef HAVE_TLS_CLIENT_METHOD if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) {
if (( context->tls_min_version
&& context->tls_min_version != GETDNS_TLS1_2)
|| context->tls_max_version) {
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support setting of mimum or maximum "
"TLS versions");
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
# endif
# endif
/* Be strict and only use the cipher suites recommended
* in RFC7525 Unless we later fallback to opportunistic.
*/
if (!SSL_CTX_set_cipher_list(context->tls_ctx,
context->tls_cipher_list
? context->tls_cipher_list
: _getdns_default_tls_cipher_list)) {
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"cipher list"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
# ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
if (!SSL_CTX_set_ciphersuites(context->tls_ctx,
context->tls_ciphersuites
? context->tls_ciphersuites
: _getdns_default_tls_ciphersuites)) {
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"cipher suites"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
# else
if (context->tls_ciphersuites) {
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support configuring cipher suites");
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
# endif
# 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)) {
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS context with "
"curves list"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
# else
if (context->tls_curves_list) {
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support configuring curves list");
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
# endif
/* For strict authentication, we must have local root
* certs available. Set up is done only when the tls_ctx
* is created (per getdns_context)
*/
osr = 0;
if (context->tls_ca_file || context->tls_ca_path) {
osr = SSL_CTX_load_verify_locations(
context->tls_ctx
, context->tls_ca_file
, context->tls_ca_path );
if (!osr) {
ERR_error_string_n( ERR_get_error()
, ssl_err
, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB
, GETDNS_LOG_WARNING
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Could not load verify locations"
, ssl_err);
} else {
_getdns_log(&context->log _getdns_log(&context->log
, GETDNS_LOG_SYS_STUB , GETDNS_LOG_SYS_STUB
, GETDNS_LOG_DEBUG , GETDNS_LOG_DEBUG
, "%s: %s\n" , "%s: %s\n"
, STUB_DEBUG_SETUP_TLS , STUB_DEBUG_SETUP_TLS
, "Verify locations loaded"); , "Authentication is needed but no "
"verify location could be loaded");
_getdns_tls_context_free(&context->my_mf, context->tls_ctx);
context->tls_ctx = NULL;
return GETDNS_RETURN_BAD_CONTEXT;
} }
} }
if (osr) _getdns_tls_context_pinset_init(context->tls_ctx);
; /* verify locations loaded: pass */
# ifndef USE_WINSOCK
else if (!SSL_CTX_set_default_verify_paths(
context->tls_ctx) &&
# else
else if (!add_WIN_cacerts_to_openssl_store(
context, context->tls_ctx) &&
# endif /* USE_WINSOCK */
context->tls_auth_min
== GETDNS_AUTHENTICATION_REQUIRED) {
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB
, GETDNS_LOG_ERR
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Authentication is needed but no default "
"verify location could be loaded"
, ssl_err);
return GETDNS_RETURN_BAD_CONTEXT;
}
# if defined(HAVE_SSL_CTX_DANE_ENABLE)
if (!SSL_CTX_dane_enable(context->tls_ctx)) {
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_WARNING
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Could not enable DANE on TLX context"
, ssl_err);
}
# elif defined(USE_DANESSL)
if (!DANESSL_CTX_init(context->tls_ctx)) {
ERR_error_string_n( ERR_get_error()
, ssl_err, sizeof(ssl_err));
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_WARNING
, "%s: %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Could not enable DANE on TLX context"
, ssl_err);
}
# endif
#else /* HAVE_TLS_v1_2 */
if (tls_only_is_in_transports_list(context) == 1) {
_getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n"
, STUB_DEBUG_SETUP_TLS
, "This version of OpenSSL does not "
"support authenticated TLS");
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
/* A null tls_ctx will make TLS fail and fallback to
* the other transports will kick-in.
*/
#endif /* HAVE_TLS_v1_2 */
} }
} }
/* Block use of TLS ONLY in recursive mode as it won't work */ /* Block use of TLS ONLY in recursive mode as it won't work */
/* Note: If TLS is used in recursive mode this will try TLS on port /* Note: If TLS is used in recursive mode this will try TLS on port
* 53 so it is blocked here. */ * 53 so it is blocked here. */
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING if (context->resolution_type == GETDNS_RESOLUTION_RECURSING &&
&& tls_only_is_in_transports_list(context) == 1) { tls_only_is_in_transports_list(context) == 1) {
_getdns_log(&context->log _getdns_log(&context->log
, GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR , GETDNS_LOG_SYS_STUB, GETDNS_LOG_ERR
, "%s: %s\n" , "%s: %s\n"
, STUB_DEBUG_SETUP_TLS , STUB_DEBUG_SETUP_TLS
, "TLS only transport is not supported for the recursing " , "TLS only transport is not supported for the recursing "
"resolution type"); "resolution type");
_getdns_tls_context_free(&context->my_mf, context->tls_ctx);
context->tls_ctx = NULL;
return GETDNS_RETURN_NOT_IMPLEMENTED; return GETDNS_RETURN_NOT_IMPLEMENTED;
} }
if (context->resolution_type_set == context->resolution_type) if (context->resolution_type_set == context->resolution_type)
@ -4397,32 +4046,7 @@ getdns_context_get_api_information(const getdns_context* context)
&& ! getdns_dict_util_set_string( && ! getdns_dict_util_set_string(
result, "default_hosts_location", GETDNS_FN_HOSTS) result, "default_hosts_location", GETDNS_FN_HOSTS)
&& ! getdns_dict_set_int( && ! _getdns_tls_get_api_information(result)
result, "openssl_build_version_number", OPENSSL_VERSION_NUMBER)
#ifdef HAVE_OPENSSL_VERSION_NUM
&& ! getdns_dict_set_int(
result, "openssl_version_number", OpenSSL_version_num())
#endif
#ifdef HAVE_OPENSSL_VERSION
&& ! getdns_dict_util_set_string(
result, "openssl_version_string", OpenSSL_version(OPENSSL_VERSION))
&& ! getdns_dict_util_set_string(
result, "openssl_cflags", OpenSSL_version(OPENSSL_CFLAGS))
&& ! getdns_dict_util_set_string(
result, "openssl_built_on", OpenSSL_version(OPENSSL_BUILT_ON))
&& ! getdns_dict_util_set_string(
result, "openssl_platform", OpenSSL_version(OPENSSL_PLATFORM))
&& ! getdns_dict_util_set_string(
result, "openssl_dir", OpenSSL_version(OPENSSL_DIR))
&& ! getdns_dict_util_set_string(
result, "openssl_engines_dir", OpenSSL_version(OPENSSL_ENGINES_DIR))
#endif
&& ! getdns_dict_set_int( && ! getdns_dict_set_int(
result, "resolution_type", context->resolution_type) result, "resolution_type", context->resolution_type)
@ -5658,7 +5282,7 @@ getdns_context_get_tls_cipher_list(
*tls_cipher_list = context->tls_cipher_list *tls_cipher_list = context->tls_cipher_list
? context->tls_cipher_list ? context->tls_cipher_list
: _getdns_default_tls_cipher_list; : _getdns_tls_context_get_default_cipher_list();
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -5687,7 +5311,7 @@ getdns_context_get_tls_ciphersuites(
*tls_ciphersuites = context->tls_ciphersuites *tls_ciphersuites = context->tls_ciphersuites
? context->tls_ciphersuites ? context->tls_ciphersuites
: _getdns_default_tls_ciphersuites; : _getdns_tls_context_get_default_cipher_suites();
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -5697,7 +5321,7 @@ getdns_context_set_tls_curves_list(
{ {
if (!context) if (!context)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
#if defined(HAVE_DECL_SSL_CTX_SET1_CURVES_LIST) && HAVE_DECL_SSL_CTX_SET1_CURVES_LIST #if HAVE_TLS_CTX_CURVES_LIST
if (context->tls_curves_list) if (context->tls_curves_list)
GETDNS_FREE(context->mf, context->tls_curves_list); GETDNS_FREE(context->mf, context->tls_curves_list);
context->tls_curves_list = tls_curves_list context->tls_curves_list = tls_curves_list

View File

@ -50,6 +50,7 @@
#endif #endif
#include "rr-iter.h" #include "rr-iter.h"
#include "anchor.h" #include "anchor.h"
#include "tls.h"
struct getdns_dns_req; struct getdns_dns_req;
struct ub_ctx; struct ub_ctx;
@ -200,9 +201,9 @@ typedef struct getdns_upstream {
getdns_network_req *write_queue_last; getdns_network_req *write_queue_last;
_getdns_rbtree_t netreq_by_query_id; _getdns_rbtree_t netreq_by_query_id;
/* TLS specific connection handling */ /* TLS specific connection handling*/
SSL* tls_obj; _getdns_tls_connection* tls_obj;
SSL_SESSION* tls_session; _getdns_tls_session* tls_session;
getdns_tls_hs_state_t tls_hs_state; getdns_tls_hs_state_t tls_hs_state;
getdns_auth_state_t tls_auth_state; getdns_auth_state_t tls_auth_state;
unsigned tls_fallback_ok : 1; unsigned tls_fallback_ok : 1;
@ -382,7 +383,7 @@ struct getdns_context {
int edns_maximum_udp_payload_size; /* -1 is unset */ int edns_maximum_udp_payload_size; /* -1 is unset */
uint8_t edns_client_subnet_private; uint8_t edns_client_subnet_private;
uint16_t tls_query_padding_blocksize; uint16_t tls_query_padding_blocksize;
SSL_CTX* tls_ctx; _getdns_tls_context* tls_ctx;
getdns_update_callback update_callback; getdns_update_callback update_callback;
getdns_update_callback2 update_callback2; getdns_update_callback2 update_callback2;

View File

@ -194,7 +194,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <ctype.h> #include <ctype.h>
#include <openssl/sha.h>
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "context.h" #include "context.h"
#include "util-internal.h" #include "util-internal.h"
@ -210,6 +209,7 @@
#include "list.h" #include "list.h"
#include "util/val_secalgo.h" #include "util/val_secalgo.h"
#include "anchor.h" #include "anchor.h"
#include "tls.h"
#define SIGNATURE_VERIFIED 0x10000 #define SIGNATURE_VERIFIED 0x10000
#define NSEC3_ITERATION_COUNT_HIGH 0x20000 #define NSEC3_ITERATION_COUNT_HIGH 0x20000
@ -1584,12 +1584,12 @@ static uint8_t *_getdns_nsec3_hash_label(uint8_t *label, size_t label_len,
(void)memcpy(dst, salt + 1, *salt); (void)memcpy(dst, salt + 1, *salt);
dst += *salt; dst += *salt;
(void)SHA1(buf, dst - buf, md); _getdns_tls_sha1(buf, dst - buf, md);
if (iterations) { if (iterations) {
(void)memcpy(buf + SHA_DIGEST_LENGTH, salt + 1, *salt); (void)memcpy(buf + SHA_DIGEST_LENGTH, salt + 1, *salt);
while (iterations--) { while (iterations--) {
(void)memcpy(buf, md, SHA_DIGEST_LENGTH); (void)memcpy(buf, md, SHA_DIGEST_LENGTH);
SHA1(buf, SHA_DIGEST_LENGTH + *salt, md); _getdns_tls_sha1(buf, SHA_DIGEST_LENGTH + *salt, md);
} }
} }
*label = gldns_b32_ntop_extended_hex( *label = gldns_b32_ntop_extended_hex(

View File

@ -251,10 +251,18 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
#ifdef HAVE_UNBOUND_EVENT_API #ifdef HAVE_UNBOUND_EVENT_API
#if UNBOUND_VERSION_MAJOR > 1 || (UNBOUND_VERSION_MAJOR == 1 && UNBOUND_VERSION_MINOR >= 8)
static void
ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len,
int sec, char* why_bogus, int was_ratelimited)
{
(void) was_ratelimited;
#else
static void static void
ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len, ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len,
int sec, char* why_bogus) int sec, char* why_bogus)
{ {
#endif
getdns_network_req *netreq = (getdns_network_req *) arg; getdns_network_req *netreq = (getdns_network_req *) arg;
getdns_dns_req *dns_req = netreq->owner; getdns_dns_req *dns_req = netreq->owner;

View File

@ -14,29 +14,6 @@
#include "gldns/keyraw.h" #include "gldns/keyraw.h"
#include "gldns/rrdef.h" #include "gldns/rrdef.h"
#ifdef HAVE_SSL
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#ifdef HAVE_OPENSSL_CONF_H
# include <openssl/conf.h>
#endif
#ifdef HAVE_OPENSSL_ENGINE_H
# include <openssl/engine.h>
#endif
#ifdef HAVE_OPENSSL_BN_H
#include <openssl/bn.h>
#endif
#ifdef HAVE_OPENSSL_RSA_H
#include <openssl/rsa.h>
#endif
#ifdef HAVE_OPENSSL_DSA_H
#include <openssl/dsa.h>
#endif
#endif /* HAVE_SSL */
size_t size_t
gldns_rr_dnskey_key_size_raw(const unsigned char* keydata, gldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
const size_t len, int alg) const size_t len, int alg)
@ -129,344 +106,3 @@ uint16_t gldns_calc_keytag_raw(const uint8_t* key, size_t keysize)
return (uint16_t) (ac32 & 0xFFFF); return (uint16_t) (ac32 & 0xFFFF);
} }
} }
#ifdef HAVE_SSL
#ifdef USE_GOST
/** store GOST engine reference loaded into OpenSSL library */
#ifdef OPENSSL_NO_ENGINE
int
gldns_key_EVP_load_gost_id(void)
{
return 0;
}
void gldns_key_EVP_unload_gost(void)
{
}
#else
ENGINE* gldns_gost_engine = NULL;
int
gldns_key_EVP_load_gost_id(void)
{
static int gost_id = 0;
const EVP_PKEY_ASN1_METHOD* meth;
ENGINE* e;
if(gost_id) return gost_id;
/* see if configuration loaded gost implementation from other engine*/
meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
if(meth) {
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
return gost_id;
}
/* see if engine can be loaded already */
e = ENGINE_by_id("gost");
if(!e) {
/* load it ourself, in case statically linked */
ENGINE_load_builtin_engines();
ENGINE_load_dynamic();
e = ENGINE_by_id("gost");
}
if(!e) {
/* no gost engine in openssl */
return 0;
}
if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
ENGINE_finish(e);
ENGINE_free(e);
return 0;
}
meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
if(!meth) {
/* algo not found */
ENGINE_finish(e);
ENGINE_free(e);
return 0;
}
/* Note: do not ENGINE_finish and ENGINE_free the acquired engine
* on some platforms this frees up the meth and unloads gost stuff */
gldns_gost_engine = e;
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
return gost_id;
}
void gldns_key_EVP_unload_gost(void)
{
if(gldns_gost_engine) {
ENGINE_finish(gldns_gost_engine);
ENGINE_free(gldns_gost_engine);
gldns_gost_engine = NULL;
}
}
#endif /* ifndef OPENSSL_NO_ENGINE */
#endif /* USE_GOST */
DSA *
gldns_key_buf2dsa_raw(unsigned char* key, size_t len)
{
uint8_t T;
uint16_t length;
uint16_t offset;
DSA *dsa;
BIGNUM *Q; BIGNUM *P;
BIGNUM *G; BIGNUM *Y;
if(len == 0)
return NULL;
T = (uint8_t)key[0];
length = (64 + T * 8);
offset = 1;
if (T > 8) {
return NULL;
}
if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
return NULL;
Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
offset += SHA_DIGEST_LENGTH;
P = BN_bin2bn(key+offset, (int)length, NULL);
offset += length;
G = BN_bin2bn(key+offset, (int)length, NULL);
offset += length;
Y = BN_bin2bn(key+offset, (int)length, NULL);
/* create the key and set its properties */
if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
BN_free(Q);
BN_free(P);
BN_free(G);
BN_free(Y);
return NULL;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
#ifndef S_SPLINT_S
dsa->p = P;
dsa->q = Q;
dsa->g = G;
dsa->pub_key = Y;
#endif /* splint */
#else /* OPENSSL_VERSION_NUMBER */
if (!DSA_set0_pqg(dsa, P, Q, G)) {
/* QPG not yet attached, need to free */
BN_free(Q);
BN_free(P);
BN_free(G);
DSA_free(dsa);
BN_free(Y);
return NULL;
}
if (!DSA_set0_key(dsa, Y, NULL)) {
/* QPG attached, cleaned up by DSA_fre() */
DSA_free(dsa);
BN_free(Y);
return NULL;
}
#endif
return dsa;
}
RSA *
gldns_key_buf2rsa_raw(unsigned char* key, size_t len)
{
uint16_t offset;
uint16_t exp;
uint16_t int16;
RSA *rsa;
BIGNUM *modulus;
BIGNUM *exponent;
if (len == 0)
return NULL;
if (key[0] == 0) {
if(len < 3)
return NULL;
memmove(&int16, key+1, 2);
exp = ntohs(int16);
offset = 3;
} else {
exp = key[0];
offset = 1;
}
/* key length at least one */
if(len < (size_t)offset + exp + 1)
return NULL;
/* Exponent */
exponent = BN_new();
if(!exponent) return NULL;
(void) BN_bin2bn(key+offset, (int)exp, exponent);
offset += exp;
/* Modulus */
modulus = BN_new();
if(!modulus) {
BN_free(exponent);
return NULL;
}
/* length of the buffer must match the key length! */
(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
rsa = RSA_new();
if(!rsa) {
BN_free(exponent);
BN_free(modulus);
return NULL;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
#ifndef S_SPLINT_S
rsa->n = modulus;
rsa->e = exponent;
#endif /* splint */
#else /* OPENSSL_VERSION_NUMBER */
if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
BN_free(exponent);
BN_free(modulus);
RSA_free(rsa);
return NULL;
}
#endif
return rsa;
}
#ifdef USE_GOST
EVP_PKEY*
gldns_gost2pkey_raw(unsigned char* key, size_t keylen)
{
/* prefix header for X509 encoding */
uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
unsigned char encoded[37+64];
const unsigned char* pp;
if(keylen != 64) {
/* key wrong size */
return NULL;
}
/* create evp_key */
memmove(encoded, asn, 37);
memmove(encoded+37, key, 64);
pp = (unsigned char*)&encoded[0];
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
}
#endif /* USE_GOST */
#ifdef USE_ECDSA
EVP_PKEY*
gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
{
unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
const unsigned char* pp = buf;
EVP_PKEY *evp_key;
EC_KEY *ec;
/* check length, which uncompressed must be 2 bignums */
if(algo == GLDNS_ECDSAP256SHA256) {
if(keylen != 2*256/8) return NULL;
ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
} else if(algo == GLDNS_ECDSAP384SHA384) {
if(keylen != 2*384/8) return NULL;
ec = EC_KEY_new_by_curve_name(NID_secp384r1);
} else ec = NULL;
if(!ec) return NULL;
if(keylen+1 > sizeof(buf)) { /* sanity check */
EC_KEY_free(ec);
return NULL;
}
/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
* of openssl) for uncompressed data */
buf[0] = POINT_CONVERSION_UNCOMPRESSED;
memmove(buf+1, key, keylen);
if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
EC_KEY_free(ec);
return NULL;
}
evp_key = EVP_PKEY_new();
if(!evp_key) {
EC_KEY_free(ec);
return NULL;
}
if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
EVP_PKEY_free(evp_key);
EC_KEY_free(ec);
return NULL;
}
return evp_key;
}
#endif /* USE_ECDSA */
#ifdef USE_ED25519
EVP_PKEY*
gldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
{
/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
0x70, 0x03, 0x21, 0x00};
int pre_len = 12;
uint8_t buf[256];
EVP_PKEY *evp_key;
/* pp gets modified by d2i() */
const unsigned char* pp = (unsigned char*)buf;
if(keylen != 32 || keylen + pre_len > sizeof(buf))
return NULL; /* wrong length */
memmove(buf, pre, pre_len);
memmove(buf+pre_len, key, keylen);
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
return evp_key;
}
#endif /* USE_ED25519 */
#ifdef USE_ED448
EVP_PKEY*
gldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
{
/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
0x71, 0x03, 0x3a, 0x00};
int pre_len = 12;
uint8_t buf[256];
EVP_PKEY *evp_key;
/* pp gets modified by d2i() */
const unsigned char* pp = (unsigned char*)buf;
if(keylen != 57 || keylen + pre_len > sizeof(buf))
return NULL; /* wrong length */
memmove(buf, pre, pre_len);
memmove(buf+pre_len, key, keylen);
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
return evp_key;
}
#endif /* USE_ED448 */
int
gldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
const EVP_MD* md)
{
EVP_MD_CTX* ctx;
ctx = EVP_MD_CTX_create();
if(!ctx)
return 0;
if(!EVP_DigestInit_ex(ctx, md, NULL) ||
!EVP_DigestUpdate(ctx, data, len) ||
!EVP_DigestFinal_ex(ctx, dest, NULL)) {
EVP_MD_CTX_destroy(ctx);
return 0;
}
EVP_MD_CTX_destroy(ctx);
return 1;
}
#endif /* HAVE_SSL */

View File

@ -20,13 +20,11 @@
#ifndef GLDNS_KEYRAW_H #ifndef GLDNS_KEYRAW_H
#define GLDNS_KEYRAW_H #define GLDNS_KEYRAW_H
#include "keyraw-internal.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#if GLDNS_BUILD_CONFIG_HAVE_SSL
# include <openssl/ssl.h>
# include <openssl/evp.h>
#endif /* GLDNS_BUILD_CONFIG_HAVE_SSL */
/** /**
* get the length of the keydata in bits * get the length of the keydata in bits
@ -46,83 +44,6 @@ size_t gldns_rr_dnskey_key_size_raw(const unsigned char *keydata,
*/ */
uint16_t gldns_calc_keytag_raw(const uint8_t* key, size_t keysize); uint16_t gldns_calc_keytag_raw(const uint8_t* key, size_t keysize);
#if GLDNS_BUILD_CONFIG_HAVE_SSL
/**
* Get the PKEY id for GOST, loads GOST into openssl as a side effect.
* Only available if GOST is compiled into the library and openssl.
* \return the gost id for EVP_CTX creation.
*/
int gldns_key_EVP_load_gost_id(void);
/** Release the engine reference held for the GOST engine. */
void gldns_key_EVP_unload_gost(void);
/**
* Like gldns_key_buf2dsa, but uses raw buffer.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return a DSA * structure with the key material
*/
DSA *gldns_key_buf2dsa_raw(unsigned char* key, size_t len);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with GOST.
* \param[in] key data to convert
* \param[in] keylen length of the key data
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_gost2pkey_raw(unsigned char* key, size_t keylen);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with ECDSA.
* \param[in] key data to convert
* \param[in] keylen length of the key data
* \param[in] algo precise algorithm to initialize ECC group values.
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
/**
* Like gldns_key_buf2rsa, but uses raw buffer.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return a RSA * structure with the key material
*/
RSA *gldns_key_buf2rsa_raw(unsigned char* key, size_t len);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with ED25519.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_ed255192pkey_raw(const unsigned char* key, size_t len);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with ED448.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_ed4482pkey_raw(const unsigned char* key, size_t len);
/**
* Utility function to calculate hash using generic EVP_MD pointer.
* \param[in] data the data to hash.
* \param[in] len length of data.
* \param[out] dest the destination of the hash, must be large enough.
* \param[in] md the message digest to use.
* \return true if worked, false on failure.
*/
int gldns_digest_evp(unsigned char* data, unsigned int len,
unsigned char* dest, const EVP_MD* md);
#endif /* GLDNS_BUILD_CONFIG_HAVE_SSL */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -0,0 +1,48 @@
/**
*
* /brief functions for DNSSEC trust anchor management
*
*/
/*
* Copyright (c) 2017, NLnet Labs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "anchor.h"
void _getdns_context_equip_with_anchor(
getdns_context *context, uint64_t *now_ms)
{
}
uint8_t *_getdns_tas_validate(struct mem_funcs *mf,
const getdns_bindata *xml_bd, const getdns_bindata *p7s_bd,
const getdns_bindata *crt_bd, const char *p7signer,
uint64_t *now_ms, uint8_t *tas, size_t *tas_len)
{
return NULL;
}

View File

@ -0,0 +1,15 @@
/*
* keyraw.c - raw key operations and conversions - OpenSSL version
*
* (c) NLnet Labs, 2004-2008
*
* See the file LICENSE for the license
*/
/**
* \file
* Implementation of raw DNSKEY functions (work on wire rdata).
*/
#include "config.h"
#include "gldns/keyraw.h"
#include "gldns/rrdef.h"

View File

@ -0,0 +1,31 @@
/*
* keyraw.h -- raw key and signature access and conversion - OpenSSL
*
* Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
*
* See LICENSE for the license.
*
*/
/**
* \file
*
* raw key and signature access and conversion
*
* Since those functions heavily rely op cryptographic operations,
* this module is dependent on openssl.
*
*/
#ifndef GLDNS_KEYRAW_INTERNAL_H
#define GLDNS_KEYRAW_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* GLDNS_KEYRAW_INTERNAL_H */

View File

@ -0,0 +1,59 @@
/**
*
* /brief functions for dealing with pubkey pinsets
*
*/
/*
* Copyright (c) 2015 ACLU
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "context.h"
#include <nettle/base64.h>
#include "types-internal.h"
#include "pubkey-pinning.h"
/**
** Interfaces from pubkey-pinning.h
**/
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size)
{
struct base64_decode_ctx ctx;
uint8_t* lim = res + res_size;
base64_decode_init(&ctx);
for(; *str != '\0' && res < lim; ++str) {
int r = base64_decode_single(&ctx, res, *str);
if (r == -1 )
return GETDNS_RETURN_GENERIC_ERROR;
res += r;
}
return (res == lim) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
}

View File

102
src/gnutls/tls-internal.h Normal file
View File

@ -0,0 +1,102 @@
/**
*
* \file tls-internal.h
* @brief getdns TLS implementation-specific items
*/
/*
* Copyright (c) 2018-2019, NLnet Labs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _GETDNS_TLS_INTERNAL_H
#define _GETDNS_TLS_INTERNAL_H
#include <stdbool.h>
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include <gnutls/dane.h>
#include "getdns/getdns.h"
#define SHA_DIGEST_LENGTH 20
#define SHA224_DIGEST_LENGTH 28
#define SHA256_DIGEST_LENGTH 32
#define SHA384_DIGEST_LENGTH 48
#define SHA512_DIGEST_LENGTH 64
#define GETDNS_TLS_MAX_DIGEST_LENGTH (SHA512_DIGEST_LENGTH)
#define HAVE_TLS_CTX_CURVES_LIST 0
#define HAVE_TLS_CONN_CURVES_LIST 0
typedef struct getdns_log_config getdns_log_config;
typedef struct _getdns_tls_context {
struct mem_funcs* mfs;
char* cipher_list;
char* cipher_suites;
char* curve_list;
gnutls_protocol_t min_tls;
gnutls_protocol_t max_tls;
char* ca_trust_file;
char* ca_trust_path;
const getdns_log_config* log;
} _getdns_tls_context;
typedef struct _getdns_tls_connection {
gnutls_session_t tls;
gnutls_certificate_credentials_t cred;
int shutdown;
_getdns_tls_context* ctx;
struct mem_funcs* mfs;
char* cipher_list;
char* cipher_suites;
char* curve_list;
gnutls_protocol_t min_tls;
gnutls_protocol_t max_tls;
dane_query_t dane_query;
dane_state_t dane_state;
char* tlsa;
const getdns_log_config* log;
} _getdns_tls_connection;
typedef struct _getdns_tls_session {
gnutls_datum_t tls;
} _getdns_tls_session;
typedef struct _getdns_tls_x509
{
gnutls_datum_t tls;
} _getdns_tls_x509;
typedef struct _getdns_tls_hmac
{
gnutls_hmac_hd_t tls;
unsigned int md_len;
} _getdns_tls_hmac;
#endif /* _GETDNS_TLS_INTERNAL_H */

903
src/gnutls/tls.c Normal file
View File

@ -0,0 +1,903 @@
/**
*
* \file tls.c
* @brief getdns TLS functions
*/
/*
* Copyright (c) 2018-2019, NLnet Labs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gnutls/x509.h>
#include "config.h"
#include "debug.h"
#include "context.h"
#include "tls.h"
/*
* Cipher suites recommended in RFC7525.
*
* The following strings generate a list with the same ciphers that are
* generated by the equivalent string in the OpenSSL version of this file.
*/
static char const * const _getdns_tls_context_default_cipher_list =
"+ECDHE-RSA:+ECDHE-ECDSA:+AEAD";
static char const * const _getdns_tls_context_default_cipher_suites =
"+AES-256-GCM:+AES-128-GCM:+CHACHA20-POLY1305";
static char const * const _getdns_tls_connection_opportunistic_cipher_list =
"NORMAL";
static char const * const _getdns_tls_priorities[] = {
NULL, /* No protocol */
NULL, /* SSL3 - no available keyword. */
"+VERS-TLS1.0", /* TLS1.0 */
"+VERS-TLS1.1", /* TLS1.1 */
"+VERS-TLS1.2", /* TLS1.2 */
"+VERS-TLS1.3", /* TLS1.3 */
};
static char* getdns_strdup(struct mem_funcs* mfs, const char* s)
{
char* res;
if (!s)
return NULL;
res = GETDNS_XMALLOC(*mfs, char, strlen(s) + 1);
if (!res)
return NULL;
strcpy(res, s);
return res;
}
static char* getdns_priappend(struct mem_funcs* mfs, char* s1, const char* s2)
{
char* res;
if (!s1)
return getdns_strdup(mfs, s2);
if (!s2)
return s1;
res = GETDNS_XMALLOC(*mfs, char, strlen(s1) + strlen(s2) + 2);
if (!res)
return NULL;
strcpy(res, s1);
strcat(res, ":");
strcat(res, s2);
GETDNS_FREE(*mfs, s1);
return res;
}
static int set_connection_ciphers(_getdns_tls_connection* conn)
{
char* pri = NULL;
int res;
pri = getdns_priappend(conn->mfs, pri, "NONE:+COMP-ALL:+SIGN-RSA-SHA384");
if (conn->cipher_suites)
pri = getdns_priappend(conn->mfs, pri, conn->cipher_suites);
else if (conn->ctx->cipher_suites)
pri = getdns_priappend(conn->mfs, pri, conn->ctx->cipher_suites);
if (conn->cipher_list)
pri = getdns_priappend(conn->mfs, pri, conn->cipher_list);
else if (conn->ctx->cipher_list)
pri = getdns_priappend(conn->mfs, pri, conn->ctx->cipher_list);
if (conn->curve_list)
pri = getdns_priappend(conn->mfs, pri, conn->curve_list);
else if (conn->ctx->curve_list)
pri = getdns_priappend(conn->mfs, pri, conn->ctx->curve_list);
else
pri = getdns_priappend(conn->mfs, pri, "+CURVE-ALL");
gnutls_protocol_t min = conn->min_tls;
gnutls_protocol_t max = conn->max_tls;
if (!min) min = conn->ctx->min_tls;
if (!max) max = conn->ctx->max_tls;
if (!min && !max) {
pri = getdns_priappend(conn->mfs, pri, "+VERS-TLS-ALL");
} else {
if (!max) max = GNUTLS_TLS_VERSION_MAX;
for (gnutls_protocol_t i = min; i <= max; ++i)
pri = getdns_priappend(conn->mfs, pri, _getdns_tls_priorities[i]);
}
if (pri) {
res = gnutls_priority_set_direct(conn->tls, pri, NULL);
if (res != GNUTLS_E_SUCCESS) {
_getdns_log(conn->log
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%s: %s %s (%s)\n"
, STUB_DEBUG_SETUP_TLS
, "Error configuring TLS connection with "
, pri
, gnutls_strerror(res));
}
}
else
res = gnutls_set_default_priority(conn->tls);
GETDNS_FREE(*conn->mfs, pri);
return res;
}
static getdns_return_t error_may_want_read_write(_getdns_tls_connection* conn, int err)
{
switch (err) {
case GNUTLS_E_INTERRUPTED:
case GNUTLS_E_AGAIN:
case GNUTLS_E_WARNING_ALERT_RECEIVED:
case GNUTLS_E_GOT_APPLICATION_DATA:
if (gnutls_record_get_direction(conn->tls) == 0)
return GETDNS_RETURN_TLS_WANT_READ;
else
return GETDNS_RETURN_TLS_WANT_WRITE;
default:
return GETDNS_RETURN_GENERIC_ERROR;
}
}
static getdns_return_t get_gnu_mac_algorithm(int algorithm, gnutls_mac_algorithm_t* gnualg)
{
switch (algorithm) {
case GETDNS_HMAC_MD5 : *gnualg = GNUTLS_MAC_MD5 ; break;
case GETDNS_HMAC_SHA1 : *gnualg = GNUTLS_MAC_SHA1 ; break;
case GETDNS_HMAC_SHA224: *gnualg = GNUTLS_MAC_SHA224; break;
case GETDNS_HMAC_SHA256: *gnualg = GNUTLS_MAC_SHA256; break;
case GETDNS_HMAC_SHA384: *gnualg = GNUTLS_MAC_SHA384; break;
case GETDNS_HMAC_SHA512: *gnualg = GNUTLS_MAC_SHA512; break;
default : return GETDNS_RETURN_GENERIC_ERROR;
}
return GETDNS_RETURN_GOOD;
}
static gnutls_protocol_t _getdns_tls_version2gnutls_version(getdns_tls_version_t v)
{
switch (v) {
case GETDNS_SSL3 : return GNUTLS_SSL3;
case GETDNS_TLS1 : return GNUTLS_TLS1;
case GETDNS_TLS1_1: return GNUTLS_TLS1_1;
case GETDNS_TLS1_2: return GNUTLS_TLS1_2;
#if GNUTLS_VERSION_NUMBER >= 0x030605
case GETDNS_TLS1_3: return GNUTLS_TLS1_3;
#endif
default : return GNUTLS_TLS_VERSION_MAX;
}
}
static _getdns_tls_x509* _getdns_tls_x509_new(struct mem_funcs* mfs, gnutls_datum_t cert)
{
_getdns_tls_x509* res;
res = GETDNS_MALLOC(*mfs, _getdns_tls_x509);
if (res)
res->tls = cert;
return res;
}
void _getdns_tls_init()
{
gnutls_global_init();
}
_getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs, const getdns_log_config* log)
{
_getdns_tls_context* res;
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_context)))
return NULL;
res->mfs = mfs;
res->cipher_list = res->cipher_suites = res->curve_list = NULL;
res->min_tls = res->max_tls = 0;
res->ca_trust_file = NULL;
res->ca_trust_path = NULL;
res->log = log;
return res;
}
getdns_return_t _getdns_tls_context_free(struct mem_funcs* mfs, _getdns_tls_context* ctx)
{
if (!ctx)
return GETDNS_RETURN_INVALID_PARAMETER;
GETDNS_FREE(*mfs, ctx->ca_trust_path);
GETDNS_FREE(*mfs, ctx->ca_trust_file);
GETDNS_FREE(*mfs, ctx->curve_list);
GETDNS_FREE(*mfs, ctx->cipher_suites);
GETDNS_FREE(*mfs, ctx->cipher_list);
GETDNS_FREE(*mfs, ctx);
return GETDNS_RETURN_GOOD;
}
void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx)
{
(void) ctx;
}
getdns_return_t _getdns_tls_context_set_min_max_tls_version(_getdns_tls_context* ctx, getdns_tls_version_t min, getdns_tls_version_t max)
{
if (!ctx)
return GETDNS_RETURN_INVALID_PARAMETER;
ctx->min_tls = _getdns_tls_version2gnutls_version(min);
ctx->max_tls = _getdns_tls_version2gnutls_version(max);
return GETDNS_RETURN_GOOD;
}
const char* _getdns_tls_context_get_default_cipher_list()
{
return _getdns_tls_context_default_cipher_list;
}
getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list)
{
if (!ctx)
return GETDNS_RETURN_INVALID_PARAMETER;
if (!list)
list = _getdns_tls_context_default_cipher_list;
GETDNS_FREE(*ctx->mfs, ctx->cipher_list);
ctx->cipher_list = getdns_strdup(ctx->mfs, list);
return GETDNS_RETURN_GOOD;
}
const char* _getdns_tls_context_get_default_cipher_suites()
{
return _getdns_tls_context_default_cipher_suites;
}
getdns_return_t _getdns_tls_context_set_cipher_suites(_getdns_tls_context* ctx, const char* list)
{
if (!ctx)
return GETDNS_RETURN_INVALID_PARAMETER;
if (!list)
list = _getdns_tls_context_default_cipher_suites;
GETDNS_FREE(*ctx->mfs, ctx->cipher_suites);
ctx->cipher_suites = getdns_strdup(ctx->mfs, list);
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_context_set_curves_list(_getdns_tls_context* ctx, const char* list)
{
if (!ctx)
return GETDNS_RETURN_INVALID_PARAMETER;
GETDNS_FREE(*ctx->mfs, ctx->curve_list);
ctx->curve_list = getdns_strdup(ctx->mfs, list);
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char* file, const char* path)
{
if (!ctx)
return GETDNS_RETURN_INVALID_PARAMETER;
GETDNS_FREE(*ctx->mfs, ctx->ca_trust_file);
ctx->ca_trust_file = getdns_strdup(ctx->mfs, file);
GETDNS_FREE(*ctx->mfs, ctx->ca_trust_path);
ctx->ca_trust_path = getdns_strdup(ctx->mfs, path);
return GETDNS_RETURN_GOOD;
}
_getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd, const getdns_log_config* log)
{
_getdns_tls_connection* res;
if (!ctx)
return NULL;
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_connection)))
return NULL;
res->shutdown = 0;
res->ctx = ctx;
res->mfs = mfs;
res->cred = NULL;
res->tls = NULL;
res->cipher_list = res->cipher_suites = res->curve_list = NULL;
res->min_tls = res->max_tls = 0;
res->dane_state = NULL;
res->dane_query = NULL;
res->tlsa = NULL;
res->log = log;
if (gnutls_certificate_allocate_credentials(&res->cred) != GNUTLS_E_SUCCESS)
goto failed;
if (!ctx->ca_trust_file && !ctx->ca_trust_path)
gnutls_certificate_set_x509_system_trust(res->cred);
else {
if (ctx->ca_trust_file)
gnutls_certificate_set_x509_trust_file(res->cred, ctx->ca_trust_file, GNUTLS_X509_FMT_PEM);
if (ctx->ca_trust_path)
gnutls_certificate_set_x509_trust_dir(res->cred, ctx->ca_trust_path, GNUTLS_X509_FMT_PEM);
}
if (gnutls_init(&res->tls, GNUTLS_CLIENT | GNUTLS_NONBLOCK) != GNUTLS_E_SUCCESS)
goto failed;
if (set_connection_ciphers(res) != GNUTLS_E_SUCCESS) {
goto failed;
}
if (gnutls_credentials_set(res->tls, GNUTLS_CRD_CERTIFICATE, res->cred) != GNUTLS_E_SUCCESS)
goto failed;
if (dane_state_init(&res->dane_state, DANE_F_IGNORE_DNSSEC) != DANE_E_SUCCESS)
goto failed;
gnutls_transport_set_int(res->tls, fd);
return res;
failed:
_getdns_tls_connection_free(mfs, res);
return NULL;
}
getdns_return_t _getdns_tls_connection_free(struct mem_funcs* mfs, _getdns_tls_connection* conn)
{
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
if (conn->dane_query)
dane_query_deinit(conn->dane_query);
if (conn->dane_state)
dane_state_deinit(conn->dane_state);
if (conn->tls)
gnutls_deinit(conn->tls);
if (conn->cred)
gnutls_certificate_free_credentials(conn->cred);
GETDNS_FREE(*mfs, conn->tlsa);
GETDNS_FREE(*mfs, conn->curve_list);
GETDNS_FREE(*mfs, conn->cipher_suites);
GETDNS_FREE(*mfs, conn->cipher_list);
GETDNS_FREE(*mfs, conn);
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn)
{
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
if (conn->shutdown == 0) {
gnutls_bye(conn->tls, GNUTLS_SHUT_WR);
conn->shutdown++;
} else {
gnutls_bye(conn->tls, GNUTLS_SHUT_RDWR);
conn->shutdown++;
}
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_set_min_max_tls_version(_getdns_tls_connection* conn, getdns_tls_version_t min, getdns_tls_version_t max)
{
if (!conn)
return GETDNS_RETURN_INVALID_PARAMETER;
conn->min_tls = _getdns_tls_version2gnutls_version(min);
conn->max_tls = _getdns_tls_version2gnutls_version(max);
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list)
{
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
if (!list)
list = _getdns_tls_connection_opportunistic_cipher_list;
GETDNS_FREE(*conn->mfs, conn->cipher_list);
conn->cipher_list = getdns_strdup(conn->mfs, list);
if (set_connection_ciphers(conn) == GNUTLS_E_SUCCESS)
return GETDNS_RETURN_GOOD;
else
return GETDNS_RETURN_GENERIC_ERROR;
}
getdns_return_t _getdns_tls_connection_set_cipher_suites(_getdns_tls_connection* conn, const char* list)
{
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
GETDNS_FREE(*conn->mfs, conn->cipher_list);
conn->cipher_suites = getdns_strdup(conn->mfs, list);
if (set_connection_ciphers(conn) == GNUTLS_E_SUCCESS)
return GETDNS_RETURN_GOOD;
else
return GETDNS_RETURN_GENERIC_ERROR;
}
getdns_return_t _getdns_tls_connection_set_curves_list(_getdns_tls_connection* conn, const char* list)
{
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
GETDNS_FREE(*conn->mfs, conn->curve_list);
conn->curve_list = getdns_strdup(conn->mfs, list);
if (set_connection_ciphers(conn) == GNUTLS_E_SUCCESS)
return GETDNS_RETURN_GOOD;
else
return GETDNS_RETURN_GENERIC_ERROR;
}
getdns_return_t _getdns_tls_connection_set_session(_getdns_tls_connection* conn, _getdns_tls_session* s)
{
int r;
if (!conn || !conn->tls || !s)
return GETDNS_RETURN_INVALID_PARAMETER;
r = gnutls_session_set_data(conn->tls, s->tls.data, s->tls.size);
if (r != GNUTLS_E_SUCCESS)
return GETDNS_RETURN_GENERIC_ERROR;
return GETDNS_RETURN_GOOD;
}
_getdns_tls_session* _getdns_tls_connection_get_session(struct mem_funcs* mfs, _getdns_tls_connection* conn)
{
_getdns_tls_session* res;
int r;
if (!conn || !conn->tls)
return NULL;
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_session)))
return NULL;
r = gnutls_session_get_data2(conn->tls, &res->tls);
if (r != GNUTLS_E_SUCCESS) {
GETDNS_FREE(*mfs, res);
return NULL;
}
return res;
}
const char* _getdns_tls_connection_get_version(_getdns_tls_connection* conn)
{
if (!conn || !conn->tls)
return NULL;
return gnutls_protocol_get_name(gnutls_protocol_get_version(conn->tls));
}
getdns_return_t _getdns_tls_connection_do_handshake(_getdns_tls_connection* conn)
{
int r;
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
r = gnutls_handshake(conn->tls);
if (r == GNUTLS_E_SUCCESS) {
return GETDNS_RETURN_GOOD;
}
else
return error_may_want_read_write(conn, r);
}
_getdns_tls_x509* _getdns_tls_connection_get_peer_certificate(struct mem_funcs* mfs, _getdns_tls_connection* conn)
{
const gnutls_datum_t *cert_list;
unsigned int cert_list_size;
if (!conn || !conn->tls)
return NULL;
cert_list = gnutls_certificate_get_peers(conn->tls, &cert_list_size);
if (cert_list == NULL)
return NULL;
return _getdns_tls_x509_new(mfs, *cert_list);
}
getdns_return_t _getdns_tls_connection_is_session_reused(_getdns_tls_connection* conn)
{
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
if (gnutls_session_is_resumed(conn->tls) != 0)
return GETDNS_RETURN_GOOD;
else
return GETDNS_RETURN_TLS_CONNECTION_FRESH;
}
getdns_return_t _getdns_tls_connection_setup_hostname_auth(_getdns_tls_connection* conn, const char* auth_name)
{
int r;
if (!conn || !conn->tls || !auth_name)
return GETDNS_RETURN_INVALID_PARAMETER;
r = gnutls_server_name_set(conn->tls, GNUTLS_NAME_DNS, auth_name, strlen(auth_name));
if (r != GNUTLS_E_SUCCESS)
return GETDNS_RETURN_GENERIC_ERROR;
gnutls_session_set_verify_cert(conn->tls, auth_name, 0);
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_set_host_pinset(_getdns_tls_connection* conn, const char* auth_name, const sha256_pin_t* pinset)
{
int r;
if (!conn || !conn->tls || !auth_name)
return GETDNS_RETURN_INVALID_PARAMETER;
size_t npins = 0;
for (const sha256_pin_t* pin = pinset; pin; pin = pin->next)
npins++;
GETDNS_FREE(*conn->mfs, conn->tlsa);
conn->tlsa = GETDNS_XMALLOC(*conn->mfs, char, npins * (SHA256_DIGEST_LENGTH + 3) * 2);
if (!conn->tlsa)
return GETDNS_RETURN_GENERIC_ERROR;
char** dane_data = GETDNS_XMALLOC(*conn->mfs, char*, npins * 2 + 1);
if (!dane_data)
return GETDNS_RETURN_GENERIC_ERROR;
int* dane_data_len = GETDNS_XMALLOC(*conn->mfs, int, npins * 2 + 1);
if (!dane_data_len) {
GETDNS_FREE(*conn->mfs, dane_data);
return GETDNS_RETURN_GENERIC_ERROR;
}
char** dane_p = dane_data;
int* dane_len_p = dane_data_len;
char* p = conn->tlsa;
for (const sha256_pin_t* pin = pinset; pin; pin = pin->next) {
*dane_p++ = p;
*dane_len_p++ = SHA256_DIGEST_LENGTH + 3;
p[0] = DANE_CERT_USAGE_LOCAL_CA;
p[1] = DANE_CERT_PK;
p[2] = DANE_MATCH_SHA2_256;
memcpy(&p[3], pin->pin, SHA256_DIGEST_LENGTH);
p += SHA256_DIGEST_LENGTH + 3;
*dane_p++ = p;
*dane_len_p++ = SHA256_DIGEST_LENGTH + 3;
p[0] = DANE_CERT_USAGE_LOCAL_EE;
p[1] = DANE_CERT_PK;
p[2] = DANE_MATCH_SHA2_256;
memcpy(&p[3], pin->pin, SHA256_DIGEST_LENGTH);
p += SHA256_DIGEST_LENGTH + 3;
}
*dane_p = NULL;
if (conn->dane_query)
dane_query_deinit(conn->dane_query);
r = dane_raw_tlsa(conn->dane_state, &conn->dane_query, dane_data, dane_data_len, 0, 0);
GETDNS_FREE(*conn->mfs, dane_data_len);
GETDNS_FREE(*conn->mfs, dane_data);
return (r == DANE_E_SUCCESS) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
}
getdns_return_t _getdns_tls_connection_certificate_verify(_getdns_tls_connection* conn, long* errnum, const char** errmsg)
{
if (!conn || !conn->tls)
return GETDNS_RETURN_INVALID_PARAMETER;
/* If no pinset, no DANE info to check. */
if (!conn->dane_query)
return GETDNS_RETURN_GOOD;
/* Most of the internals of dane_verify_session_crt() */
const gnutls_datum_t* cert_list;
unsigned int cert_list_size = 0;
unsigned int type;
int ret;
const gnutls_datum_t* cl;
gnutls_datum_t* new_cert_list = NULL;
int clsize;
unsigned int verify;
cert_list = gnutls_certificate_get_peers(conn->tls, &cert_list_size);
if (cert_list_size == 0) {
*errnum = 1;
*errmsg = "No peer certificate";
return GETDNS_RETURN_GENERIC_ERROR;
}
cl = cert_list;
type = gnutls_certificate_type_get(conn->tls);
/* this list may be incomplete, try to get the self-signed CA if any */
if (cert_list_size > 0) {
gnutls_x509_crt_t crt, ca;
gnutls_certificate_credentials_t sc;
ret = gnutls_x509_crt_init(&crt);
if (ret < 0)
goto failsafe;
ret = gnutls_x509_crt_import(crt, &cert_list[cert_list_size-1], GNUTLS_X509_FMT_DER);
if (ret < 0) {
gnutls_x509_crt_deinit(crt);
goto failsafe;
}
/* if it is already self signed continue normally */
ret = gnutls_x509_crt_check_issuer(crt, crt);
if (ret != 0) {
gnutls_x509_crt_deinit(crt);
goto failsafe;
}
/* chain does not finish in a self signed cert, try to obtain the issuer */
ret = gnutls_credentials_get(conn->tls, GNUTLS_CRD_CERTIFICATE, (void**)&sc);
if (ret < 0) {
gnutls_x509_crt_deinit(crt);
goto failsafe;
}
ret = gnutls_certificate_get_issuer(sc, crt, &ca, 0);
if (ret < 0) {
gnutls_x509_crt_deinit(crt);
goto failsafe;
}
/* make the new list */
new_cert_list = GETDNS_XMALLOC(*conn->mfs, gnutls_datum_t, cert_list_size + 1);
if (new_cert_list == NULL) {
gnutls_x509_crt_deinit(crt);
goto failsafe;
}
memcpy(new_cert_list, cert_list, cert_list_size*sizeof(gnutls_datum_t));
cl = new_cert_list;
ret = gnutls_x509_crt_export2(ca, GNUTLS_X509_FMT_DER, &new_cert_list[cert_list_size]);
if (ret < 0) {
GETDNS_FREE(*conn->mfs, new_cert_list);
gnutls_x509_crt_deinit(crt);
goto failsafe;
}
}
failsafe:
clsize = cert_list_size;
if (cl == new_cert_list)
clsize += 1;
ret = dane_verify_crt_raw(conn->dane_state, cl, clsize, type, conn->dane_query, 0, 0, &verify);
if (new_cert_list) {
gnutls_free(new_cert_list[cert_list_size].data);
GETDNS_FREE(*conn->mfs, new_cert_list);
}
if (ret != DANE_E_SUCCESS)
return GETDNS_RETURN_GENERIC_ERROR;
if (verify != 0) {
if (verify & DANE_VERIFY_CERT_DIFFERS) {
*errnum = 3;
*errmsg = "Pinset validation: Certificate differs";
} else if (verify & DANE_VERIFY_CA_CONSTRAINTS_VIOLATED) {
*errnum = 2;
*errmsg = "Pinset validation: CA constraints violated";
} else {
*errnum = 4;
*errmsg = "Pinset validation: Unknown DANE info";
}
return GETDNS_RETURN_GENERIC_ERROR;
}
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_read(_getdns_tls_connection* conn, uint8_t* buf, size_t to_read, size_t* read)
{
ssize_t sread;
if (!conn || !conn->tls || !read)
return GETDNS_RETURN_INVALID_PARAMETER;
sread = gnutls_record_recv(conn->tls, buf, to_read);
if (sread < 0)
return error_may_want_read_write(conn, sread);
*read = sread;
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_connection_write(_getdns_tls_connection* conn, uint8_t* buf, size_t to_write, size_t* written)
{
int swritten;
if (!conn || !conn->tls || !written)
return GETDNS_RETURN_INVALID_PARAMETER;
swritten = gnutls_record_send(conn->tls, buf, to_write);
if (swritten < 0)
return error_may_want_read_write(conn, swritten);
*written = swritten;
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_session_free(struct mem_funcs* mfs, _getdns_tls_session* s)
{
if (!s)
return GETDNS_RETURN_INVALID_PARAMETER;
GETDNS_FREE(*mfs, s);
return GETDNS_RETURN_GOOD;
}
getdns_return_t _getdns_tls_get_api_information(getdns_dict* dict)
{
if (! getdns_dict_set_int(
dict, "gnutls_version_number", GNUTLS_VERSION_NUMBER)
&& ! getdns_dict_util_set_string(
dict, "gnutls_version_string", GNUTLS_VERSION)
)
return GETDNS_RETURN_GOOD;
return GETDNS_RETURN_GENERIC_ERROR;
}
void _getdns_tls_x509_free(struct mem_funcs* mfs, _getdns_tls_x509* cert)
{
if (cert)
GETDNS_FREE(*mfs, cert);
}
int _getdns_tls_x509_to_der(struct mem_funcs* mfs, _getdns_tls_x509* cert, getdns_bindata* bindata)
{
gnutls_x509_crt_t crt;
size_t s;
if (!cert || gnutls_x509_crt_init(&crt) != GNUTLS_E_SUCCESS)
return 0;
gnutls_x509_crt_import(crt, &cert->tls, GNUTLS_X509_FMT_DER);
gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL, &s);
if (!bindata) {
gnutls_x509_crt_deinit(crt);
return s;
}
bindata->data = GETDNS_XMALLOC(*mfs, uint8_t, s);
if (!bindata->data) {
gnutls_x509_crt_deinit(crt);
return 0;
}
gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, bindata->data, &s);
bindata->size = s;
gnutls_x509_crt_deinit(crt);
return s;
}
unsigned char* _getdns_tls_hmac_hash(struct mem_funcs* mfs, int algorithm, const void* key, size_t key_size, const void* data, size_t data_size, size_t* output_size)
{
gnutls_mac_algorithm_t alg;
unsigned int md_len;
unsigned char* res;
if (get_gnu_mac_algorithm(algorithm, &alg) != GETDNS_RETURN_GOOD)
return NULL;
md_len = gnutls_hmac_get_len(alg);
res = (unsigned char*) GETDNS_XMALLOC(*mfs, unsigned char, md_len);
if (!res)
return NULL;
(void) gnutls_hmac_fast(alg, key, key_size, data, data_size, res);
if (output_size)
*output_size = md_len;
return res;
}
_getdns_tls_hmac* _getdns_tls_hmac_new(struct mem_funcs* mfs, int algorithm, const void* key, size_t key_size)
{
gnutls_mac_algorithm_t alg;
_getdns_tls_hmac* res;
if (get_gnu_mac_algorithm(algorithm, &alg) != GETDNS_RETURN_GOOD)
return NULL;
if (!(res = GETDNS_MALLOC(*mfs, struct _getdns_tls_hmac)))
return NULL;
if (gnutls_hmac_init(&res->tls, alg, key, key_size) < 0) {
GETDNS_FREE(*mfs, res);
return NULL;
}
res->md_len = gnutls_hmac_get_len(alg);
return res;
}
getdns_return_t _getdns_tls_hmac_add(_getdns_tls_hmac* h, const void* data, size_t data_size)
{
if (!h || !h->tls || !data)
return GETDNS_RETURN_INVALID_PARAMETER;
if (gnutls_hmac(h->tls, data, data_size) < 0)
return GETDNS_RETURN_GENERIC_ERROR;
else
return GETDNS_RETURN_GOOD;
}
unsigned char* _getdns_tls_hmac_end(struct mem_funcs* mfs, _getdns_tls_hmac* h, size_t* output_size)
{
unsigned char* res;
if (!h || !h->tls)
return NULL;
res = (unsigned char*) GETDNS_XMALLOC(*mfs, unsigned char, h->md_len);
if (!res)
return NULL;
gnutls_hmac_deinit(h->tls, res);
if (output_size)
*output_size = h->md_len;
GETDNS_FREE(*mfs, h);
return res;
}
void _getdns_tls_sha1(const void* data, size_t data_size, unsigned char* buf)
{
gnutls_hash_fast(GNUTLS_DIG_SHA1, data, data_size, buf);
}
void _getdns_tls_cookie_sha256(uint32_t secret, void* addr, size_t addrlen, unsigned char* buf, size_t* buflen)
{
gnutls_hash_hd_t digest;
gnutls_hash_init(&digest, GNUTLS_DIG_SHA256);
gnutls_hash(digest, &secret, sizeof(secret));
gnutls_hash(digest, addr, addrlen);
gnutls_hash_deinit(digest, buf);
*buflen = gnutls_hash_get_len(GNUTLS_DIG_SHA256);
}
/* tls.c */

1
src/gnutls/val_secalgo.c Symbolic link
View File

@ -0,0 +1 @@
../openssl/val_secalgo.c

1
src/gnutls/validator Symbolic link
View File

@ -0,0 +1 @@
../openssl/validator

View File

@ -0,0 +1,382 @@
/**
*
* /brief functions for DNSSEC trust anchor management
*/
/*
* Copyright (c) 2017, NLnet Labs, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "debug.h"
#include "anchor.h"
#include <fcntl.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <strings.h>
#include <time.h>
#include "types-internal.h"
#include "context.h"
#include "dnssec.h"
#include "yxml/yxml.h"
#include "gldns/parseutil.h"
#include "gldns/gbuffer.h"
#include "gldns/str2wire.h"
#include "gldns/wire2str.h"
#include "gldns/pkthdr.h"
#include "gldns/keyraw.h"
#include "general.h"
#include "util-internal.h"
#include "platform.h"
/* get key usage out of its extension, returns 0 if no key_usage extension */
static unsigned long
_getdns_get_usage_of_ex(X509* cert)
{
unsigned long val = 0;
ASN1_BIT_STRING* s;
if((s=X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL))) {
if(s->length > 0) {
val = s->data[0];
if(s->length > 1)
val |= s->data[1] << 8;
}
ASN1_BIT_STRING_free(s);
}
return val;
}
/** get valid signers from the list of signers in the signature */
static STACK_OF(X509)*
_getdns_get_valid_signers(PKCS7* p7, const char* p7signer)
{
int i;
STACK_OF(X509)* validsigners = sk_X509_new_null();
STACK_OF(X509)* signers = PKCS7_get0_signers(p7, NULL, 0);
unsigned long usage = 0;
if(!validsigners) {
DEBUG_ANCHOR("ERROR %s(): Failed to allocated validsigners\n"
, __FUNC__);
sk_X509_free(signers);
return NULL;
}
if(!signers) {
DEBUG_ANCHOR("ERROR %s(): Failed to allocated signers\n"
, __FUNC__);
sk_X509_free(validsigners);
return NULL;
}
for(i=0; i<sk_X509_num(signers); i++) {
char buf[1024];
X509_NAME* nm = X509_get_subject_name(
sk_X509_value(signers, i));
if(!nm) {
DEBUG_ANCHOR("%s(): cert %d has no subject name\n"
, __FUNC__, i);
continue;
}
if(!p7signer || strcmp(p7signer, "")==0) {
/* there is no name to check, return all records */
DEBUG_ANCHOR("%s(): did not check commonName of signer\n"
, __FUNC__);
} else {
if(!X509_NAME_get_text_by_NID(nm,
NID_pkcs9_emailAddress,
buf, (int)sizeof(buf))) {
DEBUG_ANCHOR("%s(): removed cert with no name\n"
, __FUNC__);
continue; /* no name, no use */
}
if(strcmp(buf, p7signer) != 0) {
DEBUG_ANCHOR("%s(): removed cert with wrong name\n"
, __FUNC__);
continue; /* wrong name, skip it */
}
}
/* check that the key usage allows digital signatures
* (the p7s) */
usage = _getdns_get_usage_of_ex(sk_X509_value(signers, i));
if(!(usage & KU_DIGITAL_SIGNATURE)) {
DEBUG_ANCHOR("%s(): removed cert with no key usage "
"Digital Signature allowed\n"
, __FUNC__);
continue;
}
/* we like this cert, add it to our list of valid
* signers certificates */
sk_X509_push(validsigners, sk_X509_value(signers, i));
}
sk_X509_free(signers);
return validsigners;
}
static int
_getdns_verify_p7sig(BIO* data, BIO* p7s, X509_STORE *store, const char* p7signer)
{
PKCS7* p7;
STACK_OF(X509)* validsigners;
int secure = 0;
#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new();
if(!param) {
DEBUG_ANCHOR("ERROR %s(): Failed to allocated param\n"
, __FUNC__);
return 0;
}
/* do the selfcheck on the root certificate; it checks that the
* input is valid */
X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CHECK_SS_SIGNATURE);
X509_STORE_set1_param(store, param);
X509_VERIFY_PARAM_free(param);
#endif
(void)BIO_reset(p7s);
(void)BIO_reset(data);
/* convert p7s to p7 (the signature) */
p7 = d2i_PKCS7_bio(p7s, NULL);
if(!p7) {
DEBUG_ANCHOR("ERROR %s(): could not parse p7s signature file\n"
, __FUNC__);
return 0;
}
/* check what is in the Subject name of the certificates,
* and build a stack that contains only the right certificates */
validsigners = _getdns_get_valid_signers(p7, p7signer);
if(!validsigners) {
PKCS7_free(p7);
return 0;
}
if(PKCS7_verify(p7, validsigners, store, data, NULL, PKCS7_NOINTERN) == 1) {
secure = 1;
}
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
else {
DEBUG_ANCHOR("ERROR %s(): the PKCS7 signature did not verify\n"
, __FUNC__);
ERR_print_errors_cb(_getdns_ERR_print_errors_cb_f, NULL);
}
#endif
sk_X509_free(validsigners);
PKCS7_free(p7);
return secure;
}
uint8_t *_getdns_tas_validate(struct mem_funcs *mf,
const getdns_bindata *xml_bd, const getdns_bindata *p7s_bd,
const getdns_bindata *crt_bd, const char *p7signer,
uint64_t *now_ms, uint8_t *tas, size_t *tas_len)
{
BIO *xml = NULL, *p7s = NULL, *crt = NULL;
X509 *x = NULL;
X509_STORE *store = NULL;
uint8_t *success = NULL;
if (!(xml = BIO_new_mem_buf(xml_bd->data, xml_bd->size)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating xml BIO\n"
, __FUNC__);
else if (!(p7s = BIO_new_mem_buf(p7s_bd->data, p7s_bd->size)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating p7s BIO\n"
, __FUNC__);
else if (!(crt = BIO_new_mem_buf(crt_bd->data, crt_bd->size)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating crt BIO\n"
, __FUNC__);
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
DEBUG_ANCHOR("ERROR %s(): Parsing builtin certificate\n"
, __FUNC__);
else if (!(store = X509_STORE_new()))
DEBUG_ANCHOR("ERROR %s(): Failed allocating store\n"
, __FUNC__);
else if (!X509_STORE_add_cert(store, x))
DEBUG_ANCHOR("ERROR %s(): Adding certificate to store\n"
, __FUNC__);
else if (_getdns_verify_p7sig(xml, p7s, store, p7signer)) {
gldns_buffer gbuf;
gldns_buffer_init_vfixed_frm_data(&gbuf, tas, *tas_len);
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms,
(char *)xml_bd->data, xml_bd->size))
DEBUG_ANCHOR("Failed to parse trust anchor XML data");
else if (gldns_buffer_position(&gbuf) > *tas_len) {
*tas_len = gldns_buffer_position(&gbuf);
if ((success = GETDNS_XMALLOC(*mf, uint8_t, *tas_len))) {
gldns_buffer_init_frm_data(&gbuf, success, *tas_len);
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf,
now_ms, (char *)xml_bd->data, xml_bd->size)) {
DEBUG_ANCHOR("Failed to re-parse trust"
" anchor XML data\n");
GETDNS_FREE(*mf, success);
success = NULL;
}
} else
DEBUG_ANCHOR("Could not allocate space for "
"trust anchors\n");
} else {
success = tas;
*tas_len = gldns_buffer_position(&gbuf);
}
} else {
DEBUG_ANCHOR("Verifying trust-anchors failed!\n");
}
if (store) X509_STORE_free(store);
if (x) X509_free(x);
if (crt) BIO_free(crt);
if (xml) BIO_free(xml);
if (p7s) BIO_free(p7s);
return success;
}
void _getdns_context_equip_with_anchor(
getdns_context *context, uint64_t *now_ms)
{
uint8_t xml_spc[4096], *xml_data = NULL;
uint8_t p7s_spc[4096], *p7s_data = NULL;
size_t xml_len, p7s_len;
const char *verify_email = NULL;
const char *verify_CA = NULL;
getdns_return_t r;
BIO *xml = NULL, *p7s = NULL, *crt = NULL;
X509 *x = NULL;
X509_STORE *store = NULL;
if ((r = getdns_context_get_trust_anchors_verify_CA(
context, &verify_CA)))
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify"
" CA: \"%s\"\n", __FUNC__
, getdns_get_errorstr_by_id(r));
else if (!verify_CA || !*verify_CA)
DEBUG_ANCHOR("NOTICE: Trust anchor verification explicitely "
"disabled by empty verify CA\n");
else if ((r = getdns_context_get_trust_anchors_verify_email(
context, &verify_email)))
DEBUG_ANCHOR("ERROR %s(): Getting trust anchor verify email "
"address: \"%s\"\n", __FUNC__
, getdns_get_errorstr_by_id(r));
else if (!verify_email || !*verify_email)
DEBUG_ANCHOR("NOTICE: Trust anchor verification explicitely "
"disabled by empty verify email\n");
else if (!(xml_data = _getdns_context_get_priv_file(context,
"root-anchors.xml", xml_spc, sizeof(xml_spc), &xml_len)))
DEBUG_ANCHOR("DEBUG %s(): root-anchors.xml not present\n"
, __FUNC__);
else if (!(p7s_data = _getdns_context_get_priv_file(context,
"root-anchors.p7s", p7s_spc, sizeof(p7s_spc), &p7s_len)))
DEBUG_ANCHOR("DEBUG %s(): root-anchors.p7s not present\n"
, __FUNC__);
else if (!(xml = BIO_new_mem_buf(xml_data, xml_len)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating xml BIO\n"
, __FUNC__);
else if (!(p7s = BIO_new_mem_buf(p7s_data, p7s_len)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating p7s BIO\n"
, __FUNC__);
else if (!(crt = BIO_new_mem_buf((void *)verify_CA, -1)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating crt BIO\n"
, __FUNC__);
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
DEBUG_ANCHOR("ERROR %s(): Parsing builtin certificate\n"
, __FUNC__);
else if (!(store = X509_STORE_new()))
DEBUG_ANCHOR("ERROR %s(): Failed allocating store\n"
, __FUNC__);
else if (!X509_STORE_add_cert(store, x))
DEBUG_ANCHOR("ERROR %s(): Adding certificate to store\n"
, __FUNC__);
else if (_getdns_verify_p7sig(xml, p7s, store, verify_email)) {
uint8_t ta_spc[sizeof(context->trust_anchors_spc)];
size_t ta_len;
uint8_t *ta = NULL;
gldns_buffer gbuf;
gldns_buffer_init_vfixed_frm_data(
&gbuf, ta_spc, sizeof(ta_spc));
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms,
(char *)xml_data, xml_len))
DEBUG_ANCHOR("Failed to parse trust anchor XML data");
else if ((ta_len = gldns_buffer_position(&gbuf)) > sizeof(ta_spc)) {
if ((ta = GETDNS_XMALLOC(context->mf, uint8_t, ta_len))) {
gldns_buffer_init_frm_data(&gbuf, ta,
gldns_buffer_position(&gbuf));
if (!_getdns_parse_xml_trust_anchors_buf(
&gbuf, now_ms, (char *)xml_data, xml_len)) {
DEBUG_ANCHOR("Failed to re-parse trust"
" anchor XML data");
GETDNS_FREE(context->mf, ta);
} else {
context->trust_anchors = ta;
context->trust_anchors_len = ta_len;
context->trust_anchors_source = GETDNS_TASRC_XML;
_getdns_ta_notify_dnsreqs(context);
}
} else
DEBUG_ANCHOR("Could not allocate space for XML file");
} else {
(void)memcpy(context->trust_anchors_spc, ta_spc, ta_len);
context->trust_anchors = context->trust_anchors_spc;
context->trust_anchors_len = ta_len;
context->trust_anchors_source = GETDNS_TASRC_XML;
_getdns_ta_notify_dnsreqs(context);
}
DEBUG_ANCHOR("ta: %p, ta_len: %d\n",
(void *)context->trust_anchors, (int)context->trust_anchors_len);
} else {
DEBUG_ANCHOR("Verifying trust-anchors failed!\n");
}
if (store) X509_STORE_free(store);
if (x) X509_free(x);
if (crt) BIO_free(crt);
if (xml) BIO_free(xml);
if (p7s) BIO_free(p7s);
if (xml_data && xml_data != xml_spc)
GETDNS_FREE(context->mf, xml_data);
if (p7s_data && p7s_data != p7s_spc)
GETDNS_FREE(context->mf, p7s_data);
}

View File

@ -0,0 +1,380 @@
/*
* keyraw.c - raw key operations and conversions - OpenSSL version
*
* (c) NLnet Labs, 2004-2008
*
* See the file LICENSE for the license
*/
/**
* \file
* Implementation of raw DNSKEY functions (work on wire rdata).
*/
#include "config.h"
#include "gldns/keyraw.h"
#include "gldns/rrdef.h"
#ifdef HAVE_SSL
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#ifdef HAVE_OPENSSL_CONF_H
# include <openssl/conf.h>
#endif
#ifdef HAVE_OPENSSL_ENGINE_H
# include <openssl/engine.h>
#endif
#ifdef HAVE_OPENSSL_BN_H
#include <openssl/bn.h>
#endif
#ifdef HAVE_OPENSSL_RSA_H
#include <openssl/rsa.h>
#endif
#ifdef HAVE_OPENSSL_DSA_H
#include <openssl/dsa.h>
#endif
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
#ifdef USE_GOST
/** store GOST engine reference loaded into OpenSSL library */
#ifdef OPENSSL_NO_ENGINE
int
gldns_key_EVP_load_gost_id(void)
{
return 0;
}
void gldns_key_EVP_unload_gost(void)
{
}
#else
ENGINE* gldns_gost_engine = NULL;
int
gldns_key_EVP_load_gost_id(void)
{
static int gost_id = 0;
const EVP_PKEY_ASN1_METHOD* meth;
ENGINE* e;
if(gost_id) return gost_id;
/* see if configuration loaded gost implementation from other engine*/
meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
if(meth) {
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
return gost_id;
}
/* see if engine can be loaded already */
e = ENGINE_by_id("gost");
if(!e) {
/* load it ourself, in case statically linked */
ENGINE_load_builtin_engines();
ENGINE_load_dynamic();
e = ENGINE_by_id("gost");
}
if(!e) {
/* no gost engine in openssl */
return 0;
}
if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
ENGINE_finish(e);
ENGINE_free(e);
return 0;
}
meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
if(!meth) {
/* algo not found */
ENGINE_finish(e);
ENGINE_free(e);
return 0;
}
/* Note: do not ENGINE_finish and ENGINE_free the acquired engine
* on some platforms this frees up the meth and unloads gost stuff */
gldns_gost_engine = e;
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
return gost_id;
}
void gldns_key_EVP_unload_gost(void)
{
if(gldns_gost_engine) {
ENGINE_finish(gldns_gost_engine);
ENGINE_free(gldns_gost_engine);
gldns_gost_engine = NULL;
}
}
#endif /* ifndef OPENSSL_NO_ENGINE */
#endif /* USE_GOST */
DSA *
gldns_key_buf2dsa_raw(unsigned char* key, size_t len)
{
uint8_t T;
uint16_t length;
uint16_t offset;
DSA *dsa;
BIGNUM *Q; BIGNUM *P;
BIGNUM *G; BIGNUM *Y;
if(len == 0)
return NULL;
T = (uint8_t)key[0];
length = (64 + T * 8);
offset = 1;
if (T > 8) {
return NULL;
}
if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
return NULL;
Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
offset += SHA_DIGEST_LENGTH;
P = BN_bin2bn(key+offset, (int)length, NULL);
offset += length;
G = BN_bin2bn(key+offset, (int)length, NULL);
offset += length;
Y = BN_bin2bn(key+offset, (int)length, NULL);
/* create the key and set its properties */
if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
BN_free(Q);
BN_free(P);
BN_free(G);
BN_free(Y);
return NULL;
}
#if defined(HAVE_DSA_SET0_PQG) && defined(HAVE_DSA_SET0_KEY)
if (!DSA_set0_pqg(dsa, P, Q, G)) {
/* QPG not yet attached, need to free */
BN_free(Q);
BN_free(P);
BN_free(G);
DSA_free(dsa);
BN_free(Y);
return NULL;
}
if (!DSA_set0_key(dsa, Y, NULL)) {
/* QPG attached, cleaned up by DSA_fre() */
DSA_free(dsa);
BN_free(Y);
return NULL;
}
#else
# ifndef S_SPLINT_S
dsa->p = P;
dsa->q = Q;
dsa->g = G;
dsa->pub_key = Y;
# endif /* splint */
#endif
return dsa;
}
RSA *
gldns_key_buf2rsa_raw(unsigned char* key, size_t len)
{
uint16_t offset;
uint16_t exp;
uint16_t int16;
RSA *rsa;
BIGNUM *modulus;
BIGNUM *exponent;
if (len == 0)
return NULL;
if (key[0] == 0) {
if(len < 3)
return NULL;
memmove(&int16, key+1, 2);
exp = ntohs(int16);
offset = 3;
} else {
exp = key[0];
offset = 1;
}
/* key length at least one */
if(len < (size_t)offset + exp + 1)
return NULL;
/* Exponent */
exponent = BN_new();
if(!exponent) return NULL;
(void) BN_bin2bn(key+offset, (int)exp, exponent);
offset += exp;
/* Modulus */
modulus = BN_new();
if(!modulus) {
BN_free(exponent);
return NULL;
}
/* length of the buffer must match the key length! */
(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
rsa = RSA_new();
if(!rsa) {
BN_free(exponent);
BN_free(modulus);
return NULL;
}
#if defined(HAVE_RSA_SET0_KEY)
if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
BN_free(exponent);
BN_free(modulus);
RSA_free(rsa);
return NULL;
}
#else
# ifndef S_SPLINT_S
rsa->n = modulus;
rsa->e = exponent;
# endif /* splint */
#endif
return rsa;
}
#ifdef USE_GOST
EVP_PKEY*
gldns_gost2pkey_raw(unsigned char* key, size_t keylen)
{
/* prefix header for X509 encoding */
uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
unsigned char encoded[37+64];
const unsigned char* pp;
if(keylen != 64) {
/* key wrong size */
return NULL;
}
/* create evp_key */
memmove(encoded, asn, 37);
memmove(encoded+37, key, 64);
pp = (unsigned char*)&encoded[0];
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
}
#endif /* USE_GOST */
#ifdef USE_ECDSA
EVP_PKEY*
gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
{
unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
const unsigned char* pp = buf;
EVP_PKEY *evp_key;
EC_KEY *ec;
/* check length, which uncompressed must be 2 bignums */
if(algo == GLDNS_ECDSAP256SHA256) {
if(keylen != 2*256/8) return NULL;
ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
} else if(algo == GLDNS_ECDSAP384SHA384) {
if(keylen != 2*384/8) return NULL;
ec = EC_KEY_new_by_curve_name(NID_secp384r1);
} else ec = NULL;
if(!ec) return NULL;
if(keylen+1 > sizeof(buf)) { /* sanity check */
EC_KEY_free(ec);
return NULL;
}
/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
* of openssl) for uncompressed data */
buf[0] = POINT_CONVERSION_UNCOMPRESSED;
memmove(buf+1, key, keylen);
if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
EC_KEY_free(ec);
return NULL;
}
evp_key = EVP_PKEY_new();
if(!evp_key) {
EC_KEY_free(ec);
return NULL;
}
if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
EVP_PKEY_free(evp_key);
EC_KEY_free(ec);
return NULL;
}
return evp_key;
}
#endif /* USE_ECDSA */
#ifdef USE_ED25519
EVP_PKEY*
gldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
{
/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
0x70, 0x03, 0x21, 0x00};
int pre_len = 12;
uint8_t buf[256];
EVP_PKEY *evp_key;
/* pp gets modified by d2i() */
const unsigned char* pp = (unsigned char*)buf;
if(keylen != 32 || keylen + pre_len > sizeof(buf))
return NULL; /* wrong length */
memmove(buf, pre, pre_len);
memmove(buf+pre_len, key, keylen);
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
return evp_key;
}
#endif /* USE_ED25519 */
#ifdef USE_ED448
EVP_PKEY*
gldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
{
/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
0x71, 0x03, 0x3a, 0x00};
int pre_len = 12;
uint8_t buf[256];
EVP_PKEY *evp_key;
/* pp gets modified by d2i() */
const unsigned char* pp = (unsigned char*)buf;
if(keylen != 57 || keylen + pre_len > sizeof(buf))
return NULL; /* wrong length */
memmove(buf, pre, pre_len);
memmove(buf+pre_len, key, keylen);
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
return evp_key;
}
#endif /* USE_ED448 */
int
gldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
const EVP_MD* md)
{
EVP_MD_CTX* ctx;
ctx = EVP_MD_CTX_create();
if(!ctx)
return 0;
if(!EVP_DigestInit_ex(ctx, md, NULL) ||
!EVP_DigestUpdate(ctx, data, len) ||
!EVP_DigestFinal_ex(ctx, dest, NULL)) {
EVP_MD_CTX_destroy(ctx);
return 0;
}
EVP_MD_CTX_destroy(ctx);
return 1;
}
#endif /* HAVE_SSL */

View File

@ -0,0 +1,110 @@
/*
* keyraw.h -- raw key and signature access and conversion - OpenSSL
*
* Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
*
* See LICENSE for the license.
*
*/
/**
* \file
*
* raw key and signature access and conversion
*
* Since those functions heavily rely op cryptographic operations,
* this module is dependent on openssl.
*
*/
#ifndef GLDNS_KEYRAW_INTERNAL_H
#define GLDNS_KEYRAW_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#if GLDNS_BUILD_CONFIG_HAVE_SSL
# include <openssl/ssl.h>
# include <openssl/evp.h>
/**
* Get the PKEY id for GOST, loads GOST into openssl as a side effect.
* Only available if GOST is compiled into the library and openssl.
* \return the gost id for EVP_CTX creation.
*/
int gldns_key_EVP_load_gost_id(void);
/** Release the engine reference held for the GOST engine. */
void gldns_key_EVP_unload_gost(void);
/**
* Like gldns_key_buf2dsa, but uses raw buffer.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return a DSA * structure with the key material
*/
DSA *gldns_key_buf2dsa_raw(unsigned char* key, size_t len);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with GOST.
* \param[in] key data to convert
* \param[in] keylen length of the key data
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_gost2pkey_raw(unsigned char* key, size_t keylen);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with ECDSA.
* \param[in] key data to convert
* \param[in] keylen length of the key data
* \param[in] algo precise algorithm to initialize ECC group values.
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
/**
* Like gldns_key_buf2rsa, but uses raw buffer.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return a RSA * structure with the key material
*/
RSA *gldns_key_buf2rsa_raw(unsigned char* key, size_t len);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with ED25519.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_ed255192pkey_raw(const unsigned char* key, size_t len);
/**
* Converts a holding buffer with key material to EVP PKEY in openssl.
* Only available if ldns was compiled with ED448.
* \param[in] key the uncompressed wireformat of the key.
* \param[in] len length of key data
* \return the key or NULL on error.
*/
EVP_PKEY* gldns_ed4482pkey_raw(const unsigned char* key, size_t len);
/**
* Utility function to calculate hash using generic EVP_MD pointer.
* \param[in] data the data to hash.
* \param[in] len length of data.
* \param[out] dest the destination of the hash, must be large enough.
* \param[in] md the message digest to use.
* \return true if worked, false on failure.
*/
int gldns_digest_evp(unsigned char* data, unsigned int len,
unsigned char* dest, const EVP_MD* md);
#endif /* GLDNS_BUILD_CONFIG_HAVE_SSL */
#ifdef __cplusplus
}
#endif
#endif /* GLDNS_KEYRAW_INTERNAL_H */

View File

@ -0,0 +1,90 @@
/**
*
* /brief functions for Public Key Pinning
*
*/
/*
* Copyright (c) 2015, Daniel Kahn Gillmor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* getdns Public Key Pinning
*
* a public key pinset is a list of dicts. each dict should have a
* "digest" and a "value".
*
* "digest": a string indicating the type of digest. at the moment, we
* only support a "digest" of "sha256".
*
* "value": a binary representation of the digest provided.
*
* given a such a pinset, we should be able to validate a chain
* properly according to section 2.6 of RFC 7469.
*/
#include "config.h"
#include "debug.h"
#include <getdns/getdns.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/sha.h>
#include <openssl/x509.h>
#include <string.h>
#include "context.h"
#include "util-internal.h"
#include "pubkey-pinning-internal.h"
/* we only support sha256 at the moment. adding support for another
digest is more complex than just adding another entry here. in
particular, you'll probably need a match for a particular cert
against all supported algorithms. better to wait on doing that
until it is a better-understood problem (i.e. wait until hpkp is
updated and follow the guidance in rfc7469bis)
*/
/* b64 turns every 3 octets (or fraction thereof) into 4 octets */
#define B64_ENCODED_SHA256_LENGTH (((SHA256_DIGEST_LENGTH + 2)/3) * 4)
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size)
{
BIO *bio = NULL;
char inbuf[B64_ENCODED_SHA256_LENGTH + 1];
getdns_return_t ret = GETDNS_RETURN_GOOD;
/* openssl needs a trailing newline to base64 decode */
memcpy(inbuf, str, B64_ENCODED_SHA256_LENGTH);
inbuf[B64_ENCODED_SHA256_LENGTH] = '\n';
bio = BIO_push(BIO_new(BIO_f_base64()),
BIO_new_mem_buf(inbuf, sizeof(inbuf)));
if (BIO_read(bio, res, res_size) != (int) res_size)
ret = GETDNS_RETURN_GENERIC_ERROR;
BIO_free_all(bio);
return ret;
}
/* pubkey-pinning.c */

View File

@ -0,0 +1,42 @@
/**
*
* /brief internal functions for dealing with pubkey pinsets
*
*/
/*
* Copyright (c) 2015 ACLU
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PUBKEY_PINNING_INTERNAL_H_
#define PUBKEY_PINNING_INTERNAL_H_
#include <openssl/x509.h>
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size);
#endif
/* pubkey-pinning-internal.h */

View File

@ -0,0 +1,91 @@
/**
*
* \file tls-internal.h
* @brief getdns TLS implementation-specific items
*/
/*
* Copyright (c) 2018-2019, NLnet Labs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _GETDNS_TLS_INTERNAL_H
#define _GETDNS_TLS_INTERNAL_H
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include "getdns/getdns.h"
#ifndef HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
#define HAVE_TLS_CTX_CURVES_LIST 0
#else
#define HAVE_TLS_CTX_CURVES_LIST (HAVE_DECL_SSL_CTX_SET1_CURVES_LIST)
#endif
#ifndef HAVE_DECL_SSL_SET1_CURVES_LIST
#define HAVE_TLS_CONN_CURVES_LIST 0
#else
#define HAVE_TLS_CONN_CURVES_LIST (HAVE_DECL_SSL_SET1_CURVES_LIST)
#endif
#define GETDNS_TLS_MAX_DIGEST_LENGTH (EVP_MAX_MD_SIZE)
typedef struct sha256_pin sha256_pin_t;
typedef struct getdns_log_config getdns_log_config;
typedef struct _getdns_tls_context {
SSL_CTX* ssl;
const getdns_log_config* log;
} _getdns_tls_context;
typedef struct _getdns_tls_connection {
SSL* ssl;
const getdns_log_config* log;
#if defined(USE_DANESSL)
const char* auth_name;
sha256_pin_t* pinset;
#endif
} _getdns_tls_connection;
typedef struct _getdns_tls_session {
SSL_SESSION* ssl;
} _getdns_tls_session;
typedef struct _getdns_tls_x509
{
X509* ssl;
} _getdns_tls_x509;
typedef struct _getdns_tls_hmac
{
HMAC_CTX *ctx;
#ifndef HAVE_HMAC_CTX_NEW
HMAC_CTX ctx_space;
#endif
} _getdns_tls_hmac;
#endif /* _GETDNS_TLS_INTERNAL_H */

1278
src/openssl/tls.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -91,6 +91,7 @@ log_crypto_error(const char* str, unsigned long e)
/* buf now contains */ /* buf now contains */
/* error:[error code]:[library name]:[function name]:[reason string] */ /* error:[error code]:[library name]:[function name]:[reason string] */
log_err("%s crypto %s", str, buf); log_err("%s crypto %s", str, buf);
(void) str; /* In case log_err() does nothing. */
} }
/* return size of digest if supported, or 0 otherwise */ /* return size of digest if supported, or 0 otherwise */
@ -1351,21 +1352,21 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
#elif defined(HAVE_NETTLE) #elif defined(HAVE_NETTLE)
#include "sha.h" #include <nettle/sha.h>
#include "bignum.h" #include <nettle/bignum.h>
#include "macros.h" #include <nettle/macros.h>
#include "rsa.h" #include <nettle/rsa.h>
#include "dsa.h" #include <nettle/dsa.h>
#ifdef HAVE_NETTLE_DSA_COMPAT_H #ifdef HAVE_NETTLE_DSA_COMPAT_H
#include "dsa-compat.h" #include <nettle/dsa-compat.h>
#endif #endif
#include "asn1.h" #include <nettle/asn1.h>
#ifdef USE_ECDSA #ifdef USE_ECDSA
#include "ecdsa.h" #include <nettle/ecdsa.h>
#include "ecc-curve.h" #include <nettle/ecc-curve.h>
#endif #endif
#ifdef HAVE_NETTLE_EDDSA_H #ifdef HAVE_NETTLE_EDDSA_H
#include "eddsa.h" #include <nettle/eddsa.h>
#endif #endif
static int static int

View File

@ -0,0 +1,53 @@
#ifndef VAL_SECALGO_H_VALIDATOR
#define VAL_SECALGO_H_VALIDATOR
#define sldns_buffer gldns_buffer
#define nsec3_hash_algo_size_supported _getdns_nsec3_hash_algo_size_supported
#define secalgo_nsec3_hash _getdns_secalgo_nsec3_hash
#define secalgo_hash_sha256 _getdns_secalgo_hash_sha256
#define ds_digest_size_supported _getdns_ds_digest_size_supported
#define secalgo_ds_digest _getdns_secalgo_ds_digest
#define dnskey_algo_id_is_supported _getdns_dnskey_algo_id_is_supported
#define verify_canonrrset _getdns_verify_canonrrset
#define sec_status _getdns_sec_status
#define sec_status_secure _getdns_sec_status_secure
#define sec_status_insecure _getdns_sec_status_insecure
#define sec_status_unchecked _getdns_sec_status_unchecked
#define sec_status_bogus _getdns_sec_status_bogus
#define fake_sha1 _getdns_fake_sha1
#define fake_dsa _getdns_fake_dsa
#define NSEC3_HASH_SHA1 0x01
#define LDNS_SHA1 GLDNS_SHA1
#define LDNS_SHA256 GLDNS_SHA256
#define LDNS_SHA384 GLDNS_SHA384
#define LDNS_HASH_GOST GLDNS_HASH_GOST
#define LDNS_RSAMD5 GLDNS_RSAMD5
#define LDNS_DSA GLDNS_DSA
#define LDNS_DSA_NSEC3 GLDNS_DSA_NSEC3
#define LDNS_RSASHA1 GLDNS_RSASHA1
#define LDNS_RSASHA1_NSEC3 GLDNS_RSASHA1_NSEC3
#define LDNS_RSASHA256 GLDNS_RSASHA256
#define LDNS_RSASHA512 GLDNS_RSASHA512
#define LDNS_ECDSAP256SHA256 GLDNS_ECDSAP256SHA256
#define LDNS_ECDSAP384SHA384 GLDNS_ECDSAP384SHA384
#define LDNS_ECC_GOST GLDNS_ECC_GOST
#define LDNS_ED25519 GLDNS_ED25519
#define LDNS_ED448 GLDNS_ED448
#define sldns_ed255192pkey_raw gldns_ed255192pkey_raw
#define sldns_ed4482pkey_raw gldns_ed4482pkey_raw
#define sldns_key_EVP_load_gost_id gldns_key_EVP_load_gost_id
#define sldns_digest_evp gldns_digest_evp
#define sldns_key_buf2dsa_raw gldns_key_buf2dsa_raw
#define sldns_key_buf2rsa_raw gldns_key_buf2rsa_raw
#define sldns_gost2pkey_raw gldns_gost2pkey_raw
#define sldns_ecdsa2pkey_raw gldns_ecdsa2pkey_raw
#define sldns_buffer_begin gldns_buffer_begin
#define sldns_buffer_limit gldns_buffer_limit
#include "util/val_secalgo.h"
#endif

View File

@ -48,18 +48,13 @@
#include "config.h" #include "config.h"
#include "debug.h" #include "debug.h"
#include <getdns/getdns.h> #include <getdns/getdns.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/sha.h>
#include <openssl/x509.h>
#include <string.h> #include <string.h>
#include "context.h" #include "context.h"
#include "util-internal.h" #include "util-internal.h"
#include "gldns/parseutil.h" #include "gldns/parseutil.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #include "pubkey-pinning.h"
#define X509_STORE_CTX_get0_untrusted(store) store->untrusted #include "pubkey-pinning-internal.h"
#endif
/* we only support sha256 at the moment. adding support for another /* we only support sha256 at the moment. adding support for another
digest is more complex than just adding another entry here. in digest is more complex than just adding another entry here. in
@ -74,12 +69,10 @@ static const getdns_bindata sha256 = {
.data = (uint8_t*)"sha256" .data = (uint8_t*)"sha256"
}; };
#define PIN_PREFIX "pin-sha256=\"" #define PIN_PREFIX "pin-sha256=\""
#define PIN_PREFIX_LENGTH (sizeof(PIN_PREFIX) - 1) #define PIN_PREFIX_LENGTH (sizeof(PIN_PREFIX) - 1)
/* b64 turns every 3 octets (or fraction thereof) into 4 octets */ /* b64 turns every 3 octets (or fraction thereof) into 4 octets */
#define B64_ENCODED_SHA256_LENGTH (((SHA256_DIGEST_LENGTH + 2)/3) * 4) #define B64_ENCODED_SHA256_LENGTH (((SHA256_DIGEST_LENGTH + 2)/3) * 4)
/* convert an HPKP-style pin description to an appropriate getdns data /* convert an HPKP-style pin description to an appropriate getdns data
structure. An example string is: (with the quotes, without any structure. An example string is: (with the quotes, without any
leading or trailing whitespace): leading or trailing whitespace):
@ -96,10 +89,8 @@ static const getdns_bindata sha256 = {
getdns_dict *getdns_pubkey_pin_create_from_string( getdns_dict *getdns_pubkey_pin_create_from_string(
const getdns_context *context, const char *str) const getdns_context *context, const char *str)
{ {
BIO *bio = NULL;
size_t i; size_t i;
uint8_t buf[SHA256_DIGEST_LENGTH]; uint8_t buf[SHA256_DIGEST_LENGTH];
char inbuf[B64_ENCODED_SHA256_LENGTH + 1];
getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf }; getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf };
getdns_dict *out = NULL; getdns_dict *out = NULL;
@ -119,14 +110,8 @@ getdns_dict *getdns_pubkey_pin_create_from_string(
if (str[i++] != '\0') if (str[i++] != '\0')
return NULL; return NULL;
/* openssl needs a trailing newline to base64 decode */ if (_getdns_decode_base64(str + PIN_PREFIX_LENGTH, buf, sizeof(buf)) != GETDNS_RETURN_GOOD)
memcpy(inbuf, str + PIN_PREFIX_LENGTH, B64_ENCODED_SHA256_LENGTH); goto fail;
inbuf[B64_ENCODED_SHA256_LENGTH] = '\n';
bio = BIO_push(BIO_new(BIO_f_base64()),
BIO_new_mem_buf(inbuf, sizeof(inbuf)));
if (BIO_read(bio, buf, sizeof(buf)) != sizeof(buf))
goto fail;
if (context) if (context)
out = getdns_dict_create_with_context(context); out = getdns_dict_create_with_context(context);
@ -141,12 +126,10 @@ getdns_dict *getdns_pubkey_pin_create_from_string(
return out; return out;
fail: fail:
BIO_free_all(bio);
getdns_dict_destroy(out); getdns_dict_destroy(out);
return NULL; return NULL;
} }
/* Test whether a given pinset is reasonable, including: /* Test whether a given pinset is reasonable, including:
* is it well-formed? * is it well-formed?
@ -306,261 +289,3 @@ _getdns_get_pubkey_pinset_list(const getdns_context *ctx,
getdns_list_destroy(out); getdns_list_destroy(out);
return r; return r;
} }
/* this should only happen once ever in the life of the library. it's
used to associate a getdns_context_t with an SSL_CTX, to be able to
do custom verification.
see doc/HOWTO/proxy_certificates.txt as an example
*/
static int
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
_get_ssl_getdns_upstream_idx(void)
#else
_get_ssl_getdns_upstream_idx(X509_STORE *store)
#endif
{
static volatile int idx = -1;
if (idx < 0) {
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
#else
X509_STORE_lock(store);
#endif
if (idx < 0)
idx = SSL_get_ex_new_index(0, "associated getdns upstream",
NULL,NULL,NULL);
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
#else
X509_STORE_unlock(store);
#endif
}
return idx;
}
getdns_upstream*
_getdns_upstream_from_x509_store(X509_STORE_CTX *store)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
int uidx = _get_ssl_getdns_upstream_idx();
#else
int uidx = _get_ssl_getdns_upstream_idx(X509_STORE_CTX_get0_store(store));
#endif
int sslidx = SSL_get_ex_data_X509_STORE_CTX_idx();
const SSL *ssl;
/* all *_get_ex_data() should return NULL on failure anyway */
ssl = X509_STORE_CTX_get_ex_data(store, sslidx);
if (ssl)
return (getdns_upstream*) SSL_get_ex_data(ssl, uidx);
else
return NULL;
/* TODO: if we want more details about errors somehow, we
* might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
}
getdns_return_t
_getdns_associate_upstream_with_SSL(SSL *ssl,
getdns_upstream *upstream)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
int uidx = _get_ssl_getdns_upstream_idx();
#else
int uidx = _get_ssl_getdns_upstream_idx(SSL_CTX_get_cert_store(SSL_get_SSL_CTX(ssl)));
#endif
if (SSL_set_ex_data(ssl, uidx, upstream))
return GETDNS_RETURN_GOOD;
else
return GETDNS_RETURN_GENERIC_ERROR;
/* TODO: if we want more details about errors somehow, we
* might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
}
getdns_return_t
_getdns_verify_pinset_match(const getdns_upstream *upstream,
const sha256_pin_t *pinset, X509_STORE_CTX *store)
{
X509 *x, *prev = NULL;
char x_name_spc[1024], *x_name, prev_name_spc[1024];
int i, len;
unsigned char raw[4096];
unsigned char *next;
unsigned char buf[sizeof(pinset->pin)];
const sha256_pin_t *p;
assert(pinset);
assert(store);
/* start at the base of the chain (the end-entity cert) and
* make sure that some valid element of the chain does match
* the pinset. */
/* Testing with OpenSSL 1.0.1e-1 on debian indicates that
* store->untrusted holds the chain offered by the server in
* the order that the server offers it. If the server offers
* bogus certificates (that is, matching and valid certs that
* belong to private keys that the server does not control),
* the the verification will succeed (including this pinset
* check), but the handshake will fail outside of this
* verification. */
/* TODO: how do we handle raw public keys? */
for ( i = 0
; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store))
; i++, prev = x) {
x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i);
x_name = NULL;
if (upstream->upstreams
&& _getdns_check_log(&upstream->upstreams->log,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG)) {
x_name = X509_NAME_oneline( X509_get_subject_name(x)
, x_name_spc
, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG
, "%-40s : Verifying pinsets with cert: %d %s\n"
, upstream->addr_str, i, x_name);
}
if (i > 0) {
/* we ensure that "prev" is signed by "x" */
EVP_PKEY *pkey = X509_get_pubkey(x);
int verified;
if (!pkey) {
if (!upstream->upstreams
|| !_getdns_check_log(
&upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_ERR
))
return GETDNS_RETURN_GENERIC_ERROR;
if (!x_name)
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%-40s : Could not get pubkey from cert "
"cert: %d %s\n"
, upstream->addr_str, i, x_name);
return GETDNS_RETURN_GENERIC_ERROR;
}
verified = X509_verify(prev, pkey);
EVP_PKEY_free(pkey);
if (!verified) {
if (!upstream->upstreams
|| !_getdns_check_log(
&upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_ERR
))
return GETDNS_RETURN_GENERIC_ERROR;
if (!x_name)
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR
, "%-40s : Cert: %d %swas not signed "
"by cert %d %s\n", upstream->addr_str
, i - 1
, X509_NAME_oneline(
X509_get_subject_name(prev)
, prev_name_spc
, sizeof(prev_name_spc) )
, i, x_name);
return GETDNS_RETURN_GENERIC_ERROR;
}
}
/* digest the cert with sha256 */
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
if (len > (int)sizeof(raw)) {
if (!upstream->upstreams
|| !_getdns_check_log( &upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_WARNING ))
continue;
if (!x_name)
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING
, "%-40s : Skipping cert %d %s, because pubkey is "
"larger than buffer size (%"PRIsz" octets)\n"
, upstream->addr_str, i, x_name, sizeof(raw));
continue;
}
next = raw;
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
if (next - raw != len) {
if (!upstream->upstreams
|| !_getdns_check_log( &upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_WARNING ))
continue;
if (!x_name)
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_WARNING
, "%-40s : Skipping cert %d %s, because pubkey si"
"ze %"PRIsz" differs from earlier reported %d\n"
, upstream->addr_str, i, x_name, next - raw, len);
continue;
}
SHA256(raw, len, buf);
/* compare it */
for (p = pinset; p; p = p->next) {
char pin_str[1024];
if (x_name) /* only when debugging */
gldns_b64_ntop( p->pin , sizeof(p->pin)
, pin_str, sizeof(pin_str) );
if (0 == memcmp(buf, p->pin, sizeof(p->pin))) {
if (!upstream->upstreams
|| !_getdns_check_log(
&upstream->upstreams->log
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_INFO))
return GETDNS_RETURN_GOOD;
if (!x_name) {
x_name = X509_NAME_oneline(
X509_get_subject_name(x)
, x_name_spc, sizeof(x_name_spc));
gldns_b64_ntop( p->pin , sizeof(p->pin)
, pin_str
, sizeof(pin_str) );
}
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS
, GETDNS_LOG_INFO
, "%-40s : Pubkey of cert %d %s matched "
"pin %s\n", upstream->addr_str
, i, x_name, pin_str);
return GETDNS_RETURN_GOOD;
}
_getdns_upstream_log( upstream
, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG
, "%-40s : Pubkey of cert %d %s did not match"
" pin %s\n", upstream->addr_str
, i, x_name, pin_str);
}
}
return GETDNS_RETURN_GENERIC_ERROR;
}
/* pubkey-pinning.c */

View File

@ -1,6 +1,6 @@
/** /**
* *
* /brief internal functions for dealing with pubkey pinsets * /brief functions for dealing with pubkey pinsets
* *
*/ */
@ -34,6 +34,10 @@
#ifndef PUBKEY_PINNING_H_ #ifndef PUBKEY_PINNING_H_
#define PUBKEY_PINNING_H_ #define PUBKEY_PINNING_H_
/* getdns_pubkey_pin_create_from_string() is implemented in pubkey-pinning.c */
#include "getdns/getdns_extra.h"
#include "tls.h"
/* create and populate a pinset linked list from a getdns_list pinset */ /* create and populate a pinset linked list from a getdns_list pinset */
getdns_return_t getdns_return_t
@ -48,21 +52,5 @@ _getdns_get_pubkey_pinset_list(const getdns_context *ctx,
const sha256_pin_t *pinset_in, const sha256_pin_t *pinset_in,
getdns_list **pinset_list); getdns_list **pinset_list);
/* internal functions for associating X.509 verification processes in
* OpenSSL with getdns_upstream objects. */
getdns_upstream*
_getdns_upstream_from_x509_store(X509_STORE_CTX *store);
getdns_return_t
_getdns_associate_upstream_with_SSL(SSL *ssl,
getdns_upstream *upstream);
getdns_return_t
_getdns_verify_pinset_match(const getdns_upstream *upstream,
const sha256_pin_t *pinset, X509_STORE_CTX *store);
#endif #endif
/* pubkey-pinning.h */ /* pubkey-pinning.h */

View File

@ -44,6 +44,7 @@
#include "debug.h" #include "debug.h"
#include "convert.h" #include "convert.h"
#include "general.h" #include "general.h"
#include "tls.h"
/* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256 /* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256
* TSIG type (uint16_t) : 2 * TSIG type (uint16_t) : 2
@ -54,15 +55,15 @@
* Time Signed (uint48_t) : 6 * Time Signed (uint48_t) : 6
* Fudge (uint16_t) : 2 * Fudge (uint16_t) : 2
* Mac Size (uint16_t) : 2 * Mac Size (uint16_t) : 2
* Mac (variable) : EVP_MAX_MD_SIZE * Mac (variable) : GETDNS_TLS_MAX_DIGEST_LENGTH
* Original Id (uint16_t) : 2 * Original Id (uint16_t) : 2
* Error (uint16_t) : 2 * Error (uint16_t) : 2
* Other Len (uint16_t) : 2 * Other Len (uint16_t) : 2
* Other Data (nothing) : 0 * Other Data (nothing) : 0
* ---- + * ---- +
* 538 + EVP_MAX_MD_SIZE * 538 + GETDNS_TLS_MAX_DIGEST_LENGTH
*/ */
#define MAXIMUM_TSIG_SPACE (538 + EVP_MAX_MD_SIZE) #define MAXIMUM_TSIG_SPACE (538 + GETDNS_TLS_MAX_DIGEST_LENGTH)
getdns_dict dnssec_ok_checking_disabled_spc = { getdns_dict dnssec_ok_checking_disabled_spc = {
{ RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp }, { RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
@ -125,7 +126,7 @@ network_req_cleanup(getdns_network_req *net_req)
GETDNS_FREE(net_req->owner->my_mf, net_req->response); GETDNS_FREE(net_req->owner->my_mf, net_req->response);
if (net_req->debug_tls_peer_cert.size && if (net_req->debug_tls_peer_cert.size &&
net_req->debug_tls_peer_cert.data) net_req->debug_tls_peer_cert.data)
OPENSSL_free(net_req->debug_tls_peer_cert.data); GETDNS_FREE(net_req->owner->my_mf, net_req->debug_tls_peer_cert.data);
} }
static uint8_t * static uint8_t *
@ -401,9 +402,8 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
gldns_buffer gbuf; gldns_buffer gbuf;
uint16_t arcount; uint16_t arcount;
const getdns_tsig_info *tsig_info; const getdns_tsig_info *tsig_info;
uint8_t md_buf[EVP_MAX_MD_SIZE]; unsigned char* md_buf;
unsigned int md_len = EVP_MAX_MD_SIZE; size_t md_len;
const EVP_MD *digester;
/* Should only be called when in stub mode */ /* Should only be called when in stub mode */
assert(req->query); assert(req->query);
@ -436,31 +436,9 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
gldns_buffer_write_u16(&gbuf, 0); /* Error */ gldns_buffer_write_u16(&gbuf, 0); /* Error */
gldns_buffer_write_u16(&gbuf, 0); /* Other len */ gldns_buffer_write_u16(&gbuf, 0); /* Other len */
switch (upstream->tsig_alg) { md_buf = _getdns_tls_hmac_hash(&req->owner->my_mf, upstream->tsig_alg, upstream->tsig_key, upstream->tsig_size, (void *)req->query, gldns_buffer_current(&gbuf) - req->query, &md_len);
#ifdef HAVE_EVP_MD5 if (!md_buf)
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break; return req->response - req->query;
#endif
#ifdef HAVE_EVP_SHA1
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
#endif
#ifdef HAVE_EVP_SHA224
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
#endif
#ifdef HAVE_EVP_SHA256
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
#endif
#ifdef HAVE_EVP_SHA384
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
#endif
#ifdef HAVE_EVP_SHA512
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
#endif
default : return req->response - req->query;
}
(void) HMAC(digester, upstream->tsig_key, upstream->tsig_size,
(void *)req->query, gldns_buffer_current(&gbuf) - req->query,
md_buf, &md_len);
gldns_buffer_rewind(&gbuf); gldns_buffer_rewind(&gbuf);
gldns_buffer_write(&gbuf, gldns_buffer_write(&gbuf,
@ -480,6 +458,8 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
gldns_buffer_write_u16(&gbuf, 0); /* Error */ gldns_buffer_write_u16(&gbuf, 0); /* Error */
gldns_buffer_write_u16(&gbuf, 0); /* Other len */ gldns_buffer_write_u16(&gbuf, 0); /* Other len */
GETDNS_FREE(req->owner->my_mf, md_buf);
if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf)) if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
return req->response - req->query; return req->response - req->query;
@ -509,14 +489,10 @@ _getdns_network_validate_tsig(getdns_network_req *req)
const uint8_t *response_mac; const uint8_t *response_mac;
uint16_t response_mac_len; uint16_t response_mac_len;
uint8_t other_len; uint8_t other_len;
uint8_t result_mac[EVP_MAX_MD_SIZE]; unsigned char *result_mac;
unsigned int result_mac_len = EVP_MAX_MD_SIZE; size_t result_mac_len;
uint16_t original_id; uint16_t original_id;
const EVP_MD *digester; _getdns_tls_hmac *hmac;
HMAC_CTX *ctx;
#ifndef HAVE_HMAC_CTX_NEW
HMAC_CTX ctx_space;
#endif
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__); DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__);
for ( rr = _getdns_rr_iter_init(&rr_spc, req->query, for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
@ -623,39 +599,16 @@ _getdns_network_validate_tsig(getdns_network_req *req)
gldns_read_uint16(req->response + 10) - 1); gldns_read_uint16(req->response + 10) - 1);
gldns_write_uint16(req->response, original_id); gldns_write_uint16(req->response, original_id);
switch (req->upstream->tsig_alg) { hmac = _getdns_tls_hmac_new(&req->owner->my_mf, req->upstream->tsig_alg, req->upstream->tsig_key, req->upstream->tsig_size);
#ifdef HAVE_EVP_MD5 if (!hmac)
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break; return;
#endif
#ifdef HAVE_EVP_SHA1 _getdns_tls_hmac_add(hmac, request_mac - 2, request_mac_len + 2);
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break; _getdns_tls_hmac_add(hmac, req->response, rr->pos - req->response);
#endif _getdns_tls_hmac_add(hmac, tsig_vars, gldns_buffer_position(&gbuf));
#ifdef HAVE_EVP_SHA224 result_mac = _getdns_tls_hmac_end(&req->owner->my_mf, hmac, &result_mac_len);
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break; if (!result_mac)
#endif return;
#ifdef HAVE_EVP_SHA256
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
#endif
#ifdef HAVE_EVP_SHA384
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
#endif
#ifdef HAVE_EVP_SHA512
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
#endif
default : return;
}
#ifdef HAVE_HMAC_CTX_NEW
ctx = HMAC_CTX_new();
#else
ctx = &ctx_space;
HMAC_CTX_init(ctx);
#endif
(void) HMAC_Init_ex(ctx, req->upstream->tsig_key,
req->upstream->tsig_size, digester, NULL);
(void) HMAC_Update(ctx, request_mac - 2, request_mac_len + 2);
(void) HMAC_Update(ctx, req->response, rr->pos - req->response);
(void) HMAC_Update(ctx, tsig_vars, gldns_buffer_position(&gbuf));
HMAC_Final(ctx, result_mac, &result_mac_len);
DEBUG_STUB("%s %-35s: Result MAC length: %d\n", DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
STUB_DEBUG_TSIG, __FUNC__, (int)(result_mac_len)); STUB_DEBUG_TSIG, __FUNC__, (int)(result_mac_len));
@ -663,11 +616,8 @@ _getdns_network_validate_tsig(getdns_network_req *req)
memcmp(result_mac, response_mac, result_mac_len) == 0) memcmp(result_mac, response_mac, result_mac_len) == 0)
req->tsig_status = GETDNS_DNSSEC_SECURE; req->tsig_status = GETDNS_DNSSEC_SECURE;
#ifdef HAVE_HMAC_CTX_FREE GETDNS_FREE(req->owner->my_mf, result_mac);
HMAC_CTX_free(ctx);
#else
HMAC_CTX_cleanup(ctx);
#endif
gldns_write_uint16(req->response, gldns_read_uint16(req->query)); gldns_write_uint16(req->response, gldns_read_uint16(req->query));
gldns_write_uint16(req->response + 10, gldns_write_uint16(req->response + 10,
gldns_read_uint16(req->response + 10) + 1); gldns_read_uint16(req->response + 10) + 1);

View File

@ -39,9 +39,6 @@
#define INTERCEPT_COM_DS 0 #define INTERCEPT_COM_DS 0
#include "debug.h" #include "debug.h"
#include <openssl/err.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
#include <fcntl.h> #include <fcntl.h>
#include "stub.h" #include "stub.h"
#include "gldns/gbuffer.h" #include "gldns/gbuffer.h"
@ -55,10 +52,6 @@
#include "platform.h" #include "platform.h"
#include "general.h" #include "general.h"
#include "pubkey-pinning.h" #include "pubkey-pinning.h"
#ifdef USE_DANESSL
# include "ssl_dane/danessl.h"
#endif
#include "const-info.h"
/* WSA TODO: /* WSA TODO:
* STUB_TCP_RETRY added to deal with edge triggered event loops (versus * STUB_TCP_RETRY added to deal with edge triggered event loops (versus
@ -128,10 +121,8 @@ rollover_secret()
static void static void
calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie) calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie)
{ {
const EVP_MD *md; unsigned char md_value[GETDNS_TLS_MAX_DIGEST_LENGTH];
EVP_MD_CTX *mdctx; size_t md_len;
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
size_t i; size_t i;
sa_family_t af = upstream->addr.ss_family; sa_family_t af = upstream->addr.ss_family;
void *sa_addr = ((struct sockaddr*)&upstream->addr)->sa_data; void *sa_addr = ((struct sockaddr*)&upstream->addr)->sa_data;
@ -139,13 +130,7 @@ calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie)
: af == AF_INET ? sizeof(struct sockaddr_in) : af == AF_INET ? sizeof(struct sockaddr_in)
: 0 ) - sizeof(sa_family_t); : 0 ) - sizeof(sa_family_t);
md = EVP_sha256(); _getdns_tls_cookie_sha256(secret, sa_addr, addr_len, md_value, &md_len);
mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, &secret, sizeof(secret));
EVP_DigestUpdate(mdctx, sa_addr, addr_len);
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_destroy(mdctx);
(void) memset(cookie, 0, 8); (void) memset(cookie, 0, 8);
for (i = 0; i < md_len; i++) for (i = 0; i < md_len; i++)
@ -830,194 +815,46 @@ tls_requested(getdns_network_req *netreq)
1 : 0; 1 : 0;
} }
static _getdns_tls_connection*
#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;
getdns_return_t pinset_ret = GETDNS_RETURN_GOOD;
upstream = _getdns_upstream_from_x509_store(ctx);
if (!upstream)
return 0;
int err = X509_STORE_CTX_get_error(ctx);
# if defined(STUB_DEBUG) && STUB_DEBUG
DEBUG_STUB("%s %-35s: FD: %d Verify result: (%d) \"%s\"\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err,
X509_verify_cert_error_string(err));
# endif
if (!preverify_ok && !upstream->tls_fallback_ok)
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : Verify failed: TLS - *Failure* - (%d) \"%s\"\n",
upstream->addr_str, err,
X509_verify_cert_error_string(err));
/* No need to deal with hostname authentication, since this will be
* dealt with in the DANE preprocessor paths.
*/
/* Deal with the pinset validation */
if (upstream->tls_pubkey_pinset)
pinset_ret = _getdns_verify_pinset_match(
upstream, upstream->tls_pubkey_pinset, ctx);
if (pinset_ret != GETDNS_RETURN_GOOD) {
DEBUG_STUB("%s %-35s: FD: %d, WARNING: Pinset validation failure!\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
preverify_ok = 0;
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
if (upstream->tls_fallback_ok)
DEBUG_STUB("%s %-35s: FD: %d, WARNING: Proceeding even though pinset validation failed!\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
else
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : Conn failed: TLS - *Failure* - Pinset validation failure\n",
upstream->addr_str);
}
/* If nothing has failed yet and we had credentials, we have successfully authenticated*/
if (preverify_ok == 0)
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
else if (upstream->tls_auth_state == GETDNS_AUTH_NONE &&
(upstream->tls_pubkey_pinset || upstream->tls_auth_name[0]))
upstream->tls_auth_state = GETDNS_AUTH_OK;
/* If fallback is allowed, proceed regardless of what the auth error is
(might not be hostname or pinset related) */
return (upstream->tls_fallback_ok) ? 1 : preverify_ok;
}
#endif /* #else defined(HAVE_SSL_DANE_ENABLE) || defined(USE_DANESSL) */
static SSL*
tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
{ {
/* Create SSL instance */ /* Create SSL instance and connect with a file descriptor */
getdns_context *context = dnsreq->context; getdns_context *context = dnsreq->context;
if (context->tls_ctx == NULL) if (context->tls_ctx == NULL)
return NULL; return NULL;
SSL* ssl = SSL_new(context->tls_ctx); _getdns_tls_connection* tls = _getdns_tls_connection_new(&context->my_mf, context->tls_ctx, fd, &upstream->upstreams->log);
if(!ssl) if(!tls)
return NULL; return NULL;
/* Connect the SSL object with a file descriptor */
if(!SSL_set_fd(ssl,fd)) { getdns_return_t r = GETDNS_RETURN_GOOD;
SSL_free(ssl);
if (upstream->tls_curves_list)
r = _getdns_tls_connection_set_curves_list(tls, upstream->tls_curves_list);
if (!r && upstream->tls_ciphersuites)
r = _getdns_tls_connection_set_cipher_suites(tls, upstream->tls_ciphersuites);
if (!r)
r = _getdns_tls_connection_set_min_max_tls_version(tls, upstream->tls_min_version, upstream->tls_max_version);
if (!r)
{
if (upstream->tls_fallback_ok)
r = _getdns_tls_connection_set_cipher_list(tls, NULL);
else if (upstream->tls_cipher_list)
r = _getdns_tls_connection_set_cipher_list(tls, upstream->tls_cipher_list);
}
if (r) {
_getdns_tls_connection_free(&upstream->upstreams->mf, tls);
upstream->tls_auth_state = GETDNS_AUTH_NONE;
return NULL; return NULL;
} }
#if defined(HAVE_DECL_SSL_SET1_CURVES_LIST) && HAVE_DECL_SSL_SET1_CURVES_LIST
if (upstream->tls_curves_list if (upstream->tls_fallback_ok) {
&& !SSL_set1_curves_list(ssl, upstream->tls_curves_list)) { DEBUG_STUB("%s %-35s: WARNING: Using Opportunistic TLS (fallback allowed)!\n",
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, STUB_DEBUG_SETUP_TLS, __FUNC__);
GETDNS_LOG_ERR, "%-40s : Error configuring tls_curves_list " } else {
"\"%s\"\n", upstream->addr_str, upstream->tls_curves_list); DEBUG_STUB("%s %-35s: Using Strict TLS \n",
SSL_free(ssl); STUB_DEBUG_SETUP_TLS, __FUNC__);
return NULL;
}
#else
if (upstream->tls_curves_list) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : tls_curves_list not supported "
"in tls library\n", upstream->addr_str);
SSL_free(ssl);
return NULL;
}
#endif
#ifdef HAVE_SSL_SET_CIPHERSUITES
if (upstream->tls_ciphersuites &&
!SSL_set_ciphersuites(ssl, upstream->tls_ciphersuites)) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring tls_ciphersuites "
"\"%s\"\n", upstream->addr_str, upstream->tls_ciphersuites);
}
#else
if (upstream->tls_ciphersuites) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : tls_ciphersuites not "
"supported in tls library\n", upstream->addr_str);
SSL_free(ssl);
return NULL;
}
#endif
#if defined(HAVE_DECL_SSL_SET_MIN_PROTO_VERSION) \
&& HAVE_DECL_SSL_SET_MIN_PROTO_VERSION
if (upstream->tls_min_version && !SSL_set_min_proto_version(ssl,
_getdns_tls_version2openssl_version(upstream->tls_min_version))) {
struct const_info *ci =
_getdns_get_const_info(upstream->tls_min_version);
if (ci && *ci->name)
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring "
"tls_min_version \"%s\"\n", upstream->addr_str,
ci->name);
else
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring "
"tls_min_version \"%d\"\n", upstream->addr_str,
upstream->tls_min_version);
}
if (upstream->tls_max_version && !SSL_set_max_proto_version(ssl,
_getdns_tls_version2openssl_version(upstream->tls_max_version))) {
struct const_info *ci =
_getdns_get_const_info(upstream->tls_max_version);
if (ci && *ci->name)
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring "
"tls_max_version \"%s\"\n", upstream->addr_str,
ci->name);
else
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : Error configuring "
"tls_max_version \"%d\"\n", upstream->addr_str,
upstream->tls_max_version);
}
#else
if (upstream->tls_min_version) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : tls_min_version not "
"supported in tls library\n", upstream->addr_str);
SSL_free(ssl);
return NULL;
}
if (upstream->tls_max_version) {
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
GETDNS_LOG_ERR, "%-40s : tls_max_version not "
"supported in tls library\n", upstream->addr_str);
SSL_free(ssl);
return NULL;
}
#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);
return NULL;
} }
/* NOTE: this code will fallback on a given upstream, without trying /* NOTE: this code will fallback on a given upstream, without trying
@ -1030,29 +867,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
/*Request certificate for the auth_name*/ /*Request certificate for the auth_name*/
DEBUG_STUB("%s %-35s: Hostname verification requested for: %s\n", DEBUG_STUB("%s %-35s: Hostname verification requested for: %s\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->tls_auth_name); STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->tls_auth_name);
SSL_set_tlsext_host_name(ssl, upstream->tls_auth_name); _getdns_tls_connection_setup_hostname_auth(tls, upstream->tls_auth_name);
#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);
#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__);
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : ERROR: Hostname Authentication not available from TLS library (check library version)\n",
upstream->addr_str);
upstream->tls_hs_state = GETDNS_HS_FAILED;
SSL_free(ssl);
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
return NULL;
}
#endif
/* Allow fallback to opportunistic if settings permit it*/ /* Allow fallback to opportunistic if settings permit it*/
if (dnsreq->netreqs[0]->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED) if (dnsreq->netreqs[0]->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
upstream->tls_fallback_ok = 1; upstream->tls_fallback_ok = 1;
@ -1070,7 +885,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
"%-40s : Verify fail: *CONFIG ERROR* - No auth name or pinset provided for this upstream for Strict TLS authentication\n", "%-40s : Verify fail: *CONFIG ERROR* - No auth name or pinset provided for this upstream for Strict TLS authentication\n",
upstream->addr_str); upstream->addr_str);
upstream->tls_hs_state = GETDNS_HS_FAILED; upstream->tls_hs_state = GETDNS_HS_FAILED;
SSL_free(ssl); _getdns_tls_connection_free(&upstream->upstreams->mf, tls);
upstream->tls_auth_state = GETDNS_AUTH_FAILED; upstream->tls_auth_state = GETDNS_AUTH_FAILED;
return NULL; return NULL;
} }
@ -1081,89 +896,8 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
upstream->tls_fallback_ok = 1; upstream->tls_fallback_ok = 1;
} }
} }
if (upstream->tls_fallback_ok) {
SSL_set_cipher_list(ssl, "DEFAULT");
DEBUG_STUB("%s %-35s: WARNING: Using Oppotunistic TLS (fallback allowed)!\n",
STUB_DEBUG_SETUP_TLS, __FUNC__);
} else {
if (upstream->tls_cipher_list &&
!SSL_set_cipher_list(ssl, upstream->tls_cipher_list))
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : Error configuring cipher_list\"%s\"\n",
upstream->addr_str, upstream->tls_cipher_list);
DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS, _getdns_tls_connection_set_host_pinset(tls, upstream->tls_auth_name, upstream->tls_pubkey_pinset);
__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);
/* Session resumption. There are trade-offs here. Want to do it when /* Session resumption. There are trade-offs here. Want to do it when
possible only if we have the right type of connection. Note a change possible only if we have the right type of connection. Note a change
@ -1172,12 +906,12 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
if ((upstream->tls_fallback_ok == 0 && if ((upstream->tls_fallback_ok == 0 &&
upstream->last_tls_auth_state == GETDNS_AUTH_OK) || upstream->last_tls_auth_state == GETDNS_AUTH_OK) ||
upstream->tls_fallback_ok == 1) { upstream->tls_fallback_ok == 1) {
SSL_set_session(ssl, upstream->tls_session); _getdns_tls_connection_set_session(tls, upstream->tls_session);
DEBUG_STUB("%s %-35s: Attempting session re-use\n", STUB_DEBUG_SETUP_TLS, DEBUG_STUB("%s %-35s: Attempting session re-use\n", STUB_DEBUG_SETUP_TLS,
__FUNC__); __FUNC__);
} }
} }
return ssl; return tls;
} }
static int static int
@ -1186,13 +920,10 @@ tls_do_handshake(getdns_upstream *upstream)
DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SETUP_TLS, DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SETUP_TLS,
__FUNC__, upstream->fd); __FUNC__, upstream->fd);
int r; int r;
int want; while ((r = _getdns_tls_connection_do_handshake(upstream->tls_obj)) != GETDNS_RETURN_GOOD)
ERR_clear_error();
while ((r = SSL_do_handshake(upstream->tls_obj)) != 1)
{ {
want = SSL_get_error(upstream->tls_obj, r); switch (r) {
switch (want) { case GETDNS_RETURN_TLS_WANT_READ:
case SSL_ERROR_WANT_READ:
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->event.read_cb = upstream_read_cb; upstream->event.read_cb = upstream_read_cb;
upstream->event.write_cb = NULL; upstream->event.write_cb = NULL;
@ -1200,7 +931,7 @@ tls_do_handshake(getdns_upstream *upstream)
upstream->fd, TIMEOUT_TLS, &upstream->event); upstream->fd, TIMEOUT_TLS, &upstream->event);
upstream->tls_hs_state = GETDNS_HS_READ; upstream->tls_hs_state = GETDNS_HS_READ;
return STUB_TCP_RETRY; return STUB_TCP_RETRY;
case SSL_ERROR_WANT_WRITE: case GETDNS_RETURN_TLS_WANT_WRITE:
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->event.read_cb = NULL; upstream->event.read_cb = NULL;
upstream->event.write_cb = upstream_write_cb; upstream->event.write_cb = upstream_write_cb;
@ -1216,33 +947,13 @@ tls_do_handshake(getdns_upstream *upstream)
} }
} }
/* A re-used session is not verified so need to fix up state in that case */ /* A re-used session is not verified so need to fix up state in that case */
if (SSL_session_reused(upstream->tls_obj)) if (!_getdns_tls_connection_is_session_reused(upstream->tls_obj))
upstream->tls_auth_state = upstream->last_tls_auth_state; upstream->tls_auth_state = upstream->last_tls_auth_state;
else if (upstream->tls_pubkey_pinset || upstream->tls_auth_name[0]) { else if (upstream->tls_pubkey_pinset || upstream->tls_auth_name[0]) {
X509 *peer_cert = SSL_get_peer_certificate(upstream->tls_obj); _getdns_tls_x509* peer_cert = _getdns_tls_connection_get_peer_certificate(&upstream->upstreams->mf, 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, if (!peer_cert) {
* we need to verify auth_name explicitly (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 explicitly.
*/
#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_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_UPSTREAM_STATS,
( upstream->tls_fallback_ok ( upstream->tls_fallback_ok
@ -1253,71 +964,44 @@ tls_do_handshake(getdns_upstream *upstream)
( upstream->tls_fallback_ok ( upstream->tls_fallback_ok
? "Tolerated because of Opportunistic profile" ? "Tolerated because of Opportunistic profile"
: "*Failure*" )); : "*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; upstream->tls_auth_state = GETDNS_AUTH_FAILED;
} } else {
#endif long verify_errno;
else const char* verify_errmsg;
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : Verify passed : TLS\n",
upstream->addr_str);
X509_free(peer_cert); if (_getdns_tls_connection_certificate_verify(upstream->tls_obj, &verify_errno, &verify_errmsg)) {
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
if (verify_errno != 0) {
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS,
( upstream->tls_fallback_ok
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
"%-40s : Verify failed : TLS - %s - "
"(%ld) \"%s\"\n", upstream->addr_str,
( upstream->tls_fallback_ok
? "Tolerated because of Opportunistic profile"
: "*Failure*" ),
verify_errno, verify_errmsg);
} else {
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS,
( upstream->tls_fallback_ok
? GETDNS_LOG_INFO : GETDNS_LOG_ERR), "%-40s : Verify failed : TLS - %s - "
"%s\n", upstream->addr_str,
( upstream->tls_fallback_ok
? "Tolerated because of Opportunistic profile"
: "*Failure*" ),
verify_errmsg);
}
} else {
upstream->tls_auth_state = GETDNS_AUTH_OK;
_getdns_upstream_log(upstream,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : Verify passed : TLS\n",
upstream->addr_str);
}
_getdns_tls_x509_free(&upstream->upstreams->mf, peer_cert);
}
if (upstream->tls_auth_state == GETDNS_AUTH_FAILED if (upstream->tls_auth_state == GETDNS_AUTH_FAILED
&& !upstream->tls_fallback_ok) && !upstream->tls_fallback_ok)
return STUB_SETUP_ERROR; return STUB_SETUP_ERROR;
@ -1325,13 +1009,13 @@ tls_do_handshake(getdns_upstream *upstream)
DEBUG_STUB("%s %-35s: FD: %d Handshake succeeded with auth state %s. Session is %s.\n", DEBUG_STUB("%s %-35s: FD: %d Handshake succeeded with auth state %s. Session is %s.\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd,
_getdns_auth_str(upstream->tls_auth_state), _getdns_auth_str(upstream->tls_auth_state),
SSL_session_reused(upstream->tls_obj) ?"re-used":"new"); _getdns_tls_connection_is_session_reused(upstream->tls_obj) ? "new" : "re-used");
upstream->tls_hs_state = GETDNS_HS_DONE; upstream->tls_hs_state = GETDNS_HS_DONE;
upstream->conn_state = GETDNS_CONN_OPEN; upstream->conn_state = GETDNS_CONN_OPEN;
upstream->conn_completed++; upstream->conn_completed++;
if (upstream->tls_session != NULL) if (upstream->tls_session != NULL)
SSL_SESSION_free(upstream->tls_session); _getdns_tls_session_free(&upstream->upstreams->mf, upstream->tls_session);
upstream->tls_session = SSL_get1_session(upstream->tls_obj); upstream->tls_session = _getdns_tls_connection_get_session(&upstream->upstreams->mf, upstream->tls_obj);
/* Reset timeout on success*/ /* Reset timeout on success*/
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->event.read_cb = NULL; upstream->event.read_cb = NULL;
@ -1369,10 +1053,10 @@ static int
stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp, stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
struct mem_funcs *mf) struct mem_funcs *mf)
{ {
ssize_t read; size_t read;
uint8_t *buf; uint8_t *buf;
size_t buf_size; size_t buf_size;
SSL* tls_obj = upstream->tls_obj; _getdns_tls_connection* tls_obj = upstream->tls_obj;
int q = tls_connected(upstream); int q = tls_connected(upstream);
if (q != 0) if (q != 0)
@ -1388,17 +1072,14 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
tcp->to_read = 2; /* Packet size */ tcp->to_read = 2; /* Packet size */
} }
ERR_clear_error(); getdns_return_t r = _getdns_tls_connection_read(tls_obj, tcp->read_pos, tcp->to_read, &read);
read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read); /* TODO[TLS]: Handle GETDNS_RETURN_TLS_WANT_WRITE which means handshake
if (read <= 0) { renegotiation. Need to keep handshake state to do that.*/
/* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake if (r == GETDNS_RETURN_TLS_WANT_READ)
renegotiation. Need to keep handshake state to do that.*/ return STUB_TCP_RETRY;
int want = SSL_get_error(tls_obj, read); else if (r != GETDNS_RETURN_GOOD)
if (want == SSL_ERROR_WANT_READ) { return STUB_TCP_ERROR;
return STUB_TCP_RETRY; /* Come back later */
} else
return STUB_TCP_ERROR;
}
tcp->to_read -= read; tcp->to_read -= read;
tcp->read_pos += read; tcp->read_pos += read;
@ -1429,15 +1110,17 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
/* Ready to start reading the packet */ /* Ready to start reading the packet */
tcp->read_pos = tcp->read_buf; tcp->read_pos = tcp->read_buf;
read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read); switch ((int)_getdns_tls_connection_read(tls_obj, tcp->read_pos, tcp->to_read, &read)) {
if (read <= 0) { case GETDNS_RETURN_GOOD:
/* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake break;
case GETDNS_RETURN_TLS_WANT_READ:
return STUB_TCP_RETRY; /* Come back later */
default:
/* TODO[TLS]: Handle GETDNS_RETURN_TLS_WANT_WRITE which means handshake
renegotiation. Need to keep handshake state to do that.*/ renegotiation. Need to keep handshake state to do that.*/
int want = SSL_get_error(tls_obj, read); return STUB_TCP_ERROR;
if (want == SSL_ERROR_WANT_READ) {
return STUB_TCP_RETRY; /* read more later */
} else
return STUB_TCP_ERROR;
} }
tcp->to_read -= read; tcp->to_read -= read;
tcp->read_pos += read; tcp->read_pos += read;
@ -1452,10 +1135,10 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
getdns_network_req *netreq) getdns_network_req *netreq)
{ {
size_t pkt_len; size_t pkt_len;
ssize_t written; size_t written;
uint16_t query_id; uint16_t query_id;
intptr_t query_id_intptr; intptr_t query_id_intptr;
SSL* tls_obj = upstream->tls_obj; _getdns_tls_connection* tls_obj = upstream->tls_obj;
uint16_t padding_sz; uint16_t padding_sz;
int q = tls_connected(upstream); int q = tls_connected(upstream);
@ -1530,7 +1213,8 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
* Lets see how much of it we can write */ * Lets see how much of it we can write */
/* TODO[TLS]: Handle error cases, partial writes, renegotiation etc. */ /* TODO[TLS]: Handle error cases, partial writes, renegotiation etc. */
ERR_clear_error(); getdns_return_t r;
#if INTERCEPT_COM_DS #if INTERCEPT_COM_DS
/* Intercept and do not sent out COM DS queries. For debugging /* Intercept and do not sent out COM DS queries. For debugging
* purposes only. Never commit with this turned on. * purposes only. Never commit with this turned on.
@ -1545,25 +1229,16 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
debug_req("Intercepting", netreq); debug_req("Intercepting", netreq);
written = pkt_len + 2; written = pkt_len + 2;
r = GETDNS_RETURN_GOOD;
} else } else
#endif #endif
written = SSL_write(tls_obj, netreq->query - 2, pkt_len + 2); r = _getdns_tls_connection_write(tls_obj, netreq->query - 2, pkt_len + 2, &written);
if (written <= 0) { if (r == GETDNS_RETURN_TLS_WANT_READ ||
/* SSL_write will not do partial writes, because r == GETDNS_RETURN_TLS_WANT_WRITE)
* SSL_MODE_ENABLE_PARTIAL_WRITE is not default, return STUB_TCP_RETRY;
* but the write could fail because of renegotiation. else if (r != GETDNS_RETURN_GOOD)
* In that case SSL_get_error() will return return STUB_TCP_ERROR;
* SSL_ERROR_WANT_READ or, SSL_ERROR_WANT_WRITE.
* Return for retry in such cases.
*/
switch (SSL_get_error(tls_obj, written)) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
return STUB_TCP_RETRY;
default:
return STUB_TCP_ERROR;
}
}
/* We were able to write everything! Start reading. */ /* We were able to write everything! Start reading. */
return (int) query_id; return (int) query_id;
@ -1897,7 +1572,7 @@ upstream_write_cb(void *userarg)
getdns_upstream *upstream = (getdns_upstream *)userarg; getdns_upstream *upstream = (getdns_upstream *)userarg;
getdns_network_req *netreq = upstream->write_queue; getdns_network_req *netreq = upstream->write_queue;
int q; int q;
X509 *cert; _getdns_tls_x509 *cert;
if (!netreq) { if (!netreq) {
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
@ -1960,12 +1635,11 @@ upstream_write_cb(void *userarg)
if (netreq->owner->return_call_reporting && if (netreq->owner->return_call_reporting &&
netreq->upstream->tls_obj) { netreq->upstream->tls_obj) {
if (netreq->debug_tls_peer_cert.data == NULL && if (netreq->debug_tls_peer_cert.data == NULL &&
(cert = SSL_get_peer_certificate(netreq->upstream->tls_obj))) { (cert = _getdns_tls_connection_get_peer_certificate(&upstream->upstreams->mf, netreq->upstream->tls_obj))) {
netreq->debug_tls_peer_cert.size = i2d_X509( _getdns_tls_x509_to_der(&upstream->upstreams->mf, cert, &netreq->debug_tls_peer_cert);
cert, &netreq->debug_tls_peer_cert.data); _getdns_tls_x509_free(&upstream->upstreams->mf, cert);
X509_free(cert);
} }
netreq->debug_tls_version = SSL_get_version(netreq->upstream->tls_obj); netreq->debug_tls_version = _getdns_tls_connection_get_version(netreq->upstream->tls_obj);
} }
/* Need this because auth status is reset on connection close */ /* Need this because auth status is reset on connection close */
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state; netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;

465
src/tls.h Normal file
View File

@ -0,0 +1,465 @@
/**
*
* \file tls.h
* @brief getdns TLS functions
*/
/*
* Copyright (c) 2018-2019, NLnet Labs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _GETDNS_TLS_H
#define _GETDNS_TLS_H
#include "getdns/getdns.h"
#include "types-internal.h"
#include "tls-internal.h"
/* Forward declare type. */
struct sha256_pin;
typedef struct sha256_pin sha256_pin_t;
/* Additional return codes required by TLS abstraction. Internal use only. */
#define GETDNS_RETURN_TLS_WANT_READ ((getdns_return_t) 420)
#define GETDNS_RETURN_TLS_WANT_WRITE ((getdns_return_t) 421)
#define GETDNS_RETURN_TLS_CONNECTION_FRESH ((getdns_return_t) 422)
/**
* Global initialisation of the TLS interface.
*/
void _getdns_tls_init();
/**
* Create a new TLS context.
*
* @param mfs pointer to getdns memory functions.
* @paam log pointer to context log config.
* @return pointer to new context or NULL on error.
*/
_getdns_tls_context* _getdns_tls_context_new(struct mem_funcs* mfs, const getdns_log_config* log);
/**
* Free a TLS context.
*
* @param mfs point to getdns memory functions.
* @param ctx the context to free.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER if <code>ctx</code> is invalid.
*/
getdns_return_t _getdns_tls_context_free(struct mem_funcs* mfs, _getdns_tls_context* ctx);
/**
* Initialise any shared state for pinset checking.
*
* @param ctx the context to initialise.
*/
void _getdns_tls_context_pinset_init(_getdns_tls_context* ctx);
/**
* Set minimum and maximum TLS versions.
* If max or min are 0, that boundary is not set.
*
* @param ctx the context.
* @param min the minimum TLS version.
* @param max the maximum TLS version.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_NOT_IMPLEMENTED if not implemented.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_context_set_min_max_tls_version(_getdns_tls_context* ctx, getdns_tls_version_t min, getdns_tls_version_t max);
/**
* Get the default context cipher list.
*
* @return the default context cipher list.
*/
const char* _getdns_tls_context_get_default_cipher_list();
/**
* Set list of allowed ciphers.
*
* @param ctx the context.
* @param list the list of cipher identifiers. NULL for default setting.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_context_set_cipher_list(_getdns_tls_context* ctx, const char* list);
/**
* Get the default context cipher suites.
*
* @return the default context cipher suites.
*/
const char* _getdns_tls_context_get_default_cipher_suites();
/**
* Set list of allowed cipher suites.
*
* @param ctx the context.
* @param list the list of cipher suites. NULL for default setting.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_context_set_cipher_suites(_getdns_tls_context* ctx, const char* list);
/**
* Set list of allowed curves.
*
* @param ctx the context.
* @param list the list of curve identifiers. NULL for default setting.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_context_set_curves_list(_getdns_tls_context* ctx, const char* list);
/**
* Set certificate authority details.
*
* Load CA from either a file or a directory. If both <code>file</code>
* and <code>path</code> are <code>NULL</code>, use default locations.
*
* @param ctx the context.
* @param file a file of CA certificates in PEM format.
* @param path a directory containing CA certificates in PEM format.
* Files are looked up by CA subject name hash value.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_GENERIC_ERROR on failure.
*/
getdns_return_t _getdns_tls_context_set_ca(_getdns_tls_context* ctx, const char* file, const char* path);
/**
* Create a new TLS connection and associate it with a file descriptior.
*
* @param mfs pointer to getdns memory functions.
* @param ctx the context.
* @param fd the file descriptor to associate with the connection.
* @paam log pointer to connection log config.
* @return pointer to new connection or NULL on error.
*/
_getdns_tls_connection* _getdns_tls_connection_new(struct mem_funcs* mfs, _getdns_tls_context* ctx, int fd, const getdns_log_config* log);
/**
* Free a TLS connection.
*
* @param mfs pointer to getdns memory functions.
* @param conn the connection to free.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER if <code>conn</code> is invalid.
*/
getdns_return_t _getdns_tls_connection_free(struct mem_funcs* mfs, _getdns_tls_connection* conn);
/**
* Shut down a TLS connection.
*
* @param conn the connection to shut down.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER if <code>conn</code> is invalid.
* @return GETDNS_RETURN_CONTEXT_UPDATE_FAIL if shutdown is not finished,
* and this routine should be called again.
* @return GETDNS_RETURN_GENERIC_ERROR on error.
*/
getdns_return_t _getdns_tls_connection_shutdown(_getdns_tls_connection* conn);
/**
* Set minimum and maximum TLS versions for this connection.
* If max or min are 0, that boundary is not set.
*
* @param conn the connection.
* @param min the minimum TLS version.
* @param max the maximum TLS version.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_NOT_IMPLEMENTED if not implemented.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_connection_set_min_max_tls_version(_getdns_tls_connection* conn, getdns_tls_version_t min, getdns_tls_version_t max);
/**
* Set list of allowed ciphers on this connection.
*
* @param conn the connection.
* @param list the list of cipher identifiers. NULL for opportunistic setting.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad connection pointer.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_connection_set_cipher_list(_getdns_tls_connection* conn, const char* list);
/**
* Set list of allowed cipher suites on this connection.
*
* @param conn the connection.
* @param list the list of cipher suites. NULL for default setting.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad context pointer.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_connection_set_cipher_suites(_getdns_tls_connection* conn, const char* list);
/**
* Set list of allowed curves on this connection.
*
* @param conn the connection.
* @param list the list of curve identifiers. NULL for default setting.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad connection pointer.
* @return GETDNS_RETURN_BAD_CONTEXT on failure.
*/
getdns_return_t _getdns_tls_connection_set_curves_list(_getdns_tls_connection* conn, const char* list);
/**
* Set the session for this connection.
*
* @param conn the connection.
* @param s the session.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER on bad connection pointer.
* @return GETDNS_RETURN_GENERIC_ERROR on failure.
*/
getdns_return_t _getdns_tls_connection_set_session(_getdns_tls_connection* conn, _getdns_tls_session* s);
/**
* Get the session for this connection.
*
* @param mfs pointer to getdns memory functions.
* @param conn the connection.
* @return pointer to the session or NULL on error.
*/
_getdns_tls_session* _getdns_tls_connection_get_session(struct mem_funcs* mfs, _getdns_tls_connection* conn);
/**
* Report the TLS version of the connection.
*
* @param conn the connection.
* @return string with the connection description, NULL on error.
*/
const char* _getdns_tls_connection_get_version(_getdns_tls_connection* conn);
/**
* Attempt TLS handshake.
*
* @param conn the connection.
* @return GETDNS_RETURN_GOOD if handshake is complete.
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
* @return GETDNS_RETURN_TLS_WANT_READ if handshake needs to read to proceed.
* @return GETDNS_RETURN_TLS_WANT_WRITE if handshake needs to write to proceed.
* @return GETDNS_RETURN_GENERIC_ERROR if handshake failed.
*/
getdns_return_t _getdns_tls_connection_do_handshake(_getdns_tls_connection* conn);
/**
* Get the connection peer certificate.
*
* @param mfs pointer to getdns memory functions.
* @param conn the connection.
* @return certificate or NULL on error.
*/
_getdns_tls_x509* _getdns_tls_connection_get_peer_certificate(struct mem_funcs* mfs, _getdns_tls_connection* conn);
/**
* See whether the connection is reusing a session.
*
* @param conn the connection.
* @return GETDNS_RETURN_GOOD if connection is being reused.
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
* @return GETDNS_RETURN_TLS_CONNECTION_FRESH if connection is not being reused.
*/
getdns_return_t _getdns_tls_connection_is_session_reused(_getdns_tls_connection* conn);
/**
* Set up host name verification.
*
* @param conn the connection.
* @param auth_name the hostname.
* @return GETDNS_RETURN_GOOD if all OK.
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
*/
getdns_return_t _getdns_tls_connection_setup_hostname_auth(_getdns_tls_connection* conn, const char* auth_name);
/**
* Set host pinset.
*
* @param conn the connection.
* @param auth_name the hostname.
* @return GETDNS_RETURN_GOOD if all OK.
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
*/
getdns_return_t _getdns_tls_connection_set_host_pinset(_getdns_tls_connection* conn, const char* auth_name, const sha256_pin_t* pinset);
/**
* Get result of certificate verification.
*
* @param conn the connection.
* @param errno failure error number.
* @param errmsg failure error message.
* @return GETDNS_RETURN_GOOD if all OK.
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
* @return GETDNS_RETURN_GENERIC_ERROR if verification failed.
*/
getdns_return_t _getdns_tls_connection_certificate_verify(_getdns_tls_connection* conn, long* errnum, const char** errmsg);
/**
* Read from TLS.
*
* @param conn the connection.
* @param buf the buffer to read to.
* @param to_read the number of bytes to read.
* @param read pointer to holder for the number of bytes read.
* @return GETDNS_RETURN_GOOD if some bytes were read.
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
* @return GETDNS_RETURN_TLS_WANT_READ if the read needs to be retried.
* @return GETDNS_RETURN_TLS_WANT_WRITE if handshake isn't finished.
* @return GETDNS_RETURN_GENERIC_ERROR if read failed.
*/
getdns_return_t _getdns_tls_connection_read(_getdns_tls_connection* conn, uint8_t* buf, size_t to_read, size_t* read);
/**
* Write to TLS.
*
* @param conn the connection.
* @param buf the buffer to write from.
* @param to_write the number of bytes to write.
* @param written the number of bytes written.
* @return GETDNS_RETURN_GOOD if some bytes were read.
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
* @return GETDNS_RETURN_TLS_WANT_READ if handshake isn't finished.
* @return GETDNS_RETURN_TLS_WANT_WRITE if the write needs to be retried.
* @return GETDNS_RETURN_GENERIC_ERROR if write failed.
*/
getdns_return_t _getdns_tls_connection_write(_getdns_tls_connection* conn, uint8_t* buf, size_t to_write, size_t* written);
/**
* Free a session.
*
* @param mfs pointer to getdns memory functions.
* @param s the session.
* @return GETDNS_RETURN_GOOD on success.
* @return GETDNS_RETURN_INVALID_PARAMETER if s is null or has no SSL.
*/
getdns_return_t _getdns_tls_session_free(struct mem_funcs* mfs, _getdns_tls_session* s);
/**
* Free X509 certificate.
*
* @param mfs pointer to getdns memory functions.
* @param cert the certificate.
*/
void _getdns_tls_x509_free(struct mem_funcs* mfs, _getdns_tls_x509* cert);
/**
* Convert X509 to DER.
*
* @param cert the certificate.
* @param buf buffer to receive conversion.
* @return length of conversion, 0 on error.
*/
int _getdns_tls_x509_to_der(struct mem_funcs* mfs, _getdns_tls_x509* cert, getdns_bindata* bindata);
/**
* Fill in dictionary with TLS API information.
*
* @param dict the dictionary to add to.
* @return GETDNS_RETURN_GOOD if some bytes were read.
* @return GETDNS_RETURN_GENERIC_ERROR if items cannot be set.
*/
getdns_return_t _getdns_tls_get_api_information(getdns_dict* dict);
/**
* Return buffer with HMAC hash.
*
* @param mfs pointer to getdns memory functions.
* @param algorithm hash algorithm to use (<code>GETDNS_HMAC_?</code>).
* @param key the key.
* @param key_size the key size.
* @param data the data to hash.
* @param data_size the data size.
* @param output_size the output size will be written here if not NULL.
* @return output malloc'd buffer with output, NULL on error.
*/
unsigned char* _getdns_tls_hmac_hash(struct mem_funcs* mfs, int algorithm, const void* key, size_t key_size, const void* data, size_t data_size, size_t* output_size);
/**
* Return a new HMAC handle.
*
* @param mfs pointer to getdns memory functions.
* @param algorithm hash algorithm to use (<code>GETDNS_HMAC_?</code>).
* @param key the key.
* @param key_size the key size.
* @return HMAC handle or NULL on error.
*/
_getdns_tls_hmac* _getdns_tls_hmac_new(struct mem_funcs* mfs, int algorithm, const void* key, size_t key_size);
/**
* Add data to a HMAC.
*
* @param h the HMAC.
* @param data the data to add.
* @param data_size the size of data to add.
* @return GETDNS_RETURN_GOOD if added.
* @return GETDNS_RETURN_INVALID_PARAMETER if h is null or has no HMAC.
* @return GETDNS_RETURN_GENERIC_ERROR on error.
*/
getdns_return_t _getdns_tls_hmac_add(_getdns_tls_hmac* h, const void* data, size_t data_size);
/**
* Return the HMAC digest and free the handle.
*
* @param mfs pointer to getdns memory functions.
* @param h the HMAC.
* @param output_size the output size will be written here if not NULL.
* @return output malloc'd buffer with output, NULL on error.
*/
unsigned char* _getdns_tls_hmac_end(struct mem_funcs* mfs, _getdns_tls_hmac* h, size_t* output_size);
/**
* Calculate a SHA1 hash.
*
* @param data the data to hash.
* @param data_size the size of the data to hash.
* @param buf the buffer to receive the hash. Must be at least
* SHA_DIGEST_LENGTH bytes.
*/
void _getdns_tls_sha1(const void* data, size_t data_size, unsigned char* buf);
/**
* Calculate SHA256 for cookie.
*
* @param secret the secret.
* @param addr the address.
* @param addrlen the address length.
* @param buf buffer to receive hash.
* @param buflen receive the hash length.
*/
void _getdns_tls_cookie_sha256(uint32_t secret, void* addr, size_t addrlen, unsigned char* buf, size_t* buflen);
#endif /* _GETDNS_TLS_H */

View File

@ -127,10 +127,7 @@ getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \
$(srcdir)/../debug.h \ $(srcdir)/../debug.h \
../getdns/getdns.h \ ../getdns/getdns.h \
../getdns/getdns_extra.h ../getdns/getdns_extra.h
# Dependencies for getdns_server_mon
getdns_server_mon.lo getdns_server_mon.o: $(srcdir)/getdns_server_mon.c \ getdns_server_mon.lo getdns_server_mon.o: $(srcdir)/getdns_server_mon.c \
../config.h \ ../config.h \
$(srcdir)/../debug.h \
../getdns/getdns.h \ ../getdns/getdns.h \
../getdns/getdns_extra.h ../getdns/getdns_extra.h

View File

@ -74,9 +74,11 @@ static getdns_dict *listen_dict = NULL;
static size_t pincount = 0; static size_t pincount = 0;
static size_t listen_count = 0; static size_t listen_count = 0;
static uint16_t request_type = GETDNS_RRTYPE_NS; static uint16_t request_type = GETDNS_RRTYPE_NS;
static int got_rrtype = 0;
static int timeout, edns0_size, padding_blocksize; static int timeout, edns0_size, padding_blocksize;
static int async = 0, interactive = 0; static int async = 0, interactive = 0;
static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL; static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
static int got_calltype = 0;
static int bogus_answers = 0; static int bogus_answers = 0;
static int check_dnssec = 0; static int check_dnssec = 0;
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
@ -581,8 +583,6 @@ getdns_return_t parse_args(int argc, char **argv)
size_t upstream_count = 0; size_t upstream_count = 0;
FILE *fh; FILE *fh;
int int_value; int int_value;
int got_rrtype = 0;
int got_calltype = 0;
int got_qname = 0; int got_qname = 0;
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
@ -1181,7 +1181,7 @@ getdns_return_t do_the_call(void)
r = GETDNS_RETURN_GENERIC_ERROR; r = GETDNS_RETURN_GENERIC_ERROR;
break; break;
} }
if (r == GETDNS_RETURN_GOOD && !batch_mode) if (r == GETDNS_RETURN_GOOD && !batch_mode && !interactive)
getdns_context_run(context); getdns_context_run(context);
if (r != GETDNS_RETURN_GOOD) if (r != GETDNS_RETURN_GOOD)
fprintf(stderr, "An error occurred: %d '%s'\n", (int)r, fprintf(stderr, "An error occurred: %d '%s'\n", (int)r,
@ -1258,14 +1258,28 @@ static void incoming_request_handler(getdns_context *context,
void *userarg, getdns_transaction_t request_id); void *userarg, getdns_transaction_t request_id);
void read_line_cb(void *userarg);
void read_line_tiny_delay_cb(void *userarg)
{
getdns_eventloop_event *read_line_ev = userarg;
loop->vmt->clear(loop, read_line_ev);
read_line_ev->timeout_cb = NULL;
read_line_ev->read_cb = read_line_cb;
loop->vmt->schedule(loop, fileno(fp), -1, read_line_ev);
}
void read_line_cb(void *userarg) void read_line_cb(void *userarg)
{ {
static int n = 0;
getdns_eventloop_event *read_line_ev = userarg; getdns_eventloop_event *read_line_ev = userarg;
getdns_return_t r; getdns_return_t r;
char line[1024], *token, *linev[256]; char line[1024], *token, *linev[256];
int linec; int linec;
assert(n == 0);
n += 1;
if (!fgets(line, 1024, fp) || !*line) { if (!fgets(line, 1024, fp) || !*line) {
if (query_file && verbosity) if (query_file && verbosity)
fprintf(stdout,"End of file."); fprintf(stdout,"End of file.");
@ -1276,6 +1290,7 @@ void read_line_cb(void *userarg)
if (interactive && !query_file) if (interactive && !query_file)
(void) getdns_context_set_upstream_recursive_servers( (void) getdns_context_set_upstream_recursive_servers(
context, NULL); context, NULL);
n -= 1;
return; return;
} }
if (query_file && verbosity) if (query_file && verbosity)
@ -1288,6 +1303,7 @@ void read_line_cb(void *userarg)
printf("> "); printf("> ");
fflush(stdout); fflush(stdout);
} }
n -= 1;
return; return;
} }
if (*token == '#') { if (*token == '#') {
@ -1297,6 +1313,7 @@ void read_line_cb(void *userarg)
printf("> "); printf("> ");
fflush(stdout); fflush(stdout);
} }
n -= 1;
return; return;
} }
do linev[linec++] = token; do linev[linec++] = token;
@ -1312,10 +1329,23 @@ void read_line_cb(void *userarg)
(r != CONTINUE && r != CONTINUE_ERROR)) (r != CONTINUE && r != CONTINUE_ERROR))
loop->vmt->clear(loop, read_line_ev); loop->vmt->clear(loop, read_line_ev);
else if (! query_file) { else {
printf("> "); #if 0
fflush(stdout); /* Tiny delay, to make sending queries less bursty with
* -F parameter.
*
*/
loop->vmt->clear(loop, read_line_ev);
read_line_ev->read_cb = NULL;
read_line_ev->timeout_cb = read_line_tiny_delay_cb;
loop->vmt->schedule(loop, fileno(fp), 1, read_line_ev);
#endif
if (! query_file) {
printf("> ");
fflush(stdout);
}
} }
n -= 1;
} }
typedef struct dns_msg { typedef struct dns_msg {

View File

@ -36,9 +36,13 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#ifdef USE_GNUTLS
#include <gnutls/x509.h>
#else
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#include <openssl/bio.h> #include <openssl/bio.h>
#endif
#include <getdns/getdns.h> #include <getdns/getdns.h>
#include <getdns/getdns_extra.h> #include <getdns/getdns_extra.h>
@ -181,7 +185,7 @@ static const char *rcode_text(int rcode)
return getdns_intval_text(rcode, "rcode", "GETDNS_RCODE_"); return getdns_intval_text(rcode, "rcode", "GETDNS_RCODE_");
} }
#if OPENSSL_VERSION_NUMBER < 0x10002000 || defined(LIBRESSL_VERSION_NUMBER) #if !defined(USE_GNUTLS) && (OPENSSL_VERSION_NUMBER < 0x10002000 || defined(LIBRESSL_VERSION_NUMBER))
/* /*
* Convert date to Julian day. * Convert date to Julian day.
* See https://en.wikipedia.org/wiki/Julian_day * See https://en.wikipedia.org/wiki/Julian_day
@ -212,6 +216,27 @@ static long secs_in_day(const struct tm *tm)
*/ */
static bool extract_cert_expiry(const unsigned char *data, size_t len, time_t *t) static bool extract_cert_expiry(const unsigned char *data, size_t len, time_t *t)
{ {
#ifdef USE_GNUTLS
gnutls_x509_crt_t cert;
gnutls_datum_t datum;
bool res = false;
datum.data = (unsigned char*) data;
datum.size = len;
if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
return false;
if (gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER) == GNUTLS_E_SUCCESS) {
time_t expiry = gnutls_x509_crt_get_expiration_time(cert);
if (expiry != GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION) {
res = true;
*t = expiry;
}
}
gnutls_x509_crt_deinit(cert);
return res;
#else
X509 *cert = d2i_X509(NULL, &data, len); X509 *cert = d2i_X509(NULL, &data, len);
if (!cert) if (!cert)
return false; return false;
@ -299,6 +324,7 @@ static bool extract_cert_expiry(const unsigned char *data, size_t len, time_t *t
X509_free(cert); X509_free(cert);
#endif #endif
*t += day_diff * SECS_IN_DAY + sec_diff; *t += day_diff * SECS_IN_DAY + sec_diff;
#endif /* USE_GNUTLS */
return true; return true;
} }

View File

@ -934,7 +934,7 @@ _getdns_create_call_reporting_dict(
return NULL; return NULL;
} }
netreq->debug_tls_peer_cert.size = 0; netreq->debug_tls_peer_cert.size = 0;
OPENSSL_free(netreq->debug_tls_peer_cert.data); GETDNS_FREE(context->my_mf, netreq->debug_tls_peer_cert.data);
netreq->debug_tls_peer_cert.data = NULL; netreq->debug_tls_peer_cert.data = NULL;
return netreq_debug; return netreq_debug;
} }

View File

@ -219,46 +219,5 @@ INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms)
return *now_ms >= expires ? 0 : expires - *now_ms; return *now_ms >= expires ? 0 : expires - *now_ms;
} }
#if defined(HAVE_DECL_SSL_SET_MIN_PROTO_VERSION) \
&& HAVE_DECL_SSL_SET_MIN_PROTO_VERSION
INLINE int _getdns_tls_version2openssl_version(getdns_tls_version_t v)
{
switch (v) {
# ifdef SSL3_VERSION
case GETDNS_SSL3 : return SSL3_VERSION;
# endif
# ifdef TLS1_VERSION
case GETDNS_TLS1 : return TLS1_VERSION;
# endif
# ifdef TLS1_1_VERSION
case GETDNS_TLS1_1: return TLS1_1_VERSION;
# endif
# ifdef TLS1_2_VERSION
case GETDNS_TLS1_2: return TLS1_2_VERSION;
# endif
# ifdef TLS1_3_VERSION
case GETDNS_TLS1_3: return TLS1_3_VERSION;
# endif
default :
# if defined(TLS_MAX_VERSION)
return TLS_MAX_VERSION;
# elif defined(TLS1_3_VERSION)
return TLS1_3_VERSION;
# elif defined(TLS1_2_VERSION)
return TLS1_2_VERSION;
# elif defined(TLS1_1_VERSION)
return TLS1_1_VERSION;
# elif defined(TLS1_VERSION)
return TLS1_VERSION;
# elif defined(SSL3_VERSION)
return SSL3_VERSION;
# else
return -1;
# endif
}
}
#endif
#endif #endif
/* util-internal.h */ /* util-internal.h */

View File

@ -1 +0,0 @@
#include "util/val_secalgo.h"

View File

@ -1,7 +1,7 @@
/** /**
* *
* \file rbtree.h * \file val_secalgo.h
* /brief Alternative symbol names for unbound's rbtree.h * /brief secalgo interface.
* *
*/ */
/* /*
@ -32,53 +32,23 @@
*/ */
#ifndef VAL_SECALGO_H_SYMBOLS #ifndef VAL_SECALGO_H_SYMBOLS
#define VAL_SECALGO_H_SYMBOLS #define VAL_SECALGO_H_SYMBOLS
#define sldns_buffer gldns_buffer
#define nsec3_hash_algo_size_supported _getdns_nsec3_hash_algo_size_supported #include "gldns/gbuffer.h"
#define secalgo_nsec3_hash _getdns_secalgo_nsec3_hash
#define secalgo_hash_sha256 _getdns_secalgo_hash_sha256
#define ds_digest_size_supported _getdns_ds_digest_size_supported
#define secalgo_ds_digest _getdns_secalgo_ds_digest
#define dnskey_algo_id_is_supported _getdns_dnskey_algo_id_is_supported
#define verify_canonrrset _getdns_verify_canonrrset
#define sec_status _getdns_sec_status
#define sec_status_secure _getdns_sec_status_secure
#define sec_status_insecure _getdns_sec_status_insecure
#define sec_status_unchecked _getdns_sec_status_unchecked
#define sec_status_bogus _getdns_sec_status_bogus
#define fake_sha1 _getdns_fake_sha1
#define fake_dsa _getdns_fake_dsa
enum sec_status { sec_status_bogus = 0 enum sec_status { sec_status_bogus = 0
, sec_status_unchecked = 0 , sec_status_unchecked = 0
, sec_status_insecure = 0 , sec_status_insecure = 0
, sec_status_secure = 1 }; , sec_status_secure = 1 };
#define NSEC3_HASH_SHA1 0x01
#define LDNS_SHA1 GLDNS_SHA1 size_t _getdns_ds_digest_size_supported(int algo);
#define LDNS_SHA256 GLDNS_SHA256
#define LDNS_SHA384 GLDNS_SHA384 int _getdns_secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
#define LDNS_HASH_GOST GLDNS_HASH_GOST unsigned char* res);
#define LDNS_RSAMD5 GLDNS_RSAMD5
#define LDNS_DSA GLDNS_DSA int _getdns_dnskey_algo_id_is_supported(int id);
#define LDNS_DSA_NSEC3 GLDNS_DSA_NSEC3
#define LDNS_RSASHA1 GLDNS_RSASHA1 enum sec_status _getdns_verify_canonrrset(struct gldns_buffer* buf, int algo,
#define LDNS_RSASHA1_NSEC3 GLDNS_RSASHA1_NSEC3 unsigned char* sigblock, unsigned int sigblock_len,
#define LDNS_RSASHA256 GLDNS_RSASHA256 unsigned char* key, unsigned int keylen, char** reason);
#define LDNS_RSASHA512 GLDNS_RSASHA512
#define LDNS_ECDSAP256SHA256 GLDNS_ECDSAP256SHA256
#define LDNS_ECDSAP384SHA384 GLDNS_ECDSAP384SHA384
#define LDNS_ECC_GOST GLDNS_ECC_GOST
#define LDNS_ED25519 GLDNS_ED25519
#define LDNS_ED448 GLDNS_ED448
#define sldns_ed255192pkey_raw gldns_ed255192pkey_raw
#define sldns_ed4482pkey_raw gldns_ed4482pkey_raw
#define sldns_key_EVP_load_gost_id gldns_key_EVP_load_gost_id
#define sldns_digest_evp gldns_digest_evp
#define sldns_key_buf2dsa_raw gldns_key_buf2dsa_raw
#define sldns_key_buf2rsa_raw gldns_key_buf2rsa_raw
#define sldns_gost2pkey_raw gldns_gost2pkey_raw
#define sldns_ecdsa2pkey_raw gldns_ecdsa2pkey_raw
#define sldns_buffer_begin gldns_buffer_begin
#define sldns_buffer_limit gldns_buffer_limit
#include "util/orig-headers/val_secalgo.h"
#endif #endif

2
stubby

@ -1 +1 @@
Subproject commit 9c6e55a16af8f3258736b804b17eac3d35daebf3 Subproject commit 8fb853ac8d6148fd9b53fdcbc107ecd375071ec5