resolved: introduce support for per-interface negative trust anchors

This commit is contained in:
Lennart Poettering
2016-01-06 18:36:32 +01:00
parent bec690501e
commit 8a516214c4
11 changed files with 231 additions and 66 deletions
+63 -59
View File
@@ -123,60 +123,7 @@ static int network_link_get_string(int ifindex, const char *field, char **ret) {
return 0;
}
_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
return network_link_get_string(ifindex, "ADMIN_STATE", state);
}
_public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
return network_link_get_string(ifindex, "NETWORK_FILE", filename);
}
_public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
return network_link_get_string(ifindex, "OPER_STATE", state);
}
_public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
return network_link_get_string(ifindex, "LLMNR", llmnr);
}
_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;
int r;
assert_return(ifindex > 0, -EINVAL);
assert_return(lldp, -EINVAL);
if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0)
return -ENOMEM;
r = read_full_file(p, &s, &size);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
return r;
if (size <= 0)
return -ENODATA;
*lldp = s;
s = NULL;
return 0;
}
int sd_network_link_get_timezone(int ifindex, char **ret) {
return network_link_get_string(ifindex, "TIMEZONE", ret);
}
static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
static int network_link_get_strv(int ifindex, const char *key, char ***ret) {
_cleanup_free_ char *p = NULL, *s = NULL;
_cleanup_strv_free_ char **a = NULL;
int r;
@@ -210,24 +157,81 @@ static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
return r;
}
_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
return network_link_get_string(ifindex, "ADMIN_STATE", state);
}
_public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
return network_link_get_string(ifindex, "NETWORK_FILE", filename);
}
_public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
return network_link_get_string(ifindex, "OPER_STATE", state);
}
_public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
return network_link_get_string(ifindex, "LLMNR", llmnr);
}
_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_dnssec_negative_trust_anchors(int ifindex, char ***nta) {
return network_link_get_strv(ifindex, "DNSSEC_NTA", nta);
}
_public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
_cleanup_free_ char *s = NULL, *p = NULL;
size_t size;
int r;
assert_return(ifindex > 0, -EINVAL);
assert_return(lldp, -EINVAL);
if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0)
return -ENOMEM;
r = read_full_file(p, &s, &size);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
return r;
if (size <= 0)
return -ENODATA;
*lldp = s;
s = NULL;
return 0;
}
int sd_network_link_get_timezone(int ifindex, char **ret) {
return network_link_get_string(ifindex, "TIMEZONE", ret);
}
_public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
return network_get_link_strv("DNS", ifindex, ret);
return network_link_get_strv(ifindex, "DNS", ret);
}
_public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
return network_get_link_strv("NTP", ifindex, ret);
return network_link_get_strv(ifindex, "NTP", ret);
}
_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
return network_get_link_strv("DOMAINS", ifindex, ret);
return network_link_get_strv(ifindex, "DOMAINS", ret);
}
_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
return network_get_link_strv("CARRIER_BOUND_TO", ifindex, ret);
return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret);
}
_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
return network_get_link_strv("CARRIER_BOUND_BY", ifindex, ret);
return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret);
}
_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
+14 -1
View File
@@ -2875,6 +2875,20 @@ int link_save(Link *link) {
fprintf(f, "DNSSEC=%s\n",
dnssec_mode_to_string(link->network->dnssec_mode));
if (!set_isempty(link->network->dnssec_negative_trust_anchors)) {
const char *n;
fputs("DNSSEC_NTA=", f);
space = false;
SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) {
if (space)
fputc(' ', f);
fputs(n, f);
space = true;
}
fputc('\n', f);
}
fputs("ADDRESSES=", f);
space = false;
SET_FOREACH(a, link->addresses, i) {
@@ -2887,7 +2901,6 @@ int link_save(Link *link) {
fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen);
space = true;
}
fputc('\n', f);
fputs("ROUTES=", f);
+1
View File
@@ -48,6 +48,7 @@ Network.DNS, config_parse_strv,
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.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, offsetof(Network, dnssec_negative_trust_anchors)
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)
+55
View File
@@ -32,6 +32,7 @@
#include "networkd-network.h"
#include "networkd.h"
#include "parse-util.h"
#include "set.h"
#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
@@ -277,6 +278,8 @@ void network_free(Network *network) {
free(network->dhcp_server_dns);
free(network->dhcp_server_ntp);
set_free_free(network->dnssec_negative_trust_anchors);
free(network);
}
@@ -910,3 +913,55 @@ int config_parse_dhcp_server_ntp(
n->dhcp_server_ntp = m;
}
}
int config_parse_dnssec_negative_trust_anchors(
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 *p = rvalue;
Network *n = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
return 0;
}
for (;;) {
_cleanup_free_ char *w = NULL;
r = extract_first_word(&p, &w, NULL, 0);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
break;
}
if (r == 0)
break;
r = dns_name_is_valid(w);
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name, ignoring.", w);
continue;
}
r = set_put(n->dnssec_negative_trust_anchors, w);
if (r < 0)
return log_oom();
if (r > 0)
w = NULL;
}
return 0;
}
+2
View File
@@ -147,6 +147,7 @@ struct Network {
ResolveSupport llmnr;
ResolveSupport mdns;
DnssecMode dnssec_mode;
Set *dnssec_negative_trust_anchors;
LIST_FIELDS(Network, networks);
};
@@ -173,6 +174,7 @@ int config_parse_hostname(const char *unit, const char *filename, unsigned line,
int config_parse_timezone(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_dhcp_server_dns(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_dhcp_server_ntp(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_negative_trust_anchors(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);
/* Legacy IPv4LL support */
int config_parse_ipv4ll(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);
+24 -5
View File
@@ -1406,6 +1406,25 @@ static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags
return false;
}
static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) {
int r;
assert(t);
/* Check whether the specified name is in the the NTA
* database, either in the global one, or the link-local
* one. */
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, name);
if (r != 0)
return r;
if (!t->scope->link)
return 0;
return set_contains(t->scope->link->dnssec_negative_trust_anchors, name);
}
static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
int r;
@@ -1422,7 +1441,7 @@ static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
/* Is this key explicitly listed as a negative trust anchor?
* If so, it's nothing we need to care about */
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(t->key));
r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(t->key));
if (r < 0)
return r;
if (r > 0)
@@ -1513,7 +1532,7 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
continue;
/* If this RR is in the negative trust anchor, we don't need to validate it. */
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key));
if (r < 0)
return r;
if (r > 0)
@@ -1863,7 +1882,7 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
if (dns_type_is_pseudo(rr->key->type))
return -EINVAL;
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key));
if (r < 0)
return r;
if (r > 0)
@@ -2066,7 +2085,7 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) {
if (dns_type_is_pseudo(t->key->type))
return -EINVAL;
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(t->key));
r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(t->key));
if (r < 0)
return r;
if (r > 0)
@@ -2135,7 +2154,7 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe
* the specified RRset is authenticated (i.e. has a matching
* DS RR). */
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key));
if (r < 0)
return r;
if (r > 0)
+43
View File
@@ -82,6 +82,8 @@ Link *link_free(Link *l) {
dns_scope_free(l->mdns_ipv4_scope);
dns_scope_free(l->mdns_ipv6_scope);
set_free_free(l->dnssec_negative_trust_anchors);
free(l);
return NULL;
}
@@ -302,6 +304,43 @@ clear:
return r;
}
static int link_update_dnssec_negative_trust_anchors(Link *l) {
_cleanup_strv_free_ char **ntas = NULL;
_cleanup_set_free_free_ Set *ns = NULL;
char **i;
int r;
assert(l);
r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
if (r == -ENODATA) {
r = 0;
goto clear;
}
if (r < 0)
goto clear;
ns = set_new(&dns_name_hash_ops);
if (!ns)
return -ENOMEM;
STRV_FOREACH(i, ntas) {
r = set_put_strdup(ns, *i);
if (r < 0)
return r;
}
set_free_free(l->dnssec_negative_trust_anchors);
l->dnssec_negative_trust_anchors = ns;
ns = NULL;
return 0;
clear:
l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
return r;
}
static int link_update_search_domains(Link *l) {
_cleanup_strv_free_ char **domains = NULL;
char **i;
@@ -365,6 +404,10 @@ int link_update_monitor(Link *l) {
if (r < 0)
log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
r = link_update_dnssec_negative_trust_anchors(l);
if (r < 0)
log_warning_errno(r, "Failed to read DNSSEC negative trust anchors 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);
+1
View File
@@ -70,6 +70,7 @@ struct Link {
ResolveSupport llmnr_support;
ResolveSupport mdns_support;
DnssecMode dnssec_mode;
Set *dnssec_negative_trust_anchors;
DnsScope *unicast_scope;
DnsScope *llmnr_ipv4_scope;
+6
View File
@@ -126,6 +126,12 @@ int sd_network_link_get_mdns(int ifindex, char **mdns);
*/
int sd_network_link_get_dnssec(int ifindex, char **dnssec);
/* Returns the list of per-interface DNSSEC negative trust anchors
* Possible return codes:
* -ENODATA: networkd is not aware of the link, or has no such data
*/
int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta);
int sd_network_link_get_lldp(int ifindex, char **lldp);
/* Get the DNS domain names for a given link. */