]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added dane_verification_status_print() and danetool can verify a DANE entry.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 1 Nov 2012 18:46:43 +0000 (19:46 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 1 Nov 2012 20:01:45 +0000 (21:01 +0100)
13 files changed:
NEWS
doc/invoke-danetool.texi
lib/libgnutls.map
libdane/Makefile.am
libdane/dane.c
libdane/includes/gnutls/dane.h
libdane/libdane.map
src/cli.c
src/common.c
src/danetool-args.c
src/danetool-args.def
src/danetool-args.h
src/danetool.c

diff --git a/NEWS b/NEWS
index 74d5fcbe826f41901d206a1f100e1b085f17dea6..b50a73568be58d18248ed2f5f2a915331aaca994 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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
index 636ab982acb404f5f8cd3b4bf79b11c176e4335d..e840936351086326b5809810550d4caf007d5cfd 100644 (file)
@@ -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
 
index b1f5b91948c01f2f3016690839a2616fd7fb5f6e..975a32e072ba5793d53c7a357191472461191f7c 100644 (file)
@@ -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:
index bffa102fbe1f6c6a54576a484361cfbe6b34bf34..d880cc8aaabeaae76c850e698beeb5114b50a569 100644 (file)
@@ -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
 
index 5428a331733b3c8855a26aaa39fff124d81dd3bd..b1b83a0249df4645125223320d4ed845dde9fe38 100644 (file)
@@ -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;
+}
index 9a08737a6acce81512d86ea12deeea8a31fe195a..75d2e36e6b2ca3f47c19ae98776fabe2236572be 100644 (file)
@@ -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,
index 335869c1c876bab9d559adb830619b692036f841..b3894e1b378876d4c94ace5a86a8c67ba1a8c595 100644 (file)
@@ -16,6 +16,7 @@ DANE_0_0
         dane_cert_type_name;
        dane_match_type_name;
        dane_cert_usage_name;
+       dane_verification_status_print;
   local:
     *;
 };
index 6064ad4e31b0aeec16bf8316a32f20222bbf94f3..513dda7d81cc85df1ab51b269da6d5139fd63f4e 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -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);
         }
 
     }
index 7841d43f49001e844f9e9ea7fd14b49fac6a80e6..9836125f7d503539ed8eca900cfd24c6c468a111 100644 (file)
@@ -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);
 
index 4eff5496286d6692ef706fe2fef6ffc882fdbfa6..d50d47643be2442d9334352b3770d9887296b97f 100644 (file)
@@ -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"
index 06390c9a44cbdbfb6669163204dff3aec6b12dc2..dc29c4fa13a62e8a00b25437fc1c09a348448eaa 100644 (file)
@@ -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_;
 };
index 4980c4e48a501e6026ca590d13ad5bbc97996fce..dfab6bb1d9bea061a33d733daa37243c0932a886 100644 (file)
@@ -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
  *
index 5770854dca23552eeb883e67245ba8bfa46f6b3c..f7736ed4a9764d3c2bab3336ea1b4e97d4898a26 100644 (file)
@@ -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);