Skip to content

Commit 8e54f5d

Browse files
committed
resolved: add negative trust anchro support, and add trust anchor configuration files
This adds negative trust anchor support and allows reading trust anchor data from disk, from files /etc/systemd/dnssec-trust-anchors.d/*.positive and /etc/systemd/dnssec-trust-anchros.d/*.negative, as well as the matching counterparts in /usr/lib and /run. The positive trust anchor files are more or less compatible to normal DNS zone files containing DNSKEY and DS RRs. The negative trust anchor files contain only new-line separated hostnames for which to require no signing. By default no trust anchor files are installed, in which case the compiled-in root domain DS RR is used, as before. As soon as at least one positive root anchor for the root is defined via trust anchor files this buil-in DS RR is not added though.
1 parent e48b9a6 commit 8e54f5d

File tree

6 files changed

+372
-28
lines changed

6 files changed

+372
-28
lines changed

src/resolve/resolved-dns-dnssec.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
*
3636
* TODO:
3737
*
38-
* - Make trust anchor store read additional DS+DNSKEY data from disk
3938
* - wildcard zones compatibility (NSEC/NSEC3 wildcard check is missing)
4039
* - multi-label zone compatibility
4140
* - cname/dname compatibility

src/resolve/resolved-dns-rr.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -916,32 +916,37 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
916916
break;
917917

918918
case DNS_TYPE_DNSKEY: {
919-
const char *alg;
919+
_cleanup_free_ char *alg = NULL;
920920

921-
alg = dnssec_algorithm_to_string(rr->dnskey.algorithm);
921+
r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
922+
if (r < 0)
923+
return NULL;
922924

923925
t = base64mem(rr->dnskey.key, rr->dnskey.key_size);
924926
if (!t)
925927
return NULL;
926928

927-
r = asprintf(&s, "%s %u %u %.*s%.*u %s",
929+
r = asprintf(&s, "%s %u %u %s %s",
928930
k,
929931
rr->dnskey.flags,
930932
rr->dnskey.protocol,
931-
alg ? -1 : 0, alg,
932-
alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
933+
alg,
933934
t);
934935
if (r < 0)
935936
return NULL;
936937
break;
937938
}
938939

939940
case DNS_TYPE_RRSIG: {
940-
const char *type, *alg;
941+
_cleanup_free_ char *alg = NULL;
941942
char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1];
943+
const char *type;
942944

943945
type = dns_type_to_string(rr->rrsig.type_covered);
944-
alg = dnssec_algorithm_to_string(rr->rrsig.algorithm);
946+
947+
r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg);
948+
if (r < 0)
949+
return NULL;
945950

946951
t = base64mem(rr->rrsig.signature, rr->rrsig.signature_size);
947952
if (!t)
@@ -958,12 +963,11 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
958963
/* TYPE?? follows
959964
* http://tools.ietf.org/html/rfc3597#section-5 */
960965

961-
r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %s %s %u %s %s",
966+
r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %s",
962967
k,
963968
type ?: "TYPE",
964969
type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
965-
alg ? -1 : 0, alg,
966-
alg ? 0 : 1, alg ? 0u : (unsigned) rr->rrsig.algorithm,
970+
alg,
967971
rr->rrsig.labels,
968972
rr->rrsig.original_ttl,
969973
expiration,
@@ -1131,7 +1135,7 @@ static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] =
11311135
[DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
11321136
[DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
11331137
};
1134-
DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);
1138+
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255);
11351139

11361140
static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = {
11371141
/* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
@@ -1140,4 +1144,4 @@ static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = {
11401144
[DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94",
11411145
[DNSSEC_DIGEST_SHA384] = "SHA-384",
11421146
};
1143-
DEFINE_STRING_TABLE_LOOKUP(dnssec_digest, int);
1147+
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255);

src/resolve/resolved-dns-rr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b);
279279

280280
extern const struct hash_ops dns_resource_key_hash_ops;
281281

282-
const char* dnssec_algorithm_to_string(int i) _const_;
282+
int dnssec_algorithm_to_string_alloc(int i, char **ret);
283283
int dnssec_algorithm_from_string(const char *s) _pure_;
284284

285-
const char *dnssec_digest_to_string(int i) _const_;
285+
int dnssec_digest_to_string_alloc(int i, char **ret);
286286
int dnssec_digest_from_string(const char *s) _pure_;

src/resolve/resolved-dns-transaction.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
892892

893893
/* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
894894
if (t->scope->protocol == DNS_PROTOCOL_DNS) {
895-
r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, t->key, &t->answer);
895+
r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, t->key, &t->answer);
896896
if (r < 0)
897897
return r;
898898
if (r > 0) {
@@ -1270,7 +1270,7 @@ static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *
12701270
return 0;
12711271

12721272
/* Try to get the data from the trust anchor */
1273-
r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, key, &a);
1273+
r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, key, &a);
12741274
if (r < 0)
12751275
return r;
12761276
if (r > 0) {
@@ -1328,6 +1328,14 @@ static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
13281328
if (r > 0)
13291329
return false;
13301330

1331+
/* Is this key explicitly listed as a negative trust anchor?
1332+
* If so, it's nothing we need to care about */
1333+
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(t->key));
1334+
if (r < 0)
1335+
return r;
1336+
if (r > 0)
1337+
return false;
1338+
13311339
/* The answer does not contain any RRs that match to the
13321340
* question. If so, let's see if there are any NSEC/NSEC3 RRs
13331341
* included. If not, the answer is unsigned. */
@@ -1412,6 +1420,13 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
14121420
if (dns_type_is_pseudo(rr->key->type))
14131421
continue;
14141422

1423+
/* If this RR is in the negative trust anchor, we don't need to validate it. */
1424+
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
1425+
if (r < 0)
1426+
return r;
1427+
if (r > 0)
1428+
continue;
1429+
14151430
switch (rr->key->type) {
14161431

14171432
case DNS_TYPE_RRSIG: {
@@ -1756,6 +1771,12 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
17561771
if (dns_type_is_pseudo(rr->key->type))
17571772
return -EINVAL;
17581773

1774+
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
1775+
if (r < 0)
1776+
return r;
1777+
if (r > 0)
1778+
return false;
1779+
17591780
switch (rr->key->type) {
17601781

17611782
case DNS_TYPE_RRSIG:
@@ -1893,6 +1914,12 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) {
18931914
if (dns_type_is_pseudo(t->key->type))
18941915
return -EINVAL;
18951916

1917+
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(t->key));
1918+
if (r < 0)
1919+
return r;
1920+
if (r > 0)
1921+
return false;
1922+
18961923
name = DNS_RESOURCE_KEY_NAME(t->key);
18971924

18981925
if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) {
@@ -1944,6 +1971,12 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe
19441971
* the specified RRset is authenticated (i.e. has a matching
19451972
* DS RR). */
19461973

1974+
r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
1975+
if (r < 0)
1976+
return r;
1977+
if (r > 0)
1978+
return false;
1979+
19471980
DNS_ANSWER_FOREACH(rrsig, t->answer) {
19481981
DnsTransaction *dt;
19491982
Iterator i;

0 commit comments

Comments
 (0)