pdns: add patch for CVE-2022-27227
Signed-off-by: Peter van Dijk <peter.van.dijk@powerdns.com>
This commit is contained in:
parent
8d1a786d5b
commit
f618daa55f
1 changed files with 85 additions and 0 deletions
85
net/pdns/patches/200-cve-2022-27227.patch
Normal file
85
net/pdns/patches/200-cve-2022-27227.patch
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue