summaryrefslogtreecommitdiff
path: root/libdane
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2014-05-10 12:02:18 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2014-05-10 12:02:18 +0200
commitd19ac66361300aaf188bc69ae64d5fcd7e89b0f6 (patch)
tree775122d42de88687b7c3cf879b9d7f4376f120a2 /libdane
parent0ec6cd0ddfa4a72c08e0d16fd74f6ef7fcea8bbb (diff)
downloadgnutls-d19ac66361300aaf188bc69ae64d5fcd7e89b0f6.tar.gz
Added dane_verify_crt_raw2() which allows verifying against the certificate name.
Diffstat (limited to 'libdane')
-rw-r--r--libdane/dane.c86
-rw-r--r--libdane/includes/gnutls/dane.h9
-rw-r--r--libdane/libdane.map1
3 files changed, 89 insertions, 7 deletions
diff --git a/libdane/dane.c b/libdane/dane.c
index 44734257bc..1199091c22 100644
--- a/libdane/dane.c
+++ b/libdane/dane.c
@@ -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,
@@ -638,6 +664,52 @@ dane_verify_crt_raw(dane_state_t s,
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;
unsigned int usage, type, match, idx;
@@ -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);
diff --git a/libdane/includes/gnutls/dane.h b/libdane/includes/gnutls/dane.h
index 98e4a96faa..d0067992a3 100644
--- a/libdane/includes/gnutls/dane.h
+++ b/libdane/includes/gnutls/dane.h
@@ -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,
diff --git a/libdane/libdane.map b/libdane/libdane.map
index 3fee935ef3..12e13b06c5 100644
--- a/libdane/libdane.map
+++ b/libdane/libdane.map
@@ -20,6 +20,7 @@ DANE_0_0
dane_state_set_dlv_file;
dane_verify_crt_raw;
dane_raw_tlsa;
+ dane_verify_crt_raw2;
local:
*;
};