]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added a DANE library.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 6 Oct 2012 02:26:05 +0000 (04:26 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 6 Oct 2012 12:57:19 +0000 (14:57 +0200)
22 files changed:
.gitignore
Makefile.am
NEWS
configure.ac
doc/Makefile.am
doc/cha-cert-auth.texi
doc/cha-functions.texi
doc/invoke-gnutls-cli.texi
doc/manpages/Makefile.am
doc/scripts/getfuncs.pl
libdane/Makefile.am [new file with mode: 0644]
libdane/dane.c [new file with mode: 0644]
libdane/errors.c [new file with mode: 0644]
libdane/includes/Makefile.am [new file with mode: 0644]
libdane/includes/gnutls/dane.h [new file with mode: 0644]
libdane/libdane.map [new file with mode: 0644]
m4/hooks.m4
src/Makefile.am
src/cli-args.c
src/cli-args.def
src/cli-args.h
src/cli.c

index 36c5151f78719a1543a3cd1cafc5356f5a7bc455..80ac853faa847582a44310933d19a1be50e75074 100644 (file)
@@ -31,6 +31,7 @@ configure
 doc/Makefile
 doc/Makefile.in
 doc/abstract-api.texi
+doc/dane-api.texi
 doc/algorithms.texi
 doc/compat-api.texi
 doc/core.c.texi
@@ -122,6 +123,7 @@ doc/manpages/gnutls-cli-debug.1
 doc/manpages/gnutls-cli.1
 doc/manpages/gnutls-serv.1
 doc/manpages/gnutls_*.3
+doc/manpages/dane_*.3
 doc/manpages/ocsptool.1
 doc/manpages/p11tool.1
 doc/manpages/psktool.1
@@ -594,3 +596,4 @@ tests/mini-dtls-heartbeat
 tests/mini-handshake-timeout
 tests/mini-x509-callbacks
 doc/manpages/stamp_mans
+libdane/libdane.la
index e866bd392ab442f16183ad5fddc6489430366ed7..74208b1e38a9422c4cd88240371fcee9c39b8ba9 100644 (file)
@@ -21,7 +21,7 @@
 
 DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --disable-valgrind-tests
 
-SUBDIRS = gl lib extra po
+SUBDIRS = gl lib extra libdane po
 
 SUBDIRS += src doc tests
 
diff --git a/NEWS b/NEWS
index bf81f812f48a6f6d04d6b15a471258452ca4544b..caafbbd6c523ff05d997d937f2e82f4a44e0d6ab 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,12 +16,24 @@ Reported by danblack at http://savannah.gnu.org/support/?108146
 ** libgnutls: Added gnutls_ocsp_resp_check_crt() to check whether the OCSP
 response corresponds to the given certificate.
 
+** libdane: Added. It is a library to provide DANE with DNSSEC certificate
+verification.
+
 ** API and ABI modifications:
 gnutls_certificate_set_ocsp_status_request_function: Added
 gnutls_certificate_set_ocsp_status_request_file: Added
 gnutls_ocsp_status_request_enable_client: Added
 gnutls_ocsp_status_request_get: Added
 gnutls_ocsp_resp_check_crt: Added
+dane_query_init: Added
+dane_query_deinit: Added
+dane_query_resolve_tlsa: Added
+dane_query_data: Added
+dane_query_status: Added
+dane_query_entries: Added
+dane_verify_crt: Added
+dane_verify_session_crt: Added
+dane_strerror: Added
 
 
 * Version 3.1.2 (released 2012-09-26)
index d3bec268920aed124c6ac2b2a428a73cfda6bd1b..1828a299a133d055a93b5556e92b38bc6f6f03b9 100644 (file)
@@ -115,6 +115,45 @@ dnl Try the hooks.m4
 LIBGNUTLS_HOOKS
 LIBGNUTLS_EXTRA_HOOKS
 
+AC_MSG_CHECKING([whether to build libdane])
+AC_ARG_ENABLE(libdane,
+    AS_HELP_STRING([--disable-libdane],
+                   [disable the built of libdane]),
+    enable_dane=$enableval, enable_dane=yes)
+AC_MSG_RESULT($enable_dane)
+
+if test "$enable_dane" != "no"; then
+    LIBS="$oldlibs -lunbound"
+    AC_MSG_CHECKING([for unbound library])
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([
+                  #include <unbound.h>],[
+                  struct ub_ctx* ctx;
+                  ctx = ub_ctx_create();])],
+                 [AC_MSG_RESULT(yes)
+                  AC_SUBST([UNBOUND_LIBS], [-lunbound])
+                  AC_SUBST([UNBOUND_CFLAGS], [])
+                  AC_DEFINE([HAVE_DANE], 1, [Enable the DANE library])
+                  enable_dane=yes],
+                 [AC_MSG_RESULT(no)
+                  AC_MSG_WARN([[
+*** 
+*** libunbound was not found. Libdane will not be built.
+*** ]])
+                 enable_dane=no])
+    LIBS="$oldlibs"
+fi
+
+AM_CONDITIONAL(ENABLE_DANE, test "$enable_dane" = "yes")
+
+AC_ARG_WITH(unbound-root-key-file, AS_HELP_STRING([--with-unbound-root-key-file],
+                                 [specify the unbound root key file]),
+            unbound_root_key_file="$withval", 
+            unbound_root_key_file="/etc/unbound/root.key")
+
+AC_DEFINE_UNQUOTED([UNBOUND_ROOT_KEY_FILE],
+  ["$unbound_root_key_file"], [The DNSSEC root key file])
+
+
 GTK_DOC_CHECK(1.1)
 AM_GNU_GETTEXT([external])
 AM_GNU_GETTEXT_VERSION([0.18])
@@ -521,6 +560,8 @@ AC_CONFIG_FILES([
   doc/scripts/Makefile
   extra/Makefile
   extra/includes/Makefile
+  libdane/Makefile
+  libdane/includes/Makefile
   gl/Makefile
   gl/tests/Makefile
   guile/Makefile
@@ -579,6 +620,14 @@ AC_MSG_NOTICE([summary of build options:
   Valgrind:         $opt_valgrind_tests ${VALGRIND}
 ])
 
+AC_MSG_NOTICE([Hardware acceleration/support:
+
+  /dev/crypto:      $enable_cryptodev
+  Hardware accel:   $hw_accel
+  PKCS#11 support:  $with_p11_kit
+  TPM support:      $with_tpm
+])
+
 AC_MSG_NOTICE([Optional features:
 (note that included applications might not compile properly
 if features are disabled)
@@ -588,10 +637,6 @@ if features are disabled)
   SRP support:      $ac_enable_srp
   PSK support:      $ac_enable_psk
   Anon auth support:$ac_enable_anon
-
-  Trust store pkcs: $with_default_trust_store_pkcs11
-  Trust store file: $with_default_trust_store_file
-  CRL file: $with_default_crl_file
 ])
 
 AC_MSG_NOTICE([Optional applications:
@@ -604,13 +649,24 @@ AC_MSG_NOTICE([Optional libraries:
 
   Guile wrappers:   $opt_guile_bindings
   C++ library:      $use_cxx
+  DANE library:     $enable_dane
   OpenSSL compat:   $enable_openssl
 ])
 
-AC_MSG_NOTICE([Hardware acceleration/support:
+AC_MSG_NOTICE([System files:
 
-  /dev/crypto:      $enable_cryptodev
-  Hardware accel:   $hw_accel
-  PKCS#11 support:  $with_p11_kit
-  TPM support:      $with_tpm
+  Trust store pkcs:     $with_default_trust_store_pkcs11
+  Trust store file:     $with_default_trust_store_file
+  CRL file:             $with_default_crl_file
+  DNSSEC root key file: $unbound_root_key_file
 ])
+
+if test ! -f "$unbound_root_key_file"; then
+AC_MSG_WARN([[
+*** 
+*** The DNSSEC root key file in $unbound_root_key_file was not found. 
+*** This file is needed for the verification of DNSSEC responses.
+*** Use the command: unbound-anchor -a "$unbound_root_key_file"
+*** to generate or update it.
+*** ]])
+fi
index b375353087f9816b26fdf8107b027df42f70531f..ac4ee64a8d8cfed8b2d3fd893434db09ab225ffa 100644 (file)
@@ -190,18 +190,21 @@ MAINTAINERCLEANFILES =
 
 gnutls_TEXINFOS += gnutls-api.texi x509-api.texi pgp-api.texi          \
        pkcs12-api.texi pkcs11-api.texi abstract-api.texi tpm-api.texi  \
-       compat-api.texi dtls-api.texi crypto-api.texi ocsp-api.texi
+       compat-api.texi dtls-api.texi crypto-api.texi ocsp-api.texi     \
+       dane-api.texi
 
 MAINTAINERCLEANFILES += gnutls-api.texi x509-api.texi pgp-api.texi     \
        pkcs12-api.texi pkcs11-api.texi abstract-api.texi tpm-api.texi  \
-       compat-api.texi dtls-api.texi crypto-api.texi ocsp-api.texi
+       compat-api.texi dtls-api.texi crypto-api.texi ocsp-api.texi     \
+       dane-api.texi
 
 HEADER_FILES = $(top_srcdir)/lib/includes/gnutls/gnutls.h.in \
        $(top_srcdir)/lib/includes/gnutls/x509.h $(top_srcdir)/lib/includes/gnutls/openpgp.h \
        $(top_srcdir)/lib/includes/gnutls/pkcs12.h $(top_srcdir)/lib/includes/gnutls/pkcs11.h \
        $(top_srcdir)/lib/includes/gnutls/abstract.h $(top_srcdir)/lib/includes/gnutls/compat.h \
        $(top_srcdir)/lib/includes/gnutls/dtls.h $(top_srcdir)/lib/includes/gnutls/crypto.h \
-       $(top_srcdir)/lib/includes/gnutls/ocsp.h $(top_srcdir)/lib/includes/gnutls/tpm.h
+       $(top_srcdir)/lib/includes/gnutls/ocsp.h $(top_srcdir)/lib/includes/gnutls/tpm.h \
+       $(top_srcdir)/libdane/includes/gnutls/dane.h
 
 gnutls-api.texi: $(top_srcdir)/lib/includes/gnutls/gnutls.h.in
        echo "" > $@-tmp
@@ -214,6 +217,17 @@ gnutls-api.texi: $(top_srcdir)/lib/includes/gnutls/gnutls.h.in
        done
        mv -f $@-tmp $@
 
+dane-api.texi: $(top_srcdir)/libdane/includes/gnutls/dane.h
+       echo "" > $@-tmp
+       for i in `$(top_srcdir)/doc/scripts/getfuncs.pl <$^|sort|uniq`; do \
+               echo -n "Creating documentation for $$i... " && \
+               $(srcdir)/scripts/gdoc -texinfo \
+                       -function $$i \
+                       $(top_srcdir)/libdane/*.c >> $@-tmp 2>/dev/null && \
+               echo "ok"; \
+       done
+       mv -f $@-tmp $@
+
 x509-api.texi: $(top_srcdir)/lib/includes/gnutls/x509.h
        echo "" > $@-tmp
        for i in `$(top_srcdir)/doc/scripts/getfuncs.pl <$(top_srcdir)/lib/includes/gnutls/x509.h|sort|uniq`; do \
@@ -375,7 +389,7 @@ enums.texi: $(HEADER_FILES)
 gnutls_TEXINFOS += $(ENUMS) $(FUNCS)
 DISTCLEANFILES += $(ENUMS) stamp_enums stamp_functions
 
-stamp_functions: gnutls-api.texi x509-api.texi pgp-api.texi pkcs12-api.texi tpm-api.texi pkcs11-api.texi abstract-api.texi compat-api.texi dtls-api.texi crypto-api.texi ocsp-api.texi tpm-api.texi
+stamp_functions: gnutls-api.texi x509-api.texi pgp-api.texi pkcs12-api.texi tpm-api.texi pkcs11-api.texi abstract-api.texi compat-api.texi dtls-api.texi crypto-api.texi ocsp-api.texi tpm-api.texi dane-api.texi
        -mkdir functions
        for i in $^; do \
                $(srcdir)/scripts/split-texi.pl functions < $$i; \
index 46195f9fe0e431272895ab576047bcd2b628667f..05246e14ab5a0fef833de76a9080ab5868c1e885 100644 (file)
@@ -60,6 +60,7 @@ to use this key exchange algorithm.
 @menu
 * X.509 certificates::
 * OpenPGP certificates::
+* Advanced certificate verification::
 * Digital signatures::
 @end menu
 
@@ -88,7 +89,6 @@ acceptable.  The framework is illustrated on @ref{fig:x509}.
 * X.509 distinguished names::
 * Verifying X.509 certificate paths::
 * Verifying a certificate in the context of TLS session::
-* Verifying a certificate using trust on first use authentication::
 @end menu
 
 @node X.509 certificate structure
@@ -301,42 +301,6 @@ about the peer's identity. It is required to verify if the
 certificate's owner is the one you expect. For more information
 consult @ref{gnutls_x509_crt_check_hostname}, section @ref{ex:verify} for an example, and @xcite{RFC2818}.
 
-@node Verifying a certificate using trust on first use authentication
-@subsection Verifying a certificate using trust on first use authentication
-@cindex verifying certificate paths
-@cindex SSH-style authentication
-@cindex Trust on first use
-@cindex Key pinning
-@tindex gnutls_certificate_verify_flags
-
-It is possible to use a trust on first use (similar to SSH) authentication 
-method in GnuTLS. That is the concept used by the SSH programs, where the 
-public key of the peer is not verified, or verified in an out-of-bound way,
-but subsequent connections to the same peer require the public key to 
-remain the same.  Such a system in combination with the typical CA 
-verification of a certificate, and OCSP revocation checks,
-can help to provide multiple factor verification, where a single point of
-failure is not enough to compromise the system. For example a server compromise
-may be detected using OCSP, and a CA compromise can be detected using
-the trust on first use method.
-Such a hybrid system with X.509 and trust on first use authentication is 
-shown in @ref{Simple client example with SSH-style certificate verification}.
-
-@showfuncdesc{gnutls_verify_stored_pubkey}
-@showfuncdesc{gnutls_store_pubkey}
-
-In addition to the above the @funcref{gnutls_store_commitment} can be 
-used to implement a key-pinning architecture as in @xcite{KEYPIN}. 
-This provides a way for web server to commit on a public key that is
-not yet active.
-
-@showfuncdesc{gnutls_store_commitment}
-
-The storage and verification functions may be used with the default
-text file based back-end, or another back-end may be specified. That
-should contain storage and retrieval functions and specified as below.
-
-@showfuncE{gnutls_tdb_init,gnutls_tdb_deinit,gnutls_tdb_set_verify_func,gnutls_tdb_set_store_func,gnutls_tdb_set_store_commitment_func}
 
 @node OpenPGP certificates
 @section @acronym{OpenPGP} certificates
@@ -474,7 +438,83 @@ to verify the signatures in the certificate sent by the peer.
 
 @showfuncdesc{gnutls_certificate_set_openpgp_keyring_file}
 
+@node Advanced certificate verification
+@section Advanced certificate verification
+@cindex Certificate verification
+
+@menu
+* Verifying a certificate using trust on first use authentication::
+* Verifying a certificate using DANE (DNSSEC)::
+@end menu
+
+@node Verifying a certificate using trust on first use authentication
+@subsection Verifying a certificate using trust on first use authentication
+@cindex verifying certificate paths
+@cindex SSH-style authentication
+@cindex Trust on first use
+@cindex Key pinning
+@tindex gnutls_certificate_verify_flags
+
+It is possible to use a trust on first use (TOFU) authentication 
+method in GnuTLS. That is the concept used by the SSH programs, where the 
+public key of the peer is not verified, or verified in an out-of-bound way,
+but subsequent connections to the same peer require the public key to 
+remain the same.  Such a system in combination with the typical CA 
+verification of a certificate, and OCSP revocation checks,
+can help to provide multiple factor verification, where a single point of
+failure is not enough to compromise the system. For example a server compromise
+may be detected using OCSP, and a CA compromise can be detected using
+the trust on first use method.
+Such a hybrid system with X.509 and trust on first use authentication is 
+shown in @ref{Simple client example with SSH-style certificate verification}.
+
+@showfuncdesc{gnutls_verify_stored_pubkey}
+@showfuncdesc{gnutls_store_pubkey}
+
+In addition to the above the @funcref{gnutls_store_commitment} can be 
+used to implement a key-pinning architecture as in @xcite{KEYPIN}. 
+This provides a way for web server to commit on a public key that is
+not yet active.
+
+@showfuncdesc{gnutls_store_commitment}
+
+The storage and verification functions may be used with the default
+text file based back-end, or another back-end may be specified. That
+should contain storage and retrieval functions and specified as below.
+
+@showfuncE{gnutls_tdb_init,gnutls_tdb_deinit,gnutls_tdb_set_verify_func,gnutls_tdb_set_store_func,gnutls_tdb_set_store_commitment_func}
+
+@node Verifying a certificate using DANE (DNSSEC)
+@subsection Verifying a certificate using DANE (DNSSEC)
+@cindex verifying certificate paths
+@cindex DANE
+@cindex DNSSEC
+@tindex gnutls_certificate_verify_flags
+
+The DANE protocol is a protocol that can be used to verify TLS certificates
+using the DNS (or better DNSSEC) protocols. The DNS security extensions (DNSSEC)
+provide an alternative public key infrastructure to the commercial CAs that
+are typically used to sign TLS certificates. The DANE protocol takes advantage
+of the DNSSEC infrastructure to verify TLS certificates. This can be 
+in addition to the verification by commercial CA infrastructure or 
+could even replace it where DNSSEC is deployed.
+
+The DANE functionality is provided by the @code{libdane} library that is shipped
+with GnuTLS and the function prototypes are in @code{gnutls/dane.h}. The
+high level verification functions are shown below.
+
+@showfuncdesc{dane_verify_crt}
+
+@showfuncB{dane_verify_session_crt,dane_strerror}
+
+The allowed flags for the verification function follow.
+
+@showenumdesc{dane_verify_flags_t,The DANE verification flags.}
+
+The following flags are returned by the verify functions to
+indicate the status of the verification.
 
+@showenumdesc{dane_verify_status_t,The DANE verification status flags.}
 
 
 @node Digital signatures
index 786c2503e92b19a66beee8bb45083a232871672c..549767c84bf0b290b2c65fbf5a9044f45a2a57a1 100644 (file)
@@ -12,6 +12,7 @@
 * PKCS 11 API::
 * TPM API::
 * Abstract key API::
+* DANE API::
 * Cryptographic API::
 * Compatibility API::
 @end menu
@@ -92,6 +93,15 @@ Their prototypes lie in @file{gnutls/abstract.h}.
 
 @include abstract-api.texi
 
+@node DANE API
+@section DANE API
+
+The following functions are to be used for DANE certificate verification.
+Their prototypes lie in @file{gnutls/dane.h}. Note that you need to link
+with the @code{libdane} library to use them.
+
+@include dane-api.texi
+
 @node Cryptographic API
 @section Cryptographic API
 
index dad4069c4f75739808eb2dab8345c8f6de6ab532..91f597097bb54d251ba51192c240c993a977391e 100644 (file)
@@ -7,7 +7,7 @@
 # 
 # DO NOT EDIT THIS FILE   (invoke-gnutls-cli.texi)
 # 
-# It has been AutoGen-ed  October  4, 2012 at 07:18:42 PM by AutoGen 5.16
+# It has been AutoGen-ed  October  6, 2012 at 03:27:13 AM by AutoGen 5.16
 # From the definitions    ../src/cli-args.def
 # and the template file   agtexi-cmd.tpl
 @end ignore
@@ -45,6 +45,8 @@ USAGE:  gnutls-cli [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]... [hostname]
                                 - may appear multiple times
        --tofu                 Enable trust on first use authentication
                                 - disabled as --no-tofu
+       --dane                 Enable DANE certificate verification (DNSSEC)
+                                - disabled as --no-dane
        --ocsp                 Enable OCSP certificate verification
                                 - disabled as --no-ocsp
    -r, --resume               Establish a session and resume
@@ -123,6 +125,14 @@ Specifies the debug level.
 
 This is the ``enable trust on first use authentication'' option.
 This option will, in addition to certificate authentication, perform authentication based on previously seen public keys, a model similar to SSH authentication.
+@anchor{gnutls-cli dane}
+@subheading dane option
+@cindex gnutls-cli-dane
+
+This is the ``enable dane certificate verification (dnssec)'' option.
+This option will, in addition to certificate authentication using 
+the trusted CAs, verify the server certificates using on the DANE information
+available via DNSSEC.
 @anchor{gnutls-cli ocsp}
 @subheading ocsp option
 @cindex gnutls-cli-ocsp
index fdf35879861be3b6d92a842a51f39f47f82bc40b..47dade5947dffce746abd3c640c23f4cb50b2ade 100644 (file)
@@ -31,7 +31,8 @@ HEADER_FILES = $(top_srcdir)/lib/includes/gnutls/gnutls.h.in \
        $(top_srcdir)/lib/includes/gnutls/pkcs12.h $(top_srcdir)/lib/includes/gnutls/pkcs11.h \
        $(top_srcdir)/lib/includes/gnutls/abstract.h $(top_srcdir)/lib/includes/gnutls/compat.h \
        $(top_srcdir)/lib/includes/gnutls/dtls.h $(top_srcdir)/lib/includes/gnutls/crypto.h \
-       $(top_srcdir)/lib/includes/gnutls/ocsp.h $(top_srcdir)/lib/includes/gnutls/tpm.h
+       $(top_srcdir)/lib/includes/gnutls/ocsp.h $(top_srcdir)/lib/includes/gnutls/tpm.h \
+       $(top_srcdir)/libdane/includes/gnutls/dane.h
 
 # Note that our .def files depend on autogen
 # supporting the @subheading texi keyword. This
@@ -892,6 +893,20 @@ stamp_mans: $(HEADER_FILES)
                echo -n "."; \
        done
        @echo ""
+       @echo -n "Creating man pages for dane.h..." && \
+       for i in `$(top_srcdir)/doc/scripts/getfuncs.pl <$(top_srcdir)/libdane/includes/gnutls/dane.h`; do \
+               $(top_srcdir)/doc/scripts/gdoc -man \
+                       -module $(PACKAGE) -sourceversion $(VERSION) \
+                       -bugsto $(PACKAGE_BUGREPORT) \
+                       -pkg-name "$(PACKAGE_NAME)" \
+                       -include "gnutls/dane.h" \
+                       -seeinfo $(PACKAGE) -verbatimcopying \
+                       -copyright "2012 Free Software Foundation, Inc." \
+                       -function $$i \
+                       $(top_srcdir)/libdane/*.c > $$i.3 2>/dev/null && \
+               echo -n "."; \
+       done
+       @echo ""
        @echo -n "Creating man pages for x509.h..." && \
        for i in `$(top_srcdir)/doc/scripts/getfuncs.pl <$(top_srcdir)/lib/includes/gnutls/x509.h`; do \
                $(top_srcdir)/doc/scripts/gdoc -man \
index 383924045f8848855102c3b05933fa7a52e6774a..9e7680558a4833ca5df9fcac5db595de7ff33804 100755 (executable)
@@ -42,7 +42,7 @@ while ($line=<STDIN>) {
         $func = $1;
     }
     
-    if ($func ne '' && $func =~ m/gnutls_.*/) {
+    if ($func ne '' && ($func =~ m/gnutls_.*/ || $func =~ m/dane_.*/)) {
       print $func . "\n";
     }
   }
diff --git a/libdane/Makefile.am b/libdane/Makefile.am
new file mode 100644 (file)
index 0000000..87a9413
--- /dev/null
@@ -0,0 +1,66 @@
+## Process this file with automake to produce Makefile.in
+# Copyright (C) 2012 KU Leuven
+#
+# Author: Nikos Mavrogiannopoulos
+#
+# This file is part of libdane.
+#
+# libdane is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3 of the
+# License, or (at your option) any later version.
+#
+# GnuTLS-extra is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>
+
+ACLOCAL_AMFLAGS = -I ../m4 -I ../gl/m4
+
+AM_CFLAGS = $(WERROR_CFLAGS) $(WSTACK_CFLAGS) $(WARN_CFLAGS)
+AM_CPPFLAGS = \
+       -I$(srcdir)/../gl                       \
+       -I$(builddir)/../gl                     \
+       -I$(builddir)/../lib/includes   \
+       -I$(srcdir)/../lib/includes     \
+       -I$(srcdir)/includes            \
+       -I$(builddir)/includes
+
+SUBDIRS = includes
+
+defexecdir = $(bindir)
+defexec_DATA = 
+
+
+libdane_la_LDFLAGS = -no-undefined
+
+if ENABLE_DANE
+lib_LTLIBRARIES = libdane.la
+
+libdane_la_SOURCES = dane.c errors.c libdane.map
+
+libdane_la_LIBADD = ../gl/libgnu.la \
+       ../lib/libgnutls.la
+
+libdane_la_LDFLAGS += -version-info $(LT_DANE_CURRENT):$(LT_DANE_REVISION):$(LT_DANE_AGE)
+
+libdane_la_LIBADD += $(LIBSOCKET) $(UNBOUND_LIBS)
+
+if HAVE_LD_VERSION_SCRIPT
+libdane_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libdane.map
+else
+libdane_la_LDFLAGS += -export-symbols-regex '^(dane).*'
+endif
+
+if HAVE_LD_OUTPUT_DEF
+libdane_la_LDFLAGS += \
+       -Wl,--output-def,libdane-$(DLL_VERSION).def
+libdane-$(DLL_VERSION).def: libdane.la
+defexec_DATA += libdane-$(DLL_VERSION).def
+endif
+endif
+
+DISTCLEANFILES = $(defexec_DATA)
diff --git a/libdane/dane.c b/libdane/dane.c
new file mode 100644 (file)
index 0000000..f3d2834
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2012 KU Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of libdane.
+ *
+ * libdane is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <unbound.h>
+#include <gnutls/dane.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include <gnutls/crypto.h>
+
+#define MAX_DATA_ENTRIES 4
+
+struct dane_query_st
+{
+       unsigned int data_entries;
+       dane_cert_usage_t usage[MAX_DATA_ENTRIES];
+       dane_cert_type_t  type[MAX_DATA_ENTRIES];
+       dane_match_type_t match[MAX_DATA_ENTRIES];
+       gnutls_datum_t data[MAX_DATA_ENTRIES];
+       struct ub_ctx* ctx;
+       struct ub_result* result;
+       unsigned int flags;
+       dane_query_status_t status;
+};
+
+/**
+ * dane_query_status:
+ * @q: The query structure
+ *
+ * This function will return the status of the query response.
+ * See %dane_query_status_t for the possible types.
+ *
+ * Returns: The status type.
+ **/
+dane_query_status_t dane_query_status(dane_query_t q)
+{
+       return q->status;
+}
+
+/**
+ * dane_query_entries:
+ * @q: The query structure
+ *
+ * This function will return the number of entries in a query.
+ *
+ * Returns: The number of entries.
+ **/
+unsigned int dane_query_entries(dane_query_t q)
+{
+       return q->data_entries;
+}
+
+/**
+ * dane_query_data:
+ * @q: The query structure
+ * @idx: The index of the query response.
+ * @usage: The certificate usage (see %dane_cert_usage_t)
+ * @type: The certificate type (see %dane_cert_type_t)
+ * @match: The DANE matching type (see %dane_match_type_t)
+ * @data: The DANE data.
+ *
+ * This function will provide the DANE data from the query
+ * response.
+ *
+ * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ **/
+int dane_query_data(dane_query_t q, unsigned int idx,
+                       unsigned int *usage, unsigned int *type,
+                       unsigned int *match, gnutls_datum_t * data)
+{
+       if (idx >= q->data_entries)
+               return DANE_E_REQUESTED_DATA_NOT_AVAILABLE;
+
+       if (usage)
+               *usage = q->usage[idx];
+       if (type)
+               *type = q->type[idx];
+       if (match)
+               *match = q->match[idx];
+       if (data) {
+               data->data = q->data[idx].data;
+               data->size = q->data[idx].size;
+       }
+
+       return DANE_E_SUCCESS;
+}
+
+/**
+ * dane_query_init:
+ * @q: The structure to be initialized
+ * @flags: flags from the DANE_F_* definitions
+ *
+ * This function will initialize a DANE query structure.
+ *
+ * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ **/
+int dane_query_init(dane_query_t* q, unsigned int flags)
+{
+       struct ub_ctx* ctx;
+       int ret;
+
+       *q = calloc(1, sizeof(struct dane_query_st));
+       if (*q == NULL)
+               return DANE_E_MEMORY_ERROR;
+
+       ctx = ub_ctx_create();
+       if(!ctx) {
+               ret = DANE_E_INITIALIZATION_ERROR;
+               goto cleanup;
+       }
+       ub_ctx_debugout(ctx, stderr);
+
+       if (!(flags & DANE_F_IGNORE_LOCAL_RESOLVER)) {
+               if( (ret=ub_ctx_resolvconf(ctx, NULL)) != 0) {
+                       ret = DANE_E_INITIALIZATION_ERROR;
+                       goto cleanup;
+               }
+
+               if( (ret=ub_ctx_hosts(ctx, NULL)) != 0) {
+                       ret = DANE_E_INITIALIZATION_ERROR;
+                       goto cleanup;
+               }
+       }
+
+       /* read public keys for DNSSEC verification */
+       if( (ret=ub_ctx_add_ta_file(ctx, (char*)UNBOUND_ROOT_KEY_FILE)) != 0) {
+               ret = DANE_E_INITIALIZATION_ERROR;
+               goto cleanup;
+       }
+
+       (*q)->ctx = ctx;
+       (*q)->flags = flags;
+       
+       return DANE_E_SUCCESS;
+cleanup:
+
+       if (ctx)
+               ub_ctx_delete(ctx);
+       free(*q);
+       
+       return ret;
+}
+
+/**
+ * dane_query_init:
+ * @q: The structure to be deinitialized
+ *
+ * This function will deinitialize a DANE query structure.
+ *
+ **/
+void dane_query_deinit(dane_query_t q)
+{
+       if (q->result)
+       ub_ctx_delete(q->ctx);
+               ub_resolve_free(q->result);
+
+       free(q);
+}
+
+/**
+ * dane_query_resolve_tlsa:
+ * @q: The query structure
+ * @host: The host name to resolve.
+ * @proto: The protocol type (tcp, udp, etc.)
+ * @port: The service port number (eg. 443).
+ *
+ * This function will query the DNS server for the TLSA (DANE)
+ * data for the given host.
+ *
+ * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ **/
+int dane_query_resolve_tlsa(dane_query_t q, const char* host, const char* proto, unsigned int port)
+{
+       char ns[1024];
+       int ret;
+       unsigned int i;
+
+       if (q->result) {
+               ub_resolve_free(q->result);
+               q->result = NULL;
+       }
+       
+       snprintf(ns, sizeof(ns), "_%u._%s.%s", port, proto, host);
+
+       /* query for webserver */
+       ret = ub_resolve(q->ctx, ns, 52, 1, &q->result);
+       if(ret != 0) {
+               return DANE_E_RESOLVING_ERROR;
+       }
+
+/* show first result */
+       if(!q->result->havedata) {
+               return DANE_E_NO_DANE_DATA;
+       }
+
+       i = 0;
+       do {
+
+               if (q->result->len[i] > 3)
+                       ret = DANE_E_SUCCESS;
+               else {
+                       return DANE_E_RECEIVED_CORRUPT_DATA;
+               }
+       
+               q->usage[i] = q->result->data[i][0];
+               q->type[i] = q->result->data[i][1];
+               q->match[i] = q->result->data[i][2];
+               q->data[i].data = (void*)&q->result->data[i][3];
+               q->data[i].size = q->result->len[i];
+               i++;
+       } while(q->result->data[i] != NULL);
+       
+       q->data_entries = i;
+
+       if (q->flags & DANE_F_REQUIRE_DNSSEC) {
+               if (!q->result->secure) {
+                       if (q->result->bogus)
+                               ret = DANE_E_INVALID_DNSSEC_SIG;
+                       else
+                               ret = DANE_E_NO_DNSSEC_SIG;
+               }
+       }
+
+       /* show security status */
+       if (q->result->secure)
+               q->status = DANE_QUERY_DNSSEC_VERIFIED;
+       else if (q->result->bogus)
+               q->status = DANE_QUERY_BOGUS;
+       else q->status = DANE_QUERY_NO_DNSSEC;
+
+       return ret;
+}
+
+static unsigned int matches(const gnutls_datum_t *raw1, const gnutls_datum_t *raw2, 
+                                                       dane_match_type_t match)
+{
+uint8_t digest[64];
+int ret;
+
+       if (match == DANE_MATCH_EXACT) {
+               if (raw1->size != raw2->size)
+                       return 0;
+
+               if (memcmp(raw1->data, raw2->data, raw1->size) != 0)
+                       return 0;
+               
+               return 1;
+       } else if (match == DANE_MATCH_SHA2_256) {
+
+               if (raw2->size < 32)
+                       return 0;
+               
+               ret = gnutls_hash_fast(GNUTLS_DIG_SHA256, raw1->data, raw1->size, digest);
+               if (ret < 0)
+                       return 0;
+
+               if (memcmp(digest, raw2->data, 32) != 0)
+                       return 0;
+               
+               return 1;
+       } else if (match == DANE_MATCH_SHA2_512) {
+               if (raw2->size < 64)
+                       return 0;
+               
+               ret = gnutls_hash_fast(GNUTLS_DIG_SHA512, raw1->data, raw1->size, digest);
+               if (ret < 0)
+                       return 0;
+               
+               if (memcmp(digest, raw2->data, 64) != 0)
+                       return 0;
+               
+               return 1;
+       }
+       
+       return 0;
+}
+
+static int crt_to_pubkey(const gnutls_datum_t *raw_crt, gnutls_datum_t * out)
+{
+gnutls_pubkey_t pub = NULL;
+gnutls_x509_crt_t crt = NULL;
+int ret;
+size_t size;
+
+       out->data = NULL;
+
+       ret = gnutls_x509_crt_init(&crt);
+       if (ret < 0)
+               return DANE_E_PUBKEY_ERROR;
+
+       ret = gnutls_pubkey_init( &pub);
+       if (ret < 0) {
+               ret = DANE_E_PUBKEY_ERROR;
+               goto cleanup;
+       }
+               
+       ret = gnutls_x509_crt_import(crt, raw_crt, GNUTLS_X509_FMT_DER);
+       if (ret < 0) {
+               ret = DANE_E_PUBKEY_ERROR;
+               goto cleanup;
+       }
+
+       ret = gnutls_pubkey_import_x509(pub, crt, 0);
+       if (ret < 0) {
+               ret = DANE_E_PUBKEY_ERROR;
+               goto cleanup;
+       }
+
+       size = 0;
+       ret = gnutls_pubkey_export(pub, GNUTLS_X509_FMT_DER, NULL, &size);
+       if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+               ret = DANE_E_PUBKEY_ERROR;
+               goto cleanup;
+       }
+       
+       out->data = malloc(size);
+       if (out->data == NULL) {
+               ret = DANE_E_MEMORY_ERROR;
+               goto cleanup;
+       }
+
+       ret = gnutls_pubkey_export(pub, GNUTLS_X509_FMT_DER, out->data, &size);
+       if (ret < 0) {
+               ret = DANE_E_PUBKEY_ERROR;
+               goto cleanup;
+       }
+       
+       out->size = size;
+
+       ret = 0;
+       goto clean_certs;
+
+cleanup:
+       free(out->data);
+clean_certs:
+       if (pub)
+               gnutls_pubkey_deinit(pub);
+       if (crt)
+               gnutls_x509_crt_deinit(crt);
+
+       return ret;
+}
+
+static int verify_ca(const gnutls_datum_t *raw_crt, unsigned raw_crt_size,
+                                        gnutls_certificate_type_t crt_type,
+                                        dane_cert_type_t ctype,
+                                        dane_match_type_t match, gnutls_datum_t * data,
+                                        unsigned int *verify)
+{
+gnutls_datum_t pubkey = {NULL, 0};
+int ret;
+
+       if (raw_crt_size < 2)
+               return DANE_E_INVALID_REQUEST;
+
+       if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
+       
+               if (!matches(&raw_crt[1], data, match))
+                       *verify |= DANE_VERIFY_CA_CONSTRAINS_VIOLATED;
+
+       } else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
+               ret = crt_to_pubkey(&raw_crt[1], &pubkey);
+               if (ret < 0)
+                       goto cleanup;
+
+               if (!matches(&pubkey, data, match))
+                       *verify |= DANE_VERIFY_CA_CONSTRAINS_VIOLATED;
+       }
+
+       ret = 0;
+cleanup:
+       free(pubkey.data);
+       return ret;
+}
+
+static int verify_ee(const gnutls_datum_t *raw_crt, gnutls_certificate_type_t crt_type,
+                dane_cert_type_t ctype, dane_match_type_t match, gnutls_datum_t * data,
+                unsigned int *verify)
+{
+gnutls_datum_t pubkey = {NULL, 0};
+int ret;
+
+       if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
+
+               if (!matches(raw_crt, data, match))
+                       *verify |= DANE_VERIFY_CERT_DIFFERS;
+
+       } else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
+
+               ret = crt_to_pubkey(raw_crt, &pubkey);
+               if (ret < 0)
+                       goto cleanup;
+
+               if (!matches(&pubkey, data, match))
+                       *verify |= DANE_VERIFY_CERT_DIFFERS;
+       }
+
+       ret = 0;
+cleanup:
+       free(pubkey.data);
+       return ret;
+}
+
+/**
+ * dane_verify_crt:
+ * @chain: A certificate chain
+ * @chain_size: The size of the chain
+ * @chain_type: The type of the certificate chain
+ * @hostname: The hostname associated with the chain
+ * @proto: The protocol of the service connecting (e.g. tcp)
+ * @port: The port of the service connecting (e.g. 443)
+ * @flags: The %DANE_F flags.
+ * @verify: An OR'ed list of %dane_verify_status_t.
+ *
+ * This function will verify the given certificate chain against the
+ * CA constrains and/or the certificate available via DANE. 
+ * If no information via DANE can be obtained the flag %DANE_VERIFY_NO_DANE_INFO
+ * is set. If a DNSSEC signature is not available for the DANE 
+ * record then the verify flag %DANE_VERIFY_NO_DNSSEC_DATA is set.
+ * 
+ * Note that when verifying untrusted certificates, it is recommended to 
+ * use the %DANE_F_REQUIRE_DNSSEC flag.
+ * 
+ * Due to the many possible options of DANE, there is no single threat
+ * model countered. When notifying the user about DANE verification results
+ * it may be better to mention: DANE verification did not reject the certificate,
+ * rather than mentioning a successful DANE verication.
+ * 
+ * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ **/
+int dane_verify_crt (
+       const gnutls_datum_t *chain, unsigned chain_size,
+       gnutls_certificate_type_t chain_type,
+       const char * hostname, const char* proto, unsigned int port,
+       unsigned int flags, unsigned int *verify)
+{
+dane_query_t q;
+int ret;
+unsigned int usage, type, match, idx, status;
+gnutls_datum_t data;
+       
+       if (chain_type != GNUTLS_CRT_X509)
+               return DANE_E_INVALID_REQUEST;
+       
+       *verify = 0;
+       
+       ret = dane_query_init(&q, flags);
+       if (ret < 0) {
+               return ret;
+       }
+       
+       ret = dane_query_resolve_tlsa(q, hostname, proto, port);
+       if (ret < 0) {
+               goto cleanup;
+       }
+
+       status = dane_query_status(q);
+       if (status == DANE_QUERY_BOGUS) {
+               *verify |= DANE_VERIFY_DNSSEC_DATA_INVALID;
+               goto cleanup;
+       } else if (status == DANE_QUERY_NO_DNSSEC) {
+               *verify |= DANE_VERIFY_NO_DNSSEC_DATA;
+               goto cleanup;
+       }
+
+       idx = 0;
+       do {
+               ret = dane_query_data(q, idx++, &usage, &type, &match, &data);
+               if (ret == DANE_E_REQUESTED_DATA_NOT_AVAILABLE)
+                       break;
+
+               if (ret < 0) {
+                       goto cleanup;
+               }
+       
+               if (usage == DANE_CERT_USAGE_LOCAL_CA || usage == DANE_CERT_USAGE_CA) {
+                       ret = verify_ca(chain, chain_size, chain_type, type, match, &data, verify);
+                       if (ret < 0)
+                               goto cleanup;
+               
+               } else if (usage == DANE_CERT_USAGE_LOCAL_EE || usage == DANE_CERT_USAGE_EE) {
+                       ret = verify_ee(&chain[0], chain_type, type, match, &data, verify);
+                       if (ret < 0)
+                               goto cleanup;
+               }
+       } while(1);
+
+       ret = 0;
+
+cleanup:
+       dane_query_deinit(q);
+       return ret;
+}
+
+/**
+ * dane_verify_session_crt:
+ * @session: A gnutls session
+ * @hostname: The hostname associated with the chain
+ * @proto: The protocol of the service connecting (e.g. tcp)
+ * @port: The port of the service connecting (e.g. 443)
+ * @flags: The %DANE_F flags.
+ * @verify: An OR'ed list of %dane_verify_status_t.
+ *
+ * This function will verify session's certificate chain against the
+ * CA constrains and/or the certificate available via DANE. 
+ * See dane_verify_crt() for more information.
+ *
+ * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ **/
+int dane_verify_session_crt (
+       gnutls_session_t session,
+       const char * hostname, const char* proto, unsigned int port,
+       unsigned int flags, unsigned int *verify)
+{
+const gnutls_datum_t *cert_list;
+unsigned int cert_list_size = 0;
+unsigned int type;
+
+       cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
+       if (cert_list_size == 0) {
+               return DANE_E_NO_CERT;
+       }
+       
+       type = gnutls_certificate_type_get(session);
+       
+       return dane_verify_crt(cert_list, cert_list_size, type, hostname, proto, port, flags, verify);
+}
diff --git a/libdane/errors.c b/libdane/errors.c
new file mode 100644 (file)
index 0000000..0753265
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 KU Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of libdane.
+ *
+ * libdane is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+#include <gnutls/dane.h>
+
+/* I18n of error codes. */
+#include "gettext.h"
+#define _(String) dgettext (PACKAGE, String)
+#define N_(String) gettext_noop (String)
+
+#define ERROR_ENTRY(desc, name) \
+       { desc, #name, name}
+
+struct error_entry
+{
+  const char *desc;
+  const char *_name;
+  int number;
+};
+typedef struct error_entry error_entry;
+
+static const error_entry error_algorithms[] = {
+  ERROR_ENTRY (N_("Success."), DANE_E_SUCCESS),
+  ERROR_ENTRY (N_("There was error initializing the DNS query."),
+               DANE_E_INITIALIZATION_ERROR),
+  ERROR_ENTRY (N_("There was an error while resolving."),
+               DANE_E_RESOLVING_ERROR),
+  ERROR_ENTRY (N_("No DANE data were found."),
+               DANE_E_NO_DANE_DATA),
+  ERROR_ENTRY (N_("No DNSSEC signature was found."),
+               DANE_E_NO_DNSSEC_SIG),
+  ERROR_ENTRY (N_("Received corrupt data."),
+               DANE_E_RECEIVED_CORRUPT_DATA),
+  ERROR_ENTRY (N_("The DNSSEC signature is invalid."),
+               DANE_E_INVALID_DNSSEC_SIG),
+  ERROR_ENTRY (N_("There was a memory error."),
+               DANE_E_MEMORY_ERROR),
+  ERROR_ENTRY (N_("There requested data are not available."),
+               DANE_E_REQUESTED_DATA_NOT_AVAILABLE),
+  ERROR_ENTRY (N_("There request is invalid."),
+               DANE_E_INVALID_REQUEST),
+  ERROR_ENTRY (N_("There was an error in the public key."),
+               DANE_E_PUBKEY_ERROR),
+  ERROR_ENTRY (N_("No certificate was found."),
+               DANE_E_NO_CERT),
+  {NULL, NULL, 0}
+};
+
+/**
+ * dane_strerror:
+ * @error: is a DANE error code, a negative error code
+ *
+ * This function is similar to strerror.  The difference is that it
+ * accepts an error number returned by a gnutls function; In case of
+ * an unknown error a descriptive string is sent instead of %NULL.
+ *
+ * Error codes are always a negative error code.
+ *
+ * Returns: A string explaining the DANE error message.
+ **/
+const char *
+dane_strerror (int error)
+{
+  const char *ret = NULL;
+  const error_entry *p;
+
+  for (p = error_algorithms; p->desc != NULL; p++)
+    {
+      if (p->number == error)
+        {
+          ret = p->desc;
+          break;
+        }
+    }
+
+  /* avoid prefix */
+  if (ret == NULL)
+    return _("(unknown error code)");
+
+  return _(ret);
+}
diff --git a/libdane/includes/Makefile.am b/libdane/includes/Makefile.am
new file mode 100644 (file)
index 0000000..59fdcbe
--- /dev/null
@@ -0,0 +1,25 @@
+## Process this file with automake to produce Makefile.in
+# Copyright (C) 2012 KU Leuven
+#
+# Author: Nikos Mavrogiannopoulos
+#
+# This file is part of libdane.
+#
+# libdane is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3 of the
+# License, or (at your option) any later version.
+#
+# GnuTLS-extra is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>
+
+nobase_include_HEADERS = 
+
+if ENABLE_DANE
+nobase_include_HEADERS += gnutls/dane.h
+endif
diff --git a/libdane/includes/gnutls/dane.h b/libdane/includes/gnutls/dane.h
new file mode 100644 (file)
index 0000000..fbe9b89
--- /dev/null
@@ -0,0 +1,162 @@
+/* -*- c -*-
+ * Copyright (C) 2012 KU Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of libdane.
+ *
+ * libdane is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+#include <gnutls/gnutls.h> /* for gnutls_datum_t */
+
+/**
+ * dane_cert_usage_t:
+ * @DANE_CERT_USAGE_CA: CA constraint. The certificate/key
+ *   presented must have signed the verified key.
+ * @DANE_CERT_USAGE_EE: The key or the certificate of the end
+ *   entity.
+ * @DANE_CERT_USAGE_LOCAL_CA: The remote CA is local and possibly
+ *   untrusted by the verifier.
+ * @DANE_CERT_USAGE_LOCAL_EE: The remote end-entity key is local
+ *   and possibly untrusted by the verifier (not signed by a CA).
+ *
+ * Enumeration of different certificate usage types.
+ */
+typedef enum dane_cert_usage_t
+{
+  DANE_CERT_USAGE_CA = 0,
+  DANE_CERT_USAGE_EE = 1,
+  DANE_CERT_USAGE_LOCAL_CA = 2,
+  DANE_CERT_USAGE_LOCAL_EE = 3
+} dane_cert_usage_t;
+
+/**
+ * dane_cert_type_t:
+ * @DANE_CERT_X509: An X.509 certificate.
+ * @DANE_CERT_PK: A public key.
+ *
+ * Enumeration of different certificate types.
+ */
+typedef enum dane_cert_type_t 
+{
+  DANE_CERT_X509 = 0,
+  DANE_CERT_PK = 1
+} dane_cert_type_t;
+
+/**
+ * dane_match_type_t:
+ * @DANE_MATCH_EXACT: The full content.
+ * @DANE_MATCH_SHA2_256: A SHA-256 hash of the content.
+ * @DANE_MATCH_SHA2_512: A SHA-512 hash of the content.
+ *
+ * Enumeration of different content matching types.
+ */
+typedef enum dane_match_type_t 
+{
+  DANE_MATCH_EXACT = 0,
+  DANE_MATCH_SHA2_256 = 1,
+  DANE_MATCH_SHA2_512 = 2
+} dane_match_type_t;
+
+/**
+ * dane_query_status_t:
+ * @DANE_QUERY_UNKNOWN: There was no query.
+ * @DANE_QUERY_DNSSEC_VERIFIED: The query was verified using DNSSEC.
+ * @DANE_QUERY_BOGUS: The query has wrong DNSSEC signature.
+ * @DANE_QUERY_NO_DNSSEC: The query has no DNSSEC data.
+ *
+ * Enumeration of different certificate types.
+ */
+typedef enum dane_query_status_t 
+{
+  DANE_QUERY_UNKNOWN = 0,
+  DANE_QUERY_DNSSEC_VERIFIED,
+  DANE_QUERY_BOGUS,
+  DANE_QUERY_NO_DNSSEC
+} dane_query_status_t;
+
+typedef struct dane_query_st *dane_query_t;
+
+
+int dane_query_init (dane_query_t* q, unsigned int flags);
+void dane_query_deinit (dane_query_t q);
+int dane_query_resolve_tlsa (dane_query_t q, const char* host, const char* proto, unsigned int port);
+int dane_query_data(dane_query_t q, unsigned int idx,
+                                       unsigned int *usage, unsigned int *type,
+                                       unsigned int *match, gnutls_datum_t * data);
+dane_query_status_t dane_query_status(dane_query_t q);
+unsigned int dane_query_entries(dane_query_t q);
+
+
+/**
+ * dane_verify_status_t:
+ * @DANE_VERIFY_CA_CONSTRAINS_VIOLATED: The CA constrains was violated.
+ * @DANE_VERIFY_CERT_DIFFERS: The certificate obtained via DNS differs.
+ * @DANE_VERIFY_NO_DANE_INFO: No DANE data were found in the DNS record.
+ * @DANE_VERIFY_DNSSEC_DATA_INVALID: The DNSSEC data are invalid.
+ * @DANE_VERIFY_NO_DNSSEC_DATA: The DNS data were not signed using DNSSEC.
+ *
+ * Enumeration of different verification status flags.
+ */
+typedef enum dane_verify_status_t 
+{
+  DANE_VERIFY_CA_CONSTRAINS_VIOLATED = 1,
+  DANE_VERIFY_CERT_DIFFERS = 1<<1,
+  DANE_VERIFY_NO_DANE_INFO = 1<<2,
+  DANE_VERIFY_DNSSEC_DATA_INVALID = 1<<3,
+  DANE_VERIFY_NO_DNSSEC_DATA = 1<<4,
+} dane_verify_status_t;
+
+/**
+ * dane_verify_flags_t:
+ * @DANE_F_REQUIRE_DNSSEC: Require DNSSEC for verification.
+ * @DANE_F_IGNORE_LOCAL_RESOLVER: Many systems are not DNSSEC-ready. In that case the local resolver is ignored, and a direct recursive resolve occurs.
+ *
+ * Enumeration of different verification flags.
+ */
+typedef enum dane_verify_flags_t 
+{
+  DANE_F_REQUIRE_DNSSEC = 1,
+  DANE_F_IGNORE_LOCAL_RESOLVER = 1<<2,
+} dane_verify_flags_t;
+
+int dane_verify_crt (
+       const gnutls_datum_t *chain, unsigned chain_size,
+       gnutls_certificate_type_t chain_type,
+       const char * hostname, const char* proto, unsigned int port,
+       unsigned int flags, unsigned int *verify);
+
+int dane_verify_session_crt (
+       gnutls_session_t session,
+       const char * hostname, const char* proto, unsigned int port,
+       unsigned int flags, unsigned int *verify);
+
+const char * dane_strerror (int error);
+
+#define DANE_E_SUCCESS 0
+#define DANE_E_INITIALIZATION_ERROR -1
+#define DANE_E_RESOLVING_ERROR -2
+#define DANE_E_NO_DANE_DATA -3
+#define DANE_E_RECEIVED_CORRUPT_DATA -4
+#define DANE_E_INVALID_DNSSEC_SIG -5
+#define DANE_E_NO_DNSSEC_SIG -6
+#define DANE_E_MEMORY_ERROR -7
+#define DANE_E_REQUESTED_DATA_NOT_AVAILABLE -8
+#define DANE_E_INVALID_REQUEST -9
+#define DANE_E_PUBKEY_ERROR -10
+#define DANE_E_NO_CERT -11
+
diff --git a/libdane/libdane.map b/libdane/libdane.map
new file mode 100644 (file)
index 0000000..a5af353
--- /dev/null
@@ -0,0 +1,19 @@
+# libgnutls.map -- libgnutls linker version script.           -*- ld-script -*-
+
+DANE_0_0
+{
+  global:
+       dane_strerror;
+       dane_verify_session_crt;
+       dane_verify_crt;
+       dane_query_init;
+       dane_query_deinit;
+       dane_query_resolve_tlsa;
+       dane_query_data;
+       dane_query_status;
+       dane_query_entries;
+
+  local:
+    *;
+};
+
index 6c9f81497fb377ee4694c5a21d9dcf3157f60e90..d3c8c79666bb6d3495a58581dffccc2c0d6106ed 100644 (file)
@@ -47,6 +47,10 @@ AC_DEFUN([LIBGNUTLS_HOOKS],
   AC_SUBST(LT_SSL_REVISION, 2)
   AC_SUBST(LT_SSL_AGE, 0)
 
+  AC_SUBST(LT_DANE_CURRENT, 0)
+  AC_SUBST(LT_DANE_REVISION, 0)
+  AC_SUBST(LT_DANE_AGE, 0)
+
   AC_SUBST(CXX_LT_CURRENT, 29)
   AC_SUBST(CXX_LT_REVISION, 0)
   AC_SUBST(CXX_LT_AGE, 1)
index 5a11ebee3e4d2f1ca6673baad31bbb846257f4b7..f4aa7e024d0dc3f056b2707796b019882b1c4544 100644 (file)
@@ -35,6 +35,7 @@ AM_CPPFLAGS = \
        -I$(builddir)/../gl                     \
        -I$(builddir)/../lib/includes           \
        -I$(srcdir)/../lib/includes             \
+       -I$(srcdir)/../libdane/includes         \
        -I$(srcdir)/../extra/includes   \
        $(LIBOPTS_CFLAGS)
 
@@ -102,6 +103,9 @@ gnutls_cli_SOURCES = cli.c common.h common.c \
        socket.c socket.h ocsptool-common.c \
        $(BENCHMARK_SRCS)
 gnutls_cli_LDADD = ../lib/libgnutls.la
+if ENABLE_DANE
+gnutls_cli_LDADD += ../libdane/libdane.la
+endif
 gnutls_cli_LDADD += libcmd-cli.la ../gl/libgnu.la $(LIBOPTS_LDADD) $(LTLIBINTL)
 gnutls_cli_LDADD += $(LIBSOCKET) $(GETADDRINFO_LIB) $(LIB_CLOCK_GETTIME) \
         $(SERVENT_LIB)
index 62b005444d5c9205f192cacc5d817517a5f9e12d..05f8af5e8fea22638299ea5ba0dd668aee85dc0c 100644 (file)
@@ -2,7 +2,7 @@
  *  
  *  DO NOT EDIT THIS FILE   (cli-args.c)
  *  
- *  It has been AutoGen-ed  October  4, 2012 at 07:09:10 PM by AutoGen 5.16
+ *  It has been AutoGen-ed  October  6, 2012 at 03:20:01 AM by AutoGen 5.16
  *  From the definitions    cli-args.def
  *  and the template file   options
  *
@@ -67,7 +67,7 @@ extern FILE * option_usage_fp;
 /*
  *  gnutls-cli option static const strings
  */
-static char const gnutls_cli_opt_strs[3608] =
+static char const gnutls_cli_opt_strs[3667] =
 /*     0 */ "gnutls-cli @VERSION@\n"
             "Copyright (C) 2000-2012 Free Software Foundation, all rights reserved.\n"
             "This is free software. It is licensed for use, modification and\n"
@@ -94,131 +94,134 @@ static char const gnutls_cli_opt_strs[3608] =
 /*   997 */ "TOFU\0"
 /*  1002 */ "no-tofu\0"
 /*  1010 */ "no\0"
-/*  1013 */ "Enable OCSP certificate verification\0"
-/*  1050 */ "OCSP\0"
-/*  1055 */ "no-ocsp\0"
-/*  1063 */ "Establish a session and resume\0"
-/*  1094 */ "RESUME\0"
-/*  1101 */ "resume\0"
-/*  1108 */ "Activate heartbeat support\0"
-/*  1135 */ "HEARTBEAT\0"
-/*  1145 */ "heartbeat\0"
-/*  1155 */ "Establish a session and rehandshake\0"
-/*  1191 */ "REHANDSHAKE\0"
-/*  1203 */ "rehandshake\0"
-/*  1215 */ "Don't accept session tickets\0"
-/*  1244 */ "NOTICKET\0"
-/*  1253 */ "noticket\0"
-/*  1262 */ "Enable OCSP status request\0"
-/*  1289 */ "OCSP_STATUS_REQUEST\0"
-/*  1309 */ "no-ocsp-status-request\0"
-/*  1332 */ "Connect, establish a plain session and start TLS.\0"
-/*  1382 */ "STARTTLS\0"
-/*  1391 */ "starttls\0"
-/*  1400 */ "Use DTLS (datagram TLS) over UDP\0"
-/*  1433 */ "UDP\0"
-/*  1437 */ "udp\0"
-/*  1441 */ "Set MTU for datagram TLS\0"
-/*  1466 */ "MTU\0"
-/*  1470 */ "mtu\0"
-/*  1474 */ "Send CR LF instead of LF\0"
-/*  1499 */ "CRLF\0"
-/*  1504 */ "crlf\0"
-/*  1509 */ "Use DER format for certificates to read from\0"
-/*  1554 */ "X509FMTDER\0"
-/*  1565 */ "x509fmtder\0"
-/*  1576 */ "Send the openpgp fingerprint, instead of the key\0"
-/*  1625 */ "FINGERPRINT\0"
-/*  1637 */ "fingerprint\0"
-/*  1649 */ "Disable all the TLS extensions\0"
-/*  1680 */ "DISABLE_EXTENSIONS\0"
-/*  1699 */ "disable-extensions\0"
-/*  1718 */ "Print peer's certificate in PEM format\0"
-/*  1757 */ "PRINT_CERT\0"
-/*  1768 */ "print-cert\0"
-/*  1779 */ "The maximum record size to advertize\0"
-/*  1816 */ "RECORDSIZE\0"
-/*  1827 */ "recordsize\0"
-/*  1838 */ "The minimum number of bits allowed for DH\0"
-/*  1880 */ "DH_BITS\0"
-/*  1888 */ "dh-bits\0"
-/*  1896 */ "Priorities string\0"
-/*  1914 */ "PRIORITY\0"
-/*  1923 */ "priority\0"
-/*  1932 */ "Certificate file or PKCS #11 URL to use\0"
-/*  1972 */ "X509CAFILE\0"
-/*  1983 */ "x509cafile\0"
-/*  1994 */ "CRL file to use\0"
-/*  2010 */ "X509CRLFILE\0"
-/*  2022 */ "x509crlfile\0"
-/*  2034 */ "PGP Key file to use\0"
-/*  2054 */ "PGPKEYFILE\0"
-/*  2065 */ "pgpkeyfile\0"
-/*  2076 */ "PGP Key ring file to use\0"
-/*  2101 */ "PGPKEYRING\0"
-/*  2112 */ "pgpkeyring\0"
-/*  2123 */ "PGP Public Key (certificate) file to use\0"
-/*  2164 */ "PGPCERTFILE\0"
-/*  2176 */ "pgpcertfile\0"
-/*  2188 */ "X.509 key file or PKCS #11 URL to use\0"
-/*  2226 */ "X509KEYFILE\0"
-/*  2238 */ "x509keyfile\0"
-/*  2250 */ "X.509 Certificate file or PKCS #11 URL to use\0"
-/*  2296 */ "X509CERTFILE\0"
-/*  2309 */ "x509certfile\0"
-/*  2322 */ "PGP subkey to use (hex or auto)\0"
-/*  2354 */ "PGPSUBKEY\0"
-/*  2364 */ "pgpsubkey\0"
-/*  2374 */ "SRP username to use\0"
-/*  2394 */ "SRPUSERNAME\0"
-/*  2406 */ "srpusername\0"
-/*  2418 */ "SRP password to use\0"
-/*  2438 */ "SRPPASSWD\0"
-/*  2448 */ "srppasswd\0"
-/*  2458 */ "PSK username to use\0"
-/*  2478 */ "PSKUSERNAME\0"
-/*  2490 */ "pskusername\0"
-/*  2502 */ "PSK key (in hex) to use\0"
-/*  2526 */ "PSKKEY\0"
-/*  2533 */ "pskkey\0"
-/*  2540 */ "The port or service to connect to\0"
-/*  2574 */ "PORT\0"
-/*  2579 */ "port\0"
-/*  2584 */ "Don't abort program if server certificate can't be validated\0"
-/*  2645 */ "INSECURE\0"
-/*  2654 */ "insecure\0"
-/*  2663 */ "Benchmark individual ciphers\0"
-/*  2692 */ "BENCHMARK_CIPHERS\0"
-/*  2710 */ "benchmark-ciphers\0"
-/*  2728 */ "Benchmark individual software ciphers (no hw acceleration)\0"
-/*  2787 */ "BENCHMARK_SOFT_CIPHERS\0"
-/*  2810 */ "benchmark-soft-ciphers\0"
-/*  2833 */ "Benchmark TLS key exchange methods\0"
-/*  2868 */ "BENCHMARK_TLS_KX\0"
-/*  2885 */ "benchmark-tls-kx\0"
-/*  2902 */ "Benchmark TLS ciphers\0"
-/*  2924 */ "BENCHMARK_TLS_CIPHERS\0"
-/*  2946 */ "benchmark-tls-ciphers\0"
-/*  2968 */ "Print a list of the supported algorithms and modes\0"
-/*  3019 */ "LIST\0"
-/*  3024 */ "list\0"
-/*  3029 */ "Display extended usage information and exit\0"
-/*  3073 */ "help\0"
-/*  3078 */ "Extended usage information passed thru pager\0"
-/*  3123 */ "more-help\0"
-/*  3133 */ "Output version information and exit\0"
-/*  3169 */ "version\0"
-/*  3177 */ "GNUTLS_CLI\0"
-/*  3188 */ "gnutls-cli - GnuTLS client - Ver. @VERSION@\n"
+/*  1013 */ "Enable DANE certificate verification (DNSSEC)\0"
+/*  1059 */ "DANE\0"
+/*  1064 */ "no-dane\0"
+/*  1072 */ "Enable OCSP certificate verification\0"
+/*  1109 */ "OCSP\0"
+/*  1114 */ "no-ocsp\0"
+/*  1122 */ "Establish a session and resume\0"
+/*  1153 */ "RESUME\0"
+/*  1160 */ "resume\0"
+/*  1167 */ "Activate heartbeat support\0"
+/*  1194 */ "HEARTBEAT\0"
+/*  1204 */ "heartbeat\0"
+/*  1214 */ "Establish a session and rehandshake\0"
+/*  1250 */ "REHANDSHAKE\0"
+/*  1262 */ "rehandshake\0"
+/*  1274 */ "Don't accept session tickets\0"
+/*  1303 */ "NOTICKET\0"
+/*  1312 */ "noticket\0"
+/*  1321 */ "Enable OCSP status request\0"
+/*  1348 */ "OCSP_STATUS_REQUEST\0"
+/*  1368 */ "no-ocsp-status-request\0"
+/*  1391 */ "Connect, establish a plain session and start TLS.\0"
+/*  1441 */ "STARTTLS\0"
+/*  1450 */ "starttls\0"
+/*  1459 */ "Use DTLS (datagram TLS) over UDP\0"
+/*  1492 */ "UDP\0"
+/*  1496 */ "udp\0"
+/*  1500 */ "Set MTU for datagram TLS\0"
+/*  1525 */ "MTU\0"
+/*  1529 */ "mtu\0"
+/*  1533 */ "Send CR LF instead of LF\0"
+/*  1558 */ "CRLF\0"
+/*  1563 */ "crlf\0"
+/*  1568 */ "Use DER format for certificates to read from\0"
+/*  1613 */ "X509FMTDER\0"
+/*  1624 */ "x509fmtder\0"
+/*  1635 */ "Send the openpgp fingerprint, instead of the key\0"
+/*  1684 */ "FINGERPRINT\0"
+/*  1696 */ "fingerprint\0"
+/*  1708 */ "Disable all the TLS extensions\0"
+/*  1739 */ "DISABLE_EXTENSIONS\0"
+/*  1758 */ "disable-extensions\0"
+/*  1777 */ "Print peer's certificate in PEM format\0"
+/*  1816 */ "PRINT_CERT\0"
+/*  1827 */ "print-cert\0"
+/*  1838 */ "The maximum record size to advertize\0"
+/*  1875 */ "RECORDSIZE\0"
+/*  1886 */ "recordsize\0"
+/*  1897 */ "The minimum number of bits allowed for DH\0"
+/*  1939 */ "DH_BITS\0"
+/*  1947 */ "dh-bits\0"
+/*  1955 */ "Priorities string\0"
+/*  1973 */ "PRIORITY\0"
+/*  1982 */ "priority\0"
+/*  1991 */ "Certificate file or PKCS #11 URL to use\0"
+/*  2031 */ "X509CAFILE\0"
+/*  2042 */ "x509cafile\0"
+/*  2053 */ "CRL file to use\0"
+/*  2069 */ "X509CRLFILE\0"
+/*  2081 */ "x509crlfile\0"
+/*  2093 */ "PGP Key file to use\0"
+/*  2113 */ "PGPKEYFILE\0"
+/*  2124 */ "pgpkeyfile\0"
+/*  2135 */ "PGP Key ring file to use\0"
+/*  2160 */ "PGPKEYRING\0"
+/*  2171 */ "pgpkeyring\0"
+/*  2182 */ "PGP Public Key (certificate) file to use\0"
+/*  2223 */ "PGPCERTFILE\0"
+/*  2235 */ "pgpcertfile\0"
+/*  2247 */ "X.509 key file or PKCS #11 URL to use\0"
+/*  2285 */ "X509KEYFILE\0"
+/*  2297 */ "x509keyfile\0"
+/*  2309 */ "X.509 Certificate file or PKCS #11 URL to use\0"
+/*  2355 */ "X509CERTFILE\0"
+/*  2368 */ "x509certfile\0"
+/*  2381 */ "PGP subkey to use (hex or auto)\0"
+/*  2413 */ "PGPSUBKEY\0"
+/*  2423 */ "pgpsubkey\0"
+/*  2433 */ "SRP username to use\0"
+/*  2453 */ "SRPUSERNAME\0"
+/*  2465 */ "srpusername\0"
+/*  2477 */ "SRP password to use\0"
+/*  2497 */ "SRPPASSWD\0"
+/*  2507 */ "srppasswd\0"
+/*  2517 */ "PSK username to use\0"
+/*  2537 */ "PSKUSERNAME\0"
+/*  2549 */ "pskusername\0"
+/*  2561 */ "PSK key (in hex) to use\0"
+/*  2585 */ "PSKKEY\0"
+/*  2592 */ "pskkey\0"
+/*  2599 */ "The port or service to connect to\0"
+/*  2633 */ "PORT\0"
+/*  2638 */ "port\0"
+/*  2643 */ "Don't abort program if server certificate can't be validated\0"
+/*  2704 */ "INSECURE\0"
+/*  2713 */ "insecure\0"
+/*  2722 */ "Benchmark individual ciphers\0"
+/*  2751 */ "BENCHMARK_CIPHERS\0"
+/*  2769 */ "benchmark-ciphers\0"
+/*  2787 */ "Benchmark individual software ciphers (no hw acceleration)\0"
+/*  2846 */ "BENCHMARK_SOFT_CIPHERS\0"
+/*  2869 */ "benchmark-soft-ciphers\0"
+/*  2892 */ "Benchmark TLS key exchange methods\0"
+/*  2927 */ "BENCHMARK_TLS_KX\0"
+/*  2944 */ "benchmark-tls-kx\0"
+/*  2961 */ "Benchmark TLS ciphers\0"
+/*  2983 */ "BENCHMARK_TLS_CIPHERS\0"
+/*  3005 */ "benchmark-tls-ciphers\0"
+/*  3027 */ "Print a list of the supported algorithms and modes\0"
+/*  3078 */ "LIST\0"
+/*  3083 */ "list\0"
+/*  3088 */ "Display extended usage information and exit\0"
+/*  3132 */ "help\0"
+/*  3137 */ "Extended usage information passed thru pager\0"
+/*  3182 */ "more-help\0"
+/*  3192 */ "Output version information and exit\0"
+/*  3228 */ "version\0"
+/*  3236 */ "GNUTLS_CLI\0"
+/*  3247 */ "gnutls-cli - GnuTLS client - Ver. @VERSION@\n"
             "USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]... [hostname]\n\0"
-/*  3301 */ "bug-gnutls@gnu.org\0"
-/*  3320 */ "\n\n\0"
-/*  3323 */ "\n"
+/*  3360 */ "bug-gnutls@gnu.org\0"
+/*  3379 */ "\n\n\0"
+/*  3382 */ "\n"
             "Simple client program to set up a TLS connection to some other computer.  It\n"
             "sets up a TLS connection and forwards data from the standard input to the\n"
             "secured socket and vice versa.\n\0"
-/*  3507 */ "gnutls-cli @VERSION@\0"
-/*  3528 */ "Usage: gnutls-cli [options] hostname\n"
+/*  3566 */ "gnutls-cli @VERSION@\0"
+/*  3587 */ "Usage: gnutls-cli [options] hostname\n"
             "gnutls-cli --help for usage instructions.\n";
 
 /*
@@ -248,12 +251,22 @@ static char const gnutls_cli_opt_strs[3608] =
 #define TOFU_name      (NOT_TOFU_name + 3)
 #define TOFU_FLAGS     (OPTST_DISABLED)
 
+/*
+ *  dane option description:
+ */
+#define DANE_DESC      (gnutls_cli_opt_strs+1013)
+#define DANE_NAME      (gnutls_cli_opt_strs+1059)
+#define NOT_DANE_name  (gnutls_cli_opt_strs+1064)
+#define NOT_DANE_PFX   (gnutls_cli_opt_strs+1010)
+#define DANE_name      (NOT_DANE_name + 3)
+#define DANE_FLAGS     (OPTST_DISABLED)
+
 /*
  *  ocsp option description:
  */
-#define OCSP_DESC      (gnutls_cli_opt_strs+1013)
-#define OCSP_NAME      (gnutls_cli_opt_strs+1050)
-#define NOT_OCSP_name  (gnutls_cli_opt_strs+1055)
+#define OCSP_DESC      (gnutls_cli_opt_strs+1072)
+#define OCSP_NAME      (gnutls_cli_opt_strs+1109)
+#define NOT_OCSP_name  (gnutls_cli_opt_strs+1114)
 #define NOT_OCSP_PFX   (gnutls_cli_opt_strs+1010)
 #define OCSP_name      (NOT_OCSP_name + 3)
 #define OCSP_FLAGS     (OPTST_DISABLED)
@@ -261,41 +274,41 @@ static char const gnutls_cli_opt_strs[3608] =
 /*
  *  resume option description:
  */
-#define RESUME_DESC      (gnutls_cli_opt_strs+1063)
-#define RESUME_NAME      (gnutls_cli_opt_strs+1094)
-#define RESUME_name      (gnutls_cli_opt_strs+1101)
+#define RESUME_DESC      (gnutls_cli_opt_strs+1122)
+#define RESUME_NAME      (gnutls_cli_opt_strs+1153)
+#define RESUME_name      (gnutls_cli_opt_strs+1160)
 #define RESUME_FLAGS     (OPTST_DISABLED)
 
 /*
  *  heartbeat option description:
  */
-#define HEARTBEAT_DESC      (gnutls_cli_opt_strs+1108)
-#define HEARTBEAT_NAME      (gnutls_cli_opt_strs+1135)
-#define HEARTBEAT_name      (gnutls_cli_opt_strs+1145)
+#define HEARTBEAT_DESC      (gnutls_cli_opt_strs+1167)
+#define HEARTBEAT_NAME      (gnutls_cli_opt_strs+1194)
+#define HEARTBEAT_name      (gnutls_cli_opt_strs+1204)
 #define HEARTBEAT_FLAGS     (OPTST_DISABLED)
 
 /*
  *  rehandshake option description:
  */
-#define REHANDSHAKE_DESC      (gnutls_cli_opt_strs+1155)
-#define REHANDSHAKE_NAME      (gnutls_cli_opt_strs+1191)
-#define REHANDSHAKE_name      (gnutls_cli_opt_strs+1203)
+#define REHANDSHAKE_DESC      (gnutls_cli_opt_strs+1214)
+#define REHANDSHAKE_NAME      (gnutls_cli_opt_strs+1250)
+#define REHANDSHAKE_name      (gnutls_cli_opt_strs+1262)
 #define REHANDSHAKE_FLAGS     (OPTST_DISABLED)
 
 /*
  *  noticket option description:
  */
-#define NOTICKET_DESC      (gnutls_cli_opt_strs+1215)
-#define NOTICKET_NAME      (gnutls_cli_opt_strs+1244)
-#define NOTICKET_name      (gnutls_cli_opt_strs+1253)
+#define NOTICKET_DESC      (gnutls_cli_opt_strs+1274)
+#define NOTICKET_NAME      (gnutls_cli_opt_strs+1303)
+#define NOTICKET_name      (gnutls_cli_opt_strs+1312)
 #define NOTICKET_FLAGS     (OPTST_DISABLED)
 
 /*
  *  ocsp-status-request option description:
  */
-#define OCSP_STATUS_REQUEST_DESC      (gnutls_cli_opt_strs+1262)
-#define OCSP_STATUS_REQUEST_NAME      (gnutls_cli_opt_strs+1289)
-#define NOT_OCSP_STATUS_REQUEST_name  (gnutls_cli_opt_strs+1309)
+#define OCSP_STATUS_REQUEST_DESC      (gnutls_cli_opt_strs+1321)
+#define OCSP_STATUS_REQUEST_NAME      (gnutls_cli_opt_strs+1348)
+#define NOT_OCSP_STATUS_REQUEST_name  (gnutls_cli_opt_strs+1368)
 #define NOT_OCSP_STATUS_REQUEST_PFX   (gnutls_cli_opt_strs+1010)
 #define OCSP_STATUS_REQUEST_name      (NOT_OCSP_STATUS_REQUEST_name + 3)
 #define OCSP_STATUS_REQUEST_FLAGS     (OPTST_INITENABLED)
@@ -303,268 +316,268 @@ static char const gnutls_cli_opt_strs[3608] =
 /*
  *  starttls option description:
  */
-#define STARTTLS_DESC      (gnutls_cli_opt_strs+1332)
-#define STARTTLS_NAME      (gnutls_cli_opt_strs+1382)
-#define STARTTLS_name      (gnutls_cli_opt_strs+1391)
+#define STARTTLS_DESC      (gnutls_cli_opt_strs+1391)
+#define STARTTLS_NAME      (gnutls_cli_opt_strs+1441)
+#define STARTTLS_name      (gnutls_cli_opt_strs+1450)
 #define STARTTLS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  udp option description:
  */
-#define UDP_DESC      (gnutls_cli_opt_strs+1400)
-#define UDP_NAME      (gnutls_cli_opt_strs+1433)
-#define UDP_name      (gnutls_cli_opt_strs+1437)
+#define UDP_DESC      (gnutls_cli_opt_strs+1459)
+#define UDP_NAME      (gnutls_cli_opt_strs+1492)
+#define UDP_name      (gnutls_cli_opt_strs+1496)
 #define UDP_FLAGS     (OPTST_DISABLED)
 
 /*
  *  mtu option description:
  */
-#define MTU_DESC      (gnutls_cli_opt_strs+1441)
-#define MTU_NAME      (gnutls_cli_opt_strs+1466)
-#define MTU_name      (gnutls_cli_opt_strs+1470)
+#define MTU_DESC      (gnutls_cli_opt_strs+1500)
+#define MTU_NAME      (gnutls_cli_opt_strs+1525)
+#define MTU_name      (gnutls_cli_opt_strs+1529)
 #define MTU_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
  *  crlf option description:
  */
-#define CRLF_DESC      (gnutls_cli_opt_strs+1474)
-#define CRLF_NAME      (gnutls_cli_opt_strs+1499)
-#define CRLF_name      (gnutls_cli_opt_strs+1504)
+#define CRLF_DESC      (gnutls_cli_opt_strs+1533)
+#define CRLF_NAME      (gnutls_cli_opt_strs+1558)
+#define CRLF_name      (gnutls_cli_opt_strs+1563)
 #define CRLF_FLAGS     (OPTST_DISABLED)
 
 /*
  *  x509fmtder option description:
  */
-#define X509FMTDER_DESC      (gnutls_cli_opt_strs+1509)
-#define X509FMTDER_NAME      (gnutls_cli_opt_strs+1554)
-#define X509FMTDER_name      (gnutls_cli_opt_strs+1565)
+#define X509FMTDER_DESC      (gnutls_cli_opt_strs+1568)
+#define X509FMTDER_NAME      (gnutls_cli_opt_strs+1613)
+#define X509FMTDER_name      (gnutls_cli_opt_strs+1624)
 #define X509FMTDER_FLAGS     (OPTST_DISABLED)
 
 /*
  *  fingerprint option description:
  */
-#define FINGERPRINT_DESC      (gnutls_cli_opt_strs+1576)
-#define FINGERPRINT_NAME      (gnutls_cli_opt_strs+1625)
-#define FINGERPRINT_name      (gnutls_cli_opt_strs+1637)
+#define FINGERPRINT_DESC      (gnutls_cli_opt_strs+1635)
+#define FINGERPRINT_NAME      (gnutls_cli_opt_strs+1684)
+#define FINGERPRINT_name      (gnutls_cli_opt_strs+1696)
 #define FINGERPRINT_FLAGS     (OPTST_DISABLED)
 
 /*
  *  disable-extensions option description:
  */
-#define DISABLE_EXTENSIONS_DESC      (gnutls_cli_opt_strs+1649)
-#define DISABLE_EXTENSIONS_NAME      (gnutls_cli_opt_strs+1680)
-#define DISABLE_EXTENSIONS_name      (gnutls_cli_opt_strs+1699)
+#define DISABLE_EXTENSIONS_DESC      (gnutls_cli_opt_strs+1708)
+#define DISABLE_EXTENSIONS_NAME      (gnutls_cli_opt_strs+1739)
+#define DISABLE_EXTENSIONS_name      (gnutls_cli_opt_strs+1758)
 #define DISABLE_EXTENSIONS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  print-cert option description:
  */
-#define PRINT_CERT_DESC      (gnutls_cli_opt_strs+1718)
-#define PRINT_CERT_NAME      (gnutls_cli_opt_strs+1757)
-#define PRINT_CERT_name      (gnutls_cli_opt_strs+1768)
+#define PRINT_CERT_DESC      (gnutls_cli_opt_strs+1777)
+#define PRINT_CERT_NAME      (gnutls_cli_opt_strs+1816)
+#define PRINT_CERT_name      (gnutls_cli_opt_strs+1827)
 #define PRINT_CERT_FLAGS     (OPTST_DISABLED)
 
 /*
  *  recordsize option description:
  */
-#define RECORDSIZE_DESC      (gnutls_cli_opt_strs+1779)
-#define RECORDSIZE_NAME      (gnutls_cli_opt_strs+1816)
-#define RECORDSIZE_name      (gnutls_cli_opt_strs+1827)
+#define RECORDSIZE_DESC      (gnutls_cli_opt_strs+1838)
+#define RECORDSIZE_NAME      (gnutls_cli_opt_strs+1875)
+#define RECORDSIZE_name      (gnutls_cli_opt_strs+1886)
 #define RECORDSIZE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
  *  dh-bits option description:
  */
-#define DH_BITS_DESC      (gnutls_cli_opt_strs+1838)
-#define DH_BITS_NAME      (gnutls_cli_opt_strs+1880)
-#define DH_BITS_name      (gnutls_cli_opt_strs+1888)
+#define DH_BITS_DESC      (gnutls_cli_opt_strs+1897)
+#define DH_BITS_NAME      (gnutls_cli_opt_strs+1939)
+#define DH_BITS_name      (gnutls_cli_opt_strs+1947)
 #define DH_BITS_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
  *  priority option description:
  */
-#define PRIORITY_DESC      (gnutls_cli_opt_strs+1896)
-#define PRIORITY_NAME      (gnutls_cli_opt_strs+1914)
-#define PRIORITY_name      (gnutls_cli_opt_strs+1923)
+#define PRIORITY_DESC      (gnutls_cli_opt_strs+1955)
+#define PRIORITY_NAME      (gnutls_cli_opt_strs+1973)
+#define PRIORITY_name      (gnutls_cli_opt_strs+1982)
 #define PRIORITY_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509cafile option description:
  */
-#define X509CAFILE_DESC      (gnutls_cli_opt_strs+1932)
-#define X509CAFILE_NAME      (gnutls_cli_opt_strs+1972)
-#define X509CAFILE_name      (gnutls_cli_opt_strs+1983)
+#define X509CAFILE_DESC      (gnutls_cli_opt_strs+1991)
+#define X509CAFILE_NAME      (gnutls_cli_opt_strs+2031)
+#define X509CAFILE_name      (gnutls_cli_opt_strs+2042)
 #define X509CAFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509crlfile option description:
  */
-#define X509CRLFILE_DESC      (gnutls_cli_opt_strs+1994)
-#define X509CRLFILE_NAME      (gnutls_cli_opt_strs+2010)
-#define X509CRLFILE_name      (gnutls_cli_opt_strs+2022)
+#define X509CRLFILE_DESC      (gnutls_cli_opt_strs+2053)
+#define X509CRLFILE_NAME      (gnutls_cli_opt_strs+2069)
+#define X509CRLFILE_name      (gnutls_cli_opt_strs+2081)
 #define X509CRLFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpkeyfile option description:
  */
-#define PGPKEYFILE_DESC      (gnutls_cli_opt_strs+2034)
-#define PGPKEYFILE_NAME      (gnutls_cli_opt_strs+2054)
-#define PGPKEYFILE_name      (gnutls_cli_opt_strs+2065)
+#define PGPKEYFILE_DESC      (gnutls_cli_opt_strs+2093)
+#define PGPKEYFILE_NAME      (gnutls_cli_opt_strs+2113)
+#define PGPKEYFILE_name      (gnutls_cli_opt_strs+2124)
 #define PGPKEYFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpkeyring option description:
  */
-#define PGPKEYRING_DESC      (gnutls_cli_opt_strs+2076)
-#define PGPKEYRING_NAME      (gnutls_cli_opt_strs+2101)
-#define PGPKEYRING_name      (gnutls_cli_opt_strs+2112)
+#define PGPKEYRING_DESC      (gnutls_cli_opt_strs+2135)
+#define PGPKEYRING_NAME      (gnutls_cli_opt_strs+2160)
+#define PGPKEYRING_name      (gnutls_cli_opt_strs+2171)
 #define PGPKEYRING_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpcertfile option description:
  */
-#define PGPCERTFILE_DESC      (gnutls_cli_opt_strs+2123)
-#define PGPCERTFILE_NAME      (gnutls_cli_opt_strs+2164)
-#define PGPCERTFILE_name      (gnutls_cli_opt_strs+2176)
+#define PGPCERTFILE_DESC      (gnutls_cli_opt_strs+2182)
+#define PGPCERTFILE_NAME      (gnutls_cli_opt_strs+2223)
+#define PGPCERTFILE_name      (gnutls_cli_opt_strs+2235)
 #define PGPCERTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  x509keyfile option description:
  */
-#define X509KEYFILE_DESC      (gnutls_cli_opt_strs+2188)
-#define X509KEYFILE_NAME      (gnutls_cli_opt_strs+2226)
-#define X509KEYFILE_name      (gnutls_cli_opt_strs+2238)
+#define X509KEYFILE_DESC      (gnutls_cli_opt_strs+2247)
+#define X509KEYFILE_NAME      (gnutls_cli_opt_strs+2285)
+#define X509KEYFILE_name      (gnutls_cli_opt_strs+2297)
 #define X509KEYFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509certfile option description:
  */
-#define X509CERTFILE_DESC      (gnutls_cli_opt_strs+2250)
-#define X509CERTFILE_NAME      (gnutls_cli_opt_strs+2296)
-#define X509CERTFILE_name      (gnutls_cli_opt_strs+2309)
+#define X509CERTFILE_DESC      (gnutls_cli_opt_strs+2309)
+#define X509CERTFILE_NAME      (gnutls_cli_opt_strs+2355)
+#define X509CERTFILE_name      (gnutls_cli_opt_strs+2368)
 #define X509CERTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  pgpsubkey option description:
  */
-#define PGPSUBKEY_DESC      (gnutls_cli_opt_strs+2322)
-#define PGPSUBKEY_NAME      (gnutls_cli_opt_strs+2354)
-#define PGPSUBKEY_name      (gnutls_cli_opt_strs+2364)
+#define PGPSUBKEY_DESC      (gnutls_cli_opt_strs+2381)
+#define PGPSUBKEY_NAME      (gnutls_cli_opt_strs+2413)
+#define PGPSUBKEY_name      (gnutls_cli_opt_strs+2423)
 #define PGPSUBKEY_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  srpusername option description:
  */
-#define SRPUSERNAME_DESC      (gnutls_cli_opt_strs+2374)
-#define SRPUSERNAME_NAME      (gnutls_cli_opt_strs+2394)
-#define SRPUSERNAME_name      (gnutls_cli_opt_strs+2406)
+#define SRPUSERNAME_DESC      (gnutls_cli_opt_strs+2433)
+#define SRPUSERNAME_NAME      (gnutls_cli_opt_strs+2453)
+#define SRPUSERNAME_name      (gnutls_cli_opt_strs+2465)
 #define SRPUSERNAME_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  srppasswd option description:
  */
-#define SRPPASSWD_DESC      (gnutls_cli_opt_strs+2418)
-#define SRPPASSWD_NAME      (gnutls_cli_opt_strs+2438)
-#define SRPPASSWD_name      (gnutls_cli_opt_strs+2448)
+#define SRPPASSWD_DESC      (gnutls_cli_opt_strs+2477)
+#define SRPPASSWD_NAME      (gnutls_cli_opt_strs+2497)
+#define SRPPASSWD_name      (gnutls_cli_opt_strs+2507)
 #define SRPPASSWD_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  pskusername option description:
  */
-#define PSKUSERNAME_DESC      (gnutls_cli_opt_strs+2458)
-#define PSKUSERNAME_NAME      (gnutls_cli_opt_strs+2478)
-#define PSKUSERNAME_name      (gnutls_cli_opt_strs+2490)
+#define PSKUSERNAME_DESC      (gnutls_cli_opt_strs+2517)
+#define PSKUSERNAME_NAME      (gnutls_cli_opt_strs+2537)
+#define PSKUSERNAME_name      (gnutls_cli_opt_strs+2549)
 #define PSKUSERNAME_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  pskkey option description:
  */
-#define PSKKEY_DESC      (gnutls_cli_opt_strs+2502)
-#define PSKKEY_NAME      (gnutls_cli_opt_strs+2526)
-#define PSKKEY_name      (gnutls_cli_opt_strs+2533)
+#define PSKKEY_DESC      (gnutls_cli_opt_strs+2561)
+#define PSKKEY_NAME      (gnutls_cli_opt_strs+2585)
+#define PSKKEY_name      (gnutls_cli_opt_strs+2592)
 #define PSKKEY_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  port option description:
  */
-#define PORT_DESC      (gnutls_cli_opt_strs+2540)
-#define PORT_NAME      (gnutls_cli_opt_strs+2574)
-#define PORT_name      (gnutls_cli_opt_strs+2579)
+#define PORT_DESC      (gnutls_cli_opt_strs+2599)
+#define PORT_NAME      (gnutls_cli_opt_strs+2633)
+#define PORT_name      (gnutls_cli_opt_strs+2638)
 #define PORT_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  insecure option description:
  */
-#define INSECURE_DESC      (gnutls_cli_opt_strs+2584)
-#define INSECURE_NAME      (gnutls_cli_opt_strs+2645)
-#define INSECURE_name      (gnutls_cli_opt_strs+2654)
+#define INSECURE_DESC      (gnutls_cli_opt_strs+2643)
+#define INSECURE_NAME      (gnutls_cli_opt_strs+2704)
+#define INSECURE_name      (gnutls_cli_opt_strs+2713)
 #define INSECURE_FLAGS     (OPTST_DISABLED)
 
 /*
  *  benchmark-ciphers option description:
  */
-#define BENCHMARK_CIPHERS_DESC      (gnutls_cli_opt_strs+2663)
-#define BENCHMARK_CIPHERS_NAME      (gnutls_cli_opt_strs+2692)
-#define BENCHMARK_CIPHERS_name      (gnutls_cli_opt_strs+2710)
+#define BENCHMARK_CIPHERS_DESC      (gnutls_cli_opt_strs+2722)
+#define BENCHMARK_CIPHERS_NAME      (gnutls_cli_opt_strs+2751)
+#define BENCHMARK_CIPHERS_name      (gnutls_cli_opt_strs+2769)
 #define BENCHMARK_CIPHERS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  benchmark-soft-ciphers option description:
  */
-#define BENCHMARK_SOFT_CIPHERS_DESC      (gnutls_cli_opt_strs+2728)
-#define BENCHMARK_SOFT_CIPHERS_NAME      (gnutls_cli_opt_strs+2787)
-#define BENCHMARK_SOFT_CIPHERS_name      (gnutls_cli_opt_strs+2810)
+#define BENCHMARK_SOFT_CIPHERS_DESC      (gnutls_cli_opt_strs+2787)
+#define BENCHMARK_SOFT_CIPHERS_NAME      (gnutls_cli_opt_strs+2846)
+#define BENCHMARK_SOFT_CIPHERS_name      (gnutls_cli_opt_strs+2869)
 #define BENCHMARK_SOFT_CIPHERS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  benchmark-tls-kx option description:
  */
-#define BENCHMARK_TLS_KX_DESC      (gnutls_cli_opt_strs+2833)
-#define BENCHMARK_TLS_KX_NAME      (gnutls_cli_opt_strs+2868)
-#define BENCHMARK_TLS_KX_name      (gnutls_cli_opt_strs+2885)
+#define BENCHMARK_TLS_KX_DESC      (gnutls_cli_opt_strs+2892)
+#define BENCHMARK_TLS_KX_NAME      (gnutls_cli_opt_strs+2927)
+#define BENCHMARK_TLS_KX_name      (gnutls_cli_opt_strs+2944)
 #define BENCHMARK_TLS_KX_FLAGS     (OPTST_DISABLED)
 
 /*
  *  benchmark-tls-ciphers option description:
  */
-#define BENCHMARK_TLS_CIPHERS_DESC      (gnutls_cli_opt_strs+2902)
-#define BENCHMARK_TLS_CIPHERS_NAME      (gnutls_cli_opt_strs+2924)
-#define BENCHMARK_TLS_CIPHERS_name      (gnutls_cli_opt_strs+2946)
+#define BENCHMARK_TLS_CIPHERS_DESC      (gnutls_cli_opt_strs+2961)
+#define BENCHMARK_TLS_CIPHERS_NAME      (gnutls_cli_opt_strs+2983)
+#define BENCHMARK_TLS_CIPHERS_name      (gnutls_cli_opt_strs+3005)
 #define BENCHMARK_TLS_CIPHERS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  list option description:
  */
-#define LIST_DESC      (gnutls_cli_opt_strs+2968)
-#define LIST_NAME      (gnutls_cli_opt_strs+3019)
-#define LIST_name      (gnutls_cli_opt_strs+3024)
+#define LIST_DESC      (gnutls_cli_opt_strs+3027)
+#define LIST_NAME      (gnutls_cli_opt_strs+3078)
+#define LIST_name      (gnutls_cli_opt_strs+3083)
 #define LIST_FLAGS     (OPTST_DISABLED)
 
 /*
  *  Help/More_Help/Version option descriptions:
  */
-#define HELP_DESC       (gnutls_cli_opt_strs+3029)
-#define HELP_name       (gnutls_cli_opt_strs+3073)
+#define HELP_DESC       (gnutls_cli_opt_strs+3088)
+#define HELP_name       (gnutls_cli_opt_strs+3132)
 #ifdef HAVE_WORKING_FORK
-#define MORE_HELP_DESC  (gnutls_cli_opt_strs+3078)
-#define MORE_HELP_name  (gnutls_cli_opt_strs+3123)
+#define MORE_HELP_DESC  (gnutls_cli_opt_strs+3137)
+#define MORE_HELP_name  (gnutls_cli_opt_strs+3182)
 #define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT)
 #else
 #define MORE_HELP_DESC  NULL
@@ -577,8 +590,8 @@ static char const gnutls_cli_opt_strs[3608] =
 #  define VER_FLAGS     (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
                          OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT)
 #endif
-#define VER_DESC        (gnutls_cli_opt_strs+3133)
-#define VER_name        (gnutls_cli_opt_strs+3169)
+#define VER_DESC        (gnutls_cli_opt_strs+3192)
+#define VER_name        (gnutls_cli_opt_strs+3228)
 /*
  *  Declare option callback procedures
  */
@@ -635,8 +648,20 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ TOFU_DESC, TOFU_NAME, TOFU_name,
      /* disablement strs */ NOT_TOFU_name, NOT_TOFU_PFX },
 
-  {  /* entry idx, value */ 3, VALUE_OPT_OCSP,
-     /* equiv idx, value */ 3, VALUE_OPT_OCSP,
+  {  /* entry idx, value */ 3, VALUE_OPT_DANE,
+     /* equiv idx, value */ 3, VALUE_OPT_DANE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ DANE_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --dane */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ DANE_DESC, DANE_NAME, DANE_name,
+     /* disablement strs */ NOT_DANE_name, NOT_DANE_PFX },
+
+  {  /* entry idx, value */ 4, VALUE_OPT_OCSP,
+     /* equiv idx, value */ 4, VALUE_OPT_OCSP,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ OCSP_FLAGS, 0,
@@ -647,8 +672,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ OCSP_DESC, OCSP_NAME, OCSP_name,
      /* disablement strs */ NOT_OCSP_name, NOT_OCSP_PFX },
 
-  {  /* entry idx, value */ 4, VALUE_OPT_RESUME,
-     /* equiv idx, value */ 4, VALUE_OPT_RESUME,
+  {  /* entry idx, value */ 5, VALUE_OPT_RESUME,
+     /* equiv idx, value */ 5, VALUE_OPT_RESUME,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ RESUME_FLAGS, 0,
@@ -659,8 +684,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ RESUME_DESC, RESUME_NAME, RESUME_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 5, VALUE_OPT_HEARTBEAT,
-     /* equiv idx, value */ 5, VALUE_OPT_HEARTBEAT,
+  {  /* entry idx, value */ 6, VALUE_OPT_HEARTBEAT,
+     /* equiv idx, value */ 6, VALUE_OPT_HEARTBEAT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ HEARTBEAT_FLAGS, 0,
@@ -671,8 +696,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ HEARTBEAT_DESC, HEARTBEAT_NAME, HEARTBEAT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 6, VALUE_OPT_REHANDSHAKE,
-     /* equiv idx, value */ 6, VALUE_OPT_REHANDSHAKE,
+  {  /* entry idx, value */ 7, VALUE_OPT_REHANDSHAKE,
+     /* equiv idx, value */ 7, VALUE_OPT_REHANDSHAKE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ REHANDSHAKE_FLAGS, 0,
@@ -683,8 +708,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ REHANDSHAKE_DESC, REHANDSHAKE_NAME, REHANDSHAKE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 7, VALUE_OPT_NOTICKET,
-     /* equiv idx, value */ 7, VALUE_OPT_NOTICKET,
+  {  /* entry idx, value */ 8, VALUE_OPT_NOTICKET,
+     /* equiv idx, value */ 8, VALUE_OPT_NOTICKET,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ NOTICKET_FLAGS, 0,
@@ -695,8 +720,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ NOTICKET_DESC, NOTICKET_NAME, NOTICKET_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 8, VALUE_OPT_OCSP_STATUS_REQUEST,
-     /* equiv idx, value */ 8, VALUE_OPT_OCSP_STATUS_REQUEST,
+  {  /* entry idx, value */ 9, VALUE_OPT_OCSP_STATUS_REQUEST,
+     /* equiv idx, value */ 9, VALUE_OPT_OCSP_STATUS_REQUEST,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ OCSP_STATUS_REQUEST_FLAGS, 0,
@@ -707,8 +732,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ OCSP_STATUS_REQUEST_DESC, OCSP_STATUS_REQUEST_NAME, OCSP_STATUS_REQUEST_name,
      /* disablement strs */ NOT_OCSP_STATUS_REQUEST_name, NOT_OCSP_STATUS_REQUEST_PFX },
 
-  {  /* entry idx, value */ 9, VALUE_OPT_STARTTLS,
-     /* equiv idx, value */ 9, VALUE_OPT_STARTTLS,
+  {  /* entry idx, value */ 10, VALUE_OPT_STARTTLS,
+     /* equiv idx, value */ 10, VALUE_OPT_STARTTLS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ STARTTLS_FLAGS, 0,
@@ -719,8 +744,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ STARTTLS_DESC, STARTTLS_NAME, STARTTLS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 10, VALUE_OPT_UDP,
-     /* equiv idx, value */ 10, VALUE_OPT_UDP,
+  {  /* entry idx, value */ 11, VALUE_OPT_UDP,
+     /* equiv idx, value */ 11, VALUE_OPT_UDP,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ UDP_FLAGS, 0,
@@ -731,8 +756,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ UDP_DESC, UDP_NAME, UDP_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 11, VALUE_OPT_MTU,
-     /* equiv idx, value */ 11, VALUE_OPT_MTU,
+  {  /* entry idx, value */ 12, VALUE_OPT_MTU,
+     /* equiv idx, value */ 12, VALUE_OPT_MTU,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ MTU_FLAGS, 0,
@@ -743,8 +768,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ MTU_DESC, MTU_NAME, MTU_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 12, VALUE_OPT_CRLF,
-     /* equiv idx, value */ 12, VALUE_OPT_CRLF,
+  {  /* entry idx, value */ 13, VALUE_OPT_CRLF,
+     /* equiv idx, value */ 13, VALUE_OPT_CRLF,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ CRLF_FLAGS, 0,
@@ -755,8 +780,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ CRLF_DESC, CRLF_NAME, CRLF_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 13, VALUE_OPT_X509FMTDER,
-     /* equiv idx, value */ 13, VALUE_OPT_X509FMTDER,
+  {  /* entry idx, value */ 14, VALUE_OPT_X509FMTDER,
+     /* equiv idx, value */ 14, VALUE_OPT_X509FMTDER,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509FMTDER_FLAGS, 0,
@@ -767,8 +792,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509FMTDER_DESC, X509FMTDER_NAME, X509FMTDER_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 14, VALUE_OPT_FINGERPRINT,
-     /* equiv idx, value */ 14, VALUE_OPT_FINGERPRINT,
+  {  /* entry idx, value */ 15, VALUE_OPT_FINGERPRINT,
+     /* equiv idx, value */ 15, VALUE_OPT_FINGERPRINT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ FINGERPRINT_FLAGS, 0,
@@ -779,8 +804,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ FINGERPRINT_DESC, FINGERPRINT_NAME, FINGERPRINT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 15, VALUE_OPT_DISABLE_EXTENSIONS,
-     /* equiv idx, value */ 15, VALUE_OPT_DISABLE_EXTENSIONS,
+  {  /* entry idx, value */ 16, VALUE_OPT_DISABLE_EXTENSIONS,
+     /* equiv idx, value */ 16, VALUE_OPT_DISABLE_EXTENSIONS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ DISABLE_EXTENSIONS_FLAGS, 0,
@@ -791,8 +816,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ DISABLE_EXTENSIONS_DESC, DISABLE_EXTENSIONS_NAME, DISABLE_EXTENSIONS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 16, VALUE_OPT_PRINT_CERT,
-     /* equiv idx, value */ 16, VALUE_OPT_PRINT_CERT,
+  {  /* entry idx, value */ 17, VALUE_OPT_PRINT_CERT,
+     /* equiv idx, value */ 17, VALUE_OPT_PRINT_CERT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PRINT_CERT_FLAGS, 0,
@@ -803,8 +828,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PRINT_CERT_DESC, PRINT_CERT_NAME, PRINT_CERT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 17, VALUE_OPT_RECORDSIZE,
-     /* equiv idx, value */ 17, VALUE_OPT_RECORDSIZE,
+  {  /* entry idx, value */ 18, VALUE_OPT_RECORDSIZE,
+     /* equiv idx, value */ 18, VALUE_OPT_RECORDSIZE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ RECORDSIZE_FLAGS, 0,
@@ -815,8 +840,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ RECORDSIZE_DESC, RECORDSIZE_NAME, RECORDSIZE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 18, VALUE_OPT_DH_BITS,
-     /* equiv idx, value */ 18, VALUE_OPT_DH_BITS,
+  {  /* entry idx, value */ 19, VALUE_OPT_DH_BITS,
+     /* equiv idx, value */ 19, VALUE_OPT_DH_BITS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ DH_BITS_FLAGS, 0,
@@ -827,8 +852,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ DH_BITS_DESC, DH_BITS_NAME, DH_BITS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 19, VALUE_OPT_PRIORITY,
-     /* equiv idx, value */ 19, VALUE_OPT_PRIORITY,
+  {  /* entry idx, value */ 20, VALUE_OPT_PRIORITY,
+     /* equiv idx, value */ 20, VALUE_OPT_PRIORITY,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PRIORITY_FLAGS, 0,
@@ -839,8 +864,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PRIORITY_DESC, PRIORITY_NAME, PRIORITY_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 20, VALUE_OPT_X509CAFILE,
-     /* equiv idx, value */ 20, VALUE_OPT_X509CAFILE,
+  {  /* entry idx, value */ 21, VALUE_OPT_X509CAFILE,
+     /* equiv idx, value */ 21, VALUE_OPT_X509CAFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CAFILE_FLAGS, 0,
@@ -851,8 +876,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CAFILE_DESC, X509CAFILE_NAME, X509CAFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 21, VALUE_OPT_X509CRLFILE,
-     /* equiv idx, value */ 21, VALUE_OPT_X509CRLFILE,
+  {  /* entry idx, value */ 22, VALUE_OPT_X509CRLFILE,
+     /* equiv idx, value */ 22, VALUE_OPT_X509CRLFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CRLFILE_FLAGS, 0,
@@ -863,8 +888,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CRLFILE_DESC, X509CRLFILE_NAME, X509CRLFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 22, VALUE_OPT_PGPKEYFILE,
-     /* equiv idx, value */ 22, VALUE_OPT_PGPKEYFILE,
+  {  /* entry idx, value */ 23, VALUE_OPT_PGPKEYFILE,
+     /* equiv idx, value */ 23, VALUE_OPT_PGPKEYFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPKEYFILE_FLAGS, 0,
@@ -875,8 +900,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPKEYFILE_DESC, PGPKEYFILE_NAME, PGPKEYFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 23, VALUE_OPT_PGPKEYRING,
-     /* equiv idx, value */ 23, VALUE_OPT_PGPKEYRING,
+  {  /* entry idx, value */ 24, VALUE_OPT_PGPKEYRING,
+     /* equiv idx, value */ 24, VALUE_OPT_PGPKEYRING,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPKEYRING_FLAGS, 0,
@@ -887,8 +912,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPKEYRING_DESC, PGPKEYRING_NAME, PGPKEYRING_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 24, VALUE_OPT_PGPCERTFILE,
-     /* equiv idx, value */ 24, VALUE_OPT_PGPCERTFILE,
+  {  /* entry idx, value */ 25, VALUE_OPT_PGPCERTFILE,
+     /* equiv idx, value */ 25, VALUE_OPT_PGPCERTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPCERTFILE_FLAGS, 0,
@@ -899,8 +924,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPCERTFILE_DESC, PGPCERTFILE_NAME, PGPCERTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 25, VALUE_OPT_X509KEYFILE,
-     /* equiv idx, value */ 25, VALUE_OPT_X509KEYFILE,
+  {  /* entry idx, value */ 26, VALUE_OPT_X509KEYFILE,
+     /* equiv idx, value */ 26, VALUE_OPT_X509KEYFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509KEYFILE_FLAGS, 0,
@@ -911,8 +936,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509KEYFILE_DESC, X509KEYFILE_NAME, X509KEYFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 26, VALUE_OPT_X509CERTFILE,
-     /* equiv idx, value */ 26, VALUE_OPT_X509CERTFILE,
+  {  /* entry idx, value */ 27, VALUE_OPT_X509CERTFILE,
+     /* equiv idx, value */ 27, VALUE_OPT_X509CERTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CERTFILE_FLAGS, 0,
@@ -923,8 +948,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CERTFILE_DESC, X509CERTFILE_NAME, X509CERTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 27, VALUE_OPT_PGPSUBKEY,
-     /* equiv idx, value */ 27, VALUE_OPT_PGPSUBKEY,
+  {  /* entry idx, value */ 28, VALUE_OPT_PGPSUBKEY,
+     /* equiv idx, value */ 28, VALUE_OPT_PGPSUBKEY,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPSUBKEY_FLAGS, 0,
@@ -935,8 +960,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPSUBKEY_DESC, PGPSUBKEY_NAME, PGPSUBKEY_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 28, VALUE_OPT_SRPUSERNAME,
-     /* equiv idx, value */ 28, VALUE_OPT_SRPUSERNAME,
+  {  /* entry idx, value */ 29, VALUE_OPT_SRPUSERNAME,
+     /* equiv idx, value */ 29, VALUE_OPT_SRPUSERNAME,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ SRPUSERNAME_FLAGS, 0,
@@ -947,8 +972,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ SRPUSERNAME_DESC, SRPUSERNAME_NAME, SRPUSERNAME_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 29, VALUE_OPT_SRPPASSWD,
-     /* equiv idx, value */ 29, VALUE_OPT_SRPPASSWD,
+  {  /* entry idx, value */ 30, VALUE_OPT_SRPPASSWD,
+     /* equiv idx, value */ 30, VALUE_OPT_SRPPASSWD,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ SRPPASSWD_FLAGS, 0,
@@ -959,8 +984,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ SRPPASSWD_DESC, SRPPASSWD_NAME, SRPPASSWD_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 30, VALUE_OPT_PSKUSERNAME,
-     /* equiv idx, value */ 30, VALUE_OPT_PSKUSERNAME,
+  {  /* entry idx, value */ 31, VALUE_OPT_PSKUSERNAME,
+     /* equiv idx, value */ 31, VALUE_OPT_PSKUSERNAME,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PSKUSERNAME_FLAGS, 0,
@@ -971,8 +996,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PSKUSERNAME_DESC, PSKUSERNAME_NAME, PSKUSERNAME_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 31, VALUE_OPT_PSKKEY,
-     /* equiv idx, value */ 31, VALUE_OPT_PSKKEY,
+  {  /* entry idx, value */ 32, VALUE_OPT_PSKKEY,
+     /* equiv idx, value */ 32, VALUE_OPT_PSKKEY,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PSKKEY_FLAGS, 0,
@@ -983,8 +1008,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PSKKEY_DESC, PSKKEY_NAME, PSKKEY_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 32, VALUE_OPT_PORT,
-     /* equiv idx, value */ 32, VALUE_OPT_PORT,
+  {  /* entry idx, value */ 33, VALUE_OPT_PORT,
+     /* equiv idx, value */ 33, VALUE_OPT_PORT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PORT_FLAGS, 0,
@@ -995,8 +1020,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PORT_DESC, PORT_NAME, PORT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 33, VALUE_OPT_INSECURE,
-     /* equiv idx, value */ 33, VALUE_OPT_INSECURE,
+  {  /* entry idx, value */ 34, VALUE_OPT_INSECURE,
+     /* equiv idx, value */ 34, VALUE_OPT_INSECURE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ INSECURE_FLAGS, 0,
@@ -1007,8 +1032,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ INSECURE_DESC, INSECURE_NAME, INSECURE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 34, VALUE_OPT_BENCHMARK_CIPHERS,
-     /* equiv idx, value */ 34, VALUE_OPT_BENCHMARK_CIPHERS,
+  {  /* entry idx, value */ 35, VALUE_OPT_BENCHMARK_CIPHERS,
+     /* equiv idx, value */ 35, VALUE_OPT_BENCHMARK_CIPHERS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BENCHMARK_CIPHERS_FLAGS, 0,
@@ -1019,8 +1044,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ BENCHMARK_CIPHERS_DESC, BENCHMARK_CIPHERS_NAME, BENCHMARK_CIPHERS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 35, VALUE_OPT_BENCHMARK_SOFT_CIPHERS,
-     /* equiv idx, value */ 35, VALUE_OPT_BENCHMARK_SOFT_CIPHERS,
+  {  /* entry idx, value */ 36, VALUE_OPT_BENCHMARK_SOFT_CIPHERS,
+     /* equiv idx, value */ 36, VALUE_OPT_BENCHMARK_SOFT_CIPHERS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BENCHMARK_SOFT_CIPHERS_FLAGS, 0,
@@ -1031,8 +1056,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ BENCHMARK_SOFT_CIPHERS_DESC, BENCHMARK_SOFT_CIPHERS_NAME, BENCHMARK_SOFT_CIPHERS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 36, VALUE_OPT_BENCHMARK_TLS_KX,
-     /* equiv idx, value */ 36, VALUE_OPT_BENCHMARK_TLS_KX,
+  {  /* entry idx, value */ 37, VALUE_OPT_BENCHMARK_TLS_KX,
+     /* equiv idx, value */ 37, VALUE_OPT_BENCHMARK_TLS_KX,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BENCHMARK_TLS_KX_FLAGS, 0,
@@ -1043,8 +1068,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ BENCHMARK_TLS_KX_DESC, BENCHMARK_TLS_KX_NAME, BENCHMARK_TLS_KX_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 37, VALUE_OPT_BENCHMARK_TLS_CIPHERS,
-     /* equiv idx, value */ 37, VALUE_OPT_BENCHMARK_TLS_CIPHERS,
+  {  /* entry idx, value */ 38, VALUE_OPT_BENCHMARK_TLS_CIPHERS,
+     /* equiv idx, value */ 38, VALUE_OPT_BENCHMARK_TLS_CIPHERS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BENCHMARK_TLS_CIPHERS_FLAGS, 0,
@@ -1055,8 +1080,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ BENCHMARK_TLS_CIPHERS_DESC, BENCHMARK_TLS_CIPHERS_NAME, BENCHMARK_TLS_CIPHERS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 38, VALUE_OPT_LIST,
-     /* equiv idx, value */ 38, VALUE_OPT_LIST,
+  {  /* entry idx, value */ 39, VALUE_OPT_LIST,
+     /* equiv idx, value */ 39, VALUE_OPT_LIST,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ LIST_FLAGS, 0,
@@ -1111,14 +1136,14 @@ static tOptDesc optDesc[OPTION_CT] = {
  *
  *  Define the gnutls-cli Option Environment
  */
-#define zPROGNAME       (gnutls_cli_opt_strs+3177)
-#define zUsageTitle     (gnutls_cli_opt_strs+3188)
+#define zPROGNAME       (gnutls_cli_opt_strs+3236)
+#define zUsageTitle     (gnutls_cli_opt_strs+3247)
 #define zRcName         NULL
 #define apzHomeList     NULL
-#define zBugsAddr       (gnutls_cli_opt_strs+3301)
-#define zExplain        (gnutls_cli_opt_strs+3320)
-#define zDetail         (gnutls_cli_opt_strs+3323)
-#define zFullVersion    (gnutls_cli_opt_strs+3507)
+#define zBugsAddr       (gnutls_cli_opt_strs+3360)
+#define zExplain        (gnutls_cli_opt_strs+3379)
+#define zDetail         (gnutls_cli_opt_strs+3382)
+#define zFullVersion    (gnutls_cli_opt_strs+3566)
 /* extracted from optcode.tlib near line 350 */
 
 #if defined(ENABLE_NLS)
@@ -1132,7 +1157,7 @@ static tOptDesc optDesc[OPTION_CT] = {
 
 #define gnutls_cli_full_usage (NULL)
 
-#define gnutls_cli_short_usage (gnutls_cli_opt_strs+3528)
+#define gnutls_cli_short_usage (gnutls_cli_opt_strs+3587)
 
 #endif /* not defined __doxygen__ */
 
@@ -1410,7 +1435,7 @@ tOptions gnutls_cliOptions = {
       NO_EQUIVALENT, /* '-#' option index */
       NO_EQUIVALENT /* index of default opt */
     },
-    42 /* full option count */, 39 /* user option count */,
+    43 /* full option count */, 40 /* user option count */,
     gnutls_cli_full_usage, gnutls_cli_short_usage,
     NULL, NULL,
     PKGDATADIR, gnutls_cli_packager_info
index 6a4d7176db53d12dad4afde9935bbf7a7ca52693..954faeaf6eb68bc3f183aa393c6007cc0e16dce7 100644 (file)
@@ -20,6 +20,16 @@ flag = {
     doc       = "This option will, in addition to certificate authentication, perform authentication based on previously seen public keys, a model similar to SSH authentication.";
 };
 
+flag = {
+    name      = dane;
+    descrip   = "Enable DANE certificate verification (DNSSEC)";
+    disabled;
+    disable   = "no";
+    doc       = "This option will, in addition to certificate authentication using 
+the trusted CAs, verify the server certificates using on the DANE information
+available via DNSSEC.";
+};
+
 flag = {
     name      = ocsp;
     descrip   = "Enable OCSP certificate verification";
index 0085141d33609a73f0e7296428760797ee3afb73..adc0730296387f6b59e131e539208667bc63fc22 100644 (file)
@@ -2,7 +2,7 @@
  *  
  *  DO NOT EDIT THIS FILE   (cli-args.h)
  *  
- *  It has been AutoGen-ed  October  4, 2012 at 07:09:10 PM by AutoGen 5.16
+ *  It has been AutoGen-ed  October  6, 2012 at 03:20:01 AM by AutoGen 5.16
  *  From the definitions    cli-args.def
  *  and the template file   options
  *
@@ -70,48 +70,49 @@ typedef enum {
     INDEX_OPT_DEBUG                   =  0,
     INDEX_OPT_VERBOSE                 =  1,
     INDEX_OPT_TOFU                    =  2,
-    INDEX_OPT_OCSP                    =  3,
-    INDEX_OPT_RESUME                  =  4,
-    INDEX_OPT_HEARTBEAT               =  5,
-    INDEX_OPT_REHANDSHAKE             =  6,
-    INDEX_OPT_NOTICKET                =  7,
-    INDEX_OPT_OCSP_STATUS_REQUEST     =  8,
-    INDEX_OPT_STARTTLS                =  9,
-    INDEX_OPT_UDP                     = 10,
-    INDEX_OPT_MTU                     = 11,
-    INDEX_OPT_CRLF                    = 12,
-    INDEX_OPT_X509FMTDER              = 13,
-    INDEX_OPT_FINGERPRINT             = 14,
-    INDEX_OPT_DISABLE_EXTENSIONS      = 15,
-    INDEX_OPT_PRINT_CERT              = 16,
-    INDEX_OPT_RECORDSIZE              = 17,
-    INDEX_OPT_DH_BITS                 = 18,
-    INDEX_OPT_PRIORITY                = 19,
-    INDEX_OPT_X509CAFILE              = 20,
-    INDEX_OPT_X509CRLFILE             = 21,
-    INDEX_OPT_PGPKEYFILE              = 22,
-    INDEX_OPT_PGPKEYRING              = 23,
-    INDEX_OPT_PGPCERTFILE             = 24,
-    INDEX_OPT_X509KEYFILE             = 25,
-    INDEX_OPT_X509CERTFILE            = 26,
-    INDEX_OPT_PGPSUBKEY               = 27,
-    INDEX_OPT_SRPUSERNAME             = 28,
-    INDEX_OPT_SRPPASSWD               = 29,
-    INDEX_OPT_PSKUSERNAME             = 30,
-    INDEX_OPT_PSKKEY                  = 31,
-    INDEX_OPT_PORT                    = 32,
-    INDEX_OPT_INSECURE                = 33,
-    INDEX_OPT_BENCHMARK_CIPHERS       = 34,
-    INDEX_OPT_BENCHMARK_SOFT_CIPHERS  = 35,
-    INDEX_OPT_BENCHMARK_TLS_KX        = 36,
-    INDEX_OPT_BENCHMARK_TLS_CIPHERS   = 37,
-    INDEX_OPT_LIST                    = 38,
-    INDEX_OPT_VERSION                 = 39,
-    INDEX_OPT_HELP                    = 40,
-    INDEX_OPT_MORE_HELP               = 41
+    INDEX_OPT_DANE                    =  3,
+    INDEX_OPT_OCSP                    =  4,
+    INDEX_OPT_RESUME                  =  5,
+    INDEX_OPT_HEARTBEAT               =  6,
+    INDEX_OPT_REHANDSHAKE             =  7,
+    INDEX_OPT_NOTICKET                =  8,
+    INDEX_OPT_OCSP_STATUS_REQUEST     =  9,
+    INDEX_OPT_STARTTLS                = 10,
+    INDEX_OPT_UDP                     = 11,
+    INDEX_OPT_MTU                     = 12,
+    INDEX_OPT_CRLF                    = 13,
+    INDEX_OPT_X509FMTDER              = 14,
+    INDEX_OPT_FINGERPRINT             = 15,
+    INDEX_OPT_DISABLE_EXTENSIONS      = 16,
+    INDEX_OPT_PRINT_CERT              = 17,
+    INDEX_OPT_RECORDSIZE              = 18,
+    INDEX_OPT_DH_BITS                 = 19,
+    INDEX_OPT_PRIORITY                = 20,
+    INDEX_OPT_X509CAFILE              = 21,
+    INDEX_OPT_X509CRLFILE             = 22,
+    INDEX_OPT_PGPKEYFILE              = 23,
+    INDEX_OPT_PGPKEYRING              = 24,
+    INDEX_OPT_PGPCERTFILE             = 25,
+    INDEX_OPT_X509KEYFILE             = 26,
+    INDEX_OPT_X509CERTFILE            = 27,
+    INDEX_OPT_PGPSUBKEY               = 28,
+    INDEX_OPT_SRPUSERNAME             = 29,
+    INDEX_OPT_SRPPASSWD               = 30,
+    INDEX_OPT_PSKUSERNAME             = 31,
+    INDEX_OPT_PSKKEY                  = 32,
+    INDEX_OPT_PORT                    = 33,
+    INDEX_OPT_INSECURE                = 34,
+    INDEX_OPT_BENCHMARK_CIPHERS       = 35,
+    INDEX_OPT_BENCHMARK_SOFT_CIPHERS  = 36,
+    INDEX_OPT_BENCHMARK_TLS_KX        = 37,
+    INDEX_OPT_BENCHMARK_TLS_CIPHERS   = 38,
+    INDEX_OPT_LIST                    = 39,
+    INDEX_OPT_VERSION                 = 40,
+    INDEX_OPT_HELP                    = 41,
+    INDEX_OPT_MORE_HELP               = 42
 } teOptIndex;
 
-#define OPTION_CT    42
+#define OPTION_CT    43
 #define GNUTLS_CLI_VERSION       "@VERSION@"
 #define GNUTLS_CLI_FULL_VERSION  "gnutls-cli @VERSION@"
 
@@ -154,47 +155,48 @@ typedef enum {
 #define OPT_VALUE_DEBUG          (DESC(DEBUG).optArg.argInt)
 #define VALUE_OPT_VERBOSE        'V'
 #define VALUE_OPT_TOFU           2
-#define VALUE_OPT_OCSP           3
+#define VALUE_OPT_DANE           3
+#define VALUE_OPT_OCSP           4
 #define VALUE_OPT_RESUME         'r'
 #define VALUE_OPT_HEARTBEAT      'b'
 #define VALUE_OPT_REHANDSHAKE    'e'
-#define VALUE_OPT_NOTICKET       7
-#define VALUE_OPT_OCSP_STATUS_REQUEST 8
+#define VALUE_OPT_NOTICKET       8
+#define VALUE_OPT_OCSP_STATUS_REQUEST 9
 #define VALUE_OPT_STARTTLS       's'
 #define VALUE_OPT_UDP            'u'
-#define VALUE_OPT_MTU            11
+#define VALUE_OPT_MTU            12
 
 #define OPT_VALUE_MTU            (DESC(MTU).optArg.argInt)
-#define VALUE_OPT_CRLF           12
-#define VALUE_OPT_X509FMTDER     13
+#define VALUE_OPT_CRLF           13
+#define VALUE_OPT_X509FMTDER     14
 #define VALUE_OPT_FINGERPRINT    'f'
-#define VALUE_OPT_DISABLE_EXTENSIONS 15
-#define VALUE_OPT_PRINT_CERT     16
-#define VALUE_OPT_RECORDSIZE     17
+#define VALUE_OPT_DISABLE_EXTENSIONS 16
+#define VALUE_OPT_PRINT_CERT     17
+#define VALUE_OPT_RECORDSIZE     18
 
 #define OPT_VALUE_RECORDSIZE     (DESC(RECORDSIZE).optArg.argInt)
-#define VALUE_OPT_DH_BITS        18
+#define VALUE_OPT_DH_BITS        19
 
 #define OPT_VALUE_DH_BITS        (DESC(DH_BITS).optArg.argInt)
-#define VALUE_OPT_PRIORITY       19
-#define VALUE_OPT_X509CAFILE     20
-#define VALUE_OPT_X509CRLFILE    21
-#define VALUE_OPT_PGPKEYFILE     22
-#define VALUE_OPT_PGPKEYRING     23
-#define VALUE_OPT_PGPCERTFILE    24
-#define VALUE_OPT_X509KEYFILE    25
-#define VALUE_OPT_X509CERTFILE   26
-#define VALUE_OPT_PGPSUBKEY      27
-#define VALUE_OPT_SRPUSERNAME    28
-#define VALUE_OPT_SRPPASSWD      29
-#define VALUE_OPT_PSKUSERNAME    30
-#define VALUE_OPT_PSKKEY         31
+#define VALUE_OPT_PRIORITY       20
+#define VALUE_OPT_X509CAFILE     21
+#define VALUE_OPT_X509CRLFILE    22
+#define VALUE_OPT_PGPKEYFILE     23
+#define VALUE_OPT_PGPKEYRING     24
+#define VALUE_OPT_PGPCERTFILE    25
+#define VALUE_OPT_X509KEYFILE    26
+#define VALUE_OPT_X509CERTFILE   27
+#define VALUE_OPT_PGPSUBKEY      28
+#define VALUE_OPT_SRPUSERNAME    29
+#define VALUE_OPT_SRPPASSWD      30
+#define VALUE_OPT_PSKUSERNAME    31
+#define VALUE_OPT_PSKKEY         32
 #define VALUE_OPT_PORT           'p'
-#define VALUE_OPT_INSECURE       129
-#define VALUE_OPT_BENCHMARK_CIPHERS 130
-#define VALUE_OPT_BENCHMARK_SOFT_CIPHERS 131
-#define VALUE_OPT_BENCHMARK_TLS_KX 132
-#define VALUE_OPT_BENCHMARK_TLS_CIPHERS 133
+#define VALUE_OPT_INSECURE       130
+#define VALUE_OPT_BENCHMARK_CIPHERS 131
+#define VALUE_OPT_BENCHMARK_SOFT_CIPHERS 132
+#define VALUE_OPT_BENCHMARK_TLS_KX 133
+#define VALUE_OPT_BENCHMARK_TLS_CIPHERS 134
 #define VALUE_OPT_LIST           'l'
 #define VALUE_OPT_HELP          'h'
 #define VALUE_OPT_MORE_HELP     '!'
index 410e1dc6cb4a035e6057e77cf2d08128733ad648..a375a7c9e2597dc9abe491bdd225b8e6eb657b7f 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
 #include "sockets.h"
 #include "benchmark.h"
 
+#ifdef HAVE_DANE
+#include <gnutls/dane.h>
+#endif
+
 #include <common.h>
 #include <socket.h>
 
@@ -394,6 +398,7 @@ cert_verify_callback (gnutls_session_t session)
   int rc;
   unsigned int status = 0;
   int ssh = ENABLED_OPT(TOFU);
+  int dane = ENABLED_OPT(DANE);
   const char* txt_service;
 
   rc = cert_verify(session, hostname);
@@ -470,6 +475,42 @@ cert_verify_callback (gnutls_session_t session)
         }
     }
 
+#ifdef HAVE_DANE
+  if (dane) /* try DANE auth */
+    {
+      rc = dane_verify_session_crt( session, hostname, udp?"udp":"tcp", atoi(service), 
+              DANE_F_REQUIRE_DNSSEC|DANE_F_IGNORE_LOCAL_RESOLVER, &status);
+      if (rc < 0)
+        {
+          fprintf(stderr, "*** DANE verification error: %s\n", dane_strerror(rc));
+          if (!insecure)
+            return -1;
+        }
+      else
+        {
+          if (status != 0)
+            {
+              fprintf(stderr, "*** DANE certificate verification failed (flags %x).\n", status);
+              if (status & DANE_VERIFY_CA_CONSTRAINS_VIOLATED)
+                fprintf(stderr, "- CA constrains were violated.\n");
+              if (status & DANE_VERIFY_CERT_DIFFERS)
+                fprintf(stderr, "- The certificate differs.\n");
+              if (status & DANE_VERIFY_NO_DANE_INFO)
+                fprintf(stderr, "- There was no DANE information.\n");
+              if (status & DANE_VERIFY_DNSSEC_DATA_INVALID)
+                fprintf(stderr, "- The DNSSEC signature is invalid.\n");
+              if (status & DANE_VERIFY_NO_DNSSEC_DATA)
+                fprintf(stderr, "- There was no DNSSEC signature.\n");
+              if (!insecure)
+                return -1;
+            }
+          else
+            printf("- DANE verification didn't reject the certificate.\n");
+        }
+
+    }
+#endif
+
   return 0;
 }