summaryrefslogtreecommitdiff
path: root/src/resolve
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-12-03 18:26:12 +0100
committerLennart Poettering <lennart@poettering.net>2015-12-03 21:17:49 +0100
commit28b9b7640603f88cb49f95609331fa5072715f15 (patch)
tree783bf5e750679fbb00fba97858d3d665c2992fbf /src/resolve
parent22f711bb6a1ca9ef20c1672a7fa077f5d3235d55 (diff)
downloadsystemd-28b9b7640603f88cb49f95609331fa5072715f15.tar.gz
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()).
Diffstat (limited to 'src/resolve')
-rw-r--r--src/resolve/resolved-dns-rr.c8
-rw-r--r--src/resolve/resolved-dns-rr.h1
-rw-r--r--src/resolve/resolved-dns-scope.c58
-rw-r--r--src/resolve/resolved-dns-scope.h1
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);