bool haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* ksk=0);
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);
+ 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 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);
+ void setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent& n3p);
+ void unsetNSEC3PARAM(const std::string& zname);
static unsigned int getNextKeyIDFromDir(const std::string& dirname);
std::string getKeyFilenameById(const std::string& dirname, unsigned int id);
private:
}
-void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, int algorithm, bool active)
+void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, int algorithm, int bits, bool active)
{
+ if(!bits)
+ bits = keyOrZone ? 2048 : 1024;
DNSSECPrivateKey dpk;
- dpk.d_key.create(1024); // for testing, 1024
+ dpk.d_key.create(bits); // for testing, 1024
string isc = dpk.d_key.convertToISC();
DNSKEYRecordContent drc = dpk.getDNSKEY();
drc.d_flags = 256 + keyOrZone; // KSK
- drc.d_algorithm = algorithm;
+ drc.d_algorithm = algorithm; // 5 = RSA, we'll add '2' later on for NSEC3 if needed
string iscName=d_dirname+"/"+name+"/keys/";
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.%u") % id
+ 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 % drc.getTag()).str();
+ % ts.tm_mday % ts.tm_hour % ts.tm_min).str();
iscName += keyOrZone ? ".ksk" : ".zsk";
iscName += active ? ".active" : ".passive";
ofstream iscFile((iscName+".private").c_str());
iscFile << isc;
}
-
+#if 0
{
ofstream dnskeyFile((iscName+".key").c_str());
dnskeyFile << toCanonic("", name) << " IN DNSKEY " << drc.getZoneRepresentation()<<endl;
}
-
+#endif
}
make_pair(!b.second.keyOrZone, b.second.id);
}
+DNSSECPrivateKey DNSSECKeeper::getKeyById(const std::string& zname, unsigned int id)
+{
+ string fname = getKeyFilenameById(d_dirname+"/"+zname+"/keys", id);
+ DNSSECPrivateKey dpk;
+ getRSAKeyFromISC(&dpk.d_key.getContext(), fname.c_str());
+ dpk.d_algorithm = 5 + 2 * getNSEC3PARAM(zname);
+ dpk.d_flags = 256 + (fname.find(".ksk.") != string::npos); // this falls over on zones with .ksk. in the name!
+ return dpk;
+
+}
+
+
void DNSSECKeeper::removeKey(const std::string& zname, unsigned int id)
{
string fname = getKeyFilenameById(d_dirname+"/"+zname+"/keys", id);
if(ns3p) {
string descr;
getline(ifs, descr);
+ reportAllTypes();
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";
+ return false;
}
*ns3p = *tmp;
delete tmp;
-
- cerr<<"hmm salt: "<<makeHexDump(ns3p->d_salt)<<endl;
}
return true;
}
-void DNSSECKeeper::setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent* ns3p)
+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());
- }
+ string descr = ns3p.getZoneRepresentation();
+ ofstream of(full_path.external_directory_string().c_str());
+ of << descr;
+}
+
+void DNSSECKeeper::unsetNSEC3PARAM(const std::string& zname)
+{
+ fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zname + "/nsec3param" ) );
+ unlink(full_path.external_directory_string().c_str());
}
if(mkdir((d_dirname+"/"+name+"/keys").c_str(), 0700) < 0)
unixDie("Making directory for keys in '"+d_dirname+"'");
-
// now add the KSK
-
addKey(name, true, algorithm);
-#if 0
-
- 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+"/keys/";
-
- 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.%s.%s") % id
- % (1900+ts.tm_year) % (ts.tm_mon + 1)
- % ts.tm_mday % ts.tm_hour % ts.tm_min % drc.getTag() % "ksk" % "active").str();
-
-
- {
- ofstream iscFile((iscName+".private").c_str());
- iscFile << isc;
- }
-
- {
- ofstream dnskeyFile((iscName+".key").c_str());
- dnskeyFile << toCanonic("", name) << " IN DNSKEY " << drc.getZoneRepresentation()<<endl;
- }
-#endif
}
// cerr<<rr.qname<<endl;
qnames.insert(rr.qname);
}
-#if 0
- string salt;
- char tmp[]={0xab, 0xcd};
- salt.assign(tmp, 2);
-#endif
NSEC3PARAMRecordContent ns3pr;
dk.getNSEC3PARAM(zone, &ns3pr);
if(cmds.empty() || g_vm.count("help")) {
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<<" [import-zone-key] [export-zone-key] [set-nsec3] [unset-nsec3] [export-zone-dnskey]"<<endl;
cerr<<desc<<endl;
return 0;
}
}
checkZone(dk, cmds[1]);
}
-#if 0
- else if(cmds[0] == "update-zone-keys") {
+
+ else if(cmds[0] == "show-zone") {
if(cmds.size() != 2) {
cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
return 0;
}
-
const string& zone=cmds[1];
- DNSSECPrivateKey dpk;
-
- if(!dk.haveKSKFor(zone, &dpk)) {
- cerr << "No KSK for zone '"<<zone<<"', can't update the ZSKs"<<endl;
- return 0;
- }
- DNSSECKeeper::keyset_t zskset=dk.getZSKsFor(zone);
- int inforce=0;
- time_t now = time(&now);
-
+ NSEC3PARAMRecordContent ns3pr;
+ dk.getNSEC3PARAM(zone, &ns3pr);
- if(!zskset.empty()) {
- cout<<"There were ZSKs already for zone '"<<zone<<"': "<<endl;
-
- 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++;
- if(!value.second.active) { // was: 'expired more than two days ago'
- cout<<"\tThis key is no longer used and too old to keep around, deleting!\n";
- dk.deleteZSKFor(zone, value.second.fname);
- } else /* if( value.second.endValidity < now ) */{ // 'expired more than two days ago'
- cout<<"\tThis key is no longer in active use, but needs to linger\n";
- }
- }
- }
-
- if(inforce >= 2) {
- cerr << "Two or more ZSKs were active already, not generating a third" << endl;
- return 0;
- }
- dk.addKey(zone, true, 5);
- dk.addKey(zone, true, 5, false); // not yet active
-
- keyset = dk.getKeys(zone);
- if(zskset.empty()) {
- cerr<<"This should not happen, still no ZSK!"<<endl;
- }
+ if(ns3pr.d_salt.empty())
+ cerr<<"Zone has NSEC semantics"<<endl;
+ else
+ cerr<<"Zone has hashed NSEC3 semantics, configuration: "<<ns3pr.getZoneRepresentation()<<endl;
- cout<<"There are now "<<zskset.size()<<" ZSKs"<<endl;
- BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
- cout<<"Tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl;
- }
-
- }
-#endif
- else if(cmds[0] == "show-zone") {
- if(cmds.size() != 2) {
- cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
- return 0;
- }
- const string& zone=cmds[1];
DNSSECKeeper::keyset_t keyset=dk.getKeys(zone);
cerr << "No keys for zone '"<<zone<<"'."<<endl;
}
else {
- cout << "keys: for zone '"<<zone<<"':"<<endl;
+ cout << "keys: "<<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;
+ cout<<"ID = "<<value.second.id<<" ("<<(value.second.keyOrZone ? "KSK" : "ZSK")<<"), tag = "<<value.first.getDNSKEY().getTag();
+ cout<<", algo = "<<(int)value.first.d_algorithm<<", bits = "<<value.first.d_key.getConstContext().len*8<<"\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;
}
dk.addKey(zone, false, 5);
- dk.addKey(zone, false, 5, false); // not active
+ dk.addKey(zone, false, 5, 0, false); // not active
zskset = dk.getKeys(zone, false);
if(zskset.empty()) {
cout<<"There are now "<<zskset.size()<<" ZSKs"<<endl;
BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
- cout<<"id = "<<value.second.id<<", tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl;
+ cout<<"id = "<<value.second.id<<", tag = "<<value.first.getDNSKEY().getTag()<<", algo = "<<(int)value.first.d_algorithm<<
+ ", bits = "<<value.first.d_key.getContext().len*8;
+ cout<<"\tActive: "<<value.second.active<<endl;
}
}
+ else if(cmds[0]=="set-nsec3") {
+ string nsec3params = cmds.size() > 2 ? cmds[2] : "1 0 1 ab";
+
+ NSEC3PARAMRecordContent ns3pr(nsec3params);
+ dk.setNSEC3PARAM(cmds[1], ns3pr);
+ }
+ else if(cmds[0]=="unset-nsec3") {
+ dk.unsetNSEC3PARAM(cmds[1]);
+ }
+ else if(cmds[0]=="export-zone-key") {
+ string zone=cmds[1];
+ unsigned int id=atoi(cmds[2].c_str());
+ DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
+ cout << dpk.d_key.convertToISC() <<endl;
+ }
+ else if(cmds[0]=="export-zone-dnskey") {
+ string zone=cmds[1];
+ unsigned int id=atoi(cmds[2].c_str());
+ DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
+ cout << zone<<" IN DNSKEY "<<dpk.getDNSKEY().getZoneRepresentation() <<endl;
+ if(dpk.d_flags == 257)
+ cout << zone << " IN DS "<<makeDSFromDNSKey(zone, dpk.getDNSKEY()).getZoneRepresentation() << endl;
+ }
else {
cerr<<"Unknown command '"<<cmds[0]<<"'\n";
return 1;