From: Wouter Wijngaards Date: Mon, 12 Mar 2018 14:34:24 +0000 (+0000) Subject: - Check IXFR start serial. X-Git-Tag: release-1.7.1rc1~84 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d1a76b55bc35a4f789739fae02c8567ef55f8343;p=thirdparty%2Funbound.git - Check IXFR start serial. git-svn-id: file:///svn/unbound/trunk@4579 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 5cdcdf9ad..94cdf25bd 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,7 @@ - tag 1.7.0rc3. - Fix #3727: Protocol name is TLS, options have been renamed but documentation is not consistent. + - Check IXFR start serial. 9 March 2018: Wouter - Fix #3598: Fix swig build issue on rhel6 based system. diff --git a/services/authzone.c b/services/authzone.c index 1da924d84..13e36b2cb 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -4032,6 +4032,56 @@ log_rrlist_position(const char* label, struct auth_chunk* rr_chunk, str, typestr); } +/** check that start serial is OK for ixfr. we are at rr_counter == 0, + * and we are going to check rr_counter == 1 (has to be type SOA) serial */ +static int +ixfr_start_serial(struct auth_chunk* rr_chunk, int rr_num, size_t rr_pos, + uint8_t* rr_dname, uint16_t rr_type, uint16_t rr_class, + uint32_t rr_ttl, uint16_t rr_rdlen, uint8_t* rr_rdata, + size_t rr_nextpos, uint32_t transfer_serial, uint32_t xfr_serial) +{ + uint32_t startserial; + /* move forward on RR */ + chunk_rrlist_gonext(&rr_chunk, &rr_num, &rr_pos, rr_nextpos); + if(chunk_rrlist_end(rr_chunk, rr_num)) { + /* no second SOA */ + verbose(VERB_OPS, "IXFR has no second SOA record"); + return 0; + } + if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos, + &rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen, + &rr_rdata, &rr_nextpos)) { + verbose(VERB_OPS, "IXFR cannot parse second SOA record"); + /* failed to parse RR */ + return 0; + } + if(rr_type != LDNS_RR_TYPE_SOA) { + verbose(VERB_OPS, "IXFR second record is not type SOA"); + return 0; + } + if(rr_rdlen < 22) { + verbose(VERB_OPS, "IXFR, second SOA has short rdlength"); + return 0; /* bad SOA rdlen */ + } + startserial = sldns_read_uint32(rr_rdata+rr_rdlen-20); + if(startserial == transfer_serial) { + /* empty AXFR, not an IXFR */ + verbose(VERB_OPS, "IXFR second serial same as first"); + return 0; + } + if(startserial != xfr_serial) { + /* wrong start serial, it does not match the serial in + * memory */ + verbose(VERB_OPS, "IXFR is from serial %u to %u but %u " + "in memory, rejecting the zone transfer", + (unsigned)startserial, (unsigned)transfer_serial, + (unsigned)xfr_serial); + return 0; + } + /* everything OK in second SOA serial */ + return 1; +} + /** apply IXFR to zone in memory. z is locked. false on failure(mallocfail) */ static int apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z, @@ -4078,6 +4128,13 @@ apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z, have_transfer_serial = 1; transfer_serial = serial; delmode = 1; /* gets negated below */ + /* check second RR before going any further */ + if(!ixfr_start_serial(rr_chunk, rr_num, rr_pos, + rr_dname, rr_type, rr_class, rr_ttl, + rr_rdlen, rr_rdata, rr_nextpos, + transfer_serial, xfr->serial)) { + return 0; + } } else if(transfer_serial == serial) { have_transfer_serial++; if(rr_counter == 1) {