blob: b2f9d44ce9ef5ffae1cbffb87d22fcdc02fd6600 [file] [log] [blame]
Jiewen Tan870b29b2014-11-17 19:09:49 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Yumin Xiaacd21332016-11-28 22:54:48 -08003 * Copyright (c) 2014-2017, Regents of the University of California.
Jiewen Tan870b29b2014-11-17 19:09:49 -08004 *
5 * This file is part of NDNS (Named Data Networking Domain Name Service).
6 * See AUTHORS.md for complete list of NDNS authors and contributors.
7 *
8 * NDNS is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "management-tool.hpp"
21#include "logger.hpp"
22#include "ndns-label.hpp"
23#include "ndns-tlv.hpp"
24
25#include <string>
26#include <iomanip>
27
28#include <boost/filesystem/operations.hpp>
29#include <boost/filesystem/path.hpp>
30#include <boost/algorithm/string/replace.hpp>
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -080031#include <boost/lexical_cast.hpp>
Jiewen Tan870b29b2014-11-17 19:09:49 -080032
Jiewen Tan870b29b2014-11-17 19:09:49 -080033#include <ndn-cxx/util/regex.hpp>
Jiewen Tand1dd86d2015-03-20 10:26:28 -070034#include <ndn-cxx/util/indented-stream.hpp>
Jiewen Tan870b29b2014-11-17 19:09:49 -080035#include <ndn-cxx/encoding/oid.hpp>
36#include <ndn-cxx/security/cryptopp.hpp>
Yumin Xia5dd9f2b2016-10-26 20:48:05 -070037#include <ndn-cxx/link.hpp>
Jiewen Tan870b29b2014-11-17 19:09:49 -080038
39namespace ndn {
40namespace ndns {
41
Alexander Afanasyevc7c99002015-10-09 17:27:30 -070042NDNS_LOG_INIT("ManagementTool")
Jiewen Tan870b29b2014-11-17 19:09:49 -080043
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -080044ManagementTool::ManagementTool(const std::string& dbFile, KeyChain& keyChain)
45 : m_keyChain(keyChain)
46 , m_dbMgr(dbFile)
Jiewen Tan870b29b2014-11-17 19:09:49 -080047{
48}
49
50void
51ManagementTool::createZone(const Name &zoneName,
52 const Name& parentZoneName,
53 const time::seconds& cacheTtl,
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -080054 const time::seconds& certValidity,
Jiewen Tan870b29b2014-11-17 19:09:49 -080055 const Name& kskCertName,
56 const Name& dskCertName)
57{
58 bool isRoot = zoneName == ROOT_ZONE;
59
60 //check preconditions
61 Zone zone(zoneName, cacheTtl);
62 if (m_dbMgr.find(zone)) {
63 throw Error(zoneName.toUri() + " is already presented in the NDNS db");
64 }
65
66 if (!isRoot && parentZoneName.equals(zoneName)) {
67 throw Error("Parent zone name can not be the zone itself");
68 }
69
70 if (!isRoot && !parentZoneName.isPrefixOf(zoneName)) {
71 throw Error(parentZoneName.toUri() + " is not a prefix of " + zoneName.toUri());
72 }
73
Jiewen Tan01693fd2015-03-25 20:34:45 -070074 // if dsk is provided, there is no need to check ksk
Jiewen Tan870b29b2014-11-17 19:09:49 -080075 if (dskCertName != DEFAULT_CERT) {
76 if (!matchCertificate(dskCertName, zoneName)) {
77 throw Error("Cannot verify DSK certificate");
78 }
79 }
Jiewen Tan01693fd2015-03-25 20:34:45 -070080 else if (kskCertName != DEFAULT_CERT) {
81 if (!matchCertificate(kskCertName, zoneName)) {
82 throw Error("Cannot verify KSK certificate");
83 }
84 }
Jiewen Tan870b29b2014-11-17 19:09:49 -080085
86 if (kskCertName == DEFAULT_CERT && isRoot) {
87 throw Error("Cannot generate KSK for root zone");
88 }
89
90 //first generate KSK and DSK to the keyChain system, and add DSK as default
91 NDNS_LOG_INFO("Start generating KSK and DSK and their corresponding certificates");
Jiewen Tan870b29b2014-11-17 19:09:49 -080092 Name dskName;
93 shared_ptr<IdentityCertificate> dskCert;
94 if (dskCertName == DEFAULT_CERT) {
Jiewen Tan01693fd2015-03-25 20:34:45 -070095 // if no dsk provided, then generate a dsk either signed by ksk auto generated or user provided
96 time::system_clock::TimePoint notBefore = time::system_clock::now();
97 time::system_clock::TimePoint notAfter = notBefore + certValidity;
98 shared_ptr<IdentityCertificate> kskCert;
99
100 if (kskCertName == DEFAULT_CERT) {
101 //create KSK's certificate
102 Name kskName = m_keyChain.generateRsaKeyPair(zoneName, true);
103 std::vector<CertificateSubjectDescription> kskDesc;
104 kskCert = m_keyChain.prepareUnsignedIdentityCertificate(kskName, zoneName, notBefore,
105 notAfter, kskDesc, parentZoneName);
106 kskCert->setFreshnessPeriod(cacheTtl);
107
108 m_keyChain.selfSign(*kskCert);
109 m_keyChain.addCertificate(*kskCert);
110 NDNS_LOG_INFO("Generated KSK: " << kskCert->getName());
111 }
112 else {
113 kskCert = m_keyChain.getCertificate(kskCertName);
114 }
115
Jiewen Tan870b29b2014-11-17 19:09:49 -0800116 dskName = m_keyChain.generateRsaKeyPairAsDefault(zoneName, false);
117 //create DSK's certificate
118 std::vector<CertificateSubjectDescription> dskDesc;
119 dskCert = m_keyChain.prepareUnsignedIdentityCertificate(dskName, zoneName, notBefore, notAfter,
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800120 dskDesc, zoneName);
121 dskCert->setFreshnessPeriod(cacheTtl);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800122 m_keyChain.sign(*dskCert, kskCert->getName());
123 m_keyChain.addCertificateAsKeyDefault(*dskCert);
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800124 NDNS_LOG_INFO("Generated DSK: " << dskCert->getName());
Jiewen Tan870b29b2014-11-17 19:09:49 -0800125 }
126 else {
127 dskCert = m_keyChain.getCertificate(dskCertName);
128 dskName = dskCert->getPublicKeyName();
129 m_keyChain.setDefaultKeyNameForIdentity(dskName);
130 m_keyChain.setDefaultCertificateNameForKey(dskCert->getName());
131 }
132
133 //second add zone to the database
134 NDNS_LOG_INFO("Start adding new zone to data base");
135 addZone(zone);
136
137 //third create ID-cert
138 NDNS_LOG_INFO("Start creating DSK's ID-CERT");
139 addIdCert(zone, dskCert, cacheTtl);
140}
141
142void
143ManagementTool::deleteZone(const Name& zoneName)
144{
145 //check pre-conditions
146 Zone zone(zoneName);
147 if (!m_dbMgr.find(zone)) {
148 throw Error(zoneName.toUri() + " is not presented in the NDNS db");
149 }
150
151 //first remove all rrsets of this zone from local ndns database
152 std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
153 for (Rrset& rrset : rrsets) {
154 m_dbMgr.remove(rrset);
155 }
156
157 //second remove zone from local ndns database
158 removeZone(zone);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800159}
160
161void
162ManagementTool::exportCertificate(const Name& certName, const std::string& outFile)
163{
164 //search for the certificate, start from KeyChain then local NDNS database
165 shared_ptr<IdentityCertificate> cert;
166 if (m_keyChain.doesCertificateExist(certName)) {
167 cert = m_keyChain.getCertificate(certName);
168 }
169 else {
170 shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
171 if (regex->match(certName) != true) {
172 throw Error("Certificate name is illegal");
173 }
174 Name zoneName = regex->expand("\\1");
175 Name label = regex->expand("\\2");
176
177 Zone zone(zoneName);
178 Rrset rrset(&zone);
179 rrset.setLabel(label);
180 rrset.setType(label::CERT_RR_TYPE);
181 if (m_dbMgr.find(rrset)) {
182 Data data(rrset.getData());
183 cert = make_shared<IdentityCertificate>(data);
184 }
185 else {
186 throw Error("Cannot find the cert: " + certName.toUri());
187 }
188 }
189
190 if (outFile == DEFAULT_IO) {
191 ndn::io::save(*cert, std::cout);
192 }
193 else {
194 ndn::io::save(*cert, outFile);
195 NDNS_LOG_INFO("save cert to file: " << outFile);
196 }
197}
198
199void
Yumin Xiaacd21332016-11-28 22:54:48 -0800200ManagementTool::addMultiLevelLabelRrset(Rrset& rrset,
201 RrsetFactory& zoneRrFactory,
202 const time::seconds& authTtl)
203{
204 const Name& label = rrset.getLabel();
205
206 // Check whether it is legal to insert the rrset
207 for (size_t i = 1; i <= label.size() - 1; i++) {
208 Name prefix = label.getPrefix(i);
209 Rrset prefixNsRr(rrset.getZone());
210 prefixNsRr.setLabel(prefix);
211 prefixNsRr.setType(label::NS_RR_TYPE);
212 if (m_dbMgr.find(prefixNsRr)) {
213 Data data(prefixNsRr.getData());
214 if (data.getContentType() == NDNS_LINK) {
215 BOOST_THROW_EXCEPTION(Error("Cannot override " + boost::lexical_cast<std::string>(prefixNsRr) + " (NDNS_LINK)"));
216 }
217 }
218 }
219
220 // check that it does not override existing AUTH
221 if (rrset.getType() == label::NS_RR_TYPE) {
222 Rrset rrsetCopy = rrset;
223 if (m_dbMgr.find(rrsetCopy)) {
224 if (Data(rrsetCopy.getData()).getContentType() == NDNS_AUTH) {
225 BOOST_THROW_EXCEPTION(Error("Cannot override " + boost::lexical_cast<std::string>(rrsetCopy) + " (NDNS_AUTH)"));
226 }
227 }
228 }
229
230 for (size_t i = 1; i <= label.size() - 1; i++) {
231 Name prefix = label.getPrefix(i);
232 Rrset prefixNsRr(rrset.getZone());
233 prefixNsRr.setLabel(prefix);
234 prefixNsRr.setType(label::NS_RR_TYPE);
235 if (m_dbMgr.find(prefixNsRr)) {
236 NDNS_LOG_INFO("NDNS_AUTH Rrset Label=" << prefix << " is already existed, insertion skipped");
237 continue;
238 }
239
240 Rrset authRr = zoneRrFactory.generateAuthRrset(prefix, label::NS_RR_TYPE,
241 VERSION_USE_UNIX_TIMESTAMP, authTtl);
242 NDNS_LOG_INFO("Adding NDNS_AUTH " << authRr);
243 m_dbMgr.insert(authRr);
244 }
245
246 checkRrsetVersion(rrset);
247 NDNS_LOG_INFO("Adding " << rrset);
248 m_dbMgr.insert(rrset);
249}
250
251void
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700252ManagementTool::addRrset(Rrset& rrset)
Jiewen Tan870b29b2014-11-17 19:09:49 -0800253{
Yumin Xiaacd21332016-11-28 22:54:48 -0800254 if (rrset.getLabel().size() > 1) {
255 throw Error("Cannot add rrset with label size > 1, should use addMultiLevelLabelRrset instead");
256 }
257
258 // check that it does not override existing AUTH
259 Rrset rrsetCopy = rrset;
260 rrsetCopy.setType(label::NS_RR_TYPE);
261 if (m_dbMgr.find(rrsetCopy)) {
262 if (Data(rrsetCopy.getData()).getContentType() == NDNS_AUTH) {
263 BOOST_THROW_EXCEPTION(Error("Can not add this Rrset: it overrides a NDNS_AUTH record"));
264 }
265 }
266
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700267 checkRrsetVersion(rrset);
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800268 NDNS_LOG_INFO("Added " << rrset);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800269 m_dbMgr.insert(rrset);
270}
271
272void
273ManagementTool::addRrSet(const Name& zoneName,
274 const std::string& inFile,
275 const time::seconds& ttl,
Jiewen Tan74d745c2015-03-20 01:40:41 -0700276 const Name& inputDskCertName,
277 const ndn::io::IoEncoding encoding)
Jiewen Tan870b29b2014-11-17 19:09:49 -0800278{
279 //check precondition
280 Zone zone(zoneName);
281 if (!m_dbMgr.find(zone)) {
282 throw Error(zoneName.toUri() + " is not presented in the NDNS db");
283 }
284
285 Name dskName;
286 Name dskCertName = inputDskCertName;
287 if (dskCertName == DEFAULT_CERT) {
288 dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
289 dskCertName = m_keyChain.getDefaultCertificateNameForKey(dskName);
290 }
291 else {
292 if (!matchCertificate(dskCertName, zoneName)) {
293 throw Error("Cannot verify certificate");
294 }
295 }
296
297 if (inFile != DEFAULT_IO) {
298 boost::filesystem::path dir = boost::filesystem::path(inFile);
299 if (!boost::filesystem::exists(dir) || boost::filesystem::is_directory(dir)) {
300 throw Error("Data: " + inFile + " does not exist");
301 }
302 }
303
304 //first load the data
305 shared_ptr<Data> data;
306 if (inFile == DEFAULT_IO)
Jiewen Tan74d745c2015-03-20 01:40:41 -0700307 data = ndn::io::load<ndn::Data>(std::cin, encoding);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800308 else
Jiewen Tan74d745c2015-03-20 01:40:41 -0700309 data = ndn::io::load<ndn::Data>(inFile, encoding);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800310
Jiewen Tand2d21822015-03-19 15:37:03 -0700311 if (data == nullptr) {
Jiewen Tan74d745c2015-03-20 01:40:41 -0700312 throw Error("input does not contain a valid Data packet");
Jiewen Tand2d21822015-03-19 15:37:03 -0700313 }
314
Alexander Afanasyevfde570c2016-12-19 16:02:55 -0800315 // determine whether the data is a self-signed certificate
Jiewen Tan870b29b2014-11-17 19:09:49 -0800316 shared_ptr<Regex> regex1 = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
317 if (regex1->match(data->getName())) {
318 IdentityCertificate scert(*data);
319 Name keyName = scert.getPublicKeyName();
Alexander Afanasyevfde570c2016-12-19 16:02:55 -0800320 if (keyName.getPrefix(zoneName.size()) != zoneName) {
321 throw Error("the input key does not belong to the zone");
322 }
323
Jiewen Tan870b29b2014-11-17 19:09:49 -0800324 Name keyLocator = scert.getSignature().getKeyLocator().getName();
325
Alexander Afanasyevfde570c2016-12-19 16:02:55 -0800326 // if it is, extract the content and name from the data, and resign it using the dsk.
Jiewen Tan870b29b2014-11-17 19:09:49 -0800327 shared_ptr<Regex> regex2 = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT>");
328 BOOST_VERIFY(regex2->match(keyLocator) == true);
329 if (keyName == regex2->expand("\\1\\2")) {
Alexander Afanasyevfde570c2016-12-19 16:02:55 -0800330
331 Name canonicalName;
332 canonicalName
333 .append(zoneName)
334 .append("KEY")
335 .append(keyName.getSubName(zoneName.size(), keyName.size() - zoneName.size()))
336 .append("ID-CERT")
337 .append(data->getName().get(-1));
338
339 if (data->getName() != canonicalName) {
340 // name need to be adjusted
341 auto newData = make_shared<Data>();
342 newData->setName(canonicalName);
343 newData->setMetaInfo(data->getMetaInfo());
344 newData->setContent(data->getContent());
345 m_keyChain.sign(*newData);
346
347 data = newData;
Jiewen Tan870b29b2014-11-17 19:09:49 -0800348 }
Jiewen Tan870b29b2014-11-17 19:09:49 -0800349 }
350 }
351
352 // create response for the input data
353 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700354 re.fromData(zoneName, *data);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800355 Name label = re.getRrLabel();
356 name::Component type = re.getRrType();
357
358 Rrset rrset(&zone);
359 rrset.setLabel(label);
360 rrset.setType(type);
361 if (ttl == DEFAULT_RR_TTL)
362 rrset.setTtl(zone.getTtl());
363 else
364 rrset.setTtl(ttl);
365 rrset.setVersion(re.getVersion());
366 rrset.setData(data->wireEncode());
367
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700368 checkRrsetVersion(rrset);
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800369 NDNS_LOG_INFO("Added " << rrset);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800370 m_dbMgr.insert(rrset);
371}
372
373void
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800374ManagementTool::listZone(const Name& zoneName, std::ostream& os, const bool printRaw)
375{
Jiewen Tan870b29b2014-11-17 19:09:49 -0800376 Zone zone(zoneName);
377 if (!m_dbMgr.find(zone)) {
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800378 throw Error("Zone " + zoneName.toUri() + " is not found in the database");
Jiewen Tan870b29b2014-11-17 19:09:49 -0800379 }
380
381 //first output the zone name
382 os << "; Zone " << zoneName.toUri() << std::endl << std::endl;
383
384 //second output all rrsets
385 std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
386
387 //set width for different columns
388 size_t labelWidth = 0;
389 size_t ttlWidth = 0;
390 size_t typeWidth = 0;
391 for (Rrset& rrset : rrsets) {
392 Data data(rrset.getData());
393 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700394 re.fromData(zoneName, data);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800395
396 if (rrset.getLabel().toUri().size() > labelWidth)
397 labelWidth = rrset.getLabel().toUri().size();
398
399 std::stringstream seconds;
400 seconds << rrset.getTtl().count();
401 if (seconds.str().size() > ttlWidth)
402 ttlWidth = seconds.str().size();
403
404 if (rrset.getType().toUri().size() > typeWidth)
405 typeWidth = rrset.getType().toUri().size();
406 }
407
408 //output
409 for (Rrset& rrset : rrsets) {
410 Data data(rrset.getData());
411 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700412 re.fromData(zoneName, data);
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800413 int iteration = re.getContentType() == NDNS_BLOB
414 || re.getContentType() == NDNS_KEY
415 || re.getContentType() == NDNS_AUTH ? 1 : re.getRrs().size();
416
Jiewen Tan870b29b2014-11-17 19:09:49 -0800417 const std::vector<Block> &rrs = re.getRrs();
418
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800419 if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800420 os << "; rrset=" << rrset.getLabel().toUri()
421 << " type=" << rrset.getType().toUri()
422 << " version=" << rrset.getVersion().toUri()
423 << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri()
424 << std::endl;
425 }
426
427 for (int i = 0; i < iteration; i++) {
428 os.setf(os.left);
429 os.width(labelWidth + 2);
430 os << rrset.getLabel().toUri();
431
432 os.width(ttlWidth + 2);
433 os << rrset.getTtl().count();
434
435 os.width(typeWidth + 2);
436 os << rrset.getType().toUri();
437
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800438 if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800439 using namespace CryptoPP;
440 if (rrset.getType() == label::TXT_RR_TYPE) {
441 os.write(reinterpret_cast<const char*>(rrs[i].value()), rrs[i].value_size());
442 os << std::endl;
443 }
444 else if (rrset.getType() == label::NS_RR_TYPE) {
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700445 BOOST_ASSERT(iteration == 1);
Yumin Xiaa484ba72016-11-10 20:40:12 -0800446 if (re.getContentType() == NDNS_AUTH) {
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700447 const std::string authStr = "NDNS-Auth";
448 os << authStr;
449 } else {
450 Link link(rrset.getData());
451 const Link::DelegationSet& ds = link.getDelegations();
452 for (const auto& i: ds) {
453 std::string str = boost::lexical_cast<std::string>(i.first)
454 + "," + i.second.toUri() + ";";
455 os << str;
456 }
457 }
Jiewen Tan870b29b2014-11-17 19:09:49 -0800458 os << std::endl;
459 }
460 else {
461 StringSource ss(rrs[i].wire(), rrs[i].size(), true,
462 new Base64Encoder(new FileSink(os), true, 64));
463 }
464 }
465 }
466
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800467 if (re.getContentType() == NDNS_BLOB || re.getContentType() == NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800468 os.width();
Yumin Xiaa484ba72016-11-10 20:40:12 -0800469 os << "; content-type=" << re.getContentType()
Jiewen Tan870b29b2014-11-17 19:09:49 -0800470 << " version=" << rrset.getVersion().toUri()
471 << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri();
472 os << std::endl;
473
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800474 if (printRaw && (re.getContentType() == NDNS_BLOB
475 || re.getContentType() == NDNS_KEY)) {
Jiewen Tand1dd86d2015-03-20 10:26:28 -0700476 util::IndentedStream istream(os, "; ");
Jiewen Tan870b29b2014-11-17 19:09:49 -0800477
Jiewen Tand1dd86d2015-03-20 10:26:28 -0700478 if (re.getRrType() == label::CERT_RR_TYPE) {
479 shared_ptr<Data> data = re.toData();
480 IdentityCertificate cert(*data);
481 cert.printCertificate(istream);
482 }
483 else {
484 using namespace CryptoPP;
485 StringSource ss(re.getAppContent().wire(), re.getAppContent().size(), true,
486 new Base64Encoder(new FileSink(istream), true, 64));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800487 }
Jiewen Tan870b29b2014-11-17 19:09:49 -0800488 }
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800489 os << std::endl;
Jiewen Tan870b29b2014-11-17 19:09:49 -0800490 }
491 else {
492 os << std::endl;
493 }
494 }
495}
496
497void
498ManagementTool::listAllZones(std::ostream& os) {
499 std::vector<Zone> zones = m_dbMgr.listZones();
500
501 size_t nameWidth = 0;
502 for (const Zone& zone : zones) {
503 if (zone.getName().toUri().size() > nameWidth)
504 nameWidth = zone.getName().toUri().size();
505 }
506
507 for (const Zone& zone : zones) {
508 os.setf(os.left);
509 os.width(nameWidth + 2);
510 os << zone.getName().toUri();
511
512 os << "; default-ttl=" << zone.getTtl().count();
513 os << " default-key=" << m_keyChain.getDefaultKeyNameForIdentity(zone.getName());
514 os << " default-certificate="
515 << m_keyChain.getDefaultCertificateNameForIdentity(zone.getName());
516 os << std::endl;
517 }
518}
519
520void
521ManagementTool::removeRrSet(const Name& zoneName, const Name& label, const name::Component& type)
522{
523 Zone zone(zoneName);
524 Rrset rrset(&zone);
525 rrset.setLabel(label);
526 rrset.setType(type);
527
528 if (!m_dbMgr.find(rrset)) {
529 return;
530 }
531 NDNS_LOG_INFO("Remove rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
532 << type);
533 m_dbMgr.remove(rrset);
534}
535
536void
537ManagementTool::getRrSet(const Name& zoneName,
538 const Name& label,
539 const name::Component& type,
540 std::ostream& os)
541{
542 Zone zone(zoneName);
543 Rrset rrset(&zone);
544 rrset.setLabel(label);
545 rrset.setType(type);
546
547 if (!m_dbMgr.find(rrset)) {
548 os << "No record is found" << std::endl;
549 return;
550 }
551
552 using namespace CryptoPP;
553 StringSource ss(rrset.getData().wire(), rrset.getData().size(), true,
554 new Base64Encoder(new FileSink(os), true, 64));
555}
556
557void
558ManagementTool::addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert,
559 const time::seconds& ttl)
560{
561 Rrset rrset(&zone);
562 size_t size = zone.getName().size();
563 Name label = cert->getName().getSubName(size + 1, cert->getName().size() - size - 3);
564 rrset.setLabel(label);
565 rrset.setType(label::CERT_RR_TYPE);
566 rrset.setTtl(ttl);
567 rrset.setVersion(cert->getName().get(-1));
568 rrset.setData(cert->wireEncode());
569
570 if (m_dbMgr.find(rrset)) {
571 throw Error("ID-CERT with label=" + label.toUri() +
572 " is already presented in local NDNS databse");
573 }
574 NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
575 << label::CERT_RR_TYPE);
576 m_dbMgr.insert(rrset);
577}
578
579void
580ManagementTool::addZone(Zone& zone)
581{
582 if (m_dbMgr.find(zone)) {
583 throw Error("Zone with Name=" + zone.getName().toUri() +
584 " is already presented in local NDNS databse");
585 }
586 NDNS_LOG_INFO("Add zone with Name: " << zone.getName().toUri());
587 m_dbMgr.insert(zone);
588}
589
590void
591ManagementTool::removeZone(Zone& zone)
592{
593 if (!m_dbMgr.find(zone)) {
594 return;
595 }
596 NDNS_LOG_INFO("Remove zone with Name: " << zone.getName().toUri());
597 m_dbMgr.remove(zone);
598}
599
600bool
601ManagementTool::matchCertificate(const Name& certName, const Name& identity)
602{
603 if (!m_keyChain.doesCertificateExist(certName)) {
604 NDNS_LOG_WARN(certName.toUri() << " is not presented in KeyChain");
605 return false;
606 }
607
608 //check its public key information
609 shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(certName);
610 Name keyName = cert->getPublicKeyName();
611
612 if (!identity.isPrefixOf(keyName) || identity.size()!=keyName.size()-1) {
613 NDNS_LOG_WARN(keyName.toUri() << " is not a key of " << identity.toUri());
614 return false;
615 }
616
Alexander Afanasyev74975e12016-08-01 14:24:03 -0700617 if (!m_keyChain.doesKeyExistInTpm(keyName, KeyClass::PRIVATE)) {
618 NDNS_LOG_WARN("Private key: " << keyName.toUri() << " is not present in KeyChain");
Jiewen Tan870b29b2014-11-17 19:09:49 -0800619 return false;
620 }
621
622 return true;
623}
624
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700625void
626ManagementTool::checkRrsetVersion(const Rrset& rrset)
627{
628 Rrset originalRrset(rrset);
629 if (m_dbMgr.find(originalRrset)) {
630 // update only if rrset has a newer version
631 if (originalRrset.getVersion() == rrset.getVersion()) {
632 throw Error("Duplicate: " + boost::lexical_cast<std::string>(originalRrset));
633 }
634 else if (originalRrset.getVersion() > rrset.getVersion()) {
635 throw Error("Newer version exists: " + boost::lexical_cast<std::string>(originalRrset));
636 }
637
638 m_dbMgr.remove(originalRrset);
639 }
640}
641
Jiewen Tan870b29b2014-11-17 19:09:49 -0800642} // namespace ndns
643} // namespace ndn