]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: cache - rework which RR types we apply redirection to
authorTom Gundersen <teg@jklm.no>
Thu, 3 Dec 2015 20:40:06 +0000 (21:40 +0100)
committerTom Gundersen <teg@jklm.no>
Thu, 10 Dec 2015 16:06:26 +0000 (17:06 +0100)
The logic of dns_cache_get() is now:
 - look up the precise key;
 - look up NXDOMAIN item;
 - if an RR type that may be redirected
   (i.e., not CNAME, DNAME, RRSIG, NSEC, NSEC3, SIG, KEY, or
   NXT) look up a correpsonding CNAME or DNAME record;
 - look up a corresponding NSEC record;

Before this change we would give up before potentially finding
negative cache entries for DNAME, CNAME and NSEC records, we
would return NSEC records for aliases where we had DNAME or CNAME
records available and we would incorrectly try to redirect DNSSEC RRs.

src/resolve/resolved-dns-cache.c

index a2cbdd8259d6c922e7e580464c3d86c0f7c18b80..794d587d4d50f72eed2200f5a4598517dd286bcd 100644 (file)
@@ -548,7 +548,7 @@ static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, D
          * much, after all this is just a cache */
 
         i = hashmap_get(c->by_key, k);
-        if (i || IN_SET(k->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME, DNS_TYPE_NSEC))
+        if (i)
                 return i;
 
         n = DNS_RESOURCE_KEY_NAME(k);
@@ -559,31 +559,39 @@ static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, D
         if (i && i->type == DNS_CACHE_NXDOMAIN)
                 return i;
 
-        /* Check if we have an NSEC record instead for the name. */
-        i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_NSEC, n));
-        if (i)
-                return i;
+        /* The following record types should never be redirected. See
+         * <https://tools.ietf.org/html/rfc4035#section-2.5>. */
+        if (!IN_SET(k->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME,
+                            DNS_TYPE_NSEC3, DNS_TYPE_NSEC, DNS_TYPE_RRSIG,
+                            DNS_TYPE_NXT, DNS_TYPE_SIG, DNS_TYPE_KEY)) {
+                /* Check if we have a CNAME record instead */
+                i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_CNAME, n));
+                if (i)
+                        return i;
 
-        /* Check if we have a CNAME record instead */
-        i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_CNAME, n));
-        if (i)
-                return i;
+                /* OK, let's look for cached DNAME records. */
+                for (;;) {
+                        char label[DNS_LABEL_MAX];
 
-        /* OK, let's look for cached DNAME records. */
-        for (;;) {
-                char label[DNS_LABEL_MAX];
+                        if (isempty(n))
+                                return NULL;
+
+                        i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_DNAME, n));
+                        if (i)
+                                return i;
 
-                if (isempty(n))
-                        return NULL;
+                        /* Jump one label ahead */
+                        r = dns_label_unescape(&n, label, sizeof(label));
+                        if (r <= 0)
+                                return NULL;
+                }
+        }
 
-                i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_DNAME, n));
+        if (k-> type != DNS_TYPE_NSEC) {
+                /* Check if we have an NSEC record instead for the name. */
+                i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_NSEC, n));
                 if (i)
                         return i;
-
-                /* Jump one label ahead */
-                r = dns_label_unescape(&n, label, sizeof(label));
-                if (r <= 0)
-                        return NULL;
         }
 
         return NULL;