return EXIT_SUCCESS;
}
-static int createSecondaryZone(const vector<string>& cmds)
-{
- UeberBackend B;
- DomainInfo di;
- DNSName zone(cmds.at(1));
- if (B.getDomainInfo(zone, di)) {
- cerr << "Zone '" << zone << "' exists already" << endl;
- return EXIT_FAILURE;
- }
- vector<ComboAddress> primaries;
- for (unsigned i=2; i < cmds.size(); i++) {
- primaries.emplace_back(cmds.at(i), 53);
- }
- cerr << "Creating secondary zone '" << zone << "', with primaries '" << comboAddressVecToString(primaries) << "'" << endl;
- B.createDomain(zone, DomainInfo::Secondary, primaries, "");
- if(!B.getDomainInfo(zone, di)) {
- cerr << "Zone '" << zone << "' was not created!" << endl;
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
-}
-
-static int changeSecondaryZonePrimary(const vector<string>& cmds)
-{
- UeberBackend B;
- DomainInfo di;
- DNSName zone(cmds.at(1));
- if (!B.getDomainInfo(zone, di)) {
- cerr << "Zone '" << zone << "' doesn't exist" << endl;
- return EXIT_FAILURE;
- }
- vector<ComboAddress> primaries;
- for (unsigned i=2; i < cmds.size(); i++) {
- primaries.emplace_back(cmds.at(i), 53);
- }
- cerr << "Updating secondary zone '" << zone << "', primaries to '" << comboAddressVecToString(primaries) << "'" << endl;
- try {
- di.backend->setPrimaries(zone, primaries);
- return EXIT_SUCCESS;
- }
- catch (PDNSException& e) {
- cerr << "Setting primary for zone '" << zone << "' failed: " << e.reason << endl;
- return EXIT_FAILURE;
- }
-}
-
// add-record ZONE name type [ttl] "content" ["content"]
static int addOrReplaceRecord(bool addOrReplace, const vector<string>& cmds) {
DNSResourceRecord rr;
return 0;
}
-static int addZoneKey(vector<string>& cmds, DNSSECKeeper& dk) //NOLINT(readability-identifier-length)
+// Command handlers
+
+static int lmdbGetBackendVersion([[maybe_unused]] vector<string>& cmds)
{
- if(cmds.size() < 3 ) {
- cerr << "Syntax: pdnsutil add-zone-key ZONE [zsk|ksk] [BITS] [active|inactive] [rsasha1|rsasha1-nsec3-sha1|rsasha256|rsasha512|ecdsa256|ecdsa384";
-#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO_ED25519)
- cerr << "|ed25519";
-#endif
-#if defined(HAVE_LIBCRYPTO_ED448)
- cerr << "|ed448";
-#endif
- cerr << "]"<<endl;
- cerr << endl;
- cerr << "If zsk|ksk is omitted, add-zone-key makes a key with flags 256 (a 'ZSK')."<<endl;
+ cout << "5" << endl; // FIXME this should reuse the constant from lmdbbackend but that is currently a #define in a .cc
+ return 0;
+}
+
+static int testAlgorithm(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil test-algorithm algonum"<<endl;
return 0;
}
- DNSName zone(cmds.at(1));
+ if (testAlgorithm(pdns::checked_stoi<int>(cmds.at(1))))
+ return 0;
+ return 1;
+}
- UeberBackend B("default"); //NOLINT(readability-identifier-length)
- DomainInfo di; //NOLINT(readability-identifier-length)
+static int ipEncrypt(vector<string>& cmds)
+{
+ if (cmds.size() < 3 || (cmds.size() == 4 && cmds.at(3) != "key")) {
+ cerr<<"Syntax: pdnsutil [ipencrypt|ipdecrypt] IP passphrase [key]"<<endl;
+ return 0;
+ }
+#ifdef HAVE_IPCIPHER
+ string key;
+ if(cmds.size()==4) {
+ if (B64Decode(cmds.at(2), key) < 0) {
+ cerr << "Could not parse '" << cmds.at(3) << "' as base64" << endl;
+ return 0;
+ }
+ }
+ else {
+ key = makeIPCipherKey(cmds.at(2));
+ }
+ return xcryptIP(cmds.at(0), cmds.at(1), key);
+#else
+ cerr<<cmds.at(0)<<" requires ipcipher support which is not available"<<endl;
+ return 0;
+#endif /* HAVE_IPCIPHER */
+}
- if (!B.getDomainInfo(zone, di)){
- cerr << "No such zone in the database" << endl;
+static int testAlgorithms([[maybe_unused]] vector<string>& cmds)
+{
+ if (testAlgorithms())
return 0;
+ return 1;
+}
+
+static int listAlgorithms(vector<string>& cmds)
+{
+ if ((cmds.size() == 2 && cmds.at(1) != "with-backend") || cmds.size() > 2) {
+ cerr<<"Syntax: pdnsutil list-algorithms [with-backend]"<<endl;
+ return 1;
}
- // need to get algorithm, bits & ksk or zsk from commandline
- bool keyOrZone=false;
- int tmp_algo=0;
- int bits=0;
- int algorithm=DNSSECKeeper::ECDSA256;
- bool active=false;
- bool published=true;
- for(unsigned int n=2; n < cmds.size(); ++n) { //NOLINT(readability-identifier-length)
- if (pdns_iequals(cmds.at(n), "zsk")) {
- keyOrZone = false;
- }
- else if (pdns_iequals(cmds.at(n), "ksk")) {
- keyOrZone = true;
- }
- else if ((tmp_algo = DNSSECKeeper::shorthand2algorithm(cmds.at(n))) > 0) {
- algorithm = tmp_algo;
- }
- else if (pdns_iequals(cmds.at(n), "active")) {
- active=true;
- }
- else if (pdns_iequals(cmds.at(n), "inactive") || pdns_iequals(cmds.at(n), "passive")) { // 'passive' eventually needs to be removed
- active=false;
- }
- else if (pdns_iequals(cmds.at(n), "published")) {
- published = true;
- }
- else if (pdns_iequals(cmds.at(n), "unpublished")) {
- published = false;
+ cout<<"DNSKEY algorithms supported by this installation of PowerDNS:"<<endl;
+
+ auto algosWithBackend = DNSCryptoKeyEngine::listAllAlgosWithBackend();
+ for (const auto& algoWithBackend : algosWithBackend){
+ string algoName = DNSSECKeeper::algorithm2name(algoWithBackend.first);
+ cout<<std::to_string(algoWithBackend.first)<<" - "<<algoName;
+ if (cmds.size() == 2 && cmds.at(1) == "with-backend")
+ cout<<" using "<<algoWithBackend.second;
+ cout<<endl;
+ }
+ return 0;
+}
+
+
+// these need reportAllTypes
+static int createBindDb(vector<string>& cmds)
+{
+#ifdef HAVE_SQLITE3
+ if(cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil create-bind-db FNAME"<<endl;
+ return 0;
+ }
+ try {
+ SSQLite3 db(cmds.at(1), "", true); // create=ok
+ vector<string> statements;
+ stringtok(statements, sqlCreate, ";");
+ for(const string& statement : statements) {
+ db.execute(statement);
}
- else if (pdns::checked_stoi<int>(cmds.at(n)) != 0) {
- pdns::checked_stoi_into(bits, cmds.at(n));
+ }
+ catch(SSqlException& se) {
+ throw PDNSException("Error creating database in BIND backend: "+se.txtReason());
+ }
+ return 0;
+#else
+ cerr<<"bind-dnssec-db requires building PowerDNS with SQLite3"<<endl;
+ return 1;
+#endif
+}
+
+static int rawLuaFromContent(vector<string>& cmds)
+{
+ if (cmds.size() < 3) {
+ cerr<<"Usage: raw-lua-from-content TYPE CONTENT"<<endl;
+ return 1;
+ }
+
+ // DNSResourceRecord rr;
+ // rr.qtype = DNSRecordContent::TypeToNumber(cmds.at(1));
+ // rr.content = cmds.at(2);
+ auto drc = DNSRecordContent::make(DNSRecordContent::TypeToNumber(cmds.at(1)), QClass::IN, cmds.at(2));
+ cout<<makeLuaString(drc->serialize(DNSName(), true))<<endl;
+
+ return 0;
+}
+
+static int hashPassword(vector<string>& cmds)
+{
+ uint64_t workFactor = CredentialsHolder::s_defaultWorkFactor;
+ if (cmds.size() > 1) {
+ try {
+ pdns::checked_stoi_into(workFactor, cmds.at(1));
}
- else {
- cerr << "Unknown algorithm, key flag or size '" << cmds.at(n) << "'" << endl;
- return EXIT_FAILURE;
+ catch (const std::exception& e) {
+ cerr<<"Unable to parse the supplied work factor: "<<e.what()<<endl;
+ return 1;
}
}
- int64_t id{-1}; //NOLINT(readability-identifier-length)
- if (!dk.addKey(zone, keyOrZone, algorithm, id, bits, active, published)) {
- cerr<<"Adding key failed, perhaps DNSSEC not enabled in configuration?"<<endl;
+
+ auto password = CredentialsHolder::readFromTerminal();
+
+ try {
+ cout<<hashPassword(password.getString(), workFactor, CredentialsHolder::s_defaultParallelFactor, CredentialsHolder::s_defaultBlockSize)<<endl;
+ return EXIT_SUCCESS;
+ }
+ catch (const std::exception& e) {
+ cerr<<"Error while hashing the supplied password: "<<e.what()<<endl;
return 1;
}
- cerr<<"Added a " << (keyOrZone ? "KSK" : "ZSK")<<" with algorithm = "<<algorithm<<", active="<<active<<endl;
- if (bits != 0) {
- cerr<<"Requested specific key size of "<<bits<<" bits"<<endl;
+}
+
+static int zonemdVerifyFile(vector<string>& cmds)
+{
+ if(cmds.size() < 3) {
+ cerr<<"Syntax: pdnsutil zonemd-verify-file ZONE FILENAME"<<endl;
+ return 1;
}
- if (id == -1) {
- cerr<<std::to_string(id)<<": Key was added, but backend does not support returning of key id"<<endl;
- } else if (id < -1) {
- cerr<<std::to_string(id)<<": Key was added, but there was a failure while returning the key id"<<endl;
+ if(cmds[1]==".")
+ cmds[1].clear();
+
+ return zonemdVerifyFile(DNSName(cmds[1]), cmds[2]);
+}
+
+
+// these need DNSSECKeeper
+static int testSchema(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil test-schema ZONE"<<endl;
+ return 0;
+ }
+ DNSSECKeeper dk;
+ return testSchema(dk, DNSName(cmds.at(1)));
+}
+
+static int rectifyZone(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr << "Syntax: pdnsutil rectify-zone ZONE [ZONE..]"<<endl;
+ return 0;
+ }
+ DNSSECKeeper dk;
+ unsigned int exitCode = 0;
+ for(unsigned int n = 1; n < cmds.size(); ++n)
+ if (!rectifyZone(dk, DNSName(cmds.at(n))))
+ exitCode = 1;
+ return exitCode;
+}
+
+static int rectifyAllZones(vector<string>& cmds)
+{
+ bool quiet = (cmds.size() >= 2 && cmds.at(1) == "quiet");
+ DNSSECKeeper dk;
+ if (!rectifyAllZones(dk, quiet)) {
return 1;
- } else {
- try {
- dk.getKeyById(zone, id);
- cout<<std::to_string(id)<<endl;
- } catch (std::exception& e) {
- cerr<<std::to_string(id)<<": Key was added, but there was a failure while reading it back: " <<e.what()<<endl;
- return 1;
- }
}
return 0;
}
-// NOLINTNEXTLINE(readability-function-cognitive-complexity): TODO Clean this function up.
-int main(int argc, char** argv)
-try
+static int checkZone(vector<string>& cmds)
{
- po::options_description desc("Allowed options");
- desc.add_options()
- ("help,h", "produce help message")
- ("version", "show version")
- ("verbose,v", "be verbose")
- ("force", "force an action")
- ("config-name", po::value<string>()->default_value(""), "virtual configuration name")
- ("config-dir", po::value<string>()->default_value(SYSCONFDIR), "location of pdns.conf")
- ("no-colors", "do not use colors in output")
- ("commands", po::value<vector<string> >());
+ if(cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil check-zone ZONE"<<endl;
+ return 0;
+ }
+ DNSSECKeeper dk;
+ UeberBackend B("default");
+ return checkZone(dk, B, DNSName(cmds.at(1)));
+}
- po::positional_options_description p;
- p.add("commands", -1);
- po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), g_vm);
- po::notify(g_vm);
+static int benchDb(vector<string>& cmds)
+{
+ dbBench(cmds.size() > 1 ? cmds.at(1) : "");
+ return 0;
+}
- vector<string> cmds;
+static int checkAllZones(vector<string>& cmds)
+{
+ bool exitOnError = ((cmds.size() >= 2 ? cmds.at(1) : "") == "exit-on-error");
+ DNSSECKeeper dk;
+ return checkAllZones(dk, exitOnError);
+}
- if(g_vm.count("commands"))
- cmds = g_vm["commands"].as<vector<string> >();
+static int listAllZones(vector<string>& cmds)
+{
+ if (cmds.size() > 2) {
+ cerr << "Syntax: pdnsutil list-all-zones [primary|secondary|native|producer|consumer]" << endl;
+ return 0;
+ }
+ if (cmds.size() == 2)
+ return listAllZones(cmds.at(1));
+ return listAllZones();
+}
- g_verbose = g_vm.count("verbose");
+static int listMemberZones(vector<string>& cmds)
+{
+ if (cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil list-member-zones CATALOG" << endl;
+ return 0;
+ }
+ return listMemberZones(cmds.at(1));
+}
- if (g_vm.count("version")) {
- cout<<"pdnsutil "<<VERSION<<endl;
+static int testZone([[maybe_unused]] vector<string>& cmds)
+{
+ cerr << "Did you mean check-zone?"<<endl;
+ return 0;
+}
+
+static int testAllZones([[maybe_unused]] vector<string>& cmds)
+{
+ cerr << "Did you mean check-all-zones?"<<endl;
+ return 0;
+}
+
+static int testSpeed(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr << "Syntax: pdnsutil test-speed numcores [signing-server]"<<endl;
return 0;
}
+ testSpeed(DNSName(cmds.at(1)), (cmds.size() > 3) ? cmds.at(3) : "", pdns::checked_stoi<int>(cmds.at(2)));
+ return 0;
+}
- if (cmds.empty() || g_vm.count("help") || cmds.at(0) == "help") {
- cout << "Usage: \npdnsutil [options] <command> [params ..]\n"
- << endl;
- cout << "Commands:" << endl;
- cout << "activate-tsig-key ZONE NAME {primary|secondary|producer|consumer}" << endl;
- cout << " Enable TSIG authenticated AXFR using the key NAME for ZONE" << endl;
- cout << "activate-zone-key ZONE KEY-ID Activate the key with key id KEY-ID in ZONE" << endl;
- cout << "add-record ZONE NAME TYPE [ttl] content" << endl;
- cout << " [content..] Add one or more records to ZONE" << endl;
- cout << "add-autoprimary IP NAMESERVER [account]" << endl;
- cout << " Add a new autoprimary " << endl;
- cout << "remove-autoprimary IP NAMESERVER Remove an autoprimary" << endl;
- cout << "list-autoprimaries List all autoprimaries" << endl;
- cout << "add-zone-key ZONE {zsk|ksk} [BITS] [active|inactive] [published|unpublished]" << endl;
- cout << " [rsasha1|rsasha1-nsec3-sha1|rsasha256|rsasha512|ecdsa256|ecdsa384";
-#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO_ED25519)
- cout << "|ed25519";
-#endif
-#if defined(HAVE_LIBCRYPTO_ED448)
- cout << "|ed448";
-#endif
- cout << "]" << endl;
- cout << " Add a ZSK or KSK to zone and specify algo&bits" << endl;
- cout << "backend-cmd BACKEND CMD [CMD..] Perform one or more backend commands" << endl;
- cout << "backend-lookup BACKEND NAME [[TYPE] CLIENT-IP-SUBNET]" << endl;
- cout << " Perform a backend lookup of NAME, TYPE and CLIENT-IP-SUBNET" << endl;
- cout << "b2b-migrate OLD NEW Move all data from one backend to another" << endl;
- cout << "bench-db [filename] Bench database backend with queries, one zone per line" << endl;
- cout << "check-zone ZONE Check a zone for correctness" << endl;
- cout << "check-all-zones [exit-on-error] Check all zones for correctness. Set exit-on-error to exit immediately" << endl;
- cout << " after finding an error in a zone." << endl;
- cout << "clear-zone ZONE Clear all records of a zone, but keep everything else" << endl;
- cout << "create-bind-db FNAME Create DNSSEC db for BIND backend (bind-dnssec-db)" << endl;
- cout << "create-secondary-zone ZONE primary-ip [primary-ip..]" << endl;
- cout << " Create secondary zone ZONE with primary IP address primary-ip" << endl;
- cout << "change-secondary-zone-primary ZONE primary-ip [primary-ip..]" << endl;
- cout << " Change secondary zone ZONE primary IP address to primary-ip" << endl;
- cout << "create-zone ZONE [nsname] Create empty zone ZONE" << endl;
- cout << "deactivate-tsig-key ZONE NAME {primary|secondary}" << endl;
- cout << " Disable TSIG authenticated AXFR using the key NAME for ZONE" << endl;
- cout << "deactivate-zone-key ZONE KEY-ID Deactivate the key with key id KEY-ID in ZONE" << endl;
- cout << "delete-rrset ZONE NAME TYPE Delete named RRSET from zone" << endl;
- cout << "delete-tsig-key NAME Delete TSIG key (warning! will not unmap key!)" << endl;
- cout << "delete-zone ZONE Delete the zone" << endl;
- cout << "disable-dnssec ZONE Deactivate all keys and unset PRESIGNED in ZONE" << endl;
- cout << "edit-zone ZONE Edit zone contents using $EDITOR" << endl;
- cout << "export-zone-dnskey ZONE KEY-ID Export to stdout the public DNSKEY described" << endl;
- cout << "export-zone-ds ZONE Export to stdout all KSK DS records for ZONE" << endl;
- cout << "export-zone-key ZONE KEY-ID Export to stdout the private key described" << endl;
- cout << "export-zone-key-pem ZONE KEY-ID Export to stdout in PEM the private key described" << endl;
- cout << "generate-tsig-key NAME ALGORITHM Generate new TSIG key" << endl;
- cout << "generate-zone-key {zsk|ksk} [ALGORITHM] [BITS]" << endl;
- cout << " Generate a ZSK or KSK to stdout with specified ALGORITHM and BITS" << endl;
- cout << "get-meta ZONE [KIND ...] Get zone metadata. If no KIND given, lists all known" << endl;
- cout << "hash-password [WORK FACTOR] Ask for a plaintext password or api key and output a hashed and salted version" << endl;
- cout << "hash-zone-record ZONE RNAME Calculate the NSEC3 hash for RNAME in ZONE" << endl;
-#ifdef HAVE_P11KIT1
- cout << "hsm assign ZONE ALGORITHM {ksk|zsk} MODULE SLOT PIN LABEL" << endl <<
- " Assign a hardware signing module to a ZONE" << endl;
- cout << "hsm create-key ZONE KEY-ID [BITS] Create a key using hardware signing module for ZONE (use assign first)" << endl;
- cout << " BITS defaults to 2048" << endl;
-#endif
- cout << "increase-serial ZONE Increases the SOA-serial by 1. Uses SOA-EDIT" << endl;
- cout << "import-tsig-key NAME ALGORITHM KEY Import TSIG key" << endl;
- cout << "import-zone-key ZONE FILE Import from a file a private key, ZSK or KSK" << endl;
- cout << " [active|inactive] [ksk|zsk] [published|unpublished] Defaults to KSK, active and published" << endl;
- cout << "import-zone-key-pem ZONE FILE Import a private key from a PEM file" << endl;
- cout << " ALGORITHM {ksk|zsk}" << endl;
- cout << "ipdecrypt IP passphrase/key [key] Decrypt IP address using passphrase or base64 key" << endl;
- cout << "ipencrypt IP passphrase/key [key] Encrypt IP address using passphrase or base64 key" << endl;
- cout << "load-zone ZONE FILE Load ZONE from FILE, possibly creating zone or atomically" << endl;
- cout << " replacing contents" << endl;
- cout << "list-algorithms [with-backend] List all DNSSEC algorithms supported, optionally also listing the crypto library used" << endl;
- cout << "list-keys [ZONE] List DNSSEC keys for ZONE. When ZONE is unset, display all keys for all active zones" << endl;
- cout << " --verbose or -v will also include the keys for disabled or empty zones" << endl;
- cout << "list-zone ZONE List zone contents" << endl;
- cout << "list-all-zones [primary|secondary|native|producer|consumer]" << endl;
- cout << " List all active zone names. --verbose or -v will also include disabled or empty zones" << endl;
- cout << "list-member-zones CATALOG List all members of catalog zone CATALOG" << endl;
-
- cout << "list-tsig-keys List all TSIG keys" << endl;
- cout << "publish-zone-key ZONE KEY-ID Publish the zone key with key id KEY-ID in ZONE" << endl;
- cout << "rectify-zone ZONE [ZONE ..] Fix up DNSSEC fields (order, auth)" << endl;
- cout << "rectify-all-zones [quiet] Rectify all zones. Optionally quiet output with errors only" << endl;
- cout << "remove-zone-key ZONE KEY-ID Remove key with KEY-ID from ZONE" << endl;
- cout << "replace-rrset ZONE NAME TYPE [ttl] Replace named RRSET from zone" << endl;
- cout << " content [content..]" << endl;
- cout << "secure-all-zones [increase-serial] Secure all zones without keys" << endl;
- cout << "secure-zone ZONE [ZONE ..] Add DNSSEC to zone ZONE" << endl;
- cout << "set-kind ZONE KIND Change the kind of ZONE to KIND (primary, secondary, native, producer, consumer)" << endl;
- cout << "set-options-json ZONE JSON Change the options of ZONE to JSON" << endl;
- cout << "set-option ZONE Set or remove an option for ZONE Providing an empty value removes an option" << endl;
- cout << " [producer|consumer]" << endl;
- cout << " [coo|unique|group] VALUE" << endl;
- cout << " [VALUE ...]" << endl;
- cout << "set-catalog ZONE CATALOG Change the catalog of ZONE to CATALOG. Setting CATALOG to an empty "" removes ZONE from the catalog it is in" << endl;
- cout << "set-account ZONE ACCOUNT Change the account (owner) of ZONE to ACCOUNT" << endl;
- cout << "set-nsec3 ZONE ['PARAMS' [narrow]] Enable NSEC3 with PARAMS. Optionally narrow" << endl;
- cout << "set-presigned ZONE Use presigned RRSIGs from storage" << endl;
- cout << "set-publish-cdnskey ZONE [delete] Enable sending CDNSKEY responses for ZONE. Add 'delete' to publish a CDNSKEY with a" << endl;
- cout << " DNSSEC delete algorithm" << endl;
- cout << "set-publish-cds ZONE [DIGESTALGOS] Enable sending CDS responses for ZONE, using DIGESTALGOS as signature algorithms" << endl;
- cout << " DIGESTALGOS should be a comma separated list of numbers, it is '2' by default" << endl;
- cout << "add-meta ZONE KIND VALUE Add zone metadata, this adds to the existing KIND" << endl;
- cout << " [VALUE ...]" << endl;
- cout << "set-meta ZONE KIND [VALUE] [VALUE] Set zone metadata, optionally providing a value. *No* value clears meta" << endl;
- cout << " Note - this will replace all metadata records of KIND!" << endl;
- cout << "show-zone ZONE Show DNSSEC (public) key details about a zone" << endl;
- cout << "unpublish-zone-key ZONE KEY-ID Unpublish the zone key with key id KEY-ID in ZONE" << endl;
- cout << "unset-nsec3 ZONE Switch back to NSEC" << endl;
- cout << "unset-presigned ZONE No longer use presigned RRSIGs" << endl;
- cout << "unset-publish-cdnskey ZONE Disable sending CDNSKEY responses for ZONE" << endl;
- cout << "unset-publish-cds ZONE Disable sending CDS responses for ZONE" << endl;
- cout << "test-schema ZONE Test DB schema - will create ZONE" << endl;
- cout << "raw-lua-from-content TYPE CONTENT Display record contents in a form suitable for dnsdist's `SpoofRawAction`" << endl;
- cout << "zonemd-verify-file ZONE FILE Validate ZONEMD for ZONE" << endl;
- cout << "lmdb-get-backend-version Get schema version supported by backend" << endl;
- cout << desc << endl;
-
+static int verifyCrypto(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil verify-crypto FILE"<<endl;
return 0;
}
+ verifyCrypto(cmds.at(1));
+ return 0;
+}
- loadMainConfig(g_vm["config-dir"].as<string>());
-
- if (cmds.at(0) == "lmdb-get-backend-version") {
- cout << "5" << endl; // FIXME this should reuse the constant from lmdbbackend but that is currently a #define in a .cc
+static int showZone(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil show-zone ZONE"<<endl;
return 0;
}
- if (cmds.at(0) == "test-algorithm") {
- if(cmds.size() != 2) {
- cerr << "Syntax: pdnsutil test-algorithm algonum"<<endl;
- return 0;
- }
- if (testAlgorithm(pdns::checked_stoi<int>(cmds.at(1))))
- return 0;
+ DNSSECKeeper dk;
+ if (!showZone(dk, DNSName(cmds.at(1))))
return 1;
- }
+ return 0;
+}
- if (cmds.at(0) == "ipencrypt" || cmds.at(0) == "ipdecrypt") {
- if (cmds.size() < 3 || (cmds.size() == 4 && cmds.at(3) != "key")) {
- cerr<<"Syntax: pdnsutil [ipencrypt|ipdecrypt] IP passphrase [key]"<<endl;
- return 0;
- }
-#ifdef HAVE_IPCIPHER
- string key;
- if(cmds.size()==4) {
- if (B64Decode(cmds.at(2), key) < 0) {
- cerr << "Could not parse '" << cmds.at(3) << "' as base64" << endl;
- return 0;
- }
- }
- else {
- key = makeIPCipherKey(cmds.at(2));
- }
- exit(xcryptIP(cmds.at(0), cmds.at(1), key));
-#else
- cerr<<cmds.at(0)<<" requires ipcipher support which is not available"<<endl;
+static int exportZoneDS(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil export-zone-ds ZONE"<<endl;
return 0;
-#endif /* HAVE_IPCIPHER */
}
-
- if (cmds.at(0) == "test-algorithms") {
- if (testAlgorithms())
- return 0;
+ DNSSECKeeper dk;
+ if (!showZone(dk, DNSName(cmds.at(1)), true))
return 1;
- }
-
- if (cmds.at(0) == "list-algorithms") {
- if ((cmds.size() == 2 && cmds.at(1) != "with-backend") || cmds.size() > 2) {
- cerr<<"Syntax: pdnsutil list-algorithms [with-backend]"<<endl;
- return 1;
- }
-
- cout<<"DNSKEY algorithms supported by this installation of PowerDNS:"<<endl;
+ return 0;
+}
- auto algosWithBackend = DNSCryptoKeyEngine::listAllAlgosWithBackend();
- for (const auto& algoWithBackend : algosWithBackend){
- string algoName = DNSSECKeeper::algorithm2name(algoWithBackend.first);
- cout<<std::to_string(algoWithBackend.first)<<" - "<<algoName;
- if (cmds.size() == 2 && cmds.at(1) == "with-backend")
- cout<<" using "<<algoWithBackend.second;
- cout<<endl;
- }
+static int disableDNSSEC(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr << "Syntax: pdnsutil disable-dnssec ZONE"<<endl;
return 0;
}
-
- reportAllTypes();
-
- if (cmds.at(0) == "create-bind-db") {
-#ifdef HAVE_SQLITE3
- if(cmds.size() != 2) {
- cerr << "Syntax: pdnsutil create-bind-db FNAME"<<endl;
- return 0;
- }
- try {
- SSQLite3 db(cmds.at(1), "", true); // create=ok
- vector<string> statements;
- stringtok(statements, sqlCreate, ";");
- for(const string& statement : statements) {
- db.execute(statement);
- }
- }
- catch(SSqlException& se) {
- throw PDNSException("Error creating database in BIND backend: "+se.txtReason());
- }
- return 0;
-#else
- cerr<<"bind-dnssec-db requires building PowerDNS with SQLite3"<<endl;
+ DNSSECKeeper dk;
+ DNSName zone(cmds.at(1));
+ if(!disableDNSSECOnZone(dk, zone)) {
+ cerr << "Cannot disable DNSSEC on " << zone << endl;
return 1;
-#endif
}
+ return 0;
+}
- if (cmds.at(0) == "raw-lua-from-content") {
- if (cmds.size() < 3) {
- cerr<<"Usage: raw-lua-from-content TYPE CONTENT"<<endl;
- return 1;
- }
-
- // DNSResourceRecord rr;
- // rr.qtype = DNSRecordContent::TypeToNumber(cmds.at(1));
- // rr.content = cmds.at(2);
- auto drc = DNSRecordContent::make(DNSRecordContent::TypeToNumber(cmds.at(1)), QClass::IN, cmds.at(2));
- cout<<makeLuaString(drc->serialize(DNSName(), true))<<endl;
-
+static int activateZoneKey(vector<string>& cmds)
+{
+ if(cmds.size() != 3) {
+ cerr << "Syntax: pdnsutil activate-zone-key ZONE KEY-ID"<<endl;
return 0;
}
- else if (cmds.at(0) == "hash-password") {
- uint64_t workFactor = CredentialsHolder::s_defaultWorkFactor;
- if (cmds.size() > 1) {
- try {
- pdns::checked_stoi_into(workFactor, cmds.at(1));
- }
- catch (const std::exception& e) {
- cerr<<"Unable to parse the supplied work factor: "<<e.what()<<endl;
- return 1;
- }
- }
-
- auto password = CredentialsHolder::readFromTerminal();
-
- try {
- cout<<hashPassword(password.getString(), workFactor, CredentialsHolder::s_defaultParallelFactor, CredentialsHolder::s_defaultBlockSize)<<endl;
- return EXIT_SUCCESS;
- }
- catch (const std::exception& e) {
- cerr<<"Error while hashing the supplied password: "<<e.what()<<endl;
- return 1;
- }
- }
-
- if(cmds[0] == "zonemd-verify-file") {
- if(cmds.size() < 3) {
- cerr<<"Syntax: pdnsutil zonemd-verify-file ZONE FILENAME"<<endl;
- return 1;
- }
- if(cmds[1]==".")
- cmds[1].clear();
-
- auto ret = zonemdVerifyFile(DNSName(cmds[1]), cmds[2]);
- return ret;
+ DNSName zone(cmds.at(1));
+ unsigned int id = atoi(cmds.at(2).c_str()); // if you make this pdns::checked_stoi, the error gets worse
+ if(!id)
+ {
+ cerr << "Invalid KEY-ID '" << cmds.at(2) << "'" << endl;
+ return 1;
}
-
DNSSECKeeper dk;
-
- if (cmds.at(0) == "test-schema") {
- if(cmds.size() != 2) {
- cerr << "Syntax: pdnsutil test-schema ZONE"<<endl;
- return 0;
- }
- return testSchema(dk, DNSName(cmds.at(1)));
- }
- if (cmds.at(0) == "rectify-zone") {
- if(cmds.size() < 2) {
- cerr << "Syntax: pdnsutil rectify-zone ZONE [ZONE..]"<<endl;
- return 0;
- }
- unsigned int exitCode = 0;
- for(unsigned int n = 1; n < cmds.size(); ++n)
- if (!rectifyZone(dk, DNSName(cmds.at(n))))
- exitCode = 1;
- return exitCode;
- }
- else if (cmds.at(0) == "rectify-all-zones") {
- bool quiet = (cmds.size() >= 2 && cmds.at(1) == "quiet");
- if (!rectifyAllZones(dk, quiet)) {
- return 1;
- }
- }
- else if (cmds.at(0) == "check-zone") {
- if(cmds.size() != 2) {
- cerr << "Syntax: pdnsutil check-zone ZONE"<<endl;
- return 0;
- }
- UeberBackend B("default");
- return checkZone(dk, B, DNSName(cmds.at(1)));
+ try {
+ dk.getKeyById(zone, id);
+ } catch (std::exception& e) {
+ cerr<<e.what()<<endl;
+ return 1;
}
- else if (cmds.at(0) == "bench-db") {
- dbBench(cmds.size() > 1 ? cmds.at(1) : "");
+ if (!dk.activateKey(zone, id)) {
+ cerr<<"Activation of key failed"<<endl;
+ return 1;
}
- else if (cmds.at(0) == "check-all-zones") {
- bool exitOnError = ((cmds.size() >= 2 ? cmds.at(1) : "") == "exit-on-error");
- return checkAllZones(dk, exitOnError);
+ return 0;
+}
+
+static int deactivateZoneKey(vector<string>& cmds)
+{
+ if(cmds.size() != 3) {
+ cerr << "Syntax: pdnsutil deactivate-zone-key ZONE KEY-ID"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "list-all-zones") {
- if (cmds.size() > 2) {
- cerr << "Syntax: pdnsutil list-all-zones [primary|secondary|native|producer|consumer]" << endl;
- return 0;
- }
- if (cmds.size() == 2)
- return listAllZones(cmds.at(1));
- return listAllZones();
+ DNSName zone(cmds.at(1));
+ auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
+ if(!id)
+ {
+ cerr<<"Invalid KEY-ID"<<endl;
+ return 1;
}
- else if (cmds.at(0) == "list-member-zones") {
- if (cmds.size() != 2) {
- cerr << "Syntax: pdnsutil list-member-zones CATALOG" << endl;
- return 0;
- }
- return listMemberZones(cmds.at(1));
+ DNSSECKeeper dk;
+ try {
+ dk.getKeyById(zone, id);
+ } catch (std::exception& e) {
+ cerr<<e.what()<<endl;
+ return 1;
}
- else if (cmds.at(0) == "test-zone") {
- cerr << "Did you mean check-zone?"<<endl;
- return 0;
+ if (!dk.deactivateKey(zone, id)) {
+ cerr<<"Deactivation of key failed"<<endl;
+ return 1;
}
- else if (cmds.at(0) == "test-all-zones") {
- cerr << "Did you mean check-all-zones?"<<endl;
+ return 0;
+}
+
+static int publishZoneKey(vector<string>& cmds)
+{
+ if(cmds.size() != 3) {
+ cerr << "Syntax: pdnsutil publish-zone-key ZONE KEY-ID"<<endl;
return 0;
}
-#if 0
- else if(cmds.at(0) == "signing-server" )
+ DNSName zone(cmds.at(1));
+ unsigned int id = atoi(cmds.at(2).c_str()); // if you make this pdns::checked_stoi, the error gets worse
+ if(!id)
{
- signingServer();
+ cerr << "Invalid KEY-ID '" << cmds.at(2) << "'" << endl;
+ return 1;
}
- else if(cmds.at(0) == "signing-secondary")
- {
- launchSigningService(0);
+ DNSSECKeeper dk;
+ try {
+ dk.getKeyById(zone, id);
+ } catch (std::exception& e) {
+ cerr<<e.what()<<endl;
+ return 1;
}
-#endif
- else if (cmds.at(0) == "test-speed") {
- if(cmds.size() < 2) {
- cerr << "Syntax: pdnsutil test-speed numcores [signing-server]"<<endl;
- return 0;
- }
- testSpeed(DNSName(cmds.at(1)), (cmds.size() > 3) ? cmds.at(3) : "", pdns::checked_stoi<int>(cmds.at(2)));
+ if (!dk.publishKey(zone, id)) {
+ cerr<<"Publishing of key failed"<<endl;
+ return 1;
}
- else if (cmds.at(0) == "verify-crypto") {
- if(cmds.size() != 2) {
- cerr << "Syntax: pdnsutil verify-crypto FILE"<<endl;
- return 0;
- }
- verifyCrypto(cmds.at(1));
+ return 0;
+}
+
+static int unpublishZoneKey(vector<string>& cmds)
+{
+ if(cmds.size() != 3) {
+ cerr << "Syntax: pdnsutil unpublish-zone-key ZONE KEY-ID"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "show-zone") {
- if(cmds.size() != 2) {
- cerr << "Syntax: pdnsutil show-zone ZONE"<<endl;
- return 0;
- }
- if (!showZone(dk, DNSName(cmds.at(1))))
- return 1;
+ DNSName zone(cmds.at(1));
+ unsigned int id = atoi(cmds.at(2).c_str()); // if you make this pdns::checked_stoi, the error gets worse
+ if(!id)
+ {
+ cerr << "Invalid KEY-ID '" << cmds.at(2) << "'" << endl;
+ return 1;
}
- else if (cmds.at(0) == "export-zone-ds") {
- if(cmds.size() != 2) {
- cerr << "Syntax: pdnsutil export-zone-ds ZONE"<<endl;
- return 0;
- }
- if (!showZone(dk, DNSName(cmds.at(1)), true))
- return 1;
+ DNSSECKeeper dk;
+ try {
+ dk.getKeyById(zone, id);
+ } catch (std::exception& e) {
+ cerr<<e.what()<<endl;
+ return 1;
}
- else if (cmds.at(0) == "disable-dnssec") {
- if(cmds.size() != 2) {
- cerr << "Syntax: pdnsutil disable-dnssec ZONE"<<endl;
- return 0;
- }
- DNSName zone(cmds.at(1));
- if(!disableDNSSECOnZone(dk, zone)) {
- cerr << "Cannot disable DNSSEC on " << zone << endl;
- return 1;
- }
+ if (!dk.unpublishKey(zone, id)) {
+ cerr<<"Unpublishing of key failed"<<endl;
+ return 1;
}
- else if (cmds.at(0) == "activate-zone-key") {
- if(cmds.size() != 3) {
- cerr << "Syntax: pdnsutil activate-zone-key ZONE KEY-ID"<<endl;
- return 0;
- }
- DNSName zone(cmds.at(1));
- unsigned int id = atoi(cmds.at(2).c_str()); // if you make this pdns::checked_stoi, the error gets worse
- if(!id)
- {
- cerr << "Invalid KEY-ID '" << cmds.at(2) << "'" << endl;
- return 1;
- }
- try {
- dk.getKeyById(zone, id);
- } catch (std::exception& e) {
- cerr<<e.what()<<endl;
- return 1;
- }
- if (!dk.activateKey(zone, id)) {
- cerr<<"Activation of key failed"<<endl;
- return 1;
- }
+ return 0;
+}
+
+static int addZoneKey(vector<string>& cmds)
+{
+ if(cmds.size() < 3 ) {
+ cerr << "Syntax: pdnsutil add-zone-key ZONE [zsk|ksk] [BITS] [active|inactive] [rsasha1|rsasha1-nsec3-sha1|rsasha256|rsasha512|ecdsa256|ecdsa384";
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO_ED25519)
+ cerr << "|ed25519";
+#endif
+#if defined(HAVE_LIBCRYPTO_ED448)
+ cerr << "|ed448";
+#endif
+ cerr << "]"<<endl;
+ cerr << endl;
+ cerr << "If zsk|ksk is omitted, add-zone-key makes a key with flags 256 (a 'ZSK')."<<endl;
return 0;
}
- else if (cmds.at(0) == "deactivate-zone-key") {
- if(cmds.size() != 3) {
- cerr << "Syntax: pdnsutil deactivate-zone-key ZONE KEY-ID"<<endl;
- return 0;
- }
- DNSName zone(cmds.at(1));
- auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
- if(!id)
- {
- cerr<<"Invalid KEY-ID"<<endl;
- return 1;
+ DNSSECKeeper dk; //NOLINT(readability-identifier-length)
+ DNSName zone(cmds.at(1));
+
+ UeberBackend B("default"); //NOLINT(readability-identifier-length)
+ DomainInfo di; //NOLINT(readability-identifier-length)
+
+ if (!B.getDomainInfo(zone, di)){
+ cerr << "No such zone in the database" << endl;
+ return 0;
+ }
+
+ // need to get algorithm, bits & ksk or zsk from commandline
+ bool keyOrZone=false;
+ int tmp_algo=0;
+ int bits=0;
+ int algorithm=DNSSECKeeper::ECDSA256;
+ bool active=false;
+ bool published=true;
+ for(unsigned int n=2; n < cmds.size(); ++n) { //NOLINT(readability-identifier-length)
+ if (pdns_iequals(cmds.at(n), "zsk")) {
+ keyOrZone = false;
}
- try {
- dk.getKeyById(zone, id);
- } catch (std::exception& e) {
- cerr<<e.what()<<endl;
- return 1;
+ else if (pdns_iequals(cmds.at(n), "ksk")) {
+ keyOrZone = true;
}
- if (!dk.deactivateKey(zone, id)) {
- cerr<<"Deactivation of key failed"<<endl;
- return 1;
+ else if ((tmp_algo = DNSSECKeeper::shorthand2algorithm(cmds.at(n))) > 0) {
+ algorithm = tmp_algo;
}
- return 0;
- }
- else if (cmds.at(0) == "publish-zone-key") {
- if(cmds.size() != 3) {
- cerr << "Syntax: pdnsutil publish-zone-key ZONE KEY-ID"<<endl;
- return 0;
+ else if (pdns_iequals(cmds.at(n), "active")) {
+ active=true;
}
- DNSName zone(cmds.at(1));
- unsigned int id = atoi(cmds.at(2).c_str()); // if you make this pdns::checked_stoi, the error gets worse
- if(!id)
- {
- cerr << "Invalid KEY-ID '" << cmds.at(2) << "'" << endl;
- return 1;
+ else if (pdns_iequals(cmds.at(n), "inactive") || pdns_iequals(cmds.at(n), "passive")) { // 'passive' eventually needs to be removed
+ active=false;
}
- try {
- dk.getKeyById(zone, id);
- } catch (std::exception& e) {
- cerr<<e.what()<<endl;
- return 1;
+ else if (pdns_iequals(cmds.at(n), "published")) {
+ published = true;
}
- if (!dk.publishKey(zone, id)) {
- cerr<<"Publishing of key failed"<<endl;
- return 1;
+ else if (pdns_iequals(cmds.at(n), "unpublished")) {
+ published = false;
}
- return 0;
- }
- else if (cmds.at(0) == "unpublish-zone-key") {
- if(cmds.size() != 3) {
- cerr << "Syntax: pdnsutil unpublish-zone-key ZONE KEY-ID"<<endl;
- return 0;
+ else if (pdns::checked_stoi<int>(cmds.at(n)) != 0) {
+ pdns::checked_stoi_into(bits, cmds.at(n));
}
- DNSName zone(cmds.at(1));
- unsigned int id = atoi(cmds.at(2).c_str()); // if you make this pdns::checked_stoi, the error gets worse
- if(!id)
- {
- cerr << "Invalid KEY-ID '" << cmds.at(2) << "'" << endl;
- return 1;
+ else {
+ cerr << "Unknown algorithm, key flag or size '" << cmds.at(n) << "'" << endl;
+ return EXIT_FAILURE;
}
+ }
+ int64_t id{-1}; //NOLINT(readability-identifier-length)
+ if (!dk.addKey(zone, keyOrZone, algorithm, id, bits, active, published)) {
+ cerr<<"Adding key failed, perhaps DNSSEC not enabled in configuration?"<<endl;
+ return 1;
+ }
+ cerr<<"Added a " << (keyOrZone ? "KSK" : "ZSK")<<" with algorithm = "<<algorithm<<", active="<<active<<endl;
+ if (bits != 0) {
+ cerr<<"Requested specific key size of "<<bits<<" bits"<<endl;
+ }
+ if (id == -1) {
+ cerr<<std::to_string(id)<<": Key was added, but backend does not support returning of key id"<<endl;
+ } else if (id < -1) {
+ cerr<<std::to_string(id)<<": Key was added, but there was a failure while returning the key id"<<endl;
+ return 1;
+ } else {
try {
dk.getKeyById(zone, id);
+ cout<<std::to_string(id)<<endl;
} catch (std::exception& e) {
- cerr<<e.what()<<endl;
- return 1;
- }
- if (!dk.unpublishKey(zone, id)) {
- cerr<<"Unpublishing of key failed"<<endl;
+ cerr<<std::to_string(id)<<": Key was added, but there was a failure while reading it back: " <<e.what()<<endl;
return 1;
}
- return 0;
}
+ return 0;
+}
- else if (cmds.at(0) == "add-zone-key") {
- return addZoneKey(cmds, dk);
+static int removeZoneKey(vector<string>& cmds)
+{
+ if(cmds.size() < 3) {
+ cerr<<"Syntax: pdnsutil remove-zone-key ZONE KEY-ID"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "remove-zone-key") {
- if(cmds.size() < 3) {
- cerr<<"Syntax: pdnsutil remove-zone-key ZONE KEY-ID"<<endl;
- return 0;
- }
- DNSName zone(cmds.at(1));
- auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
- if (!dk.removeKey(zone, id)) {
- cerr<<"Cannot remove key " << id << " from " << zone <<endl;
- return 1;
- }
+ DNSSECKeeper dk;
+ DNSName zone(cmds.at(1));
+ auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
+ if (!dk.removeKey(zone, id)) {
+ cerr<<"Cannot remove key " << id << " from " << zone <<endl;
+ return 1;
+ }
+ return 0;
+}
+
+static int deleteZone(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr<<"Syntax: pdnsutil delete-zone ZONE"<<endl;
return 0;
}
- else if (cmds.at(0) == "delete-zone") {
- if(cmds.size() != 2) {
- cerr<<"Syntax: pdnsutil delete-zone ZONE"<<endl;
- return 0;
- }
- return deleteZone(DNSName(cmds.at(1)));
+ return deleteZone(DNSName(cmds.at(1)));
+}
+
+static int createZone(vector<string>& cmds)
+{
+ if(cmds.size() != 2 && cmds.size()!=3 ) {
+ cerr<<"Syntax: pdnsutil create-zone ZONE [nsname]"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "create-zone") {
- if(cmds.size() != 2 && cmds.size()!=3 ) {
- cerr<<"Syntax: pdnsutil create-zone ZONE [nsname]"<<endl;
- return 0;
- }
- return createZone(DNSName(cmds.at(1)), cmds.size() > 2 ? DNSName(cmds.at(2)) : DNSName());
+ return createZone(DNSName(cmds.at(1)), cmds.size() > 2 ? DNSName(cmds.at(2)) : DNSName());
+}
+
+static int createSecondaryZone(vector<string>& cmds)
+{
+ if(cmds.size() < 3 ) {
+ cerr << "Syntax: pdnsutil create-secondary-zone ZONE primary-ip [primary-ip..]" << endl;
+ return 0;
}
- else if (cmds.at(0) == "create-secondary-zone") {
- if(cmds.size() < 3 ) {
- cerr << "Syntax: pdnsutil create-secondary-zone ZONE primary-ip [primary-ip..]" << endl;
- return 0;
- }
- return createSecondaryZone(cmds);
+ UeberBackend B;
+ DomainInfo di;
+ DNSName zone(cmds.at(1));
+ if (B.getDomainInfo(zone, di)) {
+ cerr << "Zone '" << zone << "' exists already" << endl;
+ return EXIT_FAILURE;
}
- else if (cmds.at(0) == "change-secondary-zone-primary") {
- if(cmds.size() < 3 ) {
- cerr << "Syntax: pdnsutil change-secondary-zone-primary ZONE primary-ip [primary-ip..]" << endl;
- return 0;
- }
- return changeSecondaryZonePrimary(cmds);
+ vector<ComboAddress> primaries;
+ for (unsigned i=2; i < cmds.size(); i++) {
+ primaries.emplace_back(cmds.at(i), 53);
}
- else if (cmds.at(0) == "add-record") {
- if(cmds.size() < 5) {
- cerr<<R"(Syntax: pdnsutil add-record ZONE name type [ttl] "content" ["content"...])"<<endl;
- return 0;
- }
- return addOrReplaceRecord(true, cmds);
+ cerr << "Creating secondary zone '" << zone << "', with primaries '" << comboAddressVecToString(primaries) << "'" << endl;
+ B.createDomain(zone, DomainInfo::Secondary, primaries, "");
+ if(!B.getDomainInfo(zone, di)) {
+ cerr << "Zone '" << zone << "' was not created!" << endl;
+ return EXIT_FAILURE;
}
- else if (cmds.at(0) == "add-autoprimary" || cmds.at(0) == "add-autoprimary") {
- if(cmds.size() < 3) {
- cerr << "Syntax: pdnsutil add-autoprimary IP NAMESERVER [account]" << endl;
- return 0;
- }
- exit(addAutoPrimary(cmds.at(1), cmds.at(2), cmds.size() > 3 ? cmds.at(3) : ""));
+ return EXIT_SUCCESS;
+}
+
+static int changeSecondaryZonePrimary(vector<string>& cmds)
+{
+ if(cmds.size() < 3 ) {
+ cerr << "Syntax: pdnsutil change-secondary-zone-primary ZONE primary-ip [primary-ip..]" << endl;
+ return 0;
}
- else if (cmds.at(0) == "remove-autoprimary") {
- if(cmds.size() < 3) {
- cerr << "Syntax: pdnsutil remove-autoprimary IP NAMESERVER" << endl;
- return 0;
- }
- exit(removeAutoPrimary(cmds.at(1), cmds.at(2)));
+ UeberBackend B;
+ DomainInfo di;
+ DNSName zone(cmds.at(1));
+ if (!B.getDomainInfo(zone, di)) {
+ cerr << "Zone '" << zone << "' doesn't exist" << endl;
+ return EXIT_FAILURE;
}
- else if (cmds.at(0) == "list-autoprimaries") {
- exit(listAutoPrimaries());
+ vector<ComboAddress> primaries;
+ for (unsigned i=2; i < cmds.size(); i++) {
+ primaries.emplace_back(cmds.at(i), 53);
}
- else if (cmds.at(0) == "replace-rrset") {
- if(cmds.size() < 5) {
- cerr<<R"(Syntax: pdnsutil replace-rrset ZONE name type [ttl] "content" ["content"...])"<<endl;
- return 0;
- }
- return addOrReplaceRecord(false , cmds);
+ cerr << "Updating secondary zone '" << zone << "', primaries to '" << comboAddressVecToString(primaries) << "'" << endl;
+ try {
+ di.backend->setPrimaries(zone, primaries);
+ return EXIT_SUCCESS;
}
- else if (cmds.at(0) == "delete-rrset") {
- if(cmds.size() != 4) {
- cerr<<"Syntax: pdnsutil delete-rrset ZONE name type"<<endl;
- return 0;
- }
- return deleteRRSet(cmds.at(1), cmds.at(2), cmds.at(3));
+ catch (PDNSException& e) {
+ cerr << "Setting primary for zone '" << zone << "' failed: " << e.reason << endl;
+ return EXIT_FAILURE;
}
- else if (cmds.at(0) == "list-zone") {
- if(cmds.size() != 2) {
- cerr<<"Syntax: pdnsutil list-zone ZONE"<<endl;
- return 0;
- }
- if (cmds.at(1) == ".")
- cmds.at(1).clear();
+}
- return listZone(DNSName(cmds.at(1)));
+static int addRecord(vector<string>& cmds)
+{
+ if(cmds.size() < 5) {
+ cerr<<R"(Syntax: pdnsutil add-record ZONE name type [ttl] "content" ["content"...])"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "edit-zone") {
- if(cmds.size() != 2) {
- cerr<<"Syntax: pdnsutil edit-zone ZONE"<<endl;
- return 0;
- }
- if (cmds.at(1) == ".")
- cmds.at(1).clear();
+ return addOrReplaceRecord(true, cmds);
+}
- PDNSColors col(g_vm.count("no-colors"));
- return editZone(DNSName(cmds.at(1)), col);
+static int addAutoprimary(vector<string>& cmds)
+{
+ if(cmds.size() < 3) {
+ cerr << "Syntax: pdnsutil add-autoprimary IP NAMESERVER [account]" << endl;
+ return 0;
}
- else if (cmds.at(0) == "clear-zone") {
- if(cmds.size() != 2) {
- cerr<<"Syntax: pdnsutil clear-zone ZONE"<<endl;
- return 0;
- }
- if (cmds.at(1) == ".")
- cmds.at(1).clear();
+ return addAutoPrimary(cmds.at(1), cmds.at(2), cmds.size() > 3 ? cmds.at(3) : "");
+}
- return clearZone(DNSName(cmds.at(1)));
+static int removeAutoprimary(vector<string>& cmds)
+{
+ if(cmds.size() < 3) {
+ cerr << "Syntax: pdnsutil remove-autoprimary IP NAMESERVER" << endl;
+ return 0;
}
- else if (cmds.at(0) == "list-keys") {
- if(cmds.size() > 2) {
- cerr<<"Syntax: pdnsutil list-keys [ZONE]"<<endl;
- return 0;
- }
- string zname;
- if (cmds.size() == 2) {
- zname = cmds.at(1);
- }
- return listKeys(zname, dk);
+ return removeAutoPrimary(cmds.at(1), cmds.at(2));
+}
+
+static int listAutoprimaries([[maybe_unused]] vector<string>& cmds)
+{
+ return listAutoPrimaries();
+}
+
+static int replaceRRSet(vector<string>& cmds)
+{
+ if(cmds.size() < 5) {
+ cerr<<R"(Syntax: pdnsutil replace-rrset ZONE name type [ttl] "content" ["content"...])"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "load-zone") {
- if(cmds.size() < 3) {
- cerr<<"Syntax: pdnsutil load-zone ZONE FILENAME [ZONE FILENAME] .."<<endl;
- return 0;
- }
- if (cmds.at(1) == ".")
- cmds.at(1).clear();
+ return addOrReplaceRecord(false , cmds);
+}
- for(size_t n=1; n + 2 <= cmds.size(); n+=2) {
- auto ret = loadZone(DNSName(cmds.at(n)), cmds.at(n + 1));
- if (ret) exit(ret);
- }
+static int deleteRRSet(vector<string>& cmds)
+{
+ if(cmds.size() != 4) {
+ cerr<<"Syntax: pdnsutil delete-rrset ZONE name type"<<endl;
return 0;
}
- else if (cmds.at(0) == "secure-zone") {
- if(cmds.size() < 2) {
- cerr << "Syntax: pdnsutil secure-zone ZONE"<<endl;
- return 0;
- }
- vector<DNSName> mustRectify;
- unsigned int zoneErrors=0;
- for(unsigned int n = 1; n < cmds.size(); ++n) {
- DNSName zone(cmds.at(n));
- dk.startTransaction(zone, -1);
- if(secureZone(dk, zone)) {
- mustRectify.push_back(zone);
- } else {
- zoneErrors++;
- }
- dk.commitTransaction();
- }
+ return deleteRRSet(cmds.at(1), cmds.at(2), cmds.at(3));
+}
+
+static int listZone(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr<<"Syntax: pdnsutil list-zone ZONE"<<endl;
+ return 0;
+ }
+ if (cmds.at(1) == ".")
+ cmds.at(1).clear();
- for(const auto& zone : mustRectify)
- rectifyZone(dk, zone);
+ return listZone(DNSName(cmds.at(1)));
+}
- if (zoneErrors) {
- return 1;
- }
+static int editZone(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr<<"Syntax: pdnsutil edit-zone ZONE"<<endl;
return 0;
}
- else if (cmds.at(0) == "secure-all-zones") {
- if (cmds.size() >= 2 && !pdns_iequals(cmds.at(1), "increase-serial")) {
- cerr << "Syntax: pdnsutil secure-all-zones [increase-serial]"<<endl;
- return 0;
- }
+ if (cmds.at(1) == ".")
+ cmds.at(1).clear();
- UeberBackend B("default");
+ PDNSColors col(g_vm.count("no-colors"));
+ return editZone(DNSName(cmds.at(1)), col);
+}
- vector<DomainInfo> domainInfo;
- B.getAllDomains(&domainInfo, false, false);
-
- unsigned int zonesSecured=0, zoneErrors=0;
- for(const DomainInfo& di : domainInfo) {
- if(!dk.isSecuredZone(di.zone)) {
- cout<<"Securing "<<di.zone<<": ";
- if (secureZone(dk, di.zone)) {
- zonesSecured++;
- if (cmds.size() == 2) {
- if (!increaseSerial(di.zone, dk))
- continue;
- } else
- continue;
- }
- zoneErrors++;
- }
- }
+static int clearZone(vector<string>& cmds)
+{
+ if(cmds.size() != 2) {
+ cerr<<"Syntax: pdnsutil clear-zone ZONE"<<endl;
+ return 0;
+ }
+ if (cmds.at(1) == ".")
+ cmds.at(1).clear();
- cout<<"Secured: "<<zonesSecured<<" zones. Errors: "<<zoneErrors<<endl;
+ return clearZone(DNSName(cmds.at(1)));
+}
- if (zoneErrors) {
- return 1;
- }
+static int listKeys(vector<string>& cmds)
+{
+ if(cmds.size() > 2) {
+ cerr<<"Syntax: pdnsutil list-keys [ZONE]"<<endl;
return 0;
}
- else if (cmds.at(0) == "set-kind") {
- if(cmds.size() != 3) {
- cerr<<"Syntax: pdnsutil set-kind ZONE KIND"<<endl;
- return 0;
- }
- DNSName zone(cmds.at(1));
- auto kind = DomainInfo::stringToKind(cmds.at(2));
- return setZoneKind(zone, kind);
+ DNSSECKeeper dk;
+ string zname;
+ if (cmds.size() == 2) {
+ zname = cmds.at(1);
}
- else if (cmds.at(0) == "set-options-json") {
- if (cmds.size() != 3) {
- cerr << "Syntax: pdnsutil set-options ZONE VALUE" << endl;
- return EXIT_FAILURE;
- }
+ return listKeys(zname, dk);
+}
- // Verify json
- if (!cmds.at(2).empty()) {
- std::string err;
- json11::Json doc = json11::Json::parse(cmds.at(2), err);
- if (doc.is_null()) {
- cerr << "Parsing of JSON document failed:" << err << endl;
- return EXIT_FAILURE;
- }
- }
+static int loadZone(vector<string>& cmds)
+{
+ if(cmds.size() < 3) {
+ cerr<<"Syntax: pdnsutil load-zone ZONE FILENAME [ZONE FILENAME] .."<<endl;
+ return 0;
+ }
+ if (cmds.at(1) == ".")
+ cmds.at(1).clear();
- DNSName zone(cmds.at(1));
+ for(size_t n=1; n + 2 <= cmds.size(); n+=2) {
+ auto ret = loadZone(DNSName(cmds.at(n)), cmds.at(n + 1));
+ if (ret) exit(ret);
+ }
+ return 0;
+}
- return setZoneOptionsJson(zone, cmds.at(2));
+static int secureZone(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr << "Syntax: pdnsutil secure-zone ZONE"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "set-option") {
- if (cmds.size() < 5 || (cmds.size() > 5 && (cmds.at(3) != "group"))) {
- cerr << "Syntax: pdnsutil set-option ZONE [producer|consumer] [coo|unique|group] VALUE [VALUE ...]1" << endl;
- return EXIT_FAILURE;
+ DNSSECKeeper dk;
+ vector<DNSName> mustRectify;
+ unsigned int zoneErrors=0;
+ for(unsigned int n = 1; n < cmds.size(); ++n) {
+ DNSName zone(cmds.at(n));
+ dk.startTransaction(zone, -1);
+ if(secureZone(dk, zone)) {
+ mustRectify.push_back(zone);
+ } else {
+ zoneErrors++;
}
+ dk.commitTransaction();
+ }
- if ((cmds.at(2) != "producer" && cmds.at(2) != "consumer") || (cmds.at(3) != "coo" && cmds.at(3) != "unique" && cmds.at(3) != "group")) {
- cerr << "Syntax: pdnsutil set-option ZONE [producer|consumer] [coo|unique|group] VALUE [VALUE ...]" << endl;
- return EXIT_FAILURE;
- }
+ for(const auto& zone : mustRectify)
+ rectifyZone(dk, zone);
+
+ if (zoneErrors) {
+ return 1;
+ }
+ return 0;
+}
+
+static int secureAllZones(vector<string>& cmds)
+{
+ if (cmds.size() >= 2 && !pdns_iequals(cmds.at(1), "increase-serial")) {
+ cerr << "Syntax: pdnsutil secure-all-zones [increase-serial]"<<endl;
+ return 0;
+ }
+
+ DNSSECKeeper dk;
+ UeberBackend B("default");
- DNSName zone(cmds.at(1));
- set<string> values;
- for (unsigned int n = 4; n < cmds.size(); ++n) {
- if (!cmds.at(n).empty()) {
- values.insert(cmds.at(n));
+ vector<DomainInfo> domainInfo;
+ B.getAllDomains(&domainInfo, false, false);
+
+ unsigned int zonesSecured=0, zoneErrors=0;
+ for(const DomainInfo& di : domainInfo) {
+ if(!dk.isSecuredZone(di.zone)) {
+ cout<<"Securing "<<di.zone<<": ";
+ if (secureZone(dk, di.zone)) {
+ zonesSecured++;
+ if (cmds.size() == 2) {
+ if (!increaseSerial(di.zone, dk))
+ continue;
+ } else
+ continue;
}
+ zoneErrors++;
}
+ }
+
+ cout<<"Secured: "<<zonesSecured<<" zones. Errors: "<<zoneErrors<<endl;
- return setZoneOption(zone, cmds.at(2), cmds.at(3), values);
+ if (zoneErrors) {
+ return 1;
}
- else if (cmds.at(0) == "set-catalog") {
- if (cmds.size() != 3) {
- cerr << "Syntax: pdnsutil set-catalog ZONE CATALOG" << endl;
- return 0;
- }
- DNSName zone(cmds.at(1));
- DNSName catalog; // Create an empty DNSName()
- if (!cmds.at(2).empty()) {
- catalog = DNSName(cmds.at(2));
- }
- return setZoneCatalog(zone, catalog);
+ return 0;
+}
+
+static int setKind(vector<string>& cmds)
+{
+ if(cmds.size() != 3) {
+ cerr<<"Syntax: pdnsutil set-kind ZONE KIND"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "set-account") {
- if(cmds.size() != 3) {
- cerr<<"Syntax: pdnsutil set-account ZONE ACCOUNT"<<endl;
- return 0;
- }
- DNSName zone(cmds.at(1));
- return setZoneAccount(zone, cmds.at(2));
+ DNSName zone(cmds.at(1));
+ auto kind = DomainInfo::stringToKind(cmds.at(2));
+ return setZoneKind(zone, kind);
+}
+
+static int setOptionsJson(vector<string>& cmds)
+{
+ if (cmds.size() != 3) {
+ cerr << "Syntax: pdnsutil set-options ZONE VALUE" << endl;
+ return EXIT_FAILURE;
}
- else if (cmds.at(0) == "set-nsec3") {
- if(cmds.size() < 2) {
- cerr<<"Syntax: pdnsutil set-nsec3 ZONE 'params' [narrow]"<<endl;
- return 0;
- }
- string nsec3params = cmds.size() > 2 ? cmds.at(2) : "1 0 0 -";
- bool narrow = cmds.size() > 3 && cmds.at(3) == "narrow";
- NSEC3PARAMRecordContent ns3pr(nsec3params);
- DNSName zone(cmds.at(1));
- if (zone.wirelength() > 222) {
- cerr<<"Cannot enable NSEC3 for " << zone << " as it is too long (" << zone.wirelength() << " bytes, maximum is 222 bytes)"<<endl;
- return 1;
- }
- if(ns3pr.d_algorithm != 1) {
- cerr<<"NSEC3PARAM algorithm set to '"<<std::to_string(ns3pr.d_algorithm)<<"', but '1' is the only valid value"<<endl;
+ // Verify json
+ if (!cmds.at(2).empty()) {
+ std::string err;
+ json11::Json doc = json11::Json::parse(cmds.at(2), err);
+ if (doc.is_null()) {
+ cerr << "Parsing of JSON document failed:" << err << endl;
return EXIT_FAILURE;
}
- if (! dk.setNSEC3PARAM(zone, ns3pr, narrow)) {
- cerr<<"Cannot set NSEC3 param for " << zone << endl;
- return 1;
- }
+ }
- if (!ns3pr.d_flags)
- cerr<<"NSEC3 set, ";
- else
- cerr<<"NSEC3 (opt-out) set, ";
+ DNSName zone(cmds.at(1));
- if(dk.isSecuredZone(zone))
- cerr<<"Done, please rectify your zone if your backend needs it (or reload it if you are using the bindbackend)"<<endl;
- else
- cerr<<"Done, please secure and rectify your zone (or reload it if you are using the bindbackend)"<<endl;
+ return setZoneOptionsJson(zone, cmds.at(2));
+}
- return 0;
+static int setOption(vector<string>& cmds)
+{
+ if (cmds.size() < 5 || (cmds.size() > 5 && (cmds.at(3) != "group"))) {
+ cerr << "Syntax: pdnsutil set-option ZONE [producer|consumer] [coo|unique|group] VALUE [VALUE ...]1" << endl;
+ return EXIT_FAILURE;
}
- else if (cmds.at(0) == "set-presigned") {
- if(cmds.size() < 2) {
- cerr<<"Syntax: pdnsutil set-presigned ZONE"<<endl;
- return 0;
- }
- if (!dk.setPresigned(DNSName(cmds.at(1)))) {
- cerr << "Could not set presigned for " << cmds.at(1) << " (is DNSSEC enabled in your backend?)" << endl;
- return 1;
- }
- return 0;
+
+ if ((cmds.at(2) != "producer" && cmds.at(2) != "consumer") || (cmds.at(3) != "coo" && cmds.at(3) != "unique" && cmds.at(3) != "group")) {
+ cerr << "Syntax: pdnsutil set-option ZONE [producer|consumer] [coo|unique|group] VALUE [VALUE ...]" << endl;
+ return EXIT_FAILURE;
}
- else if (cmds.at(0) == "set-publish-cdnskey") {
- if (cmds.size() < 2 || (cmds.size() == 3 && cmds.at(2) != "delete")) {
- cerr<<"Syntax: pdnsutil set-publish-cdnskey ZONE [delete]"<<endl;
- return 0;
- }
- if (!dk.setPublishCDNSKEY(DNSName(cmds.at(1)), (cmds.size() == 3 && cmds.at(2) == "delete"))) {
- cerr << "Could not set publishing for CDNSKEY records for " << cmds.at(1) << endl;
- return 1;
+
+ DNSName zone(cmds.at(1));
+ set<string> values;
+ for (unsigned int n = 4; n < cmds.size(); ++n) {
+ if (!cmds.at(n).empty()) {
+ values.insert(cmds.at(n));
}
- return 0;
}
- else if (cmds.at(0) == "set-publish-cds") {
- if(cmds.size() < 2) {
- cerr<<"Syntax: pdnsutil set-publish-cds ZONE [DIGESTALGOS]"<<endl;
- return 0;
- }
- // If DIGESTALGOS is unset
- if(cmds.size() == 2)
- cmds.push_back("2");
+ return setZoneOption(zone, cmds.at(2), cmds.at(3), values);
+}
- if (!dk.setPublishCDS(DNSName(cmds.at(1)), cmds.at(2))) {
- cerr << "Could not set publishing for CDS records for " << cmds.at(1) << endl;
- return 1;
- }
- return 0;
- }
- else if (cmds.at(0) == "unset-presigned") {
- if(cmds.size() < 2) {
- cerr<<"Syntax: pdnsutil unset-presigned ZONE"<<endl;
- return 0;
- }
- if (!dk.unsetPresigned(DNSName(cmds.at(1)))) {
- cerr << "Could not unset presigned on for " << cmds.at(1) << endl;
- return 1;
- }
+static int setCatalog(vector<string>& cmds)
+{
+ if (cmds.size() != 3) {
+ cerr << "Syntax: pdnsutil set-catalog ZONE CATALOG" << endl;
return 0;
}
- else if (cmds.at(0) == "unset-publish-cdnskey") {
- if(cmds.size() < 2) {
- cerr<<"Syntax: pdnsutil unset-publish-cdnskey ZONE"<<endl;
- return 0;
- }
- if (!dk.unsetPublishCDNSKEY(DNSName(cmds.at(1)))) {
- cerr << "Could not unset publishing for CDNSKEY records for " << cmds.at(1) << endl;
- return 1;
- }
- return 0;
+ DNSName zone(cmds.at(1));
+ DNSName catalog; // Create an empty DNSName()
+ if (!cmds.at(2).empty()) {
+ catalog = DNSName(cmds.at(2));
}
- else if (cmds.at(0) == "unset-publish-cds") {
- if(cmds.size() < 2) {
- cerr<<"Syntax: pdnsutil unset-publish-cds ZONE"<<endl;
- return 0;
- }
- if (!dk.unsetPublishCDS(DNSName(cmds.at(1)))) {
- cerr << "Could not unset publishing for CDS records for " << cmds.at(1) << endl;
- return 1;
- }
+ return setZoneCatalog(zone, catalog);
+}
+
+static int setAccount(vector<string>& cmds)
+{
+ if(cmds.size() != 3) {
+ cerr<<"Syntax: pdnsutil set-account ZONE ACCOUNT"<<endl;
return 0;
}
- else if(cmds.at(0) == "hash-password") {
- if (cmds.size() < 2) {
- cerr<<"Syntax: pdnsutil hash-password PASSWORD"<<endl;
- return 0;
- }
- cout<<hashPassword(cmds.at(1))<<endl;
+ DNSName zone(cmds.at(1));
+ return setZoneAccount(zone, cmds.at(2));
+}
+
+static int setNsec3(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr<<"Syntax: pdnsutil set-nsec3 ZONE 'params' [narrow]"<<endl;
return 0;
}
- else if (cmds.at(0) == "hash-zone-record") {
- if(cmds.size() < 3) {
- cerr<<"Syntax: pdnsutil hash-zone-record ZONE RNAME"<<endl;
- return 0;
- }
- DNSName zone(cmds.at(1));
- DNSName record(cmds.at(2));
- NSEC3PARAMRecordContent ns3pr;
- bool narrow = false;
- if(!dk.getNSEC3PARAM(zone, &ns3pr, &narrow)) {
- cerr<<"The '"<<zone<<"' zone does not use NSEC3"<<endl;
- return 0;
- }
- if(narrow) {
- cerr<<"The '"<<zone<<"' zone uses narrow NSEC3, but calculating hash anyhow"<<endl;
- }
+ string nsec3params = cmds.size() > 2 ? cmds.at(2) : "1 0 0 -";
+ bool narrow = cmds.size() > 3 && cmds.at(3) == "narrow";
+ NSEC3PARAMRecordContent ns3pr(nsec3params);
- cout<<toBase32Hex(hashQNameWithSalt(ns3pr, record))<<endl;
+ DNSSECKeeper dk;
+ DNSName zone(cmds.at(1));
+ if (zone.wirelength() > 222) {
+ cerr<<"Cannot enable NSEC3 for " << zone << " as it is too long (" << zone.wirelength() << " bytes, maximum is 222 bytes)"<<endl;
+ return 1;
}
- else if (cmds.at(0) == "unset-nsec3") {
- if(cmds.size() < 2) {
- cerr<<"Syntax: pdnsutil unset-nsec3 ZONE"<<endl;
- return 0;
- }
- if (!dk.unsetNSEC3PARAM(DNSName(cmds.at(1)))) {
- cerr << "Cannot unset NSEC3 param for " << cmds.at(1) << endl;
- return 1;
- }
+ if(ns3pr.d_algorithm != 1) {
+ cerr<<"NSEC3PARAM algorithm set to '"<<std::to_string(ns3pr.d_algorithm)<<"', but '1' is the only valid value"<<endl;
+ return EXIT_FAILURE;
+ }
+ if (! dk.setNSEC3PARAM(zone, ns3pr, narrow)) {
+ cerr<<"Cannot set NSEC3 param for " << zone << endl;
+ return 1;
+ }
+
+ if (!ns3pr.d_flags)
+ cerr<<"NSEC3 set, ";
+ else
+ cerr<<"NSEC3 (opt-out) set, ";
+
+ if(dk.isSecuredZone(zone))
cerr<<"Done, please rectify your zone if your backend needs it (or reload it if you are using the bindbackend)"<<endl;
+ else
+ cerr<<"Done, please secure and rectify your zone (or reload it if you are using the bindbackend)"<<endl;
+
+ return 0;
+}
+static int setPresigned(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr<<"Syntax: pdnsutil set-presigned ZONE"<<endl;
return 0;
}
- else if (cmds.at(0) == "export-zone-key") {
- if (cmds.size() < 3) {
- cerr << "Syntax: pdnsutil export-zone-key ZONE KEY-ID" << endl;
- return 1;
- }
-
- string zone = cmds.at(1);
- auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
- DNSSECPrivateKey dpk = dk.getKeyById(DNSName(zone), id);
- cout << dpk.getKey()->convertToISC() << endl;
+ DNSSECKeeper dk;
+ if (!dk.setPresigned(DNSName(cmds.at(1)))) {
+ cerr << "Could not set presigned for " << cmds.at(1) << " (is DNSSEC enabled in your backend?)" << endl;
+ return 1;
}
- else if (cmds.at(0) == "export-zone-key-pem") {
- if (cmds.size() < 3) {
- cerr << "Syntax: pdnsutil export-zone-key-pem ZONE KEY-ID" << endl;
- return 1;
- }
+ return 0;
+}
- string zone = cmds.at(1);
- auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
- DNSSECPrivateKey dpk = dk.getKeyById(DNSName(zone), id);
- dpk.getKey()->convertToPEMFile(*stdout);
+static int setPublishCDNSKey(vector<string>& cmds)
+{
+ if (cmds.size() < 2 || (cmds.size() == 3 && cmds.at(2) != "delete")) {
+ cerr<<"Syntax: pdnsutil set-publish-cdnskey ZONE [delete]"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "increase-serial") {
- if (cmds.size() < 2) {
- cerr << "Syntax: pdnsutil increase-serial ZONE" << endl;
- return 1;
- }
- return increaseSerial(DNSName(cmds.at(1)), dk);
+ DNSSECKeeper dk;
+ if (!dk.setPublishCDNSKEY(DNSName(cmds.at(1)), (cmds.size() == 3 && cmds.at(2) == "delete"))) {
+ cerr << "Could not set publishing for CDNSKEY records for " << cmds.at(1) << endl;
+ return 1;
}
- else if (cmds.at(0) == "import-zone-key-pem") {
- if (cmds.size() < 4) {
- cerr << "Syntax: pdnsutil import-zone-key-pem ZONE FILE ALGORITHM {ksk|zsk}" << endl;
- return 1;
- }
-
- const string zone = cmds.at(1);
- const string filename = cmds.at(2);
- const auto algorithm = pdns::checked_stoi<unsigned int>(cmds.at(3));
+ return 0;
+}
- errno = 0;
- pdns::UniqueFilePtr filePtr{std::fopen(filename.c_str(), "r")};
- if (filePtr == nullptr) {
- auto errMsg = pdns::getMessageFromErrno(errno);
- throw runtime_error("Failed to open PEM file `" + filename + "`: " + errMsg);
- }
+static int setPublishCDs(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr<<"Syntax: pdnsutil set-publish-cds ZONE [DIGESTALGOS]"<<endl;
+ return 0;
+ }
- DNSKEYRecordContent drc;
- shared_ptr<DNSCryptoKeyEngine> key{DNSCryptoKeyEngine::makeFromPEMFile(drc, algorithm, *filePtr, filename)};
- if (!key) {
- cerr << "Could not convert key from PEM to internal format" << endl;
- return 1;
- }
+ // If DIGESTALGOS is unset
+ if(cmds.size() == 2)
+ cmds.push_back("2");
- DNSSECPrivateKey dpk;
+ DNSSECKeeper dk;
+ if (!dk.setPublishCDS(DNSName(cmds.at(1)), cmds.at(2))) {
+ cerr << "Could not set publishing for CDS records for " << cmds.at(1) << endl;
+ return 1;
+ }
+ return 0;
+}
- uint8_t algo = 0;
- pdns::checked_stoi_into(algo, cmds.at(3));
- if (algo == DNSSECKeeper::RSASHA1NSEC3SHA1) {
- algo = DNSSECKeeper::RSASHA1;
- }
+static int unsetPresigned(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr<<"Syntax: pdnsutil unset-presigned ZONE"<<endl;
+ return 0;
+ }
+ DNSSECKeeper dk;
+ if (!dk.unsetPresigned(DNSName(cmds.at(1)))) {
+ cerr << "Could not unset presigned on for " << cmds.at(1) << endl;
+ return 1;
+ }
+ return 0;
+}
- cerr << std::to_string(algo) << endl;
+static int unsetPublishCDNSKey(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr<<"Syntax: pdnsutil unset-publish-cdnskey ZONE"<<endl;
+ return 0;
+ }
+ DNSSECKeeper dk;
+ if (!dk.unsetPublishCDNSKEY(DNSName(cmds.at(1)))) {
+ cerr << "Could not unset publishing for CDNSKEY records for " << cmds.at(1) << endl;
+ return 1;
+ }
+ return 0;
+}
- uint16_t flags = 0;
- if (cmds.size() > 4) {
- if (pdns_iequals(cmds.at(4), "ZSK")) {
- flags = 256;
- }
- else if (pdns_iequals(cmds.at(4), "KSK")) {
- flags = 257;
- }
- else {
- cerr << "Unknown key flag '" << cmds.at(4) << "'" << endl;
- return 1;
- }
- }
- else {
- flags = 257; // ksk
- }
- dpk.setKey(key, flags, algo);
+static int unsetPublishCDs(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr<<"Syntax: pdnsutil unset-publish-cds ZONE"<<endl;
+ return 0;
+ }
+ DNSSECKeeper dk;
+ if (!dk.unsetPublishCDS(DNSName(cmds.at(1)))) {
+ cerr << "Could not unset publishing for CDS records for " << cmds.at(1) << endl;
+ return 1;
+ }
+ return 0;
+}
- int64_t id{-1};
- if (!dk.addKey(DNSName(zone), dpk, id)) {
- cerr << "Adding key failed, perhaps DNSSEC not enabled in configuration?" << endl;
- return 1;
- }
+static int hashZoneRecord(vector<string>& cmds)
+{
+ if(cmds.size() < 3) {
+ cerr<<"Syntax: pdnsutil hash-zone-record ZONE RNAME"<<endl;
+ return 0;
+ }
+ DNSSECKeeper dk;
+ DNSName zone(cmds.at(1));
+ DNSName record(cmds.at(2));
+ NSEC3PARAMRecordContent ns3pr;
+ bool narrow = false;
+ if(!dk.getNSEC3PARAM(zone, &ns3pr, &narrow)) {
+ cerr<<"The '"<<zone<<"' zone does not use NSEC3"<<endl;
+ return 0;
+ }
+ if(narrow) {
+ cerr<<"The '"<<zone<<"' zone uses narrow NSEC3, but calculating hash anyhow"<<endl;
+ }
- if (id == -1) {
- cerr << std::to_string(id) << "Key was added, but backend does not support returning of key id" << endl;
- }
- else if (id < -1) {
- cerr << std::to_string(id) << "Key was added, but there was a failure while returning the key id" << endl;
- }
- else {
- cout << std::to_string(id) << endl;
- }
+ cout<<toBase32Hex(hashQNameWithSalt(ns3pr, record))<<endl;
+ return 0;
+}
+
+static int unsetNSec3(vector<string>& cmds)
+{
+ if(cmds.size() < 2) {
+ cerr<<"Syntax: pdnsutil unset-nsec3 ZONE"<<endl;
+ return 0;
}
- else if (cmds.at(0) == "import-zone-key") {
- if(cmds.size() < 3) {
- cerr<<"Syntax: pdnsutil import-zone-key ZONE FILE [ksk|zsk] [active|inactive]"<<endl;
- return 1;
- }
- string zone = cmds.at(1);
- string fname = cmds.at(2);
- DNSKEYRecordContent drc;
- shared_ptr<DNSCryptoKeyEngine> key(DNSCryptoKeyEngine::makeFromISCFile(drc, fname.c_str()));
-
- uint16_t flags = 257;
- bool active=true;
- bool published=true;
-
- for(unsigned int n = 3; n < cmds.size(); ++n) {
- if (pdns_iequals(cmds.at(n), "ZSK"))
- flags = 256;
- else if (pdns_iequals(cmds.at(n), "KSK"))
- flags = 257;
- else if (pdns_iequals(cmds.at(n), "active"))
- active = true;
- else if (pdns_iequals(cmds.at(n), "passive") || pdns_iequals(cmds.at(n), "inactive")) // passive eventually needs to be removed
- active = false;
- else if (pdns_iequals(cmds.at(n), "published"))
- published = true;
- else if (pdns_iequals(cmds.at(n), "unpublished"))
- published = false;
- else {
- cerr << "Unknown key flag '" << cmds.at(n) << "'" << endl;
- return 1;
- }
- }
+ DNSSECKeeper dk;
+ if (!dk.unsetNSEC3PARAM(DNSName(cmds.at(1)))) {
+ cerr << "Cannot unset NSEC3 param for " << cmds.at(1) << endl;
+ return 1;
+ }
+ cerr<<"Done, please rectify your zone if your backend needs it (or reload it if you are using the bindbackend)"<<endl;
- DNSSECPrivateKey dpk;
- uint8_t algo = key->getAlgorithm();
- if (algo == DNSSECKeeper::RSASHA1NSEC3SHA1) {
- algo = DNSSECKeeper::RSASHA1;
- }
- dpk.setKey(key, flags, algo);
+ return 0;
+}
- int64_t id{-1};
- if (!dk.addKey(DNSName(zone), dpk, id, active, published)) {
- cerr<<"Adding key failed, perhaps DNSSEC not enabled in configuration?"<<endl;
- return 1;
- }
- if (id == -1) {
- cerr<<std::to_string(id)<<"Key was added, but backend does not support returning of key id"<<endl;
- } else if (id < -1) {
- cerr<<std::to_string(id)<<"Key was added, but there was a failure while returning the key id"<<endl;
- } else {
- cout<<std::to_string(id)<<endl;
- }
+static int exportZoneKey(vector<string>& cmds)
+{
+ if (cmds.size() < 3) {
+ cerr << "Syntax: pdnsutil export-zone-key ZONE KEY-ID" << endl;
+ return 1;
}
- else if (cmds.at(0) == "export-zone-dnskey") {
- if(cmds.size() < 3) {
- cerr<<"Syntax: pdnsutil export-zone-dnskey ZONE KEY-ID"<<endl;
- return 1;
- }
- DNSName zone(cmds.at(1));
- auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
- DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
- cout << zone<<" IN DNSKEY "<<dpk.getDNSKEY().getZoneRepresentation() <<endl;
+ DNSSECKeeper dk;
+ string zone = cmds.at(1);
+ auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
+ DNSSECPrivateKey dpk = dk.getKeyById(DNSName(zone), id);
+ cout << dpk.getKey()->convertToISC() << endl;
+ return 0;
+}
+
+static int exportZoneKeyPEM(vector<string>& cmds)
+{
+ if (cmds.size() < 3) {
+ cerr << "Syntax: pdnsutil export-zone-key-pem ZONE KEY-ID" << endl;
+ return 1;
}
- else if (cmds.at(0) == "generate-zone-key") {
- if(cmds.size() < 2 ) {
- cerr << "Syntax: pdnsutil generate-zone-key zsk|ksk [rsasha1|rsasha1-nsec3-sha1|rsasha256|rsasha512|ecdsa256|ecdsa384";
-#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO_ED25519)
- cerr << "|ed25519";
-#endif
-#if defined(HAVE_LIBCRYPTO_ED448)
- cerr << "|ed448";
-#endif
- cerr << "] [bits]"<<endl;
- return 0;
- }
- // need to get algorithm, bits & ksk or zsk from commandline
- bool keyOrZone=false;
- int tmp_algo=0;
- int bits=0;
- int algorithm=DNSSECKeeper::ECDSA256;
- for(unsigned int n=1; n < cmds.size(); ++n) {
- if (pdns_iequals(cmds.at(n), "zsk"))
- keyOrZone = false;
- else if (pdns_iequals(cmds.at(n), "ksk"))
- keyOrZone = true;
- else if ((tmp_algo = DNSSECKeeper::shorthand2algorithm(cmds.at(n))) > 0) {
- algorithm = tmp_algo;
- }
- else if (pdns::checked_stoi<int>(cmds.at(n)) != 0)
- pdns::checked_stoi_into(bits, cmds.at(n));
- else {
- cerr << "Unknown algorithm, key flag or size '" << cmds.at(n) << "'" << endl;
- return 0;
- }
- }
- cerr<<"Generating a " << (keyOrZone ? "KSK" : "ZSK")<<" with algorithm = "<<algorithm<<endl;
- if(bits)
- cerr<<"Requesting specific key size of "<<bits<<" bits"<<endl;
- shared_ptr<DNSCryptoKeyEngine> dpk(DNSCryptoKeyEngine::make(algorithm));
- if(!bits) {
- if(algorithm <= 10)
- bits = keyOrZone ? 2048 : 1024;
- else {
- if(algorithm == DNSSECKeeper::ECCGOST || algorithm == DNSSECKeeper::ECDSA256 || algorithm == DNSSECKeeper::ED25519)
- bits = 256;
- else if(algorithm == DNSSECKeeper::ECDSA384)
- bits = 384;
- else if(algorithm == DNSSECKeeper::ED448)
- bits = 456;
- else {
- throw runtime_error("Can not guess key size for algorithm "+std::to_string(algorithm));
- }
- }
- }
- dpk->create(bits);
- DNSSECPrivateKey dspk;
- dspk.setKey(dpk, keyOrZone ? 257 : 256, algorithm);
+ DNSSECKeeper dk;
+ string zone = cmds.at(1);
+ auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
+ DNSSECPrivateKey dpk = dk.getKeyById(DNSName(zone), id);
+ dpk.getKey()->convertToPEMFile(*stdout);
+ return 0;
+}
- // print key to stdout
- cout << "Flags: " << dspk.getFlags() << endl <<
- dspk.getKey()->convertToISC() << endl;
+static int increaseSerial(vector<string>& cmds)
+{
+ if (cmds.size() < 2) {
+ cerr << "Syntax: pdnsutil increase-serial ZONE" << endl;
+ return 1;
}
- else if (cmds.at(0) == "generate-tsig-key") {
- string usage = "Syntax: " + cmds.at(0) + " name (hmac-md5|hmac-sha1|hmac-sha224|hmac-sha256|hmac-sha384|hmac-sha512)";
- if (cmds.size() < 3) {
- cerr << usage << endl;
- return 0;
- }
- DNSName name(cmds.at(1));
- DNSName algo(cmds.at(2));
- string key;
- try {
- key = makeTSIGKey(algo);
- } catch(const PDNSException& e) {
- cerr << "Could not create new TSIG key " << name << " " << algo << ": "<< e.reason << endl;
- return 1;
- }
+ DNSSECKeeper dk;
+ return increaseSerial(DNSName(cmds.at(1)), dk);
+}
- UeberBackend B("default");
- 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 {
- cerr << "Failure storing new TSIG key " << name << " " << algo << " " << key << endl;
- return 1;
- }
- return 0;
+static int importZoneKeyPEM(vector<string>& cmds)
+{
+ if (cmds.size() < 4) {
+ cerr << "Syntax: pdnsutil import-zone-key-pem ZONE FILE ALGORITHM {ksk|zsk}" << endl;
+ return 1;
}
- else if (cmds.at(0) == "import-tsig-key") {
- if (cmds.size() < 4) {
- cerr << "Syntax: " << cmds.at(0) << " name algorithm key" << endl;
- return 0;
- }
- DNSName name(cmds.at(1));
- string algo = cmds.at(2);
- string key = cmds.at(3);
- UeberBackend B("default");
- if (B.setTSIGKey(name, DNSName(algo), key)) {
- cout << "Imported TSIG key " << name << " " << algo << endl;
- }
- else {
- cerr << "Failure importing TSIG key " << name << " " << algo << endl;
- return 1;
- }
- return 0;
+ const string zone = cmds.at(1);
+ const string filename = cmds.at(2);
+ const auto algorithm = pdns::checked_stoi<unsigned int>(cmds.at(3));
+
+ errno = 0;
+ pdns::UniqueFilePtr filePtr{std::fopen(filename.c_str(), "r")};
+ if (filePtr == nullptr) {
+ auto errMsg = pdns::getMessageFromErrno(errno);
+ throw runtime_error("Failed to open PEM file `" + filename + "`: " + errMsg);
}
- else if (cmds.at(0) == "delete-tsig-key") {
- if (cmds.size() < 2) {
- cerr << "Syntax: " << cmds.at(0) << " name" << endl;
- return 0;
- }
- DNSName name(cmds.at(1));
- UeberBackend B("default");
- if (B.deleteTSIGKey(name)) {
- cout << "Deleted TSIG key " << name << endl;
- }
- else {
- cerr << "Failure deleting TSIG key " << name << endl;
- return 1;
- }
- return 0;
+ DNSKEYRecordContent drc;
+ shared_ptr<DNSCryptoKeyEngine> key{DNSCryptoKeyEngine::makeFromPEMFile(drc, algorithm, *filePtr, filename)};
+ if (!key) {
+ cerr << "Could not convert key from PEM to internal format" << endl;
+ return 1;
}
- else if (cmds.at(0) == "list-tsig-keys") {
- std::vector<struct TSIGKey> keys;
- UeberBackend B("default");
- if (B.getTSIGKeys(keys)) {
- for (const TSIGKey& key : keys) {
- cout << key.name.toString() << " " << key.algorithm.toString() << " " << key.key << endl;
- }
- }
- return 0;
+
+ DNSSECPrivateKey dpk;
+
+ uint8_t algo = 0;
+ pdns::checked_stoi_into(algo, cmds.at(3));
+ if (algo == DNSSECKeeper::RSASHA1NSEC3SHA1) {
+ algo = DNSSECKeeper::RSASHA1;
}
- else if (cmds.at(0) == "activate-tsig-key") {
- string metaKey;
- if (cmds.size() < 4) {
- cerr << "Syntax: " << cmds.at(0) << " ZONE NAME {primary|secondary}" << endl;
- return 0;
- }
- DNSName zname(cmds.at(1));
- string name = cmds.at(2);
- if (cmds.at(3) == "primary" || cmds.at(3) == "producer")
- metaKey = "TSIG-ALLOW-AXFR";
- else if (cmds.at(3) == "secondary" || cmds.at(3) == "consumer")
- metaKey = "AXFR-MASTER-TSIG";
- else {
- cerr << "Invalid parameter '" << cmds.at(3) << "', expected primary or secondary type" << endl;
- return 1;
- }
- UeberBackend B("default");
- DomainInfo di;
- if (!B.getDomainInfo(zname, di)) {
- cerr << "Zone '" << zname << "' does not exist" << endl;
- return 1;
- }
- std::vector<std::string> meta;
- if (!B.getDomainMetadata(zname, metaKey, meta)) {
- cerr << "Failure enabling TSIG key " << name << " for " << zname << endl;
- return 1;
- }
- bool found = false;
- for (const std::string& tmpname : meta) {
- if (tmpname == name) {
- found = true;
- break;
- }
+
+ cerr << std::to_string(algo) << endl;
+
+ uint16_t flags = 0;
+ if (cmds.size() > 4) {
+ if (pdns_iequals(cmds.at(4), "ZSK")) {
+ flags = 256;
}
- if (!found)
- meta.push_back(name);
- if (B.setDomainMetadata(zname, metaKey, meta)) {
- cout << "Enabled TSIG key " << name << " for " << zname << endl;
+ else if (pdns_iequals(cmds.at(4), "KSK")) {
+ flags = 257;
}
else {
- cerr << "Failure enabling TSIG key " << name << " for " << zname << endl;
+ cerr << "Unknown key flag '" << cmds.at(4) << "'" << endl;
return 1;
}
- return 0;
}
- else if (cmds.at(0) == "deactivate-tsig-key") {
- string metaKey;
- if (cmds.size() < 4) {
- cerr << "Syntax: " << cmds.at(0) << " ZONE NAME {primary|secondary|producer|consumer}" << endl;
- return 0;
- }
- DNSName zname(cmds.at(1));
- string name = cmds.at(2);
- if (cmds.at(3) == "primary" || cmds.at(3) == "producer")
- metaKey = "TSIG-ALLOW-AXFR";
- else if (cmds.at(3) == "secondary" || cmds.at(3) == "consumer")
- metaKey = "AXFR-MASTER-TSIG";
- else {
- cerr << "Invalid parameter '" << cmds.at(3) << "', expected primary or secondary type" << endl;
- return 1;
- }
+ else {
+ flags = 257; // ksk
+ }
+ dpk.setKey(key, flags, algo);
- UeberBackend B("default");
- DomainInfo di;
- if (!B.getDomainInfo(zname, di)) {
- cerr << "Zone '" << zname << "' does not exist" << endl;
- return 1;
- }
- std::vector<std::string> meta;
- if (!B.getDomainMetadata(zname, metaKey, meta)) {
- cerr << "Failure disabling TSIG key " << name << " for " << zname << endl;
- return 1;
- }
- std::vector<std::string>::iterator iter = meta.begin();
- for (; iter != meta.end(); ++iter)
- if (*iter == name)
- break;
- if (iter != meta.end())
- meta.erase(iter);
- if (B.setDomainMetadata(zname, metaKey, meta)) {
- cout << "Disabled TSIG key " << name << " for " << zname << endl;
- }
- else {
- cerr << "Failure disabling TSIG key " << name << " for " << zname << endl;
- return 1;
- }
- return 0;
+ DNSSECKeeper dk;
+ int64_t id{-1};
+ if (!dk.addKey(DNSName(zone), dpk, id)) {
+ cerr << "Adding key failed, perhaps DNSSEC not enabled in configuration?" << endl;
+ return 1;
}
- else if (cmds.at(0) == "get-meta") {
- UeberBackend B("default");
- if (cmds.size() < 2) {
- cerr << "Syntax: " << cmds.at(0) << " zone [kind kind ..]" << endl;
- return 1;
- }
- DNSName zone(cmds.at(1));
- vector<string> keys;
- DomainInfo di;
- if (!B.getDomainInfo(zone, di)) {
- cerr << "Invalid zone '" << zone << "'" << endl;
- return 1;
- }
-
- if (cmds.size() > 2) {
- keys.assign(cmds.begin() + 2, cmds.end());
- std::cout << "Metadata for '" << zone << "'" << endl;
- for(const auto& kind : keys) {
- vector<string> meta;
- meta.clear();
- if (B.getDomainMetadata(zone, kind, meta)) {
- cout << kind << " = " << boost::join(meta, ", ") << endl;
- }
- }
- } else {
- std::map<std::string, std::vector<std::string> > meta;
- std::cout << "Metadata for '" << zone << "'" << endl;
- B.getAllDomainMetadata(zone, meta);
- for(const auto& each_meta: meta) {
- cout << each_meta.first << " = " << boost::join(each_meta.second, ", ") << endl;
- }
+ if (id == -1) {
+ cerr << std::to_string(id) << "Key was added, but backend does not support returning of key id" << endl;
}
- return 0;
+ else if (id < -1) {
+ cerr << std::to_string(id) << "Key was added, but there was a failure while returning the key id" << endl;
}
- else if (cmds.at(0) == "set-meta" || cmds.at(0) == "add-meta") {
- if (cmds.size() < 3) {
- cerr << "Syntax: " << cmds.at(0) << " ZONE KIND [VALUE VALUE ..]" << endl;
- return 1;
- }
- DNSName zone(cmds.at(1));
- string kind = cmds.at(2);
- const static std::array<string, 7> multiMetaWhitelist = {"ALLOW-AXFR-FROM", "ALLOW-DNSUPDATE-FROM",
- "ALSO-NOTIFY", "TSIG-ALLOW-AXFR", "TSIG-ALLOW-DNSUPDATE", "GSS-ALLOW-AXFR-PRINCIPAL",
- "PUBLISH-CDS"};
- bool clobber = true;
- if (cmds.at(0) == "add-meta") {
- clobber = false;
- if (find(multiMetaWhitelist.begin(), multiMetaWhitelist.end(), kind) == multiMetaWhitelist.end() && kind.find("X-") != 0) {
- cerr<<"Refusing to add metadata to single-value metadata "<<kind<<endl;
- return 1;
- }
- }
- vector<string> meta(cmds.begin() + 3, cmds.end());
- return addOrSetMeta(zone, kind, meta, clobber);
+ else {
+ cout << std::to_string(id) << endl;
}
- else if (cmds.at(0) == "hsm") {
-#ifdef HAVE_P11KIT1
- UeberBackend B("default");
- if (cmds.size() < 2) {
- cerr << "Missing sub-command for pdnsutil hsm"<< std::endl;
- return 0;
- }
- else if (cmds.at(1) == "assign") {
- DNSCryptoKeyEngine::storvector_t storvect;
- DomainInfo di;
- std::vector<DNSBackend::KeyData> keys;
-
- if (cmds.size() < 9) {
- std::cout << "Usage: pdnsutil hsm assign ZONE ALGORITHM {ksk|zsk} MODULE TOKEN PIN LABEL (PUBLABEL)" << std::endl;
- return 1;
- }
-
- DNSName zone(cmds.at(2));
-
- // verify zone
- if (!B.getDomainInfo(zone, di)) {
- cerr << "Unable to assign module to unknown zone '" << zone << "'" << std::endl;
- return 1;
- }
+ return 0;
+}
- int algorithm = DNSSECKeeper::shorthand2algorithm(cmds.at(3));
- if (algorithm<0) {
- cerr << "Unable to use unknown algorithm '" << cmds.at(3) << "'" << std::endl;
- return 1;
- }
+static int importZoneKey(vector<string>& cmds)
+{
+ if(cmds.size() < 3) {
+ cerr<<"Syntax: pdnsutil import-zone-key ZONE FILE [ksk|zsk] [active|inactive]"<<endl;
+ return 1;
+ }
+ string zone = cmds.at(1);
+ string fname = cmds.at(2);
+ DNSKEYRecordContent drc;
+ shared_ptr<DNSCryptoKeyEngine> key(DNSCryptoKeyEngine::makeFromISCFile(drc, fname.c_str()));
- bool keyOrZone = (cmds.at(4) == "ksk" ? true : false);
- string module = cmds.at(5);
- string slot = cmds.at(6);
- string pin = cmds.at(7);
- string label = cmds.at(8);
- string pub_label;
- if (cmds.size() > 9)
- pub_label = cmds.at(9);
- else
- pub_label = label;
-
- std::ostringstream iscString;
- iscString << "Private-key-format: v1.2" << std::endl <<
- "Algorithm: " << algorithm << std::endl <<
- "Engine: " << module << std::endl <<
- "Slot: " << slot << std::endl <<
- "PIN: " << pin << std::endl <<
- "Label: " << label << std::endl <<
- "PubLabel: " << pub_label << std::endl;
-
- DNSKEYRecordContent drc;
-
- shared_ptr<DNSCryptoKeyEngine> dke(DNSCryptoKeyEngine::makeFromISCString(drc, iscString.str()));
- if(!dke->checkKey()) {
- cerr << "Invalid DNS Private Key in engine " << module << " slot " << slot << std::endl;
- return 1;
- }
- DNSSECPrivateKey dpk;
- dpk.setKey(dke, keyOrZone ? 257 : 256);
+ uint16_t flags = 257;
+ bool active=true;
+ bool published=true;
- // make sure this key isn't being reused.
- B.getDomainKeys(zone, keys);
+ for(unsigned int n = 3; n < cmds.size(); ++n) {
+ if (pdns_iequals(cmds.at(n), "ZSK"))
+ flags = 256;
+ else if (pdns_iequals(cmds.at(n), "KSK"))
+ flags = 257;
+ else if (pdns_iequals(cmds.at(n), "active"))
+ active = true;
+ else if (pdns_iequals(cmds.at(n), "passive") || pdns_iequals(cmds.at(n), "inactive")) // passive eventually needs to be removed
+ active = false;
+ else if (pdns_iequals(cmds.at(n), "published"))
+ published = true;
+ else if (pdns_iequals(cmds.at(n), "unpublished"))
+ published = false;
+ else {
+ cerr << "Unknown key flag '" << cmds.at(n) << "'" << endl;
+ return 1;
+ }
+ }
- int64_t id{-1};
- for(DNSBackend::KeyData& kd : keys) {
- if (kd.content == iscString.str()) {
- // it's this one, I guess...
- id = kd.id;
- break;
- }
- }
+ DNSSECPrivateKey dpk;
+ uint8_t algo = key->getAlgorithm();
+ if (algo == DNSSECKeeper::RSASHA1NSEC3SHA1) {
+ algo = DNSSECKeeper::RSASHA1;
+ }
+ dpk.setKey(key, flags, algo);
- if (id > -1) {
- cerr << "You have already assigned this key with ID=" << id << std::endl;
- return 1;
- }
+ DNSSECKeeper dk;
+ int64_t id{-1};
+ if (!dk.addKey(DNSName(zone), dpk, id, active, published)) {
+ cerr<<"Adding key failed, perhaps DNSSEC not enabled in configuration?"<<endl;
+ return 1;
+ }
+ if (id == -1) {
+ cerr<<std::to_string(id)<<"Key was added, but backend does not support returning of key id"<<endl;
+ } else if (id < -1) {
+ cerr<<std::to_string(id)<<"Key was added, but there was a failure while returning the key id"<<endl;
+ } else {
+ cout<<std::to_string(id)<<endl;
+ }
+ return 0;
+}
- if (!dk.addKey(zone, dpk, id)) {
- cerr << "Unable to assign module slot to zone" << std::endl;
- return 1;
- }
+static int expotZoneDNSKey(vector<string>& cmds)
+{
+ if(cmds.size() < 3) {
+ cerr<<"Syntax: pdnsutil export-zone-dnskey ZONE KEY-ID"<<endl;
+ return 1;
+ }
- cerr << "Module " << module << " slot " << slot << " assigned to " << zone << " with key id " << id << endl;
+ DNSSECKeeper dk;
+ DNSName zone(cmds.at(1));
+ auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
+ DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
+ cout << zone<<" IN DNSKEY "<<dpk.getDNSKEY().getZoneRepresentation() <<endl;
+ return 0;
+}
+static int generateZoneKey(vector<string>& cmds)
+{
+ if(cmds.size() < 2 ) {
+ cerr << "Syntax: pdnsutil generate-zone-key zsk|ksk [rsasha1|rsasha1-nsec3-sha1|rsasha256|rsasha512|ecdsa256|ecdsa384";
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO_ED25519)
+ cerr << "|ed25519";
+#endif
+#if defined(HAVE_LIBCRYPTO_ED448)
+ cerr << "|ed448";
+#endif
+ cerr << "] [bits]"<<endl;
+ return 0;
+ }
+ // need to get algorithm, bits & ksk or zsk from commandline
+ bool keyOrZone=false;
+ int tmp_algo=0;
+ int bits=0;
+ int algorithm=DNSSECKeeper::ECDSA256;
+ for(unsigned int n=1; n < cmds.size(); ++n) {
+ if (pdns_iequals(cmds.at(n), "zsk"))
+ keyOrZone = false;
+ else if (pdns_iequals(cmds.at(n), "ksk"))
+ keyOrZone = true;
+ else if ((tmp_algo = DNSSECKeeper::shorthand2algorithm(cmds.at(n))) > 0) {
+ algorithm = tmp_algo;
+ }
+ else if (pdns::checked_stoi<int>(cmds.at(n)) != 0)
+ pdns::checked_stoi_into(bits, cmds.at(n));
+ else {
+ cerr << "Unknown algorithm, key flag or size '" << cmds.at(n) << "'" << endl;
return 0;
}
- else if (cmds.at(1) == "create-key") {
+ }
+ cerr<<"Generating a " << (keyOrZone ? "KSK" : "ZSK")<<" with algorithm = "<<algorithm<<endl;
+ if(bits)
+ cerr<<"Requesting specific key size of "<<bits<<" bits"<<endl;
- if (cmds.size() < 4) {
- cerr << "Usage: pdnsutil hsm create-key ZONE KEY-ID [BITS]" << endl;
- return 1;
- }
- DomainInfo di;
- DNSName zone(cmds.at(2));
- unsigned int id;
- int bits = 2048;
- // verify zone
- if (!B.getDomainInfo(zone, di)) {
- cerr << "Unable to create key for unknown zone '" << zone << "'" << std::endl;
- return 1;
+ shared_ptr<DNSCryptoKeyEngine> dpk(DNSCryptoKeyEngine::make(algorithm));
+ if(!bits) {
+ if(algorithm <= 10)
+ bits = keyOrZone ? 2048 : 1024;
+ else {
+ if(algorithm == DNSSECKeeper::ECCGOST || algorithm == DNSSECKeeper::ECDSA256 || algorithm == DNSSECKeeper::ED25519)
+ bits = 256;
+ else if(algorithm == DNSSECKeeper::ECDSA384)
+ bits = 384;
+ else if(algorithm == DNSSECKeeper::ED448)
+ bits = 456;
+ else {
+ throw runtime_error("Can not guess key size for algorithm "+std::to_string(algorithm));
}
+ }
+ }
+ dpk->create(bits);
+ DNSSECPrivateKey dspk;
+ dspk.setKey(dpk, keyOrZone ? 257 : 256, algorithm);
- pdns::checked_stoi_into(id, cmds.at(3));
- std::vector<DNSBackend::KeyData> keys;
- if (!B.getDomainKeys(zone, keys)) {
- cerr << "No keys found for zone " << zone << std::endl;
- return 1;
- }
+ // print key to stdout
+ cout << "Flags: " << dspk.getFlags() << endl <<
+ dspk.getKey()->convertToISC() << endl;
+ return 0;
+}
- std::unique_ptr<DNSCryptoKeyEngine> dke = nullptr;
- // lookup correct key
- for(DNSBackend::KeyData &kd : keys) {
- if (kd.id == id) {
- // found our key.
- DNSKEYRecordContent dkrc;
- dke = DNSCryptoKeyEngine::makeFromISCString(dkrc, kd.content);
- }
- }
+static int generateTSIGKey(vector<string>& cmds)
+{
+ string usage = "Syntax: " + cmds.at(0) + " name (hmac-md5|hmac-sha1|hmac-sha224|hmac-sha256|hmac-sha384|hmac-sha512)";
+ if (cmds.size() < 3) {
+ cerr << usage << endl;
+ return 0;
+ }
+ DNSName name(cmds.at(1));
+ DNSName algo(cmds.at(2));
+ string key;
+ try {
+ key = makeTSIGKey(algo);
+ } catch(const PDNSException& e) {
+ cerr << "Could not create new TSIG key " << name << " " << algo << ": "<< e.reason << endl;
+ return 1;
+ }
- if (!dke) {
- cerr << "Could not find key with ID " << id << endl;
- return 1;
- }
- if (cmds.size() > 4) {
- pdns::checked_stoi_into(bits, cmds.at(4));
- }
- if (bits < 1) {
- cerr << "Invalid bit size " << bits << "given, must be positive integer";
- return 1;
- }
- try {
- dke->create(bits);
- } catch (PDNSException& e) {
- cerr << e.reason << endl;
- return 1;
- }
+ UeberBackend B("default");
+ 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 {
+ cerr << "Failure storing new TSIG key " << name << " " << algo << " " << key << endl;
+ return 1;
+ }
+ return 0;
+}
- cerr << "Key of size " << dke->getBits() << " created" << std::endl;
- return 0;
- }
-#else
- cerr<<"PKCS#11 support not enabled"<<endl;
+static int importTSIGKey(vector<string>& cmds)
+{
+ if (cmds.size() < 4) {
+ cerr << "Syntax: " << cmds.at(0) << " name algorithm key" << endl;
+ return 0;
+ }
+ DNSName name(cmds.at(1));
+ string algo = cmds.at(2);
+ string key = cmds.at(3);
+
+ UeberBackend B("default");
+ if (B.setTSIGKey(name, DNSName(algo), key)) {
+ cout << "Imported TSIG key " << name << " " << algo << endl;
+ }
+ else {
+ cerr << "Failure importing TSIG key " << name << " " << algo << endl;
return 1;
-#endif
}
- else if (cmds.at(0) == "b2b-migrate") {
- if (cmds.size() < 3) {
- cerr << "Usage: b2b-migrate OLD NEW" << endl;
- return 1;
+ return 0;
+}
+
+static int deleteTSIGKey(vector<string>& cmds)
+{
+ if (cmds.size() < 2) {
+ cerr << "Syntax: " << cmds.at(0) << " name" << endl;
+ return 0;
+ }
+ DNSName name(cmds.at(1));
+
+ UeberBackend B("default");
+ if (B.deleteTSIGKey(name)) {
+ cout << "Deleted TSIG key " << name << endl;
+ }
+ else {
+ cerr << "Failure deleting TSIG key " << name << endl;
+ return 1;
+ }
+ return 0;
+}
+
+static int listTSIGKeys([[maybe_unused]] vector<string>& cmds)
+{
+ std::vector<struct TSIGKey> keys;
+ UeberBackend B("default");
+ if (B.getTSIGKeys(keys)) {
+ for (const TSIGKey& key : keys) {
+ cout << key.name.toString() << " " << key.algorithm.toString() << " " << key.key << endl;
}
+ }
+ return 0;
+}
- if (cmds.at(1) == cmds.at(2)) {
- cerr << "Error: b2b-migrate OLD NEW: OLD cannot be the same as NEW" << endl;
- return 1;
+static int activateTSIGKey(vector<string>& cmds)
+{
+ string metaKey;
+ if (cmds.size() < 4) {
+ cerr << "Syntax: " << cmds.at(0) << " ZONE NAME {primary|secondary}" << endl;
+ return 0;
+ }
+ DNSName zname(cmds.at(1));
+ string name = cmds.at(2);
+ if (cmds.at(3) == "primary" || cmds.at(3) == "producer")
+ metaKey = "TSIG-ALLOW-AXFR";
+ else if (cmds.at(3) == "secondary" || cmds.at(3) == "consumer")
+ metaKey = "AXFR-MASTER-TSIG";
+ else {
+ cerr << "Invalid parameter '" << cmds.at(3) << "', expected primary or secondary type" << endl;
+ return 1;
+ }
+ UeberBackend B("default");
+ DomainInfo di;
+ if (!B.getDomainInfo(zname, di)) {
+ cerr << "Zone '" << zname << "' does not exist" << endl;
+ return 1;
+ }
+ std::vector<std::string> meta;
+ if (!B.getDomainMetadata(zname, metaKey, meta)) {
+ cerr << "Failure enabling TSIG key " << name << " for " << zname << endl;
+ return 1;
+ }
+ bool found = false;
+ for (const std::string& tmpname : meta) {
+ if (tmpname == name) {
+ found = true;
+ break;
}
+ }
+ if (!found)
+ meta.push_back(name);
+ if (B.setDomainMetadata(zname, metaKey, meta)) {
+ cout << "Enabled TSIG key " << name << " for " << zname << endl;
+ }
+ else {
+ cerr << "Failure enabling TSIG key " << name << " for " << zname << endl;
+ return 1;
+ }
+ return 0;
+}
- unique_ptr<DNSBackend> src{nullptr};
- unique_ptr<DNSBackend> tgt{nullptr};
+static int deactivateTSIGKey(vector<string>& cmds)
+{
+ string metaKey;
+ if (cmds.size() < 4) {
+ cerr << "Syntax: " << cmds.at(0) << " ZONE NAME {primary|secondary|producer|consumer}" << endl;
+ return 0;
+ }
+ DNSName zname(cmds.at(1));
+ string name = cmds.at(2);
+ if (cmds.at(3) == "primary" || cmds.at(3) == "producer")
+ metaKey = "TSIG-ALLOW-AXFR";
+ else if (cmds.at(3) == "secondary" || cmds.at(3) == "consumer")
+ metaKey = "AXFR-MASTER-TSIG";
+ else {
+ cerr << "Invalid parameter '" << cmds.at(3) << "', expected primary or secondary type" << endl;
+ return 1;
+ }
- for (auto& backend : BackendMakers().all()) {
- if (backend->getPrefix() == cmds.at(1)) {
- src = std::move(backend);
- }
- else if (backend->getPrefix() == cmds.at(2)) {
- tgt = std::move(backend);
+ UeberBackend B("default");
+ DomainInfo di;
+ if (!B.getDomainInfo(zname, di)) {
+ cerr << "Zone '" << zname << "' does not exist" << endl;
+ return 1;
+ }
+ std::vector<std::string> meta;
+ if (!B.getDomainMetadata(zname, metaKey, meta)) {
+ cerr << "Failure disabling TSIG key " << name << " for " << zname << endl;
+ return 1;
+ }
+ std::vector<std::string>::iterator iter = meta.begin();
+ for (; iter != meta.end(); ++iter)
+ if (*iter == name)
+ break;
+ if (iter != meta.end())
+ meta.erase(iter);
+ if (B.setDomainMetadata(zname, metaKey, meta)) {
+ cout << "Disabled TSIG key " << name << " for " << zname << endl;
+ }
+ else {
+ cerr << "Failure disabling TSIG key " << name << " for " << zname << endl;
+ return 1;
+ }
+ return 0;
+}
+
+static int getMeta(vector<string>& cmds)
+{
+ UeberBackend B("default");
+ if (cmds.size() < 2) {
+ cerr << "Syntax: " << cmds.at(0) << " zone [kind kind ..]" << endl;
+ return 1;
+ }
+ DNSName zone(cmds.at(1));
+ vector<string> keys;
+
+ DomainInfo di;
+ if (!B.getDomainInfo(zone, di)) {
+ cerr << "Invalid zone '" << zone << "'" << endl;
+ return 1;
+ }
+
+ if (cmds.size() > 2) {
+ keys.assign(cmds.begin() + 2, cmds.end());
+ std::cout << "Metadata for '" << zone << "'" << endl;
+ for(const auto& kind : keys) {
+ vector<string> meta;
+ meta.clear();
+ if (B.getDomainMetadata(zone, kind, meta)) {
+ cout << kind << " = " << boost::join(meta, ", ") << endl;
}
}
-
- if (src == nullptr) {
- cerr << "Unknown source backend '" << cmds.at(1) << "'" << endl;
- return 1;
+ } else {
+ std::map<std::string, std::vector<std::string> > meta;
+ std::cout << "Metadata for '" << zone << "'" << endl;
+ B.getAllDomainMetadata(zone, meta);
+ for(const auto& each_meta: meta) {
+ cout << each_meta.first << " = " << boost::join(each_meta.second, ", ") << endl;
}
- if (tgt == nullptr) {
- cerr << "Unknown target backend '" << cmds.at(2) << "'" << endl;
+ }
+ return 0;
+}
+
+static int setMeta(vector<string>& cmds)
+{
+ if (cmds.size() < 3) {
+ cerr << "Syntax: " << cmds.at(0) << " ZONE KIND [VALUE VALUE ..]" << endl;
+ return 1;
+ }
+ DNSName zone(cmds.at(1));
+ string kind = cmds.at(2);
+ const static std::array<string, 7> multiMetaWhitelist = {"ALLOW-AXFR-FROM", "ALLOW-DNSUPDATE-FROM",
+ "ALSO-NOTIFY", "TSIG-ALLOW-AXFR", "TSIG-ALLOW-DNSUPDATE", "GSS-ALLOW-AXFR-PRINCIPAL",
+ "PUBLISH-CDS"};
+ bool clobber = true;
+ if (cmds.at(0) == "add-meta") {
+ clobber = false;
+ if (find(multiMetaWhitelist.begin(), multiMetaWhitelist.end(), kind) == multiMetaWhitelist.end() && kind.find("X-") != 0) {
+ cerr<<"Refusing to add metadata to single-value metadata "<<kind<<endl;
return 1;
}
+ }
+ vector<string> meta(cmds.begin() + 3, cmds.end());
+ return addOrSetMeta(zone, kind, meta, clobber);
+}
+
+#ifdef HAVE_P11KIT1 // {
+static int HSMAssign(vector<string>& cmds)
+{
+ DNSCryptoKeyEngine::storvector_t storvect;
+ DomainInfo di;
+ std::vector<DNSBackend::KeyData> keys;
+
+ if (cmds.size() < 9) {
+ std::cout << "Usage: pdnsutil hsm assign ZONE ALGORITHM {ksk|zsk} MODULE TOKEN PIN LABEL (PUBLABEL)" << std::endl;
+ return 1;
+ }
+
+ UeberBackend B("default");
+ DNSName zone(cmds.at(2));
+
+ // verify zone
+ if (!B.getDomainInfo(zone, di)) {
+ cerr << "Unable to assign module to unknown zone '" << zone << "'" << std::endl;
+ return 1;
+ }
- cout<<"Moving zone(s) from "<<src->getPrefix()<<" to "<<tgt->getPrefix()<<endl;
+ int algorithm = DNSSECKeeper::shorthand2algorithm(cmds.at(3));
+ if (algorithm<0) {
+ cerr << "Unable to use unknown algorithm '" << cmds.at(3) << "'" << std::endl;
+ return 1;
+ }
- vector<DomainInfo> domains;
+ bool keyOrZone = (cmds.at(4) == "ksk" ? true : false);
+ string module = cmds.at(5);
+ string slot = cmds.at(6);
+ string pin = cmds.at(7);
+ string label = cmds.at(8);
+ string pub_label;
+ if (cmds.size() > 9)
+ pub_label = cmds.at(9);
+ else
+ pub_label = label;
- tgt->getAllDomains(&domains, false, true);
- if (!domains.empty())
- throw PDNSException("Target backend has zone(s), please clean it first");
+ std::ostringstream iscString;
+ iscString << "Private-key-format: v1.2" << std::endl <<
+ "Algorithm: " << algorithm << std::endl <<
+ "Engine: " << module << std::endl <<
+ "Slot: " << slot << std::endl <<
+ "PIN: " << pin << std::endl <<
+ "Label: " << label << std::endl <<
+ "PubLabel: " << pub_label << std::endl;
- src->getAllDomains(&domains, false, true);
- // iterate zones
- for(const DomainInfo& di: domains) {
- size_t nr,nc,nm,nk;
- DomainInfo di_new;
- DNSResourceRecord rr;
- cout<<"Processing '"<<di.zone<<"'"<<endl;
- // create zone
- if (!tgt->createDomain(di.zone, di.kind, di.primaries, di.account))
- throw PDNSException("Failed to create zone");
- if (!tgt->getDomainInfo(di.zone, di_new)) throw PDNSException("Failed to create zone");
- // move records
- if (!src->list(di.zone, di.id, true)) throw PDNSException("Failed to list records");
- nr=0;
+ DNSKEYRecordContent drc;
- tgt->startTransaction(di.zone, di_new.id);
+ shared_ptr<DNSCryptoKeyEngine> dke(DNSCryptoKeyEngine::makeFromISCString(drc, iscString.str()));
+ if(!dke->checkKey()) {
+ cerr << "Invalid DNS Private Key in engine " << module << " slot " << slot << std::endl;
+ return 1;
+ }
+ DNSSECPrivateKey dpk;
+ dpk.setKey(dke, keyOrZone ? 257 : 256);
- while(src->get(rr)) {
- rr.domain_id = di_new.id;
- if (!tgt->feedRecord(rr, DNSName())) throw PDNSException("Failed to feed record");
- nr++;
- }
+ // make sure this key isn't being reused.
+ B.getDomainKeys(zone, keys);
- // move comments
- nc=0;
- if (src->listComments(di.id)) {
- Comment c;
- while(src->getComment(c)) {
- c.domain_id = di_new.id;
- if (!tgt->feedComment(c)) {
- throw PDNSException("Target backend does not support comments - remove them first");
- }
- nc++;
- }
- }
- // move metadata
- nm=0;
- std::map<std::string, std::vector<std::string> > meta;
- if (src->getAllDomainMetadata(di.zone, meta)) {
- for (const auto& i : meta) {
- if (!tgt->setDomainMetadata(di.zone, i.first, i.second))
- throw PDNSException("Failed to feed zone metadata");
- nm++;
- }
- }
- // move keys
- nk=0;
- // temp var for KeyID
- int64_t keyID;
- std::vector<DNSBackend::KeyData> keys;
- if (src->getDomainKeys(di.zone, keys)) {
- for(const DNSBackend::KeyData& k: keys) {
- tgt->addDomainKey(di.zone, k, keyID);
- nk++;
- }
- }
- tgt->commitTransaction();
- cout<<"Moved "<<nr<<" record(s), "<<nc<<" comment(s), "<<nm<<" metadata(s) and "<<nk<<" cryptokey(s)"<<endl;
+ int64_t id{-1};
+ for(DNSBackend::KeyData& kd : keys) {
+ if (kd.content == iscString.str()) {
+ // it's this one, I guess...
+ id = kd.id;
+ break;
}
+ }
- int ntk=0;
- // move tsig keys
- std::vector<struct TSIGKey> tkeys;
- if (src->getTSIGKeys(tkeys)) {
- for(auto& tk: tkeys) {
- if (!tgt->setTSIGKey(tk.name, tk.algorithm, tk.key)) throw PDNSException("Failed to feed TSIG key");
- ntk++;
- }
- }
- cout<<"Moved "<<ntk<<" TSIG key(s)"<<endl;
+ if (id > -1) {
+ cerr << "You have already assigned this key with ID=" << id << std::endl;
+ return 1;
+ }
+
+ DNSSECKeeper dk;
+ if (!dk.addKey(zone, dpk, id)) {
+ cerr << "Unable to assign module slot to zone" << std::endl;
+ return 1;
+ }
- cout<<"Remember to drop the old backend and run rectify-all-zones"<<endl;
+ cerr << "Module " << module << " slot " << slot << " assigned to " << zone << " with key id " << id << endl;
- return 0;
+ return 0;
+}
+
+static int HSMCreateKey(vector<string>& cmds)
+{
+ if (cmds.size() < 4) {
+ cerr << "Usage: pdnsutil hsm create-key ZONE KEY-ID [BITS]" << endl;
+ return 1;
+ }
+ UeberBackend B("default");
+ DomainInfo di;
+ DNSName zone(cmds.at(2));
+ unsigned int id;
+ int bits = 2048;
+ // verify zone
+ if (!B.getDomainInfo(zone, di)) {
+ cerr << "Unable to create key for unknown zone '" << zone << "'" << std::endl;
+ return 1;
}
- else if (cmds.at(0) == "backend-cmd") {
- if (cmds.size() < 3) {
- cerr<<"Usage: backend-cmd BACKEND CMD [CMD..]"<<endl;
- return 1;
- }
- std::unique_ptr<DNSBackend> matchingBackend{nullptr};
+ pdns::checked_stoi_into(id, cmds.at(3));
+ std::vector<DNSBackend::KeyData> keys;
+ if (!B.getDomainKeys(zone, keys)) {
+ cerr << "No keys found for zone " << zone << std::endl;
+ return 1;
+ }
- for (auto& backend : BackendMakers().all()) {
- if (backend->getPrefix() == cmds.at(1)) {
- matchingBackend = std::move(backend);
- }
+ std::unique_ptr<DNSCryptoKeyEngine> dke = nullptr;
+ // lookup correct key
+ for(DNSBackend::KeyData &kd : keys) {
+ if (kd.id == id) {
+ // found our key.
+ DNSKEYRecordContent dkrc;
+ dke = DNSCryptoKeyEngine::makeFromISCString(dkrc, kd.content);
}
+ }
- if (matchingBackend == nullptr) {
- cerr << "Unknown backend '" << cmds.at(1) << "'" << endl;
- return 1;
- }
+ if (!dke) {
+ cerr << "Could not find key with ID " << id << endl;
+ return 1;
+ }
+ if (cmds.size() > 4) {
+ pdns::checked_stoi_into(bits, cmds.at(4));
+ }
+ if (bits < 1) {
+ cerr << "Invalid bit size " << bits << "given, must be positive integer";
+ return 1;
+ }
+ try {
+ dke->create(bits);
+ } catch (PDNSException& e) {
+ cerr << e.reason << endl;
+ return 1;
+ }
- for (auto i = next(begin(cmds), 2); i != end(cmds); ++i) {
- cerr << "== " << *i << endl;
- cout << matchingBackend->directBackendCmd(*i);
- }
+ cerr << "Key of size " << dke->getBits() << " created" << std::endl;
+ return 0;
+}
+#endif // }
+static int HSM([[maybe_unused]] vector<string>& cmds)
+{
+#ifdef HAVE_P11KIT1
+ if (cmds.size() < 2) {
+ cerr << "Missing sub-command for pdnsutil hsm"<< std::endl;
return 0;
}
- else if (cmds.at(0) == "backend-lookup") {
- if (cmds.size() < 3) {
- cerr << "Usage: backend-lookup BACKEND NAME [TYPE [CLIENT-IP-SUBNET]]" << endl;
- return 1;
+ else if (cmds.at(1) == "assign") {
+ return HSMAssign(cmds);
+ }
+ else if (cmds.at(1) == "create-key") {
+ return HSMCreateKey(cmds);
+ }
+ return 1;
+#else
+ cerr<<"PKCS#11 support not enabled"<<endl;
+ return 1;
+#endif
+}
+
+static int B2BMigrate(vector<string>& cmds)
+{
+ if (cmds.size() < 3) {
+ cerr << "Usage: b2b-migrate OLD NEW" << endl;
+ return 1;
+ }
+
+ if (cmds.at(1) == cmds.at(2)) {
+ cerr << "Error: b2b-migrate OLD NEW: OLD cannot be the same as NEW" << endl;
+ return 1;
+ }
+
+ unique_ptr<DNSBackend> src{nullptr};
+ unique_ptr<DNSBackend> tgt{nullptr};
+
+ for (auto& backend : BackendMakers().all()) {
+ if (backend->getPrefix() == cmds.at(1)) {
+ src = std::move(backend);
}
+ else if (backend->getPrefix() == cmds.at(2)) {
+ tgt = std::move(backend);
+ }
+ }
- std::unique_ptr<DNSBackend> matchingBackend{nullptr};
+ if (src == nullptr) {
+ cerr << "Unknown source backend '" << cmds.at(1) << "'" << endl;
+ return 1;
+ }
+ if (tgt == nullptr) {
+ cerr << "Unknown target backend '" << cmds.at(2) << "'" << endl;
+ return 1;
+ }
+
+ cout<<"Moving zone(s) from "<<src->getPrefix()<<" to "<<tgt->getPrefix()<<endl;
+
+ vector<DomainInfo> domains;
+
+ tgt->getAllDomains(&domains, false, true);
+ if (!domains.empty())
+ throw PDNSException("Target backend has zone(s), please clean it first");
- for (auto& backend : BackendMakers().all()) {
- if (backend->getPrefix() == cmds.at(1)) {
- matchingBackend = std::move(backend);
+ src->getAllDomains(&domains, false, true);
+ // iterate zones
+ for(const DomainInfo& di: domains) {
+ size_t nr,nc,nm,nk;
+ DomainInfo di_new;
+ DNSResourceRecord rr;
+ cout<<"Processing '"<<di.zone<<"'"<<endl;
+ // create zone
+ if (!tgt->createDomain(di.zone, di.kind, di.primaries, di.account))
+ throw PDNSException("Failed to create zone");
+ if (!tgt->getDomainInfo(di.zone, di_new)) throw PDNSException("Failed to create zone");
+ // move records
+ if (!src->list(di.zone, di.id, true)) throw PDNSException("Failed to list records");
+ nr=0;
+
+ tgt->startTransaction(di.zone, di_new.id);
+
+ while(src->get(rr)) {
+ rr.domain_id = di_new.id;
+ if (!tgt->feedRecord(rr, DNSName())) throw PDNSException("Failed to feed record");
+ nr++;
+ }
+
+ // move comments
+ nc=0;
+ if (src->listComments(di.id)) {
+ Comment c;
+ while(src->getComment(c)) {
+ c.domain_id = di_new.id;
+ if (!tgt->feedComment(c)) {
+ throw PDNSException("Target backend does not support comments - remove them first");
+ }
+ nc++;
}
}
-
- if (matchingBackend == nullptr) {
- cerr << "Unknown backend '" << cmds.at(1) << "'" << endl;
- return 1;
+ // move metadata
+ nm=0;
+ std::map<std::string, std::vector<std::string> > meta;
+ if (src->getAllDomainMetadata(di.zone, meta)) {
+ for (const auto& i : meta) {
+ if (!tgt->setDomainMetadata(di.zone, i.first, i.second))
+ throw PDNSException("Failed to feed zone metadata");
+ nm++;
+ }
+ }
+ // move keys
+ nk=0;
+ // temp var for KeyID
+ int64_t keyID;
+ std::vector<DNSBackend::KeyData> keys;
+ if (src->getDomainKeys(di.zone, keys)) {
+ for(const DNSBackend::KeyData& k: keys) {
+ tgt->addDomainKey(di.zone, k, keyID);
+ nk++;
+ }
}
+ tgt->commitTransaction();
+ cout<<"Moved "<<nr<<" record(s), "<<nc<<" comment(s), "<<nm<<" metadata(s) and "<<nk<<" cryptokey(s)"<<endl;
+ }
- QType type = QType::ANY;
- if (cmds.size() > 3) {
- type = DNSRecordContent::TypeToNumber(cmds.at(3));
+ int ntk=0;
+ // move tsig keys
+ std::vector<struct TSIGKey> tkeys;
+ if (src->getTSIGKeys(tkeys)) {
+ for(auto& tk: tkeys) {
+ if (!tgt->setTSIGKey(tk.name, tk.algorithm, tk.key)) throw PDNSException("Failed to feed TSIG key");
+ ntk++;
}
+ }
+ cout<<"Moved "<<ntk<<" TSIG key(s)"<<endl;
- DNSName name{cmds.at(2)};
+ cout<<"Remember to drop the old backend and run rectify-all-zones"<<endl;
- DNSPacket queryPacket(true);
- Netmask clientNetmask;
- if (cmds.size() > 4) {
- clientNetmask = cmds.at(4);
- queryPacket.setRealRemote(clientNetmask);
- }
+ return 0;
+}
- matchingBackend->lookup(type, name, -1, &queryPacket);
+static int backendCmd(vector<string>& cmds)
+{
+ if (cmds.size() < 3) {
+ cerr<<"Usage: backend-cmd BACKEND CMD [CMD..]"<<endl;
+ return 1;
+ }
- bool found = false;
- DNSZoneRecord resultZoneRecord;
- while (matchingBackend->get(resultZoneRecord)) {
- cout << resultZoneRecord.dr.d_name.toString() << "\t" << std::to_string(resultZoneRecord.dr.d_ttl) << "\t" << QClass(resultZoneRecord.dr.d_class).toString() << "\t" << DNSRecordContent::NumberToType(resultZoneRecord.dr.d_type, resultZoneRecord.dr.d_class) << "\t" << resultZoneRecord.dr.getContent()->getZoneRepresentation();
- if (resultZoneRecord.scopeMask > 0) {
- clientNetmask.setBits(resultZoneRecord.scopeMask);
- cout << "\t" << "; " << clientNetmask.toString();
- }
- cout << endl;
- found = true;
+ std::unique_ptr<DNSBackend> matchingBackend{nullptr};
+
+ for (auto& backend : BackendMakers().all()) {
+ if (backend->getPrefix() == cmds.at(1)) {
+ matchingBackend = std::move(backend);
}
- if (!found) {
- cerr << "Backend found 0 zone record results";
- if (type != QType::ANY) {
- cerr << "- maybe retry with type ANY?";
- }
- cerr << endl;
- return 1;
+ }
+
+ if (matchingBackend == nullptr) {
+ cerr << "Unknown backend '" << cmds.at(1) << "'" << endl;
+ return 1;
+ }
+
+ for (auto i = next(begin(cmds), 2); i != end(cmds); ++i) {
+ cerr << "== " << *i << endl;
+ cout << matchingBackend->directBackendCmd(*i);
+ }
+
+ return 0;
+}
+
+static int backendLookup(vector<string>& cmds)
+{
+ if (cmds.size() < 3) {
+ cerr << "Usage: backend-lookup BACKEND NAME [TYPE [CLIENT-IP-SUBNET]]" << endl;
+ return 1;
+ }
+
+ std::unique_ptr<DNSBackend> matchingBackend{nullptr};
+
+ for (auto& backend : BackendMakers().all()) {
+ if (backend->getPrefix() == cmds.at(1)) {
+ matchingBackend = std::move(backend);
}
+ }
- return 0;
+ if (matchingBackend == nullptr) {
+ cerr << "Unknown backend '" << cmds.at(1) << "'" << endl;
+ return 1;
+ }
+
+ QType type = QType::ANY;
+ if (cmds.size() > 3) {
+ type = DNSRecordContent::TypeToNumber(cmds.at(3));
+ }
+
+ DNSName name{cmds.at(2)};
+
+ DNSPacket queryPacket(true);
+ Netmask clientNetmask;
+ if (cmds.size() > 4) {
+ clientNetmask = cmds.at(4);
+ queryPacket.setRealRemote(clientNetmask);
+ }
+
+ matchingBackend->lookup(type, name, -1, &queryPacket);
+
+ bool found = false;
+ DNSZoneRecord resultZoneRecord;
+ while (matchingBackend->get(resultZoneRecord)) {
+ cout << resultZoneRecord.dr.d_name.toString() << "\t" << std::to_string(resultZoneRecord.dr.d_ttl) << "\t" << QClass(resultZoneRecord.dr.d_class).toString() << "\t" << DNSRecordContent::NumberToType(resultZoneRecord.dr.d_type, resultZoneRecord.dr.d_class) << "\t" << resultZoneRecord.dr.getContent()->getZoneRepresentation();
+ if (resultZoneRecord.scopeMask > 0) {
+ clientNetmask.setBits(resultZoneRecord.scopeMask);
+ cout << "\t" << "; " << clientNetmask.toString();
+ }
+ cout << endl;
+ found = true;
+ }
+ if (!found) {
+ cerr << "Backend found 0 zone record results";
+ if (type != QType::ANY) {
+ cerr << "- maybe retry with type ANY?";
+ }
+ cerr << endl;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+// NOLINTNEXTLINE(readability-function-cognitive-complexity): TODO Clean this function up.
+int main(int argc, char** argv)
+try
+{
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help,h", "produce help message")
+ ("version", "show version")
+ ("verbose,v", "be verbose")
+ ("force", "force an action")
+ ("config-name", po::value<string>()->default_value(""), "virtual configuration name")
+ ("config-dir", po::value<string>()->default_value(SYSCONFDIR), "location of pdns.conf")
+ ("no-colors", "do not use colors in output")
+ ("commands", po::value<vector<string> >());
+
+ po::positional_options_description p;
+ p.add("commands", -1);
+ po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), g_vm);
+ po::notify(g_vm);
+
+ vector<string> cmds;
+
+ if(g_vm.count("commands"))
+ cmds = g_vm["commands"].as<vector<string> >();
+
+ g_verbose = g_vm.count("verbose");
+
+ if (g_vm.count("version")) {
+ cout<<"pdnsutil "<<VERSION<<endl;
+ return 0;
+ }
+
+ if (cmds.empty() || g_vm.count("help") || cmds.at(0) == "help") {
+ cout << "Usage: \npdnsutil [options] <command> [params ..]\n"
+ << endl;
+ cout << "Commands:" << endl;
+ cout << "activate-tsig-key ZONE NAME {primary|secondary|producer|consumer}" << endl;
+ cout << " Enable TSIG authenticated AXFR using the key NAME for ZONE" << endl;
+ cout << "activate-zone-key ZONE KEY-ID Activate the key with key id KEY-ID in ZONE" << endl;
+ cout << "add-record ZONE NAME TYPE [ttl] content" << endl;
+ cout << " [content..] Add one or more records to ZONE" << endl;
+ cout << "add-autoprimary IP NAMESERVER [account]" << endl;
+ cout << " Add a new autoprimary " << endl;
+ cout << "remove-autoprimary IP NAMESERVER Remove an autoprimary" << endl;
+ cout << "list-autoprimaries List all autoprimaries" << endl;
+ cout << "add-zone-key ZONE {zsk|ksk} [BITS] [active|inactive] [published|unpublished]" << endl;
+ cout << " [rsasha1|rsasha1-nsec3-sha1|rsasha256|rsasha512|ecdsa256|ecdsa384";
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO_ED25519)
+ cout << "|ed25519";
+#endif
+#if defined(HAVE_LIBCRYPTO_ED448)
+ cout << "|ed448";
+#endif
+ cout << "]" << endl;
+ cout << " Add a ZSK or KSK to zone and specify algo&bits" << endl;
+ cout << "backend-cmd BACKEND CMD [CMD..] Perform one or more backend commands" << endl;
+ cout << "backend-lookup BACKEND NAME [[TYPE] CLIENT-IP-SUBNET]" << endl;
+ cout << " Perform a backend lookup of NAME, TYPE and CLIENT-IP-SUBNET" << endl;
+ cout << "b2b-migrate OLD NEW Move all data from one backend to another" << endl;
+ cout << "bench-db [filename] Bench database backend with queries, one zone per line" << endl;
+ cout << "check-zone ZONE Check a zone for correctness" << endl;
+ cout << "check-all-zones [exit-on-error] Check all zones for correctness. Set exit-on-error to exit immediately" << endl;
+ cout << " after finding an error in a zone." << endl;
+ cout << "clear-zone ZONE Clear all records of a zone, but keep everything else" << endl;
+ cout << "create-bind-db FNAME Create DNSSEC db for BIND backend (bind-dnssec-db)" << endl;
+ cout << "create-secondary-zone ZONE primary-ip [primary-ip..]" << endl;
+ cout << " Create secondary zone ZONE with primary IP address primary-ip" << endl;
+ cout << "change-secondary-zone-primary ZONE primary-ip [primary-ip..]" << endl;
+ cout << " Change secondary zone ZONE primary IP address to primary-ip" << endl;
+ cout << "create-zone ZONE [nsname] Create empty zone ZONE" << endl;
+ cout << "deactivate-tsig-key ZONE NAME {primary|secondary}" << endl;
+ cout << " Disable TSIG authenticated AXFR using the key NAME for ZONE" << endl;
+ cout << "deactivate-zone-key ZONE KEY-ID Deactivate the key with key id KEY-ID in ZONE" << endl;
+ cout << "delete-rrset ZONE NAME TYPE Delete named RRSET from zone" << endl;
+ cout << "delete-tsig-key NAME Delete TSIG key (warning! will not unmap key!)" << endl;
+ cout << "delete-zone ZONE Delete the zone" << endl;
+ cout << "disable-dnssec ZONE Deactivate all keys and unset PRESIGNED in ZONE" << endl;
+ cout << "edit-zone ZONE Edit zone contents using $EDITOR" << endl;
+ cout << "export-zone-dnskey ZONE KEY-ID Export to stdout the public DNSKEY described" << endl;
+ cout << "export-zone-ds ZONE Export to stdout all KSK DS records for ZONE" << endl;
+ cout << "export-zone-key ZONE KEY-ID Export to stdout the private key described" << endl;
+ cout << "export-zone-key-pem ZONE KEY-ID Export to stdout in PEM the private key described" << endl;
+ cout << "generate-tsig-key NAME ALGORITHM Generate new TSIG key" << endl;
+ cout << "generate-zone-key {zsk|ksk} [ALGORITHM] [BITS]" << endl;
+ cout << " Generate a ZSK or KSK to stdout with specified ALGORITHM and BITS" << endl;
+ cout << "get-meta ZONE [KIND ...] Get zone metadata. If no KIND given, lists all known" << endl;
+ cout << "hash-password [WORK FACTOR] Ask for a plaintext password or api key and output a hashed and salted version" << endl;
+ cout << "hash-zone-record ZONE RNAME Calculate the NSEC3 hash for RNAME in ZONE" << endl;
+#ifdef HAVE_P11KIT1
+ cout << "hsm assign ZONE ALGORITHM {ksk|zsk} MODULE SLOT PIN LABEL" << endl <<
+ " Assign a hardware signing module to a ZONE" << endl;
+ cout << "hsm create-key ZONE KEY-ID [BITS] Create a key using hardware signing module for ZONE (use assign first)" << endl;
+ cout << " BITS defaults to 2048" << endl;
+#endif
+ cout << "increase-serial ZONE Increases the SOA-serial by 1. Uses SOA-EDIT" << endl;
+ cout << "import-tsig-key NAME ALGORITHM KEY Import TSIG key" << endl;
+ cout << "import-zone-key ZONE FILE Import from a file a private key, ZSK or KSK" << endl;
+ cout << " [active|inactive] [ksk|zsk] [published|unpublished] Defaults to KSK, active and published" << endl;
+ cout << "import-zone-key-pem ZONE FILE Import a private key from a PEM file" << endl;
+ cout << " ALGORITHM {ksk|zsk}" << endl;
+ cout << "ipdecrypt IP passphrase/key [key] Decrypt IP address using passphrase or base64 key" << endl;
+ cout << "ipencrypt IP passphrase/key [key] Encrypt IP address using passphrase or base64 key" << endl;
+ cout << "load-zone ZONE FILE Load ZONE from FILE, possibly creating zone or atomically" << endl;
+ cout << " replacing contents" << endl;
+ cout << "list-algorithms [with-backend] List all DNSSEC algorithms supported, optionally also listing the crypto library used" << endl;
+ cout << "list-keys [ZONE] List DNSSEC keys for ZONE. When ZONE is unset, display all keys for all active zones" << endl;
+ cout << " --verbose or -v will also include the keys for disabled or empty zones" << endl;
+ cout << "list-zone ZONE List zone contents" << endl;
+ cout << "list-all-zones [primary|secondary|native|producer|consumer]" << endl;
+ cout << " List all active zone names. --verbose or -v will also include disabled or empty zones" << endl;
+ cout << "list-member-zones CATALOG List all members of catalog zone CATALOG" << endl;
+
+ cout << "list-tsig-keys List all TSIG keys" << endl;
+ cout << "publish-zone-key ZONE KEY-ID Publish the zone key with key id KEY-ID in ZONE" << endl;
+ cout << "rectify-zone ZONE [ZONE ..] Fix up DNSSEC fields (order, auth)" << endl;
+ cout << "rectify-all-zones [quiet] Rectify all zones. Optionally quiet output with errors only" << endl;
+ cout << "remove-zone-key ZONE KEY-ID Remove key with KEY-ID from ZONE" << endl;
+ cout << "replace-rrset ZONE NAME TYPE [ttl] Replace named RRSET from zone" << endl;
+ cout << " content [content..]" << endl;
+ cout << "secure-all-zones [increase-serial] Secure all zones without keys" << endl;
+ cout << "secure-zone ZONE [ZONE ..] Add DNSSEC to zone ZONE" << endl;
+ cout << "set-kind ZONE KIND Change the kind of ZONE to KIND (primary, secondary, native, producer, consumer)" << endl;
+ cout << "set-options-json ZONE JSON Change the options of ZONE to JSON" << endl;
+ cout << "set-option ZONE Set or remove an option for ZONE Providing an empty value removes an option" << endl;
+ cout << " [producer|consumer]" << endl;
+ cout << " [coo|unique|group] VALUE" << endl;
+ cout << " [VALUE ...]" << endl;
+ cout << "set-catalog ZONE CATALOG Change the catalog of ZONE to CATALOG. Setting CATALOG to an empty "" removes ZONE from the catalog it is in" << endl;
+ cout << "set-account ZONE ACCOUNT Change the account (owner) of ZONE to ACCOUNT" << endl;
+ cout << "set-nsec3 ZONE ['PARAMS' [narrow]] Enable NSEC3 with PARAMS. Optionally narrow" << endl;
+ cout << "set-presigned ZONE Use presigned RRSIGs from storage" << endl;
+ cout << "set-publish-cdnskey ZONE [delete] Enable sending CDNSKEY responses for ZONE. Add 'delete' to publish a CDNSKEY with a" << endl;
+ cout << " DNSSEC delete algorithm" << endl;
+ cout << "set-publish-cds ZONE [DIGESTALGOS] Enable sending CDS responses for ZONE, using DIGESTALGOS as signature algorithms" << endl;
+ cout << " DIGESTALGOS should be a comma separated list of numbers, it is '2' by default" << endl;
+ cout << "add-meta ZONE KIND VALUE Add zone metadata, this adds to the existing KIND" << endl;
+ cout << " [VALUE ...]" << endl;
+ cout << "set-meta ZONE KIND [VALUE] [VALUE] Set zone metadata, optionally providing a value. *No* value clears meta" << endl;
+ cout << " Note - this will replace all metadata records of KIND!" << endl;
+ cout << "show-zone ZONE Show DNSSEC (public) key details about a zone" << endl;
+ cout << "unpublish-zone-key ZONE KEY-ID Unpublish the zone key with key id KEY-ID in ZONE" << endl;
+ cout << "unset-nsec3 ZONE Switch back to NSEC" << endl;
+ cout << "unset-presigned ZONE No longer use presigned RRSIGs" << endl;
+ cout << "unset-publish-cdnskey ZONE Disable sending CDNSKEY responses for ZONE" << endl;
+ cout << "unset-publish-cds ZONE Disable sending CDS responses for ZONE" << endl;
+ cout << "test-schema ZONE Test DB schema - will create ZONE" << endl;
+ cout << "raw-lua-from-content TYPE CONTENT Display record contents in a form suitable for dnsdist's `SpoofRawAction`" << endl;
+ cout << "zonemd-verify-file ZONE FILE Validate ZONEMD for ZONE" << endl;
+ cout << "lmdb-get-backend-version Get schema version supported by backend" << endl;
+ cout << desc << endl;
+
+ return 0;
+ }
+
+ loadMainConfig(g_vm["config-dir"].as<string>());
+
+ if (cmds.at(0) == "lmdb-get-backend-version") {
+ return lmdbGetBackendVersion(cmds);
+ }
+ if (cmds.at(0) == "test-algorithm") {
+ return testAlgorithm(cmds);
+ }
+
+ if (cmds.at(0) == "ipencrypt" || cmds.at(0) == "ipdecrypt") {
+ return ipEncrypt(cmds);
+ }
+
+ if (cmds.at(0) == "test-algorithms") {
+ return testAlgorithms(cmds);
+ }
+
+ if (cmds.at(0) == "list-algorithms") {
+ return listAlgorithms(cmds);
+ }
+
+ reportAllTypes();
+
+ if (cmds.at(0) == "create-bind-db") {
+ return createBindDb(cmds);
+ }
+
+ if (cmds.at(0) == "raw-lua-from-content") {
+ return rawLuaFromContent(cmds);
+ }
+ else if (cmds.at(0) == "hash-password") {
+ return hashPassword(cmds);
+ }
+
+ if(cmds[0] == "zonemd-verify-file") {
+ return zonemdVerifyFile(cmds);
+ }
+
+ if (cmds.at(0) == "test-schema") {
+ return testSchema(cmds);
+ }
+ if (cmds.at(0) == "rectify-zone") {
+ return rectifyZone(cmds);
+ }
+ else if (cmds.at(0) == "rectify-all-zones") {
+ return rectifyAllZones(cmds);
+ }
+ else if (cmds.at(0) == "check-zone") {
+ return checkZone(cmds);
+ }
+ else if (cmds.at(0) == "bench-db") {
+ return benchDb(cmds);
+ }
+ else if (cmds.at(0) == "check-all-zones") {
+ return checkAllZones(cmds);
+ }
+ else if (cmds.at(0) == "list-all-zones") {
+ return listAllZones(cmds);
+ }
+ else if (cmds.at(0) == "list-member-zones") {
+ return listMemberZones(cmds);
+ }
+ else if (cmds.at(0) == "test-zone") {
+ return testZone(cmds);
+ }
+ else if (cmds.at(0) == "test-all-zones") {
+ return testAllZones(cmds);
+ }
+ else if (cmds.at(0) == "test-speed") {
+ return testSpeed(cmds);
+ }
+ else if (cmds.at(0) == "verify-crypto") {
+ return verifyCrypto(cmds);
+ }
+ else if (cmds.at(0) == "show-zone") {
+ return showZone(cmds);
+ }
+ else if (cmds.at(0) == "export-zone-ds") {
+ return exportZoneDS(cmds);
+ }
+ else if (cmds.at(0) == "disable-dnssec") {
+ return disableDNSSEC(cmds);
+ }
+ else if (cmds.at(0) == "activate-zone-key") {
+ return activateZoneKey(cmds);
+ }
+ else if (cmds.at(0) == "deactivate-zone-key") {
+ return deactivateZoneKey(cmds);
+ }
+ else if (cmds.at(0) == "publish-zone-key") {
+ return publishZoneKey(cmds);
+ }
+ else if (cmds.at(0) == "unpublish-zone-key") {
+ return unpublishZoneKey(cmds);
+ }
+
+ else if (cmds.at(0) == "add-zone-key") {
+ return addZoneKey(cmds);
+ }
+ else if (cmds.at(0) == "remove-zone-key") {
+ return removeZoneKey(cmds);
+ }
+ else if (cmds.at(0) == "delete-zone") {
+ return deleteZone(cmds);
+ }
+ else if (cmds.at(0) == "create-zone") {
+ return createZone(cmds);
+ }
+ else if (cmds.at(0) == "create-secondary-zone") {
+ return createSecondaryZone(cmds);
+ }
+ else if (cmds.at(0) == "change-secondary-zone-primary") {
+ return changeSecondaryZonePrimary(cmds);
+ }
+ else if (cmds.at(0) == "add-record") {
+ return addRecord(cmds);
+ }
+ else if (cmds.at(0) == "add-autoprimary") {
+ return addAutoprimary(cmds);
+ }
+ else if (cmds.at(0) == "remove-autoprimary") {
+ return removeAutoprimary(cmds);
+ }
+ else if (cmds.at(0) == "list-autoprimaries") {
+ return listAutoprimaries(cmds);
+ }
+ else if (cmds.at(0) == "replace-rrset") {
+ return replaceRRSet(cmds);
+ }
+ else if (cmds.at(0) == "delete-rrset") {
+ return deleteRRSet(cmds);
+ }
+ else if (cmds.at(0) == "list-zone") {
+ return listZone(cmds);
+ }
+ else if (cmds.at(0) == "edit-zone") {
+ return editZone(cmds);
+ }
+ else if (cmds.at(0) == "clear-zone") {
+ return clearZone(cmds);
+ }
+ else if (cmds.at(0) == "list-keys") {
+ return listKeys(cmds);
+ }
+ else if (cmds.at(0) == "load-zone") {
+ return loadZone(cmds);
+ }
+ else if (cmds.at(0) == "secure-zone") {
+ return secureZone(cmds);
+ }
+ else if (cmds.at(0) == "secure-all-zones") {
+ return secureAllZones(cmds);
+ }
+ else if (cmds.at(0) == "set-kind") {
+ return setKind(cmds);
+ }
+ else if (cmds.at(0) == "set-options-json") {
+ return setOptionsJson(cmds);
+ }
+ else if (cmds.at(0) == "set-option") {
+ return setOption(cmds);
+ }
+ else if (cmds.at(0) == "set-catalog") {
+ return setCatalog(cmds);
+ }
+ else if (cmds.at(0) == "set-account") {
+ return setAccount(cmds);
+ }
+ else if (cmds.at(0) == "set-nsec3") {
+ return setNsec3(cmds);
+ }
+ else if (cmds.at(0) == "set-presigned") {
+ return setPresigned(cmds);
+ }
+ else if (cmds.at(0) == "set-publish-cdnskey") {
+ return setPublishCDNSKey(cmds);
+ }
+ else if (cmds.at(0) == "set-publish-cds") {
+ return setPublishCDs(cmds);
+ }
+ else if (cmds.at(0) == "unset-presigned") {
+ return unsetPresigned(cmds);
+ }
+ else if (cmds.at(0) == "unset-publish-cdnskey") {
+ return unsetPublishCDNSKey(cmds);
+ }
+ else if (cmds.at(0) == "unset-publish-cds") {
+ return unsetPublishCDs(cmds);
+ }
+ else if (cmds.at(0) == "hash-zone-record") {
+ return hashZoneRecord(cmds);
+ }
+ else if (cmds.at(0) == "unset-nsec3") {
+ return unsetNSec3(cmds);
+ }
+ else if (cmds.at(0) == "export-zone-key") {
+ return exportZoneKey(cmds);
+ }
+ else if (cmds.at(0) == "export-zone-key-pem") {
+ return exportZoneKeyPEM(cmds);
+ }
+ else if (cmds.at(0) == "increase-serial") {
+ return increaseSerial(cmds);
+ }
+ else if (cmds.at(0) == "import-zone-key-pem") {
+ return importZoneKeyPEM(cmds);
+ }
+ else if (cmds.at(0) == "import-zone-key") {
+ return importZoneKey(cmds);
+ }
+ else if (cmds.at(0) == "export-zone-dnskey") {
+ return expotZoneDNSKey(cmds);
+ }
+ else if (cmds.at(0) == "generate-zone-key") {
+ return generateZoneKey(cmds);
+ }
+ else if (cmds.at(0) == "generate-tsig-key") {
+ return generateTSIGKey(cmds);
+ }
+ else if (cmds.at(0) == "import-tsig-key") {
+ return importTSIGKey(cmds);
+ }
+ else if (cmds.at(0) == "delete-tsig-key") {
+ return deleteTSIGKey(cmds);
+ }
+ else if (cmds.at(0) == "list-tsig-keys") {
+ return listTSIGKeys(cmds);
+ }
+ else if (cmds.at(0) == "activate-tsig-key") {
+ return activateTSIGKey(cmds);
+ }
+ else if (cmds.at(0) == "deactivate-tsig-key") {
+ return deactivateTSIGKey(cmds);
+ }
+ else if (cmds.at(0) == "get-meta") {
+ return getMeta(cmds);
+ }
+ else if (cmds.at(0) == "set-meta" || cmds.at(0) == "add-meta") {
+ return setMeta(cmds);
+ }
+ else if (cmds.at(0) == "hsm") {
+ return HSM(cmds);
+ }
+ else if (cmds.at(0) == "b2b-migrate") {
+ return B2BMigrate(cmds);
+ }
+ else if (cmds.at(0) == "backend-cmd") {
+ return backendCmd(cmds);
+ }
+ else if (cmds.at(0) == "backend-lookup") {
+ return backendLookup(cmds);
}
else {
cerr << "Unknown command '" << cmds.at(0) << "'" << endl;