aes/aescrypt.c aes/aes.h aes/aeskey.c aes/aes_modes.c aes/aesopt.h \
aes/aestab.c aes/aestab.h aes/brg_endian.h aes/brg_types.h aes/dns_random.cc \
randomhelper.cc namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc dnssecinfra.cc \
-dnsseckeeper.hh dnssecinfra.hh base32.hh
+dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc
#
pdns_server_LDFLAGS=@moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREADFLAGS@ $(BOOST_FILESYSTEM_LDFLAGS) $(BOOST_SYSTEM_LDFLAGS) -Lext/polarssl/library
backends/bind/bindparser.cc backends/bind/bindlexer.c \
backends/gsql/gsqlbackend.cc \
backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh zoneparser-tng.cc \
- dynlistener.cc
+ dynlistener.cc dns.cc
pdnssec_LDFLAGS=@moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREADFLAGS@ -Lext/polarssl/library/
pdnssec_LDADD=$(BOOST_FILESYSTEM_LIBS) $(BOOST_SYSTEM_LIBS) -lpolarssl $(BOOST_PROGRAM_OPTIONS_LIBS)
#include <boost/algorithm/string.hpp>
#include <sstream>
#include <boost/foreach.hpp>
+#include <boost/format.hpp>
using namespace boost;
void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial)
d_ListDomainKeysQuery = "select cryptokeys.id, flags, active, content from domains, cryptokeys where domain_id=domains.id and name='%s'";
d_GetDomainMetadataQuery = "select content from domains, domainmetadata where domain_id=domains.id and name='%s' and domainmetadata.kind='%s'";
+ d_ClearDomainMetadataQuery = "delete from domainmetadata where domain_id=(select id from domains where name='%s') and domainmetadata.kind='%s'";
d_SetDomainMetadataQuery = "insert into domainmetadata (domain_id, kind, content) select id, '%s', '%s' from domains where name='%s'";
}
bool GSQLBackend::setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta)
{
char output[16384];
- snprintf(output,sizeof(output)-1,d_SetDomainMetadataQuery.c_str(),
- sqlEscape(kind).c_str(), sqlEscape(*meta.begin()).c_str(), sqlEscape(name).c_str());
+
+ if(!meta.empty())
+ snprintf(output,sizeof(output)-1,d_SetDomainMetadataQuery.c_str(),
+ sqlEscape(kind).c_str(), sqlEscape(*meta.begin()).c_str(), sqlEscape(name).c_str());
+
+ string clearQuery = (boost::format(d_ClearDomainMetadataQuery) % sqlEscape(name) % sqlEscape(kind)).str();
try {
- d_db->doCommand(output);
+ d_db->doCommand(clearQuery);
+ if(!meta.empty())
+ d_db->doCommand(output);
}
catch (SSqlException &e) {
throw AhuException("GSQLBackend unable to store metadata key: "+e.txtReason());
}
+
return true;
}
string d_AddDomainKeyQuery;
string d_ListDomainKeysQuery;
string d_GetDomainMetadataQuery;
+ string d_ClearDomainMetadataQuery;
string d_SetDomainMetadataQuery;
protected:
bool d_dnssecQueries;
::arg().set("webserver-address","IP Address of webserver to listen on")="127.0.0.1";
::arg().set("webserver-port","Port of webserver to listen on")="8081";
::arg().set("webserver-password","Password required for accessing the webserver")="";
- ::arg().set("key-repository", "Where DNSSEC keying material lives")="./keys";
::arg().setSwitch("out-of-zone-additional-processing","Do out of zone additional processing")="yes";
::arg().setSwitch("do-ipv6-additional-processing", "Do AAAA additional processing")="no";
bits = keyOrZone ? 2048 : 1024;
DNSSECPrivateKey dpk;
dpk.d_key.create(bits);
-
+ addKey(name, keyOrZone, dpk, active);
+}
+
+void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, const DNSSECPrivateKey& dpk, bool active)
+{
DNSBackend::KeyData kd;
kd.flags = 256 + keyOrZone;
kd.active = active;
- kd.content = dpk.d_key.convertToISC(algorithm);
+ kd.content = dpk.d_key.convertToISC(5);
// now store it
UeberBackend db;
return dpk;
}
throw runtime_error("Can't find a key with id "+lexical_cast<string>(id)+" for zone '"+zname+"'");
-
-
}
meta.push_back(descr);
UeberBackend db;
db.setDomainMetadata(zname, "NSEC3PARAM", meta);
-
- // XXX do db
}
void DNSSECKeeper::unsetNSEC3PARAM(const std::string& zname)
{
- // XXX do db
+ UeberBackend db;
+ db.setDomainMetadata(zname, "NSEC3PARAM", vector<string>());
}
addKey(name, true, algorithm);
}
+bool getSignerFor(const std::string& qname, std::string &signer)
+{
+ DNSSECKeeper dk;
+
+ signer=qname;
+ do {
+ if(dk.haveActiveKSKFor(signer))
+ return true;
+ } while(chopOff(signer));
+ return false;
+}
+
+DNSKEYRecordContent getDNSKEYFor(const std::string& qname, bool withKSK, RSAContext* rc)
+{
+ DNSSECKeeper dk;
+ 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;
+ *rc=value.first.d_key;
+ return value.first.getDNSKEY();
+ }
+ else
+ cerr<<"Found an inactive ZSK for '"<<qname<<"', key tag = "<<value.first.getDNSKEY().getTag()<<endl;
+ }
+ cerr<<"Could not find an active ZSK for '"<<qname<<"'"<<endl;
+ exit(1);
+ }
+ else if(dk.haveActiveKSKFor(qname, &dpk)) {
+ cerr<<"Found a KSK for '"<<qname<<"'"<<endl;
+ *rc=dpk.d_key;
+ return dpk.getDNSKEY();
+ } else {
+ cerr<<"DID NOT FIND A ZSK for '"<<qname<<"'"<<endl;
+ exit(1);
+ }
+}
+
+int getRRSIGForRRSET(const std::string signQName, uint16_t signQType, uint32_t signTTL,
+ vector<shared_ptr<DNSRecordContent> >& toSign, RRSIGRecordContent& rrc, bool ksk)
+{
+ if(toSign.empty())
+ return -1;
+
+ rrc.d_type=signQType;
+
+ // d_algorithm gets filled out by fillOutRRSIG, since it gets the key
+ rrc.d_labels=countLabels(signQName);
+ rrc.d_originalttl=signTTL;
+ rrc.d_siginception=getCurrentInception();;
+ rrc.d_sigexpire = rrc.d_siginception + 14*86400;
+
+ rrc.d_tag=0;
+ if(!getSignerFor(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);
+ 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)
+{
+ // cerr<<"Asked to sign '"<<signQName<<"'|"<<DNSRecordContent::NumberToType(signQType)<<", "<<toSign.size()<<" records\n";
+
+ RRSIGRecordContent rrc;
+ if(toSign.empty())
+ return;
+
+ for(int ksk = 0; ksk < 2; ++ksk) {
+ if(getRRSIGForRRSET(wildcardname.empty() ? signQName : wildcardname, signQType, signTTL, toSign, rrc, ksk) < 0) {
+ cerr<<"Error signing a record!"<<endl;
+ return;
+ }
+
+ pw.startRecord(signQName, QType::RRSIG, 3600, 1,
+ signQType==QType::DNSKEY ? DNSPacketWriter:: ANSWER : signPlace);
+ rrc.toPacket(pw);
+
+ pw.commit();
+ if(signQType != QType::DNSKEY)
+ break;
+ }
+
+ toSign.clear();
+}
+
+// XXXX FIXME THINK ABOUT LOCKING HERE
+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)
+{
+ RSAContext rc;
+
+ DNSKEYRecordContent drc=getDNSKEYFor(rrc.d_signer, withKSK, &rc);
+ rrc.d_tag = drc.getTag();
+ rrc.d_algorithm = drc.d_algorithm;
+
+ if(g_rrsigs.count(make_pair(hash, rrc.d_tag))) {
+ // cerr<<"RRSIG cache hit !"<<endl;
+ rrc = g_rrsigs[make_pair(hash, rrc.d_tag)];
+ return;
+ }
+
+ string realhash=getSHA1HashForRRSET(signQName, rrc, toSign);
+
+ unsigned char signature[mpi_size(&rc.getContext().N)];
+
+ int ret=rsa_pkcs1_sign(&rc.getContext(), RSA_PRIVATE, SIG_RSA_SHA1, 20, (unsigned char*) realhash.c_str(), signature);
+
+ if(ret!=0) {
+ cerr<<"signing returned: "<<ret<<endl;
+ exit(1);
+ }
+
+ rrc.d_signature.assign((char*)signature, sizeof(signature));
+
+ g_rrsigs[make_pair(hash, rrc.d_tag)] = rrc;
+
+}
throw runtime_error("Key generation failed");
}
-std::string RSAContext::convertToISC(unsigned int algorithm)
+std::string RSAContext::convertToISC(unsigned int algorithm) const
{
string ret;
- typedef vector<pair<string, mpi*> > outputs_t;
+ typedef vector<pair<string, const mpi*> > outputs_t;
outputs_t outputs;
push_back(outputs)("Modulus", &d_context.N)("PublicExponent",&d_context.E)
("PrivateExponent",&d_context.D)
return drc;
}
-bool getSignerFor(const std::string& keyRepositoryDir, const std::string& qname, std::string &signer)
-{
- DNSSECKeeper dk(keyRepositoryDir);
-
- signer=qname;
- do {
- if(dk.haveActiveKSKFor(signer))
- return true;
- } while(chopOff(signer));
- return false;
-}
int countLabels(const std::string& signQName)
{
-DNSKEYRecordContent getDNSKEYFor(const std::string& keyRepositoryDir, const std::string& qname, bool withKSK, RSAContext* rc)
-{
- DNSSECKeeper dk(keyRepositoryDir);
- 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;
- *rc=value.first.d_key;
- return value.first.getDNSKEY();
- }
- else
- cerr<<"Found an inactive ZSK for '"<<qname<<"', key tag = "<<value.first.getDNSKEY().getTag()<<endl;
- }
- cerr<<"Could not find an active ZSK for '"<<qname<<"'"<<endl;
- exit(1);
- }
- else if(dk.haveActiveKSKFor(qname, &dpk)) {
- cerr<<"Found a KSK for '"<<qname<<"'"<<endl;
- *rc=dpk.d_key;
- return dpk.getDNSKEY();
- } else {
- cerr<<"DID NOT FIND A ZSK for '"<<qname<<"'"<<endl;
- exit(1);
- }
-}
-
-// XXXX FIXME THINK ABOUT LOCKING HERE
-map<pair<string, uint16_t>, RRSIGRecordContent> g_rrsigs;
-
-void fillOutRRSIG(const std::string& keyrepodir, const std::string& signQName, RRSIGRecordContent& rrc, const std::string& hash, vector<shared_ptr<DNSRecordContent> >& toSign, bool withKSK)
-{
- RSAContext rc;
-
- DNSKEYRecordContent drc =getDNSKEYFor(keyrepodir, rrc.d_signer, withKSK, &rc);
- rrc.d_tag = drc.getTag();
- rrc.d_algorithm = drc.d_algorithm;
-
- if(g_rrsigs.count(make_pair(hash, rrc.d_tag))) {
- // cerr<<"RRSIG cache hit !"<<endl;
- rrc = g_rrsigs[make_pair(hash, rrc.d_tag)];
- return;
- }
-
- string realhash=getSHA1HashForRRSET(signQName, rrc, toSign);
-
- unsigned char signature[mpi_size(&rc.getContext().N)];
-
- int ret=rsa_pkcs1_sign(&rc.getContext(), RSA_PRIVATE, SIG_RSA_SHA1, 20, (unsigned char*) realhash.c_str(), signature);
-
- if(ret!=0) {
- cerr<<"signing returned: "<<ret<<endl;
- exit(1);
- }
-
- rrc.d_signature.assign((char*)signature, sizeof(signature));
-
- g_rrsigs[make_pair(hash, rrc.d_tag)] = rrc;
-
-}
-
uint32_t getCurrentInception()
{
uint32_t now = time(0);
}
-int getRRSIGForRRSET(const std::string& keyrepodir, const std::string signQName, uint16_t signQType, uint32_t signTTL,
- vector<shared_ptr<DNSRecordContent> >& toSign, RRSIGRecordContent& rrc, bool ksk)
-{
- if(toSign.empty())
- return -1;
-
- rrc.d_type=signQType;
-
- // d_algorithm gets filled out by fillOutRRSIG, since it gets the key
- rrc.d_labels=countLabels(signQName);
- rrc.d_originalttl=signTTL;
- rrc.d_siginception=getCurrentInception();;
- rrc.d_sigexpire = rrc.d_siginception + 14*86400;
-
- rrc.d_tag=0;
- if(!getSignerFor(keyrepodir, signQName, rrc.d_signer)) {
- cerr<<"No signer known for '"<<signQName<<"'\n";
- return -1;
- }
-
- string hash= getSHA1HashForRRSET(signQName, rrc, toSign);
- fillOutRRSIG(keyrepodir, signQName, rrc, hash, toSign, ksk);
- return 0;
-}
-
-void addSignature(const std::string& keyrepodir, 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";
-
- RRSIGRecordContent rrc;
- if(toSign.empty())
- return;
-
- for(int ksk = 0; ksk < 2; ++ksk) {
- if(getRRSIGForRRSET(keyrepodir, wildcardname.empty() ? signQName : wildcardname, signQType, signTTL, toSign, rrc, ksk) < 0) {
- cerr<<"Error signing a record!"<<endl;
- return;
- }
-
- pw.startRecord(signQName, QType::RRSIG, 3600, 1,
- signQType==QType::DNSKEY ? DNSPacketWriter:: ANSWER : signPlace);
- rrc.toPacket(pw);
-
- pw.commit();
- if(signQType != QType::DNSKEY)
- break;
- }
-
- toSign.clear();
-}
-
std::string hashQNameWithSalt(unsigned int times, const std::string& salt, const std::string& qname)
{
class RSAContext;
DNSKEYRecordContent getDNSKEYFor(const std::string& keyrepodir, const std::string& qname, bool withKSK, RSAContext* rc);
-void fillOutRRSIG(const std::string& keyrepodir, const std::string& signQName, RRSIGRecordContent& rrc, const std::string& hash, vector<shared_ptr<DNSRecordContent> >& toSign, bool withKSK=false);
+void fillOutRRSIG(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& keyrepodir, 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& keyrepodir, const std::string signQName, uint16_t signQType, uint32_t signTTL,
+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,
vector<shared_ptr<DNSRecordContent> >& toSign, RRSIGRecordContent &rrc, bool ksk);
std::string hashQNameWithSalt(unsigned int times, const std::string& salt, const std::string& qname);
void create(unsigned int bits);
- std::string convertToISC(unsigned int algorithm);
+ std::string convertToISC(unsigned int algorithm) const;
private:
rsa_context d_context;
typedef std::vector<std::pair<DNSSECPrivateKey, KeyMetaData> > keyset_t;
public:
- explicit DNSSECKeeper(const std::string& dirname) : d_dirname(dirname){}
-
bool haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* ksk=0);
keyset_t getKeys(const std::string& zone, boost::tribool allOrKeyOrZone = boost::indeterminate);
DNSSECPrivateKey getKeyById(const std::string& zone, unsigned int id);
void addKey(const std::string& zname, bool keyOrZone, int algorithm=5, int bits=0, bool active=true);
+ void addKey(const std::string& zname, bool keyOrZone, const DNSSECPrivateKey& dpk, bool active=true);
void removeKey(const std::string& zname, unsigned int id);
void activateKey(const std::string& zname, unsigned int id);
void deactivateKey(const std::string& zname, unsigned int id);
bool getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* n3p=0);
void setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent& n3p);
void unsetNSEC3PARAM(const std::string& zname);
-
-private:
- std::string d_dirname;
};
#endif
return false;
DNSResourceRecord rr;
- DNSSECKeeper dk(::arg()["key-repository"]);
-
+ DNSSECKeeper dk;
bool haveOne=false;
DNSSECPrivateKey dpk;
return false;
DNSResourceRecord rr;
- DNSSECKeeper dk(::arg()["key-repository"]);
+ DNSSECKeeper dk;
NSEC3PARAMRecordContent ns3prc;
if(dk.getNSEC3PARAM(p->qdomain, &ns3prc)) {
*/
void PacketHandler::addNSECX(DNSPacket *p, DNSPacket *r, const string& target, const string& auth, int mode)
{
- DNSSECKeeper dk(::arg()["key-repository"]);
+ DNSSECKeeper dk;
NSEC3PARAMRecordContent ns3rc;
cerr<<"Doing NSEC3PARAM lookup for '"<<auth<<"': ";
if(dk.getNSEC3PARAM(auth, &ns3rc)) {
BOOST_FOREACH(records_t::value_type& iter, records) {
RRSIGRecordContent rrc;
for(int ksk =0 ; ksk < 2; ++ksk) {
- getRRSIGForRRSET(::arg()["key-repository"], p->qdomain, iter.first, 3600, iter.second, rrc, ksk);
+ getRRSIGForRRSET(p->qdomain, iter.first, 3600, iter.second, rrc, ksk);
rr.content=rrc.getZoneRepresentation();
r->addRecord(rr);
if(iter.first != QType::DNSKEY)
nsecrepo_t nsecrepo;
// this is where the DNSKEYs go
- DNSSECKeeper dk(::arg()["key-repository"]);
+ DNSSECKeeper dk;
DNSSECKeeper::keyset_t keys = dk.getKeys(target);
BOOST_FOREACH(const DNSSECKeeper::keyset_t::value_type& value, keys) {
rr.qname = target;