Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add limits to the size of received AXFR, in megabytes #4134

Merged
merged 1 commit into from
Jul 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add limits to the size of received AXFR, in megabytes
This prevents resource exhaustion in case the master is sending a
very large amount of data in an update.
  • Loading branch information
rgacogne committed Jul 7, 2016
commit a014f4c224a7b21f1c648257d1fd1128413129aa
2 changes: 2 additions & 0 deletions pdns/common_startup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions pdns/docs/pdns.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
5 changes: 5 additions & 0 deletions pdns/pdns.conf-dist
Original file line number Diff line number Diff line change
Expand Up @@ -534,4 +534,9 @@
#
# webserver-print-arguments=no

#################################
# xfr-max-received-mbytes Maximum number of megabytes received from an incoming AXFR
#
# xfr-max-received-mbytes=100


15 changes: 11 additions & 4 deletions pdns/resolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion pdns/resolver.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion pdns/slavecommunicator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down