]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: some RR types may appear only or not at all in a zone apex
authorLennart Poettering <lennart@poettering.net>
Thu, 14 Jan 2016 16:25:06 +0000 (17:25 +0100)
committerLennart Poettering <lennart@poettering.net>
Sun, 17 Jan 2016 19:44:25 +0000 (20:44 +0100)
Add extra checks when validating with RRSIGs. This follows recommendations from:

http://www.george-barwood.pwp.blueyonder.co.uk/DnsServer/NotesOnDNSSSEC.htm

src/resolve/dns-type.c
src/resolve/dns-type.h
src/resolve/resolved-dns-dnssec.c

index 47a37fa0a7577fa76f2a49e9a3e088942f25a065..058d14009abff7310ca2e35f7c8e81c7cebcd674 100644 (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,
index 747bc854e1a16046f163cc56a1a26cfba6043665..78ff71b06e2f77eb04792defffa802fc44e67264 100644 (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);
index afff979b5affd29c299ef1d3e650a10ff263c6d2..4aade4829e438e26fee798c3645ce803fd44dbd7 100644 (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