resolved: use RRSIG expiry and original TTL for cache management

When we verified a signature, fix up the RR's TTL to the original TTL
mentioned in the signature, and store the signature expiry information
in the RR, too. Then, use that when adding RRs to the cache.
This commit is contained in:
Lennart Poettering 2015-12-28 00:30:56 +01:00
parent f535705a45
commit ee3d6aff9b
4 changed files with 57 additions and 3 deletions

View File

@ -272,6 +272,30 @@ static DnsCacheItem* dns_cache_get(DnsCache *c, DnsResourceRecord *rr) {
return NULL;
}
static usec_t calculate_until(DnsResourceRecord *rr, usec_t timestamp) {
usec_t ttl;
assert(rr);
ttl = rr->ttl * USEC_PER_SEC;
if (ttl > CACHE_TTL_MAX_USEC)
ttl = CACHE_TTL_MAX_USEC;
if (rr->expiry != USEC_INFINITY) {
usec_t left;
/* Make use of the DNSSEC RRSIG expiry info, if we have it */
left = LESS_BY(rr->expiry, now(CLOCK_REALTIME));
if (ttl > left)
ttl = left;
}
return timestamp + ttl;
}
static void dns_cache_item_update_positive(
DnsCache *c,
DnsCacheItem *i,
@ -302,7 +326,7 @@ static void dns_cache_item_update_positive(
dns_resource_key_unref(i->key);
i->key = dns_resource_key_ref(rr->key);
i->until = timestamp + MIN(rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
i->until = calculate_until(rr, timestamp);
i->authenticated = authenticated;
i->shared_owner = shared_owner;
@ -383,7 +407,7 @@ static int dns_cache_put_positive(
i->type = DNS_CACHE_POSITIVE;
i->key = dns_resource_key_ref(rr->key);
i->rr = dns_resource_record_ref(rr);
i->until = timestamp + MIN(i->rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
i->until = calculate_until(rr, timestamp);
i->authenticated = authenticated;
i->shared_owner = shared_owner;
i->owner_family = owner_family;

View File

@ -701,6 +701,30 @@ int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig)
return dns_name_equal(DNS_RESOURCE_KEY_NAME(rrsig->key), DNS_RESOURCE_KEY_NAME(key));
}
static int dnssec_fix_rrset_ttl(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord *rrsig, usec_t realtime) {
DnsResourceRecord *rr;
int r;
assert(key);
assert(rrsig);
DNS_ANSWER_FOREACH(rr, a) {
r = dns_resource_key_equal(key, rr->key);
if (r < 0)
return r;
if (r == 0)
continue;
/* Pick the TTL as the minimum of the RR's TTL, the
* RR's original TTL according to the RRSIG and the
* RRSIG's own TTL, see RFC 4035, Section 5.3.3 */
rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl);
rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
}
return 0;
}
int dnssec_verify_rrset_search(
DnsAnswer *a,
DnsResourceKey *key,
@ -767,7 +791,11 @@ int dnssec_verify_rrset_search(
case DNSSEC_VALIDATED:
/* Yay, the RR has been validated,
* return immediately. */
* return immediately, but fix up the expiry */
r = dnssec_fix_rrset_ttl(a, key, rrsig, realtime);
if (r < 0)
return r;
*result = DNSSEC_VALIDATED;
return 0;

View File

@ -339,6 +339,7 @@ DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
rr->n_ref = 1;
rr->key = dns_resource_key_ref(key);
rr->expiry = USEC_INFINITY;
return rr;
}

View File

@ -100,6 +100,7 @@ struct DnsResourceRecord {
DnsResourceKey *key;
char *to_string;
uint32_t ttl;
usec_t expiry; /* RRSIG signature expiry */
bool unparseable:1;
bool wire_format_canonical:1;
void *wire_format;