From: bert hubert Date: Wed, 22 Oct 2014 14:55:06 +0000 (+0200) Subject: implement security polling for auth X-Git-Tag: auth-3.3.2~2^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8115a837fac21ee77bd325e61c8f85c8674016fe;p=thirdparty%2Fpdns.git implement security polling for auth --- diff --git a/pdns/Makefile.am b/pdns/Makefile.am index 52713d2d32..19441ef7c2 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -59,7 +59,8 @@ randomhelper.cc namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc dnsseci dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc dnssecsigner.cc polarrsakeyinfra.cc \ md5.hh signingpipe.cc signingpipe.hh dnslabeltext.cc lua-pdns.cc lua-auth.cc lua-auth.hh serialtweaker.cc \ ednssubnet.cc ednssubnet.hh cachecleaner.hh json.cc json.hh \ -version.hh version.cc +version.hh version.cc secpoll-auth.cc secpoll-auth.hh + # pdns_server_LDFLAGS=@moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREADFLAGS@ $(BOOST_SERIALIZATION_LDFLAGS) -rdynamic diff --git a/pdns/common_startup.cc b/pdns/common_startup.cc index 3b76f48411..10e196a28f 100644 --- a/pdns/common_startup.cc +++ b/pdns/common_startup.cc @@ -16,6 +16,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "common_startup.hh" +#include "secpoll-auth.hh" + bool g_anyToTcp; bool g_addSuperfluousNSEC3; typedef Distributor DNSDistributor; @@ -147,6 +149,7 @@ void declareArguments() ::arg().set("max-nsec3-iterations","Limit the number of NSEC3 hash iterations")="500"; // RFC5155 10.3 ::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."; } void declareStats(void) @@ -178,7 +181,7 @@ void declareStats(void) S.declare("servfail-packets","Number of times a server-failed packet was sent out"); S.declare("latency","Average number of microseconds needed to answer a question"); S.declare("timedout-packets","Number of packets which weren't answered within timeout set"); - + S.declare("security-status", "Security status based on regular polling"); S.declareRing("queries","UDP Queries Received"); S.declareRing("nxdomain-queries","Queries for non-existent records within existent domains"); S.declareRing("noerror-queries","Queries for existing records, but for type we don't have"); @@ -338,6 +341,9 @@ void mainthread() DNSPacket::s_doEDNSSubnetProcessing = ::arg().mustDo("edns-subnet-processing"); #ifndef WIN32 + + doSecPoll(true); // this must be BEFORE chroot + if(!::arg()["chroot"].empty()) { if(::arg().mustDo("master") || ::arg().mustDo("slave")) gethostbyname("a.root-servers.net"); // this forces all lookup libraries to be loaded @@ -377,8 +383,10 @@ void mainthread() for(unsigned int n=0; n < max_rthreads; ++n) pthread_create(&qtid,0,qthread, reinterpret_cast(n)); // receives packets - void *p; - pthread_join(qtid, &p); + for(;;) { + sleep(1800); + doSecPoll(false); + } L< +#include "sstuff.hh" +#include "dnswriter.hh" +#include "dns_random.hh" +#include "namespaces.hh" +#include "statbag.hh" +#ifndef PACKAGEVERSION +#define PACKAGEVERSION PDNS_VERSION +#endif + +string g_security_message; + +extern StatBag S; + +static vector parseResolveConf() +{ + vector ret; + ifstream ifs("/etc/resolv.conf"); + if(!ifs) + return ret; + + string line; + while(std::getline(ifs, line)) { + boost::trim_right_if(line, is_any_of(" \r\n\x1a")); + boost::trim_left(line); // leading spaces, let's be nice + + string::size_type tpos = line.find_first_of(";#"); + if(tpos != string::npos) + line.resize(tpos); + + if(boost::starts_with(line, "nameserver ") || boost::starts_with(line, "nameserver\t")) { + vector parts; + stringtok(parts, line, " \t,"); // be REALLY nice + for(vector::const_iterator iter = parts.begin()+1; iter != parts.end(); ++iter) { + + try { + ret.push_back(ComboAddress(*iter, 53)); + } + catch(...) + { + } + } + } + + } + + return ret; +} + +int doResolve(const string& qname, uint16_t qtype, vector& ret) +{ + vector packet; + + DNSPacketWriter pw(packet, qname, qtype); + pw.getHeader()->id=dns_random(0xffff); + pw.getHeader()->rd=1; + + static vector s_servers; + vector servers = parseResolveConf(); + if(!servers.empty()) + s_servers = servers; // in case we chrooted in the meantime + + if(s_servers.empty()) + L< sizeof(struct dnsheader)) { + struct dnsheader d; + memcpy(&d, reply.c_str(), sizeof(d)); + if(d.id != pw.getHeader()->id) + goto retry; + } + } + catch(...) { + continue; + } + MOADNSParser mdp(reply); + if(mdp.d_header.rcode == RCode::ServFail) + continue; + + + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + if(i->first.d_place == 1 && i->first.d_type==QType::TXT) { + DNSResourceRecord rr; + rr.qname = i->first.d_label; + rr.qtype = QType(i->first.d_type); + rr.content = i->first.d_content->getZoneRepresentation(); + rr.ttl=i->first.d_ttl; + ret.push_back(rr); + } + } + + return mdp.d_header.rcode; + } + return RCode::ServFail; +} + +void doSecPoll(bool first) +{ + if(::arg()["security-poll-suffix"].empty()) + return; + + struct timeval now; + gettimeofday(&now, 0); + + string query = "auth-" PACKAGEVERSION ".security-status."+::arg()["security-poll-suffix"]; + + if(*query.rbegin()!='.') + query+='.'; + + boost::replace_all(query, "+", "_"); + + vector ret; + + int res=doResolve(query, QType::TXT, ret); + + int security_status; + + if(!res && !ret.empty()) { + string content=ret.begin()->content; + if(!content.empty() && content[0]=='"' && content[content.size()-1]=='"') { + content=content.substr(1, content.length()-2); + } + + pair split = splitField(content, ' '); + + security_status = atoi(split.first.c_str()); + g_security_message = split.second; + + } + else { + L< +#include "namespaces.hh" + +void doSecPoll(bool first); +extern std::string g_security_message; + +#endif