From 28b9b7640603f88cb49f95609331fa5072715f15 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Dec 2015 18:26:12 +0100 Subject: 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()). --- src/resolve/resolved-dns-scope.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/resolve/resolved-dns-scope.h') 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); -- cgit v1.2.3-54-g00ecf From 24710c48ed16be5fa461fbb303a744a907541daf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Dec 2015 19:51:04 +0100 Subject: resolved: introduce a dnssec_mode setting per scope The setting controls which kind of DNSSEC validation is done: none at all, trusting the AD bit, or client-side validation. For now, no validation is implemented, hence the setting doesn't do much yet, except of toggling the CD bit in the generated messages if full client-side validation is requested. --- src/resolve/resolved-conf.c | 35 ++++++++++++++++++++++++++++++++++ src/resolve/resolved-conf.h | 1 + src/resolve/resolved-dns-dnssec.c | 8 ++++++++ src/resolve/resolved-dns-dnssec.h | 20 ++++++++++++++++++- src/resolve/resolved-dns-packet.c | 4 ++-- src/resolve/resolved-dns-packet.h | 2 +- src/resolve/resolved-dns-scope.h | 2 ++ src/resolve/resolved-dns-server.h | 3 ++- src/resolve/resolved-dns-transaction.c | 2 +- src/resolve/resolved-gperf.gperf | 1 + src/resolve/resolved.conf.in | 1 + 11 files changed, 73 insertions(+), 6 deletions(-) (limited to 'src/resolve/resolved-dns-scope.h') diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 3fc7d9ae3d..1b2f3e336e 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -234,6 +234,41 @@ int config_parse_support( return 0; } +int config_parse_dnssec( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Manager *m = data; + DnssecMode mode; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + mode = dnssec_mode_from_string(rvalue); + if (mode < 0) { + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNSSEC mode '%s'. Ignoring.", rvalue); + return 0; + } + + mode = r ? DNSSEC_YES : DNSSEC_NO; + } + + m->unicast_scope->dnssec_mode = mode; + return 0; +} + int manager_parse_config_file(Manager *m) { int r; diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h index 28d2549d35..668ea02bba 100644 --- a/src/resolve/resolved-conf.h +++ b/src/resolve/resolved-conf.h @@ -36,3 +36,4 @@ const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned len int config_parse_dns_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_support(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_dnssec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 608a8a2191..bd3d2f5c58 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -25,6 +25,7 @@ #include "dns-domain.h" #include "resolved-dns-dnssec.h" #include "resolved-dns-packet.h" +#include "string-table.h" /* Open question: * @@ -697,3 +698,10 @@ finish: gcry_md_close(md); return r; } + +static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = { + [DNSSEC_NO] = "no", + [DNSSEC_TRUST] = "trust", + [DNSSEC_YES] = "yes", +}; +DEFINE_STRING_TABLE_LOOKUP(dnssec_mode, DnssecMode); diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h index 8f812bc1fb..f4cb58988a 100644 --- a/src/resolve/resolved-dns-dnssec.h +++ b/src/resolve/resolved-dns-dnssec.h @@ -21,10 +21,26 @@ along with systemd; If not, see . ***/ +typedef enum DnssecMode DnssecMode; + #include "dns-domain.h" #include "resolved-dns-answer.h" #include "resolved-dns-rr.h" +enum DnssecMode { + /* No DNSSEC validation is done */ + DNSSEC_NO, + + /* Trust the AD bit sent by the server. UNSAFE! */ + DNSSEC_TRUST, + + /* Validate locally, if the server knows DO, but if not, don't. Don't trust the AD bit */ + DNSSEC_YES, + + _DNSSEC_MODE_MAX, + _DNSSEC_MODE_INVALID = -1 +}; + enum { DNSSEC_VERIFIED, DNSSEC_INVALID, @@ -33,7 +49,6 @@ enum { DNSSEC_SIGNATURE_EXPIRED, }; - #define DNSSEC_CANONICAL_HOSTNAME_MAX (DNS_HOSTNAME_MAX + 2) int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey); @@ -47,3 +62,6 @@ int dnssec_verify_dnskey(DnsResourceRecord *dnskey, DnsResourceRecord *ds); uint16_t dnssec_keytag(DnsResourceRecord *dnskey); int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max); + +const char* dnssec_mode_to_string(DnssecMode m) _const_; +DnssecMode dnssec_mode_from_string(const char *s) _pure_; diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 2a010ef507..ea776f7916 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -65,7 +65,7 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) { return 0; } -int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) { +int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) { DnsPacket *p; DnsPacketHeader *h; int r; @@ -96,7 +96,7 @@ int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) { 1 /* rd (ask for recursion) */, 0 /* ra */, 0 /* ad */, - 0 /* cd */, + dnssec_checking_disabled /* cd */, 0 /* rcode */)); *ret = p; diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index a6b88e6c79..ffa6c44213 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -144,7 +144,7 @@ static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) { } int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t mtu); -int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu); +int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled); DnsPacket *dns_packet_ref(DnsPacket *p); DnsPacket *dns_packet_unref(DnsPacket *p); diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index b816e90cf1..15d9a1fd6f 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -26,6 +26,7 @@ typedef struct DnsScope DnsScope; #include "resolved-dns-cache.h" +#include "resolved-dns-dnssec.h" #include "resolved-dns-packet.h" #include "resolved-dns-server.h" #include "resolved-dns-zone.h" @@ -44,6 +45,7 @@ struct DnsScope { DnsProtocol protocol; int family; + DnssecMode dnssec_mode; Link *link; diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index 00366a48c9..b07fc3af3d 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -61,10 +61,11 @@ struct DnsServer { int family; union in_addr_union address; + bool marked:1; + usec_t resend_timeout; usec_t max_rtt; - bool marked:1; DnsServerFeatureLevel verified_features; DnsServerFeatureLevel possible_features; size_t received_udp_packet_max; diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 7bef4be2ad..d22acf085b 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -598,7 +598,7 @@ static int dns_transaction_make_packet(DnsTransaction *t) { if (t->sent) return 0; - r = dns_packet_new_query(&p, t->scope->protocol, 0); + r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode == DNSSEC_YES); if (r < 0) return r; diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf index 50662656d5..c815eae850 100644 --- a/src/resolve/resolved-gperf.gperf +++ b/src/resolve/resolved-gperf.gperf @@ -18,3 +18,4 @@ Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0 Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0 Resolve.Domains, config_parse_search_domains, 0, 0 Resolve.LLMNR, config_parse_support, 0, offsetof(Manager, llmnr_support) +Resolve.DNSSEC, config_parse_dnssec, 0, 0 diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in index 39ecf83217..efc9c6733a 100644 --- a/src/resolve/resolved.conf.in +++ b/src/resolve/resolved.conf.in @@ -16,3 +16,4 @@ #FallbackDNS=@DNS_SERVERS@ #Domains= #LLMNR=yes +#DNSSEC=no -- cgit v1.2.3-54-g00ecf