mirror of https://github.com/getdnsapi/getdns.git
Merge abstracted TLS API + GnuTLS alternative
Thank you Jim! Merge branch 'devel/abstract-tls' into develop
This commit is contained in:
commit
2206558376
|
@ -1,4 +1,5 @@
|
|||
sudo: false
|
||||
dist: xenial
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
|
@ -6,6 +7,7 @@ compiler:
|
|||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libssl-dev
|
||||
- libunbound-dev
|
||||
- libidn11-dev
|
||||
- libyaml-dev
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
* 2019-01-11: Version 1.5.1
|
||||
* Introduce proof of concept GnuTLS implementation. Incomplete support
|
||||
for Trust Anchor validation. Requires GnuTLS DANE library. Currently
|
||||
untested with GnuTLS prior to 3.5.19, so configure demands a minumum
|
||||
version of 3.5.0.
|
||||
* Be consistent and always fail connection setup if setting ciphers/curves/
|
||||
TLS version/cipher suites fails.
|
||||
* Refactor OpenSSL usage into modules under src/openssl.
|
||||
Drop support for LibreSSL and versions of OpenSSL prior to 1.0.2.
|
||||
* PR #414: remove TLS13 ciphers from cipher_list, but
|
||||
only when SSL_CTX_set_ciphersuites is available.
|
||||
Thanks Bruno Pagani
|
||||
|
|
|
@ -213,6 +213,7 @@ $(distdir):
|
|||
mkdir -p $(distdir)/src/compat
|
||||
mkdir -p $(distdir)/src/util
|
||||
mkdir -p $(distdir)/src/gldns
|
||||
mkdir -p $(distdir)/src/openssl
|
||||
mkdir -p $(distdir)/src/tools
|
||||
mkdir -p $(distdir)/src/jsmn
|
||||
mkdir -p $(distdir)/src/yxml
|
||||
|
@ -266,6 +267,7 @@ $(distdir):
|
|||
cp $(srcdir)/spec/*.html $(distdir)/spec
|
||||
cp $(srcdir)/spec/example/Makefile.in $(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/*.[ch] $(distdir)/src/tools
|
||||
cp $(srcdir)/stubby/stubby.yml.example $(distdir)/stubby
|
||||
|
|
87
configure.ac
87
configure.ac
|
@ -33,6 +33,7 @@ AC_PREREQ([2.68])
|
|||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
sinclude(./m4/acx_openssl.m4)
|
||||
sinclude(./m4/acx_getaddrinfo.m4)
|
||||
sinclude(./m4/ac_lib_nettle.m4)
|
||||
sinclude(./m4/ax_check_compile_flag.m4)
|
||||
sinclude(./m4/pkg.m4)
|
||||
|
||||
|
@ -441,25 +442,65 @@ dnl SSLLIB=""
|
|||
dnl ]
|
||||
dnl )
|
||||
|
||||
# Which TLS and crypto libs to use.
|
||||
AC_ARG_WITH([gnutls],
|
||||
[AS_HELP_STRING([--with-gnutls],
|
||||
[use GnuTLS instead of OpenSSL])],
|
||||
[
|
||||
PKG_CHECK_MODULES([libgnutls], [gnutls >= 3.5.0])
|
||||
PKG_CHECK_MODULES([libgnutlsdane], [gnutls-dane >= 3.5.0])
|
||||
LIBS="$libgnutls_LIBS $libgnutlsdane_LIBS $LIBS"
|
||||
CFLAGS="$libgnutls_CFLAGS $libgnutlsdane_CFLAGS $CFLAGS"
|
||||
AC_SUBST([TLSDIR], 'gnutls')
|
||||
AC_DEFINE([USE_GNUTLS], [1], [Use the GnuTLS library])
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
|
||||
AX_LIB_NETTLE(yes)
|
||||
USE_NETTLE="yes"
|
||||
AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
|
||||
AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT])
|
||||
fi
|
||||
],
|
||||
[
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
ACX_WITH_SSL
|
||||
fi
|
||||
ACX_LIB_SSL
|
||||
AC_SUBST([TLSDIR], 'openssl')
|
||||
|
||||
# Verify OpenSSL is at least version 1.0.2.
|
||||
# We also check it's not LibreSSL, but that's a little later, not here.
|
||||
AC_CHECK_FUNCS([X509_check_host SSL_dane_enable])
|
||||
if test "x$ac_cv_func_X509_check_host" != xyes; then
|
||||
AC_MSG_ERROR([getdns requires OpenSSL version 1.0.2 or later])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether we need to compile/link DANE support])
|
||||
DANESSL_XTRA_OBJS=""
|
||||
if test "x$ac_cv_func_SSL_dane_enable" = xyes; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([USE_DANESSL], [1], [Define this to use DANE functions from the ssl_dane/danessl library.])
|
||||
DANESSL_XTRA_OBJS="danessl.lo"
|
||||
fi
|
||||
AC_SUBST(DANESSL_XTRA_OBJS)
|
||||
])
|
||||
|
||||
|
||||
# openssl
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
ACX_WITH_SSL
|
||||
fi
|
||||
ACX_LIB_SSL
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no" ; then
|
||||
AC_MSG_CHECKING([for LibreSSL])
|
||||
if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_LIBRESSL], [1], [Define if we have LibreSSL])
|
||||
# libressl provides these compat functions, but they may also be
|
||||
# declared by the OS in libc. See if they have been declared.
|
||||
AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform])
|
||||
AC_MSG_ERROR([getdns does not support LibreSSL])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version 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_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
|
@ -480,29 +521,7 @@ AC_INCLUDES_DEFAULT
|
|||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
|
||||
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)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
|
||||
case "$enable_sha1" in
|
||||
|
@ -772,8 +791,8 @@ case "$enable_edns_cookies" in
|
|||
no)
|
||||
;;
|
||||
yes|*)
|
||||
if test "x_$HAVE_SSL" != "x_yes"; then
|
||||
AC_MSG_ERROR([edns cookies need openssl libcrypto which is not available, please rerun with --disable-edns-cookies])
|
||||
if test "x_$HAVE_SSL" != "x_yes" -a $USE_NETTLE = "no"; then
|
||||
AC_MSG_ERROR([edns cookies needs crypto library which is not available, please rerun with --disable-edns-cookies])
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([EDNS_COOKIES], [1], [Define this to enable the experimental edns cookies.])
|
||||
;;
|
||||
|
|
|
@ -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
|
||||
])
|
264
src/Makefile.in
264
src/Makefile.in
|
@ -52,11 +52,12 @@ INSTALL = @INSTALL@
|
|||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
srcdir = @srcdir@
|
||||
tlsdir = @TLSDIR@
|
||||
stubbysrcdir = $(srcdir)/../stubby
|
||||
LIBTOOL = ../libtool
|
||||
|
||||
CC=@CC@
|
||||
CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary -I$(stubbysrcdir)/src @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS)
|
||||
CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary -I$(srcdir)/$(tlsdir) -I$(stubbysrcdir)/src @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS)
|
||||
WPEDANTICFLAG=@WPEDANTICFLAG@
|
||||
WNOERRORFLAG=@WNOERRORFLAG@
|
||||
LDFLAGS=@LDFLAGS@ @LIBS@
|
||||
|
@ -78,9 +79,9 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
|
|||
DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo
|
||||
|
||||
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
|
||||
list.lo request-internal.lo platform.lo pubkey-pinning.lo rr-dict.lo \
|
||||
list.lo request-internal.lo platform.lo rr-dict.lo \
|
||||
rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \
|
||||
mdns.lo
|
||||
mdns.lo pubkey-pinning.lo
|
||||
|
||||
GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
|
||||
str2wire.lo
|
||||
|
@ -91,9 +92,10 @@ LIBOBJDIR=
|
|||
LIBOBJS=@LIBOBJS@
|
||||
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
|
||||
|
||||
UTIL_OBJ=rbtree.lo val_secalgo.lo lruhash.lo lookup3.lo locks.lo
|
||||
UTIL_OBJ=rbtree.lo lruhash.lo lookup3.lo locks.lo
|
||||
|
||||
JSMN_OBJ=jsmn.lo
|
||||
TLS_OBJ=tls.lo pubkey-pinning-internal.lo keyraw-internal.lo val_secalgo.lo anchor-internal.lo
|
||||
YXML_OBJ=yxml.lo
|
||||
|
||||
YAML_OBJ=convert_yaml_to_json.lo
|
||||
|
@ -133,6 +135,9 @@ $(UTIL_OBJ):
|
|||
$(JSMN_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@
|
||||
|
||||
$(TLS_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$(tlsdir)/$(@:.lo=.c) -o $@
|
||||
|
||||
$(YAML_OBJ):
|
||||
$(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
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols
|
||||
|
||||
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS)
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
|
||||
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(TLS_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS)
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(TLS_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
|
||||
|
||||
test: default
|
||||
cd test && $(MAKE) $@
|
||||
|
@ -271,15 +276,15 @@ Makefile: $(srcdir)/Makefile.in ../config.status
|
|||
depend:
|
||||
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
|
||||
|
||||
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -Iyxml -Iutil/auxiliary -I../stubby/src *.c gldns/*.c compat/*.c util/*.c jsmn/*.c yxml/*.c 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" \
|
||||
-e 's? gldns/? $$(srcdir)/gldns/?g' \
|
||||
-e 's? compat/? $$(srcdir)/compat/?g' \
|
||||
-e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?g' \
|
||||
-e 's? util/? $$(srcdir)/util/?g' \
|
||||
-e 's? jsmn/? $$(srcdir)/jsmn/?g' \
|
||||
-e 's? $(tlsdir)/? $$(srcdir)/$$(tlsdir)/?g' \
|
||||
-e 's? yxml/? $$(srcdir)/yxml/?g' \
|
||||
-e 's? ssl_dane/? $$(srcdir)/ssl_dane/?g' \
|
||||
-e 's? extension/? $$(srcdir)/extension/?g' \
|
||||
-e 's? \.\./stubby/? $$(stubbysrcdir)/?g' \
|
||||
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
|
||||
|
@ -300,124 +305,102 @@ FORCE:
|
|||
|
||||
# Dependencies for gldns, utils, the extensions and compat functions
|
||||
anchor.lo anchor.o: $(srcdir)/anchor.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/anchor.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/anchor.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/yxml/yxml.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/dnssec.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/yxml/yxml.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/str2wire.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h \
|
||||
$(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
const-info.lo const-info.o: $(srcdir)/const-info.c \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/const-info.h
|
||||
context.lo context.o: $(srcdir)/context.c \
|
||||
config.h \
|
||||
$(srcdir)/anchor.h \
|
||||
config.h $(srcdir)/anchor.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/debug.h \
|
||||
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/dnssec.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h $(srcdir)/ssl_dane/danessl.h
|
||||
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/tls.h \
|
||||
$(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h $(srcdir)/const-info.h
|
||||
convert.lo convert.o: $(srcdir)/convert.c \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.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)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
|
||||
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
|
||||
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \
|
||||
$(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h
|
||||
dict.lo dict.o: $(srcdir)/dict.c \
|
||||
config.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)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h \
|
||||
$(srcdir)/debug.h
|
||||
dict.lo dict.o: $(srcdir)/dict.c config.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/parseutil.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/dict.h $(srcdir)/list.h \
|
||||
$(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/parseutil.h
|
||||
dnssec.lo dnssec.o: $(srcdir)/dnssec.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/context.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h \
|
||||
$(srcdir)/util/orig-headers/val_secalgo.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h \
|
||||
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h \
|
||||
$(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h $(srcdir)/gldns/gbuffer.h
|
||||
general.lo general.o: $(srcdir)/general.c \
|
||||
config.h \
|
||||
$(srcdir)/general.h \
|
||||
config.h $(srcdir)/general.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
|
||||
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
|
||||
$(srcdir)/dict.h $(srcdir)/mdns.h $(srcdir)/platform.h
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h \
|
||||
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h $(srcdir)/mdns.h $(srcdir)/debug.h
|
||||
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h \
|
||||
config.h \
|
||||
$(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/list.h $(srcdir)/dict.h
|
||||
mdns.lo mdns.o: $(srcdir)/mdns.c \
|
||||
config.h \
|
||||
config.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/list.h $(srcdir)/dict.h
|
||||
mdns.lo mdns.o: $(srcdir)/mdns.c config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/context.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h \
|
||||
$(srcdir)/platform.h $(srcdir)/mdns.h $(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.h \
|
||||
$(srcdir)/util/orig-headers/lookup3.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/general.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/mdns.h
|
||||
platform.lo platform.o: $(srcdir)/platform.c $(srcdir)/platform.h \
|
||||
config.h
|
||||
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/context.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h \
|
||||
$(srcdir)/$(tlsdir)/pubkey-pinning-internal.h
|
||||
request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
|
||||
config.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
|
@ -425,11 +408,9 @@ request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/dict.h $(srcdir)/convert.h $(srcdir)/general.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/debug.h $(srcdir)/convert.h $(srcdir)/general.h
|
||||
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
@ -437,10 +418,8 @@ rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h \
|
||||
$(srcdir)/dict.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h \
|
||||
$(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/dict.h
|
||||
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
@ -451,12 +430,10 @@ server.lo server.o: $(srcdir)/server.c \
|
|||
getdns/getdns.h \
|
||||
$(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
stub.lo stub.o: $(srcdir)/stub.c \
|
||||
config.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)/debug.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
stub.lo stub.o: $(srcdir)/stub.c config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/stub.h \
|
||||
getdns/getdns.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)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h \
|
||||
$(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
|
||||
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/anchor.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h $(srcdir)/ssl_dane/danessl.h
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/anchor.h \
|
||||
$(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h \
|
||||
$(srcdir)/pubkey-pinning.h
|
||||
sync.lo sync.o: $(srcdir)/sync.c \
|
||||
getdns/getdns.h \
|
||||
config.h \
|
||||
$(srcdir)/context.h \
|
||||
config.h $(srcdir)/context.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/general.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
|
||||
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h
|
||||
config.h
|
||||
util-internal.lo util-internal.o: $(srcdir)/util-internal.c \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
$(srcdir)/dict.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/types-internal.h \
|
||||
getdns/getdns.h $(srcdir)/dict.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/types-internal.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
|
||||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
|
||||
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
|
||||
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/str2wire.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h
|
||||
$(srcdir)/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)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \
|
||||
$(srcdir)/gldns/rrdef.h
|
||||
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/gbuffer.h
|
||||
keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/rrdef.h
|
||||
parse.lo parse.o: $(srcdir)/gldns/parse.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h
|
||||
config.h $(srcdir)/gldns/parse.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h
|
||||
parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/parseutil.h
|
||||
rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c \
|
||||
config.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h
|
||||
config.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/gldns/parseutil.h
|
||||
str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \
|
||||
config.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 \
|
||||
config.h \
|
||||
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h \
|
||||
$(srcdir)/$(tlsdir)/keyraw-internal.h
|
||||
arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \
|
||||
config.h
|
||||
arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \
|
||||
|
@ -548,8 +518,8 @@ strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \
|
|||
strptime.lo strptime.o: $(srcdir)/compat/strptime.c \
|
||||
config.h
|
||||
locks.lo locks.o: $(srcdir)/util/locks.c \
|
||||
config.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h
|
||||
config.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h
|
||||
lookup3.lo lookup3.o: $(srcdir)/util/lookup3.c \
|
||||
config.h \
|
||||
$(srcdir)/util/auxiliary/util/storage/lookup3.h $(srcdir)/util/lookup3.h \
|
||||
|
@ -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/fptr_wlist.h $(srcdir)/util/auxiliary/util/fptr_wlist.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h
|
||||
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \
|
||||
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 \
|
||||
$(srcdir)/util/auxiliary/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/auxiliary/validator/val_secalgo.h $(srcdir)/util/val_secalgo.h \
|
||||
$(srcdir)/util/orig-headers/val_secalgo.h $(srcdir)/util/auxiliary/validator/val_nsec3.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/gldns/rrdef.h
|
||||
pubkey-pinning-internal.lo pubkey-pinning-internal.o: $(srcdir)/$(tlsdir)/pubkey-pinning-internal.c $(srcdir)/context.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)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \
|
||||
$(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h
|
||||
jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
|
||||
$(srcdir)/$(tlsdir)/keyraw-internal.h $(srcdir)/util/auxiliary/sldns/sbuffer.h
|
||||
yxml.lo yxml.o: $(srcdir)/yxml/yxml.c $(srcdir)/yxml/yxml.h
|
||||
danessl.lo danessl.o: $(srcdir)/ssl_dane/danessl.c $(srcdir)/ssl_dane/danessl.h
|
||||
libev.lo libev.o: $(srcdir)/extension/libev.c \
|
||||
config.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
|
@ -588,8 +582,8 @@ libevent.lo libevent.o: $(srcdir)/extension/libevent.c \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h
|
||||
libuv.lo libuv.o: $(srcdir)/extension/libuv.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/types-internal.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h
|
||||
|
@ -600,13 +594,11 @@ poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \
|
|||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/platform.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/tls.h $(srcdir)/$(tlsdir)/tls-internal.h $(srcdir)/platform.h $(srcdir)/debug.h
|
||||
select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/types-internal.h \
|
||||
config.h $(srcdir)/debug.h \
|
||||
$(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/platform.h \
|
||||
|
|
393
src/anchor.c
393
src/anchor.c
|
@ -33,9 +33,6 @@
|
|||
#include "debug.h"
|
||||
#include "anchor.h"
|
||||
#include <fcntl.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include <strings.h>
|
||||
#include <time.h>
|
||||
#include "types-internal.h"
|
||||
|
@ -52,141 +49,6 @@
|
|||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
|
||||
/* get key usage out of its extension, returns 0 if no key_usage extension */
|
||||
static unsigned long
|
||||
_getdns_get_usage_of_ex(X509* cert)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
ASN1_BIT_STRING* s;
|
||||
|
||||
if((s=X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL))) {
|
||||
if(s->length > 0) {
|
||||
val = s->data[0];
|
||||
if(s->length > 1)
|
||||
val |= s->data[1] << 8;
|
||||
}
|
||||
ASN1_BIT_STRING_free(s);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/** get valid signers from the list of signers in the signature */
|
||||
static STACK_OF(X509)*
|
||||
_getdns_get_valid_signers(PKCS7* p7, const char* p7signer)
|
||||
{
|
||||
int i;
|
||||
STACK_OF(X509)* validsigners = sk_X509_new_null();
|
||||
STACK_OF(X509)* signers = PKCS7_get0_signers(p7, NULL, 0);
|
||||
unsigned long usage = 0;
|
||||
if(!validsigners) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed to allocated validsigners\n"
|
||||
, __FUNC__);
|
||||
sk_X509_free(signers);
|
||||
return NULL;
|
||||
}
|
||||
if(!signers) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed to allocated signers\n"
|
||||
, __FUNC__);
|
||||
sk_X509_free(validsigners);
|
||||
return NULL;
|
||||
}
|
||||
for(i=0; i<sk_X509_num(signers); i++) {
|
||||
char buf[1024];
|
||||
X509_NAME* nm = X509_get_subject_name(
|
||||
sk_X509_value(signers, i));
|
||||
if(!nm) {
|
||||
DEBUG_ANCHOR("%s(): cert %d has no subject name\n"
|
||||
, __FUNC__, i);
|
||||
continue;
|
||||
}
|
||||
if(!p7signer || strcmp(p7signer, "")==0) {
|
||||
/* there is no name to check, return all records */
|
||||
DEBUG_ANCHOR("%s(): did not check commonName of signer\n"
|
||||
, __FUNC__);
|
||||
} else {
|
||||
if(!X509_NAME_get_text_by_NID(nm,
|
||||
NID_pkcs9_emailAddress,
|
||||
buf, (int)sizeof(buf))) {
|
||||
DEBUG_ANCHOR("%s(): removed cert with no name\n"
|
||||
, __FUNC__);
|
||||
continue; /* no name, no use */
|
||||
}
|
||||
if(strcmp(buf, p7signer) != 0) {
|
||||
DEBUG_ANCHOR("%s(): removed cert with wrong name\n"
|
||||
, __FUNC__);
|
||||
continue; /* wrong name, skip it */
|
||||
}
|
||||
}
|
||||
|
||||
/* check that the key usage allows digital signatures
|
||||
* (the p7s) */
|
||||
usage = _getdns_get_usage_of_ex(sk_X509_value(signers, i));
|
||||
if(!(usage & KU_DIGITAL_SIGNATURE)) {
|
||||
DEBUG_ANCHOR("%s(): removed cert with no key usage "
|
||||
"Digital Signature allowed\n"
|
||||
, __FUNC__);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we like this cert, add it to our list of valid
|
||||
* signers certificates */
|
||||
sk_X509_push(validsigners, sk_X509_value(signers, i));
|
||||
}
|
||||
sk_X509_free(signers);
|
||||
return validsigners;
|
||||
}
|
||||
|
||||
static int
|
||||
_getdns_verify_p7sig(BIO* data, BIO* p7s, X509_STORE *store, const char* p7signer)
|
||||
{
|
||||
PKCS7* p7;
|
||||
STACK_OF(X509)* validsigners;
|
||||
int secure = 0;
|
||||
#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
|
||||
X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new();
|
||||
if(!param) {
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed to allocated param\n"
|
||||
, __FUNC__);
|
||||
return 0;
|
||||
}
|
||||
/* do the selfcheck on the root certificate; it checks that the
|
||||
* input is valid */
|
||||
X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CHECK_SS_SIGNATURE);
|
||||
X509_STORE_set1_param(store, param);
|
||||
X509_VERIFY_PARAM_free(param);
|
||||
#endif
|
||||
(void)BIO_reset(p7s);
|
||||
(void)BIO_reset(data);
|
||||
|
||||
/* convert p7s to p7 (the signature) */
|
||||
p7 = d2i_PKCS7_bio(p7s, NULL);
|
||||
if(!p7) {
|
||||
DEBUG_ANCHOR("ERROR %s(): could not parse p7s signature file\n"
|
||||
, __FUNC__);
|
||||
return 0;
|
||||
}
|
||||
/* check what is in the Subject name of the certificates,
|
||||
* and build a stack that contains only the right certificates */
|
||||
validsigners = _getdns_get_valid_signers(p7, p7signer);
|
||||
if(!validsigners) {
|
||||
PKCS7_free(p7);
|
||||
return 0;
|
||||
}
|
||||
if(PKCS7_verify(p7, validsigners, store, data, NULL, PKCS7_NOINTERN) == 1) {
|
||||
secure = 1;
|
||||
}
|
||||
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
|
||||
else {
|
||||
DEBUG_ANCHOR("ERROR %s(): the PKCS7 signature did not verify\n"
|
||||
, __FUNC__);
|
||||
ERR_print_errors_cb(_getdns_ERR_print_errors_cb_f, NULL);
|
||||
}
|
||||
#endif
|
||||
sk_X509_free(validsigners);
|
||||
PKCS7_free(p7);
|
||||
return secure;
|
||||
}
|
||||
|
||||
typedef struct ta_iter {
|
||||
uint8_t yxml_buf[4096];
|
||||
yxml_t x;
|
||||
|
@ -206,6 +68,15 @@ typedef struct ta_iter {
|
|||
char digest[2048];
|
||||
} ta_iter;
|
||||
|
||||
static void strcpytrunc(char* dst, const char* src, size_t dstsize)
|
||||
{
|
||||
size_t to_copy = strlen(src);
|
||||
if (to_copy >= dstsize)
|
||||
to_copy = dstsize -1;
|
||||
memcpy(dst, src, to_copy);
|
||||
dst[to_copy] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* XML convert DateTime element to time_t.
|
||||
* [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
|
||||
|
@ -213,7 +84,7 @@ typedef struct ta_iter {
|
|||
* @param str: the string
|
||||
* @return a time_t representation or 0 on failure.
|
||||
*/
|
||||
static time_t
|
||||
time_t
|
||||
_getdns_xml_convertdate(const char* str)
|
||||
{
|
||||
time_t t = 0;
|
||||
|
@ -328,8 +199,8 @@ static ta_iter *ta_iter_next(ta_iter *ta)
|
|||
|
||||
else if (level == 0 && cur) {
|
||||
/* <Zone> content ready */
|
||||
(void) strncpy( ta->zone, value
|
||||
, sizeof(ta->zone));
|
||||
strcpytrunc( ta->zone, value
|
||||
, sizeof(ta->zone));
|
||||
|
||||
/* Reset to start of <TrustAnchor> */
|
||||
cur = NULL;
|
||||
|
@ -504,20 +375,20 @@ static ta_iter *ta_iter_next(ta_iter *ta)
|
|||
DEBUG_ANCHOR("elem end: %s\n", value);
|
||||
switch (elem_type) {
|
||||
case KEYTAG:
|
||||
(void) strncpy( ta->keytag, value
|
||||
, sizeof(ta->keytag));
|
||||
strcpytrunc( ta->keytag, value
|
||||
, sizeof(ta->keytag));
|
||||
break;
|
||||
case ALGORITHM:
|
||||
(void) strncpy( ta->algorithm, value
|
||||
, sizeof(ta->algorithm));
|
||||
strcpytrunc( ta->algorithm, value
|
||||
, sizeof(ta->algorithm));
|
||||
break;
|
||||
case DIGESTTYPE:
|
||||
(void) strncpy( ta->digesttype, value
|
||||
, sizeof(ta->digesttype));
|
||||
strcpytrunc( ta->digesttype, value
|
||||
, sizeof(ta->digesttype));
|
||||
break;
|
||||
case DIGEST:
|
||||
(void) strncpy( ta->digest, value
|
||||
, sizeof(ta->digest));
|
||||
strcpytrunc( ta->digest, value
|
||||
, sizeof(ta->digest));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -558,7 +429,7 @@ static ta_iter *ta_iter_init(ta_iter *ta, const char *doc, size_t doc_len)
|
|||
return ta_iter_next(ta);
|
||||
}
|
||||
|
||||
static uint16_t _getdns_parse_xml_trust_anchors_buf(
|
||||
uint16_t _getdns_parse_xml_trust_anchors_buf(
|
||||
gldns_buffer *gbuf, uint64_t *now_ms, char *xml_data, size_t xml_len)
|
||||
{
|
||||
ta_iter ta_spc, *ta;
|
||||
|
@ -647,226 +518,6 @@ static uint16_t _getdns_parse_xml_trust_anchors_buf(
|
|||
return ta_count;
|
||||
}
|
||||
|
||||
static uint8_t *tas_validate(struct mem_funcs *mf,
|
||||
const getdns_bindata *xml_bd, const getdns_bindata *p7s_bd,
|
||||
const getdns_bindata *crt_bd, const char *p7signer,
|
||||
uint64_t *now_ms, uint8_t *tas, size_t *tas_len)
|
||||
{
|
||||
BIO *xml = NULL, *p7s = NULL, *crt = NULL;
|
||||
X509 *x = NULL;
|
||||
X509_STORE *store = NULL;
|
||||
uint8_t *success = NULL;
|
||||
|
||||
if (!(xml = BIO_new_mem_buf(xml_bd->data, xml_bd->size)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating xml BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(p7s = BIO_new_mem_buf(p7s_bd->data, p7s_bd->size)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating p7s BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(crt = BIO_new_mem_buf(crt_bd->data, crt_bd->size)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating crt BIO\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
|
||||
DEBUG_ANCHOR("ERROR %s(): Parsing builtin certificate\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!(store = X509_STORE_new()))
|
||||
DEBUG_ANCHOR("ERROR %s(): Failed allocating store\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (!X509_STORE_add_cert(store, x))
|
||||
DEBUG_ANCHOR("ERROR %s(): Adding certificate to store\n"
|
||||
, __FUNC__);
|
||||
|
||||
else if (_getdns_verify_p7sig(xml, p7s, store, p7signer)) {
|
||||
gldns_buffer gbuf;
|
||||
|
||||
gldns_buffer_init_vfixed_frm_data(&gbuf, tas, *tas_len);
|
||||
|
||||
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf, now_ms,
|
||||
(char *)xml_bd->data, xml_bd->size))
|
||||
DEBUG_ANCHOR("Failed to parse trust anchor XML data");
|
||||
|
||||
else if (gldns_buffer_position(&gbuf) > *tas_len) {
|
||||
*tas_len = gldns_buffer_position(&gbuf);
|
||||
if ((success = GETDNS_XMALLOC(*mf, uint8_t, *tas_len))) {
|
||||
gldns_buffer_init_frm_data(&gbuf, success, *tas_len);
|
||||
if (!_getdns_parse_xml_trust_anchors_buf(&gbuf,
|
||||
now_ms, (char *)xml_bd->data, xml_bd->size)) {
|
||||
|
||||
DEBUG_ANCHOR("Failed to re-parse trust"
|
||||
" anchor XML data\n");
|
||||
GETDNS_FREE(*mf, success);
|
||||
success = NULL;
|
||||
}
|
||||
} else
|
||||
DEBUG_ANCHOR("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[] =
|
||||
"GET %s HTTP/1.1\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: "
|
||||
"\"%s\"\n", getdns_get_errorstr_by_id(r));
|
||||
|
||||
else if (!(tas = tas_validate(&context->mf, &a->xml, &p7s_bd,
|
||||
else if (!(tas = _getdns_tas_validate(&context->mf, &a->xml, &p7s_bd,
|
||||
&verify_CA, verify_email, &now_ms, tas, &tas_len)))
|
||||
; /* pass */
|
||||
|
||||
|
|
23
src/anchor.h
23
src/anchor.h
|
@ -39,6 +39,29 @@
|
|||
#include <time.h>
|
||||
#include "rr-iter.h"
|
||||
|
||||
#include "types-internal.h"
|
||||
|
||||
/**
|
||||
** Internal functions, implemented in anchor-internal.c.
|
||||
**/
|
||||
void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms);
|
||||
|
||||
uint8_t *_getdns_tas_validate(struct mem_funcs *mf,
|
||||
const getdns_bindata *xml_bd, const getdns_bindata *p7s_bd,
|
||||
const getdns_bindata *crt_bd, const char *p7signer,
|
||||
uint64_t *now_ms, uint8_t *tas, size_t *tas_len);
|
||||
|
||||
|
||||
/**
|
||||
** anchor.c functions used by anchor-internal.c.
|
||||
**/
|
||||
time_t _getdns_xml_convertdate(const char* str);
|
||||
|
||||
uint16_t _getdns_parse_xml_trust_anchors_buf(gldns_buffer *gbuf, uint64_t *now_ms, char *xml_data, size_t xml_len);
|
||||
|
||||
/**
|
||||
** Public interface.
|
||||
**/
|
||||
void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms);
|
||||
|
||||
void _getdns_start_fetching_ta(
|
||||
|
|
|
@ -171,6 +171,9 @@ _rs_init(u_char *buf, size_t n)
|
|||
if(!rsx)
|
||||
abort();
|
||||
#endif
|
||||
/* Pleast older clang scan-build */
|
||||
if (!buf)
|
||||
buf = rsx->rs_buf;
|
||||
}
|
||||
|
||||
chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
|
||||
|
|
466
src/context.c
466
src/context.c
|
@ -47,20 +47,12 @@
|
|||
#include <iphlpapi.h>
|
||||
typedef unsigned short in_port_t;
|
||||
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -90,10 +82,8 @@ typedef unsigned short in_port_t;
|
|||
#include "list.h"
|
||||
#include "dict.h"
|
||||
#include "pubkey-pinning.h"
|
||||
#ifdef USE_DANESSL
|
||||
# include "ssl_dane/danessl.h"
|
||||
#endif
|
||||
#include "const-info.h"
|
||||
#include "tls.h"
|
||||
|
||||
#define GETDNS_PORT_ZERO 0
|
||||
#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*
|
||||
upstream_addr(getdns_upstream *upstream)
|
||||
{
|
||||
|
@ -762,14 +634,11 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
|||
}
|
||||
}
|
||||
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) {
|
||||
SSL_shutdown(upstream->tls_obj);
|
||||
#ifdef USE_DANESSL
|
||||
DANESSL_cleanup(upstream->tls_obj);
|
||||
#endif
|
||||
SSL_free(upstream->tls_obj);
|
||||
_getdns_tls_connection_shutdown(upstream->tls_obj);
|
||||
_getdns_tls_connection_free(&upstreams->mf, upstream->tls_obj);
|
||||
}
|
||||
if (upstream->fd != -1)
|
||||
{
|
||||
|
@ -867,11 +736,8 @@ _getdns_upstream_reset(getdns_upstream *upstream)
|
|||
upstream->loop, &upstream->event);
|
||||
}
|
||||
if (upstream->tls_obj != NULL) {
|
||||
SSL_shutdown(upstream->tls_obj);
|
||||
#ifdef USE_DANESSL
|
||||
DANESSL_cleanup(upstream->tls_obj);
|
||||
#endif
|
||||
SSL_free(upstream->tls_obj);
|
||||
_getdns_tls_connection_shutdown(upstream->tls_obj);
|
||||
_getdns_tls_connection_free(&upstream->upstreams->mf, upstream->tls_obj);
|
||||
upstream->tls_obj = NULL;
|
||||
}
|
||||
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 =
|
||||
"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
|
||||
*
|
||||
|
@ -1692,18 +1547,7 @@ getdns_context_create_with_extended_memory_functions(
|
|||
#endif
|
||||
/* Only initialise SSL once and ideally in a thread-safe manner */
|
||||
if (ssl_init == false) {
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
OpenSSL_add_all_algorithms();
|
||||
SSL_library_init();
|
||||
# ifdef USE_DANESSL
|
||||
(void) DANESSL_library_init();
|
||||
# endif
|
||||
#else
|
||||
OPENSSL_init_crypto( OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(0, NULL);
|
||||
#endif
|
||||
_getdns_tls_init();
|
||||
ssl_init = true;
|
||||
}
|
||||
#ifdef HAVE_PTHREAD
|
||||
|
@ -1829,7 +1673,7 @@ getdns_context_destroy(struct getdns_context *context)
|
|||
GETDNS_FREE(context->my_mf, context->dns_transports);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -3718,8 +3562,6 @@ getdns_return_t
|
|||
_getdns_context_prepare_for_resolution(getdns_context *context)
|
||||
{
|
||||
getdns_return_t r;
|
||||
char ssl_err[256];
|
||||
int osr;
|
||||
|
||||
assert(context);
|
||||
if (context->destroying)
|
||||
|
@ -3741,256 +3583,63 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
|
|||
}
|
||||
|
||||
if (context->tls_ctx == NULL) {
|
||||
#ifdef HAVE_TLS_v1_2
|
||||
/* Create client context, use TLS v1.2 only for now */
|
||||
# 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);
|
||||
context->tls_ctx = _getdns_tls_context_new(&context->my_mf, &context->log);
|
||||
if (context->tls_ctx == NULL)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
}
|
||||
|
||||
# if defined(HAVE_DECL_SSL_SET_MIN_PROTO_VERSION) \
|
||||
&& HAVE_DECL_SSL_SET_MIN_PROTO_VERSION
|
||||
if (!SSL_CTX_set_min_proto_version(context->tls_ctx,
|
||||
_getdns_tls_version2openssl_version(
|
||||
context->tls_min_version))) {
|
||||
SSL_CTX_free(context->tls_ctx);
|
||||
r = _getdns_tls_context_set_min_max_tls_version(context->tls_ctx, context->tls_min_version, context->tls_max_version);
|
||||
if (r) {
|
||||
_getdns_tls_context_free(&context->my_mf, context->tls_ctx);
|
||||
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 configuring TLS context with "
|
||||
"minimum TLS version"
|
||||
, ssl_err);
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
return r;
|
||||
}
|
||||
if (context->tls_max_version
|
||||
&& !SSL_CTX_set_max_proto_version(context->tls_ctx,
|
||||
_getdns_tls_version2openssl_version(
|
||||
context->tls_max_version))) {
|
||||
SSL_CTX_free(context->tls_ctx);
|
||||
|
||||
/* Be strict and only use the cipher suites recommended in RFC7525
|
||||
Unless we later fallback to opportunistic. */
|
||||
r = _getdns_tls_context_set_cipher_list(context->tls_ctx, context->tls_cipher_list);
|
||||
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;
|
||||
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 "
|
||||
"maximum TLS version"
|
||||
, ssl_err);
|
||||
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
}
|
||||
# else
|
||||
# ifndef HAVE_TLS_CLIENT_METHOD
|
||||
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 {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* For strict authentication, we must have local root certs available
|
||||
Set up is done only when the tls_ctx is created (per getdns_context)*/
|
||||
if (_getdns_tls_context_set_ca(context->tls_ctx, context->tls_ca_file, context->tls_ca_path)) {
|
||||
if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) {
|
||||
_getdns_log(&context->log
|
||||
, GETDNS_LOG_SYS_STUB
|
||||
, GETDNS_LOG_DEBUG
|
||||
, "%s: %s\n"
|
||||
, 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)
|
||||
; /* 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 */
|
||||
_getdns_tls_context_pinset_init(context->tls_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
* 53 so it is blocked here. */
|
||||
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
||||
&& tls_only_is_in_transports_list(context) == 1) {
|
||||
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING &&
|
||||
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
|
||||
, "TLS only transport is not supported for the recursing "
|
||||
"resolution type");
|
||||
_getdns_tls_context_free(&context->my_mf, context->tls_ctx);
|
||||
context->tls_ctx = NULL;
|
||||
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
}
|
||||
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(
|
||||
result, "default_hosts_location", GETDNS_FN_HOSTS)
|
||||
|
||||
&& ! getdns_dict_set_int(
|
||||
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_tls_get_api_information(result)
|
||||
|
||||
&& ! getdns_dict_set_int(
|
||||
result, "resolution_type", context->resolution_type)
|
||||
|
@ -5658,7 +5282,7 @@ getdns_context_get_tls_cipher_list(
|
|||
|
||||
*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;
|
||||
}
|
||||
|
||||
|
@ -5687,7 +5311,7 @@ getdns_context_get_tls_ciphersuites(
|
|||
|
||||
*tls_ciphersuites = context->tls_ciphersuites
|
||||
? context->tls_ciphersuites
|
||||
: _getdns_default_tls_ciphersuites;
|
||||
: _getdns_tls_context_get_default_cipher_suites();
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
|
@ -5697,7 +5321,7 @@ getdns_context_set_tls_curves_list(
|
|||
{
|
||||
if (!context)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
#if defined(HAVE_DECL_SSL_CTX_SET1_CURVES_LIST) && HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
|
||||
#if HAVE_TLS_CTX_CURVES_LIST
|
||||
if (context->tls_curves_list)
|
||||
GETDNS_FREE(context->mf, context->tls_curves_list);
|
||||
context->tls_curves_list = tls_curves_list
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#endif
|
||||
#include "rr-iter.h"
|
||||
#include "anchor.h"
|
||||
#include "tls.h"
|
||||
|
||||
struct getdns_dns_req;
|
||||
struct ub_ctx;
|
||||
|
@ -200,9 +201,9 @@ typedef struct getdns_upstream {
|
|||
getdns_network_req *write_queue_last;
|
||||
_getdns_rbtree_t netreq_by_query_id;
|
||||
|
||||
/* TLS specific connection handling */
|
||||
SSL* tls_obj;
|
||||
SSL_SESSION* tls_session;
|
||||
/* TLS specific connection handling*/
|
||||
_getdns_tls_connection* tls_obj;
|
||||
_getdns_tls_session* tls_session;
|
||||
getdns_tls_hs_state_t tls_hs_state;
|
||||
getdns_auth_state_t tls_auth_state;
|
||||
unsigned tls_fallback_ok : 1;
|
||||
|
@ -382,7 +383,7 @@ struct getdns_context {
|
|||
int edns_maximum_udp_payload_size; /* -1 is unset */
|
||||
uint8_t edns_client_subnet_private;
|
||||
uint16_t tls_query_padding_blocksize;
|
||||
SSL_CTX* tls_ctx;
|
||||
_getdns_tls_context* tls_ctx;
|
||||
|
||||
getdns_update_callback update_callback;
|
||||
getdns_update_callback2 update_callback2;
|
||||
|
|
|
@ -194,7 +194,6 @@
|
|||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <openssl/sha.h>
|
||||
#include "getdns/getdns.h"
|
||||
#include "context.h"
|
||||
#include "util-internal.h"
|
||||
|
@ -210,6 +209,7 @@
|
|||
#include "list.h"
|
||||
#include "util/val_secalgo.h"
|
||||
#include "anchor.h"
|
||||
#include "tls.h"
|
||||
|
||||
#define SIGNATURE_VERIFIED 0x10000
|
||||
#define NSEC3_ITERATION_COUNT_HIGH 0x20000
|
||||
|
@ -1584,12 +1584,12 @@ static uint8_t *_getdns_nsec3_hash_label(uint8_t *label, size_t label_len,
|
|||
(void)memcpy(dst, salt + 1, *salt);
|
||||
dst += *salt;
|
||||
|
||||
(void)SHA1(buf, dst - buf, md);
|
||||
_getdns_tls_sha1(buf, dst - buf, md);
|
||||
if (iterations) {
|
||||
(void)memcpy(buf + SHA_DIGEST_LENGTH, salt + 1, *salt);
|
||||
while (iterations--) {
|
||||
(void)memcpy(buf, md, SHA_DIGEST_LENGTH);
|
||||
SHA1(buf, SHA_DIGEST_LENGTH + *salt, md);
|
||||
_getdns_tls_sha1(buf, SHA_DIGEST_LENGTH + *salt, md);
|
||||
}
|
||||
}
|
||||
*label = gldns_b32_ntop_extended_hex(
|
||||
|
|
|
@ -251,10 +251,18 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
|||
|
||||
#ifdef HAVE_LIBUNBOUND
|
||||
#ifdef HAVE_UNBOUND_EVENT_API
|
||||
#if UNBOUND_VERSION_MAJOR > 1 || (UNBOUND_VERSION_MAJOR == 1 && UNBOUND_VERSION_MINOR >= 8)
|
||||
static void
|
||||
ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len,
|
||||
int sec, char* why_bogus, int was_ratelimited)
|
||||
{
|
||||
(void) was_ratelimited;
|
||||
#else
|
||||
static void
|
||||
ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len,
|
||||
int sec, char* why_bogus)
|
||||
{
|
||||
#endif
|
||||
getdns_network_req *netreq = (getdns_network_req *) arg;
|
||||
getdns_dns_req *dns_req = netreq->owner;
|
||||
|
||||
|
|
|
@ -14,29 +14,6 @@
|
|||
#include "gldns/keyraw.h"
|
||||
#include "gldns/rrdef.h"
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md5.h>
|
||||
#ifdef HAVE_OPENSSL_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
|
||||
gldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
|
|
@ -20,13 +20,11 @@
|
|||
#ifndef GLDNS_KEYRAW_H
|
||||
#define GLDNS_KEYRAW_H
|
||||
|
||||
#include "keyraw-internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if GLDNS_BUILD_CONFIG_HAVE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/evp.h>
|
||||
#endif /* GLDNS_BUILD_CONFIG_HAVE_SSL */
|
||||
|
||||
/**
|
||||
* get the length of the keydata in bits
|
||||
|
@ -46,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);
|
||||
|
||||
#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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* keyraw.c - raw key operations and conversions - OpenSSL version
|
||||
*
|
||||
* (c) NLnet Labs, 2004-2008
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Implementation of raw DNSKEY functions (work on wire rdata).
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "gldns/keyraw.h"
|
||||
#include "gldns/rrdef.h"
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* keyraw.h -- raw key and signature access and conversion - OpenSSL
|
||||
*
|
||||
* Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* See LICENSE for the license.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* raw key and signature access and conversion
|
||||
*
|
||||
* Since those functions heavily rely op cryptographic operations,
|
||||
* this module is dependent on openssl.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLDNS_KEYRAW_INTERNAL_H
|
||||
#define GLDNS_KEYRAW_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GLDNS_KEYRAW_INTERNAL_H */
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
*
|
||||
* /brief functions for dealing with pubkey pinsets
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 ACLU
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "context.h"
|
||||
#include <nettle/base64.h>
|
||||
|
||||
#include "types-internal.h"
|
||||
|
||||
#include "pubkey-pinning.h"
|
||||
|
||||
/**
|
||||
** Interfaces from pubkey-pinning.h
|
||||
**/
|
||||
|
||||
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size)
|
||||
{
|
||||
struct base64_decode_ctx ctx;
|
||||
uint8_t* lim = res + res_size;
|
||||
|
||||
base64_decode_init(&ctx);
|
||||
|
||||
for(; *str != '\0' && res < lim; ++str) {
|
||||
int r = base64_decode_single(&ctx, res, *str);
|
||||
if (r == -1 )
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
res += r;
|
||||
}
|
||||
return (res == lim) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
|
@ -0,0 +1,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 */
|
|
@ -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 */
|
|
@ -0,0 +1 @@
|
|||
../openssl/val_secalgo.c
|
|
@ -0,0 +1 @@
|
|||
../openssl/validator
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* keyraw.c - raw key operations and conversions - OpenSSL version
|
||||
*
|
||||
* (c) NLnet Labs, 2004-2008
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Implementation of raw DNSKEY functions (work on wire rdata).
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "gldns/keyraw.h"
|
||||
#include "gldns/rrdef.h"
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md5.h>
|
||||
#ifdef HAVE_OPENSSL_CONF_H
|
||||
# include <openssl/conf.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_ENGINE_H
|
||||
# include <openssl/engine.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_BN_H
|
||||
#include <openssl/bn.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_RSA_H
|
||||
#include <openssl/rsa.h>
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_DSA_H
|
||||
#include <openssl/dsa.h>
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef USE_GOST
|
||||
|
||||
/** store GOST engine reference loaded into OpenSSL library */
|
||||
#ifdef OPENSSL_NO_ENGINE
|
||||
int
|
||||
gldns_key_EVP_load_gost_id(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void gldns_key_EVP_unload_gost(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
ENGINE* gldns_gost_engine = NULL;
|
||||
|
||||
int
|
||||
gldns_key_EVP_load_gost_id(void)
|
||||
{
|
||||
static int gost_id = 0;
|
||||
const EVP_PKEY_ASN1_METHOD* meth;
|
||||
ENGINE* e;
|
||||
|
||||
if(gost_id) return gost_id;
|
||||
|
||||
/* see if configuration loaded gost implementation from other engine*/
|
||||
meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
|
||||
if(meth) {
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
|
||||
/* see if engine can be loaded already */
|
||||
e = ENGINE_by_id("gost");
|
||||
if(!e) {
|
||||
/* load it ourself, in case statically linked */
|
||||
ENGINE_load_builtin_engines();
|
||||
ENGINE_load_dynamic();
|
||||
e = ENGINE_by_id("gost");
|
||||
}
|
||||
if(!e) {
|
||||
/* no gost engine in openssl */
|
||||
return 0;
|
||||
}
|
||||
if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
|
||||
if(!meth) {
|
||||
/* algo not found */
|
||||
ENGINE_finish(e);
|
||||
ENGINE_free(e);
|
||||
return 0;
|
||||
}
|
||||
/* Note: do not ENGINE_finish and ENGINE_free the acquired engine
|
||||
* on some platforms this frees up the meth and unloads gost stuff */
|
||||
gldns_gost_engine = e;
|
||||
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
|
||||
void gldns_key_EVP_unload_gost(void)
|
||||
{
|
||||
if(gldns_gost_engine) {
|
||||
ENGINE_finish(gldns_gost_engine);
|
||||
ENGINE_free(gldns_gost_engine);
|
||||
gldns_gost_engine = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* ifndef OPENSSL_NO_ENGINE */
|
||||
#endif /* USE_GOST */
|
||||
|
||||
DSA *
|
||||
gldns_key_buf2dsa_raw(unsigned char* key, size_t len)
|
||||
{
|
||||
uint8_t T;
|
||||
uint16_t length;
|
||||
uint16_t offset;
|
||||
DSA *dsa;
|
||||
BIGNUM *Q; BIGNUM *P;
|
||||
BIGNUM *G; BIGNUM *Y;
|
||||
|
||||
if(len == 0)
|
||||
return NULL;
|
||||
T = (uint8_t)key[0];
|
||||
length = (64 + T * 8);
|
||||
offset = 1;
|
||||
|
||||
if (T > 8) {
|
||||
return NULL;
|
||||
}
|
||||
if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
|
||||
return NULL;
|
||||
|
||||
Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
|
||||
offset += SHA_DIGEST_LENGTH;
|
||||
|
||||
P = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
offset += length;
|
||||
|
||||
G = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
offset += length;
|
||||
|
||||
Y = BN_bin2bn(key+offset, (int)length, NULL);
|
||||
|
||||
/* create the key and set its properties */
|
||||
if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
|
||||
BN_free(Q);
|
||||
BN_free(P);
|
||||
BN_free(G);
|
||||
BN_free(Y);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(HAVE_DSA_SET0_PQG) && defined(HAVE_DSA_SET0_KEY)
|
||||
if (!DSA_set0_pqg(dsa, P, Q, G)) {
|
||||
/* QPG not yet attached, need to free */
|
||||
BN_free(Q);
|
||||
BN_free(P);
|
||||
BN_free(G);
|
||||
|
||||
DSA_free(dsa);
|
||||
BN_free(Y);
|
||||
return NULL;
|
||||
}
|
||||
if (!DSA_set0_key(dsa, Y, NULL)) {
|
||||
/* QPG attached, cleaned up by DSA_fre() */
|
||||
DSA_free(dsa);
|
||||
BN_free(Y);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
# ifndef S_SPLINT_S
|
||||
dsa->p = P;
|
||||
dsa->q = Q;
|
||||
dsa->g = G;
|
||||
dsa->pub_key = Y;
|
||||
# endif /* splint */
|
||||
#endif
|
||||
|
||||
return dsa;
|
||||
}
|
||||
|
||||
RSA *
|
||||
gldns_key_buf2rsa_raw(unsigned char* key, size_t len)
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t exp;
|
||||
uint16_t int16;
|
||||
RSA *rsa;
|
||||
BIGNUM *modulus;
|
||||
BIGNUM *exponent;
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
if (key[0] == 0) {
|
||||
if(len < 3)
|
||||
return NULL;
|
||||
memmove(&int16, key+1, 2);
|
||||
exp = ntohs(int16);
|
||||
offset = 3;
|
||||
} else {
|
||||
exp = key[0];
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
/* key length at least one */
|
||||
if(len < (size_t)offset + exp + 1)
|
||||
return NULL;
|
||||
|
||||
/* Exponent */
|
||||
exponent = BN_new();
|
||||
if(!exponent) return NULL;
|
||||
(void) BN_bin2bn(key+offset, (int)exp, exponent);
|
||||
offset += exp;
|
||||
|
||||
/* Modulus */
|
||||
modulus = BN_new();
|
||||
if(!modulus) {
|
||||
BN_free(exponent);
|
||||
return NULL;
|
||||
}
|
||||
/* length of the buffer must match the key length! */
|
||||
(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
|
||||
|
||||
rsa = RSA_new();
|
||||
if(!rsa) {
|
||||
BN_free(exponent);
|
||||
BN_free(modulus);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(HAVE_RSA_SET0_KEY)
|
||||
if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
|
||||
BN_free(exponent);
|
||||
BN_free(modulus);
|
||||
RSA_free(rsa);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
# ifndef S_SPLINT_S
|
||||
rsa->n = modulus;
|
||||
rsa->e = exponent;
|
||||
# endif /* splint */
|
||||
#endif
|
||||
|
||||
return rsa;
|
||||
}
|
||||
|
||||
#ifdef USE_GOST
|
||||
EVP_PKEY*
|
||||
gldns_gost2pkey_raw(unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* prefix header for X509 encoding */
|
||||
uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
|
||||
0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
|
||||
unsigned char encoded[37+64];
|
||||
const unsigned char* pp;
|
||||
if(keylen != 64) {
|
||||
/* key wrong size */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create evp_key */
|
||||
memmove(encoded, asn, 37);
|
||||
memmove(encoded+37, key, 64);
|
||||
pp = (unsigned char*)&encoded[0];
|
||||
|
||||
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
|
||||
}
|
||||
#endif /* USE_GOST */
|
||||
|
||||
#ifdef USE_ECDSA
|
||||
EVP_PKEY*
|
||||
gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
|
||||
{
|
||||
unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
|
||||
const unsigned char* pp = buf;
|
||||
EVP_PKEY *evp_key;
|
||||
EC_KEY *ec;
|
||||
/* check length, which uncompressed must be 2 bignums */
|
||||
if(algo == GLDNS_ECDSAP256SHA256) {
|
||||
if(keylen != 2*256/8) return NULL;
|
||||
ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
} else if(algo == GLDNS_ECDSAP384SHA384) {
|
||||
if(keylen != 2*384/8) return NULL;
|
||||
ec = EC_KEY_new_by_curve_name(NID_secp384r1);
|
||||
} else ec = NULL;
|
||||
if(!ec) return NULL;
|
||||
if(keylen+1 > sizeof(buf)) { /* sanity check */
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
|
||||
* of openssl) for uncompressed data */
|
||||
buf[0] = POINT_CONVERSION_UNCOMPRESSED;
|
||||
memmove(buf+1, key, keylen);
|
||||
if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
evp_key = EVP_PKEY_new();
|
||||
if(!evp_key) {
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
|
||||
EVP_PKEY_free(evp_key);
|
||||
EC_KEY_free(ec);
|
||||
return NULL;
|
||||
}
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ECDSA */
|
||||
|
||||
#ifdef USE_ED25519
|
||||
EVP_PKEY*
|
||||
gldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
|
||||
uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
|
||||
0x70, 0x03, 0x21, 0x00};
|
||||
int pre_len = 12;
|
||||
uint8_t buf[256];
|
||||
EVP_PKEY *evp_key;
|
||||
/* pp gets modified by d2i() */
|
||||
const unsigned char* pp = (unsigned char*)buf;
|
||||
if(keylen != 32 || keylen + pre_len > sizeof(buf))
|
||||
return NULL; /* wrong length */
|
||||
memmove(buf, pre, pre_len);
|
||||
memmove(buf+pre_len, key, keylen);
|
||||
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ED25519 */
|
||||
|
||||
#ifdef USE_ED448
|
||||
EVP_PKEY*
|
||||
gldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
|
||||
uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
|
||||
0x71, 0x03, 0x3a, 0x00};
|
||||
int pre_len = 12;
|
||||
uint8_t buf[256];
|
||||
EVP_PKEY *evp_key;
|
||||
/* pp gets modified by d2i() */
|
||||
const unsigned char* pp = (unsigned char*)buf;
|
||||
if(keylen != 57 || keylen + pre_len > sizeof(buf))
|
||||
return NULL; /* wrong length */
|
||||
memmove(buf, pre, pre_len);
|
||||
memmove(buf+pre_len, key, keylen);
|
||||
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ED448 */
|
||||
|
||||
int
|
||||
gldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
|
||||
const EVP_MD* md)
|
||||
{
|
||||
EVP_MD_CTX* ctx;
|
||||
ctx = EVP_MD_CTX_create();
|
||||
if(!ctx)
|
||||
return 0;
|
||||
if(!EVP_DigestInit_ex(ctx, md, NULL) ||
|
||||
!EVP_DigestUpdate(ctx, data, len) ||
|
||||
!EVP_DigestFinal_ex(ctx, dest, NULL)) {
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
return 0;
|
||||
}
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
return 1;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* keyraw.h -- raw key and signature access and conversion - OpenSSL
|
||||
*
|
||||
* Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* See LICENSE for the license.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* raw key and signature access and conversion
|
||||
*
|
||||
* Since those functions heavily rely op cryptographic operations,
|
||||
* this module is dependent on openssl.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLDNS_KEYRAW_INTERNAL_H
|
||||
#define GLDNS_KEYRAW_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if GLDNS_BUILD_CONFIG_HAVE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/evp.h>
|
||||
|
||||
/**
|
||||
* Get the PKEY id for GOST, loads GOST into openssl as a side effect.
|
||||
* Only available if GOST is compiled into the library and openssl.
|
||||
* \return the gost id for EVP_CTX creation.
|
||||
*/
|
||||
int gldns_key_EVP_load_gost_id(void);
|
||||
|
||||
/** Release the engine reference held for the GOST engine. */
|
||||
void gldns_key_EVP_unload_gost(void);
|
||||
|
||||
/**
|
||||
* Like gldns_key_buf2dsa, but uses raw buffer.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return a DSA * structure with the key material
|
||||
*/
|
||||
DSA *gldns_key_buf2dsa_raw(unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with GOST.
|
||||
* \param[in] key data to convert
|
||||
* \param[in] keylen length of the key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_gost2pkey_raw(unsigned char* key, size_t keylen);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ECDSA.
|
||||
* \param[in] key data to convert
|
||||
* \param[in] keylen length of the key data
|
||||
* \param[in] algo precise algorithm to initialize ECC group values.
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
|
||||
|
||||
/**
|
||||
* Like gldns_key_buf2rsa, but uses raw buffer.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return a RSA * structure with the key material
|
||||
*/
|
||||
RSA *gldns_key_buf2rsa_raw(unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ED25519.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_ed255192pkey_raw(const unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ED448.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* gldns_ed4482pkey_raw(const unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Utility function to calculate hash using generic EVP_MD pointer.
|
||||
* \param[in] data the data to hash.
|
||||
* \param[in] len length of data.
|
||||
* \param[out] dest the destination of the hash, must be large enough.
|
||||
* \param[in] md the message digest to use.
|
||||
* \return true if worked, false on failure.
|
||||
*/
|
||||
int gldns_digest_evp(unsigned char* data, unsigned int len,
|
||||
unsigned char* dest, const EVP_MD* md);
|
||||
|
||||
#endif /* GLDNS_BUILD_CONFIG_HAVE_SSL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GLDNS_KEYRAW_INTERNAL_H */
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
*
|
||||
* /brief functions for Public Key Pinning
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015, Daniel Kahn Gillmor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* getdns Public Key Pinning
|
||||
*
|
||||
* a public key pinset is a list of dicts. each dict should have a
|
||||
* "digest" and a "value".
|
||||
*
|
||||
* "digest": a string indicating the type of digest. at the moment, we
|
||||
* only support a "digest" of "sha256".
|
||||
*
|
||||
* "value": a binary representation of the digest provided.
|
||||
*
|
||||
* given a such a pinset, we should be able to validate a chain
|
||||
* properly according to section 2.6 of RFC 7469.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include <getdns/getdns.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <string.h>
|
||||
#include "context.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
#include "pubkey-pinning-internal.h"
|
||||
|
||||
/* we only support sha256 at the moment. adding support for another
|
||||
digest is more complex than just adding another entry here. in
|
||||
particular, you'll probably need a match for a particular cert
|
||||
against all supported algorithms. better to wait on doing that
|
||||
until it is a better-understood problem (i.e. wait until hpkp is
|
||||
updated and follow the guidance in rfc7469bis)
|
||||
*/
|
||||
|
||||
/* b64 turns every 3 octets (or fraction thereof) into 4 octets */
|
||||
#define B64_ENCODED_SHA256_LENGTH (((SHA256_DIGEST_LENGTH + 2)/3) * 4)
|
||||
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size)
|
||||
{
|
||||
BIO *bio = NULL;
|
||||
char inbuf[B64_ENCODED_SHA256_LENGTH + 1];
|
||||
getdns_return_t ret = GETDNS_RETURN_GOOD;
|
||||
|
||||
/* openssl needs a trailing newline to base64 decode */
|
||||
memcpy(inbuf, str, B64_ENCODED_SHA256_LENGTH);
|
||||
inbuf[B64_ENCODED_SHA256_LENGTH] = '\n';
|
||||
|
||||
bio = BIO_push(BIO_new(BIO_f_base64()),
|
||||
BIO_new_mem_buf(inbuf, sizeof(inbuf)));
|
||||
if (BIO_read(bio, res, res_size) != (int) res_size)
|
||||
ret = GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
BIO_free_all(bio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* pubkey-pinning.c */
|
|
@ -0,0 +1,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 */
|
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -91,6 +91,7 @@ log_crypto_error(const char* str, unsigned long e)
|
|||
/* buf now contains */
|
||||
/* error:[error code]:[library name]:[function name]:[reason string] */
|
||||
log_err("%s crypto %s", str, buf);
|
||||
(void) str; /* In case log_err() does nothing. */
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
||||
#include "sha.h"
|
||||
#include "bignum.h"
|
||||
#include "macros.h"
|
||||
#include "rsa.h"
|
||||
#include "dsa.h"
|
||||
#include <nettle/sha.h>
|
||||
#include <nettle/bignum.h>
|
||||
#include <nettle/macros.h>
|
||||
#include <nettle/rsa.h>
|
||||
#include <nettle/dsa.h>
|
||||
#ifdef HAVE_NETTLE_DSA_COMPAT_H
|
||||
#include "dsa-compat.h"
|
||||
#include <nettle/dsa-compat.h>
|
||||
#endif
|
||||
#include "asn1.h"
|
||||
#include <nettle/asn1.h>
|
||||
#ifdef USE_ECDSA
|
||||
#include "ecdsa.h"
|
||||
#include "ecc-curve.h"
|
||||
#include <nettle/ecdsa.h>
|
||||
#include <nettle/ecc-curve.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETTLE_EDDSA_H
|
||||
#include "eddsa.h"
|
||||
#include <nettle/eddsa.h>
|
||||
#endif
|
||||
|
||||
static int
|
|
@ -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
|
|
@ -48,18 +48,13 @@
|
|||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include <getdns/getdns.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <string.h>
|
||||
#include "context.h"
|
||||
#include "util-internal.h"
|
||||
#include "gldns/parseutil.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
#define X509_STORE_CTX_get0_untrusted(store) store->untrusted
|
||||
#endif
|
||||
#include "pubkey-pinning.h"
|
||||
#include "pubkey-pinning-internal.h"
|
||||
|
||||
/* we only support sha256 at the moment. adding support for another
|
||||
digest is more complex than just adding another entry here. in
|
||||
|
@ -74,12 +69,10 @@ static const getdns_bindata sha256 = {
|
|||
.data = (uint8_t*)"sha256"
|
||||
};
|
||||
|
||||
|
||||
#define PIN_PREFIX "pin-sha256=\""
|
||||
#define PIN_PREFIX_LENGTH (sizeof(PIN_PREFIX) - 1)
|
||||
/* b64 turns every 3 octets (or fraction thereof) into 4 octets */
|
||||
#define B64_ENCODED_SHA256_LENGTH (((SHA256_DIGEST_LENGTH + 2)/3) * 4)
|
||||
|
||||
/* convert an HPKP-style pin description to an appropriate getdns data
|
||||
structure. An example string is: (with the quotes, without any
|
||||
leading or trailing whitespace):
|
||||
|
@ -96,10 +89,8 @@ static const getdns_bindata sha256 = {
|
|||
getdns_dict *getdns_pubkey_pin_create_from_string(
|
||||
const getdns_context *context, const char *str)
|
||||
{
|
||||
BIO *bio = NULL;
|
||||
size_t i;
|
||||
uint8_t buf[SHA256_DIGEST_LENGTH];
|
||||
char inbuf[B64_ENCODED_SHA256_LENGTH + 1];
|
||||
getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf };
|
||||
getdns_dict *out = NULL;
|
||||
|
||||
|
@ -119,15 +110,9 @@ getdns_dict *getdns_pubkey_pin_create_from_string(
|
|||
if (str[i++] != '\0')
|
||||
return NULL;
|
||||
|
||||
/* openssl needs a trailing newline to base64 decode */
|
||||
memcpy(inbuf, str + PIN_PREFIX_LENGTH, B64_ENCODED_SHA256_LENGTH);
|
||||
inbuf[B64_ENCODED_SHA256_LENGTH] = '\n';
|
||||
|
||||
bio = BIO_push(BIO_new(BIO_f_base64()),
|
||||
BIO_new_mem_buf(inbuf, sizeof(inbuf)));
|
||||
if (BIO_read(bio, buf, sizeof(buf)) != sizeof(buf))
|
||||
goto fail;
|
||||
|
||||
if (_getdns_decode_base64(str + PIN_PREFIX_LENGTH, buf, sizeof(buf)) != GETDNS_RETURN_GOOD)
|
||||
goto fail;
|
||||
|
||||
if (context)
|
||||
out = getdns_dict_create_with_context(context);
|
||||
else
|
||||
|
@ -141,12 +126,10 @@ getdns_dict *getdns_pubkey_pin_create_from_string(
|
|||
return out;
|
||||
|
||||
fail:
|
||||
BIO_free_all(bio);
|
||||
getdns_dict_destroy(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Test whether a given pinset is reasonable, including:
|
||||
|
||||
* is it well-formed?
|
||||
|
@ -306,261 +289,3 @@ _getdns_get_pubkey_pinset_list(const getdns_context *ctx,
|
|||
getdns_list_destroy(out);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* this should only happen once ever in the life of the library. it's
|
||||
used to associate a getdns_context_t with an SSL_CTX, to be able to
|
||||
do custom verification.
|
||||
|
||||
see doc/HOWTO/proxy_certificates.txt as an example
|
||||
*/
|
||||
static int
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
_get_ssl_getdns_upstream_idx(void)
|
||||
#else
|
||||
_get_ssl_getdns_upstream_idx(X509_STORE *store)
|
||||
#endif
|
||||
{
|
||||
static volatile int idx = -1;
|
||||
if (idx < 0) {
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
|
||||
#else
|
||||
X509_STORE_lock(store);
|
||||
#endif
|
||||
if (idx < 0)
|
||||
idx = SSL_get_ex_new_index(0, "associated getdns upstream",
|
||||
NULL,NULL,NULL);
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
|
||||
#else
|
||||
X509_STORE_unlock(store);
|
||||
#endif
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
getdns_upstream*
|
||||
_getdns_upstream_from_x509_store(X509_STORE_CTX *store)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
int uidx = _get_ssl_getdns_upstream_idx();
|
||||
#else
|
||||
int uidx = _get_ssl_getdns_upstream_idx(X509_STORE_CTX_get0_store(store));
|
||||
#endif
|
||||
int sslidx = SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||
const SSL *ssl;
|
||||
|
||||
/* all *_get_ex_data() should return NULL on failure anyway */
|
||||
ssl = X509_STORE_CTX_get_ex_data(store, sslidx);
|
||||
if (ssl)
|
||||
return (getdns_upstream*) SSL_get_ex_data(ssl, uidx);
|
||||
else
|
||||
return NULL;
|
||||
/* TODO: if we want more details about errors somehow, we
|
||||
* might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
_getdns_associate_upstream_with_SSL(SSL *ssl,
|
||||
getdns_upstream *upstream)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
int uidx = _get_ssl_getdns_upstream_idx();
|
||||
#else
|
||||
int uidx = _get_ssl_getdns_upstream_idx(SSL_CTX_get_cert_store(SSL_get_SSL_CTX(ssl)));
|
||||
#endif
|
||||
if (SSL_set_ex_data(ssl, uidx, upstream))
|
||||
return GETDNS_RETURN_GOOD;
|
||||
else
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
/* TODO: if we want more details about errors somehow, we
|
||||
* might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
_getdns_verify_pinset_match(const 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 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* /brief internal functions for dealing with pubkey pinsets
|
||||
* /brief functions for dealing with pubkey pinsets
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -34,6 +34,10 @@
|
|||
#ifndef PUBKEY_PINNING_H_
|
||||
#define PUBKEY_PINNING_H_
|
||||
|
||||
/* getdns_pubkey_pin_create_from_string() is implemented in pubkey-pinning.c */
|
||||
#include "getdns/getdns_extra.h"
|
||||
|
||||
#include "tls.h"
|
||||
|
||||
/* create and populate a pinset linked list from a getdns_list pinset */
|
||||
getdns_return_t
|
||||
|
@ -48,21 +52,5 @@ _getdns_get_pubkey_pinset_list(const getdns_context *ctx,
|
|||
const sha256_pin_t *pinset_in,
|
||||
getdns_list **pinset_list);
|
||||
|
||||
|
||||
/* internal functions for associating X.509 verification processes in
|
||||
* OpenSSL with getdns_upstream objects. */
|
||||
|
||||
getdns_upstream*
|
||||
_getdns_upstream_from_x509_store(X509_STORE_CTX *store);
|
||||
|
||||
|
||||
getdns_return_t
|
||||
_getdns_associate_upstream_with_SSL(SSL *ssl,
|
||||
getdns_upstream *upstream);
|
||||
|
||||
getdns_return_t
|
||||
_getdns_verify_pinset_match(const getdns_upstream *upstream,
|
||||
const sha256_pin_t *pinset, X509_STORE_CTX *store);
|
||||
|
||||
#endif
|
||||
/* pubkey-pinning.h */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "debug.h"
|
||||
#include "convert.h"
|
||||
#include "general.h"
|
||||
#include "tls.h"
|
||||
|
||||
/* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256
|
||||
* TSIG type (uint16_t) : 2
|
||||
|
@ -54,15 +55,15 @@
|
|||
* Time Signed (uint48_t) : 6
|
||||
* Fudge (uint16_t) : 2
|
||||
* Mac Size (uint16_t) : 2
|
||||
* Mac (variable) : EVP_MAX_MD_SIZE
|
||||
* Mac (variable) : GETDNS_TLS_MAX_DIGEST_LENGTH
|
||||
* Original Id (uint16_t) : 2
|
||||
* Error (uint16_t) : 2
|
||||
* Other Len (uint16_t) : 2
|
||||
* Other Data (nothing) : 0
|
||||
* ---- +
|
||||
* 538 + EVP_MAX_MD_SIZE
|
||||
* 538 + GETDNS_TLS_MAX_DIGEST_LENGTH
|
||||
*/
|
||||
#define MAXIMUM_TSIG_SPACE (538 + EVP_MAX_MD_SIZE)
|
||||
#define MAXIMUM_TSIG_SPACE (538 + GETDNS_TLS_MAX_DIGEST_LENGTH)
|
||||
|
||||
getdns_dict dnssec_ok_checking_disabled_spc = {
|
||||
{ RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
|
||||
|
@ -125,7 +126,7 @@ network_req_cleanup(getdns_network_req *net_req)
|
|||
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
||||
if (net_req->debug_tls_peer_cert.size &&
|
||||
net_req->debug_tls_peer_cert.data)
|
||||
OPENSSL_free(net_req->debug_tls_peer_cert.data);
|
||||
GETDNS_FREE(net_req->owner->my_mf, net_req->debug_tls_peer_cert.data);
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
|
@ -401,9 +402,8 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
gldns_buffer gbuf;
|
||||
uint16_t arcount;
|
||||
const getdns_tsig_info *tsig_info;
|
||||
uint8_t md_buf[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_len = EVP_MAX_MD_SIZE;
|
||||
const EVP_MD *digester;
|
||||
unsigned char* md_buf;
|
||||
size_t md_len;
|
||||
|
||||
/* Should only be called when in stub mode */
|
||||
assert(req->query);
|
||||
|
@ -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); /* Other len */
|
||||
|
||||
switch (upstream->tsig_alg) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return req->response - req->query;
|
||||
}
|
||||
|
||||
(void) HMAC(digester, upstream->tsig_key, upstream->tsig_size,
|
||||
(void *)req->query, gldns_buffer_current(&gbuf) - req->query,
|
||||
md_buf, &md_len);
|
||||
md_buf = _getdns_tls_hmac_hash(&req->owner->my_mf, upstream->tsig_alg, upstream->tsig_key, upstream->tsig_size, (void *)req->query, gldns_buffer_current(&gbuf) - req->query, &md_len);
|
||||
if (!md_buf)
|
||||
return req->response - req->query;
|
||||
|
||||
gldns_buffer_rewind(&gbuf);
|
||||
gldns_buffer_write(&gbuf,
|
||||
|
@ -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); /* Other len */
|
||||
|
||||
GETDNS_FREE(req->owner->my_mf, md_buf);
|
||||
|
||||
if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
|
||||
return req->response - req->query;
|
||||
|
||||
|
@ -509,14 +489,10 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
const uint8_t *response_mac;
|
||||
uint16_t response_mac_len;
|
||||
uint8_t other_len;
|
||||
uint8_t result_mac[EVP_MAX_MD_SIZE];
|
||||
unsigned int result_mac_len = EVP_MAX_MD_SIZE;
|
||||
unsigned char *result_mac;
|
||||
size_t result_mac_len;
|
||||
uint16_t original_id;
|
||||
const EVP_MD *digester;
|
||||
HMAC_CTX *ctx;
|
||||
#ifndef HAVE_HMAC_CTX_NEW
|
||||
HMAC_CTX ctx_space;
|
||||
#endif
|
||||
_getdns_tls_hmac *hmac;
|
||||
|
||||
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__);
|
||||
for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
|
||||
|
@ -623,39 +599,16 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
gldns_read_uint16(req->response + 10) - 1);
|
||||
gldns_write_uint16(req->response, original_id);
|
||||
|
||||
switch (req->upstream->tsig_alg) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return;
|
||||
}
|
||||
#ifdef HAVE_HMAC_CTX_NEW
|
||||
ctx = HMAC_CTX_new();
|
||||
#else
|
||||
ctx = &ctx_space;
|
||||
HMAC_CTX_init(ctx);
|
||||
#endif
|
||||
(void) HMAC_Init_ex(ctx, req->upstream->tsig_key,
|
||||
req->upstream->tsig_size, digester, NULL);
|
||||
(void) HMAC_Update(ctx, request_mac - 2, request_mac_len + 2);
|
||||
(void) HMAC_Update(ctx, req->response, rr->pos - req->response);
|
||||
(void) HMAC_Update(ctx, tsig_vars, gldns_buffer_position(&gbuf));
|
||||
HMAC_Final(ctx, result_mac, &result_mac_len);
|
||||
hmac = _getdns_tls_hmac_new(&req->owner->my_mf, req->upstream->tsig_alg, req->upstream->tsig_key, req->upstream->tsig_size);
|
||||
if (!hmac)
|
||||
return;
|
||||
|
||||
_getdns_tls_hmac_add(hmac, request_mac - 2, request_mac_len + 2);
|
||||
_getdns_tls_hmac_add(hmac, req->response, rr->pos - req->response);
|
||||
_getdns_tls_hmac_add(hmac, tsig_vars, gldns_buffer_position(&gbuf));
|
||||
result_mac = _getdns_tls_hmac_end(&req->owner->my_mf, hmac, &result_mac_len);
|
||||
if (!result_mac)
|
||||
return;
|
||||
|
||||
DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
|
||||
STUB_DEBUG_TSIG, __FUNC__, (int)(result_mac_len));
|
||||
|
@ -663,11 +616,8 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
memcmp(result_mac, response_mac, result_mac_len) == 0)
|
||||
req->tsig_status = GETDNS_DNSSEC_SECURE;
|
||||
|
||||
#ifdef HAVE_HMAC_CTX_FREE
|
||||
HMAC_CTX_free(ctx);
|
||||
#else
|
||||
HMAC_CTX_cleanup(ctx);
|
||||
#endif
|
||||
GETDNS_FREE(req->owner->my_mf, result_mac);
|
||||
|
||||
gldns_write_uint16(req->response, gldns_read_uint16(req->query));
|
||||
gldns_write_uint16(req->response + 10,
|
||||
gldns_read_uint16(req->response + 10) + 1);
|
||||
|
|
572
src/stub.c
572
src/stub.c
|
@ -39,9 +39,6 @@
|
|||
#define INTERCEPT_COM_DS 0
|
||||
|
||||
#include "debug.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <fcntl.h>
|
||||
#include "stub.h"
|
||||
#include "gldns/gbuffer.h"
|
||||
|
@ -55,10 +52,6 @@
|
|||
#include "platform.h"
|
||||
#include "general.h"
|
||||
#include "pubkey-pinning.h"
|
||||
#ifdef USE_DANESSL
|
||||
# include "ssl_dane/danessl.h"
|
||||
#endif
|
||||
#include "const-info.h"
|
||||
|
||||
/* WSA TODO:
|
||||
* STUB_TCP_RETRY added to deal with edge triggered event loops (versus
|
||||
|
@ -128,10 +121,8 @@ rollover_secret()
|
|||
static void
|
||||
calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
EVP_MD_CTX *mdctx;
|
||||
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_len;
|
||||
unsigned char md_value[GETDNS_TLS_MAX_DIGEST_LENGTH];
|
||||
size_t md_len;
|
||||
size_t i;
|
||||
sa_family_t af = upstream->addr.ss_family;
|
||||
void *sa_addr = ((struct sockaddr*)&upstream->addr)->sa_data;
|
||||
|
@ -139,13 +130,7 @@ calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie)
|
|||
: af == AF_INET ? sizeof(struct sockaddr_in)
|
||||
: 0 ) - sizeof(sa_family_t);
|
||||
|
||||
md = EVP_sha256();
|
||||
mdctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit_ex(mdctx, md, NULL);
|
||||
EVP_DigestUpdate(mdctx, &secret, sizeof(secret));
|
||||
EVP_DigestUpdate(mdctx, sa_addr, addr_len);
|
||||
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
_getdns_tls_cookie_sha256(secret, sa_addr, addr_len, md_value, &md_len);
|
||||
|
||||
(void) memset(cookie, 0, 8);
|
||||
for (i = 0; i < md_len; i++)
|
||||
|
@ -830,194 +815,46 @@ tls_requested(getdns_network_req *netreq)
|
|||
1 : 0;
|
||||
}
|
||||
|
||||
|
||||
#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*
|
||||
static _getdns_tls_connection*
|
||||
tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
||||
{
|
||||
/* Create SSL instance */
|
||||
/* Create SSL instance and connect with a file descriptor */
|
||||
getdns_context *context = dnsreq->context;
|
||||
if (context->tls_ctx == NULL)
|
||||
return NULL;
|
||||
SSL* ssl = SSL_new(context->tls_ctx);
|
||||
if(!ssl)
|
||||
_getdns_tls_connection* tls = _getdns_tls_connection_new(&context->my_mf, context->tls_ctx, fd, &upstream->upstreams->log);
|
||||
if(!tls)
|
||||
return NULL;
|
||||
/* Connect the SSL object with a file descriptor */
|
||||
if(!SSL_set_fd(ssl,fd)) {
|
||||
SSL_free(ssl);
|
||||
|
||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||
|
||||
if (upstream->tls_curves_list)
|
||||
r = _getdns_tls_connection_set_curves_list(tls, upstream->tls_curves_list);
|
||||
if (!r && upstream->tls_ciphersuites)
|
||||
r = _getdns_tls_connection_set_cipher_suites(tls, upstream->tls_ciphersuites);
|
||||
if (!r)
|
||||
r = _getdns_tls_connection_set_min_max_tls_version(tls, upstream->tls_min_version, upstream->tls_max_version);
|
||||
|
||||
if (!r)
|
||||
{
|
||||
if (upstream->tls_fallback_ok)
|
||||
r = _getdns_tls_connection_set_cipher_list(tls, NULL);
|
||||
else if (upstream->tls_cipher_list)
|
||||
r = _getdns_tls_connection_set_cipher_list(tls, upstream->tls_cipher_list);
|
||||
}
|
||||
|
||||
if (r) {
|
||||
_getdns_tls_connection_free(&upstream->upstreams->mf, tls);
|
||||
upstream->tls_auth_state = GETDNS_AUTH_NONE;
|
||||
return NULL;
|
||||
}
|
||||
#if defined(HAVE_DECL_SSL_SET1_CURVES_LIST) && HAVE_DECL_SSL_SET1_CURVES_LIST
|
||||
if (upstream->tls_curves_list
|
||||
&& !SSL_set1_curves_list(ssl, upstream->tls_curves_list)) {
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS,
|
||||
GETDNS_LOG_ERR, "%-40s : Error configuring tls_curves_list "
|
||||
"\"%s\"\n", upstream->addr_str, upstream->tls_curves_list);
|
||||
SSL_free(ssl);
|
||||
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;
|
||||
|
||||
if (upstream->tls_fallback_ok) {
|
||||
DEBUG_STUB("%s %-35s: WARNING: Using Opportunistic TLS (fallback allowed)!\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
} else {
|
||||
DEBUG_STUB("%s %-35s: Using Strict TLS \n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
}
|
||||
|
||||
/* NOTE: this code will fallback on a given upstream, without trying
|
||||
|
@ -1030,29 +867,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
/*Request certificate for the auth_name*/
|
||||
DEBUG_STUB("%s %-35s: Hostname verification requested for: %s\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->tls_auth_name);
|
||||
SSL_set_tlsext_host_name(ssl, upstream->tls_auth_name);
|
||||
#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
|
||||
_getdns_tls_connection_setup_hostname_auth(tls, upstream->tls_auth_name);
|
||||
/* Allow fallback to opportunistic if settings permit it*/
|
||||
if (dnsreq->netreqs[0]->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
|
||||
upstream->tls_fallback_ok = 1;
|
||||
|
@ -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",
|
||||
upstream->addr_str);
|
||||
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;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1081,89 +896,8 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
upstream->tls_fallback_ok = 1;
|
||||
}
|
||||
}
|
||||
if (upstream->tls_fallback_ok) {
|
||||
SSL_set_cipher_list(ssl, "DEFAULT");
|
||||
DEBUG_STUB("%s %-35s: WARNING: Using Oppotunistic TLS (fallback allowed)!\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
} else {
|
||||
if (upstream->tls_cipher_list &&
|
||||
!SSL_set_cipher_list(ssl, upstream->tls_cipher_list))
|
||||
_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,
|
||||
__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);
|
||||
_getdns_tls_connection_set_host_pinset(tls, upstream->tls_auth_name, upstream->tls_pubkey_pinset);
|
||||
|
||||
/* Session resumption. There are trade-offs here. Want to do it when
|
||||
possible only if we have the right type of connection. Note a change
|
||||
|
@ -1172,12 +906,12 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
if ((upstream->tls_fallback_ok == 0 &&
|
||||
upstream->last_tls_auth_state == GETDNS_AUTH_OK) ||
|
||||
upstream->tls_fallback_ok == 1) {
|
||||
SSL_set_session(ssl, upstream->tls_session);
|
||||
_getdns_tls_connection_set_session(tls, upstream->tls_session);
|
||||
DEBUG_STUB("%s %-35s: Attempting session re-use\n", STUB_DEBUG_SETUP_TLS,
|
||||
__FUNC__);
|
||||
}
|
||||
}
|
||||
return ssl;
|
||||
return tls;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1186,13 +920,10 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SETUP_TLS,
|
||||
__FUNC__, upstream->fd);
|
||||
int r;
|
||||
int want;
|
||||
ERR_clear_error();
|
||||
while ((r = SSL_do_handshake(upstream->tls_obj)) != 1)
|
||||
while ((r = _getdns_tls_connection_do_handshake(upstream->tls_obj)) != GETDNS_RETURN_GOOD)
|
||||
{
|
||||
want = SSL_get_error(upstream->tls_obj, r);
|
||||
switch (want) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
switch (r) {
|
||||
case GETDNS_RETURN_TLS_WANT_READ:
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
upstream->event.read_cb = upstream_read_cb;
|
||||
upstream->event.write_cb = NULL;
|
||||
|
@ -1200,7 +931,7 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
upstream->fd, TIMEOUT_TLS, &upstream->event);
|
||||
upstream->tls_hs_state = GETDNS_HS_READ;
|
||||
return STUB_TCP_RETRY;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
case GETDNS_RETURN_TLS_WANT_WRITE:
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
upstream->event.read_cb = NULL;
|
||||
upstream->event.write_cb = upstream_write_cb;
|
||||
|
@ -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 */
|
||||
if (SSL_session_reused(upstream->tls_obj))
|
||||
if (!_getdns_tls_connection_is_session_reused(upstream->tls_obj))
|
||||
upstream->tls_auth_state = upstream->last_tls_auth_state;
|
||||
|
||||
else if (upstream->tls_pubkey_pinset || upstream->tls_auth_name[0]) {
|
||||
X509 *peer_cert = SSL_get_peer_certificate(upstream->tls_obj);
|
||||
long verify_result = SSL_get_verify_result(upstream->tls_obj);
|
||||
_getdns_tls_x509* peer_cert = _getdns_tls_connection_get_peer_certificate(&upstream->upstreams->mf, upstream->tls_obj);
|
||||
|
||||
/* In case of DANESSL use, and a tls_auth_name was given alongside a pinset,
|
||||
* 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)
|
||||
if (!peer_cert) {
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
|
@ -1253,71 +964,44 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ));
|
||||
|
||||
/* Since we don't have DANE validation yet, DANE validation
|
||||
* failures are always pinset validation failures
|
||||
*/
|
||||
#if defined(HAVE_SSL_DANE_ENABLE)
|
||||
else if (verify_result == X509_V_ERR_DANE_NO_MATCH)
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"Pinset validation failure\n", upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ));
|
||||
#elif defined(USE_DANESSL)
|
||||
else if (verify_result == X509_V_ERR_CERT_UNTRUSTED
|
||||
&& upstream->tls_pubkey_pinset
|
||||
&& !DANESSL_get_match_cert(
|
||||
upstream->tls_obj, NULL, NULL, NULL))
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"Pinset validation failure\n", upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ));
|
||||
#endif
|
||||
else if (verify_result != X509_V_OK)
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"(%d) \"%s\"\n", upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ), verify_result,
|
||||
X509_verify_cert_error_string(verify_result));
|
||||
#if !defined(HAVE_SSL_HN_AUTH) && !defined(HAVE_X509_CHECK_HOST)
|
||||
else if (*upstream->tls_auth_name) {
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS,
|
||||
( upstream->tls_fallback_ok
|
||||
? GETDNS_LOG_INFO : GETDNS_LOG_ERR),
|
||||
"%-40s : Verify failed : TLS - %s - "
|
||||
"Hostname Authentication not available from TLS "
|
||||
"library (check library version)\n",
|
||||
upstream->addr_str,
|
||||
( upstream->tls_fallback_ok
|
||||
? "Tolerated because of Opportunistic profile"
|
||||
: "*Failure*" ));
|
||||
|
||||
upstream->tls_auth_state = GETDNS_AUTH_FAILED;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
|
||||
"%-40s : Verify passed : TLS\n",
|
||||
upstream->addr_str);
|
||||
} else {
|
||||
long verify_errno;
|
||||
const char* verify_errmsg;
|
||||
|
||||
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
|
||||
&& !upstream->tls_fallback_ok)
|
||||
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",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd,
|
||||
_getdns_auth_str(upstream->tls_auth_state),
|
||||
SSL_session_reused(upstream->tls_obj) ?"re-used":"new");
|
||||
_getdns_tls_connection_is_session_reused(upstream->tls_obj) ? "new" : "re-used");
|
||||
upstream->tls_hs_state = GETDNS_HS_DONE;
|
||||
upstream->conn_state = GETDNS_CONN_OPEN;
|
||||
upstream->conn_completed++;
|
||||
if (upstream->tls_session != NULL)
|
||||
SSL_SESSION_free(upstream->tls_session);
|
||||
upstream->tls_session = SSL_get1_session(upstream->tls_obj);
|
||||
_getdns_tls_session_free(&upstream->upstreams->mf, upstream->tls_session);
|
||||
upstream->tls_session = _getdns_tls_connection_get_session(&upstream->upstreams->mf, upstream->tls_obj);
|
||||
/* Reset timeout on success*/
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
upstream->event.read_cb = NULL;
|
||||
|
@ -1369,10 +1053,10 @@ static int
|
|||
stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
||||
struct mem_funcs *mf)
|
||||
{
|
||||
ssize_t read;
|
||||
size_t read;
|
||||
uint8_t *buf;
|
||||
size_t buf_size;
|
||||
SSL* tls_obj = upstream->tls_obj;
|
||||
_getdns_tls_connection* tls_obj = upstream->tls_obj;
|
||||
|
||||
int q = tls_connected(upstream);
|
||||
if (q != 0)
|
||||
|
@ -1388,17 +1072,14 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
tcp->to_read = 2; /* Packet size */
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read);
|
||||
if (read <= 0) {
|
||||
/* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake
|
||||
renegotiation. Need to keep handshake state to do that.*/
|
||||
int want = SSL_get_error(tls_obj, read);
|
||||
if (want == SSL_ERROR_WANT_READ) {
|
||||
return STUB_TCP_RETRY; /* Come back later */
|
||||
} else
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
getdns_return_t r = _getdns_tls_connection_read(tls_obj, tcp->read_pos, tcp->to_read, &read);
|
||||
/* TODO[TLS]: Handle GETDNS_RETURN_TLS_WANT_WRITE which means handshake
|
||||
renegotiation. Need to keep handshake state to do that.*/
|
||||
if (r == GETDNS_RETURN_TLS_WANT_READ)
|
||||
return STUB_TCP_RETRY;
|
||||
else if (r != GETDNS_RETURN_GOOD)
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
tcp->to_read -= read;
|
||||
tcp->read_pos += read;
|
||||
|
||||
|
@ -1429,15 +1110,17 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
|
||||
/* Ready to start reading the packet */
|
||||
tcp->read_pos = tcp->read_buf;
|
||||
read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read);
|
||||
if (read <= 0) {
|
||||
/* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake
|
||||
switch ((int)_getdns_tls_connection_read(tls_obj, tcp->read_pos, tcp->to_read, &read)) {
|
||||
case GETDNS_RETURN_GOOD:
|
||||
break;
|
||||
|
||||
case GETDNS_RETURN_TLS_WANT_READ:
|
||||
return STUB_TCP_RETRY; /* Come back later */
|
||||
|
||||
default:
|
||||
/* TODO[TLS]: Handle GETDNS_RETURN_TLS_WANT_WRITE which means handshake
|
||||
renegotiation. Need to keep handshake state to do that.*/
|
||||
int want = SSL_get_error(tls_obj, read);
|
||||
if (want == SSL_ERROR_WANT_READ) {
|
||||
return STUB_TCP_RETRY; /* read more later */
|
||||
} else
|
||||
return STUB_TCP_ERROR;
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
tcp->to_read -= read;
|
||||
tcp->read_pos += read;
|
||||
|
@ -1452,10 +1135,10 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
getdns_network_req *netreq)
|
||||
{
|
||||
size_t pkt_len;
|
||||
ssize_t written;
|
||||
size_t written;
|
||||
uint16_t query_id;
|
||||
intptr_t query_id_intptr;
|
||||
SSL* tls_obj = upstream->tls_obj;
|
||||
_getdns_tls_connection* tls_obj = upstream->tls_obj;
|
||||
uint16_t padding_sz;
|
||||
|
||||
int q = tls_connected(upstream);
|
||||
|
@ -1530,7 +1213,8 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
* Lets see how much of it we can write */
|
||||
|
||||
/* TODO[TLS]: Handle error cases, partial writes, renegotiation etc. */
|
||||
ERR_clear_error();
|
||||
getdns_return_t r;
|
||||
|
||||
#if INTERCEPT_COM_DS
|
||||
/* Intercept and do not sent out COM DS queries. For debugging
|
||||
* purposes only. Never commit with this turned on.
|
||||
|
@ -1545,25 +1229,16 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
|
||||
debug_req("Intercepting", netreq);
|
||||
written = pkt_len + 2;
|
||||
r = GETDNS_RETURN_GOOD;
|
||||
} else
|
||||
#endif
|
||||
written = SSL_write(tls_obj, netreq->query - 2, pkt_len + 2);
|
||||
if (written <= 0) {
|
||||
/* SSL_write will not do partial writes, because
|
||||
* SSL_MODE_ENABLE_PARTIAL_WRITE is not default,
|
||||
* but the write could fail because of renegotiation.
|
||||
* In that case SSL_get_error() will return
|
||||
* SSL_ERROR_WANT_READ or, SSL_ERROR_WANT_WRITE.
|
||||
* Return for retry in such cases.
|
||||
*/
|
||||
switch (SSL_get_error(tls_obj, written)) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
return STUB_TCP_RETRY;
|
||||
default:
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
}
|
||||
r = _getdns_tls_connection_write(tls_obj, netreq->query - 2, pkt_len + 2, &written);
|
||||
if (r == GETDNS_RETURN_TLS_WANT_READ ||
|
||||
r == GETDNS_RETURN_TLS_WANT_WRITE)
|
||||
return STUB_TCP_RETRY;
|
||||
else if (r != GETDNS_RETURN_GOOD)
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
/* We were able to write everything! Start reading. */
|
||||
return (int) query_id;
|
||||
|
||||
|
@ -1897,7 +1572,7 @@ upstream_write_cb(void *userarg)
|
|||
getdns_upstream *upstream = (getdns_upstream *)userarg;
|
||||
getdns_network_req *netreq = upstream->write_queue;
|
||||
int q;
|
||||
X509 *cert;
|
||||
_getdns_tls_x509 *cert;
|
||||
|
||||
if (!netreq) {
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
|
@ -1960,12 +1635,11 @@ upstream_write_cb(void *userarg)
|
|||
if (netreq->owner->return_call_reporting &&
|
||||
netreq->upstream->tls_obj) {
|
||||
if (netreq->debug_tls_peer_cert.data == NULL &&
|
||||
(cert = SSL_get_peer_certificate(netreq->upstream->tls_obj))) {
|
||||
netreq->debug_tls_peer_cert.size = i2d_X509(
|
||||
cert, &netreq->debug_tls_peer_cert.data);
|
||||
X509_free(cert);
|
||||
(cert = _getdns_tls_connection_get_peer_certificate(&upstream->upstreams->mf, netreq->upstream->tls_obj))) {
|
||||
_getdns_tls_x509_to_der(&upstream->upstreams->mf, cert, &netreq->debug_tls_peer_cert);
|
||||
_getdns_tls_x509_free(&upstream->upstreams->mf, cert);
|
||||
}
|
||||
netreq->debug_tls_version = 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 */
|
||||
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
|
||||
|
|
|
@ -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 */
|
|
@ -127,10 +127,7 @@ getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \
|
|||
$(srcdir)/../debug.h \
|
||||
../getdns/getdns.h \
|
||||
../getdns/getdns_extra.h
|
||||
|
||||
# Dependencies for getdns_server_mon
|
||||
getdns_server_mon.lo getdns_server_mon.o: $(srcdir)/getdns_server_mon.c \
|
||||
../config.h \
|
||||
$(srcdir)/../debug.h \
|
||||
../getdns/getdns.h \
|
||||
../getdns/getdns_extra.h
|
||||
|
|
|
@ -74,9 +74,11 @@ static getdns_dict *listen_dict = NULL;
|
|||
static size_t pincount = 0;
|
||||
static size_t listen_count = 0;
|
||||
static uint16_t request_type = GETDNS_RRTYPE_NS;
|
||||
static int got_rrtype = 0;
|
||||
static int timeout, edns0_size, padding_blocksize;
|
||||
static int async = 0, interactive = 0;
|
||||
static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
|
||||
static int got_calltype = 0;
|
||||
static int bogus_answers = 0;
|
||||
static int check_dnssec = 0;
|
||||
#ifndef USE_WINSOCK
|
||||
|
@ -581,8 +583,6 @@ getdns_return_t parse_args(int argc, char **argv)
|
|||
size_t upstream_count = 0;
|
||||
FILE *fh;
|
||||
int int_value;
|
||||
int got_rrtype = 0;
|
||||
int got_calltype = 0;
|
||||
int got_qname = 0;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
@ -1181,7 +1181,7 @@ getdns_return_t do_the_call(void)
|
|||
r = GETDNS_RETURN_GENERIC_ERROR;
|
||||
break;
|
||||
}
|
||||
if (r == GETDNS_RETURN_GOOD && !batch_mode)
|
||||
if (r == GETDNS_RETURN_GOOD && !batch_mode && !interactive)
|
||||
getdns_context_run(context);
|
||||
if (r != GETDNS_RETURN_GOOD)
|
||||
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 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)
|
||||
{
|
||||
static int n = 0;
|
||||
getdns_eventloop_event *read_line_ev = userarg;
|
||||
getdns_return_t r;
|
||||
|
||||
char line[1024], *token, *linev[256];
|
||||
int linec;
|
||||
|
||||
assert(n == 0);
|
||||
n += 1;
|
||||
if (!fgets(line, 1024, fp) || !*line) {
|
||||
if (query_file && verbosity)
|
||||
fprintf(stdout,"End of file.");
|
||||
|
@ -1276,6 +1290,7 @@ void read_line_cb(void *userarg)
|
|||
if (interactive && !query_file)
|
||||
(void) getdns_context_set_upstream_recursive_servers(
|
||||
context, NULL);
|
||||
n -= 1;
|
||||
return;
|
||||
}
|
||||
if (query_file && verbosity)
|
||||
|
@ -1288,6 +1303,7 @@ void read_line_cb(void *userarg)
|
|||
printf("> ");
|
||||
fflush(stdout);
|
||||
}
|
||||
n -= 1;
|
||||
return;
|
||||
}
|
||||
if (*token == '#') {
|
||||
|
@ -1297,6 +1313,7 @@ void read_line_cb(void *userarg)
|
|||
printf("> ");
|
||||
fflush(stdout);
|
||||
}
|
||||
n -= 1;
|
||||
return;
|
||||
}
|
||||
do linev[linec++] = token;
|
||||
|
@ -1312,10 +1329,23 @@ void read_line_cb(void *userarg)
|
|||
(r != CONTINUE && r != CONTINUE_ERROR))
|
||||
loop->vmt->clear(loop, read_line_ev);
|
||||
|
||||
else if (! query_file) {
|
||||
printf("> ");
|
||||
fflush(stdout);
|
||||
else {
|
||||
#if 0
|
||||
/* 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 {
|
||||
|
|
|
@ -36,9 +36,13 @@
|
|||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef USE_GNUTLS
|
||||
#include <gnutls/x509.h>
|
||||
#else
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/bio.h>
|
||||
#endif
|
||||
|
||||
#include <getdns/getdns.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_");
|
||||
}
|
||||
|
||||
#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.
|
||||
* 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)
|
||||
{
|
||||
#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);
|
||||
if (!cert)
|
||||
return false;
|
||||
|
@ -299,6 +324,7 @@ static bool extract_cert_expiry(const unsigned char *data, size_t len, time_t *t
|
|||
X509_free(cert);
|
||||
#endif
|
||||
*t += day_diff * SECS_IN_DAY + sec_diff;
|
||||
#endif /* USE_GNUTLS */
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -934,7 +934,7 @@ _getdns_create_call_reporting_dict(
|
|||
return NULL;
|
||||
}
|
||||
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;
|
||||
return netreq_debug;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
#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
|
||||
/* util-internal.h */
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "util/val_secalgo.h"
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
*
|
||||
* \file rbtree.h
|
||||
* /brief Alternative symbol names for unbound's rbtree.h
|
||||
* \file val_secalgo.h
|
||||
* /brief secalgo interface.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
|
@ -32,53 +32,23 @@
|
|||
*/
|
||||
#ifndef 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
|
||||
#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
|
||||
|
||||
#include "gldns/gbuffer.h"
|
||||
|
||||
enum sec_status { sec_status_bogus = 0
|
||||
, sec_status_unchecked = 0
|
||||
, sec_status_insecure = 0
|
||||
, sec_status_secure = 1 };
|
||||
#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/orig-headers/val_secalgo.h"
|
||||
size_t _getdns_ds_digest_size_supported(int algo);
|
||||
|
||||
int _getdns_secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
unsigned char* res);
|
||||
|
||||
int _getdns_dnskey_algo_id_is_supported(int id);
|
||||
|
||||
enum sec_status _getdns_verify_canonrrset(struct gldns_buffer* buf, int algo,
|
||||
unsigned char* sigblock, unsigned int sigblock_len,
|
||||
unsigned char* key, unsigned int keylen, char** reason);
|
||||
|
||||
#endif
|
||||
|
|
2
stubby
2
stubby
|
@ -1 +1 @@
|
|||
Subproject commit 9c6e55a16af8f3258736b804b17eac3d35daebf3
|
||||
Subproject commit 8fb853ac8d6148fd9b53fdcbc107ecd375071ec5
|
Loading…
Reference in New Issue