diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | doc/invoke-danetool.texi | 30 | ||||
-rw-r--r-- | lib/libgnutls.map | 4 | ||||
-rw-r--r-- | libdane/Makefile.am | 7 | ||||
-rw-r--r-- | libdane/dane.c | 44 | ||||
-rw-r--r-- | libdane/includes/gnutls/dane.h | 3 | ||||
-rw-r--r-- | libdane/libdane.map | 1 | ||||
-rw-r--r-- | src/cli.c | 18 | ||||
-rw-r--r-- | src/common.c | 2 | ||||
-rw-r--r-- | src/danetool-args.c | 4 | ||||
-rw-r--r-- | src/danetool-args.def | 6 | ||||
-rw-r--r-- | src/danetool-args.h | 2 | ||||
-rw-r--r-- | src/danetool.c | 54 |
13 files changed, 150 insertions, 30 deletions
@@ -19,8 +19,8 @@ for SRTP. ** danetool: Corrected bug that prevented loading PEM files. -** danetool: Added --check option to allow querying sites for -DANE data. +** danetool: Added --check option to allow querying and verifying +a site's DANE data. ** libgnutls-dane: Added pkg-config file for the library. @@ -38,6 +38,7 @@ gnutls_srtp_profile_t: Added dane_cert_type_name: Added dane_match_type_name: Added dane_cert_usage_name: Added +dane_verification_status_print: Added GNUTLS_CERT_REVOCATION_DATA_TOO_OLD: Added GNUTLS_CERT_REVOCATION_DATA_INVALID: Added GNUTLS_CERT_UNEXPECTED_OWNER: Added diff --git a/doc/invoke-danetool.texi b/doc/invoke-danetool.texi index 636ab982ac..e840936351 100644 --- a/doc/invoke-danetool.texi +++ b/doc/invoke-danetool.texi @@ -7,7 +7,7 @@ # # DO NOT EDIT THIS FILE (invoke-danetool.texi) # -# It has been AutoGen-ed October 29, 2012 at 07:37:13 PM by AutoGen 5.16 +# It has been AutoGen-ed November 1, 2012 at 07:51:08 PM by AutoGen 5.16 # From the definitions ../src/danetool-args.def # and the template file agtexi-cmd.tpl @end ignore @@ -48,6 +48,9 @@ USAGE: danetool [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]... --load-pubkey=str Loads a public key file --load-certificate=str Loads a certificate file --hash=str Hash algorithm to use for signing. + --check=str Check DANE TLSA entry. + --local-dns Use the local DNS server for DNSSEC resolving. + - disabled as --no-local-dns --inder Use DER format for input certificates and private keys. - disabled as --no-inder --inraw This is an alias for 'inder' @@ -58,7 +61,7 @@ USAGE: danetool [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]... --proto=str The protocol set for DANE data (tcp, udp etc.) --port=num Specify the port number for the DANE data. --ca Whether the provided certificate or public key is a Certificate -authority. +Authority. --x509 Use the hash of the X.509 certificate, rather than the public key. --local The provided certificate or public key is a local entity. -v, --version[=arg] Output version information and exit @@ -104,6 +107,20 @@ This can be either a file or a PKCS #11 URL This is the ``hash algorithm to use for signing.'' option. This option takes an argument string. Available hash functions are SHA1, RMD160, SHA256, SHA384, SHA512. +@anchor{danetool check} +@subheading check option +@cindex danetool-check + +This is the ``check dane tlsa entry.'' option. +This option takes an argument string. +Obtains the DANE TLSA entry from the given hostname and prints information. +@anchor{danetool local-dns} +@subheading local-dns option +@cindex danetool-local-dns + +This is the ``use the local dns server for dnssec resolving.'' option. +This option will use the local DNS server for DNSSEC. +This is disabled by default due to many servers not allowing DNSSEC. @anchor{danetool inder} @subheading inder option @cindex danetool-inder @@ -206,8 +223,13 @@ $ danetool --tlsa-rr --host www.example.com --load-certificate cert.pem \ --ca @end example -To read a server's DANE TLSA entry, using the dig tool, use: +To read a server's DANE TLSA entry, use: +@example +$ danetool --check www.example.com --proto tcp --port 443 +@end example + +To verify a server's DANE TLSA entry, use: @example -$ dig +short TYPE52 _443._tcp.www.example.com +$ danetool --check www.example.com --proto tcp --port 443 --load-certificate chain.pem @end example diff --git a/lib/libgnutls.map b/lib/libgnutls.map index b1f5b91948..975a32e072 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -896,7 +896,9 @@ GNUTLS_PRIVATE { _gnutls_buffer_append_data_prefix; _gnutls_buffer_pop_data; _gnutls_buffer_pop_prefix; - + _gnutls_buffer_init; + _gnutls_buffer_append_str; + _gnutls_buffer_to_datum; # Internal symbols needed by psktool: # Internal symbols needed by gnutls-cli-debug: diff --git a/libdane/Makefile.am b/libdane/Makefile.am index bffa102fbe..d880cc8aaa 100644 --- a/libdane/Makefile.am +++ b/libdane/Makefile.am @@ -22,12 +22,13 @@ ACLOCAL_AMFLAGS = -I ../m4 -I ../gl/m4 AM_CFLAGS = $(WERROR_CFLAGS) $(WSTACK_CFLAGS) $(WARN_CFLAGS) AM_CPPFLAGS = \ - -I$(srcdir)/../gl \ - -I$(builddir)/../gl \ + -I$(srcdir)/../gl \ + -I$(builddir)/../gl \ -I$(builddir)/../lib/includes \ -I$(srcdir)/../lib/includes \ -I$(srcdir)/includes \ - -I$(builddir)/includes + -I$(builddir)/includes \ + -I$(srcdir)/../lib SUBDIRS = includes diff --git a/libdane/dane.c b/libdane/dane.c index 5428a33173..b1b83a0249 100644 --- a/libdane/dane.c +++ b/libdane/dane.c @@ -32,6 +32,7 @@ #include <gnutls/x509.h> #include <gnutls/abstract.h> #include <gnutls/crypto.h> +#include "../lib/gnutls_int.h" #define MAX_DATA_ENTRIES 4 @@ -602,3 +603,46 @@ unsigned int type; return dane_verify_crt(s, cert_list, cert_list_size, type, hostname, proto, port, sflags, vflags, verify); } +/** + * dane_verification_status_print: + * @status: The status flags to be printed + * @type: The certificate type + * @out: Newly allocated datum with (0) terminated string. + * @flags: should be zero + * + * This function will pretty print the status of a verification + * process -- eg. the one obtained by dane_verify_crt(). + * + * The output @out needs to be deallocated using gnutls_free(). + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + **/ +int +dane_verification_status_print (unsigned int status, + gnutls_datum_t * out, unsigned int flags) +{ + gnutls_buffer_st str; + int ret; + + _gnutls_buffer_init (&str); + + if (status == 0) + _gnutls_buffer_append_str (&str, _("DANE verification didn't reject the certificate. ")); + else + _gnutls_buffer_append_str (&str, _("DANE verification failed. ")); + + if (status & DANE_VERIFY_CA_CONSTRAINS_VIOLATED) + _gnutls_buffer_append_str (&str, _("CA constrains were violated. ")); + + if (status & DANE_VERIFY_CERT_DIFFERS) + _gnutls_buffer_append_str (&str, _("The certificate differs. ")); + + if (status & DANE_VERIFY_NO_DANE_INFO) + _gnutls_buffer_append_str (&str, _("There was no DANE information. ")); + + ret = _gnutls_buffer_to_datum( &str, out); + if (out->size > 0) out->size--; + + return ret; +} diff --git a/libdane/includes/gnutls/dane.h b/libdane/includes/gnutls/dane.h index 9a08737a6a..75d2e36e6b 100644 --- a/libdane/includes/gnutls/dane.h +++ b/libdane/includes/gnutls/dane.h @@ -134,6 +134,9 @@ typedef enum dane_verify_status_t DANE_VERIFY_NO_DANE_INFO = 1<<2, } dane_verify_status_t; +int +dane_verification_status_print (unsigned int status, + gnutls_datum_t * out, unsigned int flags); int dane_verify_crt (dane_state_t s, const gnutls_datum_t *chain, unsigned chain_size, diff --git a/libdane/libdane.map b/libdane/libdane.map index 335869c1c8..b3894e1b37 100644 --- a/libdane/libdane.map +++ b/libdane/libdane.map @@ -16,6 +16,7 @@ DANE_0_0 dane_cert_type_name; dane_match_type_name; dane_cert_usage_name; + dane_verification_status_print; local: *; }; @@ -498,20 +498,18 @@ cert_verify_callback (gnutls_session_t session) } else { - if (status != 0) + gnutls_datum_t out; + + rc = dane_verification_status_print( status, &out, 0); + if (rc < 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"); + fprintf(stderr, "*** DANE error: %s\n", dane_strerror(rc)); if (!insecure) return -1; } - else - printf("- DANE verification didn't reject the certificate.\n"); + + fprintf(stderr, "- %s\n", out.data); + gnutls_free(out.data); } } diff --git a/src/common.c b/src/common.c index 7841d43f49..9836125f7d 100644 --- a/src/common.c +++ b/src/common.c @@ -340,7 +340,7 @@ cert_verify (gnutls_session_t session, const char* hostname) return 0; } - printf ("- %s", out.data); + printf ("- %s\n", out.data); gnutls_free(out.data); diff --git a/src/danetool-args.c b/src/danetool-args.c index 4eff549628..d50d47643b 100644 --- a/src/danetool-args.c +++ b/src/danetool-args.c @@ -2,7 +2,7 @@ * * DO NOT EDIT THIS FILE (danetool-args.c) * - * It has been AutoGen-ed November 1, 2012 at 06:12:17 PM by AutoGen 5.16 + * It has been AutoGen-ed November 1, 2012 at 07:45:47 PM by AutoGen 5.16 * From the definitions danetool-args.def * and the template file options * @@ -130,7 +130,7 @@ static char const danetool_opt_strs[2257] = /* 1598 */ "PORT\0" /* 1603 */ "port\0" /* 1608 */ "Whether the provided certificate or public key is a Certificate\n" - "authority.\0" + "Authority.\0" /* 1683 */ "CA\0" /* 1686 */ "ca\0" /* 1689 */ "Use the hash of the X.509 certificate, rather than the public key.\0" diff --git a/src/danetool-args.def b/src/danetool-args.def index 06390c9a44..dc29c4fa13 100644 --- a/src/danetool-args.def +++ b/src/danetool-args.def @@ -96,7 +96,7 @@ flag = { flag = { name = ca; - descrip = "Whether the provided certificate or public key is a Certificate authority."; + descrip = "Whether the provided certificate or public key is a Certificate Authority."; doc = "Marks the DANE RR as a CA certificate if specified."; }; @@ -153,9 +153,9 @@ To read a server's DANE TLSA entry, use: $ danetool --check www.example.com --proto tcp --port 443 @end example -To read a server's DANE TLSA entry, using the dig tool, use: +To verify a server's DANE TLSA entry, use: @example -$ dig +short TYPE52 _443._tcp.www.example.com +$ danetool --check www.example.com --proto tcp --port 443 --load-certificate chain.pem @end example _EOT_; }; diff --git a/src/danetool-args.h b/src/danetool-args.h index 4980c4e48a..dfab6bb1d9 100644 --- a/src/danetool-args.h +++ b/src/danetool-args.h @@ -2,7 +2,7 @@ * * DO NOT EDIT THIS FILE (danetool-args.h) * - * It has been AutoGen-ed November 1, 2012 at 06:12:16 PM by AutoGen 5.16 + * It has been AutoGen-ed November 1, 2012 at 07:45:46 PM by AutoGen 5.16 * From the definitions danetool-args.def * and the template file options * diff --git a/src/danetool.c b/src/danetool.c index 5770854dca..f7736ed4a9 100644 --- a/src/danetool.c +++ b/src/danetool.c @@ -155,7 +155,7 @@ cmd_parser (int argc, char **argv) if (HAVE_OPT(LOAD_CERTIFICATE)) cinfo.cert = OPT_ARG(LOAD_CERTIFICATE); - + if (HAVE_OPT(PORT)) port = OPT_VALUE_PORT; if (HAVE_OPT(PROTO)) @@ -166,7 +166,7 @@ cmd_parser (int argc, char **argv) HAVE_OPT(CA), HAVE_OPT(LOCAL), &cinfo); else if (HAVE_OPT(CHECK)) dane_check (OPT_ARG(CHECK), proto, port, - &cinfo); + &cinfo); else USAGE(1); @@ -186,7 +186,7 @@ dane_query_t q; int ret; unsigned int flags = DANE_F_IGNORE_LOCAL_RESOLVER, i; unsigned int usage, type, match; -gnutls_datum_t data; +gnutls_datum_t data, file; size_t size; if (ENABLED_OPT(LOCAL_DNS)) @@ -221,6 +221,54 @@ size_t size; fprintf(outfile, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n", port, proto, host, usage, type, match, buffer); } + /* Verify the DANE data */ + if (cinfo->cert) + { + gnutls_x509_crt_t *clist; + unsigned int clist_size, status; + + ret = gnutls_load_file(cinfo->cert, &file); + if (ret < 0) + error (EXIT_FAILURE, 0, "gnutls_load_file: %s", gnutls_strerror (ret)); + + ret = gnutls_x509_crt_list_import2( &clist, &clist_size, &file, cinfo->incert_format, 0); + if (ret < 0) + error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_import2: %s", gnutls_strerror (ret)); + + if (clist_size > 0) + { + gnutls_datum_t certs[clist_size]; + gnutls_datum_t out; + unsigned int i; + + for (i=0;i<clist_size;i++) + { + ret = gnutls_x509_crt_export2( clist[i], GNUTLS_X509_FMT_DER, &certs[i]); + if (ret < 0) + error (EXIT_FAILURE, 0, "gnutls_x509_crt_export2: %s", gnutls_strerror (ret)); + } + + ret = dane_verify_crt( s, certs, clist_size, GNUTLS_CRT_X509, + host, proto, port, 0, 0, &status); + if (ret < 0) + error (EXIT_FAILURE, 0, "dane_verify_crt: %s", dane_strerror (ret)); + + ret = dane_verification_status_print(status, &out, 0); + if (ret < 0) + error (EXIT_FAILURE, 0, "dane_verification_status_print: %s", dane_strerror (ret)); + + printf("\n%s\n", out.data); + gnutls_free(out.data); + + for (i=0;i<clist_size;i++) + { + gnutls_free(certs[i].data); + gnutls_x509_crt_deinit(clist[i]); + } + gnutls_free(clist); + } + } + dane_query_deinit(q); dane_state_deinit(s); |