]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Reject primary zones with an DS record at the zone apex.
authorMark Andrews <marka@isc.org>
Tue, 28 Apr 2020 05:37:19 +0000 (15:37 +1000)
committerOndřej Surý <ondrej@isc.org>
Thu, 4 Jun 2020 14:00:33 +0000 (16:00 +0200)
DS records only belong at delegation points and if present
at the zone apex are invariably the result of administrative
errors.  Additionally they can't be queried for with modern
resolvers as the parent servers will be queried.

bin/tests/system/checkzone/zones/bad-ds.db [new file with mode: 0644]
lib/dns/include/dns/result.h
lib/dns/master.c
lib/dns/result.c

diff --git a/bin/tests/system/checkzone/zones/bad-ds.db b/bin/tests/system/checkzone/zones/bad-ds.db
new file mode 100644 (file)
index 0000000..723843a
--- /dev/null
@@ -0,0 +1,4 @@
+example.       0       SOA     . . 0 0 0 0 0
+example.       0       NS      .
+example.       0       DNSKEY  257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc=
+example.       0       DS      14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
index d0df43ac14cc1149bcf5354e30abcb4550a37848..a67257a2144824d7d8d80bc89e5bf37cc3cd1595 100644 (file)
 #define DNS_R_BADSIG0          (ISC_RESULTCLASS_DNS + 116)
 #define DNS_R_TOOMANYRECORDS   (ISC_RESULTCLASS_DNS + 117)
 #define DNS_R_VERIFYFAILURE    (ISC_RESULTCLASS_DNS + 118)
+#define DNS_R_ATZONETOP                (ISC_RESULTCLASS_DNS + 119)
 
-#define DNS_R_NRESULTS 119 /*%< Number of results */
+#define DNS_R_NRESULTS 120 /*%< Number of results */
 
 /*
  * DNS wire format rcodes.
index 59a134611e55880a2572b859e530551145419ac4..8537b239e6648d6195015345725a8750e9361167 100644 (file)
@@ -339,6 +339,13 @@ static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
 static dns_name_t const ip6_arpa = DNS_NAME_INITABSOLUTE(ip6_arpa_data,
                                                         ip6_arpa_offsets);
 
+static inline bool
+dns_master_isprimary(dns_loadctx_t *lctx) {
+       return ((lctx->options & DNS_MASTER_ZONE) != 0 &&
+               (lctx->options & DNS_MASTER_SLAVE) == 0 &&
+               (lctx->options & DNS_MASTER_KEY) == 0);
+}
+
 static inline isc_result_t
 gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token, bool eol,
         dns_rdatacallbacks_t *callbacks) {
@@ -840,10 +847,7 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
         * RFC2930: TKEY and TSIG are not allowed to be loaded
         * from master files.
         */
-       if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
-           (lctx->options & DNS_MASTER_SLAVE) == 0 &&
-           dns_rdatatype_ismeta(type))
-       {
+       if (dns_master_isprimary(lctx) && dns_rdatatype_ismeta(type)) {
                (*callbacks->error)(callbacks, "%s: %s:%lu: meta RR type '%s'",
                                    "$GENERATE", source, line, gtype);
                result = DNS_R_METATYPE;
@@ -869,11 +873,8 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
                        goto error_cleanup;
                }
 
-               if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
-                   (lctx->options & DNS_MASTER_SLAVE) == 0 &&
-                   (lctx->options & DNS_MASTER_KEY) == 0 &&
-                   !dns_name_issubdomain(owner, lctx->top))
-               {
+               if (dns_master_isprimary(lctx) &&
+                   !dns_name_issubdomain(owner, lctx->top)) {
                        char namebuf[DNS_NAME_FORMATSIZE];
                        dns_name_format(owner, namebuf, sizeof(namebuf));
                        /*
@@ -1541,11 +1542,8 @@ load_text(dns_loadctx_t *lctx) {
                                                       callbacks);
                                }
                        }
-                       if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
-                           (lctx->options & DNS_MASTER_SLAVE) == 0 &&
-                           (lctx->options & DNS_MASTER_KEY) == 0 &&
-                           !dns_name_issubdomain(new_name, lctx->top))
-                       {
+                       if (dns_master_isprimary(lctx) &&
+                           !dns_name_issubdomain(new_name, lctx->top)) {
                                char namebuf[DNS_NAME_FORMATSIZE];
                                dns_name_format(new_name, namebuf,
                                                sizeof(namebuf));
@@ -1740,8 +1738,7 @@ load_text(dns_loadctx_t *lctx) {
                 * RFC1123: MD and MF are not allowed to be loaded from
                 * master files.
                 */
-               if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
-                   (lctx->options & DNS_MASTER_SLAVE) == 0 &&
+               if (dns_master_isprimary(lctx) &&
                    (type == dns_rdatatype_md || type == dns_rdatatype_mf))
                {
                        char typebuf[DNS_RDATATYPE_FORMATSIZE];
@@ -1763,10 +1760,7 @@ load_text(dns_loadctx_t *lctx) {
                 * RFC2930: TKEY and TSIG are not allowed to be loaded
                 * from master files.
                 */
-               if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
-                   (lctx->options & DNS_MASTER_SLAVE) == 0 &&
-                   dns_rdatatype_ismeta(type))
-               {
+               if (dns_master_isprimary(lctx) && dns_rdatatype_ismeta(type)) {
                        char typebuf[DNS_RDATATYPE_FORMATSIZE];
 
                        result = DNS_R_METATYPE;
@@ -1902,6 +1896,30 @@ load_text(dns_loadctx_t *lctx) {
                        }
                }
 
+               if (dns_rdatatype_atparent(type) &&
+                   dns_master_isprimary(lctx) &&
+                   dns_name_equal(ictx->current, lctx->top))
+               {
+                       char namebuf[DNS_NAME_FORMATSIZE];
+                       char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+                       dns_name_format(ictx->current, namebuf,
+                                       sizeof(namebuf));
+                       dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+                       (*callbacks->error)(
+                               callbacks,
+                               "%s:%lu: %s record at top of zone (%s)", source,
+                               line, typebuf, namebuf);
+                       result = DNS_R_ATZONETOP;
+                       if (MANYERRS(lctx, result)) {
+                               SETRESULT(lctx, result);
+                               target = target_ft;
+                               continue;
+                       } else {
+                               goto insist_and_cleanup;
+                       }
+               }
+
                if (type == dns_rdatatype_rrsig || type == dns_rdatatype_sig) {
                        covers = dns_rdata_covers(&rdata[rdcount]);
                } else {
@@ -1963,8 +1981,7 @@ load_text(dns_loadctx_t *lctx) {
                }
 
                if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
-                   lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
-                   (lctx->options & DNS_MASTER_SLAVE) == 0)
+                   lctx->warn_tcr && dns_master_isprimary(lctx))
                {
                        (*callbacks->warn)(callbacks,
                                           "%s:%lu: old style DNSSEC "
index d1457ef43a0eef8c91013a89503ae709e40afc1f..69445ad4c13591ca9043fc32b3f2e1acf22f2b9c 100644 (file)
@@ -164,6 +164,7 @@ static const char *text[DNS_R_NRESULTS] = {
        "SIG(0) in wrong location", /*%< 116 DNS_R_BADSIG0 */
        "too many records",         /*%< 117 DNS_R_TOOMANYRECORDS */
        "verify failure",           /*%< 118 DNS_R_VERIFYFAILURE */
+       "at top of zone",           /*%< 119 DNS_R_ATZONETOP */
 };
 
 static const char *ids[DNS_R_NRESULTS] = {
@@ -290,6 +291,7 @@ static const char *ids[DNS_R_NRESULTS] = {
        "DNS_R_BADSIG0",
        "DNS_R_TOOMANYRECORDS",
        "DNS_R_VERIFYFAILURE",
+       "DNS_R_ATZONETOP",
 };
 
 static const char *rcode_text[DNS_R_NRCODERESULTS] = {