endif
EXTRA_PROGRAMS=pdns_recursor sdig tsig-tests speedtest pdns_control dnsscope dnsgram \
- dnsdemog dnswasher dnsscan dnslog nproxy notify pdnssec dnsbulktest # tcptorture
+toysdig dnsdemog dnswasher dnsscan dnslog nproxy notify pdnssec dnsbulktest # dnslabel # tcptorture
pdns_server_SOURCES=dnspacket.cc nameserver.cc tcpreceiver.hh \
qtype.cc logger.cc arguments.cc packethandler.cc tcpreceiver.cc \
rcpgenerator.cc dnsparser.cc dns_random.hh aes/aescpp.h \
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 dnsseckeeper.cc dnssecinfra.cc \
+randomhelper.cc namespaces.hh nsecrecords.cc base32.cc fsdnsseckeeper.cc dnssecinfra.cc \
dnsseckeeper.hh dnssecinfra.hh base32.hh
#
-pdnssec_SOURCES=pdnssec.cc dnsseckeeper.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnswriter.hh \
+pdnssec_SOURCES=pdnssec.cc fsdnsseckeeper.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnswriter.hh \
misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \
logger.cc statbag.cc qtype.cc sillyrecords.cc nsecrecords.cc dnssecinfra.cc dnssecinfra.hh \
base32.cc ueberbackend.cc dnsbackend.cc arguments.cc packetcache.cc dnspacket.cc \
misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \
logger.cc statbag.cc qtype.cc sillyrecords.cc nsecrecords.cc base32.cc
+toysdig_SOURCES=toysdig.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnswriter.hh \
+ misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \
+ logger.cc statbag.cc qtype.cc sillyrecords.cc nsecrecords.cc base32.cc dnslabel.cc dnslabel.hh
+
+
#tcptorture_SOURCES=tcptorture.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnswriter.hh \
# misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \
# logger.cc statbag.cc qtype.cc sillyrecords.cc nsecrecords.cc base32.cc
signer=qname;
do {
- if(dk.haveKSKFor(signer))
+ if(dk.haveActiveKSKFor(signer))
return true;
} while(chopOff(signer));
return false;
DNSSECPrivateKey dpk;
if(!withKSK) {
- DNSSECKeeper::zskset_t zskset=dk.getZSKsFor(qname);
- BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
+ 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;
cerr<<"Could not find an active ZSK for '"<<qname<<"'"<<endl;
exit(1);
}
- else if(dk.haveKSKFor(qname, &dpk)) {
+ else if(dk.haveActiveKSKFor(qname, &dpk)) {
cerr<<"Found a KSK for '"<<qname<<"'"<<endl;
*rc=dpk.d_key;
return dpk.getDNSKEY();
+++ /dev/null
-#include "dnsseckeeper.hh"
-#include "dnssecinfra.hh"
-#include "statbag.hh"
-#include <iostream>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-#include <polarssl/havege.h>
-#include <polarssl/base64.h>
-#include <boost/foreach.hpp>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fstream>
-#include <boost/algorithm/string.hpp>
-#include <boost/format.hpp>
-#include <boost/assign/std/vector.hpp> // for 'operator+=()'
-#include <boost/assign/list_inserter.hpp>
-using namespace boost::assign;
-namespace fs = boost::filesystem;
-
-using namespace std;
-using namespace boost;
-
-void RSAContext::create(unsigned int bits)
-{
- havege_state hs;
- havege_init( &hs );
-
- rsa_init(&d_context, RSA_PKCS_V15, 0, havege_rand, &hs ); // FIXME this leaks memory
- int ret=rsa_gen_key(&d_context, bits, 65537);
- if(ret < 0)
- throw runtime_error("Key generation failed");
-}
-
-std::string RSAContext::convertToISC()
-{
- string ret;
- typedef vector<pair<string, mpi*> > outputs_t;
- outputs_t outputs;
- push_back(outputs)("Modulus", &d_context.N)("PublicExponent",&d_context.E)
- ("Modulus", &d_context.N)
- ("PublicExponent",&d_context.E)
- ("PrivateExponent",&d_context.D)
- ("Prime1",&d_context.P)
- ("Prime2",&d_context.Q)
- ("Exponent1",&d_context.DP)
- ("Exponent2",&d_context.DQ)
- ("Coefficient",&d_context.QP);
-
- ret = "Private-key-format: v1.2\nAlgorithm: 5 (RSASHA1)\n";
-
- BOOST_FOREACH(outputs_t::value_type value, outputs) {
- ret += value.first;
- ret += ": ";
- unsigned char tmp[mpi_size(value.second)];
- mpi_write_binary(value.second, tmp, sizeof(tmp));
- unsigned char base64tmp[sizeof(tmp)*2];
- int dlen=sizeof(base64tmp);
- base64_encode(base64tmp, &dlen, tmp, sizeof(tmp));
- ret.append((const char*)base64tmp, dlen);
- ret.append(1, '\n');
- }
- return ret;
-}
-
-bool DNSSECKeeper::haveKSKFor(const std::string& zone, DNSSECPrivateKey* dpk)
-{
- fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zone + "/ksks/" ) );
-
- if ( !fs::exists( full_path ) )
- return false;
-
- fs::directory_iterator end_iter;
- for ( fs::directory_iterator dir_itr( full_path );
- dir_itr != end_iter;
- ++dir_itr )
- {
- // cerr<<"Entry: '"<< dir_itr->leaf() <<"'"<<endl;
- if(ends_with(dir_itr->leaf(),".isc")) {
- // cerr<<"Hit!"<<endl;
-
- if(dpk) {
- getRSAKeyFromISC(&dpk->d_key.getContext(), dir_itr->path().file_string().c_str());
-
- if(getNSEC3PARAM(zone)) {
- dpk->d_algorithm = 7;
- }
- else {
- dpk->d_algorithm = 5;
- }
-
- }
- return true;
- }
- }
-
- return false;
-}
-
-unsigned int DNSSECKeeper::getNextKeyIDFromDir(const std::string& dirname)
-{
- fs::path full_path = fs::system_complete( fs::path(dirname));
-
- if ( !fs::exists( full_path ) )
- unixDie("Unable to get next free key id from '"+dirname+"'");
-
- fs::directory_iterator end_iter;
- unsigned int maxID=0;
- for ( fs::directory_iterator dir_itr( full_path );
- dir_itr != end_iter;
- ++dir_itr )
- {
- if(ends_with(dir_itr->leaf(),".isc")) {
- maxID = max(maxID, (unsigned int)atoi(dir_itr->leaf().c_str()));
- }
- }
- return maxID+1;
-}
-
-void DNSSECKeeper::addZSKFor(const std::string& name, int algorithm, bool active)
-{
- DNSSECPrivateKey dpk;
- dpk.d_key.create(1024); // for testing, 1024
-
- string isc = dpk.d_key.convertToISC();
- DNSKEYRecordContent drc = dpk.getDNSKEY();
- drc.d_flags = 256; // KSK
- drc.d_algorithm = algorithm;
- string iscName=d_dirname+"/"+name+"/zsks/";
- unsigned int id = getNextKeyIDFromDir(iscName);
- time_t inception=time(0);
-
- struct tm ts;
- gmtime_r(&inception, &ts);
-
- iscName += (boost::format("%06d-%04d%02d%02d%02d%02d") % id
- % (1900+ts.tm_year) % (ts.tm_mon + 1)
- % ts.tm_mday % ts.tm_hour % ts.tm_min).str();
-
- iscName += active ? ".active" : ".passive";
-
- {
- ofstream iscFile((iscName+".isc").c_str());
- iscFile << isc;
- }
-
- {
- ofstream dnskeyFile((iscName+".dnskey").c_str());
- dnskeyFile << toCanonic("", name) << " IN DNSKEY " << drc.getZoneRepresentation()<<endl;
- }
-
-}
-
-
-static bool zskCompareByID(const DNSSECKeeper::zskset_t::value_type& a, const DNSSECKeeper::zskset_t::value_type& b)
-{
- return a.second.id < b.second.id;
-}
-
-void DNSSECKeeper::deleteZSKFor(const std::string& zname, const std::string& fname)
-{
- unlink((d_dirname +"/"+ zname +"/zsks/"+fname).c_str());
-}
-
-bool DNSSECKeeper::getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* ns3p)
-{
- fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zname + "/nsec3param" ) );
- ifstream ifs(full_path.external_directory_string().c_str());
- // cerr<<"called for nsec3param..."<<endl;
- if(!ifs)
- return false;
-
- if(ns3p) {
- string descr;
- getline(ifs, descr);
- NSEC3PARAMRecordContent* tmp=dynamic_cast<NSEC3PARAMRecordContent*>(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, descr));
- if(!tmp) {
- cerr<<"Could not parse "<< full_path.external_directory_string() <<endl;
- cerr<<"descr: '"<<descr<<"'\n";
- }
- *ns3p = *tmp;
- delete tmp;
-
- cerr<<"hmm salt: "<<makeHexDump(ns3p->d_salt)<<endl;
- }
- return true;
-}
-
-void DNSSECKeeper::setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent* ns3p)
-{
- fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zname + "/nsec3param" ) );
- if(ns3p) {
- string descr = ns3p->getZoneRepresentation();
-
-
- ofstream of(full_path.external_directory_string().c_str());
- of << descr;
- }
- else {
- unlink(full_path.external_directory_string().c_str());
- }
-}
-
-
-DNSSECKeeper::zskset_t DNSSECKeeper::getZSKsFor(const std::string& zone, bool all)
-{
- zskset_t zskset;
-
- fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zone + "/zsks/" ) );
-
- if ( !fs::exists( full_path ) )
- return zskset;
-
- fs::directory_iterator end_iter;
- for ( fs::directory_iterator dir_itr( full_path );
- dir_itr != end_iter;
- ++dir_itr )
- {
- // cerr<<"Entry: '"<< dir_itr->leaf() <<"'"<<endl;
- if(ends_with(dir_itr->leaf(),".isc")) {
- //cerr<<"Hit!"<<endl;
- DNSSECPrivateKey dpk;
- getRSAKeyFromISC(&dpk.d_key.getContext(), dir_itr->path().file_string().c_str());
-
- if(getNSEC3PARAM(zone)) {
- dpk.d_algorithm = 7;
- }
- else {
- dpk.d_algorithm = 5;
- }
-
- struct tm ts1, ts2;
-
- memset(&ts1, 0, sizeof(ts1));
- memset(&ts2, 0, sizeof(ts2));
-
- unsigned int id;
- sscanf(dir_itr->leaf().c_str(), "%06u-%04d%02d%02d%02d%02d",
- &id,
- &ts1.tm_year,
- &ts1.tm_mon, &ts1.tm_mday, &ts1.tm_hour, &ts1.tm_min);
-
-
- ts1.tm_year -= 1900;
-
- ts1.tm_mon--;
-
- KeyMetaData kmd;
-
- kmd.id = id;
- kmd.fname = dir_itr->leaf();
- kmd.active = kmd.fname.find(".active") != string::npos;
- zskset.push_back(make_pair(dpk, kmd));
- }
- sort(zskset.begin(), zskset.end(), zskCompareByID);
- }
-
- return zskset;
-}
-
-DNSKEYRecordContent DNSSECPrivateKey::getDNSKEY()
-{
- return makeDNSKEYFromRSAKey(&d_key.getContext(), d_algorithm);
-}
-
-
-void DNSSECKeeper::secureZone(const std::string& name, int algorithm)
-{
- mkdir((d_dirname+"/"+name).c_str(), 0700);
- mkdir((d_dirname+"/"+name+"/ksks").c_str(), 0700);
- if(mkdir((d_dirname+"/"+name+"/zsks").c_str(), 0700) < 0)
- unixDie("Making directory for keys in '"+d_dirname+"'");
-
- // now add the KSK
-
- DNSSECPrivateKey dpk;
- dpk.d_key.create(2048); // for testing, 1024
-
- string isc = dpk.d_key.convertToISC();
- DNSKEYRecordContent drc = dpk.getDNSKEY();
- drc.d_flags = 257; // ZSK (?? for a KSK?)
- drc.d_algorithm = algorithm;
- string iscName=d_dirname+"/"+name+"/ksks/";
-
- time_t now=time(0);
- struct tm ts;
- gmtime_r(&now, &ts);
- unsigned int id=1;
- iscName += (boost::format("%06d-%04d%02d%02d%02d%02d.%u") % id
- % (1900+ts.tm_year) % (ts.tm_mon + 1)
- % ts.tm_mday % ts.tm_hour % ts.tm_min % drc.getTag()).str();
-
-
- {
- ofstream iscFile((iscName+".isc").c_str());
- iscFile << isc;
- }
-
- {
- ofstream dnskeyFile((iscName+".dnskey").c_str());
- dnskeyFile << toCanonic("", name) << " IN DNSKEY " << drc.getZoneRepresentation()<<endl;
- }
-
-}
-
-
#include <polarssl/rsa.h>
#include <string.h>
#include <vector>
+#include <boost/logic/tribool.hpp>
#include "dnsrecords.hh"
#define PDNSSEC_MI(x) mpi_init(&d_context.x, 0)
rsa_context d_context;
};
+// ?
#undef PDNSSEC_MC
#undef PDNSSEC_MI
#undef PDNSSEC_MF
public:
struct KeyMetaData
{
- unsigned int id;
+ unsigned int id;
bool active;
+ bool keyOrZone;
string fname;
};
- typedef std::vector<std::pair<DNSSECPrivateKey, KeyMetaData> > zskset_t;
+ typedef std::vector<std::pair<DNSSECPrivateKey, KeyMetaData> > keyset_t;
public:
explicit DNSSECKeeper(const std::string& dirname) : d_dirname(dirname){}
- bool haveKSKFor(const std::string& zone, DNSSECPrivateKey* ksk=0);
+ bool haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* ksk=0);
- zskset_t getZSKsFor(const std::string& zone, bool all=false);
- void addZSKFor(const std::string& zname, int algorithm, bool next=false);
-
- void deleteZSKFor(const std::string& zname, const std::string& fname);
+ keyset_t getKeys(const std::string& zone, boost::tribool allOrKeyOrZone = boost::indeterminate);
+ void addKey(const std::string& zname, bool keyOrZone, int algorithm, 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);
void secureZone(const std::string& fname, int algorithm);
bool getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* n3p=0);
void setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent* n3p);
static unsigned int getNextKeyIDFromDir(const std::string& dirname);
+ std::string getKeyFilenameById(const std::string& dirname, unsigned int id);
private:
std::string d_dirname;
};
cmds = g_vm["commands"].as<vector<string> >();
if(cmds.empty() || g_vm.count("help")) {
- cerr<<"Usage: \npdnssec [options] [show-zone] [secure-zone] [alter-zone] [order-zone] [update-zone-keys]\n";
+ cerr<<"Usage: \npdnssec [options] [show-zone] [secure-zone] [alter-zone] [order-zone] [add-zone-key] [deactivate-zone-key] [remove-zone-key] [activate-zone-key]\n";
cerr<<desc<<endl;
return 0;
}
cerr << "No KSK for zone '"<<zone<<"', can't update the ZSKs"<<endl;
return 0;
}
- DNSSECKeeper::zskset_t zskset=dk.getZSKsFor(zone);
+ DNSSECKeeper::keyset_t zskset=dk.getZSKsFor(zone);
int inforce=0;
time_t now = time(&now);
if(!zskset.empty()) {
cout<<"There were ZSKs already for zone '"<<zone<<"': "<<endl;
- BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
+ BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
cout<<"Tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl; // ", "<<humanTime(value.second.beginValidity)<<" - "<<humanTime(value.second.endValidity)<<endl;
if(value.second.active)
inforce++;
cerr << "Two or more ZSKs were active already, not generating a third" << endl;
return 0;
}
- dk.addZSKFor(zone, 5);
- dk.addZSKFor(zone, 5, true); // 'next'
+ dk.addKey(zone, true, 5);
+ dk.addKey(zone, true, 5, false); // not yet active
- zskset = dk.getZSKsFor(zone);
+ keyset = dk.getKeys(zone);
if(zskset.empty()) {
cerr<<"This should not happen, still no ZSK!"<<endl;
}
cout<<"There are now "<<zskset.size()<<" ZSKs"<<endl;
- BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
+ BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
cout<<"Tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl;
}
return 0;
}
const string& zone=cmds[1];
- DNSSECPrivateKey dpk;
- if(!dk.haveKSKFor(zone, &dpk)) {
- cerr << "No KSK for zone '"<<zone<<"'."<<endl;
- }
- else {
- cout<<"KSK present:"<<endl;
- cout<<"Tag = "<<dpk.getDNSKEY().getTag()<<endl;
- cout<<"KSK DNSKEY = "<<zone<<" IN DNSKEY "<< dpk.getDNSKEY().getZoneRepresentation() << endl;
- cout<<"DS = "<<zone<<" IN DS "<<makeDSFromDNSKey(zone, dpk.getDNSKEY()).getZoneRepresentation() << endl << endl;
- }
-
-
- DNSSECKeeper::zskset_t zskset=dk.getZSKsFor(zone);
+ DNSSECKeeper::keyset_t keyset=dk.getKeys(zone, boost::indeterminate);
- if(zskset.empty()) {
- cerr << "No ZSKs for zone '"<<zone<<"'."<<endl;
+ if(keyset.empty()) {
+ cerr << "No keys for zone '"<<zone<<"'."<<endl;
}
else {
- cout << "ZSKs for zone '"<<zone<<"':"<<endl;
- BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
- cout<<"ID = "<<value.second.id<<", tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<< endl; // humanTime(value.second.beginValidity)<<" - "<<humanTime(value.second.endValidity)<<endl;
+ cout << "keys: for zone '"<<zone<<"':"<<endl;
+ BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, keyset) {
+ cout<<"ID = "<<value.second.id<<" ("<<(value.second.keyOrZone ? "KSK" : "ZSK")<<"), tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<< endl; // humanTime(value.second.beginValidity)<<" - "<<humanTime(value.second.endValidity)<<endl;
+ if(value.second.keyOrZone) {
+ cout<<"KSK DNSKEY = "<<zone<<" IN DNSKEY "<< value.first.getDNSKEY().getZoneRepresentation() << endl;
+ cout<<"DS = "<<zone<<" IN DS "<<makeDSFromDNSKey(zone, value.first.getDNSKEY()).getZoneRepresentation() << endl << endl;
+ }
}
}
}
+ else if(cmds[0] == "activate-zone-key") {
+ const string& zone=cmds[1];
+ unsigned int id=atoi(cmds[2].c_str());
+ dk.activateKey(zone, id);
+ }
+ else if(cmds[0] == "deactivate-zone-key") {
+ const string& zone=cmds[1];
+ unsigned int id=atoi(cmds[2].c_str());
+ dk.deactivateKey(zone, id);
+ }
+ else if(cmds[0] == "add-zone-key") {
+ const string& zone=cmds[1];
+ // need to get algorithm & ksk or zsk
+ dk.addKey(zone, 1, 5, 0);
+ cerr<<"Not implemented"<<endl;
+ }
+ else if(cmds[0] == "remove-zone-key") {
+ const string& zone=cmds[1];
+ unsigned int id=atoi(cmds[2].c_str());
+ dk.removeKey(zone, id);
+ }
+
else if(cmds[0] == "secure-zone") {
if(cmds.size() != 2) {
cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
const string& zone=cmds[1];
DNSSECPrivateKey dpk;
- if(dk.haveKSKFor(zone, &dpk) && !g_vm.count("force")) {
+ if(dk.haveActiveKSKFor(zone, &dpk) && !g_vm.count("force")) {
cerr << "There is a key already for zone '"<<zone<<"', use --force to overwrite"<<endl;
return 0;
}
dk.secureZone(zone, 5);
- if(!dk.haveKSKFor(zone, &dpk)) {
+ if(!dk.haveActiveKSKFor(zone, &dpk)) {
cerr << "This should not happen, still no key!" << endl;
}
cout<<"Created KSK with tag "<<dpk.getDNSKEY().getTag()<<endl;
- DNSSECKeeper::zskset_t zskset=dk.getZSKsFor(zone);
+ DNSSECKeeper::keyset_t zskset=dk.getKeys(zone, false);
if(!zskset.empty() && !g_vm.count("force")) {
cerr<<"There were ZSKs already for zone '"<<zone<<"'"<<endl;
return 0;
}
- dk.addZSKFor(zone, 5);
- dk.addZSKFor(zone, 5, true); // 'next'
+ dk.addKey(zone, false, 5);
+ dk.addKey(zone, false, 5, false); // not active
- zskset = dk.getZSKsFor(zone);
+ zskset = dk.getKeys(zone, false);
if(zskset.empty()) {
cerr<<"This should not happen, still no ZSK!"<<endl;
}
cout<<"There are now "<<zskset.size()<<" ZSKs"<<endl;
- BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
+ BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
cout<<"id = "<<value.second.id<<", tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl;
}
}
#include "dnswriter.hh"
#include "dnsrecords.hh"
#include "statbag.hh"
-#include "iputils.hh"
-#include <boost/foreach.hpp>
-#include <polarssl/rsa.h>
-#include <polarssl/base64.h>
-#include <polarssl/sha1.h>
-#include "dnssecinfra.hh"
-#include "base32.hh"
-
StatBag S;
-MOADNSParser* askQuestion(DNSPacketWriter&, vector<uint8_t>& packet, const char* remote, uint16_t port=53)
-{
- int sock=socket(AF_INET, SOCK_DGRAM, 0);
-
- if(sock < 0)
- unixDie("Creating SCTP socket");
-
- ComboAddress dest(remote + (*remote=='@'), port);
- struct msghdr msg;
- struct iovec iomsg;
-
- msg.msg_name=&dest;
- msg.msg_namelen=dest.getSocklen();
- msg.msg_iov=&iomsg;
- iomsg.iov_base=&*packet.begin();
- iomsg.iov_len=packet.size();
- msg.msg_iovlen=1;
- msg.msg_control=0;
- msg.msg_controllen=0;
- msg.msg_flags=0; // just to be sure
-
- sendmsg(sock, &msg, 0);
-
- char replybuf[4096];
- socklen_t destlen=dest.getSocklen();
- int len=recvfrom(sock, replybuf, sizeof(replybuf), 0, (struct sockaddr*)&dest, &destlen);
- if(len < 0)
- unixDie("recvfrom on sctp");
-
- string reply(replybuf, len);
-
- return new MOADNSParser(reply);
-}
-
-void getKeys(const std::string& qname, uint16_t tag);
-
-void doVerifySignature(const std::string& qname, map<string, vector<shared_ptr<DNSKEYRecordContent > > >& dkrcs, pair<vector<shared_ptr<DNSRecordContent> >, vector<shared_ptr<RRSIGRecordContent> > >& records)
-{
- rsa_context rsa;
-
- BOOST_FOREACH(shared_ptr<RRSIGRecordContent>& rrc, records.second) {
- cerr<<"\nVerifying "<<qname<<"|"<<DNSRecordContent::NumberToType(rrc->d_type)<<"\n";
-
- cerr<<"Signer is: "<<rrc->d_signer<<" for which we have "<<dkrcs[rrc->d_signer].size()<<" DNSKEYs, want the one with";
- cerr<<" tag: "<<rrc->d_tag<<endl;
-
-
- getKeys(rrc->d_signer, rrc->d_tag);
-
- if(dkrcs[rrc->d_signer].empty()) {
- cerr<<"\tNo keys!\n";
- return;
- }
-
- vector<shared_ptr<DNSRecordContent> >& signRecords= records.first;
-
- string hash=getSHA1HashForRRSET(qname, *rrc.get(), signRecords);
- int ret;
- int success=0;
- BOOST_FOREACH(shared_ptr<DNSKEYRecordContent> dkrc, dkrcs[rrc->d_signer]) {
- if(dkrc->getTag() != rrc->d_tag) {
- cerr<<"Skipping key with wrong tag "<<dkrc->getTag()<< " != needed "<<rrc->d_tag<<endl;
- continue;
- }
- makeRSAPublicKeyFromDNS(&rsa, *dkrc);
-
- if((ret=rsa_pkcs1_verify(&rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20, (unsigned char*)hash.c_str(), (unsigned char*)rrc->d_signature.c_str() ) ) != 0) {
- fprintf(stderr, "Verification with tag %d failed with error %d\n", dkrc->getTag(), ret);
- }
- else {
- fprintf(stderr, "DNSSEC Record verified Ok with tag %d!\n", dkrc->getTag());
- success++;
- break;
- }
- }
- if(success)
- cerr<<"\t at least one verification was succesful!\n";
- }
-}
-
-typedef map<string, vector<shared_ptr<DNSKEYRecordContent> > > dkrc_t;
-dkrc_t dkrc;
-
-void getKeys(const std::string& qname, uint16_t tag)
-{
- BOOST_FOREACH(shared_ptr<DNSKEYRecordContent>& drc, dkrc[qname]) {
- if(drc->getTag() == tag)
- return;
- }
-
- vector<uint8_t> packet;
-
- DNSPacketWriter pw(packet, qname, QType::DNSKEY);
-
- pw.getHeader()->id=1234;
- pw.getHeader()->rd=1;
-
- pw.addOpt(4000, 0, EDNSOpts::DNSSECOK); // int udpsize, int extRCode, int Z
- pw.commit();
-
- MOADNSParser* mdp=askQuestion(pw, packet, "199.249.112.1", 53);
- if(mdp->d_header.tc) {
- cerr<<"Truncated!\n";
- }
- for(MOADNSParser::answers_t::const_iterator i=mdp->d_answers.begin(); i!=mdp->d_answers.end(); ++i) {
- if(i->first.d_type==QType::DNSKEY) {
- shared_ptr<DNSKEYRecordContent> dkrcptr=dynamic_pointer_cast<DNSKEYRecordContent>(i->first.d_content);
- dkrc[i->first.d_label].push_back(dkrcptr);
- cerr<<"Added DNSKEY for '"<<qname<<"': tag = "<<dkrcptr->getTag()<<", key length = "<<dkrcptr->getModulus().length()*8<<", SEP = "<< dkrcptr->d_flags%2 <<endl;
- }
- }
-}
-
int main(int argc, char** argv)
try
{
reportAllTypes();
if(argc < 4) {
- cerr<<"Syntax: toysdig question question-type IP-address [port]\n";
+ cerr<<"Syntax: sdig IP-address port question question-type\n";
exit(EXIT_FAILURE);
}
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, argv[1], DNSRecordContent::TypeToNumber(argv[2]));
+ DNSPacketWriter pw(packet, argv[3], DNSRecordContent::TypeToNumber(argv[4]));
- pw.getHeader()->id=1234;
- pw.getHeader()->rd=0;
+ pw.getHeader()->rd=1;
+
+ Socket sock(InterNetwork, Datagram);
+ ComboAddress dest(argv[1] + (*argv[1]=='@'), atoi(argv[2]));
+ sock.sendTo(string((char*)&*packet.begin(), (char*)&*packet.end()), dest);
+
+ string reply;
+ sock.recvFrom(reply, dest);
- pw.addOpt(4000, 0, EDNSOpts::DNSSECOK); // int udpsize, int extRCode, int Z
- pw.commit();
+ MOADNSParser mdp(reply);
+ cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
+ cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
+ cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
- MOADNSParser* mdp=askQuestion(pw, packet, argv[3], argc>4 ? atoi(argv[4]) : 53);
- if(mdp->d_header.tc) {
- cerr<<"Truncated!\n";
- }
-
- typedef map< pair<string, uint16_t>,
- pair<vector<shared_ptr<DNSRecordContent> >, vector<shared_ptr<RRSIGRecordContent> >
- > > grouped_t;
- grouped_t grouped;
-
- string salt;
- int iterations;
- for(MOADNSParser::answers_t::const_iterator i=mdp->d_answers.begin(); i!=mdp->d_answers.end(); ++i) {
+ for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
cout<<i->first.d_place-1<<"\t"<<i->first.d_label<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);
cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n";
-
- if(i->first.d_type==QType::DNSKEY) {
- dkrc[i->first.d_label].push_back(dynamic_pointer_cast<DNSKEYRecordContent>(i->first.d_content));
- }
-
- if(i->first.d_type==QType::NSEC3) {
- salt=dynamic_pointer_cast<NSEC3RecordContent>(i->first.d_content)->d_salt;
- iterations=dynamic_pointer_cast<NSEC3RecordContent>(i->first.d_content)->d_iterations;
- }
-
-
- if(i->first.d_type!=QType::RRSIG)
- grouped[make_pair(i->first.d_label, i->first.d_type)].first.push_back(i->first.d_content);
- else {
- shared_ptr<RRSIGRecordContent> rrc=dynamic_pointer_cast<RRSIGRecordContent>(i->first.d_content);
- grouped[make_pair(i->first.d_label, rrc->d_type)].second.push_back(rrc);
- cerr<<"Algorithm = "<<(int)rrc->d_algorithm<<endl;
- }
-
- }
-
- if(!salt.empty()) {
- cerr<<"We have a salt ("<<makeHexDump(salt)<<"), the NSEC3 of our query name ("<<argv[1]<<"): "<<toBase32Hex(hashQNameWithSalt(iterations, salt, argv[1]))<<endl;
- }
-
- cerr<<"Now have different names of "<<dkrc.size()<<" dnskeys!"<<endl;
-
- BOOST_FOREACH(dkrc_t::value_type& value, dkrc) {
- BOOST_FOREACH(shared_ptr<DNSKEYRecordContent>& content, value.second) {
- DSRecordContent dsrc = makeDSFromDNSKey(value.first, *content.get());
- cerr<<"ds: "<<value.first<<" IN DS "<<dsrc.getZoneRepresentation()<<endl;
- dsrc = makeDSFromDNSKey(value.first, *content.get(),2);
- cerr<<"ds: "<<value.first<<" IN DS "<<dsrc.getZoneRepresentation()<<endl;
-
- }
- }
-
- cerr<<"\n";
- BOOST_FOREACH(grouped_t::value_type& value, grouped) {
- if(value.second.first.empty() && !value.second.second.empty())
- cerr<<"Have a loose signature for"<<value.first.first<<"|"<<DNSRecordContent::NumberToType(value.first.second)<<endl;
- else if(!value.second.first.empty() && value.second.second.empty())
- cerr<<"Have unsigned content: "<<value.first.first<<"|"<<DNSRecordContent::NumberToType(value.first.second)<<endl;
- else if(!value.second.first.empty() && !value.second.second.empty()) {
- cerr<<"Have signed content: "<<value.first.first<<"|"<<DNSRecordContent::NumberToType(value.first.second);
- cerr<<" ("<<value.second.first.size()<<" recs, "<<value.second.second.size()<<" signatures)"<<endl;
- doVerifySignature(value.first.first, dkrc, value.second);
- }
- else
- cerr<<"Have empty content?? "<<value.first.first<<"|"<<DNSRecordContent::NumberToType(value.first.second)<<endl;
}
+
}
catch(std::exception &e)