Skip to content

Commit

Permalink
auth+rec secpoll: Combine secpoll result parsing code
Browse files Browse the repository at this point in the history
  • Loading branch information
pieterlexis committed Jun 24, 2019
1 parent 607f2b3 commit 2d40d42
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 55 deletions.
1 change: 1 addition & 0 deletions pdns/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ pdns_server_SOURCES = \
resolver.cc resolver.hh \
responsestats.cc responsestats.hh responsestats-auth.cc \
rfc2136handler.cc \
secpoll.cc secpoll.hh \
secpoll-auth.cc secpoll-auth.hh \
serialtweaker.cc \
sha.hh \
Expand Down
4 changes: 2 additions & 2 deletions pdns/recursordist/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ pdns_recursor_SOURCES = \
root-addresses.hh \
root-dnssec.hh \
rpzloader.cc rpzloader.hh \
secpoll-recursor.cc \
secpoll-recursor.hh \
secpoll-recursor.cc secpoll-recursor.hh \
secpoll.cc secpoll.hh \
sholder.hh \
sillyrecords.cc \
snmp-agent.hh snmp-agent.cc \
Expand Down
1 change: 1 addition & 0 deletions pdns/recursordist/secpoll.cc
1 change: 1 addition & 0 deletions pdns/recursordist/secpoll.hh
40 changes: 17 additions & 23 deletions pdns/secpoll-auth.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "namespaces.hh"
#include "statbag.hh"
#include "stubresolver.hh"
#include "secpoll.hh"
#include "dnsrecords.hh"
#include <stdint.h>
#ifndef PACKAGEVERSION
Expand All @@ -35,8 +36,9 @@ void doSecPoll(bool first)

struct timeval now;
gettimeofday(&now, 0);
string pkgv(PACKAGEVERSION);

string version = "auth-" + string(PACKAGEVERSION);
string version = "auth-" + pkgv;
string query = version.substr(0, 63) +".security-status."+::arg()["security-poll-suffix"];

if(*query.rbegin()!='.')
Expand All @@ -47,33 +49,27 @@ void doSecPoll(bool first)

int security_status = std::stoi(S.getValueStr("security-status"));

vector<DNSZoneRecord> ret;
int res=stubDoResolve(DNSName(query), QType::TXT, ret);
vector<DNSRecord> ret;
int res = stubDoResolve(DNSName(query), QType::TXT, ret);

if (res != 0) { // not NOERROR
if(security_status == 1) // it was ok, now it is unknown
S.set("security-status", 0);

string pkgv(PACKAGEVERSION);
if (std::count(pkgv.begin(), pkgv.end(), '.') > 2) {
g_log<<Logger::Warning<<"Not validating response for security status update, this is a non-release version."<<endl;
return;
}
g_log<<Logger::Warning<<"Could not retrieve security status update for '" + PACKAGEVERSION + "' on '"+ query + "', RCODE = "<< RCode::to_s(res)<<endl;
if (res == RCode::NXDomain && !isReleaseVersion(pkgv)) {
g_log<<Logger::Warning<<"Not validating response for security status update, this is a non-release version"<<endl;
return;
}

if (ret.empty()) { // empty NOERROR... wat?
if(security_status == 1) // it was ok, now it is unknown
S.set("security-status", 0);
g_log<<Logger::Warning<<"Could not retrieve security status update for '" + PACKAGEVERSION + "' on '"+ query + "', had empty answer, RCODE = "<< RCode::to_s(res)<<endl;
string security_message;

try {
processSecPoll(res, ret, security_status, security_message);
} catch(const PDNSException &pe) {
S.set("security-status", security_status);
g_log<<Logger::Warning<<"Could not retrieve security status update for '" + pkgv + "' on '"+ query + "': "<<pe.reason<<endl;
return;
}

string content=getRR<TXTRecordContent>(ret.begin()->dr)->d_text;
pair<string, string> split = splitField(unquotify(content), ' ');
security_status = std::stoi(split.first);
g_security_message = split.second;

S.set("security-status", security_status);
g_security_message = security_message;

if(security_status == 1 && first) {
g_log<<Logger::Warning << "Polled security status of version "<<PACKAGEVERSION<<" at startup, no known issues reported: " <<g_security_message<<endl;
Expand All @@ -84,6 +80,4 @@ void doSecPoll(bool first)
if(security_status == 3) {
g_log<<Logger::Error<<"PowerDNS Security Update Mandatory: "<<g_security_message<<endl;
}

S.set("security-status", security_status);
}
50 changes: 20 additions & 30 deletions pdns/secpoll-recursor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "arguments.hh"
#include "version.hh"
#include "validate-recursor.hh"
#include "secpoll.hh"

#include <stdint.h>
#ifndef PACKAGEVERSION
Expand Down Expand Up @@ -36,7 +37,7 @@ void doSecPoll(time_t* last_secpoll)
}

vector<DNSRecord> ret;

string version = "recursor-" +pkgv;
string qstring(version.substr(0, 63)+ ".security-status."+::arg()["security-poll-suffix"]);

Expand All @@ -48,7 +49,7 @@ void doSecPoll(time_t* last_secpoll)

vState state = Indeterminate;
DNSName query(qstring);
int res=sr.beginResolve(query, QType(QType::TXT), 1, ret);
int res = sr.beginResolve(query, QType(QType::TXT), 1, ret);

if (g_dnssecmode != DNSSECMode::Off && res) {
state = sr.getValidationState();
Expand All @@ -61,44 +62,33 @@ void doSecPoll(time_t* last_secpoll)
return;
}

if (res != 0) { // Not NOERROR
if(g_security_status == 1) // it was ok, now it is unknown
g_security_status = 0;

if (std::count(pkgv.begin(), pkgv.end(), '.') > 2) {
g_log<<Logger::Warning<<"Ignoring response for security status update, this is a non-release version."<<endl;
return;
}
g_log<<Logger::Warning<<"Could not retrieve security status update for '" +pkgv+ "' on '"<<query<<"', RCODE = "<< RCode::to_s(res)<<endl;
if (res == RCode::NXDomain && !isReleaseVersion(pkgv)) {
g_log<<Logger::Warning<<"Not validating response for security status update, this is a non-release version"<<endl;
return;
}

if (ret.empty()) { // Empty NOERROR
if(g_security_status == 1) // it was ok, now it is unknown
g_security_status = 0;
g_log<<Logger::Warning<<"Could not retrieve security status update for '" +pkgv+ "' on '"<<query<<"', had empty answer, RCODE = "<< RCode::to_s(res)<<endl;
string security_message;
int security_status = g_security_status;

try {
processSecPoll(res, ret, security_status, security_message);
} catch(const PDNSException &pe) {
g_security_status = security_status;
g_log<<Logger::Warning<<"Could not retrieve security status update for '" << pkgv << "' on '"<< query << "': "<<pe.reason<<endl;
return;
}

string content;
for(const auto&r : ret) {
if(r.d_type == QType::TXT)
content = r.d_content->getZoneRepresentation();
}
g_security_message = security_message;

if(!content.empty() && content[0]=='"' && content[content.size()-1]=='"') {
content=content.substr(1, content.length()-2);
if(g_security_status != 1 && security_status == 1) {
g_log<<Logger::Warning << "Polled security status of version "<<pkgv<<", no known issues reported: " <<g_security_message<<endl;
}

pair<string, string> split = splitField(content, ' ');

g_security_status = std::stoi(split.first);
g_security_message = split.second;

if(g_security_status == 2) {
if(security_status == 2) {
g_log<<Logger::Error<<"PowerDNS Security Update Recommended: "<<g_security_message<<endl;
}
else if(g_security_status == 3) {
if(security_status == 3) {
g_log<<Logger::Error<<"PowerDNS Security Update Mandatory: "<<g_security_message<<endl;
}

g_security_status = security_status;
}
73 changes: 73 additions & 0 deletions pdns/secpoll.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* This file is part of PowerDNS or dnsdist.
* Copyright -- PowerDNS.COM B.V. and its contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* In addition, for the avoidance of any doubt, permission is granted to
* link this program with OpenSSL and to (re)distribute the binaries
* produced as the result of such linking.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <string>
#include <vector>
#include "dnsrecords.hh"
#include "pdnsexception.hh"
#include "misc.hh"

bool isReleaseVersion(const std::string &version) {
return std::count(version.begin(), version.end(), '.') == 2;
}

void processSecPoll(const int res, const std::vector<DNSRecord> &ret, int &secPollStatus, std::string &secPollMessage) {
secPollMessage.clear();
if (res != 0) { // not NOERROR
if(secPollStatus == 1) // it was ok, now it is unknown
secPollStatus = 0;
throw PDNSException("RCODE was not NOERROR but " + RCode::to_s(res));
}

if (ret.empty()) { // empty NOERROR... wat?
if(secPollStatus == 1) // it was ok, now it is unknown
secPollStatus = 0;
throw PDNSException("Had empty answer on NOERROR RCODE");
}

DNSRecord record;
for (auto const &r: ret) {
if (r.d_type == QType::TXT && r.d_place == DNSResourceRecord::Place::ANSWER) {
record = r;
break;
}
}

if (record.d_name.empty()) {
throw PDNSException("No TXT record found in response");
}

auto recordContent = getRR<TXTRecordContent>(record);
if (recordContent == nullptr) {
throw PDNSException("Could not parse TXT record content");
}
string content = recordContent->d_text;

pair<string, string> split = splitField(unquotify(content), ' ');

try {
secPollStatus = std::stoi(split.first);
} catch (const std::exception &e) {
throw PDNSException(std::string("Could not parse status number: ") + e.what());
}
secPollMessage = split.second;
}
36 changes: 36 additions & 0 deletions pdns/secpoll.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* This file is part of PowerDNS or dnsdist.
* Copyright -- PowerDNS.COM B.V. and its contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* In addition, for the avoidance of any doubt, permission is granted to
* link this program with OpenSSL and to (re)distribute the binaries
* produced as the result of such linking.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <string>
#include <vector>
#include "dnsrecords.hh"

/* Parses the result of a security poll, will throw a PDNSException when it could not be parsed, secPollStatus is
* set correctly regardless whether or not an exception was thrown.
*
* res: DNS Rcode result from the secpoll
* ret: Records returned during secpoll
* secPollStatus: The actual secpoll status, pass the current status in here and it is changed to the new status
* secPollMessage: Will be cleared and filled with the message from the secpoll message
*/
void processSecPoll(const int res, const std::vector<DNSRecord> &ret, int &secPollStatus, std::string &secPollMessage);
bool isReleaseVersion(const std::string &version);
9 changes: 9 additions & 0 deletions pdns/stubresolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,12 @@ int stubDoResolve(const DNSName& qname, uint16_t qtype, vector<DNSZoneRecord>& r
}
return RCode::ServFail;
}

int stubDoResolve(const DNSName& qname, uint16_t qtype, vector<DNSRecord>& ret) {
vector<DNSZoneRecord> ret2;
int res = stubDoResolve(qname, qtype, ret2);
for (const auto &r : ret2) {
ret.push_back(r.dr);
}
return res;
}
1 change: 1 addition & 0 deletions pdns/stubresolver.hh
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
void stubParseResolveConf();
bool resolversDefined();
int stubDoResolve(const DNSName& qname, uint16_t qtype, vector<DNSZoneRecord>& ret);
int stubDoResolve(const DNSName& qname, uint16_t qtype, vector<DNSRecord>& ret);

0 comments on commit 2d40d42

Please sign in to comment.