blob: 41e93a12add94f047b5a93fda19b16d0b299b1fd [file] [log] [blame]
Yumin Xiaf853ad72016-11-03 21:14:07 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yumin Xia2c509c22017-02-09 14:37:36 -08002/*
Junxiao Shi81e98762022-01-11 18:17:24 +00003 * Copyright (c) 2014-2022, Regents of the University of California.
Yumin Xiaf853ad72016-11-03 21:14:07 -07004 *
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 "rrset-factory.hpp"
21#include "mgmt/management-tool.hpp"
Yumin Xia2c509c22017-02-09 14:37:36 -080022#include "util/cert-helper.hpp"
23
24#include <ndn-cxx/security/signing-helpers.hpp>
Yumin Xiaf853ad72016-11-03 21:14:07 -070025
26#include <boost/algorithm/string/join.hpp>
27
28namespace ndn {
29namespace ndns {
30
Yumin Xiab87b9d92016-11-14 23:41:25 -080031RrsetFactory::RrsetFactory(const boost::filesystem::path& dbFile,
Yumin Xiaf853ad72016-11-03 21:14:07 -070032 const Name& zoneName,
33 KeyChain& keyChain,
34 const Name& inputDskCertName)
35 : m_keyChain(keyChain)
Yumin Xiab87b9d92016-11-14 23:41:25 -080036 , m_dbFile(dbFile.string())
Yumin Xiaf853ad72016-11-03 21:14:07 -070037 , m_zone(zoneName)
38 , m_dskCertName(inputDskCertName)
39 , m_checked(false)
40{
Yumin Xia918343d2017-03-17 19:04:55 -070041 Name identityName = Name(zoneName).append(label::NDNS_ITERATIVE_QUERY);
Yumin Xiaf853ad72016-11-03 21:14:07 -070042 if (m_dskCertName == DEFAULT_CERT) {
Yumin Xia2c509c22017-02-09 14:37:36 -080043 m_dskName = CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, identityName);
44 m_dskCertName = CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, identityName);
Yumin Xiaf853ad72016-11-03 21:14:07 -070045 }
46}
47
48void
49RrsetFactory::checkZoneKey()
50{
51 onlyCheckZone();
Yumin Xia918343d2017-03-17 19:04:55 -070052 Name zoneIdentityName = Name(m_zone.getName()).append(label::NDNS_ITERATIVE_QUERY);
Yumin Xiaf853ad72016-11-03 21:14:07 -070053 if (m_dskCertName != DEFAULT_CERT &&
Yumin Xia2c509c22017-02-09 14:37:36 -080054 !matchCertificate(m_dskCertName, zoneIdentityName)) {
Davide Pesavento948c50c2020-12-26 21:30:45 -050055 NDN_THROW(Error("Cannot verify certificate"));
Yumin Xiaf853ad72016-11-03 21:14:07 -070056 }
57}
58
59void
60RrsetFactory::onlyCheckZone()
61{
62 if (m_checked) {
Davide Pesavento98026122022-03-14 22:00:03 -040063 return;
Yumin Xiaf853ad72016-11-03 21:14:07 -070064 }
65 m_checked = true;
66
67 DbMgr dbMgr(m_dbFile);
68 const Name& zoneName = m_zone.getName();
69 if (!dbMgr.find(m_zone)) {
Davide Pesavento948c50c2020-12-26 21:30:45 -050070 NDN_THROW(Error(zoneName.toUri() + " is not presented in the NDNS db"));
Yumin Xiaf853ad72016-11-03 21:14:07 -070071 }
72}
73
Yumin Xiaf853ad72016-11-03 21:14:07 -070074std::pair<Rrset, Name>
75RrsetFactory::generateBaseRrset(const Name& label,
76 const name::Component& type,
Yumin Xia55a7cc42017-05-14 18:43:34 -070077 uint64_t version,
Yumin Xiaf853ad72016-11-03 21:14:07 -070078 const time::seconds& ttl)
79{
80 Rrset rrset(&m_zone);
81
82 rrset.setLabel(label);
83 rrset.setType(type);
84 rrset.setTtl(ttl);
85
Yumin Xiaf853ad72016-11-03 21:14:07 -070086 Name name;
87 name.append(m_zone.getName())
Yumin Xia918343d2017-03-17 19:04:55 -070088 .append(label::NDNS_ITERATIVE_QUERY)
Yumin Xiaf853ad72016-11-03 21:14:07 -070089 .append(label)
90 .append(type);
91
92 if (version != VERSION_USE_UNIX_TIMESTAMP) {
93 name.append(name::Component::fromVersion(version));
Yumin Xia2c509c22017-02-09 14:37:36 -080094 }
95 else {
Yumin Xiaf853ad72016-11-03 21:14:07 -070096 name.appendVersion();
97 }
98
99 rrset.setVersion(name.get(-1));
100
Davide Pesavento38fd3982022-04-18 22:22:02 -0400101 return {rrset, name};
Yumin Xiaf853ad72016-11-03 21:14:07 -0700102}
103
104bool
105RrsetFactory::matchCertificate(const Name& certName, const Name& identity)
106{
Yumin Xia2c509c22017-02-09 14:37:36 -0800107 try {
108 CertHelper::getCertificate(m_keyChain, identity, certName);
109 return true;
Davide Pesavento4a315b32018-11-24 14:32:19 -0500110 } catch (const ndn::security::Pib::Error&) {
Yumin Xiaf853ad72016-11-03 21:14:07 -0700111 return false;
112 }
Yumin Xiaf853ad72016-11-03 21:14:07 -0700113}
114
115Rrset
116RrsetFactory::generateNsRrset(const Name& label,
Yumin Xia55a7cc42017-05-14 18:43:34 -0700117 uint64_t version,
Yumin Xiaf853ad72016-11-03 21:14:07 -0700118 time::seconds ttl,
Junxiao Shi81e98762022-01-11 18:17:24 +0000119 std::vector<Name> delegations)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700120{
121 if (!m_checked) {
Davide Pesavento948c50c2020-12-26 21:30:45 -0500122 NDN_THROW(Error("You have to call checkZoneKey before call generate functions"));
Yumin Xiaf853ad72016-11-03 21:14:07 -0700123 }
124
125 if (ttl == DEFAULT_RR_TTL)
126 ttl = m_zone.getTtl();
127
Davide Pesavento38fd3982022-04-18 22:22:02 -0400128 auto [rrset, name] = generateBaseRrset(label, label::NS_RR_TYPE, version, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700129
130 Link link(name);
Junxiao Shi81e98762022-01-11 18:17:24 +0000131 link.setDelegationList(std::move(delegations));
Yumin Xiaa484ba72016-11-10 20:40:12 -0800132 setContentType(link, NDNS_LINK, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700133 sign(link);
134 rrset.setData(link.wireEncode());
135
136 return rrset;
137}
138
139Rrset
140RrsetFactory::generateTxtRrset(const Name& label,
Yumin Xia55a7cc42017-05-14 18:43:34 -0700141 uint64_t version,
Yumin Xiaf853ad72016-11-03 21:14:07 -0700142 time::seconds ttl,
143 const std::vector<std::string>& strings)
144{
145 if (!m_checked) {
Davide Pesavento948c50c2020-12-26 21:30:45 -0500146 NDN_THROW(Error("You have to call checkZoneKey before call generate functions"));
Yumin Xiaf853ad72016-11-03 21:14:07 -0700147 }
148
149 if (ttl == DEFAULT_RR_TTL)
150 ttl = m_zone.getTtl();
151
Davide Pesavento38fd3982022-04-18 22:22:02 -0400152 auto [rrset, name] = generateBaseRrset(label, label::TXT_RR_TYPE, version, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700153
154 std::vector<Block> rrs;
Davide Pesavento98026122022-03-14 22:00:03 -0400155 rrs.reserve(strings.size());
Yumin Xiaf853ad72016-11-03 21:14:07 -0700156 for (const auto& item : strings) {
Davide Pesavento38fd3982022-04-18 22:22:02 -0400157 rrs.push_back(makeStringBlock(ndns::tlv::RrData, item));
Yumin Xiaf853ad72016-11-03 21:14:07 -0700158 }
159
160 Data data(name);
161 data.setContent(wireEncode(rrs));
Yumin Xiaa484ba72016-11-10 20:40:12 -0800162 setContentType(data, NDNS_RESP, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700163 sign(data);
164 rrset.setData(data.wireEncode());
165
166 return rrset;
167}
168
169Rrset
170RrsetFactory::generateCertRrset(const Name& label,
Yumin Xia55a7cc42017-05-14 18:43:34 -0700171 uint64_t version,
Yumin Xiaf853ad72016-11-03 21:14:07 -0700172 time::seconds ttl,
Alexander Afanasyev60514ec2020-06-03 14:18:53 -0400173 const ndn::security::Certificate& cert)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700174{
175 if (!m_checked) {
Davide Pesavento948c50c2020-12-26 21:30:45 -0500176 NDN_THROW(Error("You have to call checkZoneKey before call generate functions"));
Yumin Xiaf853ad72016-11-03 21:14:07 -0700177 }
178
179 if (ttl == DEFAULT_RR_TTL)
180 ttl = m_zone.getTtl();
181
Davide Pesavento38fd3982022-04-18 22:22:02 -0400182 auto [rrset, name] = generateBaseRrset(label, label::APPCERT_RR_TYPE, version, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700183
184 Data data(name);
185 data.setContent(cert.wireEncode());
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800186 setContentType(data, NDNS_KEY, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700187 sign(data);
188 rrset.setData(data.wireEncode());
189
190 return rrset;
191}
192
Yumin Xiaacd21332016-11-28 22:54:48 -0800193Rrset
194RrsetFactory::generateAuthRrset(const Name& label,
Yumin Xia55a7cc42017-05-14 18:43:34 -0700195 uint64_t version,
Yumin Xiaacd21332016-11-28 22:54:48 -0800196 time::seconds ttl)
197{
198 if (!m_checked) {
Davide Pesavento948c50c2020-12-26 21:30:45 -0500199 NDN_THROW(Error("You have to call checkZoneKey before call generate functions"));
Yumin Xiaacd21332016-11-28 22:54:48 -0800200 }
201
202 if (ttl == DEFAULT_RR_TTL)
203 ttl = m_zone.getTtl();
204
Davide Pesavento38fd3982022-04-18 22:22:02 -0400205 auto [rrset, name] = generateBaseRrset(label, label::NS_RR_TYPE, version, ttl);
Yumin Xiaacd21332016-11-28 22:54:48 -0800206
207 Data data(name);
Yumin Xiaacd21332016-11-28 22:54:48 -0800208 setContentType(data, NDNS_AUTH, ttl);
209 sign(data);
210 rrset.setData(data.wireEncode());
211
212 return rrset;
213}
Yumin Xiaf853ad72016-11-03 21:14:07 -0700214
Yumin Xia55a7cc42017-05-14 18:43:34 -0700215Rrset
216RrsetFactory::generateDoeRrset(const Name& label,
217 uint64_t version,
218 time::seconds ttl,
219 const Name& lowerLabel,
220 const Name& upperLabel)
221{
222 if (!m_checked) {
Davide Pesavento948c50c2020-12-26 21:30:45 -0500223 NDN_THROW(Error("You have to call checkZoneKey before call generate functions"));
Yumin Xia55a7cc42017-05-14 18:43:34 -0700224 }
225
226 if (ttl == DEFAULT_RR_TTL)
227 ttl = m_zone.getTtl();
228
Davide Pesavento38fd3982022-04-18 22:22:02 -0400229 auto [rrset, name] = generateBaseRrset(label, label::DOE_RR_TYPE, version, ttl);
Yumin Xia55a7cc42017-05-14 18:43:34 -0700230
231 std::vector<Block> range;
232 range.push_back(lowerLabel.wireEncode());
233 range.push_back(upperLabel.wireEncode());
234
235 Data data(name);
236 data.setContent(wireEncode(range));
237
238 setContentType(data, NDNS_DOE, ttl);
239 sign(data);
240 rrset.setData(data.wireEncode());
241
242 return rrset;
243}
244
245
Yumin Xiaf853ad72016-11-03 21:14:07 -0700246void
247RrsetFactory::sign(Data& data)
248{
Yumin Xia2c509c22017-02-09 14:37:36 -0800249 m_keyChain.sign(data, signingByCertificate(m_dskCertName));
Yumin Xiaf853ad72016-11-03 21:14:07 -0700250}
251
252void
Yumin Xiaa484ba72016-11-10 20:40:12 -0800253RrsetFactory::setContentType(Data& data, NdnsContentType contentType,
254 const time::seconds& ttl)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700255{
Yumin Xiaa484ba72016-11-10 20:40:12 -0800256 data.setContentType(contentType);
257 data.setFreshnessPeriod(ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700258}
259
260template<encoding::Tag TAG>
Davide Pesavento98026122022-03-14 22:00:03 -0400261size_t
262RrsetFactory::wireEncode(EncodingImpl<TAG>& encoder, const std::vector<Block>& rrs) const
Yumin Xiaf853ad72016-11-03 21:14:07 -0700263{
264 // Content :: = CONTENT-TYPE TLV-LENGTH
265 // Block*
266
267 size_t totalLength = 0;
268 for (auto iter = rrs.rbegin(); iter != rrs.rend(); ++iter) {
Davide Pesavento98026122022-03-14 22:00:03 -0400269 totalLength += prependBlock(encoder, *iter);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700270 }
271
Davide Pesavento98026122022-03-14 22:00:03 -0400272 totalLength += encoder.prependVarNumber(totalLength);
273 totalLength += encoder.prependVarNumber(ndn::tlv::Content);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700274 return totalLength;
275}
276
Davide Pesavento98026122022-03-14 22:00:03 -0400277Block
Yumin Xiaf853ad72016-11-03 21:14:07 -0700278RrsetFactory::wireEncode(const std::vector<Block>& rrs) const
279{
280 EncodingEstimator estimator;
281 size_t estimatedSize = wireEncode(estimator, rrs);
282 EncodingBuffer buffer(estimatedSize, 0);
283 wireEncode(buffer, rrs);
284 return buffer.block();
285}
286
287std::vector<std::string>
288RrsetFactory::wireDecodeTxt(const Block& wire)
289{
290 std::vector<std::string> txts;
291 wire.parse();
Yumin Xiaa484ba72016-11-10 20:40:12 -0800292 for (const auto& e : wire.elements()) {
Davide Pesavento38fd3982022-04-18 22:22:02 -0400293 txts.emplace_back(reinterpret_cast<const char*>(e.value()), e.value_size());
Yumin Xiaf853ad72016-11-03 21:14:07 -0700294 }
Yumin Xiaf853ad72016-11-03 21:14:07 -0700295 return txts;
296}
297
Yumin Xiaf853ad72016-11-03 21:14:07 -0700298} // namespace ndns
299} // namespace ndn