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:
parent
3d39e6e5d4
commit
588c53d044
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue