resolved: some RR types may appear only or not at all in a zone apex

Add extra checks when validating with RRSIGs. This follows recommendations from:

http://www.george-barwood.pwp.blueyonder.co.uk/DnsServer/NotesOnDNSSSEC.htm
This commit is contained in:
Lennart Poettering 2016-01-14 17:25:06 +01:00
parent 3d39e6e5d4
commit 588c53d044
3 changed files with 42 additions and 6 deletions

View File

@ -135,6 +135,17 @@ bool dns_type_may_wildcard(uint16_t type) {
DNS_TYPE_DNAME);
}
bool dns_type_apex_only(uint16_t type) {
/* Returns true for all RR types that may only appear signed in a zone apex */
return IN_SET(type,
DNS_TYPE_SOA,
DNS_TYPE_NS, /* this one can appear elsewhere, too, but not signed */
DNS_TYPE_DNSKEY,
DNS_TYPE_NSEC3PARAM);
}
bool dns_type_is_dnssec(uint16_t type) {
return IN_SET(type,
DNS_TYPE_DS,

View File

@ -132,6 +132,7 @@ bool dns_type_may_redirect(uint16_t type);
bool dns_type_is_dnssec(uint16_t type);
bool dns_type_is_obsolete(uint16_t type);
bool dns_type_may_wildcard(uint16_t type);
bool dns_type_apex_only(uint16_t type);
bool dns_class_is_pseudo(uint16_t class);
bool dns_class_is_valid_rr(uint16_t class);

View File

@ -508,14 +508,14 @@ int dnssec_verify_rrset(
DnssecResult *result) {
uint8_t wire_format_name[DNS_WIRE_FOMAT_HOSTNAME_MAX];
size_t hash_size;
void *hash;
DnsResourceRecord **list, *rr;
const char *source, *name;
gcry_md_hd_t md = NULL;
int r, md_algorithm;
size_t k, n = 0;
size_t hash_size;
void *hash;
bool wildcard;
const char *source;
assert(key);
assert(rrsig);
@ -544,8 +544,32 @@ int dnssec_verify_rrset(
return 0;
}
name = DNS_RESOURCE_KEY_NAME(key);
/* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */
if (dns_type_apex_only(rrsig->rrsig.type_covered)) {
r = dns_name_equal(rrsig->rrsig.signer, name);
if (r < 0)
return r;
if (r == 0) {
*result = DNSSEC_INVALID;
return 0;
}
}
/* OTOH DS RRs may not appear in the zone apex, but are valid everywhere else. */
if (rrsig->rrsig.type_covered == DNS_TYPE_DS) {
r = dns_name_equal(rrsig->rrsig.signer, name);
if (r < 0)
return r;
if (r > 0) {
*result = DNSSEC_INVALID;
return 0;
}
}
/* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */
r = dns_name_suffix(DNS_RESOURCE_KEY_NAME(key), rrsig->rrsig.labels, &source);
r = dns_name_suffix(name, rrsig->rrsig.labels, &source);
if (r < 0)
return r;
if (r > 0 && !dns_type_may_wildcard(rrsig->rrsig.type_covered)) {
@ -556,11 +580,11 @@ int dnssec_verify_rrset(
if (r == 1) {
/* If we stripped a single label, then let's see if that maybe was "*". If so, we are not really
* synthesized from a wildcard, we are the wildcard itself. Treat that like a normal name. */
r = dns_name_startswith(DNS_RESOURCE_KEY_NAME(key), "*");
r = dns_name_startswith(name, "*");
if (r < 0)
return r;
if (r > 0)
source = DNS_RESOURCE_KEY_NAME(key);
source = name;
wildcard = r == 0;
} else