]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Updates in DANE support. Allow caching of queries.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 9 Oct 2012 22:24:41 +0000 (00:24 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 9 Oct 2012 22:31:02 +0000 (00:31 +0200)
.gitignore
NEWS
doc/cha-cert-auth.texi
doc/invoke-certtool.texi
libdane/dane.c
libdane/includes/gnutls/dane.h
libdane/libdane.map
src/Makefile.am
src/cli.c

index 80ac853faa847582a44310933d19a1be50e75074..3d9f114098d2bac2f21ecf70645216ebd28e4aeb 100644 (file)
@@ -596,4 +596,5 @@ tests/mini-dtls-heartbeat
 tests/mini-handshake-timeout
 tests/mini-x509-callbacks
 doc/manpages/stamp_mans
-libdane/libdane.la
+libdane/libgnutls-dane.la
+doc/latex/dane-api.tex
diff --git a/NEWS b/NEWS
index 9966ba03285bd685556045e40376d629426cc365..b5bb53ec3a04ca34a08a12d3473d05c93fddd84b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -50,14 +50,15 @@ gnutls_pkcs11_obj_export2: Added
 gnutls_pkcs12_export2: Added
 gnutls_pubkey_import_openpgp_raw: Added
 gnutls_pubkey_import_x509_raw: Added
-dane_query_init: Added
-dane_query_deinit: Added
-dane_query_resolve_tlsa: Added
-dane_query_data: Added
+dane_state_init: Added
+dane_state_deinit: Added
+dane_query_tlsa: Added
 dane_query_status: Added
 dane_query_entries: Added
-dane_verify_crt: Added
+dane_query_data: Added
+dane_query_deinit: Added
 dane_verify_session_crt: Added
+dane_verify_crt: Added
 dane_strerror: Added
 
 
index e6c7c963e39d7a6a19f7fd51a43f4affeac1dcae..10f0ef91fbc3a2a94ecbcff31bfd1054eddb7d02 100644 (file)
@@ -507,10 +507,9 @@ high level verification functions are shown below.
 
 @showfuncB{dane_verify_session_crt,dane_strerror}
 
-The allowed flags for the verification function follow.
-
-@showenumdesc{dane_verify_flags_t,The DANE verification flags.}
-
+Note that the @code{dane_state_t} structure that is accepted by both
+verification functions is optional. It is required when many queries
+are performed to facilitate caching.
 The following flags are returned by the verify functions to
 indicate the status of the verification.
 
index 21f3bcb83f3e7276e4bae6e6da92a3e6fe975282..8228754c25d1f475dcdc5311203caed3e5299f4a 100644 (file)
@@ -7,7 +7,7 @@
 # 
 # DO NOT EDIT THIS FILE   (invoke-certtool.texi)
 # 
-# It has been AutoGen-ed  October  9, 2012 at 08:27:51 PM by AutoGen 5.16
+# It has been AutoGen-ed  October  9, 2012 at 10:59:40 PM by AutoGen 5.16
 # From the definitions    ../src/certtool-args.def
 # and the template file   agtexi-cmd.tpl
 @end ignore
@@ -108,7 +108,7 @@ USAGE:  certtool [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
        --template=file        Template file to use for non-interactive operation
                                 - file must pre-exist
        --pkcs-cipher=str      Cipher to use for PKCS #8 and #12 operations
-       --dane-rr              Print the DANE RR data on a certificate or public key
+       --dane-tlsa-rr         Print the DANE RR data on a certificate or public key
                                 - requires these options:
                                 dane-host
        --dane-host=str        Specify the hostname to be used in the DANE RR
@@ -116,7 +116,7 @@ USAGE:  certtool [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
        --dane-port=num        Specify the port number for the DANE data.
        --dane-ca              Whether the provided certificate or public key is a Certificate
 authority.
-       --dane-full-x509       Use the hash of the X.509 certificate, rather than the public key.
+       --dane-x509            Use the hash of the X.509 certificate, rather than the public key.
        --dane-local           The provided certificate or public key is a local entity.
    -v, --version[=arg]        Output version information and exit
    -h, --help                 Display extended usage information and exit
@@ -290,9 +290,9 @@ This is alternative to the bits option.
 This is the ``cipher to use for pkcs #8 and #12 operations'' option.
 This option takes an argument string @file{Cipher}.
 Cipher may be one of 3des, 3des-pkcs12, aes-128, aes-192, aes-256, rc2-40, arcfour.
-@anchor{certtool dane-rr}
-@subheading dane-rr option
-@cindex certtool-dane-rr
+@anchor{certtool dane-tlsa-rr}
+@subheading dane-tlsa-rr option
+@cindex certtool-dane-tlsa-rr
 
 This is the ``print the dane rr data on a certificate or public key'' option.
 
@@ -325,9 +325,9 @@ This command specifies the protocol for the service set in the DANE data.
 
 This is the ``whether the provided certificate or public key is a certificate authority.'' option.
 Marks the DANE RR as a CA certificate if specified.
-@anchor{certtool dane-full-x509}
-@subheading dane-full-x509 option
-@cindex certtool-dane-full-x509
+@anchor{certtool dane-x509}
+@subheading dane-x509 option
+@cindex certtool-dane-x509
 
 This is the ``use the hash of the x.509 certificate, rather than the public key.'' option.
 This option forces the generated record to contain the hash of the full X.509 certificate. By default only the hash of the public key is used.
@@ -476,12 +476,12 @@ $ certtool --verify-crl --load-ca-certificate x509-ca.pem < crl.pem
 To create a DANE TLSA resource record for a CA signed certificate use the following commands.
 
 @example
-$ certtool --dane-rr --dane-host www.example.com --load-certificate cert.pem
+$ certtool --dane-tlsa-rr --dane-host www.example.com --load-certificate cert.pem
 @end example
 
 For a self signed certificate use:
 @example
-$ certtool --dane-rr --dane-host www.example.com --load-certificate cert.pem \
+$ certtool --dane-tlsa-rr --dane-host www.example.com --load-certificate cert.pem \
   --dane-local
 @end example
 
@@ -491,7 +491,7 @@ certificate using DANE.
 
 In order to create a record for the signer of your certificate use:
 @example
-$ certtool --dane-rr --dane-host www.example.com --load-certificate cert.pem \
+$ certtool --dane-tlsa-rr --dane-host www.example.com --load-certificate cert.pem \
   --dane-ca
 @end example
 
index e008ad899e03428fead3aa7934ad17b200670b5a..4f4569a59b9c6c8a1a6b5312239533f9f1f23772 100644 (file)
 
 #define MAX_DATA_ENTRIES 4
 
+struct dane_state_st
+{
+       struct ub_ctx* ctx;
+       unsigned int flags;
+};
+
 struct dane_query_st
 {
+        struct ub_result* result;
        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
+ * @q: The query result structure
  *
  * This function will return the status of the query response.
  * See %dane_query_status_t for the possible types.
@@ -64,7 +69,7 @@ dane_query_status_t dane_query_status(dane_query_t q)
 
 /**
  * dane_query_entries:
- * @q: The query structure
+ * @q: The query result structure
  *
  * This function will return the number of entries in a query.
  *
@@ -77,7 +82,7 @@ unsigned int dane_query_entries(dane_query_t q)
 
 /**
  * dane_query_data:
- * @q: The query structure
+ * @q: The query result 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)
@@ -112,22 +117,22 @@ int dane_query_data(dane_query_t q, unsigned int idx,
 }
 
 /**
- * dane_query_init:
- * @q: The structure to be initialized
- * @flags: flags from the DANE_F_* definitions
+ * dane_state_init:
+ * @s: The structure to be initialized
+ * @flags: flags from the %dane_state_flags enumeration
  *
  * 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)
+int dane_state_init(dane_state_t* s, unsigned int flags)
 {
        struct ub_ctx* ctx;
        int ret;
 
-       *q = calloc(1, sizeof(struct dane_query_st));
-       if (*q == NULL)
+       *s = calloc(1, sizeof(struct dane_state_st));
+       if (*s == NULL)
                return DANE_E_MEMORY_ERROR;
 
        ctx = ub_ctx_create();
@@ -155,38 +160,50 @@ int dane_query_init(dane_query_t* q, unsigned int flags)
                goto cleanup;
        }
 
-       (*q)->ctx = ctx;
-       (*q)->flags = flags;
+       (*s)->ctx = ctx;
+       (*s)->flags = flags;
        
        return DANE_E_SUCCESS;
 cleanup:
 
        if (ctx)
                ub_ctx_delete(ctx);
-       free(*q);
+       free(*s);
        
        return ret;
 }
 
 /**
- * dane_query_init:
- * @q: The structure to be deinitialized
+ * dane_state_deinit:
+ * @s: The structure to be deinitialized
  *
  * This function will deinitialize a DANE query structure.
  *
  **/
-void dane_query_deinit(dane_query_t q)
+void dane_state_deinit(dane_state_t s)
 {
-       if (q->result)
-       ub_ctx_delete(q->ctx);
-               ub_resolve_free(q->result);
+       ub_ctx_delete(s->ctx);
+       free(s);
+}
+
 
+/**
+ * dane_query_deinit:
+ * @q: The structure to be deinitialized
+ *
+ * This function will deinitialize a DANE query result structure.
+ *
+ **/
+void dane_query_deinit(dane_query_t q)
+{
+       ub_resolve_free(q->result);
        free(q);
 }
 
 /**
- * dane_query_resolve_tlsa:
- * @q: The query structure
+ * dane_query_tlsa:
+ * @s: The DANE state structure
+ * @r: A structure to place the result
  * @host: The host name to resolve.
  * @proto: The protocol type (tcp, udp, etc.)
  * @port: The service port number (eg. 443).
@@ -197,62 +214,61 @@ void dane_query_deinit(dane_query_t q)
  * 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)
+int dane_query_tlsa(dane_state_t s, dane_query_t *r, 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;
-       }
-       
+       *r = calloc(1, sizeof(struct dane_query_st));
+       if (*r == NULL)
+               return DANE_E_MEMORY_ERROR;
+
        snprintf(ns, sizeof(ns), "_%u._%s.%s", port, proto, host);
 
        /* query for webserver */
-       ret = ub_resolve(q->ctx, ns, 52, 1, &q->result);
+       ret = ub_resolve(s->ctx, ns, 52, 1, &(*r)->result);
        if(ret != 0) {
                return DANE_E_RESOLVING_ERROR;
        }
 
 /* show first result */
-       if(!q->result->havedata) {
+       if(!(*r)->result->havedata) {
                return DANE_E_NO_DANE_DATA;
        }
 
        i = 0;
        do {
 
-               if (q->result->len[i] > 3)
+               if ((*r)->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] - 3;
+               (*r)->usage[i] = (*r)->result->data[i][0];
+               (*r)->type[i] = (*r)->result->data[i][1];
+               (*r)->match[i] = (*r)->result->data[i][2];
+               (*r)->data[i].data = (void*)&(*r)->result->data[i][3];
+               (*r)->data[i].size = (*r)->result->len[i] - 3;
                i++;
-       } while(q->result->data[i] != NULL);
+       } while((*r)->result->data[i] != NULL);
        
-       q->data_entries = i;
+       (*r)->data_entries = i;
 
-       if (!q->result->secure) {
-               if (q->result->bogus)
+       if (!(*r)->result->secure) {
+               if ((*r)->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;
+       if ((*r)->result->secure)
+               (*r)->status = DANE_QUERY_DNSSEC_VERIFIED;
+       else if ((*r)->result->bogus)
+               (*r)->status = DANE_QUERY_BOGUS;
+       else (*r)->status = DANE_QUERY_NO_DNSSEC;
 
        return ret;
 }
@@ -413,13 +429,14 @@ cleanup:
 
 /**
  * dane_verify_crt:
+ * @s: A DANE state structure (may be NULL)
  * @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.
+ * @flags: should be zero
  * @verify: An OR'ed list of %dane_verify_status_t.
  *
  * This function will verify the given certificate chain against the
@@ -433,17 +450,20 @@ cleanup:
  * it may be better to mention: DANE verification did not reject the certificate,
  * rather than mentioning a successful DANE verication.
  * 
+ * If the @q parameter is provided it will be used for caching entries.
+ *
  * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
  *   negative error value.
  *
  **/
-int dane_verify_crt (
+int dane_verify_crt (dane_state_t s,
        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;
+dane_state_t _s = NULL;
+dane_query_t r = NULL;
 int ret;
 unsigned int usage, type, match, idx;
 gnutls_datum_t data;
@@ -453,19 +473,22 @@ gnutls_datum_t data;
        
        *verify = 0;
        
-       ret = dane_query_init(&q, flags);
-       if (ret < 0) {
-               return ret;
-       }
+       if (s == NULL) {
+               ret = dane_state_init(&_s, flags);
+               if (ret < 0) {
+                       return ret;
+               }
+       } else
+               _s = s;
        
-       ret = dane_query_resolve_tlsa(q, hostname, proto, port);
+       ret = dane_query_tlsa(_s, &r, hostname, proto, port);
        if (ret < 0) {
                goto cleanup;
        }
 
        idx = 0;
        do {
-               ret = dane_query_data(q, idx++, &usage, &type, &match, &data);
+               ret = dane_query_data(r, idx++, &usage, &type, &match, &data);
                if (ret == DANE_E_REQUESTED_DATA_NOT_AVAILABLE)
                        break;
 
@@ -488,17 +511,19 @@ gnutls_datum_t data;
        ret = 0;
 
 cleanup:
-       dane_query_deinit(q);
+       if (s == NULL) dane_state_deinit(_s);
+       if (r != NULL) dane_query_deinit(r);
        return ret;
 }
 
 /**
  * dane_verify_session_crt:
+ * @s: A DANE state structure (may be NULL)
  * @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.
+ * @flags: should be zero.
  * @verify: An OR'ed list of %dane_verify_status_t.
  *
  * This function will verify session's certificate chain against the
@@ -510,6 +535,7 @@ cleanup:
  *
  **/
 int dane_verify_session_crt (
+        dane_state_t s,
        gnutls_session_t session,
        const char * hostname, const char* proto, unsigned int port,
        unsigned int flags, unsigned int *verify)
@@ -525,5 +551,5 @@ unsigned int type;
        
        type = gnutls_certificate_type_get(session);
        
-       return dane_verify_crt(cert_list, cert_list_size, type, hostname, proto, port, flags, verify);
+       return dane_verify_crt(s, cert_list, cert_list_size, type, hostname, proto, port, flags, verify);
 }
index 366d10a98014c2a1af960f735c0997fffff21e47..74a28f9bd05c59fd4ae781f2e2b811b481bbcef2 100644 (file)
@@ -89,17 +89,31 @@ typedef enum dane_query_status_t
   DANE_QUERY_NO_DNSSEC
 } dane_query_status_t;
 
+typedef struct dane_state_st *dane_state_t;
 typedef struct dane_query_st *dane_query_t;
 
+/**
+ * dane_state_flags_t:
+ * @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_state_flags_t 
+{
+  DANE_F_IGNORE_LOCAL_RESOLVER = 1,
+} dane_verify_flags_t;
+
+int dane_state_init (dane_state_t* s, unsigned int flags);
+void dane_state_deinit (dane_state_t s);
+
+int dane_query_tlsa(dane_state_t s, dane_query_t *r, const char* host, const char* proto, unsigned int port);
 
-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);
+int dane_query_data(dane_query_t q, unsigned int idx,
+                       unsigned int *usage, unsigned int *type,
+                       unsigned int *match, gnutls_datum_t * data);
+void dane_query_deinit(dane_query_t q);
 
 
 /**
@@ -117,25 +131,15 @@ typedef enum dane_verify_status_t
   DANE_VERIFY_NO_DANE_INFO = 1<<2,
 } 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_IGNORE_LOCAL_RESOLVER = 1,
-} dane_verify_flags_t;
 
-int dane_verify_crt (
+int dane_verify_crt (dane_state_t s,
        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 (
+        dane_state_t s,
        gnutls_session_t session,
        const char * hostname, const char* proto, unsigned int port,
        unsigned int flags, unsigned int *verify);
index a5af3538d21f6790b13f3b0596512a4816d92370..0bdd7a0a0ef9b0c673938d6783ef11530b0b8cac 100644 (file)
@@ -4,15 +4,15 @@ 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_state_init;
+       dane_state_deinit;
+       dane_query_tlsa;
        dane_query_status;
        dane_query_entries;
-
+       dane_query_data;
+       dane_query_deinit;
+       dane_verify_session_crt;
+       dane_verify_crt;
   local:
     *;
 };
index f4aa7e024d0dc3f056b2707796b019882b1c4544..4796c70c21cc42dffec744de055a3d5232c2588a 100644 (file)
@@ -104,7 +104,7 @@ gnutls_cli_SOURCES = cli.c common.h common.c \
        $(BENCHMARK_SRCS)
 gnutls_cli_LDADD = ../lib/libgnutls.la
 if ENABLE_DANE
-gnutls_cli_LDADD += ../libdane/libdane.la
+gnutls_cli_LDADD += ../libdane/libgnutls-dane.la
 endif
 gnutls_cli_LDADD += libcmd-cli.la ../gl/libgnu.la $(LIBOPTS_LDADD) $(LTLIBINTL)
 gnutls_cli_LDADD += $(LIBSOCKET) $(GETADDRINFO_LIB) $(LIB_CLOCK_GETTIME) \
index ca3a4f88861ca447c75d3d29b6f1baae305222ba..8dad5484d77e165c0546c5d2a57434828c467d46 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -484,7 +484,7 @@ 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), 
+      rc = dane_verify_session_crt( NULL, session, hostname, udp?"udp":"tcp", atoi(service), 
                                     DANE_F_IGNORE_LOCAL_RESOLVER, &status);
       if (rc < 0)
         {