]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/pdnsutil.cc
Merge pull request #3169 from zeha/createzonesoa
[thirdparty/pdns.git] / pdns / pdnsutil.cc
index 0813efa83ad5fd45f7d3ec927f3fac386afa73da..02abec4a7ab96d92ee6e6fb2cf7930ee492d02a5 100644 (file)
@@ -21,6 +21,9 @@
 #ifdef HAVE_LIBSODIUM
 #include <sodium.h>
 #endif
+#ifdef HAVE_OPENSSL
+#include "opensslsigners.hh"
+#endif
 #ifdef HAVE_SQLITE3
 #include "ssqlite3.hh"
 #include "bind-dnssec.schema.sqlite3.sql.h"
@@ -138,7 +141,7 @@ void loadMainConfig(const std::string& configdir)
 
   ::arg().set("default-ksk-algorithms","Default KSK algorithms")="";
   ::arg().set("default-ksk-size","Default KSK size (0 means default)")="0";
-  ::arg().set("default-zsk-algorithms","Default ZSK algorithms")="rsasha256";
+  ::arg().set("default-zsk-algorithms","Default ZSK algorithms")="ecdsa256";
   ::arg().set("default-zsk-size","Default ZSK size (0 means default)")="0";
   ::arg().set("default-soa-edit","Default SOA-EDIT value")="";
   ::arg().set("default-soa-edit-signed","Default SOA-EDIT value for signed zones")="";
@@ -420,7 +423,7 @@ int checkZone(DNSSECKeeper &dk, UeberBackend &B, const DNSName& zone)
 
   if (haveNSEC3 && isSecure && zone.wirelength() > 222) {
     numerrors++;
-    cerr<<"[Error] zone '" << zone.toStringNoDot() << "' has NSEC3 semantics but is too long to have the hash prepended. Zone name is " << zone.wirelength() << " bytes long, whereas the maximum is 222 bytes." << endl;
+    cout<<"[Error] zone '" << zone.toStringNoDot() << "' has NSEC3 semantics but is too long to have the hash prepended. Zone name is " << zone.wirelength() << " bytes long, whereas the maximum is 222 bytes." << endl;
   }
 
   // Check for delegation in parent zone
@@ -434,7 +437,7 @@ int checkZone(DNSSECKeeper &dk, UeberBackend &B, const DNSName& zone)
       while(B.get(rr))
         ns |= (rr.qtype == QType::NS);
       if (!ns) {
-        cerr<<"[Error] No delegation for zone '"<<zone.toString()<<"' in parent '"<<parent.toString()<<"'"<<endl;
+        cout<<"[Error] No delegation for zone '"<<zone.toString()<<"' in parent '"<<parent.toString()<<"'"<<endl;
         numerrors++;
       }
       break;
@@ -450,7 +453,7 @@ int checkZone(DNSSECKeeper &dk, UeberBackend &B, const DNSName& zone)
   ostringstream content;
   pair<map<string, unsigned int>::iterator,bool> ret;
 
-  sd.db->list(zone, sd.domain_id, true);
+  sd.db->list(zone, sd.domain_id, false);
 
   while(sd.db->get(rr)) {
     if(!rr.qtype.getCode())
@@ -651,7 +654,7 @@ int checkZone(DNSSECKeeper &dk, UeberBackend &B, const DNSName& zone)
 
   for(const auto &qname : checkglue) {
     if (!glue.count(qname)) {
-      cerr<<"[Warning] Missing glue for '"<<qname.toString()<<"' in zone '"<<zone.toString()<<"'"<<endl;
+      cout<<"[Warning] Missing glue for '"<<qname.toString()<<"' in zone '"<<zone.toString()<<"'"<<endl;
       numwarnings++;
     }
   }
@@ -687,7 +690,7 @@ int increaseSerial(const DNSName& zone, DNSSECKeeper &dk)
   UeberBackend B("default");
   SOAData sd;
   if(!B.getSOAUncached(zone, sd)) {
-    cout<<"No SOA for zone '"<<zone.toString()<<"'"<<endl;
+    cerr<<"No SOA for zone '"<<zone.toString()<<"'"<<endl;
     return -1;
   }
 
@@ -930,6 +933,24 @@ int createZone(const DNSName &zone) {
     cerr<<"Domain '"<<zone.toString()<<"' was not created!"<<endl;
     return 1;
   }
+
+  DNSResourceRecord rr;
+  rr.qname = zone;
+  rr.auth = 1;
+  rr.ttl = ::arg().asNum("default-ttl");
+  rr.qtype = "SOA";
+  string soa = (boost::format("%s %s 1")
+    % ::arg()["default-soa-name"]
+    % (::arg().isEmpty("default-soa-mail") ? (DNSName("hostmaster.") + zone).toString() : ::arg()["default-soa-mail"])
+  ).str();
+  SOAData sd;
+  fillSOAData(soa, sd);  // fills out default values for us
+  rr.content = DNSRecordContent::mastermake(rr.qtype.getCode(), 1, serializeSOAData(sd))->getZoneRepresentation(true);
+  rr.domain_id = di.id;
+  di.backend->startTransaction(zone, di.id);
+  di.backend->feedRecord(rr);
+  di.backend->commitTransaction();
+
   return 1;
 }
 
@@ -1129,9 +1150,59 @@ bool showZone(DNSSECKeeper& dk, const DNSName& zone)
      cerr << "Zone uses following TSIG key(s): " << boost::join(meta, ",") << endl;
   }
   
-  cout <<"Zone is " << (dk.isPresigned(zone) ? "" : "not ") << "presigned"<<endl;
+  if (dk.isPresigned(zone)) {
+    cout <<"Zone is " << (dk.isPresigned(zone) ? "" : "not ") << "presigned"<<endl;
+    // get us some keys
+    vector<DNSKEYRecordContent> keys;
+    DNSResourceRecord rr;
 
-  if(keyset.empty())  {
+    B.lookup(QType(QType::DNSKEY), DNSName(zone));
+    while(B.get(rr)) {
+      if (rr.qtype != QType::DNSKEY) continue;
+      keys.push_back(*dynamic_cast<DNSKEYRecordContent*>(DNSKEYRecordContent::make(rr.getZoneRepresentation())));
+    }
+
+    if(keys.empty()) {
+      cerr << "No keys for zone '"<<zone.toString()<<"'."<<endl;
+      return true;
+    }
+
+    if(!haveNSEC3)
+      cout<<"Zone has NSEC semantics"<<endl;
+    else
+      cout<<"Zone has " << (narrow ? "NARROW " : "") <<"hashed NSEC3 semantics, configuration: "<<ns3pr.getZoneRepresentation()<<endl;
+    cout << "keys: "<<endl;
+    sort(keys.begin(),keys.end());
+    reverse(keys.begin(),keys.end());
+    bool shown=false;
+    for(const auto& key : keys) {
+      string algname;
+      algorithm2name(key.d_algorithm,algname);
+      int bits;
+      if (key.d_key[0] == 0)
+        bits = *(uint16_t*)(key.d_key.c_str()+1);
+      else
+        bits = *(uint8_t*)key.d_key.c_str();
+      bits = (key.d_key.size() - (bits+1))*8;
+      cout << (key.d_flags == 257 ? "KSK" : "ZSK") << ", tag = " << key.getTag() << ", algo = "<<(int)key.d_algorithm << ", bits = " << bits << endl;
+      cout << "DNSKEY = " <<zone.toString()<<" IN DNSKEY "<< key.getZoneRepresentation() << "; ( " + algname + " ) " <<endl;
+      if (shown) continue;
+      shown=true;
+      cout<<"DS = "<<zone.toString()<<" IN DS "<<makeDSFromDNSKey(zone, key, 1).getZoneRepresentation() << " ; ( SHA1 digest )" << endl;
+      cout<<"DS = "<<zone.toString()<<" IN DS "<<makeDSFromDNSKey(zone, key, 2).getZoneRepresentation() << " ; ( SHA256 digest )" << endl;
+      try {
+        cout<<"DS = "<<zone.toString()<<" IN DS "<<makeDSFromDNSKey(zone, key, 3).getZoneRepresentation() << " ; ( GOST R 34.11-94 digest )" << endl;
+      }
+      catch(...)
+      {}
+      try {
+        cout<<"DS = "<<zone.toString()<<" IN DS "<<makeDSFromDNSKey(zone, key, 4).getZoneRepresentation() << " ; ( SHA-384 digest )" << endl;
+      }
+      catch(...)
+      {}
+    }
+  }
+  else if(keyset.empty())  {
     cerr << "No keys for zone '"<<zone.toString()<<"'."<<endl;
   }
   else {  
@@ -1209,14 +1280,14 @@ bool secureZone(DNSSECKeeper& dk, const DNSName& zone)
   DomainInfo di;
   UeberBackend B("default");
   if(!B.getDomainInfo(zone, di) || !di.backend) { // di.backend and B are mostly identical
-    cout<<"Can't find a zone called '"<<zone.toString()<<"'"<<endl;
+    cerr<<"Can't find a zone called '"<<zone.toString()<<"'"<<endl;
     return false;
   }
 
   if(di.kind == DomainInfo::Slave)
   {
-    cout<<"Warning! This is a slave domain! If this was a mistake, please run"<<endl;
-    cout<<"pdnsutil disable-dnssec "<<zone.toString()<<" right now!"<<endl;
+    cerr<<"Warning! This is a slave domain! If this was a mistake, please run"<<endl;
+    cerr<<"pdnsutil disable-dnssec "<<zone.toString()<<" right now!"<<endl;
   }
 
   if (k_size)
@@ -1474,6 +1545,10 @@ try
     return 0;
   }
 
+loadMainConfig(g_vm["config-dir"].as<string>());
+
+seedRandom(::arg()["entropy-source"]);
+
 #ifdef HAVE_LIBSODIUM
   if (sodium_init() == -1) {
     cerr<<"Unable to initialize sodium crypto library"<<endl;
@@ -1481,6 +1556,10 @@ try
   }
 #endif
 
+#ifdef HAVE_OPENSSL
+  openssl_seed();
+#endif
+
   if (cmds[0] == "test-algorithm") {
     if(cmds.size() != 2) {
       cerr << "Syntax: pdnsutil test-algorithm algonum"<<endl;
@@ -1497,7 +1576,6 @@ try
     return 1;
   }
 
-  loadMainConfig(g_vm["config-dir"].as<string>());
   reportAllTypes();
 
   if(cmds[0] == "create-bind-db") {
@@ -1560,7 +1638,7 @@ try
     dbBench(cmds.size() > 1 ? cmds[1] : "");
   }
   else if (cmds[0] == "check-all-zones") {
-    bool exitOnError = (cmds[1] == "exit-on-error");
+    bool exitOnError = ((cmds.size() >= 2 ? cmds[1] : "") == "exit-on-error");
     exit(checkAllZones(dk, exitOnError));
   }
   else if (cmds[0] == "list-all-zones") {
@@ -1604,7 +1682,6 @@ try
     }
     verifyCrypto(cmds[1]);
   }
-
   else if(cmds[0] == "show-zone") {
     if(cmds.size() != 2) {
       cerr << "Syntax: pdnsutil show-zone ZONE"<<endl;
@@ -2154,7 +2231,6 @@ try
      }
 
      cerr << "Generating new key with " << klen << " bytes (this can take a while)" << endl;
-     seedRandom(::arg()["entropy-source"]);
      for(size_t i = 0; i < klen; i+=4) {
         *(unsigned int*)(tmpkey+i) = dns_random(0xffffffff);
      }
@@ -2164,7 +2240,7 @@ try
      if (B.setTSIGKey(name, DNSName(algo), key)) { // you are feeling bored, put up DNSName(algo) up earlier
        cout << "Create new TSIG key " << name << " " << algo << " " << key << endl;
      } else {
-       cout << "Failure storing new TSIG key " << name << " " << algo << " " << key << endl;
+       cerr << "Failure storing new TSIG key " << name << " " << algo << " " << key << endl;
        return 1;
      }
      return 0;
@@ -2181,7 +2257,7 @@ try
      if (B.setTSIGKey(name, DNSName(algo), key)) {
        cout << "Imported TSIG key " << name << " " << algo << endl;
      } else {
-       cout << "Failure importing TSIG key " << name << " " << algo << endl;
+       cerr << "Failure importing TSIG key " << name << " " << algo << endl;
        return 1;
      }
      return 0;
@@ -2196,7 +2272,7 @@ try
      if (B.deleteTSIGKey(name)) {
        cout << "Deleted TSIG key " << name << endl;
      } else {
-       cout << "Failure deleting TSIG key " << name << endl;
+       cerr << "Failure deleting TSIG key " << name << endl;
        return 1;
      }
      return 0;
@@ -2228,7 +2304,7 @@ try
      UeberBackend B("default");
      std::vector<std::string> meta; 
      if (!B.getDomainMetadata(zname, metaKey, meta)) {
-       cout << "Failure enabling TSIG key " << name << " for " << zname << endl;
+       cerr << "Failure enabling TSIG key " << name << " for " << zname << endl;
        return 1;
      }
      bool found = false;
@@ -2239,7 +2315,7 @@ try
      if (B.setDomainMetadata(zname, metaKey, meta)) {
        cout << "Enabled TSIG key " << name << " for " << zname << endl;
      } else {
-       cout << "Failure enabling TSIG key " << name << " for " << zname << endl;
+       cerr << "Failure enabling TSIG key " << name << " for " << zname << endl;
        return 1;
      }
      return 0;
@@ -2263,7 +2339,7 @@ try
      UeberBackend B("default");
      std::vector<std::string> meta;
      if (!B.getDomainMetadata(zname, metaKey, meta)) {
-       cout << "Failure disabling TSIG key " << name << " for " << zname << endl;
+       cerr << "Failure disabling TSIG key " << name << " for " << zname << endl;
        return 1;
      }
      std::vector<std::string>::iterator iter = meta.begin();
@@ -2272,7 +2348,7 @@ try
      if (B.setDomainMetadata(zname, metaKey, meta)) {
        cout << "Disabled TSIG key " << name << " for " << zname << endl;
      } else {
-       cout << "Failure disabling TSIG key " << name << " for " << zname << endl;
+       cerr << "Failure disabling TSIG key " << name << " for " << zname << endl;
        return 1;
      }
      return 0;