summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/resolve/resolved-dns-cache.c28
-rw-r--r--src/resolve/resolved-dns-dnssec.c30
-rw-r--r--src/resolve/resolved-dns-rr.c1
-rw-r--r--src/resolve/resolved-dns-rr.h1
4 files changed, 57 insertions, 3 deletions
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index 49d5090d36..413e1080d9 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -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;
diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c
index 57093ad80c..94543fef3a 100644
--- a/src/resolve/resolved-dns-dnssec.c
+++ b/src/resolve/resolved-dns-dnssec.c
@@ -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;
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index 04d442bf03..d479de7125 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -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;
}
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index 95d260f7aa..fccc4dba6a 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -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;