diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-12-03 18:26:12 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-12-03 21:17:49 +0100 |
commit | 28b9b7640603f88cb49f95609331fa5072715f15 (patch) | |
tree | 783bf5e750679fbb00fba97858d3d665c2992fbf | |
parent | 22f711bb6a1ca9ef20c1672a7fa077f5d3235d55 (diff) |
resolved: rework how we allow allow queries to be dispatched to scopes
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()).
-rw-r--r-- | src/resolve/resolved-dns-rr.c | 8 | ||||
-rw-r--r-- | src/resolve/resolved-dns-rr.h | 1 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 58 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.h | 1 |
4 files changed, 37 insertions, 31 deletions
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index b109934d3a..934a18334c 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -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; diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h index adaca962fc..b82fa77562 100644 --- a/src/resolve/resolved-dns-rr.h +++ b/src/resolve/resolved-dns-rr.h @@ -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); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 91353a63c6..dab8bed169 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -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) { diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index 0480f702f8..b816e90cf1 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -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); |