root/trunk/pdns/pdns/pdnssec.cc @ 1953

Revision 1953, 20.5 KB (checked in by ahu, 2 years ago)

add support for Crypto++ ECDSA, refine & rename CryptoKeyEngine? interface, add 'pdnssec test-algorithm' mutual testing between engines, which found a bunch of bugs (fixed)

Line 
1#include "dnsseckeeper.hh"
2#include "dnssecinfra.hh"
3#include "statbag.hh"
4#include "base32.hh"
5#include "base64.hh"
6#include <boost/foreach.hpp>
7#include <boost/program_options.hpp>
8#include "dnsbackend.hh"
9#include "ueberbackend.hh"
10#include "arguments.hh"
11#include "packetcache.hh"
12#include "zoneparser-tng.hh"
13StatBag S;
14PacketCache PC;
15
16using namespace boost;
17namespace po = boost::program_options;
18po::variables_map g_vm;
19
20string s_programname="pdns";
21
22ArgvMap &arg()
23{
24  static ArgvMap arg;
25  return arg;
26}
27
28string humanTime(time_t t)
29{
30  char ret[256];
31  struct tm tm;
32  localtime_r(&t, &tm);
33  strftime(ret, sizeof(ret)-1, "%c", &tm);   // %h:%M %Y-%m-%d
34  return ret;
35}
36
37void loadMainConfig(const std::string& configdir)
38{
39  ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=configdir;
40 
41  ::arg().set("launch","Which backends to launch");
42  ::arg().set("dnssec","if we should do dnssec")="true";
43  ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")=g_vm["config-name"].as<string>();
44  ::arg().setCmd("help","Provide a helpful message");
45  //::arg().laxParse(argc,argv);
46
47  if(::arg().mustDo("help")) {
48    cerr<<"syntax:"<<endl<<endl;
49    cerr<<::arg().helpstring(::arg()["help"])<<endl;
50    exit(99);
51  }
52
53  if(::arg()["config-name"]!="") 
54    s_programname+="-"+::arg()["config-name"];
55
56  string configname=::arg()["config-dir"]+"/"+s_programname+".conf";
57  cleanSlashes(configname);
58 
59  ::arg().laxFile(configname.c_str());
60  ::arg().set("module-dir","Default directory for modules")=LIBDIR;
61  BackendMakers().launch(::arg()["launch"]); // vrooooom!
62  ::arg().laxFile(configname.c_str());   
63  //cerr<<"Backend: "<<::arg()["launch"]<<", '" << ::arg()["gmysql-dbname"] <<"'" <<endl;
64
65  S.declare("qsize-q","Number of questions waiting for database attention");
66   
67  S.declare("deferred-cache-inserts","Amount of cache inserts that were deferred because of maintenance");
68  S.declare("deferred-cache-lookup","Amount of cache lookups that were deferred because of maintenance");
69         
70  S.declare("query-cache-hit","Number of hits on the query cache");
71  S.declare("query-cache-miss","Number of misses on the query cache");
72  ::arg().set("max-cache-entries", "Maximum number of cache entries")="1000000";
73  ::arg().set("recursor","If recursion is desired, IP address of a recursing nameserver")="no"; 
74  ::arg().set("recursive-cache-ttl","Seconds to store packets in the PacketCache")="10";
75  ::arg().set("cache-ttl","Seconds to store packets in the PacketCache")="20";             
76  ::arg().set("negquery-cache-ttl","Seconds to store packets in the PacketCache")="60";
77  ::arg().set("query-cache-ttl","Seconds to store packets in the PacketCache")="20";             
78  ::arg().set("soa-refresh-default","Default SOA refresh")="10800";
79  ::arg().set("soa-retry-default","Default SOA retry")="3600";
80  ::arg().set("soa-expire-default","Default SOA expire")="604800";
81    ::arg().setSwitch("query-logging","Hint backends that queries should be logged")="no";
82  ::arg().set("soa-minimum-ttl","Default SOA mininum ttl")="3600";   
83 
84  UeberBackend::go();
85}
86
87void rectifyZone(DNSSECKeeper& dk, const std::string& zone)
88{
89  UeberBackend* B = new UeberBackend("default");
90  SOAData sd;
91 
92  if(!B->getSOA(zone, sd)) {
93    cerr<<"No SOA known for '"<<zone<<"', is such a zone in the database?"<<endl;
94    return;
95  } 
96  sd.db->list(zone, sd.domain_id);
97  DNSResourceRecord rr;
98
99  set<string> qnames, nsset;
100 
101  while(sd.db->get(rr)) {
102    qnames.insert(rr.qname);
103    if(rr.qtype.getCode() == QType::NS && !pdns_iequals(rr.qname, zone)) 
104      nsset.insert(rr.qname);
105  }
106
107  NSEC3PARAMRecordContent ns3pr;
108  bool narrow;
109  bool haveNSEC3=dk.getNSEC3PARAM(zone, &ns3pr, &narrow);
110  string hashed;
111  if(!haveNSEC3) 
112    cerr<<"Adding NSEC ordering information"<<endl;
113  else if(!narrow)
114    cerr<<"Adding NSEC3 hashed ordering information for '"<<zone<<"'"<<endl;
115  else 
116    cerr<<"Erasing NSEC3 ordering since we are narrow, only setting 'auth' fields"<<endl;
117 
118  sd.db->startTransaction("", -1);
119  BOOST_FOREACH(const string& qname, qnames)
120  {
121    string shorter(qname);
122    bool auth=true;
123    do {
124      if(nsset.count(shorter)) { 
125        auth=false;
126        break;
127      }
128    }while(chopOff(shorter));
129
130    if(!haveNSEC3) // NSEC
131      sd.db->updateDNSSECOrderAndAuth(sd.domain_id, zone, qname, auth);
132    else {
133      if(!narrow) {
134        hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, qname)));
135        cerr<<"'"<<qname<<"' -> '"<< hashed <<"'"<<endl;
136      }
137      sd.db->updateDNSSECOrderAndAuthAbsolute(sd.domain_id, qname, hashed, auth);
138    }
139  }
140  sd.db->commitTransaction();
141  cerr<<"Done listing"<<endl;
142}
143
144void checkZone(DNSSECKeeper& dk, const std::string& zone)
145{
146  UeberBackend* B = new UeberBackend("default");
147  SOAData sd;
148 
149  if(!B->getSOA(zone, sd)) {
150    cerr<<"No SOA!"<<endl;
151    return;
152  } 
153  sd.db->list(zone, sd.domain_id);
154  DNSResourceRecord rr;
155  uint64_t numrecords=0, numerrors=0;
156 
157  while(sd.db->get(rr)) {
158    if(rr.qtype.getCode() == QType::MX) 
159      rr.content = lexical_cast<string>(rr.priority)+" "+rr.content;
160    if(rr.auth == 0 && rr.qtype.getCode()!=QType::NS && rr.qtype.getCode()!=QType::A)
161    {
162      cerr<<"Following record is auth=0, run pdnssec rectify-zone?: "<<rr.qname<<" IN " <<rr.qtype.getName()<< " " << rr.content<<endl;
163    }
164    try {
165      shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content));
166      string tmp=drc->serialize(rr.qname);
167    }
168    catch(std::exception& e) 
169    {
170      cerr<<"Following record had a problem: "<<rr.qname<<" IN " <<rr.qtype.getName()<< " " << rr.content<<endl;
171      cerr<<"Error was: "<<e.what()<<endl;
172      numerrors++;
173    }
174    numrecords++;
175  }
176  cerr<<"Checked "<<numrecords<<" records, "<<numerrors<<" errors"<<endl;
177}
178
179void testAlgorithms()
180{
181  DNSCryptoKeyEngine::testAll();
182}
183
184void verifyCrypto(const string& zone)
185{
186  ZoneParserTNG zpt(zone);
187  DNSResourceRecord rr;
188  DNSKEYRecordContent drc;
189  RRSIGRecordContent rrc;
190  DSRecordContent dsrc;
191  vector<shared_ptr<DNSRecordContent> > toSign;
192  unsigned int ttl;
193  string qname, apex;
194  dsrc.d_digesttype=0;
195  while(zpt.get(rr)) {
196    if(rr.qtype.getCode() == QType::DNSKEY) {
197      cerr<<"got DNSKEY!"<<endl;
198      apex=rr.qname;
199      drc = *dynamic_cast<DNSKEYRecordContent*>(DNSRecordContent::mastermake(QType::DNSKEY, 1, rr.content));
200    }
201    else if(rr.qtype.getCode() == QType::RRSIG) {
202      cerr<<"got RRSIG"<<endl;
203      rrc = *dynamic_cast<RRSIGRecordContent*>(DNSRecordContent::mastermake(QType::RRSIG, 1, rr.content));
204    }
205    else if(rr.qtype.getCode() == QType::DS) {
206      cerr<<"got DS"<<endl;
207      dsrc = *dynamic_cast<DSRecordContent*>(DNSRecordContent::mastermake(QType::DS, 1, rr.content));
208    }
209    else {
210      qname = rr.qname;
211      ttl = rr.ttl;
212      toSign.push_back(shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content)));
213    }
214  }
215 
216  string msg = getMessageForRRSET(qname, rrc, toSign);       
217  DNSCryptoKeyEngine* dpk = DNSCryptoKeyEngine::make(rrc.d_algorithm);
218  string hash = dpk->sign(msg);
219  cerr<<"Verify: "<<DNSCryptoKeyEngine::makeFromPublicKeyString(drc.d_algorithm, drc.d_key)->verify(hash, rrc.d_signature)<<endl;
220  if(dsrc.d_digesttype) {
221    cerr<<"Calculated DS: "<<apex<<" IN DS "<<makeDSFromDNSKey(apex, drc, dsrc.d_digesttype).getZoneRepresentation()<<endl;
222    cerr<<"Original DS:   "<<apex<<" IN DS "<<dsrc.getZoneRepresentation()<<endl;
223  }
224#if 0
225  DNSCryptoKeyEngine*key=DNSCryptoKeyEngine::makeFromISCString(drc, "Private-key-format: v1.2\n"
226      "Algorithm: 12 (ECC-GOST)\n"
227      "GostAsn1: MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgQg/9MiXtXKg9FDXDN/R9CmVhJDyuzRAIgh4tPwCu4NHIs=\n");
228  string resign=key->sign(hash);
229  cerr<<Base64Encode(resign)<<endl;
230  cerr<<"Verify: "<<DNSCryptoKeyEngine::makeFromPublicKeyString(drc.d_algorithm, drc.d_key)->verify(hash, resign)<<endl;
231#endif
232
233}
234
235void showZone(DNSSECKeeper& dk, const std::string& zone)
236{
237  if(!dk.isSecuredZone(zone)) {
238        cerr<<"Zone is not secured\n";
239        return;
240  }
241  NSEC3PARAMRecordContent ns3pr;
242  bool narrow;
243  bool haveNSEC3=dk.getNSEC3PARAM(zone, &ns3pr, &narrow);
244 
245  if(!haveNSEC3) 
246    cout<<"Zone has NSEC semantics"<<endl;
247  else
248    cout<<"Zone has " << (narrow ? "NARROW " : "") <<"hashed NSEC3 semantics, configuration: "<<ns3pr.getZoneRepresentation()<<endl;
249 
250  cout <<"Zone is " << (dk.isPresigned(zone) ? "" : "not ") << "presigned\n";
251 
252  DNSSECKeeper::keyset_t keyset=dk.getKeys(zone);
253
254  if(keyset.empty())  {
255    cerr << "No keys for zone '"<<zone<<"'."<<endl;
256  }
257  else { 
258    cout << "keys: "<<endl;
259    BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, keyset) {
260      cout<<"ID = "<<value.second.id<<" ("<<(value.second.keyOrZone ? "KSK" : "ZSK")<<"), tag = "<<value.first.getDNSKEY().getTag();
261      cout<<", algo = "<<(int)value.first.d_algorithm<<", bits = "<<value.first.getKey()->getBits()<<"\tActive: "<<value.second.active<< endl; 
262      if(value.second.keyOrZone) {
263        cout<<"KSK DNSKEY = "<<zone<<" IN DNSKEY "<< value.first.getDNSKEY().getZoneRepresentation() << endl;
264        cout<<"DS = "<<zone<<" IN DS "<<makeDSFromDNSKey(zone, value.first.getDNSKEY(), 1).getZoneRepresentation() << endl;
265        cout<<"DS = "<<zone<<" IN DS "<<makeDSFromDNSKey(zone, value.first.getDNSKEY(), 2).getZoneRepresentation() << endl;
266        try {
267          string output=makeDSFromDNSKey(zone, value.first.getDNSKEY(), 3).getZoneRepresentation();
268          cout<<"DS = "<<zone<<" IN DS "<< output << endl;
269        }
270        catch(...)
271        {
272        }
273        cout<<endl; 
274      }
275    }
276  }
277}
278
279int main(int argc, char** argv)
280try
281{
282  po::options_description desc("Allowed options");
283  desc.add_options()
284    ("help,h", "produce help message")
285    ("verbose,v", po::value<bool>(), "be verbose")
286    ("force", "force an action")
287    ("config-name", po::value<string>()->default_value(""), "virtual configuration name")
288    ("config-dir", po::value<string>()->default_value(SYSCONFDIR), "location of pdns.conf")
289    ("commands", po::value<vector<string> >());
290
291  po::positional_options_description p;
292  p.add("commands", -1);
293  po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), g_vm);
294  po::notify(g_vm);
295
296  vector<string> cmds;
297
298  if(g_vm.count("commands")) 
299    cmds = g_vm["commands"].as<vector<string> >();
300
301  if(cmds.empty() || g_vm.count("help")) {
302    cerr<<"Usage: \npdnssec [options] [show-zone] [secure-zone] [rectify-zone] [add-zone-key] [deactivate-zone-key] [remove-zone-key] [activate-zone-key]\n";
303    cerr<<"         [import-zone-key] [export-zone-key] [set-nsec3] [set-presigned] [unset-nsec3] [unset-presigned] [export-zone-dnskey]\n\n";
304    cerr<<"activate-zone-key ZONE KEY-ID   Activate the key with key id KEY-ID in ZONE\n";
305    cerr<<"add-zone-key ZONE [zsk|ksk]     Add a ZSK or KSK to a zone\n";
306    cerr<<"  [bits] [rsasha1|rsasha256]    and specify algorithm & bits\n";
307    cerr<<"check-zone ZONE                 Check a zone for correctness\n";
308    cerr<<"deactivate-zone-key             Dectivate the key with key id KEY-ID in ZONE\n";
309    cerr<<"export-zone-dnskey ZONE KEY-ID  Export to stdout the public DNSKEY described\n";
310    cerr<<"export-zone-key ZONE KEY-ID     Export to stdout the private key described\n";
311    cerr<<"import-zone-key ZONE FILE       Import from a file a private key, ZSK or KSK\n";           
312    cerr<<"                [ksk|zsk]       Defaults to KSK\n";
313    cerr<<"rectify-zone ZONE               Fix up DNSSEC fields (order, auth)\n";
314    cerr<<"remove-zone-key ZONE KEY-ID     Remove key with KEY-ID from ZONE\n";
315    cerr<<"secure-zone                     Add KSK and two ZSKs\n";
316    cerr<<"set-nsec3 ZONE 'params' [narrow]     Enable NSEC3 with PARAMs. Optionally narrow\n";
317    cerr<<"set-presigned ZONE              Use presigned RRSIGs from storage\n";
318    cerr<<"show-zone ZONE                  Show DNSSEC (public) key details about a zone\n";
319    cerr<<"unset-nsec3 ZONE                Switch back to NSEC\n";
320        cerr<<"unset-presigned ZONE            No longer use presigned RRSIGs\n\n";
321    cerr<<"Options:"<<endl;
322    cerr<<desc<<endl;
323    return 0;
324  }
325 
326  loadMainConfig(g_vm["config-dir"].as<string>());
327  reportAllTypes();
328  DNSSECKeeper dk;
329
330  if(cmds[0] == "rectify-zone" || cmds[0] == "order-zone") {
331    if(cmds.size() != 2) {
332      cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
333      return 0;
334    }
335    rectifyZone(dk, cmds[1]);
336  }
337  else if(cmds[0] == "check-zone") {
338    if(cmds.size() != 2) {
339      cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
340      return 0;
341    }
342    checkZone(dk, cmds[1]);
343  }
344  else if(cmds[0] == "test-algorithms") {
345    testAlgorithms();
346  }
347  else if(cmds[0] == "verify-crypto") {
348    if(cmds.size() != 2) {
349      cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
350      return 0;
351    }
352    verifyCrypto(cmds[1]);
353  }
354
355  else if(cmds[0] == "show-zone") {
356    if(cmds.size() != 2) {
357      cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
358      return 0;
359    }
360    const string& zone=cmds[1];
361    showZone(dk, zone);
362  }
363  else if(cmds[0] == "activate-zone-key") {
364    const string& zone=cmds[1];
365    unsigned int id=atoi(cmds[2].c_str());
366    dk.activateKey(zone, id);
367  }
368  else if(cmds[0] == "deactivate-zone-key") {
369    const string& zone=cmds[1];
370    unsigned int id=atoi(cmds[2].c_str());
371    dk.deactivateKey(zone, id);
372  }
373  else if(cmds[0] == "add-zone-key") {
374    const string& zone=cmds[1];
375    // need to get algorithm, bits & ksk or zsk from commandline
376    bool keyOrZone=false;
377    int bits=0;
378    int algorithm=5;
379    for(unsigned int n=2; n < cmds.size(); ++n) {
380      if(pdns_iequals(cmds[n], "zsk"))
381        keyOrZone = false;
382      else if(pdns_iequals(cmds[n], "ksk"))
383        keyOrZone = true;
384      else if(pdns_iequals(cmds[n], "rsasha1"))
385        algorithm=5;
386      else if(pdns_iequals(cmds[n], "rsasha256"))
387        algorithm=8;
388      else if(pdns_iequals(cmds[n], "rsasha512"))
389        algorithm=10;
390      else if(pdns_iequals(cmds[n], "gost"))
391        algorithm=12;
392      else if(pdns_iequals(cmds[n], "ecdsa256"))
393        algorithm=13;
394      else if(pdns_iequals(cmds[n], "ecdsa384"))
395        algorithm=14;
396      else if(atoi(cmds[n].c_str()))
397        bits = atoi(cmds[n].c_str());
398      else { 
399        cerr<<"Unknown algorithm, key flag or size '"<<cmds[n]<<"'"<<endl;
400        return 0;
401      }
402    }
403    cerr<<"Adding a " << (keyOrZone ? "KSK" : "ZSK")<<" with algorithm = "<<algorithm<<endl;
404    if(bits)
405      cerr<<"Requesting specific key size of "<<bits<<" bits"<<endl;
406    dk.addKey(zone, keyOrZone, algorithm, bits); 
407  }
408  else if(cmds[0] == "remove-zone-key") {
409    if(cmds.size() < 3) {
410      cerr<<"Syntax: pdnssec remove-zone-key ZONE KEY-ID\n";
411      return 0;
412    }
413    const string& zone=cmds[1];
414    unsigned int id=atoi(cmds[2].c_str());
415    dk.removeKey(zone, id);
416  }
417 
418  else if(cmds[0] == "secure-zone") {
419    if(cmds.size() != 2) {
420      cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
421      return 0;
422    }
423    const string& zone=cmds[1];
424    DNSSECPrivateKey dpk;
425   
426    if(dk.isSecuredZone(zone)) {
427      cerr << "Zone '"<<zone<<"' already secure, remove with pdnssec remove-zone-key if needed"<<endl;
428      return 0;
429    }
430     
431    dk.secureZone(zone, 8);
432
433    if(!dk.isSecuredZone(zone)) {
434      cerr<<"Failed to secure zone - if you run with the BIND backend, make sure to also\n";
435      cerr<<"launch another backend which supports storage of DNSSEC settings.\n";
436      cerr<<"In addition, add '"<<zone<<"' to this backend, possibly like this: \n\n";
437      cerr<<"   insert into domains (name, type) values ('"<<zone<<"', 'NATIVE');\n\n";
438      cerr<<"And then rerun secure-zone"<<endl;
439      return 0;
440    }
441 
442    DNSSECKeeper::keyset_t zskset=dk.getKeys(zone, false);
443
444    if(!zskset.empty())  {
445      cerr<<"There were ZSKs already for zone '"<<zone<<"', no need to add more"<<endl;
446      return 0;
447    }
448     
449    dk.addKey(zone, false, 8);
450    dk.addKey(zone, false, 8, 0, false); // not active
451    rectifyZone(dk, zone);
452    showZone(dk, zone);
453  }
454  else if(cmds[0]=="set-nsec3") {
455    string nsec3params =  cmds.size() > 2 ? cmds[2] : "1 1 1 ab";
456    bool narrow = cmds.size() > 3 && cmds[3]=="narrow";
457    NSEC3PARAMRecordContent ns3pr(nsec3params);
458    if(!ns3pr.d_flags) {
459      cerr<<"PowerDNS only implements opt-out zones, please set the second parameter to '1' (example, '1 1 1 ab')"<<endl;
460      return 0;
461    }
462   
463    dk.setNSEC3PARAM(cmds[1], ns3pr, narrow);
464  }
465  else if(cmds[0]=="set-presigned") {
466        if(cmds.size() < 2) {
467                cerr<<"Wrong number of arguments, syntax: set-presigned DOMAIN"<<endl;
468        }
469    dk.setPresigned(cmds[1]);
470  }
471  else if(cmds[0]=="unset-presigned") {
472        if(cmds.size() < 2) {
473                cerr<<"Wrong number of arguments, syntax: unset-presigned DOMAIN"<<endl;
474        }
475    dk.unsetPresigned(cmds[1]);
476  }
477  else if(cmds[0]=="hash-zone-record") {
478    if(cmds.size() < 3) {
479      cerr<<"Wrong number of arguments, syntax: hash-zone-record ZONE RECORD"<<endl;
480      return 0;
481    }
482    string& zone=cmds[1];
483    string& record=cmds[2];
484    NSEC3PARAMRecordContent ns3pr;
485    bool narrow;
486    if(!dk.getNSEC3PARAM(zone, &ns3pr, &narrow)) {
487      cerr<<"The '"<<zone<<"' zone does not use NSEC3"<<endl;
488      return 0;
489    }
490    if(!narrow) {
491      cerr<<"The '"<<zone<<"' zone uses narrow NSEC3, but calculating hash anyhow"<<endl;
492    }
493     
494    cout<<toLower(toBase32Hex(hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, record)))<<endl;
495  }
496  else if(cmds[0]=="unset-nsec3") {
497    dk.unsetNSEC3PARAM(cmds[1]);
498  }
499  else if(cmds[0]=="export-zone-key") {
500    if(cmds.size() < 3) {
501      cerr<<"Syntax: pdnssec export-zone-key zone-name id"<<endl;
502      cerr<<cmds.size()<<endl;
503      exit(1);
504    }
505
506    string zone=cmds[1];
507    unsigned int id=atoi(cmds[2].c_str());
508    DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
509    cout << dpk.getKey()->convertToISC() <<endl;
510  } 
511  else if(cmds[0]=="import-zone-key-pem") {
512    if(cmds.size() < 4) {
513      cerr<<"Syntax: pdnssec import-zone-key zone-name filename.pem algorithm [zsk|ksk]"<<endl;
514      exit(1);
515    }
516    string zone=cmds[1];
517    string fname=cmds[2];
518    string line;
519    ifstream ifs(fname.c_str());
520    string tmp, interim, raw;
521    while(getline(ifs, line)) {
522      if(line[0]=='-')
523        continue;
524      trim(line);
525      interim += line;
526    }
527    B64Decode(interim, raw);
528    DNSSECPrivateKey dpk;
529    DNSKEYRecordContent drc;
530    shared_ptr<DNSCryptoKeyEngine> key(DNSCryptoKeyEngine::makeFromPEMString(drc, raw));
531    dpk.setKey(key);
532   
533    dpk.d_algorithm = atoi(cmds[3].c_str());
534   
535    if(dpk.d_algorithm == 7)
536      dpk.d_algorithm = 5;
537     
538    cerr<<(int)dpk.d_algorithm<<endl;
539   
540    if(cmds.size() > 4) {
541      if(pdns_iequals(cmds[4], "ZSK"))
542        dpk.d_flags = 256;
543      else if(pdns_iequals(cmds[4], "KSK"))
544        dpk.d_flags = 257;
545      else {
546        cerr<<"Unknown key flag '"<<cmds[4]<<"'\n";
547        exit(1);
548      }
549    }
550    else
551      dpk.d_flags = 257; // ksk
552     
553    dk.addKey(zone, dpk); 
554   
555  }
556  else if(cmds[0]=="import-zone-key") {
557    if(cmds.size() < 3) {
558      cerr<<"Syntax: pdnssec import-zone-key zone-name filename [zsk|ksk]"<<endl;
559      exit(1);
560    }
561    string zone=cmds[1];
562    string fname=cmds[2];
563    DNSSECPrivateKey dpk;
564    DNSKEYRecordContent drc;
565    shared_ptr<DNSCryptoKeyEngine> key(DNSCryptoKeyEngine::makeFromISCFile(drc, fname.c_str()));
566    dpk.setKey(key);
567    dpk.d_algorithm = drc.d_algorithm;
568   
569    if(dpk.d_algorithm == 7)
570      dpk.d_algorithm = 5;
571     
572    cerr<<(int)dpk.d_algorithm<<endl;
573   
574    if(cmds.size() > 3) {
575      if(pdns_iequals(cmds[3], "ZSK"))
576        dpk.d_flags = 256;
577      else if(pdns_iequals(cmds[3], "KSK"))
578        dpk.d_flags = 257;
579      else {
580        cerr<<"Unknown key flag '"<<cmds[3]<<"'\n";
581        exit(1);
582      }
583    }
584    else
585      dpk.d_flags = 257; 
586     
587    dk.addKey(zone, dpk); 
588  }
589  else if(cmds[0]=="export-zone-dnskey") {
590    if(cmds.size() < 3) {
591      cerr<<"Syntax: pdnssec export-zone-dnskey zone-name id"<<endl;
592      exit(1);
593    }
594
595    string zone=cmds[1];
596    unsigned int id=atoi(cmds[2].c_str());
597    DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
598    cout << zone<<" IN DNSKEY "<<dpk.getDNSKEY().getZoneRepresentation() <<endl;
599    if(dpk.d_flags == 257) {
600      cout << zone << " IN DS "<<makeDSFromDNSKey(zone, dpk.getDNSKEY(), 1).getZoneRepresentation() << endl;
601      cout << zone << " IN DS "<<makeDSFromDNSKey(zone, dpk.getDNSKEY(), 2).getZoneRepresentation() << endl;
602    }
603  }
604  else {
605    cerr<<"Unknown command '"<<cmds[0]<<"'\n";
606    return 1;
607  }
608  return 0;
609}
610catch(AhuException& ae) {
611  cerr<<"Error: "<<ae.reason<<endl;
612}
613catch(std::exception& e) {
614  cerr<<"Error: "<<e.what()<<endl;
615}
Note: See TracBrowser for help on using the browser.