summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-trust-anchor.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-01-07 20:33:31 +0100
committerLennart Poettering <lennart@poettering.net>2016-01-11 19:39:59 +0100
commitc9c72065419e6595131a6fe1e663e2184a843f7c (patch)
tree1706d1d0ab0ea9cc4c960af9977c5e4235fa0661 /src/resolve/resolved-dns-trust-anchor.c
parentd12315a4c883af968ec5ffb36a5aed3dc43b7ce7 (diff)
resolved: when validating, first strip revoked trust anchor keys from validated keys list
When validating a transaction we initially collect DNSKEY, DS, SOA RRs in the "validated_keys" list, that we need for the proofs. This includes DNSKEY and DS data from our trust anchor database. Quite possibly we learn that some of these DNSKEY/DS RRs have been revoked between the time we request and collect those additional RRs and we begin the validation step. In this case we need to make sure that the respective DS/DNSKEY RRs are removed again from our list. This patch adds that, and strips known revoked trust anchor RRs from the validated list before we begin the actual validation proof, and each time we add more DNSKEY material to it while we are doing the proof.
Diffstat (limited to 'src/resolve/resolved-dns-trust-anchor.c')
-rw-r--r--src/resolve/resolved-dns-trust-anchor.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c
index d2a9c3635b..9bee44b5c7 100644
--- a/src/resolve/resolved-dns-trust-anchor.c
+++ b/src/resolve/resolved-dns-trust-anchor.c
@@ -511,13 +511,18 @@ int dns_trust_anchor_load(DnsTrustAnchor *d) {
void dns_trust_anchor_flush(DnsTrustAnchor *d) {
DnsAnswer *a;
+ DnsResourceRecord *rr;
assert(d);
while ((a = hashmap_steal_first(d->positive_by_key)))
dns_answer_unref(a);
-
d->positive_by_key = hashmap_free(d->positive_by_key);
+
+ while ((rr = set_steal_first(d->revoked_by_rr)))
+ dns_resource_record_unref(rr);
+ d->revoked_by_rr = set_free(d->revoked_by_rr);
+
d->negative_by_name = set_free_free(d->negative_by_name);
}
@@ -547,11 +552,35 @@ int dns_trust_anchor_lookup_negative(DnsTrustAnchor *d, const char *name) {
return set_contains(d->negative_by_name, name);
}
+static int dns_trust_anchor_revoked_put(DnsTrustAnchor *d, DnsResourceRecord *rr) {
+ int r;
+
+ assert(d);
+
+ r = set_ensure_allocated(&d->revoked_by_rr, &dns_resource_record_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = set_put(d->revoked_by_rr, rr);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ dns_resource_record_ref(rr);
+
+ return r;
+}
+
static int dns_trust_anchor_remove_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) {
_cleanup_(dns_answer_unrefp) DnsAnswer *new_answer = NULL;
DnsAnswer *old_answer;
int r;
+ /* Remember that this is a revoked trust anchor RR */
+ r = dns_trust_anchor_revoked_put(d, rr);
+ if (r < 0)
+ return r;
+
+ /* Remove this from the positive trust anchor */
old_answer = hashmap_get(d->positive_by_key, rr->key);
if (!old_answer)
return 0;
@@ -610,6 +639,9 @@ static int dns_trust_anchor_check_revoked_one(DnsTrustAnchor *d, DnsResourceReco
if (anchor->dnskey.key_size != revoked_dnskey->dnskey.key_size)
continue;
+ /* Note that we allow the REVOKE bit to be
+ * different! It will be set in the revoked
+ * key, but unset in our version of it */
if (((anchor->dnskey.flags ^ revoked_dnskey->dnskey.flags) | DNSKEY_FLAG_REVOKE) != DNSKEY_FLAG_REVOKE)
continue;
@@ -629,6 +661,10 @@ static int dns_trust_anchor_check_revoked_one(DnsTrustAnchor *d, DnsResourceReco
DNS_ANSWER_FOREACH(anchor, a) {
+ /* We set mask_revoke to true here, since our
+ * DS fingerprint will be the one of the
+ * unrevoked DNSKEY, but the one we got passed
+ * here has the bit set. */
r = dnssec_verify_dnskey(revoked_dnskey, anchor, true);
if (r < 0)
return r;
@@ -698,3 +734,12 @@ int dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsResourceRecord *dnskey,
return 0;
}
+
+int dns_trust_anchor_is_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) {
+ assert(d);
+
+ if (!IN_SET(rr->key->type, DNS_TYPE_DS, DNS_TYPE_DNSKEY))
+ return 0;
+
+ return set_contains(d->revoked_by_rr, rr);
+}