]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
add secpoll to auth compilation & linking
authorbert hubert <bert.hubert@netherlabs.nl>
Tue, 28 Oct 2014 09:37:41 +0000 (10:37 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Tue, 28 Oct 2014 09:37:41 +0000 (10:37 +0100)
pdns/Makefile.am
pdns/secpoll-auth.cc [new file with mode: 0644]
pdns/secpoll-auth.hh [new file with mode: 0644]

index 7334fed3fb23dedbf1db29e62fa0e057819a1280..7371abb191b741f52011f9f6acb89165187fb276 100644 (file)
@@ -58,7 +58,7 @@ bind-dnssec.schema.sqlite3.sql.h \
 bindparser.cc bindlexer.c \
 backends/gsql/gsqlbackend.cc \
 backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh \
-base64.cc sillyrecords.cc \
+base64.cc sillyrecords.cc secpoll-auth.cc secpoll-auth.hh \
 base64.hh zoneparser-tng.cc dnsrecords.cc dnswriter.cc \
 rcpgenerator.cc        dnsparser.cc dns_random.hh dns_random.cc\
 randomhelper.cc namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc dnssecinfra.cc \
diff --git a/pdns/secpoll-auth.cc b/pdns/secpoll-auth.cc
new file mode 100644 (file)
index 0000000..e993690
--- /dev/null
@@ -0,0 +1,168 @@
+#include "secpoll-auth.hh"
+
+#include "logger.hh"
+#include "arguments.hh"
+#include "version.hh"
+#include "version_generated.h"
+#include "dnsparser.hh"
+#include "misc.hh"
+#include <boost/foreach.hpp>
+#include "sstuff.hh"
+#include "dnswriter.hh"
+#include "dns_random.hh"
+#include "namespaces.hh"
+#include "statbag.hh"
+#include <stdint.h>
+#ifndef PACKAGEVERSION 
+#define PACKAGEVERSION PDNS_VERSION
+#endif
+
+string g_security_message;
+
+extern StatBag S;
+
+static vector<ComboAddress> parseResolveConf()
+{
+  vector<ComboAddress> 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<string> parts;
+      stringtok(parts, line, " \t,"); // be REALLY nice
+      for(vector<string>::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<DNSResourceRecord>& ret) 
+{
+  vector<uint8_t> packet;
+
+  DNSPacketWriter pw(packet, qname, qtype);
+  pw.getHeader()->id=dns_random(0xffff);
+  pw.getHeader()->rd=1;
+
+  static vector<ComboAddress> s_servers;
+  vector<ComboAddress> servers = parseResolveConf();
+  if(!servers.empty())
+    s_servers = servers; // in case we chrooted in the meantime
+
+  if(s_servers.empty())
+    L<<Logger::Warning<<"Unable to poll PowerDNS security status, did not get any servers from resolv.conf"<<endl;
+
+  BOOST_FOREACH(ComboAddress& dest, s_servers) {
+    Socket sock(dest.sin4.sin_family, SOCK_DGRAM);
+    sock.setNonBlocking();
+    sock.sendTo(string((char*)&*packet.begin(), (char*)&*packet.end()), dest);
+    
+    string reply;
+
+    waitForData(sock.getHandle(), 2, 0);
+    try {
+    retry:
+      sock.recvFrom(reply, dest);
+      if(reply.size() > 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<DNSResourceRecord> ret;
+
+  int res=doResolve(query, QType::TXT, ret);
+
+  int security_status=0;
+
+  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<string, string> split = splitField(content, ' ');
+    
+    security_status = atoi(split.first.c_str());
+    g_security_message = split.second;
+
+  }
+  else {
+    L<<Logger::Warning<<"Could not retrieve security status update for '" PACKAGEVERSION "' on '"+query+"', RCODE = "<< RCode::to_s(res)<<endl;
+    if(security_status == 1) // it was ok, not it is unknown
+      security_status = 0;
+  }
+
+  if(security_status == 1 && first) {
+    L<<Logger::Warning << "Polled security status of version "<<PACKAGEVERSION<<" at startup, no known issues reported: " <<g_security_message<<endl;
+  }
+  if(security_status == 2) {
+    L<<Logger::Error<<"PowerDNS Security Update Recommended: "<<g_security_message<<endl;
+  }
+  else if(security_status == 3) {
+    L<<Logger::Error<<"PowerDNS Security Update Mandatory: "<<g_security_message<<endl;
+  }
+
+  S.set("security-status",security_status);
+
+}
diff --git a/pdns/secpoll-auth.hh b/pdns/secpoll-auth.hh
new file mode 100644 (file)
index 0000000..1b0c740
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef PDNS_SECPOLL_AUTH_HH
+#define PDNS_SECPOLL_AUTH_HH
+#include <time.h>
+#include "namespaces.hh"
+
+void doSecPoll(bool first);
+extern std::string g_security_message;
+
+#endif