]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added dane_verify_crt_raw2() which allows verifying against the certificate name.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 10 May 2014 10:02:18 +0000 (12:02 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 10 May 2014 10:02:18 +0000 (12:02 +0200)
libdane/dane.c
libdane/includes/gnutls/dane.h
libdane/libdane.map

index 44734257bc275ed6e12f9c28a6a0abf262843efb..1199091c2299ac6e3dfe633b5a85014a792b432a 100644 (file)
@@ -37,7 +37,7 @@
 #include "../lib/gnutls_int.h"
 
 #define MAX_DATA_ENTRIES 100
-#define DEBUG
+
 #ifdef DEBUG
 #define gnutls_assert() fprintf(stderr, "ASSERT: %s: %d\n", __FILE__, __LINE__);
 #define gnutls_assert_val(x) gnutls_assert_val_int(x, __FILE__, __LINE__)
@@ -561,7 +561,7 @@ verify_ca(const gnutls_datum_t * raw_crt, unsigned raw_crt_size,
 }
 
 static int
-verify_ee(const gnutls_datum_t * raw_crt,
+verify_ee(const char *hostname, 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)
@@ -569,8 +569,30 @@ verify_ee(const gnutls_datum_t * raw_crt,
        gnutls_datum_t pubkey = { NULL, 0 };
        int ret;
 
-       if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
+       if (crt_type == GNUTLS_CRT_X509 && hostname != NULL) {
+               gnutls_x509_crt_t crt;
+
+               ret = gnutls_x509_crt_init(&crt);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return DANE_E_CERT_ERROR;
+               }
 
+               ret = gnutls_x509_crt_import(crt, raw_crt, GNUTLS_X509_FMT_DER);
+               if (ret < 0) {
+                       gnutls_assert();
+                       gnutls_x509_crt_deinit(crt);
+                       return DANE_E_CERT_ERROR;
+               }
+
+               ret = gnutls_x509_crt_check_hostname2(crt, hostname, 0);
+               if (ret == 0) {
+                       *verify |= DANE_VERIFY_HOSTNAME_DIFFERS;
+               }
+               gnutls_x509_crt_deinit(crt);
+       }
+
+       if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
                if (!matches(raw_crt, data, match)) {
                        gnutls_assert();
                        *verify |= DANE_VERIFY_CERT_DIFFERS;
@@ -617,7 +639,9 @@ verify_ee(const gnutls_datum_t * raw_crt,
  * record then the verify flag %DANE_VERIFY_NO_DNSSEC_DATA is set.
  *
  * Note that the CA constraint only applies for the directly certifying CA
- * and does not account for long CA chains.
+ * and does not account for long CA chains. Moreover this function will NOT
+ * check the hostname of the end certificate. If that isn't done manually
+ * use dane_verify_crt_raw2().
  *
  * Due to the many possible options of DANE, there is no single threat
  * model countered. When notifying the user about DANE verification results
@@ -629,6 +653,8 @@ verify_ee(const gnutls_datum_t * raw_crt,
  * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
  *   negative error value.
  *
+ * Deprecated: use dane_verify_crt_raw2().
+ *
  **/
 int
 dane_verify_crt_raw(dane_state_t s,
@@ -637,6 +663,52 @@ dane_verify_crt_raw(dane_state_t s,
                    dane_query_t r,
                    unsigned int sflags, unsigned int vflags,
                    unsigned int *verify)
+{
+       return dane_verify_crt_raw2(s, chain, chain_size, chain_type, NULL,
+                               r, sflags, vflags, verify);
+}
+
+/**
+ * dane_verify_crt_raw2:
+ * @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 of the end certificate (to be combined with %DANE_VFLAG_ONLY_CHECK_EE_USAGE)
+ * @r: DANE data to check against
+ * @sflags: Flags for the the initialization of @s (if NULL)
+ * @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
+ * @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 the CA constraint only applies for the directly certifying CA
+ * and does not account for long CA chains. 
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Since 3.3.3.
+ *
+ **/
+int
+dane_verify_crt_raw2(dane_state_t s,
+                   const gnutls_datum_t * chain, unsigned chain_size,
+                   gnutls_certificate_type_t chain_type,
+                   dane_query_t r,
+                   unsigned int sflags, unsigned int vflags,
+                   unsigned int *verify)
 {
        int ret;
        unsigned checked = 0;
@@ -683,7 +755,7 @@ dane_verify_crt_raw(dane_state_t s,
                           && (usage == DANE_CERT_USAGE_LOCAL_EE
                               || usage == DANE_CERT_USAGE_EE)) {
                        ret =
-                           verify_ee(&chain[0], chain_type, type, match,
+                           verify_ee(hostname, &chain[0], chain_type, type, match,
                                      &data, &record_verify);
                        if (ret < 0) {
                                gnutls_assert();
@@ -775,8 +847,8 @@ dane_verify_crt(dane_state_t s,
                gnutls_assert();
                goto cleanup;
        }
-       ret = dane_verify_crt_raw(state, chain, chain_size, chain_type,
-                                 r, sflags, vflags, verify);
+       ret = dane_verify_crt_raw2(state, chain, chain_size, chain_type,
+                                 hostname, r, sflags, vflags, verify);
       cleanup:
        if (state != s)
                dane_state_deinit(state);
index 98e4a96faaae40436a4896e3b277663cdd04d90f..d0067992a310a67711badbfe74098438163525f1 100644 (file)
@@ -150,6 +150,7 @@ typedef enum dane_verify_status_t {
        DANE_VERIFY_CA_CONSTRAINTS_VIOLATED = 1,
        DANE_VERIFY_CERT_DIFFERS = 1 << 1,
        DANE_VERIFY_UNKNOWN_DANE_INFO = 1 << 2,
+       DANE_VERIFY_HOSTNAME_DIFFERS = 1 << 3,
 } dane_verify_status_t;
 
 #define DANE_VERIFY_CA_CONSTRAINS_VIOLATED DANE_VERIFY_CA_CONSTRAINTS_VIOLATED
@@ -166,6 +167,14 @@ int dane_verify_crt_raw(dane_state_t s,
                        unsigned int sflags, unsigned int vflags,
                        unsigned int *verify);
 
+int
+dane_verify_crt_raw2(dane_state_t s,
+                   const gnutls_datum_t * chain, unsigned chain_size,
+                   gnutls_certificate_type_t chain_type,
+                   dane_query_t r,
+                   unsigned int sflags, unsigned int vflags,
+                   unsigned int *verify);
+
 int dane_verify_crt(dane_state_t s,
                    const gnutls_datum_t * chain, unsigned chain_size,
                    gnutls_certificate_type_t chain_type,
index 3fee935ef32d61ba3c88dae33c38dd1c91159993..12e13b06c56706d6c7aeac669d6daf0995bfbda2 100644 (file)
@@ -20,6 +20,7 @@ DANE_0_0
        dane_state_set_dlv_file;
        dane_verify_crt_raw;
        dane_raw_tlsa;
+       dane_verify_crt_raw2;
   local:
     *;
 };