using namespace std;
using namespace boost;
-bool DNSSECKeeper::haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* dpk)
+bool DNSSECKeeper::haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* dpk)
{
keyset_t keys = getKeys(zone, true);
// need to get an *active* one!
kd.content = dpk.d_key.convertToISC(5);
// now store it
- UeberBackend db;
- db.addDomainKey(name, kd);
+ d_db.addDomainKey(name, kd);
}
DNSSECPrivateKey DNSSECKeeper::getKeyById(const std::string& zname, unsigned int id)
{
- UeberBackend db;
vector<DNSBackend::KeyData> keys;
- db.getDomainKeys(zname, 0, keys);
+ d_db.getDomainKeys(zname, 0, keys);
BOOST_FOREACH(const DNSBackend::KeyData& kd, keys) {
if(kd.id != id)
continue;
void DNSSECKeeper::removeKey(const std::string& zname, unsigned int id)
{
- UeberBackend db;
- db.removeDomainKey(zname, id);
+ d_db.removeDomainKey(zname, id);
}
void DNSSECKeeper::deactivateKey(const std::string& zname, unsigned int id)
{
- UeberBackend db;
- db.deactivateDomainKey(zname, id);
+ d_db.deactivateDomainKey(zname, id);
}
void DNSSECKeeper::activateKey(const std::string& zname, unsigned int id)
{
- UeberBackend db;
- db.activateDomainKey(zname, id);
+ d_db.activateDomainKey(zname, id);
}
bool DNSSECKeeper::getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* ns3p)
{
- UeberBackend db;
+
vector<string> meta;
- db.getDomainMetadata(zname, "NSEC3PARAM", meta);
+ d_db.getDomainMetadata(zname, "NSEC3PARAM", meta);
if(meta.empty())
return false;
string descr = ns3p.getZoneRepresentation();
vector<string> meta;
meta.push_back(descr);
- UeberBackend db;
- db.setDomainMetadata(zname, "NSEC3PARAM", meta);
+ d_db.setDomainMetadata(zname, "NSEC3PARAM", meta);
}
void DNSSECKeeper::unsetNSEC3PARAM(const std::string& zname)
{
- UeberBackend db;
- db.setDomainMetadata(zname, "NSEC3PARAM", vector<string>());
+ d_db.setDomainMetadata(zname, "NSEC3PARAM", vector<string>());
}
-DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const std::string& zone, boost::tribool allOrKeyOrZone)
+DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const std::string& zone, boost::tribool allOrKeyOrZone)
{
keyset_t keyset;
- UeberBackend db;
vector<UeberBackend::KeyData> dbkeyset;
- db.getDomainKeys(zone, 0, dbkeyset);
+ d_db.getDomainKeys(zone, 0, dbkeyset);
// do db thing
//cerr<<"Here: received " <<dbkeyset.size()<<" keys"<<endl;
BOOST_FOREACH(UeberBackend::KeyData& kd, dbkeyset)
addKey(name, true, algorithm);
}
-bool getSignerFor(const std::string& qname, std::string &signer)
+bool getSignerFor(DNSSECKeeper& dk, const std::string& qname, std::string &signer)
{
- DNSSECKeeper dk;
-
signer=qname;
do {
if(dk.haveActiveKSKFor(signer))
return false;
}
-DNSKEYRecordContent getDNSKEYFor(const std::string& qname, bool withKSK, RSAContext* rc)
+// this should be able to answer with multiple keys, in case of multiple active ZSKs XXX
+DNSKEYRecordContent getDNSKEYFor(DNSSECKeeper& dk, const std::string& qname, bool withKSK, RSAContext* rc)
{
- DNSSECKeeper dk;
- cerr<<"Asked for a DNSKEY for '"<<qname<<"', withKSK="<<withKSK<<"\n";
+ // cerr<<"Asked for a DNSKEY for '"<<qname<<"', withKSK="<<withKSK<<"\n";
DNSSECPrivateKey dpk;
if(!withKSK) {
DNSSECKeeper::keyset_t zskset=dk.getKeys(qname, false);
BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
if(value.second.active) {
- cerr<<"Found a ZSK for '"<<qname<<"', key tag = "<<value.first.getDNSKEY().getTag()<<endl;
+ // cerr<<"Found a ZSK for '"<<qname<<"', key tag = "<<value.first.getDNSKEY().getTag()<<endl;
*rc=value.first.d_key;
return value.first.getDNSKEY();
}
}
}
-int getRRSIGForRRSET(const std::string signQName, uint16_t signQType, uint32_t signTTL,
+int getRRSIGForRRSET(DNSSECKeeper& dk, const std::string signQName, uint16_t signQType, uint32_t signTTL,
vector<shared_ptr<DNSRecordContent> >& toSign, RRSIGRecordContent& rrc, bool ksk)
{
if(toSign.empty())
rrc.d_labels=countLabels(signQName);
rrc.d_originalttl=signTTL;
rrc.d_siginception=getCurrentInception();;
- rrc.d_sigexpire = rrc.d_siginception + 14*86400;
+ rrc.d_sigexpire = rrc.d_siginception + 14*86400; // XXX should come from zone metadata
rrc.d_tag=0;
- if(!getSignerFor(signQName, rrc.d_signer)) {
+ if(!getSignerFor(dk, signQName, rrc.d_signer)) {
cerr<<"No signer known for '"<<signQName<<"'\n";
return -1;
}
string hash= getSHA1HashForRRSET(signQName, rrc, toSign);
- fillOutRRSIG(signQName, rrc, hash, toSign, ksk);
+ fillOutRRSIG(dk, signQName, rrc, hash, toSign, ksk);
return 0;
}
-void addSignature(const std::string signQName, const std::string& wildcardname, uint16_t signQType, uint32_t signTTL, DNSPacketWriter::Place signPlace, vector<shared_ptr<DNSRecordContent> >& toSign, DNSPacketWriter& pw)
+void addSignature(DNSSECKeeper& dk, const std::string signQName, const std::string& wildcardname, uint16_t signQType, uint32_t signTTL, DNSPacketWriter::Place signPlace, vector<shared_ptr<DNSRecordContent> >& toSign, DNSPacketWriter& pw)
{
// cerr<<"Asked to sign '"<<signQName<<"'|"<<DNSRecordContent::NumberToType(signQType)<<", "<<toSign.size()<<" records\n";
return;
for(int ksk = 0; ksk < 2; ++ksk) {
- if(getRRSIGForRRSET(wildcardname.empty() ? signQName : wildcardname, signQType, signTTL, toSign, rrc, ksk) < 0) {
+ if(getRRSIGForRRSET(dk, wildcardname.empty() ? signQName : wildcardname, signQType, signTTL, toSign, rrc, ksk) < 0) {
cerr<<"Error signing a record!"<<endl;
return;
}
map<pair<string, uint16_t>, RRSIGRecordContent> g_rrsigs;
-void fillOutRRSIG(const std::string& signQName, RRSIGRecordContent& rrc, const std::string& hash, vector<shared_ptr<DNSRecordContent> >& toSign, bool withKSK)
+void fillOutRRSIG(DNSSECKeeper& dk, const std::string& signQName, RRSIGRecordContent& rrc, const std::string& hash, vector<shared_ptr<DNSRecordContent> >& toSign, bool withKSK)
{
RSAContext rc;
- DNSKEYRecordContent drc=getDNSKEYFor(rrc.d_signer, withKSK, &rc);
+ DNSKEYRecordContent drc=getDNSKEYFor(dk, rrc.d_signer, withKSK, &rc);
rrc.d_tag = drc.getTag();
rrc.d_algorithm = drc.d_algorithm;
return d_instances.size();
}
-vector<DNSBackend *>BackendMakerClass::all()
+vector<DNSBackend *>BackendMakerClass::all(bool skipBIND)
{
vector<DNSBackend *>ret;
if(d_instances.empty())
try {
for(vector<pair<string,string> >::const_iterator i=d_instances.begin();i!=d_instances.end();++i) {
+ if(skipBIND && i->first=="bind")
+ continue;
DNSBackend *made=d_repository[i->first]->make(i->second);
if(!made)
throw AhuException("Unable to launch backend '"+i->first+"'");
public:
void report(BackendFactory *bf);
void launch(const string &instr);
- vector<DNSBackend *>all();
+ vector<DNSBackend *>all(bool skipBIND=false);
void load(const string &module);
int numLauncheable();
vector<string> getModules();
/** Must be called before attempting to access getData(). This function stuffs all resource
* records found in rrs into the data buffer. It also frees resource records queued for us.
*/
-void DNSPacket::wrapup(void)
+void DNSPacket::wrapup(DNSSECKeeper* dk)
{
if(d_wrapped) {
return;
if(d_dnssecOk) {
if(pos != d_rrs.begin() && (signQType != pos->qtype.getCode() || signQName != pos->qname)) {
- addSignature(signQName, wildcardQName, signQType, signTTL, signPlace, toSign, pw);
+ addSignature(*dk, signQName, wildcardQName, signQType, signTTL, signPlace, toSign, pw);
}
signQName= pos->qname;
wildcardQName = pos->wildcardname;
// I assume this is some dirty hack to prevent us from signing the last SOA record in an AXFR.. XXX FIXME
if(d_dnssecOk && !(d_tcp && d_rrs.rbegin()->qtype.getCode() == QType::SOA && d_rrs.rbegin()->priority == 1234)) {
// cerr<<"Last signature.. "<<d_tcp<<", "<<d_rrs.rbegin()->priority<<", "<<d_rrs.rbegin()->qtype.getCode()<<", "<< d_rrs.size()<<endl;
- addSignature(signQName, wildcardQName, signQType, signTTL, signPlace, toSign, pw);
+ addSignature(*dk, signQName, wildcardQName, signQType, signTTL, signPlace, toSign, pw);
}
if(!opts.empty() || d_dnssecOk)
#endif // WIN32
class DNSBackend;
-
-
-
+class DNSSECKeeper;
//! This class represents DNS packets, either received or to be sent.
class DNSPacket
void setQuestion(int op, const string &qdomain, int qtype); // wipes 'd', sets a random id, creates start of packet (label, type, class etc)
DTime d_dt; //!< the time this packet was created. replyPacket() copies this in for you, so d_dt becomes the time spent processing the question+answer
- void wrapup(void); // writes out queued rrs, and generates the binary packet. also shuffles. also rectifies dnsheader 'd', and copies it to the stringbuffer
+ void wrapup(DNSSECKeeper* dk=0); // writes out queued rrs, and generates the binary packet. also shuffles. also rectifies dnsheader 'd', and copies it to the stringbuffer
const char *getData(void); //!< get binary representation of packet, will call 'wrapup' for you
const char *getRaw(void); //!< provides access to the raw packet, possibly on a packet that has never been 'wrapped'
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
#include <boost/assign/list_inserter.hpp>
-
using namespace boost;
using namespace std;
using namespace boost::assign;
-
void RSAContext::create(unsigned int bits)
{
havege_state hs;
DNSKEYRecordContent makeDNSKEYFromRSAKey(const rsa_context* rc, uint8_t algorithm, uint16_t flags);
DSRecordContent makeDSFromDNSKey(const std::string& qname, const DNSKEYRecordContent& drc, int digest=1);
-bool getSignerFor(const std::string& keyrepodir, const std::string& qname, std::string &signer);
+
int countLabels(const std::string& signQName);
class RSAContext;
+class DNSSECKeeper;
-DNSKEYRecordContent getDNSKEYFor(const std::string& keyrepodir, const std::string& qname, bool withKSK, RSAContext* rc);
-void fillOutRRSIG(const std::string& signQName, RRSIGRecordContent& rrc, const std::string& hash, vector<shared_ptr<DNSRecordContent> >& toSign, bool withKSK=false);
+bool getSignerFor(DNSSECKeeper& dk, const std::string& keyrepodir, const std::string& qname, std::string &signer);
+DNSKEYRecordContent getDNSKEYFor(DNSSECKeeper& dk, const std::string& keyrepodir, const std::string& qname, bool withKSK, RSAContext* rc);
+void fillOutRRSIG(DNSSECKeeper& dk, const std::string& signQName, RRSIGRecordContent& rrc, const std::string& hash, vector<shared_ptr<DNSRecordContent> >& toSign, bool withKSK=false);
uint32_t getCurrentInception();
-void addSignature(const std::string signQName, const std::string& wildcardname, uint16_t signQType, uint32_t signTTL, DNSPacketWriter::Place signPlace, vector<shared_ptr<DNSRecordContent> >& toSign, DNSPacketWriter& pw);
-int getRRSIGForRRSET(const std::string signQName, uint16_t signQType, uint32_t signTTL,
+void addSignature(DNSSECKeeper& dk, const std::string signQName, const std::string& wildcardname, uint16_t signQType, uint32_t signTTL, DNSPacketWriter::Place signPlace, vector<shared_ptr<DNSRecordContent> >& toSign, DNSPacketWriter& pw);
+int getRRSIGForRRSET(DNSSECKeeper& dk, const std::string signQName, uint16_t signQType, uint32_t signTTL,
vector<shared_ptr<DNSRecordContent> >& toSign, RRSIGRecordContent &rrc, bool ksk);
std::string hashQNameWithSalt(unsigned int times, const std::string& salt, const std::string& qname);
#include <vector>
#include <boost/logic/tribool.hpp>
#include "dnsrecords.hh"
+#include "ueberbackend.hh"
#define PDNSSEC_MI(x) mpi_init(&d_context.x, 0)
#define PDNSSEC_MC(x) PDNSSEC_MI(x); mpi_copy(&d_context.x, const_cast<mpi*>(&orig.d_context.x))
string fname;
};
typedef std::vector<std::pair<DNSSECPrivateKey, KeyMetaData> > keyset_t;
-
+private:
+ UeberBackend d_db;
public:
+ DNSSECKeeper() : d_db("key-only"){}
bool haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* ksk=0);
keyset_t getKeys(const std::string& zone, boost::tribool allOrKeyOrZone = boost::indeterminate);
return false;
DNSResourceRecord rr;
- DNSSECKeeper dk;
-
bool haveOne=false;
DNSSECPrivateKey dpk;
- if(dk.haveActiveKSKFor(p->qdomain, &dpk)) {
+ if(d_dk.haveActiveKSKFor(p->qdomain, &dpk)) {
rr.qtype=QType::DNSKEY;
rr.ttl=3600;
rr.qname=p->qdomain;
haveOne=true;
}
- DNSSECKeeper::keyset_t zskset = dk.getKeys(p->qdomain, false);
+ DNSSECKeeper::keyset_t zskset = d_dk.getKeys(p->qdomain, false);
BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
rr.qtype=QType::DNSKEY;
rr.ttl=3600;
return false;
DNSResourceRecord rr;
- DNSSECKeeper dk;
NSEC3PARAMRecordContent ns3prc;
- if(dk.getNSEC3PARAM(p->qdomain, &ns3prc)) {
+ if(d_dk.getNSEC3PARAM(p->qdomain, &ns3prc)) {
rr.qtype=QType::NSEC3PARAM;
rr.ttl=3600;
rr.qname=p->qdomain;
*/
void PacketHandler::addNSECX(DNSPacket *p, DNSPacket *r, const string& target, const string& auth, int mode)
{
- DNSSECKeeper dk;
NSEC3PARAMRecordContent ns3rc;
cerr<<"Doing NSEC3PARAM lookup for '"<<auth<<"': ";
- if(dk.getNSEC3PARAM(auth, &ns3rc)) {
+ if(d_dk.getNSEC3PARAM(auth, &ns3rc)) {
cerr<<"Present"<<endl;
addNSEC3(p, r, target, auth, ns3rc, mode);
}
BOOST_FOREACH(records_t::value_type& iter, records) {
RRSIGRecordContent rrc;
for(int ksk =0 ; ksk < 2; ++ksk) {
- getRRSIGForRRSET(p->qdomain, iter.first, 3600, iter.second, rrc, ksk);
+ getRRSIGForRRSET(d_dk, p->qdomain, iter.first, 3600, iter.second, rrc, ksk);
rr.content=rrc.getZoneRepresentation();
r->addRecord(rr);
if(iter.first != QType::DNSKEY)
// doDNSSECProcessing(p, r);
- r->wrapup(); // needed for inserting in cache
+ r->wrapup(&d_dk); // needed for inserting in cache
if(!noCache) {
PC.insert(p,r); // in the packet cache
}
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002 PowerDNS.COM BV
+ Copyright (C) 2002 - 2011 PowerDNS.COM BV
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
#include "ueberbackend.hh"
#include "dnspacket.hh"
#include "packetcache.hh"
+#include "dnsseckeeper.hh"
using namespace std;
bool d_doIPv6AdditionalProcessing;
UeberBackend B; // every thread an own instance
+ DNSSECKeeper d_dk; // same, might even share B?
};
#endif /* PACKETHANDLER */
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2005 - 2008 PowerDNS.COM BV
+ Copyright (C) 2005 - 2011 PowerDNS.COM BV
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
pthread_mutex_t UeberBackend::instances_lock=PTHREAD_MUTEX_INITIALIZER;
sem_t UeberBackend::d_dynserialize;
-string UeberBackend::programname;
string UeberBackend::s_status;
// initially we are blocked
}
}
-
for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
if((*i)->getSOA(domain, sd, p)) {
DNSResourceRecord rr;
UeberBackend::UeberBackend(const string &pname)
{
-// programname=pname;
pthread_mutex_lock(&instances_lock);
instances.push_back(this); // report to the static list of ourself
pthread_mutex_unlock(&instances_lock);
tid=pthread_self();
stale=false;
- backends=BackendMakers().all();
+ backends=BackendMakers().all(pname=="key-only");
}
void UeberBackend::die()
static int s_s;
static string s_status;
int d_ancount;
- static string programname;
+
bool stale;
};