summaryrefslogtreecommitdiff
path: root/libdane/dane.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-09-19 11:31:51 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-09-19 11:31:51 +0200
commit694b9db9d10911375c804c72c5d051678e88be45 (patch)
tree321121d57d49c4f82c8aef450277a95c80d23b31 /libdane/dane.c
parent8b2c9137356e8f12421275bc8d039517002e46f0 (diff)
downloadgnutls-694b9db9d10911375c804c72c5d051678e88be45.tar.gz
libdane: do not require the CA to be a direct CA
Diffstat (limited to 'libdane/dane.c')
-rw-r--r--libdane/dane.c83
1 files changed, 56 insertions, 27 deletions
diff --git a/libdane/dane.c b/libdane/dane.c
index eb12495a17..128a2c3059 100644
--- a/libdane/dane.c
+++ b/libdane/dane.c
@@ -563,28 +563,48 @@ verify_ca(const gnutls_datum_t * raw_crt, unsigned raw_crt_size,
unsigned int *verify)
{
gnutls_datum_t pubkey = { NULL, 0 };
- int ret;
- unsigned int vstatus;
+ int ret, i;
+ unsigned int vstatus = 0;
gnutls_x509_crt_t crt = NULL, ca = NULL;
+ unsigned is_ok = 0;
if (raw_crt_size < 2)
return gnutls_assert_val(DANE_E_INVALID_REQUEST);
if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
+ is_ok = 0;
+ for (i=raw_crt_size-1;i>=1;i--) {
+ if (matches(&raw_crt[i], data, match)) {
+ is_ok = 1;
+ break;
+ }
+ }
- if (!matches(&raw_crt[1], data, match)) {
+ if (is_ok == 0) {
gnutls_assert();
*verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
}
} else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
- ret = crt_to_pubkey(&raw_crt[1], &pubkey);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
+ is_ok = 0;
+
+ for (i=raw_crt_size-1;i>=1;i--) {
+ ret = crt_to_pubkey(&raw_crt[i], &pubkey);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ if (matches(&pubkey, data, match)) {
+ is_ok = 1;
+ break;
+ }
+
+ free(pubkey.data);
+ pubkey.data = NULL;
}
- if (!matches(&pubkey, data, match)) {
+ if (is_ok == 0) {
gnutls_assert();
*verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
}
@@ -600,12 +620,6 @@ verify_ca(const gnutls_datum_t * raw_crt, unsigned raw_crt_size,
goto cleanup;
}
- ret = gnutls_x509_crt_init(&ca);
- if (ret < 0) {
- ret = gnutls_assert_val(DANE_E_CERT_ERROR);
- goto cleanup;
- }
-
ret =
gnutls_x509_crt_import(crt, &raw_crt[0], GNUTLS_X509_FMT_DER);
if (ret < 0) {
@@ -613,25 +627,40 @@ verify_ca(const gnutls_datum_t * raw_crt, unsigned raw_crt_size,
goto cleanup;
}
- ret = gnutls_x509_crt_import(ca, &raw_crt[1], GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- ret = gnutls_assert_val(DANE_E_CERT_ERROR);
- goto cleanup;
+ for (i=raw_crt_size-1;i>=1;i--) {
+ ret = gnutls_x509_crt_init(&ca);
+ if (ret < 0) {
+ ret = gnutls_assert_val(DANE_E_CERT_ERROR);
+ goto cleanup;
+ }
+
+ ret = gnutls_x509_crt_import(ca, &raw_crt[i], GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ ret = gnutls_assert_val(DANE_E_CERT_ERROR);
+ goto cleanup;
+ }
+
+ ret = gnutls_x509_crt_check_issuer(crt, ca);
+ if (ret != 0)
+ break;
+
+ gnutls_x509_crt_deinit(ca);
+ ca = NULL;
}
- ret = gnutls_x509_crt_check_issuer(crt, ca);
- if (ret == 0) {
+ if (ca == NULL) {
gnutls_assert();
*verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
- }
+ } else {
+ ret = gnutls_x509_crt_verify(crt, &ca, 1, 0, &vstatus);
+ if (ret < 0) {
+ ret = gnutls_assert_val(DANE_E_CERT_ERROR);
+ goto cleanup;
+ }
- ret = gnutls_x509_crt_verify(crt, &ca, 1, 0, &vstatus);
- if (ret < 0) {
- ret = gnutls_assert_val(DANE_E_CERT_ERROR);
- goto cleanup;
+ if (vstatus != 0)
+ *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
}
- if (vstatus != 0)
- *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
ret = 0;
cleanup: