Maximum number of empty non-terminals to add to a zone. This is a
protection measure to avoid database explosion due to long names.
+.. _setting-max-include-depth:
+
+``max-include-depth``
+----------------------
+
+- Integer
+- Default: 20
+
+Maximum number of nested ``$INCLUDE`` directives while processing a zone file.
+Zero mean no ``$INCLUDE`` directives will be accepted.
+
.. _setting-max-generate-steps:
``max-generate-steps``
auto records = std::make_shared<recordstorage_t>();
ZoneParserTNG zpt(bbd->d_filename, bbd->d_name, s_binddirectory, d_upgradeContent);
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
DNSResourceRecord rr;
string hashed;
while (zpt.get(rr)) {
::arg().set("tcp-fast-open", "Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size")="0";
::arg().set("max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0";
+ ::arg().set("max-include-depth", "Maximum number of nested $INCLUDE directives while processing a zone file")="20";
::arg().setSwitch("upgrade-unknown-types","Transparently upgrade known TYPExxx records. Recommended to keep off, except for PowerDNS upgrades until data sources are cleaned up")="no";
::arg().setSwitch("svc-autohints", "Transparently fill ipv6hint=auto ipv4hint=auto SVC params with AAAA/A records for the target name of the record (if within the same zone)")="no";
ZoneParserTNG zpt(lines, g_rootdnsname);
/* limit the number of steps for '$GENERATE' entries */
zpt.setMaxGenerateSteps(10000);
+ zpt.setMaxIncludes(20);
DNSResourceRecord drr;
while (zpt.get(drr)) {
}
::arg().setSwitch("qname-minimization", "Use Query Name Minimization")="yes";
::arg().setSwitch("nothing-below-nxdomain", "When an NXDOMAIN exists in cache for a name with fewer labels than the qname, send NXDOMAIN without doing a lookup (see RFC 8020)")="dnssec";
::arg().set("max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0";
+ ::arg().set("max-include-depth", "Maximum nested $INCLUDE depth when loading a zone from a file")="20";
::arg().set("record-cache-shards", "Number of shards in the record cache")="1024";
::arg().set("refresh-on-ttl-perc", "If a record is requested from the cache and only this % of original TTL remains, refetch") = "0";
::arg().set("max-signature-cache-entries", "Maximum number of signatures cache entries")="";
::arg().set("rng", "Specify random number generator to use. Valid values are auto,sodium,openssl,getrandom,arc4random,urandom.")="auto";
::arg().set("max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0";
+ ::arg().set("max-include-depth", "Maximum nested $INCLUDE depth when loading a zone from a file")="20";
::arg().setSwitch("upgrade-unknown-types","Transparently upgrade known TYPExxx records. Recommended to keep off, except for PowerDNS upgrades until data sources are cleaned up")="no";
::arg().laxFile(configname.c_str());
cmdline.clear();
ZoneParserTNG zpt(tmpnam, g_rootdnsname);
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
DNSResourceRecord zrr;
map<pair<DNSName,uint16_t>, vector<DNSRecord> > grouped;
try {
connection. This number must be larger than 0 and smaller than 65536
and also smaller than `max-mthreads`.
+.. _setting-max-include-depth:
+
+``max-include-depth``
+----------------------
+
+- Integer
+- Default: 20
+
+Maximum number of nested ``$INCLUDE`` directives while processing a zone file.
+Zero mean no ``$INCLUDE`` directives will be accepted.
+
.. _setting-max-generate-steps:
``max-generate-steps``
DNSResourceRecord drr;
ZoneParserTNG zpt(lines, d_zone);
zpt.setMaxGenerateSteps(1);
+ zpt.setMaxIncludes(0);
while (zpt.get(drr)) {
DNSRecord dr(drr);
else {
ZoneParserTNG zpt(::arg()["hint-file"]);
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
DNSResourceRecord rr;
set<DNSName> seenNS;
set<DNSName> seenA;
g_log << Logger::Error << "Parsing authoritative data for zone '" << headers.first << "' from file '" << headers.second << "'" << endl;
ZoneParserTNG zpt(headers.second, DNSName(headers.first));
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
DNSResourceRecord rr;
DNSRecord dr;
while (zpt.get(rr)) {
shared_ptr<SOARecordContent> sr = nullptr;
ZoneParserTNG zpt(fname);
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
DNSResourceRecord drr;
DNSName domain;
while(zpt.get(drr)) {
BOOST_CHECK_THROW(zp.get(rr), std::exception);
}
- {
+ {
/* test invalid generate parameters: negative counter */
ZoneParserTNG zp(std::vector<std::string>({"$GENERATE -1-4/1 $.${1,2,o}.${3,4,d}.${5,6,X}.${7,8,x} 86400 IN A 1.2.3.4"}), DNSName("test"));
DNSResourceRecord rr;
BOOST_CHECK_THROW(zp.get(rr), std::exception);
}
+ {
+ /* test invalid generate parameters: counter out of bounds */
+ ZoneParserTNG zp(std::vector<std::string>({"$GENERATE 4294967296-4/1 $.${1,2,o}.${3,4,d}.${5,6,X}.${7,8,x} 86400 IN A 1.2.3.4"}), DNSName("test"));
+ DNSResourceRecord rr;
+ BOOST_CHECK_THROW(zp.get(rr), std::exception);
+ }
- {
+ {
/* test invalid generate parameters: negative stop */
ZoneParserTNG zp(std::vector<std::string>({"$GENERATE 0--4/1 $.${1,2,o}.${3,4,d}.${5,6,X}.${7,8,x} 86400 IN A 1.2.3.4"}), DNSName("test"));
DNSResourceRecord rr;
BOOST_CHECK_THROW(zp.get(rr), std::exception);
}
+ {
+ /* test invalid generate parameters: stop out of bounds */
+ ZoneParserTNG zp(std::vector<std::string>({"$GENERATE 0-4294967296/1 $.${1,2,o}.${3,4,d}.${5,6,X}.${7,8,x} 86400 IN A 1.2.3.4"}), DNSName("test"));
+ DNSResourceRecord rr;
+ BOOST_CHECK_THROW(zp.get(rr), std::exception);
+ }
+
{
/* test invalid generate parameters: negative step */
ZoneParserTNG zp(std::vector<std::string>({"$GENERATE 0-4/-1 $.${1,2,o}.${3,4,d}.${5,6,X}.${7,8,x} 86400 IN A 1.2.3.4"}), DNSName("test"));
ZoneParserTNG zpt(zonedata, zonename);
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
bool seenSOA=false;
::arg().set("zone-name","Specify an $ORIGIN in case it is not present")="";
::arg().set("named-conf","Bind 8/9 named.conf to parse")="";
::arg().set("max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0";
+ ::arg().set("max-include-depth", "Maximum level of nested $INCLUDE depth when loading a zone from a file")="20";
::arg().setCmd("help","Provide a helpful message");
::arg().setCmd("version","Print the version");
Json::array recs;
ZoneParserTNG zpt(i->filename, i->name, BP.getDirectory());
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
DNSResourceRecord rr;
obj["name"] = i->name.toString();
args.set( "domainid", "Domain ID of the first domain found (incremented afterwards)" ) = "1";
args.set( "metadata-dn", "DN under which to store the domain metadata" ) = "";
args.set( "max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0";
+ args.set( "max-include-depth", "Maximum nested $INCLUDE depth when loading a zone from a file")="20";
args.parse( argc, argv );
g_zonename = i.name;
ZoneParserTNG zpt(i.filename, i.name, BP.getDirectory());
zpt.setMaxGenerateSteps(args.asNum("max-generate-steps"));
+ zpt.setMaxIncludes(args.asNum("max-include-depth"));
DNSResourceRecord rr;
while(zpt.get(rr)) {
callback(g_domainid, rr.qname, rr.qtype.toString(), encode_non_ascii(rr.content), rr.ttl);
::arg().set("named-conf","Bind 8/9 named.conf to parse")="";
::arg().set("max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0";
+ ::arg().set("max-include-depth", "Maximum nested $INCLUDE depth when loading a zone from a file")="20";
::arg().setCmd("help","Provide a helpful message");
::arg().setCmd("version","Print the version");
ZoneParserTNG zpt(domain.filename, domain.name, BP.getDirectory());
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
DNSResourceRecord rr;
bool seenSOA=false;
string comment;
#include <boost/algorithm/string.hpp>
#include <system_error>
#include <cinttypes>
+#include <sys/stat.h>
-static string g_INstr("IN");
+const static string g_INstr("IN");
ZoneParserTNG::ZoneParserTNG(const string& fname, DNSName zname, string reldir, bool upgradeContent):
d_reldir(std::move(reldir)), d_zonename(std::move(zname)), d_defaultttl(3600),
void ZoneParserTNG::stackFile(const std::string& fname)
{
- FILE *fp=fopen(fname.c_str(), "r");
- if(!fp) {
- std::error_code ec (errno,std::generic_category());
- throw std::system_error(ec, "Unable to open file '"+fname+"': "+stringerror());
+ if (d_filestates.size() >= d_maxIncludes) {
+ std::error_code ec (0, std::generic_category());
+ throw std::system_error(ec, "Include limit reached");
+ }
+ int fd = open(fname.c_str(), O_RDONLY, 0);
+ if (fd == -1) {
+ int err = errno;
+ std::error_code ec (err, std::generic_category());
+ throw std::system_error(ec, "Unable to open file '" + fname + "': " + stringerror(err));
+ }
+ struct stat st;
+ if (fstat(fd, &st) == -1) {
+ int err = errno;
+ close(fd);
+ std::error_code ec (err, std::generic_category());
+ throw std::system_error(ec, "Unable to stat file '" + fname + "': " + stringerror(err));
+ }
+ if (!S_ISREG(st.st_mode)) {
+ close(fd);
+ std::error_code ec (0, std::generic_category());
+ throw std::system_error(ec, "File '" + fname + "': not a regular file");
+ }
+ FILE *fp = fdopen(fd, "r");
+ if (!fp) {
+ int err = errno;
+ close(fd);
+ std::error_code ec (err, std::generic_category());
+ throw std::system_error(ec, "Unable to open file '" + fname + "': " + stringerror(err));
}
filestate fs(fp, fname);
{
d_maxGenerateSteps = max;
}
+ void setMaxIncludes(size_t max)
+ {
+ d_maxIncludes = max;
+ }
private:
bool getLine();
bool getTemplateLine();
std::stack<filestate> d_filestates;
parts_t d_templateparts;
size_t d_maxGenerateSteps{0};
+ size_t d_maxIncludes{20};
int d_defaultttl;
uint32_t d_templatecounter, d_templatestop, d_templatestep;
bool d_havedollarttl;