]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Add limits to the size of received AXFR, in megabytes 4134/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 7 Jul 2016 14:17:22 +0000 (16:17 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 7 Jul 2016 14:17:22 +0000 (16:17 +0200)
This prevents resource exhaustion in case the master is sending a
very large amount of data in an update.

pdns/common_startup.cc
pdns/docs/pdns.xml
pdns/pdns.conf-dist
pdns/resolver.cc
pdns/resolver.hh
pdns/slavecommunicator.cc

index b9c2165de5f622c76b4ebfcbfde42940296764d8..6a10cea4c7e0c8192e5f40a28044fb725ebe6242 100644 (file)
@@ -170,6 +170,8 @@ void declareArguments()
 
   ::arg().set("include-dir","Include *.conf files from this directory");
   ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com.";
+
+  ::arg().set("xfr-max-received-mbytes", "Maximum number of megabytes received from an incoming AXFR")="100";
 }
 
 static uint64_t uptimeOfProcess(const std::string& str)
index df45dc692d71fc8cf557da9649c24fdf5857ab97..3b3b7eaf8f8fed9ef0d4dba223d35cff92b7549b 100644 (file)
@@ -17863,6 +17863,17 @@ This setting will make PowerDNS renotify the slaves after an AXFR is *received*
            <listitem><para>
              Check for wildcard URL records.
              </para></listitem></varlistentry>
+         <varlistentry>
+           <term>xfr-max-received-mbytes=...</term>
+         <listitem>
+           <para>
+             Specifies the maximum number of received megabytes allowed on an incoming AXFR update, to prevent
+              resource exhaustion. A value of 0 means no restriction.
+             The default is 100. Available since 3.4.10.
+           </para>
+         </listitem>
+       </varlistentry>
+
       </variablelist>
     </para>
   </chapter>
index b9c0bd2ee08708fecdbf7e26d391ba6f79084e06..287eee46f838d6b3ca9032c2fff4f60ae1ec38a9 100644 (file)
 #
 # webserver-print-arguments=no
 
+#################################
+# xfr-max-received-mbytes      Maximum number of megabytes received from an incoming AXFR
+#
+# xfr-max-received-mbytes=100
+
 
index 501ee2554b9960c34e9e9152118782b0b3feccee..f4e30f2a0e49708beb8645afe8606e0dc382848c 100644 (file)
@@ -379,8 +379,9 @@ AXFRRetriever::AXFRRetriever(const ComboAddress& remote,
         const string& tsigkeyname,
         const string& tsigalgorithm, 
         const string& tsigsecret,
-        const ComboAddress* laddr)
-: d_tsigkeyname(tsigkeyname), d_tsigsecret(tsigsecret), d_tsigPos(0), d_nonSignedMessages(0)
+        const ComboAddress* laddr,
+        size_t maxReceivedBytes)
+  : d_tsigkeyname(tsigkeyname), d_tsigsecret(tsigsecret), d_receivedBytes(0), d_maxReceivedBytes(maxReceivedBytes), d_tsigPos(0), d_nonSignedMessages(0)
 {
   ComboAddress local;
   if (laddr != NULL) {
@@ -461,8 +462,14 @@ int AXFRRetriever::getChunk(Resolver::res_t &res) // Implementation is making su
   int len=getLength();
   if(len<0)
     throw ResolverException("EOF trying to read axfr chunk from remote TCP client");
-  
-  timeoutReadn(len); 
+
+  if (d_maxReceivedBytes > 0 && (d_maxReceivedBytes - d_receivedBytes) < (size_t) len)
+    throw ResolverException("Reached the maximum number of received bytes during AXFR");
+
+  timeoutReadn(len);
+
+  d_receivedBytes += (uint16_t) len;
+
   MOADNSParser mdp(d_buf.get(), len);
 
   int err = parseResult(mdp, "", 0, 0, &res);
index 28fdb12a1bf3daac1aa2da14ed2388eb66269e9b..78f588b2d1ed341023ea853ad01bdf64bb6b4b94 100644 (file)
@@ -85,7 +85,8 @@ class AXFRRetriever : public boost::noncopyable
         const string& tsigkeyname=string(),
         const string& tsigalgorithm=string(),
         const string& tsigsecret=string(),
-        const ComboAddress* laddr = NULL);
+        const ComboAddress* laddr = NULL,
+        size_t maxReceivedBytes=0);
        ~AXFRRetriever();
     int getChunk(Resolver::res_t &res);  
   
@@ -104,6 +105,8 @@ class AXFRRetriever : public boost::noncopyable
     string d_tsigsecret;
     string d_prevMac; // RFC2845 4.4
     string d_signData;
+    size_t d_receivedBytes;
+    size_t d_maxReceivedBytes;
     uint32_t d_tsigPos;
     uint d_nonSignedMessages; // RFC2845 4.4
     TSIGRecordContent d_trc;
index 542c41d2176e96642b9201ca34775baef097e3b8..e068904784daea33ced3d6fa4675357600dd5903 100644 (file)
@@ -151,7 +151,7 @@ void CommunicatorClass::suck(const string &domain,const string &remote)
     vector<DNSResourceRecord> rrs;
 
     ComboAddress raddr(remote, 53);
-    AXFRRetriever retriever(raddr, domain.c_str(), tsigkeyname, tsigalgorithm, tsigsecret, (laddr.sin4.sin_family == 0) ? NULL : &laddr);
+    AXFRRetriever retriever(raddr, domain.c_str(), tsigkeyname, tsigalgorithm, tsigsecret, (laddr.sin4.sin_family == 0) ? NULL : &laddr, ((size_t) ::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024);
     Resolver::res_t recs;
     while(retriever.getChunk(recs)) {
       if(first) {