diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-09-19 11:31:51 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-09-19 11:31:51 +0200 |
commit | 694b9db9d10911375c804c72c5d051678e88be45 (patch) | |
tree | 321121d57d49c4f82c8aef450277a95c80d23b31 /libdane/dane.c | |
parent | 8b2c9137356e8f12421275bc8d039517002e46f0 (diff) | |
download | gnutls-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.c | 83 |
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: |