]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Check that the first and last SOA of an AXFR are consistent
authorMark Andrews <marka@isc.org>
Mon, 15 Mar 2021 04:43:26 +0000 (15:43 +1100)
committerMark Andrews <marka@isc.org>
Thu, 13 May 2021 03:36:50 +0000 (03:36 +0000)
lib/dns/xfrin.c

index 044acc09c3a5e69ad8f3fe12288ace5fc7abe588..cc5547ea1e961599618c18b21ad21db0d334e342 100644 (file)
@@ -180,6 +180,9 @@ struct dns_xfrin_ctx {
                uint32_t current_serial;
                dns_journal_t *journal;
        } ixfr;
+
+       dns_rdata_t firstsoa;
+       unsigned char *firstsoa_data;
 };
 
 #define XFRIN_MAGIC    ISC_MAGIC('X', 'f', 'r', 'I')
@@ -565,6 +568,13 @@ redo:
                                  xfr->ixfr.request_serial, xfr->end_serial);
                        FAIL(DNS_R_UPTODATE);
                }
+               xfr->firstsoa = *rdata;
+               if (xfr->firstsoa_data != NULL) {
+                       isc_mem_free(xfr->mctx, xfr->firstsoa_data);
+               }
+               xfr->firstsoa_data = isc_mem_allocate(xfr->mctx, rdata->length);
+               memcpy(xfr->firstsoa_data, rdata->data, rdata->length);
+               xfr->firstsoa.data = xfr->firstsoa_data;
                xfr->state = XFRST_FIRSTDATA;
                break;
 
@@ -649,6 +659,16 @@ redo:
                }
                CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
                if (rdata->type == dns_rdatatype_soa) {
+                       /*
+                        * Use dns_rdata_compare instead of memcmp to
+                        * allow for case differences.
+                        */
+                       if (dns_rdata_compare(rdata, &xfr->firstsoa) != 0) {
+                               xfrin_log(xfr, ISC_LOG_ERROR,
+                                         "start and ending SOA records "
+                                         "mismatch");
+                               FAIL(DNS_R_FORMERR);
+                       }
                        CHECK(axfr_commit(xfr));
                        xfr->state = XFRST_AXFR_END;
                        break;
@@ -852,7 +872,8 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
                                  .id = (dns_messageid_t)isc_random16(),
                                  .maxrecords = dns_zone_getmaxrecords(zone),
                                  .masteraddr = *masteraddr,
-                                 .sourceaddr = *sourceaddr };
+                                 .sourceaddr = *sourceaddr,
+                                 .firstsoa = DNS_RDATA_INIT };
 
        isc_mem_attach(mctx, &xfr->mctx);
        dns_zone_iattach(zone, &xfr->zone);
@@ -1616,6 +1637,10 @@ xfrin_destroy(dns_xfrin_ctx_t *xfr) {
                dns_zone_idetach(&xfr->zone);
        }
 
+       if (xfr->firstsoa_data != NULL) {
+               isc_mem_free(xfr->mctx, xfr->firstsoa_data);
+       }
+
        isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
 }