summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-01-05 19:57:33 +0100
committerLennart Poettering <lennart@poettering.net>2016-01-05 20:10:31 +0100
commitad6c04756115809d615dede330213d73edf732a8 (patch)
tree832a20d697321d22b62cabc5b9695b231a6f04f1
parent125ae29d1bc3a6362c9bb1acddbe09fe1b274cfc (diff)
resolved,networkd: add a per-interface DNSSEC setting
This adds a DNSSEC= setting to .network files, and makes resolved honour them.
-rw-r--r--man/resolved.conf.xml10
-rw-r--r--man/systemd.network.xml18
-rw-r--r--src/libsystemd/sd-network/sd-network.c4
-rw-r--r--src/network/networkd-link.c4
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.c1
-rw-r--r--src/network/networkd-network.h1
-rw-r--r--src/resolve/resolved-conf.c35
-rw-r--r--src/resolve/resolved-dns-dnssec.c7
-rw-r--r--src/resolve/resolved-dns-dnssec.h21
-rw-r--r--src/resolve/resolved-dns-scope.c17
-rw-r--r--src/resolve/resolved-gperf.gperf12
-rw-r--r--src/resolve/resolved-link.c34
-rw-r--r--src/resolve/resolved-link.h1
-rw-r--r--src/resolve/resolved-manager.c6
-rw-r--r--src/resolve/resolved-manager.h1
-rw-r--r--src/resolve/resolved.c6
-rw-r--r--src/shared/resolve-util.c8
-rw-r--r--src/shared/resolve-util.h23
-rw-r--r--src/systemd/sd-network.h10
20 files changed, 143 insertions, 77 deletions
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index c2c277b606..3209f73bc1 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -194,6 +194,16 @@
happen regularly. On other systems it is recommended to set
<varname>DNSSEC=</varname> to
<literal>allow-downgrade</literal>.</para>
+
+ <para>In addition to this global DNSSEC setting
+ <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ also maintains per-interface DNSSEC settings. For system DNS
+ servers (see above), only the global DNSSEC setting is in
+ effect. For per-interface DNS servers the per-interface
+ setting is in effect, unless it is unset in which case the
+ global setting is used instead.</para>
+
+ <para>Defaults to off.</para>
</listitem>
</varlistentry>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 36172ae8b5..1dfa559c8b 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -301,6 +301,24 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>DNSSEC=</varname></term>
+ <listitem>
+ <para>A boolean or
+ <literal>allow-downgrade</literal>. When true, enables
+ <ulink
+ url="https://tools.ietf.org/html/rfc4033">DNSSEC</ulink>
+ DNS validation support on the link. When set to
+ <literal>allow-downgrade</literal>, compatibility with
+ non-DNSSEC capable networks is increased, by automatically
+ turning off DNSEC in this case. This option defines a
+ per-interface setting for
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
+ global <varname>DNSSEC=</varname> option. Defaults to
+ false. This setting is read by
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>LLDP=</varname></term>
<listitem>
<para>A boolean. When true, enables LLDP link receive support.
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index a63ff46c68..517b48a04f 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -143,6 +143,10 @@ _public_ int sd_network_link_get_mdns(int ifindex, char **mdns) {
return network_link_get_string(ifindex, "MDNS", mdns);
}
+_public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) {
+ return network_link_get_string(ifindex, "DNSSEC", dnssec);
+}
+
_public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
_cleanup_free_ char *s = NULL, *p = NULL;
size_t size;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 2013a8eae7..18a82fdeb9 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2871,6 +2871,10 @@ int link_save(Link *link) {
fprintf(f, "MDNS=%s\n",
resolve_support_to_string(link->network->mdns));
+ if (link->network->dnssec_mode != _DNSSEC_MODE_INVALID)
+ fprintf(f, "DNSSEC=%s\n",
+ dnssec_mode_to_string(link->network->dnssec_mode));
+
fputs("ADDRESSES=", f);
space = false;
SET_FOREACH(a, link->addresses, i) {
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index c66ca3c1cc..75a2620804 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -47,6 +47,7 @@ Network.Domains, config_parse_domains,
Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr)
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
+Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode)
Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward)
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 7544280a7a..c91531ca69 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -122,6 +122,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->llmnr = RESOLVE_SUPPORT_YES;
network->mdns = RESOLVE_SUPPORT_NO;
+ network->dnssec_mode = _DNSSEC_MODE_INVALID;
network->link_local = ADDRESS_FAMILY_IPV6;
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 91e90e6d74..7817b13cc4 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -146,6 +146,7 @@ struct Network {
ResolveSupport llmnr;
ResolveSupport mdns;
+ DnssecMode dnssec_mode;
LIST_FIELDS(Network, networks);
};
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index 6afa61fa56..88df7534c4 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -200,41 +200,6 @@ int config_parse_search_domains(
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-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c
index ff571986c0..edbd83ce05 100644
--- a/src/resolve/resolved-dns-dnssec.c
+++ b/src/resolve/resolved-dns-dnssec.c
@@ -1566,13 +1566,6 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
return 0;
}
-static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = {
- [DNSSEC_NO] = "no",
- [DNSSEC_ALLOW_DOWNGRADE] = "allow-downgrade",
- [DNSSEC_YES] = "yes",
-};
-DEFINE_STRING_TABLE_LOOKUP(dnssec_mode, DnssecMode);
-
static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
[DNSSEC_VALIDATED] = "validated",
[DNSSEC_INVALID] = "invalid",
diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h
index d818d1a906..6977faca75 100644
--- a/src/resolve/resolved-dns-dnssec.h
+++ b/src/resolve/resolved-dns-dnssec.h
@@ -28,24 +28,6 @@ typedef enum DnssecResult DnssecResult;
#include "resolved-dns-answer.h"
#include "resolved-dns-rr.h"
-enum DnssecMode {
- /* No DNSSEC validation is done */
- DNSSEC_NO,
-
- /* Validate locally, if the server knows DO, but if not,
- * don't. Don't trust the AD bit. If the server doesn't do
- * DNSSEC properly, downgrade to non-DNSSEC operation. Of
- * course, we then are vulnerable to a downgrade attack, but
- * that's life and what is configured. */
- DNSSEC_ALLOW_DOWNGRADE,
-
- /* Insist on DNSSEC server support, and rather fail than downgrading. */
- DNSSEC_YES,
-
- _DNSSEC_MODE_MAX,
- _DNSSEC_MODE_INVALID = -1
-};
-
enum DnssecResult {
/* These four are returned by dnssec_verify_rrset() */
DNSSEC_VALIDATED,
@@ -101,8 +83,5 @@ typedef enum DnssecNsecResult {
int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl);
-const char* dnssec_mode_to_string(DnssecMode m) _const_;
-DnssecMode dnssec_mode_from_string(const char *s) _pure_;
-
const char* dnssec_result_to_string(DnssecResult m) _const_;
DnssecResult dnssec_result_from_string(const char *s) _pure_;
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 13be2a3792..c96bed04b0 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -57,6 +57,23 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int
s->family = family;
s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
+ s->dnssec_mode = _DNSSEC_MODE_INVALID;
+
+ if (protocol == DNS_PROTOCOL_DNS) {
+ /* Copy DNSSEC mode from the link if it is set there,
+ * otherwise take the manager's DNSSEC mode. Note that
+ * we copy this only at scope creation time, and do
+ * not update it from the on, even if the setting
+ * changes. */
+
+ if (l)
+ s->dnssec_mode = l->dnssec_mode;
+ if (s->dnssec_mode == _DNSSEC_MODE_INVALID)
+ s->dnssec_mode = m->dnssec_mode;
+ if (s->dnssec_mode == _DNSSEC_MODE_INVALID)
+ s->dnssec_mode = DNSSEC_NO;
+ }
+
LIST_PREPEND(scopes, m->dns_scopes, s);
dns_scope_llmnr_membership(s, true);
diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf
index fb3fe9cfb1..c5ad04afd7 100644
--- a/src/resolve/resolved-gperf.gperf
+++ b/src/resolve/resolved-gperf.gperf
@@ -14,9 +14,9 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-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_resolve_support,0, offsetof(Manager, llmnr_support)
-Resolve.MulticastDNS, config_parse_resolve_support,0, offsetof(Manager, mdns_support)
-Resolve.DNSSEC, config_parse_dnssec, 0, 0
+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_resolve_support, 0, offsetof(Manager, llmnr_support)
+Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support)
+Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode)
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index 8785079de8..50d3f9096b 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -47,6 +47,8 @@ int link_new(Manager *m, Link **ret, int ifindex) {
l->ifindex = ifindex;
l->llmnr_support = RESOLVE_SUPPORT_YES;
+ l->mdns_support = RESOLVE_SUPPORT_NO;
+ l->dnssec_mode = _DNSSEC_MODE_INVALID;
r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
if (r < 0)
@@ -273,6 +275,33 @@ clear:
return r;
}
+static int link_update_dnssec_mode(Link *l) {
+ _cleanup_free_ char *m = NULL;
+ int r;
+
+ assert(l);
+
+ r = sd_network_link_get_dnssec(l->ifindex, &m);
+ if (r == -ENODATA) {
+ r = 0;
+ goto clear;
+ }
+ if (r < 0)
+ goto clear;
+
+ l->dnssec_mode = dnssec_mode_from_string(m);
+ if (l->dnssec_mode < 0) {
+ r = -EINVAL;
+ goto clear;
+ }
+
+ return 0;
+
+clear:
+ l->dnssec_mode = _DNSSEC_MODE_INVALID;
+ return r;
+}
+
static int link_update_search_domains(Link *l) {
_cleanup_strv_free_ char **domains = NULL;
char **i;
@@ -332,12 +361,15 @@ int link_update_monitor(Link *l) {
if (r < 0)
log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
- link_allocate_scopes(l);
+ r = link_update_dnssec_mode(l);
+ if (r < 0)
+ log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
r = link_update_search_domains(l);
if (r < 0)
log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
+ link_allocate_scopes(l);
link_add_rrs(l, false);
return 0;
diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h
index bb3fe8ebff..d17b57253b 100644
--- a/src/resolve/resolved-link.h
+++ b/src/resolve/resolved-link.h
@@ -69,6 +69,7 @@ struct Link {
ResolveSupport llmnr_support;
ResolveSupport mdns_support;
+ DnssecMode dnssec_mode;
DnsScope *unicast_scope;
DnsScope *llmnr_ipv4_scope;
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index ed1ac8286f..b32bad456b 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -477,6 +477,8 @@ int manager_new(Manager **ret) {
m->hostname_fd = -1;
m->llmnr_support = RESOLVE_SUPPORT_YES;
+ m->mdns_support = RESOLVE_SUPPORT_NO;
+ m->dnssec_mode = DNSSEC_NO;
m->read_resolv_conf = true;
m->need_builtin_fallbacks = true;
@@ -484,6 +486,10 @@ int manager_new(Manager **ret) {
if (r < 0)
return r;
+ r = manager_parse_config_file(m);
+ if (r < 0)
+ return r;
+
r = sd_event_default(&m->event);
if (r < 0)
return r;
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index d61804fff2..1907d2e1bc 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -47,6 +47,7 @@ struct Manager {
ResolveSupport llmnr_support;
ResolveSupport mdns_support;
+ DnssecMode dnssec_mode;
/* Network */
Hashmap *links;
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index be406b71fe..472bb32764 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -81,12 +81,6 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = manager_parse_config_file(m);
- if (r < 0) {
- log_error_errno(r, "Failed to parse configuration file: %m");
- goto finish;
- }
-
r = manager_start(m);
if (r < 0) {
log_error_errno(r, "Failed to start manager: %m");
diff --git a/src/shared/resolve-util.c b/src/shared/resolve-util.c
index 487de3e077..bf6fc26841 100644
--- a/src/shared/resolve-util.c
+++ b/src/shared/resolve-util.c
@@ -24,6 +24,7 @@
#include "string-table.h"
DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_support, resolve_support, ResolveSupport, "Failed to parse resolve support setting");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dnssec_mode, dnssec_mode, DnssecMode, "Failed to parse DNSSEC mode setting");
static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
[RESOLVE_SUPPORT_NO] = "no",
@@ -31,3 +32,10 @@ static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
[RESOLVE_SUPPORT_RESOLVE] = "resolve",
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolve_support, ResolveSupport, RESOLVE_SUPPORT_YES);
+
+static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = {
+ [DNSSEC_NO] = "no",
+ [DNSSEC_ALLOW_DOWNGRADE] = "allow-downgrade",
+ [DNSSEC_YES] = "yes",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES);
diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h
index e585c5024f..fd93a13f73 100644
--- a/src/shared/resolve-util.h
+++ b/src/shared/resolve-util.h
@@ -24,6 +24,7 @@
#include "macro.h"
typedef enum ResolveSupport ResolveSupport;
+typedef enum DnssecMode DnssecMode;
enum ResolveSupport {
RESOLVE_SUPPORT_NO,
@@ -33,7 +34,29 @@ enum ResolveSupport {
_RESOLVE_SUPPORT_INVALID = -1
};
+enum DnssecMode {
+ /* No DNSSEC validation is done */
+ DNSSEC_NO,
+
+ /* Validate locally, if the server knows DO, but if not,
+ * don't. Don't trust the AD bit. If the server doesn't do
+ * DNSSEC properly, downgrade to non-DNSSEC operation. Of
+ * course, we then are vulnerable to a downgrade attack, but
+ * that's life and what is configured. */
+ DNSSEC_ALLOW_DOWNGRADE,
+
+ /* Insist on DNSSEC server support, and rather fail than downgrading. */
+ DNSSEC_YES,
+
+ _DNSSEC_MODE_MAX,
+ _DNSSEC_MODE_INVALID = -1
+};
+
int config_parse_resolve_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_mode(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);
const char* resolve_support_to_string(ResolveSupport p) _const_;
ResolveSupport resolve_support_from_string(const char *s) _pure_;
+
+const char* dnssec_mode_to_string(DnssecMode p) _const_;
+DnssecMode dnssec_mode_from_string(const char *s) _pure_;
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index 6765be041b..00aaa102ce 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -111,13 +111,21 @@ int sd_network_link_get_ntp(int ifindex, char ***addr);
*/
int sd_network_link_get_llmnr(int ifindex, char **llmnr);
-/* Indicates whether or not MDNS should be enabled for the link
+/* Indicates whether or not MulticastDNS should be enabled for the
+ * link.
* Possible levels of support: yes, no, resolve
* Possible return codes:
* -ENODATA: networkd is not aware of the link
*/
int sd_network_link_get_mdns(int ifindex, char **mdns);
+/* Indicates whether or not DNSSEC should be enabled for the link
+ * Possible levels of support: yes, no, allow-downgrade
+ * Possible return codes:
+ * -ENODATA: networkd is not aware of the link
+ */
+int sd_network_link_get_dnssec(int ifindex, char **dnssec);
+
int sd_network_link_get_lldp(int ifindex, char **lldp);
/* Get the DNS domain names for a given link. */