blob: da7ffde6a2f016fc096351671d6afe0dd0a7e576 [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/*
Yumin Xiaacd21332016-11-28 22:54:48 -08003 * Copyright (c) 2014-2017, 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
31NDNS_LOG_INIT("RrsetFactory")
32
Yumin Xiab87b9d92016-11-14 23:41:25 -080033RrsetFactory::RrsetFactory(const boost::filesystem::path& dbFile,
Yumin Xiaf853ad72016-11-03 21:14:07 -070034 const Name& zoneName,
35 KeyChain& keyChain,
36 const Name& inputDskCertName)
37 : m_keyChain(keyChain)
Yumin Xiab87b9d92016-11-14 23:41:25 -080038 , m_dbFile(dbFile.string())
Yumin Xiaf853ad72016-11-03 21:14:07 -070039 , m_zone(zoneName)
40 , m_dskCertName(inputDskCertName)
41 , m_checked(false)
42{
Yumin Xia2c509c22017-02-09 14:37:36 -080043 Name identityName = Name(zoneName).append(label::NDNS_CERT_QUERY);
Yumin Xiaf853ad72016-11-03 21:14:07 -070044 if (m_dskCertName == DEFAULT_CERT) {
Yumin Xia2c509c22017-02-09 14:37:36 -080045 m_dskName = CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, identityName);
46 m_dskCertName = CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, identityName);
Yumin Xiaf853ad72016-11-03 21:14:07 -070047 }
48}
49
50void
51RrsetFactory::checkZoneKey()
52{
53 onlyCheckZone();
Yumin Xia2c509c22017-02-09 14:37:36 -080054 Name zoneIdentityName = Name(m_zone.getName()).append(label::NDNS_CERT_QUERY);
Yumin Xiaf853ad72016-11-03 21:14:07 -070055 if (m_dskCertName != DEFAULT_CERT &&
Yumin Xia2c509c22017-02-09 14:37:36 -080056 !matchCertificate(m_dskCertName, zoneIdentityName)) {
Yumin Xiaf853ad72016-11-03 21:14:07 -070057 BOOST_THROW_EXCEPTION(Error("Cannot verify certificate"));
58 }
59}
60
61void
62RrsetFactory::onlyCheckZone()
63{
64 if (m_checked) {
65 return ;
66 }
67 m_checked = true;
68
69 DbMgr dbMgr(m_dbFile);
70 const Name& zoneName = m_zone.getName();
71 if (!dbMgr.find(m_zone)) {
72 BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is not presented in the NDNS db"));
73 }
74}
75
76
77std::pair<Rrset, Name>
78RrsetFactory::generateBaseRrset(const Name& label,
79 const name::Component& type,
80 const uint64_t version,
81 const time::seconds& ttl)
82{
83 Rrset rrset(&m_zone);
84
85 rrset.setLabel(label);
86 rrset.setType(type);
87 rrset.setTtl(ttl);
88
89 name::Component qType;
90 if (type == label::CERT_RR_TYPE) {
91 qType = label::NDNS_CERT_QUERY;
Yumin Xia2c509c22017-02-09 14:37:36 -080092 }
93 else {
Yumin Xiaf853ad72016-11-03 21:14:07 -070094 qType = label::NDNS_ITERATIVE_QUERY;
95 }
96
97 Name name;
98 name.append(m_zone.getName())
99 .append(qType)
100 .append(label)
101 .append(type);
102
103 if (version != VERSION_USE_UNIX_TIMESTAMP) {
104 name.append(name::Component::fromVersion(version));
Yumin Xia2c509c22017-02-09 14:37:36 -0800105 }
106 else {
Yumin Xiaf853ad72016-11-03 21:14:07 -0700107 name.appendVersion();
108 }
109
110 rrset.setVersion(name.get(-1));
111
112 return std::make_pair(rrset, name);
113}
114
115bool
116RrsetFactory::matchCertificate(const Name& certName, const Name& identity)
117{
Yumin Xia2c509c22017-02-09 14:37:36 -0800118 try {
119 CertHelper::getCertificate(m_keyChain, identity, certName);
120 return true;
121 } catch (ndn::security::Pib::Error) {
Yumin Xiaf853ad72016-11-03 21:14:07 -0700122 return false;
123 }
Yumin Xiaf853ad72016-11-03 21:14:07 -0700124}
125
126Rrset
127RrsetFactory::generateNsRrset(const Name& label,
128 const name::Component& type,
129 const uint64_t version,
130 time::seconds ttl,
Yumin Xia2c509c22017-02-09 14:37:36 -0800131 const ndn::DelegationList& delegations)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700132{
133 if (!m_checked) {
134 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
135 }
136
137 if (ttl == DEFAULT_RR_TTL)
138 ttl = m_zone.getTtl();
139
140 std::pair<Rrset, Name> rrsetAndName = generateBaseRrset(label, type, version, ttl);
141 const Name& name = rrsetAndName.second;
142 Rrset& rrset = rrsetAndName.first;
143
144 Link link(name);
Yumin Xia2c509c22017-02-09 14:37:36 -0800145 link.setDelegationList(delegations);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700146
Yumin Xiaa484ba72016-11-10 20:40:12 -0800147 setContentType(link, NDNS_LINK, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700148 sign(link);
149 rrset.setData(link.wireEncode());
150
151 return rrset;
152}
153
154Rrset
155RrsetFactory::generateTxtRrset(const Name& label,
156 const name::Component& type,
157 const uint64_t version,
158 time::seconds ttl,
159 const std::vector<std::string>& strings)
160{
161 if (!m_checked) {
162 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
163 }
164
165 if (ttl == DEFAULT_RR_TTL)
166 ttl = m_zone.getTtl();
167
168 Name name;
169 Rrset rrset;
170 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
171
172 std::vector<Block> rrs;
173 for (const auto& item : strings) {
174 rrs.push_back(makeBinaryBlock(ndns::tlv::RrData,
175 item.c_str(),
176 item.size()));
177 }
178
179 Data data(name);
180 data.setContent(wireEncode(rrs));
181
Yumin Xiaa484ba72016-11-10 20:40:12 -0800182 setContentType(data, NDNS_RESP, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700183 sign(data);
184 rrset.setData(data.wireEncode());
185
186 return rrset;
187}
188
189Rrset
190RrsetFactory::generateCertRrset(const Name& label,
191 const name::Component& type,
192 const uint64_t version,
193 time::seconds ttl,
Yumin Xia2c509c22017-02-09 14:37:36 -0800194 const ndn::security::v2::Certificate& cert)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700195{
196 if (!m_checked) {
197 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
198 }
199
200 if (ttl == DEFAULT_RR_TTL)
201 ttl = m_zone.getTtl();
202
203 Name name;
204 Rrset rrset;
205 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
206
207 Data data(name);
208 data.setContent(cert.wireEncode());
209
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800210 setContentType(data, NDNS_KEY, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700211 sign(data);
212 rrset.setData(data.wireEncode());
213
214 return rrset;
215}
216
Yumin Xiaacd21332016-11-28 22:54:48 -0800217Rrset
218RrsetFactory::generateAuthRrset(const Name& label,
219 const name::Component& type,
220 const uint64_t version,
221 time::seconds ttl)
222{
223 if (!m_checked) {
224 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
225 }
226
227 if (ttl == DEFAULT_RR_TTL)
228 ttl = m_zone.getTtl();
229
230 Name name;
231 Rrset rrset;
232 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
233
234 Data data(name);
235
236 setContentType(data, NDNS_AUTH, ttl);
237 sign(data);
238 rrset.setData(data.wireEncode());
239
240 return rrset;
241}
Yumin Xiaf853ad72016-11-03 21:14:07 -0700242
243void
244RrsetFactory::sign(Data& data)
245{
Yumin Xia2c509c22017-02-09 14:37:36 -0800246 m_keyChain.sign(data, signingByCertificate(m_dskCertName));
Yumin Xiaf853ad72016-11-03 21:14:07 -0700247}
248
249void
Yumin Xiaa484ba72016-11-10 20:40:12 -0800250RrsetFactory::setContentType(Data& data, NdnsContentType contentType,
251 const time::seconds& ttl)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700252{
Yumin Xiaa484ba72016-11-10 20:40:12 -0800253 data.setContentType(contentType);
254 data.setFreshnessPeriod(ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700255}
256
257template<encoding::Tag TAG>
258inline size_t
259RrsetFactory::wireEncode(EncodingImpl<TAG>& block, const std::vector<Block>& rrs) const
260{
261 // Content :: = CONTENT-TYPE TLV-LENGTH
262 // Block*
263
264 size_t totalLength = 0;
265 for (auto iter = rrs.rbegin(); iter != rrs.rend(); ++iter) {
266 totalLength += block.prependBlock(*iter);
267 }
268
269 totalLength += block.prependVarNumber(totalLength);
270 totalLength += block.prependVarNumber(::ndn::tlv::Content);
271
272 return totalLength;
273}
274
275const Block
276RrsetFactory::wireEncode(const std::vector<Block>& rrs) const
277{
278 EncodingEstimator estimator;
279 size_t estimatedSize = wireEncode(estimator, rrs);
280 EncodingBuffer buffer(estimatedSize, 0);
281 wireEncode(buffer, rrs);
282 return buffer.block();
283}
284
285std::vector<std::string>
286RrsetFactory::wireDecodeTxt(const Block& wire)
287{
288 std::vector<std::string> txts;
289 wire.parse();
290
Yumin Xiaa484ba72016-11-10 20:40:12 -0800291 for (const auto& e : wire.elements()) {
Yumin Xiaf853ad72016-11-03 21:14:07 -0700292 txts.push_back(std::string(reinterpret_cast<const char*>(e.value()),
293 e.value_size()));
294 }
295
296 return txts;
297}
298
299
300} // namespace ndns
301} // namespace ndn