blob: b0bd7b45bda3bfb4eb4aab50c5e3d5b1f2b41e06 [file] [log] [blame]
Jiewen Tan870b29b2014-11-17 19:09:49 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yumin Xia2c509c22017-02-09 14:37:36 -08002/*
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"
Yumin Xia2c509c22017-02-09 14:37:36 -080024#include "util/cert-helper.hpp"
Jiewen Tan870b29b2014-11-17 19:09:49 -080025
26#include <string>
27#include <iomanip>
28
29#include <boost/filesystem/operations.hpp>
30#include <boost/filesystem/path.hpp>
31#include <boost/algorithm/string/replace.hpp>
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -080032#include <boost/lexical_cast.hpp>
Jiewen Tan870b29b2014-11-17 19:09:49 -080033
Jiewen Tan870b29b2014-11-17 19:09:49 -080034#include <ndn-cxx/util/regex.hpp>
Jiewen Tand1dd86d2015-03-20 10:26:28 -070035#include <ndn-cxx/util/indented-stream.hpp>
Yumin Xia2c509c22017-02-09 14:37:36 -080036#include <ndn-cxx/util/io.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>
Yumin Xia2c509c22017-02-09 14:37:36 -080039#include <ndn-cxx/security/transform.hpp>
40
Jiewen Tan870b29b2014-11-17 19:09:49 -080041
42namespace ndn {
43namespace ndns {
44
Alexander Afanasyevc7c99002015-10-09 17:27:30 -070045NDNS_LOG_INIT("ManagementTool")
Jiewen Tan870b29b2014-11-17 19:09:49 -080046
Yumin Xia2c509c22017-02-09 14:37:36 -080047using security::transform::base64Encode;
48using security::transform::streamSink;
49using security::transform::bufferSource;
50using security::v2::Certificate;
51using security::Identity;
52using security::Key;
53
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -080054ManagementTool::ManagementTool(const std::string& dbFile, KeyChain& keyChain)
55 : m_keyChain(keyChain)
56 , m_dbMgr(dbFile)
Jiewen Tan870b29b2014-11-17 19:09:49 -080057{
58}
59
Yumin Xia2c509c22017-02-09 14:37:36 -080060Zone
61ManagementTool::createZone(const Name& zoneName,
Jiewen Tan870b29b2014-11-17 19:09:49 -080062 const Name& parentZoneName,
63 const time::seconds& cacheTtl,
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -080064 const time::seconds& certValidity,
Jiewen Tan870b29b2014-11-17 19:09:49 -080065 const Name& kskCertName,
Yumin Xia2c509c22017-02-09 14:37:36 -080066 const Name& dskCertName,
67 const Name& dkeyCertName)
Jiewen Tan870b29b2014-11-17 19:09:49 -080068{
69 bool isRoot = zoneName == ROOT_ZONE;
Yumin Xia918343d2017-03-17 19:04:55 -070070 Name zoneIdentityName = Name(zoneName).append(label::NDNS_ITERATIVE_QUERY);
Jiewen Tan870b29b2014-11-17 19:09:49 -080071
72 //check preconditions
73 Zone zone(zoneName, cacheTtl);
74 if (m_dbMgr.find(zone)) {
Yumin Xia2c509c22017-02-09 14:37:36 -080075 BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is already presented in the NDNS db"));
Jiewen Tan870b29b2014-11-17 19:09:49 -080076 }
77
78 if (!isRoot && parentZoneName.equals(zoneName)) {
Yumin Xia2c509c22017-02-09 14:37:36 -080079 BOOST_THROW_EXCEPTION(Error("Parent zone name can not be the zone itself"));
Jiewen Tan870b29b2014-11-17 19:09:49 -080080 }
81
82 if (!isRoot && !parentZoneName.isPrefixOf(zoneName)) {
Yumin Xia2c509c22017-02-09 14:37:36 -080083 BOOST_THROW_EXCEPTION(Error(parentZoneName.toUri() + " is not a prefix of " + zoneName.toUri()));
Jiewen Tan870b29b2014-11-17 19:09:49 -080084 }
85
Jiewen Tan01693fd2015-03-25 20:34:45 -070086 // if dsk is provided, there is no need to check ksk
Jiewen Tan870b29b2014-11-17 19:09:49 -080087 if (dskCertName != DEFAULT_CERT) {
Yumin Xia2c509c22017-02-09 14:37:36 -080088 if (!matchCertificate(dskCertName, zoneIdentityName)) {
89 BOOST_THROW_EXCEPTION(Error("Cannot verify DSK certificate"));
Jiewen Tan870b29b2014-11-17 19:09:49 -080090 }
91 }
Jiewen Tan01693fd2015-03-25 20:34:45 -070092 else if (kskCertName != DEFAULT_CERT) {
Yumin Xia2c509c22017-02-09 14:37:36 -080093 if (!matchCertificate(kskCertName, zoneIdentityName)) {
94 BOOST_THROW_EXCEPTION(Error("Cannot verify KSK certificate"));
Jiewen Tan01693fd2015-03-25 20:34:45 -070095 }
96 }
Jiewen Tan870b29b2014-11-17 19:09:49 -080097
Yumin Xia2c509c22017-02-09 14:37:36 -080098 if (dkeyCertName == DEFAULT_CERT && isRoot) {
99 BOOST_THROW_EXCEPTION(Error("Cannot generate dkey for root zone"));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800100 }
101
Yumin Xia2c509c22017-02-09 14:37:36 -0800102 // Generate a parentZone's identity to generate a D-Key.
103 // This D-key will be passed to parent zone and resigned.
104 Name dkeyIdentityName;
105 if (dkeyCertName == DEFAULT_CERT) {
Yumin Xia918343d2017-03-17 19:04:55 -0700106 dkeyIdentityName = Name(parentZoneName).append(label::NDNS_ITERATIVE_QUERY)
Yumin Xia2c509c22017-02-09 14:37:36 -0800107 .append(zoneName.getSubName(parentZoneName.size()));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800108 }
109 else {
Yumin Xia2c509c22017-02-09 14:37:36 -0800110 dkeyIdentityName = CertHelper::getIdentityNameFromCert(dkeyCertName);
111 }
112 NDNS_LOG_INFO("Generated D-Key's identityName: " + dkeyIdentityName.toUri());
113
114 Name dskName;
115 Key ksk;
116 Key dsk;
117 Key dkey;
118 Certificate dskCert;
119 Certificate kskCert;
120 Certificate dkeyCert;
121 Identity zoneIdentity = m_keyChain.createIdentity(zoneIdentityName);
122 Identity dkeyIdentity = m_keyChain.createIdentity(dkeyIdentityName);
123
124 if (dkeyCertName == DEFAULT_CERT) {
125 dkey = m_keyChain.createKey(dkeyIdentity);
126 m_keyChain.deleteCertificate(dkey, dkey.getDefaultCertificate().getName());
127
128 dkeyCert = CertHelper::createCertificate(m_keyChain, dkey, dkey, label::CERT_RR_TYPE.toUri(), time::days(90));
129 dkeyCert.setFreshnessPeriod(cacheTtl);
130 m_keyChain.addCertificate(dkey, dkeyCert);
131 NDNS_LOG_INFO("Generated DKEY: " << dkeyCert.getName());
132
133 }
134 else {
135 dkeyCert = CertHelper::getCertificate(m_keyChain, dkeyIdentityName, dkeyCertName);
136 dkey = dkeyIdentity.getKey(dkeyCert.getKeyName());
137 }
138
139 if (kskCertName == DEFAULT_CERT) {
140 ksk = m_keyChain.createKey(zoneIdentity);
141 // delete automatically generated certificates,
142 // because its issue is 'self' instead of CERT_RR_TYPE
143 m_keyChain.deleteCertificate(ksk, ksk.getDefaultCertificate().getName());
144 kskCert = CertHelper::createCertificate(m_keyChain, ksk, dkey, label::CERT_RR_TYPE.toUri(), time::days(90));
145 kskCert.setFreshnessPeriod(cacheTtl);
146 m_keyChain.addCertificate(ksk, kskCert);
147 NDNS_LOG_INFO("Generated KSK: " << kskCert.getName());
148 }
149 else {
150 // ksk usually might not be the default key of a zone
151 kskCert = CertHelper::getCertificate(m_keyChain, zoneIdentityName, kskCertName);
152 ksk = zoneIdentity.getKey(kskCert.getKeyName());
153 }
154
155 if (dskCertName == DEFAULT_CERT) {
156 // if no dsk provided, then generate a dsk either signed by ksk auto generated or user provided
157 dsk = m_keyChain.createKey(zoneIdentity);
158 m_keyChain.deleteCertificate(dsk, dsk.getDefaultCertificate().getName());
159 dskCert = CertHelper::createCertificate(m_keyChain, dsk, ksk, label::CERT_RR_TYPE.toUri(), certValidity);
160 dskCert.setFreshnessPeriod(cacheTtl);
161 // dskCert will become the default certificate, since the default cert has been deleted.
162 m_keyChain.addCertificate(dsk, dskCert);
163 m_keyChain.setDefaultKey(zoneIdentity, dsk);
164 NDNS_LOG_INFO("Generated DSK: " << dskCert.getName());
165 }
166 else {
167 dskCert = CertHelper::getCertificate(m_keyChain, zoneIdentityName, dskCertName);
168 dsk = zoneIdentity.getKey(dskCert.getKeyName());
169 m_keyChain.setDefaultKey(zoneIdentity, dsk);
170 m_keyChain.setDefaultCertificate(dsk, dskCert);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800171 }
172
173 //second add zone to the database
174 NDNS_LOG_INFO("Start adding new zone to data base");
175 addZone(zone);
176
177 //third create ID-cert
Yumin Xia2c509c22017-02-09 14:37:36 -0800178 NDNS_LOG_INFO("Start adding Certificates to NDNS database");
179 addIdCert(zone, kskCert, cacheTtl, dskCert);
180 addIdCert(zone, dskCert, cacheTtl, dskCert);
181
182 NDNS_LOG_INFO("Start saving KSK and DSK's id to ZoneInfo");
183 m_dbMgr.setZoneInfo(zone, "ksk", kskCert.wireEncode());
184 m_dbMgr.setZoneInfo(zone, "dsk", dskCert.wireEncode());
185
186 NDNS_LOG_INFO("Start saving DKEY certificate id to ZoneInfo");
187 m_dbMgr.setZoneInfo(zone, "dkey", dkeyCert.wireEncode());
188
189 return zone;
Jiewen Tan870b29b2014-11-17 19:09:49 -0800190}
191
192void
193ManagementTool::deleteZone(const Name& zoneName)
194{
195 //check pre-conditions
196 Zone zone(zoneName);
197 if (!m_dbMgr.find(zone)) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800198 BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is not presented in the NDNS db"));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800199 }
200
201 //first remove all rrsets of this zone from local ndns database
202 std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
203 for (Rrset& rrset : rrsets) {
204 m_dbMgr.remove(rrset);
205 }
206
207 //second remove zone from local ndns database
208 removeZone(zone);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800209}
210
211void
212ManagementTool::exportCertificate(const Name& certName, const std::string& outFile)
213{
Yumin Xia2c509c22017-02-09 14:37:36 -0800214 // only search in local NDNS database
215 security::v2::Certificate cert;
216 shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<NDNS>(<>+)<CERT><>");
217 if (!regex->match(certName)) {
218 BOOST_THROW_EXCEPTION(Error("Certificate name is illegal"));
219 return;
220 }
221
222 Name zoneName = regex->expand("\\1");
Yumin Xia918343d2017-03-17 19:04:55 -0700223 Name identityName = Name(zoneName).append(label::NDNS_ITERATIVE_QUERY);
Yumin Xia2c509c22017-02-09 14:37:36 -0800224 Name label = regex->expand("\\2");
225
226 Zone zone(zoneName);
227 Rrset rrset(&zone);
228 rrset.setLabel(label);
229 rrset.setType(label::CERT_RR_TYPE);
230 if (m_dbMgr.find(rrset)) {
231 cert = security::v2::Certificate(rrset.getData());
Jiewen Tan870b29b2014-11-17 19:09:49 -0800232 }
233 else {
Yumin Xia2c509c22017-02-09 14:37:36 -0800234 BOOST_THROW_EXCEPTION(Error("Cannot find the cert: " + certName.toUri()));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800235 }
236
237 if (outFile == DEFAULT_IO) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800238 ndn::io::save(cert, std::cout);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800239 }
240 else {
Yumin Xia2c509c22017-02-09 14:37:36 -0800241 ndn::io::save(cert, outFile);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800242 NDNS_LOG_INFO("save cert to file: " << outFile);
243 }
244}
245
246void
Yumin Xiaacd21332016-11-28 22:54:48 -0800247ManagementTool::addMultiLevelLabelRrset(Rrset& rrset,
248 RrsetFactory& zoneRrFactory,
249 const time::seconds& authTtl)
250{
251 const Name& label = rrset.getLabel();
252
253 // Check whether it is legal to insert the rrset
254 for (size_t i = 1; i <= label.size() - 1; i++) {
255 Name prefix = label.getPrefix(i);
256 Rrset prefixNsRr(rrset.getZone());
257 prefixNsRr.setLabel(prefix);
258 prefixNsRr.setType(label::NS_RR_TYPE);
259 if (m_dbMgr.find(prefixNsRr)) {
260 Data data(prefixNsRr.getData());
261 if (data.getContentType() == NDNS_LINK) {
262 BOOST_THROW_EXCEPTION(Error("Cannot override " + boost::lexical_cast<std::string>(prefixNsRr) + " (NDNS_LINK)"));
263 }
264 }
265 }
266
267 // check that it does not override existing AUTH
268 if (rrset.getType() == label::NS_RR_TYPE) {
269 Rrset rrsetCopy = rrset;
270 if (m_dbMgr.find(rrsetCopy)) {
271 if (Data(rrsetCopy.getData()).getContentType() == NDNS_AUTH) {
272 BOOST_THROW_EXCEPTION(Error("Cannot override " + boost::lexical_cast<std::string>(rrsetCopy) + " (NDNS_AUTH)"));
273 }
274 }
275 }
276
277 for (size_t i = 1; i <= label.size() - 1; i++) {
278 Name prefix = label.getPrefix(i);
279 Rrset prefixNsRr(rrset.getZone());
280 prefixNsRr.setLabel(prefix);
281 prefixNsRr.setType(label::NS_RR_TYPE);
282 if (m_dbMgr.find(prefixNsRr)) {
283 NDNS_LOG_INFO("NDNS_AUTH Rrset Label=" << prefix << " is already existed, insertion skipped");
284 continue;
285 }
286
287 Rrset authRr = zoneRrFactory.generateAuthRrset(prefix, label::NS_RR_TYPE,
288 VERSION_USE_UNIX_TIMESTAMP, authTtl);
289 NDNS_LOG_INFO("Adding NDNS_AUTH " << authRr);
290 m_dbMgr.insert(authRr);
291 }
292
293 checkRrsetVersion(rrset);
294 NDNS_LOG_INFO("Adding " << rrset);
295 m_dbMgr.insert(rrset);
296}
297
298void
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700299ManagementTool::addRrset(Rrset& rrset)
Jiewen Tan870b29b2014-11-17 19:09:49 -0800300{
Yumin Xiaacd21332016-11-28 22:54:48 -0800301 if (rrset.getLabel().size() > 1) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800302 BOOST_THROW_EXCEPTION(Error("Cannot add rrset with label size > 1, should use addMultiLevelLabelRrset instead"));
Yumin Xiaacd21332016-11-28 22:54:48 -0800303 }
304
305 // check that it does not override existing AUTH
306 Rrset rrsetCopy = rrset;
307 rrsetCopy.setType(label::NS_RR_TYPE);
308 if (m_dbMgr.find(rrsetCopy)) {
309 if (Data(rrsetCopy.getData()).getContentType() == NDNS_AUTH) {
310 BOOST_THROW_EXCEPTION(Error("Can not add this Rrset: it overrides a NDNS_AUTH record"));
311 }
312 }
313
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700314 checkRrsetVersion(rrset);
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800315 NDNS_LOG_INFO("Added " << rrset);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800316 m_dbMgr.insert(rrset);
317}
318
319void
Yumin Xiac5ed63f2017-01-26 13:44:38 -0800320ManagementTool::addRrsetFromFile(const Name& zoneName,
321 const std::string& inFile,
322 const time::seconds& ttl,
323 const Name& inputDskCertName,
324 const ndn::io::IoEncoding encoding,
325 bool needResign)
Jiewen Tan870b29b2014-11-17 19:09:49 -0800326{
327 //check precondition
328 Zone zone(zoneName);
Yumin Xia918343d2017-03-17 19:04:55 -0700329 Name zoneIdentityName = Name(zoneName).append(label::NDNS_ITERATIVE_QUERY);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800330 if (!m_dbMgr.find(zone)) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800331 BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is not presented in the NDNS db"));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800332 }
333
334 Name dskName;
335 Name dskCertName = inputDskCertName;
336 if (dskCertName == DEFAULT_CERT) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800337 dskName = CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, zoneIdentityName);
338 dskCertName = CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, zoneIdentityName);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800339 }
340 else {
Yumin Xia2c509c22017-02-09 14:37:36 -0800341 if (!matchCertificate(dskCertName, zoneIdentityName)) {
342 BOOST_THROW_EXCEPTION(Error("Cannot verify certificate"));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800343 }
344 }
345
346 if (inFile != DEFAULT_IO) {
347 boost::filesystem::path dir = boost::filesystem::path(inFile);
348 if (!boost::filesystem::exists(dir) || boost::filesystem::is_directory(dir)) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800349 BOOST_THROW_EXCEPTION(Error("Data: " + inFile + " does not exist"));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800350 }
351 }
352
Yumin Xiac5ed63f2017-01-26 13:44:38 -0800353 // load data
Jiewen Tan870b29b2014-11-17 19:09:49 -0800354 shared_ptr<Data> data;
355 if (inFile == DEFAULT_IO)
Jiewen Tan74d745c2015-03-20 01:40:41 -0700356 data = ndn::io::load<ndn::Data>(std::cin, encoding);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800357 else
Jiewen Tan74d745c2015-03-20 01:40:41 -0700358 data = ndn::io::load<ndn::Data>(inFile, encoding);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800359
Jiewen Tand2d21822015-03-19 15:37:03 -0700360 if (data == nullptr) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800361 BOOST_THROW_EXCEPTION(Error("input does not contain a valid Data packet"));
Jiewen Tand2d21822015-03-19 15:37:03 -0700362 }
363
Yumin Xiac5ed63f2017-01-26 13:44:38 -0800364 if (needResign) {
365 m_keyChain.sign(*data, signingByCertificate(dskCertName));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800366 }
367
368 // create response for the input data
369 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700370 re.fromData(zoneName, *data);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800371 Name label = re.getRrLabel();
372 name::Component type = re.getRrType();
373
374 Rrset rrset(&zone);
375 rrset.setLabel(label);
376 rrset.setType(type);
377 if (ttl == DEFAULT_RR_TTL)
378 rrset.setTtl(zone.getTtl());
379 else
380 rrset.setTtl(ttl);
381 rrset.setVersion(re.getVersion());
382 rrset.setData(data->wireEncode());
383
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700384 checkRrsetVersion(rrset);
Yumin Xia2c509c22017-02-09 14:37:36 -0800385 NDNS_LOG_INFO("Adding rrset from file " << rrset);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800386 m_dbMgr.insert(rrset);
387}
388
Yumin Xia2c509c22017-02-09 14:37:36 -0800389security::v2::Certificate
390ManagementTool::getZoneDkey(Zone& zone)
391{
392 std::map<std::string, Block> zoneInfo = m_dbMgr.getZoneInfo(zone);
393 return security::v2::Certificate(zoneInfo["dkey"]);
394}
395
Jiewen Tan870b29b2014-11-17 19:09:49 -0800396void
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800397ManagementTool::listZone(const Name& zoneName, std::ostream& os, const bool printRaw)
398{
Jiewen Tan870b29b2014-11-17 19:09:49 -0800399 Zone zone(zoneName);
400 if (!m_dbMgr.find(zone)) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800401 BOOST_THROW_EXCEPTION(Error("Zone " + zoneName.toUri() + " is not found in the database"));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800402 }
403
404 //first output the zone name
405 os << "; Zone " << zoneName.toUri() << std::endl << std::endl;
406
407 //second output all rrsets
408 std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
409
410 //set width for different columns
411 size_t labelWidth = 0;
412 size_t ttlWidth = 0;
413 size_t typeWidth = 0;
414 for (Rrset& rrset : rrsets) {
415 Data data(rrset.getData());
416 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700417 re.fromData(zoneName, data);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800418
419 if (rrset.getLabel().toUri().size() > labelWidth)
420 labelWidth = rrset.getLabel().toUri().size();
421
422 std::stringstream seconds;
423 seconds << rrset.getTtl().count();
424 if (seconds.str().size() > ttlWidth)
425 ttlWidth = seconds.str().size();
426
427 if (rrset.getType().toUri().size() > typeWidth)
428 typeWidth = rrset.getType().toUri().size();
429 }
430
431 //output
432 for (Rrset& rrset : rrsets) {
433 Data data(rrset.getData());
434 Response re;
Yumin Xia6343c5b2016-10-20 15:45:50 -0700435 re.fromData(zoneName, data);
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800436 int iteration = re.getContentType() == NDNS_BLOB
437 || re.getContentType() == NDNS_KEY
438 || re.getContentType() == NDNS_AUTH ? 1 : re.getRrs().size();
439
Yumin Xia2c509c22017-02-09 14:37:36 -0800440 const std::vector<Block>& rrs = re.getRrs();
Jiewen Tan870b29b2014-11-17 19:09:49 -0800441
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800442 if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800443 os << "; rrset=" << rrset.getLabel().toUri()
444 << " type=" << rrset.getType().toUri()
445 << " version=" << rrset.getVersion().toUri()
446 << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri()
447 << std::endl;
448 }
449
450 for (int i = 0; i < iteration; i++) {
451 os.setf(os.left);
452 os.width(labelWidth + 2);
453 os << rrset.getLabel().toUri();
454
455 os.width(ttlWidth + 2);
456 os << rrset.getTtl().count();
457
458 os.width(typeWidth + 2);
459 os << rrset.getType().toUri();
460
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800461 if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800462 if (rrset.getType() == label::TXT_RR_TYPE) {
463 os.write(reinterpret_cast<const char*>(rrs[i].value()), rrs[i].value_size());
464 os << std::endl;
465 }
466 else if (rrset.getType() == label::NS_RR_TYPE) {
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700467 BOOST_ASSERT(iteration == 1);
Yumin Xiaa484ba72016-11-10 20:40:12 -0800468 if (re.getContentType() == NDNS_AUTH) {
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700469 const std::string authStr = "NDNS-Auth";
470 os << authStr;
Yumin Xia2c509c22017-02-09 14:37:36 -0800471 }
472 else {
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700473 Link link(rrset.getData());
Yumin Xia2c509c22017-02-09 14:37:36 -0800474 const DelegationList& ds = link.getDelegationList();
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700475 for (const auto& i: ds) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800476 std::string str = std::to_string(i.preference);
477 + "," + i.name.toUri() + ";";
Yumin Xia5dd9f2b2016-10-26 20:48:05 -0700478 os << str;
479 }
480 }
Jiewen Tan870b29b2014-11-17 19:09:49 -0800481 os << std::endl;
482 }
483 else {
Yumin Xia2c509c22017-02-09 14:37:36 -0800484 bufferSource(rrs[i].wire(), rrs[i].size()) >> base64Encode() >> streamSink(os);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800485 }
486 }
487 }
488
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800489 if (re.getContentType() == NDNS_BLOB || re.getContentType() == NDNS_KEY) {
Jiewen Tan870b29b2014-11-17 19:09:49 -0800490 os.width();
Yumin Xiaa484ba72016-11-10 20:40:12 -0800491 os << "; content-type=" << re.getContentType()
Jiewen Tan870b29b2014-11-17 19:09:49 -0800492 << " version=" << rrset.getVersion().toUri()
493 << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri();
494 os << std::endl;
495
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800496 if (printRaw && (re.getContentType() == NDNS_BLOB
497 || re.getContentType() == NDNS_KEY)) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800498 ndn::util::IndentedStream istream(os, "; ");
Jiewen Tan870b29b2014-11-17 19:09:49 -0800499
Jiewen Tand1dd86d2015-03-20 10:26:28 -0700500 if (re.getRrType() == label::CERT_RR_TYPE) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800501 security::v2::Certificate cert(rrset.getData());
502 os << cert;
503 // cert.printCertificate(istream);
Jiewen Tand1dd86d2015-03-20 10:26:28 -0700504 }
505 else {
Yumin Xia2c509c22017-02-09 14:37:36 -0800506 bufferSource(re.getAppContent().wire(), re.getAppContent().size()) >> base64Encode() >> streamSink(os);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800507 }
Jiewen Tan870b29b2014-11-17 19:09:49 -0800508 }
Alexander Afanasyevd6b3bda2014-11-25 17:33:58 -0800509 os << std::endl;
Jiewen Tan870b29b2014-11-17 19:09:49 -0800510 }
511 else {
512 os << std::endl;
513 }
514 }
515}
516
517void
518ManagementTool::listAllZones(std::ostream& os) {
519 std::vector<Zone> zones = m_dbMgr.listZones();
520
521 size_t nameWidth = 0;
522 for (const Zone& zone : zones) {
523 if (zone.getName().toUri().size() > nameWidth)
524 nameWidth = zone.getName().toUri().size();
525 }
526
527 for (const Zone& zone : zones) {
528 os.setf(os.left);
529 os.width(nameWidth + 2);
530 os << zone.getName().toUri();
Yumin Xia918343d2017-03-17 19:04:55 -0700531 Name zoneIdentity = Name(zone.getName()).append(label::NDNS_ITERATIVE_QUERY);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800532
533 os << "; default-ttl=" << zone.getTtl().count();
Yumin Xia2c509c22017-02-09 14:37:36 -0800534 os << " default-key=" << CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, zoneIdentity);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800535 os << " default-certificate="
Yumin Xia2c509c22017-02-09 14:37:36 -0800536 << CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, zoneIdentity);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800537 os << std::endl;
538 }
539}
540
541void
542ManagementTool::removeRrSet(const Name& zoneName, const Name& label, const name::Component& type)
543{
544 Zone zone(zoneName);
545 Rrset rrset(&zone);
546 rrset.setLabel(label);
547 rrset.setType(type);
548
549 if (!m_dbMgr.find(rrset)) {
550 return;
551 }
552 NDNS_LOG_INFO("Remove rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
553 << type);
554 m_dbMgr.remove(rrset);
555}
556
557void
558ManagementTool::getRrSet(const Name& zoneName,
559 const Name& label,
560 const name::Component& type,
561 std::ostream& os)
562{
563 Zone zone(zoneName);
564 Rrset rrset(&zone);
565 rrset.setLabel(label);
566 rrset.setType(type);
567
568 if (!m_dbMgr.find(rrset)) {
569 os << "No record is found" << std::endl;
570 return;
571 }
572
Yumin Xia2c509c22017-02-09 14:37:36 -0800573 bufferSource(rrset.getData().wire(), rrset.getData().size()) >> base64Encode() >> streamSink(os);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800574}
575
576void
Yumin Xia2c509c22017-02-09 14:37:36 -0800577ManagementTool::addIdCert(Zone& zone, const Certificate& cert,
578 const time::seconds& ttl,
579 const Certificate& dskCert)
Jiewen Tan870b29b2014-11-17 19:09:49 -0800580{
Yumin Xia2c509c22017-02-09 14:37:36 -0800581 Rrset rrsetKey(&zone);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800582 size_t size = zone.getName().size();
Yumin Xia2c509c22017-02-09 14:37:36 -0800583 Name label = cert.getName().getSubName(size + 1, cert.getName().size() - size - 3);
584 rrsetKey.setLabel(label);
585 rrsetKey.setType(label::CERT_RR_TYPE);
586 rrsetKey.setTtl(ttl);
587 rrsetKey.setVersion(cert.getName().get(-1));
588 rrsetKey.setData(cert.wireEncode());
Jiewen Tan870b29b2014-11-17 19:09:49 -0800589
Yumin Xia2c509c22017-02-09 14:37:36 -0800590 if (m_dbMgr.find(rrsetKey)) {
591 BOOST_THROW_EXCEPTION(Error("CERT with label=" + label.toUri() +
592 " is already presented in local NDNS databse"));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800593 }
Yumin Xia2c509c22017-02-09 14:37:36 -0800594
595 m_dbMgr.insert(rrsetKey);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800596 NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
597 << label::CERT_RR_TYPE);
Jiewen Tan870b29b2014-11-17 19:09:49 -0800598}
599
600void
601ManagementTool::addZone(Zone& zone)
602{
603 if (m_dbMgr.find(zone)) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800604 BOOST_THROW_EXCEPTION(Error("Zone with Name=" + zone.getName().toUri() +
605 " is already presented in local NDNS databse"));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800606 }
607 NDNS_LOG_INFO("Add zone with Name: " << zone.getName().toUri());
608 m_dbMgr.insert(zone);
609}
610
611void
612ManagementTool::removeZone(Zone& zone)
613{
614 if (!m_dbMgr.find(zone)) {
615 return;
616 }
617 NDNS_LOG_INFO("Remove zone with Name: " << zone.getName().toUri());
618 m_dbMgr.remove(zone);
619}
620
621bool
622ManagementTool::matchCertificate(const Name& certName, const Name& identity)
623{
Yumin Xia2c509c22017-02-09 14:37:36 -0800624 security::Identity id = m_keyChain.getPib().getIdentity(identity);
625 for (const security::Key& key: id.getKeys()) {
626 try {
627 key.getCertificate(certName);
628 return true;
629 } catch (const std::exception&) {
630 }
Jiewen Tan870b29b2014-11-17 19:09:49 -0800631 }
Yumin Xia2c509c22017-02-09 14:37:36 -0800632 return false;
Jiewen Tan870b29b2014-11-17 19:09:49 -0800633}
634
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700635void
636ManagementTool::checkRrsetVersion(const Rrset& rrset)
637{
638 Rrset originalRrset(rrset);
639 if (m_dbMgr.find(originalRrset)) {
640 // update only if rrset has a newer version
641 if (originalRrset.getVersion() == rrset.getVersion()) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800642 BOOST_THROW_EXCEPTION(Error("Duplicate: "
643 + boost::lexical_cast<std::string>(originalRrset)));
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700644 }
645 else if (originalRrset.getVersion() > rrset.getVersion()) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800646 BOOST_THROW_EXCEPTION(Error("Newer version exists: "
647 + boost::lexical_cast<std::string>(originalRrset)));
Jiewen Tan8cd35ea2015-03-20 00:44:23 -0700648 }
649
650 m_dbMgr.remove(originalRrset);
651 }
652}
653
Jiewen Tan870b29b2014-11-17 19:09:49 -0800654} // namespace ndns
655} // namespace ndn