diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-01-05 01:35:28 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-01-05 01:35:28 +0100 |
commit | d3760be01b120df8980c056ecc85a4229d660264 (patch) | |
tree | ca9c2938ae603d2438e8c65a5c0c2885f0a8e3e7 /src/resolve/resolved-dns-dnssec.c | |
parent | 519d39deeeec7121649f28e7287b7790e50d2979 (diff) |
resolved: when caching negative responses, honour NSEC/NSEC3 TTLs
When storing negative responses, clamp the SOA minimum TTL (as suggested
by RFC2308) to the TTL of the NSEC/NSEC3 RRs we used to prove
non-existance, if it there is any.
This is necessary since otherwise an attacker might put together a faked
negative response for one of our question including a high-ttl SOA RR
for any parent zone, and we'd use trust the TTL.
Diffstat (limited to 'src/resolve/resolved-dns-dnssec.c')
-rw-r--r-- | src/resolve/resolved-dns-dnssec.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index ac2362275c..32d4834aa1 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -40,7 +40,6 @@ * - cname/dname compatibility * - nxdomain on qname * - per-interface DNSSEC setting - * - when doing negative caching, use NSEC/NSEC3 RR instead of SOA for TTL * * */ @@ -1250,7 +1249,7 @@ static int nsec3_hashed_domain(DnsResourceRecord *nsec3, const char *domain, con * that there is no proof either way. The latter is the case if a the proof of non-existence of a given * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records * to conclude anything we indicate this by returning NO_RR. */ -static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated) { +static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { _cleanup_free_ char *next_closer_domain = NULL, *wildcard = NULL, *wildcard_domain = NULL; const char *zone, *p, *pp = NULL; DnsResourceRecord *rr, *enclosure_rr, *suffix_rr, *wildcard_rr = NULL; @@ -1260,7 +1259,6 @@ static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecR assert(key); assert(result); - assert(authenticated); /* First step, find the zone name and the NSEC3 parameters of the zone. * it is sufficient to look for the longest common suffix we find with @@ -1369,7 +1367,10 @@ found_closest_encloser: else *result = DNSSEC_NSEC_NODATA; - *authenticated = a; + if (authenticated) + *authenticated = a; + if (ttl) + *ttl = enclosure_rr->ttl; return 0; } @@ -1452,7 +1453,6 @@ found_closest_encloser: if (!no_closer) { *result = DNSSEC_NSEC_NO_RR; - return 0; } @@ -1488,12 +1488,16 @@ found_closest_encloser: } } - *authenticated = a; + if (authenticated) + *authenticated = a; + + if (ttl) + *ttl = enclosure_rr->ttl; return 0; } -int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated) { +int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { DnsResourceRecord *rr; bool have_nsec3 = false; DnsAnswerFlags flags; @@ -1501,7 +1505,6 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r assert(key); assert(result); - assert(authenticated); /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */ @@ -1524,7 +1527,12 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r *result = DNSSEC_NSEC_CNAME; else *result = DNSSEC_NSEC_NODATA; - *authenticated = flags & DNS_ANSWER_AUTHENTICATED; + + if (authenticated) + *authenticated = flags & DNS_ANSWER_AUTHENTICATED; + if (ttl) + *ttl = rr->ttl; + return 0; } @@ -1533,7 +1541,12 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r return r; if (r > 0) { *result = DNSSEC_NSEC_NXDOMAIN; - *authenticated = flags & DNS_ANSWER_AUTHENTICATED; + + if (authenticated) + *authenticated = flags & DNS_ANSWER_AUTHENTICATED; + if (ttl) + *ttl = rr->ttl; + return 0; } break; @@ -1546,7 +1559,7 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r /* OK, this was not sufficient. Let's see if NSEC3 can help. */ if (have_nsec3) - return dnssec_test_nsec3(answer, key, result, authenticated); + return dnssec_test_nsec3(answer, key, result, authenticated, ttl); /* No approproate NSEC RR found, report this. */ *result = DNSSEC_NSEC_NO_RR; |