pdns: add patch for CVE-2022-27227

Signed-off-by: Peter van Dijk <peter.van.dijk@powerdns.com>
This commit is contained in:
Peter van Dijk 2022-04-14 19:57:03 +02:00 committed by Rosen Penev
parent 8d1a786d5b
commit f618daa55f
1 changed files with 85 additions and 0 deletions

View File

@ -0,0 +1,85 @@
--- a/pdns/ixfr.cc
+++ b/pdns/ixfr.cc
@@ -174,13 +174,21 @@ vector<pair<vector<DNSRecord>, vector<DN
std::shared_ptr<SOARecordContent> masterSOA = nullptr;
vector<DNSRecord> records;
size_t receivedBytes = 0;
- int8_t ixfrInProgress = -2;
std::string reply;
+ enum transferStyle { Unknown, AXFR, IXFR } style = Unknown;
+ const unsigned int expectedSOAForAXFR = 2;
+ const unsigned int expectedSOAForIXFR = 3;
+ unsigned int masterSOACount = 0;
+
for(;;) {
- // IXFR end
- if (ixfrInProgress >= 0)
+ // IXFR or AXFR style end reached? We don't want to process trailing data after the closing SOA
+ if (style == AXFR && masterSOACount == expectedSOAForAXFR) {
+ break;
+ }
+ else if (style == IXFR && masterSOACount == expectedSOAForIXFR) {
break;
+ }
if(s.read((char*)&len, sizeof(len)) != sizeof(len))
break;
@@ -225,16 +233,31 @@ vector<pair<vector<DNSRecord>, vector<DN
return ret;
}
masterSOA = sr;
+ ++masterSOACount;
} else if (r.first.d_type == QType::SOA) {
auto sr = getRR<SOARecordContent>(r.first);
if (!sr) {
throw std::runtime_error("Error getting the content of SOA record of IXFR answer for zone '"+zone.toLogString()+"' from master '"+master.toStringWithPort()+"'");
}
- // we hit the last SOA record
- // IXFR is considered to be done if we hit the last SOA record twice
+ // we hit a marker SOA record
if (masterSOA->d_st.serial == sr->d_st.serial) {
- ixfrInProgress++;
+ ++masterSOACount;
+ }
+ }
+ // When we see the 2nd record, we can decide what the style is
+ if (records.size() == 1 && style == Unknown) {
+ if (r.first.d_type != QType::SOA) {
+ // Non-empty AXFR style has a non-SOA record following the first SOA
+ style = AXFR;
+ }
+ else if (masterSOACount == expectedSOAForAXFR) {
+ // Empty zone AXFR style: start SOA is immediately followed by end marker SOA
+ style = AXFR;
+ }
+ else {
+ // IXFR has a 2nd SOA (with different serial) following the first
+ style = IXFR;
}
}
@@ -253,7 +276,21 @@ vector<pair<vector<DNSRecord>, vector<DN
}
}
- // cout<<"Got "<<records.size()<<" records"<<endl;
+ switch (style) {
+ case IXFR:
+ if (masterSOACount != expectedSOAForIXFR) {
+ throw std::runtime_error("Incomplete IXFR transfer for '" + zone.toLogString() + "' from primary '" + master.toStringWithPort());
+ }
+ break;
+ case AXFR:
+ if (masterSOACount != expectedSOAForAXFR){
+ throw std::runtime_error("Incomplete AXFR style transfer for '" + zone.toLogString() + "' from primary '" + master.toStringWithPort());
+ }
+ break;
+ case Unknown:
+ throw std::runtime_error("Incomplete XFR for '" + zone.toLogString() + "' from primary '" + master.toStringWithPort());
+ break;
+ }
return processIXFRRecords(master, zone, records, masterSOA);
}