blob: e74c6010485d57c05fc6f6df55a5d08711b86dbf [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>
Alexander Afanasyevd091e312017-06-13 11:04:47 -070036#include <ndn-cxx/security/v1/cryptopp.hpp>
Yumin Xia5dd9f2b2016-10-26 20:48:05 -070037#include <ndn-cxx/link.hpp>
Yumin Xiac5ed63f2017-01-26 13:44:38 -080038#include <ndn-cxx/security/signing-helpers.hpp>
Jiewen Tan870b29b2014-11-17 19:09:49 -080039
40namespace ndn {
41namespace ndns {
42
Alexander Afanasyevc7c99002015-10-09 17:27:30 -070043NDNS_LOG_INIT("ManagementTool")
Jiewen Tan870b29b2014-11-17 19:09:49 -080044
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -080045ManagementTool::ManagementTool(const std::string& dbFile, KeyChain& keyChain)
46 : m_keyChain(keyChain)
47 , m_dbMgr(dbFile)
Jiewen Tan870b29b2014-11-17 19:09:49 -080048{
49}
50
51void
52ManagementTool::createZone(const Name &zoneName,
53 const Name& parentZoneName,
54 const time::seconds& cacheTtl,
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -080055 const time::seconds& certValidity,
Jiewen Tan870b29b2014-11-17 19:09:49 -080056 const Name& kskCertName,
57 const Name& dskCertName)
58{
59 bool isRoot = zoneName == ROOT_ZONE;
60
61 //check preconditions
62 Zone zone(zoneName, cacheTtl);
63 if (m_dbMgr.find(zone)) {
64 throw Error(zoneName.toUri() + " is already presented in the NDNS db");
65 }
66
67 if (!isRoot && parentZoneName.equals(zoneName)) {
68 throw Error("Parent zone name can not be the zone itself");
69 }
70
71 if (!isRoot && !parentZoneName.isPrefixOf(zoneName)) {
72 throw Error(parentZoneName.toUri() + " is not a prefix of " + zoneName.toUri());
73 }
74
Jiewen Tan01693fd2015-03-25 20:34:45 -070075 // if dsk is provided, there is no need to check ksk
Jiewen Tan870b29b2014-11-17 19:09:49 -080076 if (dskCertName != DEFAULT_CERT) {
77 if (!matchCertificate(dskCertName, zoneName)) {
78 throw Error("Cannot verify DSK certificate");
79 }
80 }
Jiewen Tan01693fd2015-03-25 20:34:45 -070081 else if (kskCertName != DEFAULT_CERT) {
82 if (!matchCertificate(kskCertName, zoneName)) {
83 throw Error("Cannot verify KSK certificate");
84 }
85 }
Jiewen Tan870b29b2014-11-17 19:09:49 -080086
87 if (kskCertName == DEFAULT_CERT && isRoot) {
88 throw Error("Cannot generate KSK for root zone");
89 }
90
91 //first generate KSK and DSK to the keyChain system, and add DSK as default
92 NDNS_LOG_INFO("Start generating KSK and DSK and their corresponding certificates");
Jiewen Tan870b29b2014-11-17 19:09:49 -080093 Name dskName;
94 shared_ptr<IdentityCertificate> dskCert;
95 if (dskCertName == DEFAULT_CERT) {
Jiewen Tan01693fd2015-03-25 20:34:45 -070096 // if no dsk provided, then generate a dsk either signed by ksk auto generated or user provided
97 time::system_clock::TimePoint notBefore = time::system_clock::now();
98 time::system_clock::TimePoint notAfter = notBefore + certValidity;
99 shared_ptr<IdentityCertificate> kskCert;
100
101 if (kskCertName == DEFAULT_CERT) {
102 //create KSK's certificate
103 Name kskName = m_keyChain.generateRsaKeyPair(zoneName, true);
104 std::vector<CertificateSubjectDescription> kskDesc;
105 kskCert = m_keyChain.prepareUnsignedIdentityCertificate(kskName, zoneName, notBefore,
106 notAfter, kskDesc, parentZoneName);
107 kskCert->setFreshnessPeriod(cacheTtl);
108
109 m_keyChain.selfSign(*kskCert);
110 m_keyChain.addCertificate(*kskCert);
111 NDNS_LOG_INFO("Generated KSK: " << kskCert->getName());
112 }
113 else {
114 kskCert = m_keyChain.getCertificate(kskCertName);
115 }
116
Jiewen Tan870b29b2014-11-17 19:09:49 -0800117 dskName = m_keyChain.generateRsaKeyPairAsDefault(zoneName, false);
118 //create DSK's certificate
119 std::vector<CertificateSubjectDescription> dskDesc;
120 dskCert = m_keyChain.prepareUnsignedIdentityCertificate(dskName, zoneName, notBefore, notAfter,
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800121 dskDesc, zoneName);
122 dskCert->setFreshnessPeriod(cacheTtl);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800123 m_keyChain.sign(*dskCert, kskCert->getName());
124 m_keyChain.addCertificateAsKeyDefault(*dskCert);
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800125 NDNS_LOG_INFO("Generated DSK: " << dskCert->getName());
Jiewen Tan870b29b2014-11-17 19:09:49 -0800126 }
127 else {
128 dskCert = m_keyChain.getCertificate(dskCertName);
129 dskName = dskCert->getPublicKeyName();
130 m_keyChain.setDefaultKeyNameForIdentity(dskName);
131 m_keyChain.setDefaultCertificateNameForKey(dskCert->getName());
132 }
133
134 //second add zone to the database
135 NDNS_LOG_INFO("Start adding new zone to data base");
136 addZone(zone);
137
138 //third create ID-cert
139 NDNS_LOG_INFO("Start creating DSK's ID-CERT");
140 addIdCert(zone, dskCert, cacheTtl);
141}
142
143void
144ManagementTool::deleteZone(const Name& zoneName)
145{
146 //check pre-conditions
147 Zone zone(zoneName);
148 if (!m_dbMgr.find(zone)) {
149 throw Error(zoneName.toUri() + " is not presented in the NDNS db");
150 }
151
152 //first remove all rrsets of this zone from local ndns database
153 std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
154 for (Rrset& rrset : rrsets) {
155 m_dbMgr.remove(rrset);
156 }
157
158 //second remove zone from local ndns database
159 removeZone(zone);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800160}
161
162void
163ManagementTool::exportCertificate(const Name& certName, const std::string& outFile)
164{
165 //search for the certificate, start from KeyChain then local NDNS database
166 shared_ptr<IdentityCertificate> cert;
167 if (m_keyChain.doesCertificateExist(certName)) {
168 cert = m_keyChain.getCertificate(certName);
169 }
170 else {
171 shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
172 if (regex->match(certName) != true) {
173 throw Error("Certificate name is illegal");
174 }
175 Name zoneName = regex->expand("\\1");
176 Name label = regex->expand("\\2");
177
178 Zone zone(zoneName);
179 Rrset rrset(&zone);
180 rrset.setLabel(label);
181 rrset.setType(label::CERT_RR_TYPE);
182 if (m_dbMgr.find(rrset)) {
183 Data data(rrset.getData());
184 cert = make_shared<IdentityCertificate>(data);
185 }
186 else {
187 throw Error("Cannot find the cert: " + certName.toUri());
188 }
189 }
190
191 if (outFile == DEFAULT_IO) {
192 ndn::io::save(*cert, std::cout);
193 }
194 else {
195 ndn::io::save(*cert, outFile);
196 NDNS_LOG_INFO("save cert to file: " << outFile);
197 }
198}
199
200void
Yumin Xiaacd21332016-11-28 22:54:48 -0800201ManagementTool::addMultiLevelLabelRrset(Rrset& rrset,
202 RrsetFactory& zoneRrFactory,
203 const time::seconds& authTtl)
204{
205 const Name& label = rrset.getLabel();
206
207 // Check whether it is legal to insert the rrset
208 for (size_t i = 1; i <= label.size() - 1; i++) {
209 Name prefix = label.getPrefix(i);
210 Rrset prefixNsRr(rrset.getZone());
211 prefixNsRr.setLabel(prefix);
212 prefixNsRr.setType(label::NS_RR_TYPE);
213 if (m_dbMgr.find(prefixNsRr)) {
214 Data data(prefixNsRr.getData());
215 if (data.getContentType() == NDNS_LINK) {
216 BOOST_THROW_EXCEPTION(Error("Cannot override " + boost::lexical_cast<std::string>(prefixNsRr) + " (NDNS_LINK)"));
217 }
218 }
219 }
220
221 // check that it does not override existing AUTH
222 if (rrset.getType() == label::NS_RR_TYPE) {
223 Rrset rrsetCopy = rrset;
224 if (m_dbMgr.find(rrsetCopy)) {
225 if (Data(rrsetCopy.getData()).getContentType() == NDNS_AUTH) {
226 BOOST_THROW_EXCEPTION(Error("Cannot override " + boost::lexical_cast<std::string>(rrsetCopy) + " (NDNS_AUTH)"));
227 }
228 }
229 }
230
231 for (size_t i = 1; i <= label.size() - 1; i++) {
232 Name prefix = label.getPrefix(i);
233 Rrset prefixNsRr(rrset.getZone());
234 prefixNsRr.setLabel(prefix);
235 prefixNsRr.setType(label::NS_RR_TYPE);
236 if (m_dbMgr.find(prefixNsRr)) {
237 NDNS_LOG_INFO("NDNS_AUTH Rrset Label=" << prefix << " is already existed, insertion skipped");
238 continue;
239 }
240
241 Rrset authRr = zoneRrFactory.generateAuthRrset(prefix, label::NS_RR_TYPE,
242 VERSION_USE_UNIX_TIMESTAMP, authTtl);
243 NDNS_LOG_INFO("Adding NDNS_AUTH " << authRr);
244 m_dbMgr.insert(authRr);
245 }
246
247 checkRrsetVersion(rrset);
248 NDNS_LOG_INFO("Adding " << rrset);
249 m_dbMgr.insert(rrset);
250}
251
252void
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700253ManagementTool::addRrset(Rrset& rrset)
Jiewen Tan870b29b2014-11-17 19:09:49 -0800254{
Yumin Xiaacd21332016-11-28 22:54:48 -0800255 if (rrset.getLabel().size() > 1) {
256 throw Error("Cannot add rrset with label size > 1, should use addMultiLevelLabelRrset instead");
257 }
258
259 // check that it does not override existing AUTH
260 Rrset rrsetCopy = rrset;
261 rrsetCopy.setType(label::NS_RR_TYPE);
262 if (m_dbMgr.find(rrsetCopy)) {
263 if (Data(rrsetCopy.getData()).getContentType() == NDNS_AUTH) {
264 BOOST_THROW_EXCEPTION(Error("Can not add this Rrset: it overrides a NDNS_AUTH record"));
265 }
266 }
267
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700268 checkRrsetVersion(rrset);
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800269 NDNS_LOG_INFO("Added " << rrset);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800270 m_dbMgr.insert(rrset);
271}
272
273void
Yumin Xiac5ed63f2017-01-26 13:44:38 -0800274ManagementTool::addRrsetFromFile(const Name& zoneName,
275 const std::string& inFile,
276 const time::seconds& ttl,
277 const Name& inputDskCertName,
278 const ndn::io::IoEncoding encoding,
279 bool needResign)
Jiewen Tan870b29b2014-11-17 19:09:49 -0800280{
281 //check precondition
282 Zone zone(zoneName);
283 if (!m_dbMgr.find(zone)) {
284 throw Error(zoneName.toUri() + " is not presented in the NDNS db");
285 }
286
287 Name dskName;
288 Name dskCertName = inputDskCertName;
289 if (dskCertName == DEFAULT_CERT) {
290 dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
291 dskCertName = m_keyChain.getDefaultCertificateNameForKey(dskName);
292 }
293 else {
294 if (!matchCertificate(dskCertName, zoneName)) {
295 throw Error("Cannot verify certificate");
296 }
297 }
298
299 if (inFile != DEFAULT_IO) {
300 boost::filesystem::path dir = boost::filesystem::path(inFile);
301 if (!boost::filesystem::exists(dir) || boost::filesystem::is_directory(dir)) {
302 throw Error("Data: " + inFile + " does not exist");
303 }
304 }
305
Yumin Xiac5ed63f2017-01-26 13:44:38 -0800306 // load data
Jiewen Tan870b29b2014-11-17 19:09:49 -0800307 shared_ptr<Data> data;
308 if (inFile == DEFAULT_IO)
Jiewen Tan74d745c2015-03-20 01:40:41 -0700309 data = ndn::io::load<ndn::Data>(std::cin, encoding);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800310 else
Jiewen Tan74d745c2015-03-20 01:40:41 -0700311 data = ndn::io::load<ndn::Data>(inFile, encoding);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800312
Jiewen Tand2d21822015-03-19 15:37:03 -0700313 if (data == nullptr) {
Jiewen Tan74d745c2015-03-20 01:40:41 -0700314 throw Error("input does not contain a valid Data packet");
Jiewen Tand2d21822015-03-19 15:37:03 -0700315 }
316
Yumin Xiac5ed63f2017-01-26 13:44:38 -0800317 if (needResign) {
318 m_keyChain.sign(*data, signingByCertificate(dskCertName));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800319 }
320
321 // create response for the input data
322 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700323 re.fromData(zoneName, *data);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800324 Name label = re.getRrLabel();
325 name::Component type = re.getRrType();
326
327 Rrset rrset(&zone);
328 rrset.setLabel(label);
329 rrset.setType(type);
330 if (ttl == DEFAULT_RR_TTL)
331 rrset.setTtl(zone.getTtl());
332 else
333 rrset.setTtl(ttl);
334 rrset.setVersion(re.getVersion());
335 rrset.setData(data->wireEncode());
336
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700337 checkRrsetVersion(rrset);
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800338 NDNS_LOG_INFO("Added " << rrset);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800339 m_dbMgr.insert(rrset);
340}
341
342void
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800343ManagementTool::listZone(const Name& zoneName, std::ostream& os, const bool printRaw)
344{
Jiewen Tan870b29b2014-11-17 19:09:49 -0800345 Zone zone(zoneName);
346 if (!m_dbMgr.find(zone)) {
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800347 throw Error("Zone " + zoneName.toUri() + " is not found in the database");
Jiewen Tan870b29b2014-11-17 19:09:49 -0800348 }
349
350 //first output the zone name
351 os << "; Zone " << zoneName.toUri() << std::endl << std::endl;
352
353 //second output all rrsets
354 std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
355
356 //set width for different columns
357 size_t labelWidth = 0;
358 size_t ttlWidth = 0;
359 size_t typeWidth = 0;
360 for (Rrset& rrset : rrsets) {
361 Data data(rrset.getData());
362 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700363 re.fromData(zoneName, data);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800364
365 if (rrset.getLabel().toUri().size() > labelWidth)
366 labelWidth = rrset.getLabel().toUri().size();
367
368 std::stringstream seconds;
369 seconds << rrset.getTtl().count();
370 if (seconds.str().size() > ttlWidth)
371 ttlWidth = seconds.str().size();
372
373 if (rrset.getType().toUri().size() > typeWidth)
374 typeWidth = rrset.getType().toUri().size();
375 }
376
377 //output
378 for (Rrset& rrset : rrsets) {
379 Data data(rrset.getData());
380 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700381 re.fromData(zoneName, data);
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800382 int iteration = re.getContentType() == NDNS_BLOB
383 || re.getContentType() == NDNS_KEY
384 || re.getContentType() == NDNS_AUTH ? 1 : re.getRrs().size();
385
Jiewen Tan870b29b2014-11-17 19:09:49 -0800386 const std::vector<Block> &rrs = re.getRrs();
387
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800388 if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800389 os << "; rrset=" << rrset.getLabel().toUri()
390 << " type=" << rrset.getType().toUri()
391 << " version=" << rrset.getVersion().toUri()
392 << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri()
393 << std::endl;
394 }
395
396 for (int i = 0; i < iteration; i++) {
397 os.setf(os.left);
398 os.width(labelWidth + 2);
399 os << rrset.getLabel().toUri();
400
401 os.width(ttlWidth + 2);
402 os << rrset.getTtl().count();
403
404 os.width(typeWidth + 2);
405 os << rrset.getType().toUri();
406
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800407 if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800408 using namespace CryptoPP;
409 if (rrset.getType() == label::TXT_RR_TYPE) {
410 os.write(reinterpret_cast<const char*>(rrs[i].value()), rrs[i].value_size());
411 os << std::endl;
412 }
413 else if (rrset.getType() == label::NS_RR_TYPE) {
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700414 BOOST_ASSERT(iteration == 1);
Yumin Xiaa484ba72016-11-10 20:40:12 -0800415 if (re.getContentType() == NDNS_AUTH) {
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700416 const std::string authStr = "NDNS-Auth";
417 os << authStr;
418 } else {
419 Link link(rrset.getData());
420 const Link::DelegationSet& ds = link.getDelegations();
421 for (const auto& i: ds) {
422 std::string str = boost::lexical_cast<std::string>(i.first)
423 + "," + i.second.toUri() + ";";
424 os << str;
425 }
426 }
Jiewen Tan870b29b2014-11-17 19:09:49 -0800427 os << std::endl;
428 }
429 else {
430 StringSource ss(rrs[i].wire(), rrs[i].size(), true,
431 new Base64Encoder(new FileSink(os), true, 64));
432 }
433 }
434 }
435
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800436 if (re.getContentType() == NDNS_BLOB || re.getContentType() == NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800437 os.width();
Yumin Xiaa484ba72016-11-10 20:40:12 -0800438 os << "; content-type=" << re.getContentType()
Jiewen Tan870b29b2014-11-17 19:09:49 -0800439 << " version=" << rrset.getVersion().toUri()
440 << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri();
441 os << std::endl;
442
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800443 if (printRaw && (re.getContentType() == NDNS_BLOB
444 || re.getContentType() == NDNS_KEY)) {
Jiewen Tand1dd86d2015-03-20 10:26:28 -0700445 util::IndentedStream istream(os, "; ");
Jiewen Tan870b29b2014-11-17 19:09:49 -0800446
Jiewen Tand1dd86d2015-03-20 10:26:28 -0700447 if (re.getRrType() == label::CERT_RR_TYPE) {
448 shared_ptr<Data> data = re.toData();
449 IdentityCertificate cert(*data);
450 cert.printCertificate(istream);
451 }
452 else {
453 using namespace CryptoPP;
454 StringSource ss(re.getAppContent().wire(), re.getAppContent().size(), true,
455 new Base64Encoder(new FileSink(istream), true, 64));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800456 }
Jiewen Tan870b29b2014-11-17 19:09:49 -0800457 }
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800458 os << std::endl;
Jiewen Tan870b29b2014-11-17 19:09:49 -0800459 }
460 else {
461 os << std::endl;
462 }
463 }
464}
465
466void
467ManagementTool::listAllZones(std::ostream& os) {
468 std::vector<Zone> zones = m_dbMgr.listZones();
469
470 size_t nameWidth = 0;
471 for (const Zone& zone : zones) {
472 if (zone.getName().toUri().size() > nameWidth)
473 nameWidth = zone.getName().toUri().size();
474 }
475
476 for (const Zone& zone : zones) {
477 os.setf(os.left);
478 os.width(nameWidth + 2);
479 os << zone.getName().toUri();
480
481 os << "; default-ttl=" << zone.getTtl().count();
482 os << " default-key=" << m_keyChain.getDefaultKeyNameForIdentity(zone.getName());
483 os << " default-certificate="
484 << m_keyChain.getDefaultCertificateNameForIdentity(zone.getName());
485 os << std::endl;
486 }
487}
488
489void
490ManagementTool::removeRrSet(const Name& zoneName, const Name& label, const name::Component& type)
491{
492 Zone zone(zoneName);
493 Rrset rrset(&zone);
494 rrset.setLabel(label);
495 rrset.setType(type);
496
497 if (!m_dbMgr.find(rrset)) {
498 return;
499 }
500 NDNS_LOG_INFO("Remove rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
501 << type);
502 m_dbMgr.remove(rrset);
503}
504
505void
506ManagementTool::getRrSet(const Name& zoneName,
507 const Name& label,
508 const name::Component& type,
509 std::ostream& os)
510{
511 Zone zone(zoneName);
512 Rrset rrset(&zone);
513 rrset.setLabel(label);
514 rrset.setType(type);
515
516 if (!m_dbMgr.find(rrset)) {
517 os << "No record is found" << std::endl;
518 return;
519 }
520
521 using namespace CryptoPP;
522 StringSource ss(rrset.getData().wire(), rrset.getData().size(), true,
523 new Base64Encoder(new FileSink(os), true, 64));
524}
525
526void
527ManagementTool::addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert,
528 const time::seconds& ttl)
529{
530 Rrset rrset(&zone);
531 size_t size = zone.getName().size();
532 Name label = cert->getName().getSubName(size + 1, cert->getName().size() - size - 3);
533 rrset.setLabel(label);
534 rrset.setType(label::CERT_RR_TYPE);
535 rrset.setTtl(ttl);
536 rrset.setVersion(cert->getName().get(-1));
537 rrset.setData(cert->wireEncode());
538
539 if (m_dbMgr.find(rrset)) {
540 throw Error("ID-CERT with label=" + label.toUri() +
541 " is already presented in local NDNS databse");
542 }
543 NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
544 << label::CERT_RR_TYPE);
545 m_dbMgr.insert(rrset);
546}
547
548void
549ManagementTool::addZone(Zone& zone)
550{
551 if (m_dbMgr.find(zone)) {
552 throw Error("Zone with Name=" + zone.getName().toUri() +
553 " is already presented in local NDNS databse");
554 }
555 NDNS_LOG_INFO("Add zone with Name: " << zone.getName().toUri());
556 m_dbMgr.insert(zone);
557}
558
559void
560ManagementTool::removeZone(Zone& zone)
561{
562 if (!m_dbMgr.find(zone)) {
563 return;
564 }
565 NDNS_LOG_INFO("Remove zone with Name: " << zone.getName().toUri());
566 m_dbMgr.remove(zone);
567}
568
569bool
570ManagementTool::matchCertificate(const Name& certName, const Name& identity)
571{
572 if (!m_keyChain.doesCertificateExist(certName)) {
573 NDNS_LOG_WARN(certName.toUri() << " is not presented in KeyChain");
574 return false;
575 }
576
577 //check its public key information
578 shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(certName);
579 Name keyName = cert->getPublicKeyName();
580
581 if (!identity.isPrefixOf(keyName) || identity.size()!=keyName.size()-1) {
582 NDNS_LOG_WARN(keyName.toUri() << " is not a key of " << identity.toUri());
583 return false;
584 }
585
Alexander Afanasyev74975e12016-08-01 14:24:03 -0700586 if (!m_keyChain.doesKeyExistInTpm(keyName, KeyClass::PRIVATE)) {
587 NDNS_LOG_WARN("Private key: " << keyName.toUri() << " is not present in KeyChain");
Jiewen Tan870b29b2014-11-17 19:09:49 -0800588 return false;
589 }
590
591 return true;
592}
593
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700594void
595ManagementTool::checkRrsetVersion(const Rrset& rrset)
596{
597 Rrset originalRrset(rrset);
598 if (m_dbMgr.find(originalRrset)) {
599 // update only if rrset has a newer version
600 if (originalRrset.getVersion() == rrset.getVersion()) {
601 throw Error("Duplicate: " + boost::lexical_cast<std::string>(originalRrset));
602 }
603 else if (originalRrset.getVersion() > rrset.getVersion()) {
604 throw Error("Newer version exists: " + boost::lexical_cast<std::string>(originalRrset));
605 }
606
607 m_dbMgr.remove(originalRrset);
608 }
609}
610
Jiewen Tan870b29b2014-11-17 19:09:49 -0800611} // namespace ndns
612} // namespace ndn