mgmt: management tools
refs #2034
Change-Id: I43ff11e0aa7e67f6207e75f139b7417779590efc
diff --git a/AUTHORS.md b/AUTHORS.md
index d1af3b8..02ce1d8 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -5,7 +5,7 @@
* Xiaoke Jiang <http://netarchlab.tsinghua.edu.cn/~shock/>
* Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
-
+* Jiewen Tan <alanwake@ucla.edu>
## All project authors and contributors
diff --git a/src/daemon/db-mgr.cpp b/src/daemon/db-mgr.cpp
index 35af5de..53d3822 100644
--- a/src/daemon/db-mgr.cpp
+++ b/src/daemon/db-mgr.cpp
@@ -174,6 +174,31 @@
return zone.getId() != 0;
}
+std::vector<Zone>
+DbMgr::listZones()
+{
+ sqlite3_stmt* stmt;
+ const char* sql = "SELECT id, name, ttl FROM zones";
+ int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
+ if (rc != SQLITE_OK) {
+ throw PrepareError(sql);
+ }
+
+ std::vector<Zone> vec;
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ vec.emplace_back();
+ Zone& zone = vec.back();
+ zone.setId(sqlite3_column_int64(stmt, 0));
+ zone.setTtl(time::seconds(sqlite3_column_int(stmt, 2)));
+ zone.setName(Name(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 1)),
+ sqlite3_column_bytes(stmt, 1))));
+ }
+ sqlite3_finalize(stmt);
+
+ return vec;
+}
+
void
DbMgr::remove(Zone& zone)
{
diff --git a/src/daemon/db-mgr.hpp b/src/daemon/db-mgr.hpp
index ca83691..336b330 100644
--- a/src/daemon/db-mgr.hpp
+++ b/src/daemon/db-mgr.hpp
@@ -113,6 +113,12 @@
find(Zone& zone);
/**
+ * @brief get all zones in the database
+ */
+ std::vector<Zone>
+ listZones();
+
+ /**
* @brief remove the zone
* @pre m_zone.getId() > 0
* @post m_zone.getId() == 0
diff --git a/src/mgmt/management-tool.cpp b/src/mgmt/management-tool.cpp
new file mode 100644
index 0000000..619d1c0
--- /dev/null
+++ b/src/mgmt/management-tool.cpp
@@ -0,0 +1,642 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "management-tool.hpp"
+#include "logger.hpp"
+#include "ndns-label.hpp"
+#include "ndns-tlv.hpp"
+
+#include <string>
+#include <iomanip>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/util/regex.hpp>
+#include <ndn-cxx/encoding/oid.hpp>
+#include <ndn-cxx/security/cryptopp.hpp>
+
+namespace ndn {
+namespace ndns {
+
+NDNS_LOG_INIT("ManagementTool");
+
+ManagementTool::ManagementTool(const std::string& dbFile)
+ : m_dbMgr(dbFile)
+{
+}
+
+void
+ManagementTool::createZone(const Name &zoneName,
+ const Name& parentZoneName,
+ const time::seconds& cacheTtl,
+ const time::seconds& certTtl,
+ const Name& kskCertName,
+ const Name& dskCertName)
+{
+ bool isRoot = zoneName == ROOT_ZONE;
+
+ //check preconditions
+ Zone zone(zoneName, cacheTtl);
+ if (m_dbMgr.find(zone)) {
+ throw Error(zoneName.toUri() + " is already presented in the NDNS db");
+ }
+
+ if (!isRoot && parentZoneName.equals(zoneName)) {
+ throw Error("Parent zone name can not be the zone itself");
+ }
+
+ if (!isRoot && !parentZoneName.isPrefixOf(zoneName)) {
+ throw Error(parentZoneName.toUri() + " is not a prefix of " + zoneName.toUri());
+ }
+
+ if (kskCertName != DEFAULT_CERT) {
+ if (!matchCertificate(kskCertName, zoneName)) {
+ throw Error("Cannot verify KSK certificate");
+ }
+ }
+
+ if (dskCertName != DEFAULT_CERT) {
+ if (!matchCertificate(dskCertName, zoneName)) {
+ throw Error("Cannot verify DSK certificate");
+ }
+ }
+
+ if (kskCertName == DEFAULT_CERT && isRoot) {
+ throw Error("Cannot generate KSK for root zone");
+ }
+
+ //first generate KSK and DSK to the keyChain system, and add DSK as default
+ NDNS_LOG_INFO("Start generating KSK and DSK and their corresponding certificates");
+ time::system_clock::TimePoint notBefore = time::system_clock::now();
+ time::system_clock::TimePoint notAfter = notBefore + certTtl;
+ shared_ptr<IdentityCertificate> kskCert;
+
+ if (kskCertName == DEFAULT_CERT) {
+ //create KSK's certificate
+ Name kskName = m_keyChain.generateRsaKeyPair(zoneName, true);
+ std::vector<CertificateSubjectDescription> kskDesc;
+ kskCert = m_keyChain.prepareUnsignedIdentityCertificate(kskName, zoneName, notBefore, notAfter,
+ kskDesc);
+ //prepare the correct name for the ksk certificate
+ Name newScertName = parentZoneName;
+ newScertName.append(label::NDNS_CERT_QUERY);
+ newScertName.append(zoneName.getSubName(parentZoneName.size()));
+ //remove the zone prefix and KEY
+ newScertName.append(kskCert->getName().getSubName(zoneName.size()+1));
+ kskCert->setName(newScertName);
+
+ m_keyChain.selfSign(*kskCert);
+ m_keyChain.addCertificate(*kskCert);
+ NDNS_LOG_INFO("Generated KSK: " << kskCert->getName().toUri());
+ }
+ else {
+ kskCert = m_keyChain.getCertificate(kskCertName);
+ }
+
+ Name dskName;
+ shared_ptr<IdentityCertificate> dskCert;
+ if (dskCertName == DEFAULT_CERT) {
+ dskName = m_keyChain.generateRsaKeyPairAsDefault(zoneName, false);
+ //create DSK's certificate
+ std::vector<CertificateSubjectDescription> dskDesc;
+ dskCert = m_keyChain.prepareUnsignedIdentityCertificate(dskName, zoneName, notBefore, notAfter,
+ dskDesc);
+ m_keyChain.sign(*dskCert, kskCert->getName());
+ m_keyChain.addCertificateAsKeyDefault(*dskCert);
+ NDNS_LOG_INFO("Generated DSK: " << dskCert->getName().toUri());
+ }
+ else {
+ dskCert = m_keyChain.getCertificate(dskCertName);
+ dskName = dskCert->getPublicKeyName();
+ m_keyChain.setDefaultKeyNameForIdentity(dskName);
+ m_keyChain.setDefaultCertificateNameForKey(dskCert->getName());
+ }
+
+ //second add zone to the database
+ NDNS_LOG_INFO("Start adding new zone to data base");
+ addZone(zone);
+
+ //third create ID-cert
+ NDNS_LOG_INFO("Start creating DSK's ID-CERT");
+ addIdCert(zone, dskCert, cacheTtl);
+}
+
+void
+ManagementTool::deleteZone(const Name& zoneName)
+{
+ //check pre-conditions
+ Zone zone(zoneName);
+ if (!m_dbMgr.find(zone)) {
+ throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+ }
+
+ //first remove all rrsets of this zone from local ndns database
+ std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
+ for (Rrset& rrset : rrsets) {
+ m_dbMgr.remove(rrset);
+ }
+
+ //second remove zone from local ndns database
+ removeZone(zone);
+
+ //third remove identity
+ m_keyChain.deleteIdentity(zoneName);
+}
+
+void
+ManagementTool::exportCertificate(const Name& certName, const std::string& outFile)
+{
+ //search for the certificate, start from KeyChain then local NDNS database
+ shared_ptr<IdentityCertificate> cert;
+ if (m_keyChain.doesCertificateExist(certName)) {
+ cert = m_keyChain.getCertificate(certName);
+ }
+ else {
+ shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
+ if (regex->match(certName) != true) {
+ throw Error("Certificate name is illegal");
+ }
+ Name zoneName = regex->expand("\\1");
+ Name label = regex->expand("\\2");
+
+ Zone zone(zoneName);
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(label::CERT_RR_TYPE);
+ if (m_dbMgr.find(rrset)) {
+ Data data(rrset.getData());
+ cert = make_shared<IdentityCertificate>(data);
+ }
+ else {
+ throw Error("Cannot find the cert: " + certName.toUri());
+ }
+ }
+
+ if (outFile == DEFAULT_IO) {
+ ndn::io::save(*cert, std::cout);
+ }
+ else {
+ ndn::io::save(*cert, outFile);
+ NDNS_LOG_INFO("save cert to file: " << outFile);
+ }
+}
+
+void
+ManagementTool::addRrSet(const Name& zoneName,
+ const Name& label,
+ const name::Component& type,
+ NdnsType ndnsType,
+ const uint64_t version,
+ const std::vector<std::string>& contents,
+ const Name& inputDskCertName,
+ const time::seconds& ttl)
+{
+ // check pre-condition
+ Zone zone(zoneName);
+ if (!m_dbMgr.find(zone)) {
+ throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+ }
+
+ if (ndnsType == NDNS_UNKNOWN) {
+ throw Error("The ndns type is unknown");
+ }
+
+ if (type == label::CERT_RR_TYPE) {
+ throw Error("It cannot handle ID-CERT rrset type");
+ }
+
+ // check strange rr type and ndns type combination
+ if (type == label::NS_RR_TYPE && ndnsType == NDNS_RAW) {
+ throw Error("NS cannot be of the type NDNS_RAW");
+ }
+
+ if (type == label::TXT_RR_TYPE && ndnsType != NDNS_RESP) {
+ throw Error("TXT cannot be of the type NDNS_RAW or NDNS_AUTH");
+ }
+
+ if (ndnsType == NDNS_RAW && contents.size() != 1) {
+ throw Error("NDNS_RAW must contain a single content element");
+ }
+
+ Name dskName;
+ Name dskCertName = inputDskCertName;
+ if (dskCertName == DEFAULT_CERT) {
+ dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
+ dskCertName = m_keyChain.getDefaultCertificateNameForKey(dskName);
+ }
+ else {
+ if (!matchCertificate(dskCertName, zoneName)) {
+ throw Error("Cannot verify certificate");
+ }
+ }
+
+ // set rrset
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(type);
+ if (ttl == DEFAULT_RR_TTL)
+ rrset.setTtl(zone.getTtl());
+ else
+ rrset.setTtl(ttl);
+
+ // set response
+ Response re;
+ re.setZone(zoneName);
+ re.setQueryType(label::NDNS_ITERATIVE_QUERY);
+ re.setRrLabel(label);
+ re.setRrType(type);
+ re.setNdnsType(ndnsType);
+
+ //set content according to ndns type
+ if (ndnsType == NDNS_RAW) {
+ Block tmp = ndn::dataBlock(ndn::tlv::Content, contents[0].c_str(), contents[0].length());
+ re.setAppContent(tmp);
+ }
+ else if (ndnsType != NDNS_AUTH) {
+ if (contents.empty()) {
+ re.addRr("");
+ }
+ else {
+ for (const auto& item : contents) {
+ re.addRr(item);
+ }
+ }
+ }
+
+ shared_ptr<Data> data = re.toData();
+ if (version != VERSION_USE_UNIX_TIMESTAMP) {
+ name::Component tmp = name::Component::fromVersion(version);
+ re.setVersion(tmp);
+ }
+ m_keyChain.sign(*data, dskCertName);
+
+ rrset.setVersion(re.getVersion());
+ rrset.setData(data->wireEncode());
+
+ if (m_dbMgr.find(rrset)) {
+ throw Error("Rrset with label=" + label.toUri() + " is already in local NDNS databse");
+ }
+ NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
+ << type);
+ m_dbMgr.insert(rrset);
+}
+
+void
+ManagementTool::addRrSet(const Name& zoneName,
+ const std::string& inFile,
+ const time::seconds& ttl,
+ const Name& inputDskCertName)
+{
+ //check precondition
+ Zone zone(zoneName);
+ if (!m_dbMgr.find(zone)) {
+ throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+ }
+
+ Name dskName;
+ Name dskCertName = inputDskCertName;
+ if (dskCertName == DEFAULT_CERT) {
+ dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
+ dskCertName = m_keyChain.getDefaultCertificateNameForKey(dskName);
+ }
+ else {
+ if (!matchCertificate(dskCertName, zoneName)) {
+ throw Error("Cannot verify certificate");
+ }
+ }
+
+ if (inFile != DEFAULT_IO) {
+ boost::filesystem::path dir = boost::filesystem::path(inFile);
+ if (!boost::filesystem::exists(dir) || boost::filesystem::is_directory(dir)) {
+ throw Error("Data: " + inFile + " does not exist");
+ }
+ }
+
+ //first load the data
+ shared_ptr<Data> data;
+ if (inFile == DEFAULT_IO)
+ data = ndn::io::load<ndn::Data>(std::cin);
+ else
+ data = ndn::io::load<ndn::Data>(inFile);
+
+ //determine whether the data is a self-signed certificate
+ shared_ptr<Regex> regex1 = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
+ if (regex1->match(data->getName())) {
+ IdentityCertificate scert(*data);
+ Name keyName = scert.getPublicKeyName();
+ Name keyLocator = scert.getSignature().getKeyLocator().getName();
+
+ //if it is, extract the content and name from the data, and resign it using the dsk.
+ shared_ptr<Regex> regex2 = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT>");
+ BOOST_VERIFY(regex2->match(keyLocator) == true);
+ if (keyName == regex2->expand("\\1\\2")) {
+ shared_ptr<Data> pre = data;
+ Name name = pre->getName();
+ //check whether the name is legal or not. if not converting it to a legal name
+ if (zoneName != regex1->expand("\\1")) {
+ Name comp1 = regex1->expand("\\1").getSubName(zoneName.size());
+ Name comp2 = regex1->expand("\\2");
+ name = zoneName;
+ name.append("KEY");
+ name.append(comp1);
+ name.append(comp2);
+ name.append("ID-CERT");
+ name.append(pre->getName().get(-1));
+ }
+
+ data = make_shared<Data>();
+ data->setName(name);
+ data->setContent(pre->getContent());
+
+ m_keyChain.sign(*data, dskCertName);
+ }
+ }
+
+ // create response for the input data
+ Response re;
+ Name hint;
+ re.fromData(hint, zoneName, *data);
+ Name label = re.getRrLabel();
+ name::Component type = re.getRrType();
+
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(type);
+ if (ttl == DEFAULT_RR_TTL)
+ rrset.setTtl(zone.getTtl());
+ else
+ rrset.setTtl(ttl);
+ rrset.setVersion(re.getVersion());
+ rrset.setData(data->wireEncode());
+
+ if (m_dbMgr.find(rrset)) {
+ throw Error("Rrset with label=" + label.toUri() + " is already in local NDNS databse");
+ }
+ NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
+ << type);
+ m_dbMgr.insert(rrset);
+}
+
+void
+ManagementTool::listZone(const Name& zoneName, std::ostream& os, const bool printRaw) {
+ Zone zone(zoneName);
+ if (!m_dbMgr.find(zone)) {
+ os << "No record is found" << std::endl;
+ return;
+ }
+
+ //first output the zone name
+ os << "; Zone " << zoneName.toUri() << std::endl << std::endl;
+
+ //second output all rrsets
+ std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
+
+ //set width for different columns
+ size_t labelWidth = 0;
+ size_t ttlWidth = 0;
+ size_t typeWidth = 0;
+ for (Rrset& rrset : rrsets) {
+ Data data(rrset.getData());
+ Response re;
+ Name hint;
+ re.fromData(hint, zoneName, data);
+
+ if (rrset.getLabel().toUri().size() > labelWidth)
+ labelWidth = rrset.getLabel().toUri().size();
+
+ std::stringstream seconds;
+ seconds << rrset.getTtl().count();
+ if (seconds.str().size() > ttlWidth)
+ ttlWidth = seconds.str().size();
+
+ if (rrset.getType().toUri().size() > typeWidth)
+ typeWidth = rrset.getType().toUri().size();
+ }
+
+ //output
+ for (Rrset& rrset : rrsets) {
+ Data data(rrset.getData());
+ Response re;
+ Name hint;
+ re.fromData(hint, zoneName, data);
+ int iteration = re.getNdnsType() == NDNS_RAW || re.getNdnsType() == NDNS_AUTH ?
+ 1 : re.getRrs().size();
+ const std::vector<Block> &rrs = re.getRrs();
+
+ if (re.getNdnsType() != NDNS_RAW && re.getNdnsType() != NDNS_AUTH) {
+ os << "; rrset=" << rrset.getLabel().toUri()
+ << " type=" << rrset.getType().toUri()
+ << " version=" << rrset.getVersion().toUri()
+ << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri()
+ << std::endl;
+ }
+
+ for (int i = 0; i < iteration; i++) {
+ os.setf(os.left);
+ os.width(labelWidth + 2);
+ os << rrset.getLabel().toUri();
+
+ os.width(ttlWidth + 2);
+ os << rrset.getTtl().count();
+
+ os.width(typeWidth + 2);
+ os << rrset.getType().toUri();
+
+ if (re.getNdnsType() != NDNS_RAW && re.getNdnsType() != NDNS_AUTH) {
+ using namespace CryptoPP;
+ if (rrset.getType() == label::TXT_RR_TYPE) {
+ os.write(reinterpret_cast<const char*>(rrs[i].value()), rrs[i].value_size());
+ os << std::endl;
+ }
+ else if (rrset.getType() == label::NS_RR_TYPE) {
+ //TODO output the NS data once we have it
+ os << std::endl;
+ }
+ else {
+ StringSource ss(rrs[i].wire(), rrs[i].size(), true,
+ new Base64Encoder(new FileSink(os), true, 64));
+ }
+ }
+ }
+
+ if (re.getNdnsType() == NDNS_RAW || re.getNdnsType() == NDNS_AUTH) {
+ os.width();
+ os << "; content-type=" << re.getNdnsType()
+ << " version=" << rrset.getVersion().toUri()
+ << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri();
+ os << std::endl;
+
+ if (printRaw && re.getNdnsType() == NDNS_RAW) {
+ using namespace CryptoPP;
+ std::stringstream sstream;
+ StringSource ss(re.getAppContent().wire(), re.getAppContent().size(), true,
+ new Base64Encoder(new FileSink(sstream), true, 64));
+
+ std::string content = sstream.str();
+ std::string delimiter = "\n";
+ size_t pos = 0;
+ std::string token;
+ while ((pos = content.find(delimiter)) != std::string::npos) {
+ token = content.substr(0, pos);
+ os << "; " << token << std::endl;
+ content.erase(0, pos + delimiter.length());
+ }
+
+ os << std::endl;
+ }
+ }
+ else {
+ os << std::endl;
+ }
+ }
+}
+
+void
+ManagementTool::listAllZones(std::ostream& os) {
+ std::vector<Zone> zones = m_dbMgr.listZones();
+
+ size_t nameWidth = 0;
+ for (const Zone& zone : zones) {
+ if (zone.getName().toUri().size() > nameWidth)
+ nameWidth = zone.getName().toUri().size();
+ }
+
+ for (const Zone& zone : zones) {
+ os.setf(os.left);
+ os.width(nameWidth + 2);
+ os << zone.getName().toUri();
+
+ os << "; default-ttl=" << zone.getTtl().count();
+ os << " default-key=" << m_keyChain.getDefaultKeyNameForIdentity(zone.getName());
+ os << " default-certificate="
+ << m_keyChain.getDefaultCertificateNameForIdentity(zone.getName());
+ os << std::endl;
+ }
+}
+
+void
+ManagementTool::removeRrSet(const Name& zoneName, const Name& label, const name::Component& type)
+{
+ Zone zone(zoneName);
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(type);
+
+ if (!m_dbMgr.find(rrset)) {
+ return;
+ }
+ NDNS_LOG_INFO("Remove rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
+ << type);
+ m_dbMgr.remove(rrset);
+}
+
+void
+ManagementTool::getRrSet(const Name& zoneName,
+ const Name& label,
+ const name::Component& type,
+ std::ostream& os)
+{
+ Zone zone(zoneName);
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(type);
+
+ if (!m_dbMgr.find(rrset)) {
+ os << "No record is found" << std::endl;
+ return;
+ }
+
+ using namespace CryptoPP;
+ StringSource ss(rrset.getData().wire(), rrset.getData().size(), true,
+ new Base64Encoder(new FileSink(os), true, 64));
+}
+
+void
+ManagementTool::addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert,
+ const time::seconds& ttl)
+{
+ Rrset rrset(&zone);
+ size_t size = zone.getName().size();
+ Name label = cert->getName().getSubName(size + 1, cert->getName().size() - size - 3);
+ rrset.setLabel(label);
+ rrset.setType(label::CERT_RR_TYPE);
+ rrset.setTtl(ttl);
+ rrset.setVersion(cert->getName().get(-1));
+ rrset.setData(cert->wireEncode());
+
+ if (m_dbMgr.find(rrset)) {
+ throw Error("ID-CERT with label=" + label.toUri() +
+ " is already presented in local NDNS databse");
+ }
+ NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
+ << label::CERT_RR_TYPE);
+ m_dbMgr.insert(rrset);
+}
+
+void
+ManagementTool::addZone(Zone& zone)
+{
+ if (m_dbMgr.find(zone)) {
+ throw Error("Zone with Name=" + zone.getName().toUri() +
+ " is already presented in local NDNS databse");
+ }
+ NDNS_LOG_INFO("Add zone with Name: " << zone.getName().toUri());
+ m_dbMgr.insert(zone);
+}
+
+void
+ManagementTool::removeZone(Zone& zone)
+{
+ if (!m_dbMgr.find(zone)) {
+ return;
+ }
+ NDNS_LOG_INFO("Remove zone with Name: " << zone.getName().toUri());
+ m_dbMgr.remove(zone);
+}
+
+bool
+ManagementTool::matchCertificate(const Name& certName, const Name& identity)
+{
+ if (!m_keyChain.doesCertificateExist(certName)) {
+ NDNS_LOG_WARN(certName.toUri() << " is not presented in KeyChain");
+ return false;
+ }
+
+ //check its public key information
+ shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(certName);
+ Name keyName = cert->getPublicKeyName();
+
+ if (!identity.isPrefixOf(keyName) || identity.size()!=keyName.size()-1) {
+ NDNS_LOG_WARN(keyName.toUri() << " is not a key of " << identity.toUri());
+ return false;
+ }
+
+ if (!m_keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE)) {
+ NDNS_LOG_WARN("Private key: " << keyName.toUri() << " is not presented in KeyChain");
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace ndns
+} // namespace ndn
diff --git a/src/mgmt/management-tool.hpp b/src/mgmt/management-tool.hpp
new file mode 100644
index 0000000..f962b11
--- /dev/null
+++ b/src/mgmt/management-tool.hpp
@@ -0,0 +1,233 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NDNS_MGMT_MANAGEMENT_TOOL_HPP
+#define NDNS_MGMT_MANAGEMENT_TOOL_HPP
+
+#include "config.hpp"
+#include "ndns-enum.hpp"
+#include "./daemon/zone.hpp"
+#include "./daemon/db-mgr.hpp"
+#include "./daemon/rrset.hpp"
+#include "./clients/response.hpp"
+
+#include <stdexcept>
+#include <ndn-cxx/common.hpp>
+#include <ndn-cxx/security/identity-certificate.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+
+namespace ndn {
+namespace ndns {
+
+static const Name DEFAULT_CERT;
+static const Name ROOT_ZONE;
+static const time::seconds DEFAULT_CACHE_TTL = time::seconds(3600);
+static const time::seconds DEFAULT_CERT_TTL = time::days(365);
+static const std::vector<std::string> DEFAULT_CONTENTS;
+static const std::string DEFAULT_IO = "-";
+static const time::seconds DEFAULT_RR_TTL = time::seconds(0);
+static constexpr uint64_t VERSION_USE_UNIX_TIMESTAMP = std::numeric_limits<uint64_t>::max();
+
+/**
+ * @brief provides management tools to the NDNS system, such as zone creation, zone delegation, DSK
+ * generation and root zone creation.
+ */
+class ManagementTool : noncopyable
+{
+public:
+ /** @brief Represents an error might be thrown during runtime
+ */
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what) : std::runtime_error(what)
+ {
+ }
+ };
+
+ /** @param certDir Path to the directory to store certificates
+ * @param dbFile Path to the local database
+ */
+ explicit
+ ManagementTool(const std::string& dbFile);
+
+ /** @brief Create a Zone according to a given name.
+ *
+ * Specifically, It will generate a KSK and a DSK (and their certificates) to the following
+ * places:
+ * 1) Local NDNS database: a new zone is added.
+ * 2) Local NDNS database: an ID-CERT of the DSK is added.
+ * 3) KeyChain: an identity named with zone name is added.
+ * 4) KeyChain: a KSK and its self-signed certificate is added. The ownership of the KSK is the
+ * parent zone.
+ * 5) KeyChain: a DSK and its KSK signed certificate is added.
+ *
+ * -SS.cert (self-signed)
+ * -SKS.cert (self's Key signed)
+ * -PKS.cert (parent's Key Signed)
+ *
+ * @attention
+ * 1) to create root zone, supply zoneName and parentZoneName both with ROOT_ZONE
+ *
+ * @param zoneName zone's name
+ * @param parentZoneName parent zone's name
+ * @param ttl ttl for the created zone
+ * @param kskCertName if given, a zone will be created with this ksk certificate and its key
+ * @param kskCertName if given, a zone will be created with this dsk certificate and its key
+ */
+ void
+ createZone(const Name& zoneName,
+ const Name& parentZoneName,
+ const time::seconds& cacheTtl = DEFAULT_CACHE_TTL,
+ const time::seconds& certTtl = DEFAULT_CERT_TTL,
+ const Name& kskCertName = DEFAULT_CERT,
+ const Name& dskCertName = DEFAULT_CERT);
+
+ /** @brief Delete a Zone according to a given name.
+ *
+ * Specifically, It will do the following things:
+ * 1) KeyChain System: delete the Identity with zone name and all its keys/certificates
+ * 2) Local NDNS database: delete the zone record
+ * 3) Local NDNS database: delete the ID-CERT of the zone's DSK
+ */
+ void
+ deleteZone(const Name& zoneName);
+
+ /** @brief Export the certificate to file system
+ *
+ * @param certName the name of the certificate to be exported
+ * @param output the path to output to-be exported file, including the file name
+ */
+ void
+ exportCertificate(const Name& certName, const std::string& outFile = DEFAULT_IO);
+
+ /** @brief add rrset to the NDNS local database
+ *
+ * This one is only capable of adding NS type including NDNS_RESP and NDNS_AUTH and user defined
+ * type with string content.
+ * Other complicated situations can be handled by the other addRrSet() overload function.
+ *
+ * @param zoneName the name of the zone to hold the rrset
+ * @param label the rrset label
+ * @param type the rrset type
+ * @param ndnsType the ndnsType of the response, for user-defined type, just set it NDNS_RAW
+ * @param version the version of the response and rrset, default is Unix Timestamp
+ * @param content the content of the response
+ * @param dskName the DSK to signed the response, default is the zone's DSK
+ * @param ttl the ttl of the rrset
+ */
+ void
+ addRrSet(const Name& zoneName,
+ const Name& label,
+ const name::Component& type,
+ NdnsType ndnsType,
+ const uint64_t version = VERSION_USE_UNIX_TIMESTAMP,
+ const std::vector<std::string>& contents = DEFAULT_CONTENTS,
+ const Name& dskCertName = DEFAULT_CERT,
+ const time::seconds& ttl = DEFAULT_RR_TTL);
+
+ /** @brief add rrset to the NDNS local database
+ *
+ * This overload is capable of adding any data to the rrset as long as the supplied data is
+ * valid.
+ * A special case is to add the ID-CERT of KSK to the parent zone. At this case, the SS cert
+ * should be supplied, and therefore it will use the parent zone's DSK to resign the certificate.
+ * For other cases, the data will be added directly without any modification.
+ *
+ * @param zoneName the name of the zone to hold the rrset
+ * @param dataPath the path to the supplied data
+ * @param ttl the ttl of the rrset
+ * @param dskName the DSK to signed the special case, default is the zone's DSK
+ */
+ void
+ addRrSet(const Name& zoneName,
+ const std::string& inFile = DEFAULT_IO,
+ const time::seconds& ttl = DEFAULT_RR_TTL,
+ const Name& dskCertName = DEFAULT_CERT);
+
+ /** @brief remove rrset from the NDNS local database
+ *
+ * @param zonName the name of the zone holding the rrset
+ * @param label rrset's label
+ * @param type rrset's type
+ */
+ void
+ removeRrSet(const Name& zoneName, const Name& label, const name::Component& type);
+
+ /** @brief output the raw data of the selected rrset
+ *
+ * @param zonName the name of the zone holding the rrset
+ * @param label rrset's label
+ * @param type rrset's type
+ * @param os the ostream to print information to
+ * @param isPP indicate pretty print
+ */
+ void
+ getRrSet(const Name& zoneName,
+ const Name& label,
+ const name::Component& type,
+ std::ostream& os);
+
+ /** @brief generates an output like DNS zone file. Reference:
+ * http://en.wikipedia.org/wiki/Zone_file
+ *
+ * @param zoneName the name of the zone to investigate
+ * @param os the ostream to print information to
+ * @param printRaw set to print content of ndns-raw rrset
+ */
+ void
+ listZone(const Name& zoneName, std::ostream& os, const bool printRaw = false);
+
+ /** @brief lists all existing zones within this name server.
+ *
+ * @param os the ostream to print information to
+ */
+ void
+ listAllZones(std::ostream& os);
+
+private:
+ /** @brief add ID-CERT to the NDNS local database
+ */
+ void
+ addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert, const time::seconds& ttl);
+
+ /** @brief add zone to the NDNS local database
+ */
+ void
+ addZone(Zone& zone);
+
+ /** @brief remove zone from the NDNS local database
+ */
+ void
+ removeZone(Zone& zone);
+
+ /** @brief determine whether a certificate matches with both the identity and key type
+ */
+ bool
+ matchCertificate(const Name& certName, const Name& identity);
+
+private:
+ KeyChain m_keyChain;
+ DbMgr m_dbMgr;
+};
+
+} // namespace ndns
+} // namespace ndn
+#endif // NDNS_MGMT_MANAGEMENT_TOOL_HPP
diff --git a/tests/unit/daemon/db-mgr.cpp b/tests/unit/daemon/db-mgr.cpp
index fb621d2..be728d6 100644
--- a/tests/unit/daemon/db-mgr.cpp
+++ b/tests/unit/daemon/db-mgr.cpp
@@ -179,6 +179,33 @@
BOOST_CHECK_NO_THROW(session.remove(rrset1));
}
+BOOST_FIXTURE_TEST_CASE(FindAllZones, DbMgrFixture)
+{
+ Zone zone("/ndn");
+ zone.setTtl(time::seconds(1600));
+ session.insert(zone);
+
+ Zone zone2("/ndn/ucla");
+ zone2.setTtl(time::seconds(2600));
+ session.insert(zone2);
+
+ std::vector<Zone> vec = session.listZones();
+ BOOST_CHECK_EQUAL(vec.size(), 2);
+
+ std::sort(vec.begin(),
+ vec.end(),
+ [] (const Zone& n1, const Zone& n2) {
+ return n1.getName().size() < n2.getName().size();
+ });
+ BOOST_CHECK_EQUAL(vec[0].getId(), zone.getId());
+ BOOST_CHECK_EQUAL(vec[0].getName(), "/ndn");
+ BOOST_CHECK_EQUAL(vec[0].getTtl(), time::seconds(1600));
+
+ BOOST_CHECK_EQUAL(vec[1].getId(), zone2.getId());
+ BOOST_CHECK_EQUAL(vec[1].getName(), "/ndn/ucla");
+ BOOST_CHECK_EQUAL(vec[1].getTtl(), time::seconds(2600));
+
+}
BOOST_FIXTURE_TEST_CASE(FindRrsets, DbMgrFixture)
{
diff --git a/tests/unit/daemon/name-server.cpp b/tests/unit/daemon/name-server.cpp
index f721a5e..09d192f 100644
--- a/tests/unit/daemon/name-server.cpp
+++ b/tests/unit/daemon/name-server.cpp
@@ -167,7 +167,6 @@
Response resp;
BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
- std::cout << resp << std::endl;
BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
BOOST_CHECK_GT(resp.getRrs().size(), 0);
Block block = resp.getRrs()[0];
@@ -220,7 +219,6 @@
Response resp;
BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
- std::cout << resp << std::endl;
BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
BOOST_CHECK_GT(resp.getRrs().size(), 0);
Block block = resp.getRrs()[0];
@@ -401,7 +399,6 @@
Response resp;
BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
- std::cout << resp << std::endl;
BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
BOOST_CHECK_GT(resp.getRrs().size(), 0);
Block block = resp.getRrs()[0];
diff --git a/tests/unit/mgmt/management-tool.cpp b/tests/unit/mgmt/management-tool.cpp
new file mode 100644
index 0000000..2eefe15
--- /dev/null
+++ b/tests/unit/mgmt/management-tool.cpp
@@ -0,0 +1,982 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "../../src/mgmt/management-tool.hpp"
+
+#include "../../boost-test.hpp"
+#include <boost/test/output_test_stream.hpp>
+using boost::test_tools::output_test_stream;
+
+#include "ndns-enum.hpp"
+#include "ndns-label.hpp"
+#include "ndns-tlv.hpp"
+
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/security/validator.hpp>
+#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/util/regex.hpp>
+
+namespace ndn {
+namespace ndns {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(ManagementTool)
+
+static const boost::filesystem::path TEST_DATABASE = TEST_CONFIG_PATH "/management_tool.db";
+static const boost::filesystem::path TEST_CERTDIR = TEST_CONFIG_PATH "/management_tool_certs";
+static const Name FAKE_ROOT("/fake-root/123456789");
+
+class ManagementToolFixture
+{
+public:
+ ManagementToolFixture()
+ : m_tool(TEST_DATABASE.string().c_str())
+ , m_keyChain("sqlite3", "file")
+ , m_dbMgr(TEST_DATABASE.string().c_str())
+ {
+ boost::filesystem::create_directory(TEST_CERTDIR);
+ }
+
+ ~ManagementToolFixture()
+ {
+ boost::filesystem::remove_all(TEST_CERTDIR);
+ boost::filesystem::remove(TEST_DATABASE);
+ }
+
+ void
+ getKeyList(const Name& identity, std::vector<Name>& keyList)
+ {
+ m_keyChain.getAllKeyNamesOfIdentity(identity, keyList, false);
+ m_keyChain.getAllKeyNamesOfIdentity(identity, keyList, true);
+ }
+
+ void
+ getCertList(const Name& identity, std::vector<Name>& certNameList)
+ {
+ std::vector<Name> keyList;
+ getKeyList(identity, keyList);
+ for (const Name& name : keyList) {
+ m_keyChain.getAllCertificateNamesOfKey(name, certNameList, false);
+ m_keyChain.getAllCertificateNamesOfKey(name, certNameList, true);
+ }
+ }
+
+ bool
+ checkIdCert(Zone& zone, const Name& certName)
+ {
+ Rrset rrset(&zone);
+ size_t size = zone.getName().size();
+ Name label = certName.getSubName(size+1, certName.size()-size-3);
+ rrset.setLabel(label);
+ rrset.setType(label::CERT_RR_TYPE);
+
+ if (!m_dbMgr.find(rrset))
+ return false;
+
+ Data data(rrset.getData());
+ IdentityCertificate cert(data);
+ return cert.getName() == certName;
+ }
+
+ bool
+ checkNs(Zone& zone, const Name& label, NdnsType ndnsType)
+ {
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(label::NS_RR_TYPE);
+
+ if (!m_dbMgr.find(rrset))
+ return false;
+
+ Data data(rrset.getData());
+ MetaInfo info = data.getMetaInfo();
+
+ const Block* block = info.findAppMetaInfo(tlv::NdnsType);
+ if (block == 0)
+ return false;
+
+ return static_cast<NdnsType>(readNonNegativeInteger(*block)) == ndnsType;
+ }
+
+ bool
+ checkVersion(Zone& zone, const Name& label, const name::Component& type, uint64_t version)
+ {
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(type);
+
+ if (!m_dbMgr.find(rrset))
+ return false;
+
+ name::Component tmp = name::Component::fromVersion(version);
+
+ return rrset.getVersion() == tmp;
+ }
+
+ bool
+ checkTtl(Zone& zone, const Name& label, const name::Component& type, time::seconds ttl)
+ {
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(type);
+
+ if (!m_dbMgr.find(rrset))
+ return false;
+
+ return rrset.getTtl() == ttl;
+ }
+
+ // function to get a verified public key of a given data
+ PublicKey
+ getPublicKeyOfData(const Data& data) {
+ // first extract certificate name of the signing key
+ Signature sig = data.getSignature();
+ KeyLocator kl = sig.getKeyLocator();
+ Name klName = kl.getName();
+
+ //base case, return root key to verify ROOT DSK certificate
+ shared_ptr<Regex> regex1 = make_shared<Regex>(
+ "<KEY><fake-root><123456789><ksk-[0-9]+><ID-CERT>");
+ if (regex1->match(klName)) {
+ std::vector<Name> keyList1;
+ m_keyChain.getAllKeyNamesOfIdentity(FAKE_ROOT, keyList1, false);
+ shared_ptr<PublicKey> rootKey = m_keyChain.getPublicKey(keyList1.front());
+
+ // return root key
+ return *rootKey;
+ }
+
+ // second extract the certificate from local NDNS database
+ // extract zone name and label
+ shared_ptr<Regex> regex2 = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT>");
+ BOOST_ASSERT(regex2->match(klName) == true);
+ Name zoneName = regex2->expand("\\1");
+ Name label = regex2->expand("\\2");
+
+ // get ID-CERT from local NDNS database
+ Zone zone(zoneName);
+ Rrset rrset(&zone);
+ rrset.setLabel(label);
+ rrset.setType(label::CERT_RR_TYPE);
+
+ BOOST_CHECK_EQUAL(m_dbMgr.find(rrset), true);
+
+ // get public key siging the ID-CERT
+ Data tmp(rrset.getData());
+ PublicKey pk = getPublicKeyOfData(tmp);
+
+ // verified the ID-CERT
+ BOOST_CHECK_EQUAL(Validator::verifySignature(tmp, pk), true);
+ IdentityCertificate cert(tmp);
+
+ // third return public key
+ return cert.getPublicKeyInfo();
+ }
+
+public:
+ ndns::ManagementTool m_tool;
+ ndn::KeyChain m_keyChain;
+ ndns::DbMgr m_dbMgr;
+};
+
+BOOST_FIXTURE_TEST_CASE(CreateZone1, ManagementToolFixture)
+{
+ //create root zone with supplied certificates
+ bool isRoot = m_keyChain.doesIdentityExist(ROOT_ZONE);
+ size_t iniKey = 0;
+ size_t iniCert = 0;
+ if (isRoot) {
+ std::vector<Name> keyList;
+ getKeyList(ROOT_ZONE, keyList);
+ iniKey = keyList.size();
+
+ std::vector<Name> certList;
+ getCertList(ROOT_ZONE, certList);
+ iniCert = certList.size();
+ }
+
+ time::system_clock::TimePoint notBefore = time::system_clock::now();
+ time::system_clock::TimePoint notAfter = notBefore + DEFAULT_CERT_TTL;
+
+ Name kskName = m_keyChain.generateRsaKeyPair(ROOT_ZONE, true);
+ std::vector<CertificateSubjectDescription> kskDesc;
+ shared_ptr<IdentityCertificate> kskCert = m_keyChain.prepareUnsignedIdentityCertificate(kskName,
+ ROOT_ZONE, notBefore, notAfter, kskDesc);
+ m_keyChain.selfSign(*kskCert);
+ m_keyChain.addCertificate(*kskCert);
+
+ Name dskName = m_keyChain.generateRsaKeyPair(ROOT_ZONE, false);
+ std::vector<CertificateSubjectDescription> dskDesc;
+ shared_ptr<IdentityCertificate> dskCert = m_keyChain.prepareUnsignedIdentityCertificate(
+ dskName, ROOT_ZONE, notBefore, notAfter, dskDesc);
+ m_keyChain.sign(*dskCert, kskCert->getName());
+ m_keyChain.addCertificate(*dskCert);
+
+ m_tool.createZone(ROOT_ZONE, ROOT_ZONE, time::seconds(4600), time::seconds(4600),
+ kskCert->getName(), dskCert->getName());
+
+ BOOST_CHECK_EQUAL(m_keyChain.doesIdentityExist(ROOT_ZONE), true);
+
+ std::vector<Name> keyList;
+ getKeyList(ROOT_ZONE, keyList);
+ BOOST_CHECK_EQUAL(keyList.size(), 2 + iniKey);
+
+ std::vector<Name> certList;
+ getCertList(ROOT_ZONE, certList);
+ BOOST_CHECK_EQUAL(certList.size(), 2 + iniCert);
+
+ Zone zone(ROOT_ZONE);
+ BOOST_CHECK_EQUAL(m_dbMgr.find(zone), true);
+ BOOST_CHECK_EQUAL(checkIdCert(zone, dskCert->getName()), true);
+
+ if (isRoot) {
+ // will leave the identity in KeyChain
+ m_keyChain.deleteCertificate(kskCert->getName());
+ m_keyChain.deleteCertificate(dskCert->getName());
+
+ m_keyChain.deleteKey(kskName);
+ m_keyChain.deleteKey(dskName);
+ }
+ else {
+ m_tool.deleteZone(ROOT_ZONE);
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE(CreateZone2, ManagementToolFixture)
+{
+ //create normal zone
+ Name parentZoneName("/ndns-test");
+ parentZoneName.appendVersion();
+ Name zoneName = parentZoneName;
+ zoneName.append("child-zone");
+
+
+ m_tool.createZone(zoneName, parentZoneName);
+
+ BOOST_CHECK_EQUAL(m_keyChain.doesIdentityExist(zoneName), true);
+
+ std::vector<Name> keyList;
+ getKeyList(zoneName, keyList);
+ BOOST_CHECK_EQUAL(keyList.size(), 2);
+
+ std::vector<Name> certList;
+ getCertList(zoneName, certList);
+ BOOST_CHECK_EQUAL(certList.size(), 2);
+
+ Name dskName;
+ Name kskName;
+ for (std::vector<Name>::iterator it = certList.begin();
+ it != certList.end();
+ it++) {
+ std::string temp = (*it).toUri();
+ size_t found = temp.find("dsk");
+ if (found != std::string::npos) {
+ dskName = *it;
+ }
+ else {
+ kskName = *it;
+ }
+ }
+
+ Zone zone(zoneName);
+ BOOST_CHECK_EQUAL(m_dbMgr.find(zone), true);
+ BOOST_CHECK_EQUAL(checkIdCert(zone, dskName), true);
+
+ m_tool.deleteZone(zoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(CreateZone3, ManagementToolFixture)
+{
+ //create normal zone with TTL
+ Name parentZoneName("/ndns-test");
+ parentZoneName.appendVersion();
+ Name zoneName = parentZoneName;
+ zoneName.append("child-zone");
+
+ time::seconds ttl = time::seconds(4200);
+ m_tool.createZone(zoneName, parentZoneName, ttl, ttl);
+
+ BOOST_CHECK_EQUAL(m_keyChain.doesIdentityExist(zoneName), true);
+
+ std::vector<Name> keyList;
+ getKeyList(zoneName, keyList);
+ BOOST_CHECK_EQUAL(keyList.size(), 2);
+
+ std::vector<Name> certList;
+ getCertList(zoneName, certList);
+ BOOST_CHECK_EQUAL(certList.size(), 2);
+
+ Name dskName;
+ for (std::vector<Name>::iterator it = certList.begin();
+ it != certList.end();
+ it++) {
+ std::string temp = (*it).toUri();
+ size_t found = temp.find("dsk");
+ if (found != std::string::npos) {
+ dskName = *it;
+ }
+ }
+
+ //check zone ttl
+ Zone zone(zoneName);
+ BOOST_CHECK_EQUAL(m_dbMgr.find(zone), true);
+ BOOST_CHECK_EQUAL(zone.getTtl(), ttl);
+
+ //check dsk rrset ttl
+ Rrset rrset(&zone);
+ size_t size = zone.getName().size();
+ Name label = dskName.getSubName(size+1, dskName.size()-size-3);
+ rrset.setLabel(label);
+ rrset.setType(label::CERT_RR_TYPE);
+ BOOST_CHECK_EQUAL(m_dbMgr.find(rrset), true);
+ BOOST_CHECK_EQUAL(rrset.getTtl(), ttl);
+
+ //check certificate ttl
+ shared_ptr<IdentityCertificate> dskCert = m_keyChain.getCertificate(dskName);
+ time::system_clock::Duration tmp = dskCert->getNotAfter() - dskCert->getNotBefore();
+ BOOST_CHECK_EQUAL(ttl, tmp);
+
+ m_tool.deleteZone(zoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(CreateZone4, ManagementToolFixture)
+{
+ //check pre-condition
+ Name zoneName("/net/ndnsim");
+ Name parentZoneName("/net");
+
+ Zone zone(zoneName);
+ m_dbMgr.insert(zone);
+ BOOST_CHECK_THROW(m_tool.createZone(zoneName, parentZoneName), ndns::ManagementTool::Error);
+ m_dbMgr.remove(zone);
+
+ time::seconds ttl = time::seconds(4200);
+ BOOST_CHECK_THROW(m_tool.createZone(zoneName, zoneName), ndns::ManagementTool::Error);
+
+ Name fake1("/com");
+ BOOST_CHECK_THROW(m_tool.createZone(zoneName, fake1), ndns::ManagementTool::Error);
+
+ Name fake2("/com/ndnsim");
+ BOOST_CHECK_THROW(m_tool.createZone(zoneName, parentZoneName, ttl, ttl, fake2),
+ ndns::ManagementTool::Error);
+ Name cert2 = m_keyChain.createIdentity(fake2);
+ BOOST_CHECK_THROW(m_tool.createZone(zoneName, parentZoneName, ttl, ttl, cert2),
+ ndns::ManagementTool::Error);
+ m_keyChain.deleteIdentity(fake2);
+
+ Name fake3("/net/ndnsim/www");
+ Name cert3 = m_keyChain.createIdentity(fake3);
+ BOOST_CHECK_THROW(m_tool.createZone(zoneName, parentZoneName, ttl, ttl, cert3),
+ ndns::ManagementTool::Error);
+ m_keyChain.deleteIdentity(fake3);
+
+ Name cert4 = m_keyChain.createIdentity(zoneName);
+ shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(cert4);
+ //delete keys in tpm
+ m_keyChain.deleteKeyPairInTpm(cert->getPublicKeyName());
+ BOOST_CHECK_THROW(m_tool.createZone(zoneName, parentZoneName, ttl, ttl, cert4),
+ ndns::ManagementTool::Error);
+ m_keyChain.deleteIdentity(zoneName);
+
+ //for root zone special case
+ BOOST_CHECK_THROW(m_tool.createZone(ROOT_ZONE, ROOT_ZONE), ndns::ManagementTool::Error);
+}
+
+BOOST_FIXTURE_TEST_CASE(DeleteZone1, ManagementToolFixture)
+{
+ Name zoneName("/ndns-test");
+ zoneName.appendVersion();
+
+ m_tool.createZone(zoneName, ROOT_ZONE);
+
+ std::vector<Name> keyList;
+ getKeyList(zoneName, keyList);
+ std::vector<Name> certList;
+ getCertList(zoneName, certList);
+
+ m_tool.deleteZone(zoneName);
+
+ BOOST_CHECK_EQUAL(m_keyChain.doesIdentityExist(zoneName), false);
+
+ for (std::vector<Name>::iterator it = keyList.begin(); it != keyList.end(); it++) {
+ BOOST_CHECK_EQUAL(m_keyChain.doesKeyExistInTpm(*it, KEY_CLASS_PUBLIC), false);
+ BOOST_CHECK_EQUAL(m_keyChain.doesKeyExistInTpm(*it, KEY_CLASS_PRIVATE), false);
+ }
+
+ Name dskName;
+ for (std::vector<Name>::iterator it = certList.begin();
+ it != certList.end();
+ it++) {
+ BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(*it), false);
+ std::string temp = (*it).toUri();
+ size_t found = temp.find("dsk");
+ if (found != std::string::npos) {
+ dskName = *it;
+ }
+ }
+
+ Zone zone(zoneName);
+ BOOST_CHECK_EQUAL(m_dbMgr.find(zone), false);
+ BOOST_CHECK_EQUAL(checkIdCert(zone, dskName), false);
+}
+
+BOOST_FIXTURE_TEST_CASE(DeleteZone2, ManagementToolFixture)
+{
+ Name zoneName("/net/ndnsim");
+
+ BOOST_CHECK_THROW(m_tool.deleteZone(zoneName), ndns::ManagementTool::Error);
+}
+
+class OutputTester
+{
+public:
+ OutputTester()
+ : savedBuf(std::clog.rdbuf())
+ {
+ std::cout.rdbuf(buffer.rdbuf());
+ }
+
+ ~OutputTester()
+ {
+ std::cout.rdbuf(savedBuf);
+ }
+
+public:
+ std::stringstream buffer;
+ std::streambuf* savedBuf;
+};
+
+BOOST_FIXTURE_TEST_CASE(ExportCertificate, ManagementToolFixture)
+{
+ Name zoneName("/ndns-test");
+ zoneName.appendVersion();
+ std::string output = TEST_CERTDIR.string() + "/ss.cert";
+
+ /// @todo Do not generate anything in root zone. Use some prefix for testing, e.g. /test
+
+ //check precondition
+ Name certName("/net/KEY/ksk-123/ID-CERT/123");
+ BOOST_CHECK_THROW(m_tool.exportCertificate(certName, output), ndns::ManagementTool::Error);
+
+ //get certificate from KeyChain
+ m_tool.createZone(zoneName, ROOT_ZONE);
+ std::vector<Name> certList;
+ getCertList(zoneName, certList);
+ Name kskCertName;
+ Name dskCertName;
+ for (const auto& cert : certList) {
+ std::string temp = cert.toUri();
+ size_t found = temp.find("ksk");
+ if (found != std::string::npos) {
+ kskCertName = cert;
+ }
+ else {
+ dskCertName = cert;
+ }
+ }
+ m_tool.exportCertificate(kskCertName, output);
+ BOOST_CHECK_EQUAL(boost::filesystem::exists(output), true);
+
+ //get certificate from ndns database
+ boost::filesystem::remove(output);
+ m_keyChain.deleteCertificate(dskCertName);
+ m_tool.exportCertificate(dskCertName, output);
+ BOOST_CHECK_EQUAL(boost::filesystem::exists(output), true);
+
+ //output to std::cout
+ std::string acutalOutput;
+ {
+ OutputTester tester;
+ m_tool.exportCertificate(dskCertName, "-");
+ acutalOutput = tester.buffer.str();
+ }
+ // BOOST_CHECK_EQUAL(acutalOutput,
+ // "Bv0DDAdCCAluZG5zLXRlc3QICf0AAAFJ6RF8OggDS0VZCBFkc2stMTQxNjk1NDQ3\n"
+ // "NzcxNQgHSUQtQ0VSVAgJ/QAAAUnpEXzcFAMYAQIV/QF7MIIBdzAiGA8yMDE0MTEy\n"
+ // "NTIyMjc1N1oYDzIwMTUxMTI1MjIyNzU3WjAtMCsGA1UEKRMkL25kbnMtdGVzdC8l\n"
+ // "RkQlMDAlMDAlMDFJJUU5JTExJTdDJTNBMIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A\n"
+ // "MIIBCAKCAQEAvRAQ0iLGmoUCNFQjtD6ClA6BzmtViWywDRU7eDXHHqz1BmXNGS28\n"
+ // "dmVbk6C8ZiQxVh5IoN2psxU1avC2lLM7HXHnyUtmfu9/zkxdBSFq8B+8FchFpPWe\n"
+ // "9M/TSFmEemcFLdMgYEJOurF3osASZ70/kJJ7f1yiFRm1dtO2pl5eVUuiZPcgVwMU\n"
+ // "nCUDT/wZ6l2LDr4K7wo6p5F8PYiIddS6zT38gZsRNwCeR5JDwCPY3u5x21aVSSY7\n"
+ // "8PS/wdSG0vmjI/kQEWhjaV7ibyTc6ygrbq5RiLD+18CkEF+ECLKjvLnyIO8DkbbM\n"
+ // "iMVyc6QSiKnq7bLCyqbBVpZqNpBjdMvDuQIBERY+GwEBHDkHNwgDS0VZCAluZG5z\n"
+ // "LXRlc3QICf0AAAFJ6RF8OggRa3NrLTE0MTY5NTQ0Nzc2MjcIB0lELUNFUlQX/QEA\n"
+ // "BKchd4m2kpI7N376Z8yRAKA3epcUlGI5E1Xs7pKTFwA16ZQ+dTThBQSzzVaJcOC2\n"
+ // "UIc2WVRG5wCxcCLou4bxnbuPaQORyeRnmoodTPoIYsDrWVPxeVY1xJSKCbGoY8dh\n"
+ // "BuXmo9nl4X2wk/gZx6//afATgzQCliQK/J9PwigqirJqH6aD+3Ji209FbP57tv0g\n"
+ // "aL0Dy5IA6LrJI1Dxq0MXCRv3bNtdGNQZT0AfHIgCrhPe6MMLGn+C9UTDP2nzMqbX\n"
+ // "4MaAdshgUFj0mI2iPL3Bep9pYI6zxbU3hJ25UQegjJdC3qoFjz2sp/D6J8wAlCPX\n"
+ // "gGH3iewd94xFpPcdrhxtHQ==\n");
+
+ m_tool.deleteZone(zoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(AddRrSet1, ManagementToolFixture)
+{
+ // check pre-condition
+ BOOST_CHECK_THROW(m_tool.addRrSet(ROOT_ZONE, ROOT_ZONE, label::NS_RR_TYPE, NDNS_RESP),
+ ndns::ManagementTool::Error);
+
+ Name zoneName("/ndns-test");
+ zoneName.appendVersion();
+ Zone zone(zoneName);
+ m_dbMgr.insert(zone);
+
+ BOOST_CHECK_THROW(m_tool.addRrSet(ROOT_ZONE, ROOT_ZONE, label::NS_RR_TYPE, NDNS_UNKNOWN),
+ ndns::ManagementTool::Error);
+ BOOST_CHECK_THROW(m_tool.addRrSet(zoneName, zoneName, label::CERT_RR_TYPE, NDNS_RAW),
+ ndns::ManagementTool::Error);
+ BOOST_CHECK_THROW(m_tool.addRrSet(ROOT_ZONE, ROOT_ZONE, label::NS_RR_TYPE, NDNS_RAW),
+ ndns::ManagementTool::Error);
+ BOOST_CHECK_THROW(m_tool.addRrSet(ROOT_ZONE, ROOT_ZONE, label::TXT_RR_TYPE, NDNS_RAW),
+ ndns::ManagementTool::Error);
+
+ m_dbMgr.remove(zone);
+}
+
+BOOST_FIXTURE_TEST_CASE(AddRrSet2, ManagementToolFixture)
+{
+ Name zoneName("/ndns-test");
+ zoneName.appendVersion();
+ Zone zone(zoneName);
+ uint64_t version = 1234;
+ time::seconds ttl1(4200);
+ time::seconds ttl2(4500);
+ m_tool.createZone(zoneName, ROOT_ZONE, ttl1);
+
+ //add NS NDNS_AUTH and check user-defined ttl
+ Name label1("/net/ndnsim1");
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(zoneName, label1, label::NS_RR_TYPE, NDNS_AUTH, version,
+ {}, DEFAULT_CERT, ttl2));
+ BOOST_CHECK_EQUAL(checkNs(zone, label1, NDNS_AUTH), true);
+ BOOST_CHECK_EQUAL(checkVersion(zone, label1, label::NS_RR_TYPE, version), true);
+ BOOST_CHECK_EQUAL(checkTtl(zone, label1, label::NS_RR_TYPE, ttl2), true);
+
+ //add NS NDNS_RESP and check default ttl
+ Name label2("/net/ndnsim2");
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(zoneName, label2, label::NS_RR_TYPE, NDNS_RESP, version));
+ BOOST_CHECK_EQUAL(checkNs(zone, label2, NDNS_RESP), true);
+ BOOST_CHECK_EQUAL(checkVersion(zone, label2, label::NS_RR_TYPE, version), true);
+ BOOST_CHECK_EQUAL(checkTtl(zone, label2, label::NS_RR_TYPE, ttl1), true);
+
+ //add TXT NDNS_RESP and check rr
+ std::string test = "oops";
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(zoneName, label2, label::TXT_RR_TYPE, NDNS_RESP, version,
+ {test}));
+ Rrset rrset1(&zone);
+ rrset1.setLabel(label2);
+ rrset1.setType(label::TXT_RR_TYPE);
+ BOOST_CHECK_EQUAL(m_dbMgr.find(rrset1), true);
+
+ Data data1(rrset1.getData());
+ Response re1;
+ Name hint1;
+ BOOST_CHECK_EQUAL(re1.fromData(hint1, zoneName, data1), true);
+ const Block &block = re1.getRrs().front();
+ std::string someString(reinterpret_cast<const char*>(block.value()), block.value_size());
+ BOOST_CHECK_EQUAL(test, someString);
+
+ //add user defined type
+ Name label3("/net/ndnsim3");
+ name::Component type("A");
+ std::string content = "10.10.0.1";
+ m_tool.addRrSet(zoneName, label3, type, NDNS_RAW, version, {content});
+ BOOST_CHECK_EQUAL(checkVersion(zone, label3, type, version), true);
+
+ Rrset rrset2(&zone);
+ rrset2.setLabel(label3);
+ rrset2.setType(type);
+ BOOST_CHECK_EQUAL(m_dbMgr.find(rrset2), true);
+
+ Data data2(rrset2.getData());
+ Response re2;
+ Name hint2;
+ BOOST_CHECK_EQUAL(re2.fromData(hint2, zoneName, data2), true);
+ Block tmp = ndn::dataBlock(ndn::tlv::Content, content.c_str(), content.length());
+ tmp.encode();
+ BOOST_REQUIRE(tmp == re2.getAppContent());
+
+ m_tool.deleteZone(zoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(AddRrSet3, ManagementToolFixture)
+{
+ // check pre-condition
+ Name zoneName("/ndns-test");
+ zoneName.appendVersion();
+ std::string certPath = TEST_CERTDIR.string();
+ BOOST_CHECK_THROW(m_tool.addRrSet(zoneName, certPath), ndns::ManagementTool::Error);
+
+ m_tool.createZone(zoneName, ROOT_ZONE);
+ BOOST_CHECK_THROW(m_tool.addRrSet(zoneName, certPath), ndns::ManagementTool::Error);
+ m_tool.deleteZone(zoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(AddRrSet4, ManagementToolFixture)
+{
+ Name parentZoneName("/ndns-test");
+ parentZoneName.appendVersion();
+ Name zoneName = parentZoneName;
+ zoneName.append("/child-zone");
+ Zone zone(parentZoneName);
+ time::seconds ttl1(4200);
+ time::seconds ttl2(4500);
+ m_tool.createZone(zoneName, parentZoneName);
+ m_tool.createZone(parentZoneName, ROOT_ZONE, ttl1);
+
+ //add KSK ID-CERT
+ std::string output = TEST_CERTDIR.string() + "/ss.cert";
+ std::vector<Name> certList;
+ getCertList(zoneName, certList);
+ Name kskCertName;
+ for (std::vector<Name>::iterator it = certList.begin();
+ it != certList.end();
+ it++) {
+ std::string temp = (*it).toUri();
+ size_t found = temp.find("ksk");
+ if (found != std::string::npos) {
+ kskCertName = *it;
+ break;
+ }
+ }
+ m_tool.exportCertificate(kskCertName, output);
+
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(parentZoneName, output, ttl2));
+ BOOST_CHECK_EQUAL(checkIdCert(zone, kskCertName), true);
+
+ //add data
+ Response re;
+ re.setZone(parentZoneName);
+ re.setQueryType(label::NDNS_ITERATIVE_QUERY);
+ re.setRrLabel(zoneName);
+ re.setRrType(label::NS_RR_TYPE);
+ re.setNdnsType(NDNS_RESP);
+ shared_ptr<Data> data1 = re.toData();
+ m_keyChain.sign(*data1, kskCertName);
+ ndn::io::save(*data1, output);
+
+ //check user-defined ttl and default ttl
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(parentZoneName, output));
+ BOOST_CHECK_EQUAL(checkTtl(zone, zoneName, label::NS_RR_TYPE, ttl1), true);
+ m_tool.removeRrSet(parentZoneName, zoneName, label::NS_RR_TYPE);
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(parentZoneName, output, ttl2));
+ BOOST_CHECK_EQUAL(checkTtl(zone, zoneName, label::NS_RR_TYPE, ttl2), true);
+
+ Rrset rrset(&zone);
+ rrset.setLabel(zoneName);
+ rrset.setType(label::NS_RR_TYPE);
+ BOOST_CHECK_EQUAL(m_dbMgr.find(rrset), true);
+
+ Data data2(rrset.getData());
+ BOOST_REQUIRE(*data1 == data2);
+
+ //add KSK ID-CERT with illegal name and convert it
+ Name iZoneName = parentZoneName;
+ iZoneName.append("illegal");
+ Name illegalCertName = m_keyChain.createIdentity(iZoneName);
+ m_tool.exportCertificate(illegalCertName, output);
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(parentZoneName, output, ttl2));
+
+ Name legalCertName = parentZoneName;
+ legalCertName.append("KEY");
+ legalCertName.append("illegal");
+ legalCertName.append(illegalCertName.getSubName(4));
+ BOOST_CHECK_EQUAL(checkIdCert(zone, legalCertName), true);
+ m_keyChain.deleteIdentity(iZoneName);
+
+ m_tool.deleteZone(zoneName);
+ m_tool.deleteZone(parentZoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(AddRrSet5, ManagementToolFixture)
+{
+ //check using user provided certificate
+ Name parentZoneName("/ndns-test");
+ parentZoneName.appendVersion();
+ Name zoneName = parentZoneName;
+ zoneName.append("child-zone");
+
+ Name dskName = m_keyChain.generateRsaKeyPair(parentZoneName, false);
+ shared_ptr<IdentityCertificate> dskCert = m_keyChain.selfSign(dskName);
+ m_keyChain.addCertificateAsKeyDefault(*dskCert);
+
+ //check addRrSet1
+ m_tool.createZone(zoneName, parentZoneName);
+ m_tool.createZone(parentZoneName, ROOT_ZONE);
+
+ //add KSK ID-CERT
+ std::string output = TEST_CERTDIR.string() + "/ss.cert";
+ std::vector<Name> certList;
+ getCertList(zoneName, certList);
+ Name kskCertName;
+ for (std::vector<Name>::iterator it = certList.begin();
+ it != certList.end();
+ it++) {
+ std::string temp = (*it).toUri();
+ size_t found = temp.find("ksk");
+ if (found != std::string::npos) {
+ kskCertName = *it;
+ break;
+ }
+ }
+ m_tool.exportCertificate(kskCertName, output);
+
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(parentZoneName, output, time::seconds(4600),
+ dskCert->getName()));
+
+ //check addRrSet2
+ Name label1("/net/ndnsim1");
+ BOOST_CHECK_NO_THROW(m_tool.addRrSet(parentZoneName, label1, label::NS_RR_TYPE, NDNS_AUTH, -1, {},
+ dskCert->getName()));
+
+ m_tool.deleteZone(zoneName);
+ m_tool.deleteZone(parentZoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(ListZone, ManagementToolFixture)
+{
+ Name zoneName("/ndns-test/mgmt/123456789");
+
+ m_tool.createZone(zoneName, ROOT_ZONE);
+ Name certName = m_keyChain.getDefaultCertificateNameForIdentity(zoneName);
+ shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(certName);
+
+ //add NS with NDNS_RESP
+ Name label2("/ndnsim");
+ uint64_t version = 1234;
+ m_tool.addRrSet(zoneName, label2, label::NS_RR_TYPE, NDNS_RESP, version);
+
+ //add NS with NDNS_AUTH
+ Name label3("/ndnsim/oops");
+ m_tool.addRrSet(zoneName, label3, label::NS_RR_TYPE, NDNS_AUTH, version);
+
+ //add TXT
+ std::string output = TEST_CERTDIR.string() + "/a.rrset";
+ Response re1;
+ re1.setZone(zoneName);
+ re1.setQueryType(label::NDNS_ITERATIVE_QUERY);
+ re1.setRrLabel(label2);
+ re1.setRrType(label::TXT_RR_TYPE);
+ re1.setNdnsType(NDNS_RESP);
+ re1.setVersion(name::Component::fromVersion(version));
+ re1.addRr("First RR");
+ re1.addRr("Second RR");
+ re1.addRr("Last RR");
+ shared_ptr<Data> data1= re1.toData();
+ m_keyChain.sign(*data1, certName);
+ ndn::io::save(*data1, output);
+ m_tool.addRrSet(zoneName, output);
+
+ //add User-Defined
+ name::Component type("A");
+ Response re2;
+ re2.setZone(zoneName);
+ re2.setQueryType(label::NDNS_ITERATIVE_QUERY);
+ re2.setRrLabel(label2);
+ re2.setRrType(type);
+ re2.setNdnsType(NDNS_RESP);
+ re2.setVersion(name::Component::fromVersion(version));
+ re2.addRr("First RR");
+ re2.addRr("Second RR");
+ re2.addRr("Last RR");
+ shared_ptr<Data> data2= re2.toData();
+ m_keyChain.sign(*data2, certName);
+ ndn::io::save(*data2, output);
+ m_tool.addRrSet(zoneName, output);
+
+ output_test_stream testOutput;
+ m_tool.listZone(zoneName, testOutput, true);
+
+ /// @todo check the output
+
+ // BOOST_CHECK(testOutput.
+ // is_equal(
+ // "; Zone /ndns-test/mgmt/123456789\n"
+ // "\n"
+ // "; rrset=/ndnsim type=A version=%FD%04%D2 signed-by=*\n"
+ // "/ndnsim 3600 A vwhGaXJzdCBSUg==\n"
+ // "/ndnsim 3600 A vwlTZWNvbmQgUlI=\n"
+ // "/ndnsim 3600 A vwdMYXN0IFJS\n"
+ // "\n"
+ // "; rrset=/ndnsim type=NS version=%FD%04%D2 signed-by=*\n"
+ // "/ndnsim 3600 NS\n"
+ // "\n"
+ // "; rrset=/ndnsim type=TXT version=%FD%04%D2 signed-by=*\n"
+ // "/ndnsim 3600 TXT First RR\n"
+ // "/ndnsim 3600 TXT Second RR\n"
+ // "/ndnsim 3600 TXT Last RR\n"
+ // ""
+ // "/ndnsim/oops 3600 NS ; content-type=NDNS-Auth version=* signed-by=*\n"
+ // "/dsk-1416888156106 3600 ID-CERT ; content-type=NDNS-Raw version=* signed-by=*\n"
+ // "; Ff0BcjCCAW4wIhgPMjAxNDExMjUwNDAyMzVaGA8yMDE1MTEyNTA0MDIzNVowIjAg\n"
+ // "; BgNVBCkTGS9uZG5zLXRlc3QvbWdtdC8xMjM0NTY3ODkwggEiMA0GCSqGSIb3DQEB\n"
+ // "; AQUAA4IBDwAwggEKAoIBAQD8Lsd/kKdcdXTKEhcJpy7M0cnZgpZ3lpQX2Nz8InXN\n"
+ // "; BkF3b6TsuMSokmDQ78xXNTx0jGUM1g47kQNsk2WTjYgDZUOfpBWz5PZcaO35dUz8\n"
+ // "; wNGc1lED9A/PbFB4t5NPbZsrThCPw+IvzTYN6A/Dxg9h69zLEEsLWD2PzCkyHQ+F\n"
+ // "; JjRgzhJPsrl1CoVFSP/bu70xMJVqOwj3GMej6mm0gXXmMv4aEI22jot7+fO07jIy\n"
+ // "; WUl0fhY33Cgo50YvDeeRsdo+At29OMN8Dd/s2z/6olH0P7IK1/cn++DWcO5zMd1x\n"
+ // "; zWm+6IoZA6mV1J2O5U0AkbllRVZ+vZPI/lWGzCtXK6jfAgMBAAE=\n"
+ // ));
+
+ m_tool.deleteZone(zoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(ListAllZones, ManagementToolFixture)
+{
+ Name zoneName1("/ndns-test1/mgmt/123456789");
+ m_tool.createZone(zoneName1, ROOT_ZONE);
+
+ Name zoneName2("/ndns-test2/mgmt/123456789");
+ m_tool.createZone(zoneName2, ROOT_ZONE);
+
+ Name zoneName3("/ndns-test3/mgmt/123456789");
+ m_tool.createZone(zoneName3, ROOT_ZONE);
+
+ //TODO Check the output
+ // a sample output is like this
+ // /ndns-test1/mgmt/123456789 ; default-ttl=* default-key=* default-certificate=*
+ // /ndns-test2/mgmt/123456789 ; default-ttl=* default-key=* default-certificate=*
+ // /ndns-test3/mgmt/123456789 ; default-ttl=* default-key=* default-certificate=*
+ output_test_stream testOutput;
+ m_tool.listAllZones(testOutput);
+
+ m_tool.deleteZone(zoneName1);
+ m_tool.deleteZone(zoneName2);
+ m_tool.deleteZone(zoneName3);
+}
+
+BOOST_FIXTURE_TEST_CASE(GetRrSet, ManagementToolFixture)
+{
+ Name zoneName("/ndns-test");
+ zoneName.appendVersion();
+ m_tool.createZone(zoneName, ROOT_ZONE);
+
+ Name label("/net/ndnsim2");
+
+ m_tool.addRrSet(zoneName, label, label::NS_RR_TYPE, NDNS_RESP);
+
+ // a sample output is like this
+// Bv0Bjgc5CAluZG5zLXRlc3QICf0AAAFJ5Sn8HwgETkROUwgDbmV0CAduZG5zaW0y
+// CAJOUwgJ/QAAAUnlKgXYFAkZBAA27oC0AQEVAr8AFj4bAQEcOQc3CAluZG5zLXRl
+// c3QICf0AAAFJ5Sn8HwgDS0VZCBFkc2stMTQxNjg4ODk3NTY0NAgHSUQtQ0VSVBf9
+// AQBj8QOr3vPo1wzuTAwwdF6UEfHmHYxkMor5bw/5Lc6Wpt6SkTb7Ku92/MHedtRD
+// 2UsIhQV+JR7jUGzLVLUuktmrBTT7G9tSioTOVpbtJ7EEYYhcDCV0h1Kefz01AS1O
+// bUuZbxAWboZCzW6OluTq9Db2c2xEmzE8EzmMQ5zflIL7vQxEigH1kBsvGoMZThOb
+// aKrfcACfKU3kZQBzyPVbur5PER3dgBjVcdu5aIEXhO3Nf7b22OrPSP8AztZGvkz0
+// 5TSBf7wwxtB6V/aMlDPaKFPgI2mXan729e1JGYZ0OmKhvuPnhT9ApOh9UNSJuhO8
+// puPJKCOSQHspQHOhnEy9Ee9U
+ output_test_stream testOutput;
+ m_tool.getRrSet(zoneName, label, label::NS_RR_TYPE, testOutput);
+
+ m_tool.deleteZone(zoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(RemoveRrSet, ManagementToolFixture)
+{
+ Name zoneName("/ndns-test");
+ zoneName.appendVersion();
+ m_tool.createZone(zoneName, ROOT_ZONE);
+ Name label2("/net/ndnsim2");
+ m_tool.addRrSet(zoneName, label2, label::NS_RR_TYPE, NDNS_RESP);
+
+ m_tool.removeRrSet(zoneName, label2, label::NS_RR_TYPE);
+ Zone zone(zoneName);
+ BOOST_CHECK_EQUAL(checkNs(zone, label2, NDNS_RESP), false);
+
+ m_tool.deleteZone(zoneName);
+}
+
+BOOST_FIXTURE_TEST_CASE(DataValidation, ManagementToolFixture)
+{
+ Name subZoneName1 = FAKE_ROOT;
+ subZoneName1.append("net");
+ Name subZoneName2 = subZoneName1;
+ subZoneName2.append("ndnsim");
+
+ // create fake-root zone
+ m_tool.createZone(FAKE_ROOT, ROOT_ZONE);
+
+ // create subZone1 by creating zone, delegating it to ROOT zone
+ m_tool.createZone(subZoneName1, FAKE_ROOT);
+
+ std::string output1 = TEST_CERTDIR.string() + "/ss1.cert";
+ std::vector<Name> certList1;
+ getCertList(subZoneName1, certList1);
+ Name kskCertName1;
+ for (std::vector<Name>::iterator it = certList1.begin();
+ it != certList1.end();
+ it++) {
+ std::string temp = (*it).toUri();
+ size_t found = temp.find("ksk");
+ if (found != std::string::npos) {
+ kskCertName1 = *it;
+ break;
+ }
+ }
+ m_tool.exportCertificate(kskCertName1, output1);
+ m_tool.addRrSet(FAKE_ROOT, output1, time::seconds(4600));
+
+ // create subZone2 by creating zone, delegating it to subZone1
+ m_tool.createZone(subZoneName2, subZoneName1);
+
+ std::string output2 = TEST_CERTDIR.string() + "/ss2.cert";
+ std::vector<Name> certList2;
+ getCertList(subZoneName2, certList2);
+ Name kskCertName2;
+ for (std::vector<Name>::iterator it = certList2.begin();
+ it != certList2.end();
+ it++) {
+ std::string temp = (*it).toUri();
+ size_t found = temp.find("ksk");
+ if (found != std::string::npos) {
+ kskCertName2 = *it;
+ break;
+ }
+ }
+ m_tool.exportCertificate(kskCertName2, output2);
+ m_tool.addRrSet(subZoneName1, output2, time::seconds(4600));
+
+ //simulate the trust chain
+ Data data("test");
+ Name certName = m_keyChain.getDefaultCertificateNameForIdentity(subZoneName2);
+ m_keyChain.sign(data, certName);
+
+ //details of the verification please see the getPublicKeyOfData() function
+ PublicKey pk = getPublicKeyOfData(data);
+ BOOST_CHECK_EQUAL(Validator::verifySignature(data, pk), true);
+
+ m_tool.deleteZone(subZoneName2);
+ m_tool.deleteZone(subZoneName1);
+ m_tool.deleteZone(FAKE_ROOT);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace ndns
+} // namespace ndn
diff --git a/tools/ndns-add-rr-from-file.cpp b/tools/ndns-add-rr-from-file.cpp
new file mode 100644
index 0000000..4fc2066
--- /dev/null
+++ b/tools/ndns-add-rr-from-file.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+
+
+// @todo combine this command with ndns-add-rr
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ using namespace ndns;
+
+ ndn::ndns::log::init();
+ int ttlInt = -1;
+ string zoneStr;
+ string dskStr;
+ string db;
+ string file = "-";
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database. "
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db")
+ ;
+
+ po::options_description config("Record Options");
+ config.add_options()
+ ("file,f", po::value<string>(&file), "Path to the data. Default is stdin(-)")
+ ("dsk,d", po::value<std::string>(&dskStr), "Set the name of DSK's certificate. "
+ "Default: use default DSK and its default certificate")
+ ("ttl,a", po::value<int>(&ttlInt), "Set ttl of the rrset. Default: 3600 seconds")
+ ;
+
+ options.add(config);
+
+ po::options_description hidden("Hidden Options");
+ hidden.add_options()
+ ("zone", po::value<string>(&zoneStr), "host zone name")
+ ;
+
+ po::positional_options_description postion;
+ postion.add("zone", 1);
+ postion.add("file", 1);
+
+ po::options_description cmdlineOptions;
+ cmdlineOptions.add(options).add(hidden);
+
+ // po::options_description config_file_options;
+ // config_file_options.add(config).add(hidden);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdlineOptions).positional(postion).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-add-rr-from-file [-b db] zone [-f file] [-d dskCert] [-a ttl]"
+ " [file]" << std::endl
+ << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ if (vm.count("zone") == 0) {
+ std::cerr << "Error: zone must be specified" << std::endl;
+ return 1;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ Name zoneName(zoneStr);
+ Name dskName(dskStr);
+ time::seconds ttl;
+ if (ttlInt == -1)
+ ttl = ndns::DEFAULT_CACHE_TTL;
+ else
+ ttl = time::seconds(ttlInt);
+
+ ndn::ndns::ManagementTool tool(db);
+ tool.addRrSet(zoneName, file, ttl, dskName);
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}
diff --git a/tools/ndns-add-rr.cpp b/tools/ndns-add-rr.cpp
new file mode 100644
index 0000000..47e7121
--- /dev/null
+++ b/tools/ndns-add-rr.cpp
@@ -0,0 +1,161 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include "util/util.hpp"
+
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+
+#include <string>
+
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ using namespace ndns;
+
+ ndn::ndns::log::init();
+ int ttlInt = -1;
+ int versionInt = -1;
+ string zoneStr;
+ Name dsk;
+ string db;
+ string rrLabelStr;
+ string rrTypeStr;
+ string ndnsTypeStr;
+ std::vector<std::string> content;
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database. "
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db")
+ ;
+
+ po::options_description config("Record Options");
+ config.add_options()
+ ("content-type,t", po::value<string>(&ndnsTypeStr), "Set the ndnsType of the resource record."
+ "Options: resp|nack|auth|raw (will try guess type by default)")
+ ("dsk,d", po::value<Name>(&dsk), "Set the name of DSK's certificate. "
+ "Default: use default DSK and its default certificate")
+ ("content,c", po::value<std::vector<std::string>>(&content),
+ "Set the content of resource record. Default: empty string")
+ ("ttl,a", po::value<int>(&ttlInt), "Set ttl of the rrset. Default: 3600 seconds")
+ ("version,v", po::value<int>(&ttlInt), "Set version of the rrset. Default: Unix Timestamp")
+ ;
+
+ // add "Record Options" as a separate section
+ options.add(config);
+
+ po::options_description hidden("Hidden Options");
+ hidden.add_options()
+ ("zone", po::value<string>(&zoneStr), "host zone name")
+ ("label", po::value<string>(&rrLabelStr), "label of resource record.")
+ ("type", po::value<string>(&rrTypeStr), "Set the type of resource record.")
+ ;
+
+ po::positional_options_description positional;
+ positional.add("zone", 1);
+ positional.add("label", 1);
+ positional.add("type", 1);
+ positional.add("content", -1);
+
+ po::options_description cmdlineOptions;
+ cmdlineOptions.add(options).add(hidden);
+
+ // po::options_description configFileOptions;
+ // configFileOptions.add(config).add(hidden);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdlineOptions).positional(positional).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-add-rr [options] zone label type [content ...]" << std::endl
+ << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ if (vm.count("zone") == 0) {
+ std::cerr << "Error: zone, label, and type must be specified" << std::endl;
+ return 1;
+ }
+
+ if (vm.count("label") == 0) {
+ std::cerr << "Error: label and type must be specified" << std::endl;
+ return 1;
+ }
+
+ if (vm.count("type") == 0) {
+ std::cerr << "Error: type must be specified" << std::endl;
+ return 1;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ Name zoneName(zoneStr);
+ Name label(rrLabelStr);
+ name::Component type(rrTypeStr);
+
+ if (ndnsTypeStr.empty()) {
+ if (rrTypeStr == "NS" || rrTypeStr == "TXT")
+ ndnsTypeStr = "resp";
+ else if (rrTypeStr == "ID-CERT") {
+ ndnsTypeStr = "raw";
+ }
+ else {
+ std::cerr << "Error: content type needs to be explicitly set using --content-type option"
+ << std::endl;
+ return 1;
+ }
+ }
+ NdnsType ndnsType = ndns::toNdnsType(ndnsTypeStr);
+ time::seconds ttl;
+ if (ttlInt == -1)
+ ttl = ndns::DEFAULT_CACHE_TTL;
+ else
+ ttl = time::seconds(ttlInt);
+ uint64_t version = static_cast<uint64_t>(versionInt);
+
+ ndn::ndns::ManagementTool tool(db);
+ tool.addRrSet(zoneName, label, type, ndnsType, version, content, dsk, ttl);
+
+ /// @todo Report success or failure
+ // May be also show the inserted record in ndns-list-zone format
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}
diff --git a/tools/ndns-create-zone.cpp b/tools/ndns-create-zone.cpp
new file mode 100644
index 0000000..0893bc7
--- /dev/null
+++ b/tools/ndns-create-zone.cpp
@@ -0,0 +1,133 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include "config.hpp"
+
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ ndn::ndns::log::init();
+ int cacheTtlInt = -1;
+ int certTtlInt = -1;
+ string zoneStr;
+ string parentStr;
+ string dskStr;
+ string kskStr;
+ string db;
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database. "
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db")
+ ;
+
+ po::options_description config("Zone Options");
+ config.add_options()
+ ("cacheTtl,a", po::value<int>(&cacheTtlInt), "Set ttl of records of the zone and its "
+ "DSK ID-CERT. Default: 3600 seconds")
+ ("certTtl,e", po::value<int>(&certTtlInt), "Set ttl of DSK and KSK certificates. "
+ "Default: 365 days")
+ ("parent,p", po::value<std::string>(&parentStr), "Set the parent zone of the zone to be "
+ "created. Default: the zone's direct parent")
+ ("dsk,d", po::value<std::string>(&dskStr), "Set the name of DSK's certificate, "
+ "Default: generate new key and certificate")
+ ("ksk,k", po::value<std::string>(&kskStr), "Set the name of KSK's certificate, "
+ "Default: generate new key and certificate")
+ ;
+
+ options.add(config);
+
+ po::options_description hidden("Hidden Options");
+ hidden.add_options()
+ ("zone", po::value<string>(&zoneStr), "name of the zone to be created")
+ ;
+ po::positional_options_description postion;
+ postion.add("zone", 1);
+
+ po::options_description cmdline_options;
+ cmdline_options.add(options).add(hidden);
+
+ // po::options_description config_file_options;
+ // config_file_options.add(config).add(hidden);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdline_options).positional(postion).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-create-zone [-b db] zone [-a cacheTtl] [-e certTtl] [-p parent] "
+ "[-d dskCert] [-k kskCert]" << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ if (vm.count("zone") == 0) {
+ std::cerr << "Error: zone must be specified" << std::endl;
+ return 1;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ Name zone(zoneStr);
+ Name parent(parentStr);
+ if (!zone.empty() && parentStr.empty())
+ parent = zone.getPrefix(-1);
+
+ Name ksk(kskStr);
+ Name dsk(dskStr);
+
+ time::seconds cacheTtl;
+ time::seconds certTtl;
+ if (cacheTtlInt == -1)
+ cacheTtl = ndns::DEFAULT_CACHE_TTL;
+ else
+ cacheTtl = time::seconds(cacheTtlInt);
+
+ if (certTtlInt == -1)
+ certTtl = ndns::DEFAULT_CERT_TTL;
+ else
+ certTtl = time::seconds(certTtlInt);
+
+ ndn::ndns::ManagementTool tool(db);
+ tool.createZone(zone, parent, cacheTtl, certTtl, ksk, dsk);
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}
diff --git a/tools/ndns-delete-zone.cpp b/tools/ndns-delete-zone.cpp
new file mode 100644
index 0000000..12bc7f3
--- /dev/null
+++ b/tools/ndns-delete-zone.cpp
@@ -0,0 +1,88 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ ndn::ndns::log::init();
+ string zoneStr;
+ string db;
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database."
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db")
+ ;
+
+ po::options_description hidden("Hidden Options");
+ hidden.add_options()
+ ("zone", po::value<string>(&zoneStr), "name of the zone to be deleted")
+ ;
+ po::positional_options_description postion;
+ postion.add("zone", 1);
+
+ po::options_description cmdline_options;
+ cmdline_options.add(options).add(hidden);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdline_options).positional(postion).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-delete-zone zone [-b db]" << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ if (vm.count("zone") == 0) {
+ std::cerr << "Error: zone must be specified" << std::endl;
+ return 1;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ Name zone(zoneStr);
+
+ ndn::ndns::ManagementTool tool(db);
+ tool.deleteZone(zone);
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}
diff --git a/tools/ndns-export-certificate.cpp b/tools/ndns-export-certificate.cpp
new file mode 100644
index 0000000..701aa20
--- /dev/null
+++ b/tools/ndns-export-certificate.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ using namespace ndns;
+
+ ndn::ndns::log::init();
+ string certStr;
+ string db;
+ string output = "-";
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database. "
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db");
+
+ po::options_description config("Output Options");
+ config.add_options()
+ ("output,o", po::value<string>(&output), "Set the output path of the to be export cert. "
+ "Default: stdout(-)")
+ ;
+
+ options.add(config);
+
+ po::options_description hidden("Hidden Options");
+ hidden.add_options()
+ ("certName", po::value<string>(&certStr), "the name of the certificate")
+ ;
+
+ po::positional_options_description postion;
+ postion.add("certName", 1);
+
+ po::options_description cmdline_options;
+ cmdline_options.add(options).add(hidden);
+
+ // po::options_description config_file_options;
+ // config_file_options.add(config).add(hidden);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdline_options).positional(postion).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-export-certificate [-b db] certificateName [-o output] "
+ << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ if (vm.count("certName") == 0) {
+ std::cerr << "Error: certificate name must be specified" << std::endl;
+ return 1;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ Name certName(certStr);
+
+ ndn::ndns::ManagementTool tool(db);
+ tool.exportCertificate(certName, output);
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}
diff --git a/tools/ndns-get-rr.cpp b/tools/ndns-get-rr.cpp
new file mode 100644
index 0000000..bdf86e0
--- /dev/null
+++ b/tools/ndns-get-rr.cpp
@@ -0,0 +1,109 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ using namespace ndns;
+
+ ndn::ndns::log::init();
+ string zoneStr;
+ string db;
+ string rrLabelStr;
+ string rrTypeStr;
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database. "
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db")
+ ;
+
+ po::options_description hidden("Hidden Options");
+ hidden.add_options()
+ ("zone", po::value<string>(&zoneStr), "host zone name")
+ ("label", po::value<string>(&rrLabelStr), "label of the resource record.")
+ ("type", po::value<string>(&rrTypeStr), "type of the resource record.")
+ ;
+
+ po::positional_options_description postion;
+ postion.add("zone", 1);
+ postion.add("label", 1);
+ postion.add("type", 1);
+
+ po::options_description cmdline_options;
+ cmdline_options.add(options).add(hidden);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdline_options).positional(postion).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-get-rr zone label type [-b db]" << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ if (vm.count("zone") == 0) {
+ std::cerr << "Error: zone must be specified" << std::endl;
+ return 1;
+ }
+
+ if (vm.count("label") == 0) {
+ std::cerr << "Error: label must be specified" << std::endl;
+ return 1;
+ }
+
+ if (vm.count("type") == 0) {
+ std::cerr << "Error: type must be specified" << std::endl;
+ return 1;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ Name zoneName(zoneStr);
+ Name label(rrLabelStr);
+ name::Component type(rrTypeStr);
+
+ ndn::ndns::ManagementTool tool(db);
+ tool.getRrSet(zoneName, label, type, std::cout);
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}
diff --git a/tools/ndns-list-all-zones.cpp b/tools/ndns-list-all-zones.cpp
new file mode 100644
index 0000000..98c33f3
--- /dev/null
+++ b/tools/ndns-list-all-zones.cpp
@@ -0,0 +1,80 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+#include <iostream>
+
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ using namespace ndns;
+
+ ndn::ndns::log::init();
+ string zoneStr;
+ string db;
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database. "
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db")
+ ;
+
+ po::positional_options_description postion;
+ postion.add("zone", 1);
+
+ po::options_description cmdline_options;
+ cmdline_options.add(options);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdline_options).positional(postion).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-list-all-zones [-b db]" << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ ndn::ndns::ManagementTool tool(db);
+ tool.listAllZones(std::cout);
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}
diff --git a/tools/ndns-list-zone.cpp b/tools/ndns-list-zone.cpp
new file mode 100644
index 0000000..f1a85a2
--- /dev/null
+++ b/tools/ndns-list-zone.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+#include <iostream>
+
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ using namespace ndns;
+
+ ndn::ndns::log::init();
+ string zoneStr;
+ string db;
+ bool printRaw = false;
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database. "
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db");
+
+ po::options_description config("Output Options");
+ config.add_options()
+ ("printRaw,p", "Set to print raw data")
+ ;
+
+ options.add(config);
+
+ po::options_description hidden("Hidden Options");
+ hidden.add_options()
+ ("zone", po::value<string>(&zoneStr), "zone name to investigate")
+ ;
+
+ po::positional_options_description positional;
+ positional.add("zone", 1);
+
+ po::options_description cmdlineOptions;
+ cmdlineOptions.add(options).add(hidden);
+
+ // po::options_description config_file_options;
+ // config_file_options.add(config).add(hidden);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdlineOptions).positional(positional).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-list-zone zone [-b db] [-p printRaw]" << std::endl
+ << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ if (vm.count("zone") == 0) {
+ std::cerr << "Error: zone must be specified" << std::endl;
+ return 1;
+ }
+
+ if (vm.count("printRaw") != 0) {
+ printRaw = true;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ Name zoneName(zoneStr);
+
+ ndn::ndns::ManagementTool tool(db);
+ tool.listZone(zoneName, std::cout, printRaw);
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}
diff --git a/tools/ndns-remove-rr.cpp b/tools/ndns-remove-rr.cpp
new file mode 100644
index 0000000..a3fdf89
--- /dev/null
+++ b/tools/ndns-remove-rr.cpp
@@ -0,0 +1,115 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mgmt/management-tool.hpp"
+#include "ndns-label.hpp"
+#include "logger.hpp"
+#include <boost/program_options.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+
+int
+main(int argc, char* argv[])
+{
+ using std::string;
+ using namespace ndn;
+ using namespace ndns;
+
+ ndn::ndns::log::init();
+ string zoneStr;
+ string db;
+ string rrLabelStr;
+ string rrTypeStr;
+ try {
+ namespace po = boost::program_options;
+ po::variables_map vm;
+
+ po::options_description options("Generic Options");
+ options.add_options()
+ ("help,h", "print help message")
+ ("db,b", po::value<std::string>(&db), "Set the path of NDNS server database. "
+ "Default: " DEFAULT_DATABASE_PATH "/ndns.db");
+
+ po::options_description hidden("Hidden Options");
+ hidden.add_options()
+ ("zone", po::value<string>(&zoneStr), "host zone name")
+ ("label", po::value<string>(&rrLabelStr), "label of the resource record.")
+ ("type", po::value<string>(&rrTypeStr), "type of the resource record.")
+ ;
+
+ po::positional_options_description positional;
+ positional.add("zone", 1);
+ positional.add("label", 1);
+ positional.add("type", 1);
+
+ po::options_description cmdlineOptions;
+ cmdlineOptions.add(options).add(hidden);
+
+ // po::options_description configFileOptions;
+ // config_file_options.add(config).add(hidden);
+
+ po::parsed_options parsed =
+ po::command_line_parser(argc, argv).options(cmdlineOptions).positional(positional).run();
+
+ po::store(parsed, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << "Usage: ndns-remove-rr [-b db] zone label type" << std::endl
+ << std::endl;
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ if (vm.count("zone") == 0) {
+ std::cerr << "Error: zone, label, and type must be specified" << std::endl;
+ return 1;
+ }
+
+ if (vm.count("label") == 0) {
+ std::cerr << "Error: label and type must be specified" << std::endl;
+ return 1;
+ }
+
+ if (vm.count("type") == 0) {
+ std::cerr << "Error: type must be specified" << std::endl;
+ return 1;
+ }
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Parameter Error: " << ex.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ Name zoneName(zoneStr);
+ Name label(rrLabelStr);
+ name::Component type(rrTypeStr);
+
+ ndn::ndns::ManagementTool tool(db);
+ tool.removeRrSet(zoneName, label, type);
+
+ /// @todo Report how many records have been removed
+ // (or that the record was removed or record wasn't found)
+ }
+ catch (const std::exception& ex) {
+ std::cerr << "Error: " << ex.what() << std::endl;
+ return 1;
+ }
+}