]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: rework how we allow allow queries to be dispatched to scopes
authorLennart Poettering <lennart@poettering.net>
Thu, 3 Dec 2015 17:26:12 +0000 (18:26 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 3 Dec 2015 20:17:49 +0000 (21:17 +0100)
Previously, we'd never do any single-label or root domain lookups via
DNS, thus leaving single-label lookups to LLMNR and the search path
logic in order that single-label names don't leak too easily onto the
internet. With this change we open things up a bit, and only prohibit
A/AAAA lookups of single-label/root domains, but allow all other
lookups. This should provide similar protection, but allow us to resolve
DNSKEY+DS RRs for the top-level and root domains.

(This also simplifies handling of the search domain detection, and gets
rid of dns_scope_has_search_domains() in favour of
dns_scope_get_search_domains()).

src/resolve/resolved-dns-rr.c
src/resolve/resolved-dns-rr.h
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-scope.h

index b109934d3afc1864a985e6a5bddff5165931dd66..934a18334c85e9164e0353b2f2c35556e7e56349 100644 (file)
@@ -157,6 +157,14 @@ DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
         return NULL;
 }
 
+bool dns_resource_key_is_address(const DnsResourceKey *key) {
+        assert(key);
+
+        /* Check if this is an A or AAAA resource key */
+
+        return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA);
+}
+
 int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
         int r;
 
index adaca962fcfdc14be8a38008e39e7261685d5b57..b82fa7756221aef4a3596166abb1b50509771940 100644 (file)
@@ -239,6 +239,7 @@ int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key
 DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name);
 DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key);
 DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key);
+bool dns_resource_key_is_address(const DnsResourceKey *key);
 int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b);
 int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr, const char *search_domain);
 int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr, const char *search_domain);
index 91353a63c6bc97001251c20ff31454d7a8ef703a..dab8bed1692cd6d466e33b9614172608e0290312 100644 (file)
@@ -368,15 +368,16 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
         assert(s);
         assert(domain);
 
+        /* Checks if the specified domain is something to look up on
+         * this scope. Note that this accepts non-qualified hostnames,
+         * i.e. those without any search path prefixed yet. */
+
         if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
                 return DNS_SCOPE_NO;
 
         if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family) & flags) == 0)
                 return DNS_SCOPE_NO;
 
-        if (dns_name_is_root(domain))
-                return DNS_SCOPE_NO;
-
         /* Never resolve any loopback hostname or IP address via DNS,
          * LLMNR or mDNS. Instead, always rely on synthesized RRs for
          * these. */
@@ -403,9 +404,8 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
 
         case DNS_PROTOCOL_DNS:
 
-                if ((!dns_name_is_single_label(domain) ||
-                     (!(flags & SD_RESOLVED_NO_SEARCH) && dns_scope_has_search_domains(s))) &&
-                    dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
+                /* Exclude link-local IP ranges */
+                if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
                     dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
                     dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
                     dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
@@ -443,8 +443,27 @@ int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
         assert(s);
         assert(key);
 
-        if (s->protocol == DNS_PROTOCOL_DNS)
-                return true;
+        /* Check if it makes sense to resolve the specified key on
+         * this scope. Note that this call assumes as fully qualified
+         * name, i.e. the search suffixes already appended. */
+
+        if (s->protocol == DNS_PROTOCOL_DNS) {
+
+                /* On classic DNS, lookin up non-address RRs is always
+                 * fine. (Specifically, we want to permit looking up
+                 * DNSKEY and DS records on the root and top-level
+                 * domains.) */
+                if (!dns_resource_key_is_address(key))
+                        return true;
+
+                /* However, we refuse to look up A and AAAA RRs on the
+                 * root and single-label domains, under the assumption
+                 * that those should be resolved via LLMNR or search
+                 * path only, and should not be leaked onto the
+                 * internet. */
+                return !(dns_name_is_single_label(DNS_RESOURCE_KEY_NAME(key)) ||
+                         dns_name_is_root(DNS_RESOURCE_KEY_NAME(key)));
+        }
 
         /* On mDNS and LLMNR, send A and AAAA queries only on the
          * respective scopes */
@@ -910,34 +929,13 @@ void dns_scope_dump(DnsScope *s, FILE *f) {
 DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
         assert(s);
 
-        /* Returns the list of *local* search domains -- not the
-         * global ones. */
-
         if (s->protocol != DNS_PROTOCOL_DNS)
                 return NULL;
 
         if (s->link)
                 return s->link->search_domains;
 
-        return NULL;
-}
-
-bool dns_scope_has_search_domains(DnsScope *s) {
-        assert(s);
-
-        /* Tests if there are *any* search domains suitable for this
-         * scope. This means either local or global ones */
-
-        if (s->protocol != DNS_PROTOCOL_DNS)
-                return false;
-
-        if (s->manager->search_domains)
-                return true;
-
-        if (s->link && s->link->search_domains)
-                return true;
-
-        return false;
+        return s->manager->search_domains;
 }
 
 bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
index 0480f702f855855401d83e3c28b38cc66ba66a45..b816e90cf12b5d6ffaa988da5a98055379942d91 100644 (file)
@@ -102,6 +102,5 @@ void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p);
 void dns_scope_dump(DnsScope *s, FILE *f);
 
 DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s);
-bool dns_scope_has_search_domains(DnsScope *s);
 
 bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name);