blob: f82e8319e00befc753042a88580e1ea2a6879343 [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 Xia918343d2017-03-17 19:04:55 -070043 Name identityName = Name(zoneName).append(label::NDNS_ITERATIVE_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 Xia918343d2017-03-17 19:04:55 -070054 Name zoneIdentityName = Name(m_zone.getName()).append(label::NDNS_ITERATIVE_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
Yumin Xiaf853ad72016-11-03 21:14:07 -070089 Name name;
90 name.append(m_zone.getName())
Yumin Xia918343d2017-03-17 19:04:55 -070091 .append(label::NDNS_ITERATIVE_QUERY)
Yumin Xiaf853ad72016-11-03 21:14:07 -070092 .append(label)
93 .append(type);
94
95 if (version != VERSION_USE_UNIX_TIMESTAMP) {
96 name.append(name::Component::fromVersion(version));
Yumin Xia2c509c22017-02-09 14:37:36 -080097 }
98 else {
Yumin Xiaf853ad72016-11-03 21:14:07 -070099 name.appendVersion();
100 }
101
102 rrset.setVersion(name.get(-1));
103
104 return std::make_pair(rrset, name);
105}
106
107bool
108RrsetFactory::matchCertificate(const Name& certName, const Name& identity)
109{
Yumin Xia2c509c22017-02-09 14:37:36 -0800110 try {
111 CertHelper::getCertificate(m_keyChain, identity, certName);
112 return true;
113 } catch (ndn::security::Pib::Error) {
Yumin Xiaf853ad72016-11-03 21:14:07 -0700114 return false;
115 }
Yumin Xiaf853ad72016-11-03 21:14:07 -0700116}
117
118Rrset
119RrsetFactory::generateNsRrset(const Name& label,
120 const name::Component& type,
121 const uint64_t version,
122 time::seconds ttl,
Yumin Xia2c509c22017-02-09 14:37:36 -0800123 const ndn::DelegationList& delegations)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700124{
125 if (!m_checked) {
126 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
127 }
128
129 if (ttl == DEFAULT_RR_TTL)
130 ttl = m_zone.getTtl();
131
132 std::pair<Rrset, Name> rrsetAndName = generateBaseRrset(label, type, version, ttl);
133 const Name& name = rrsetAndName.second;
134 Rrset& rrset = rrsetAndName.first;
135
136 Link link(name);
Yumin Xia2c509c22017-02-09 14:37:36 -0800137 link.setDelegationList(delegations);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700138
Yumin Xiaa484ba72016-11-10 20:40:12 -0800139 setContentType(link, NDNS_LINK, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700140 sign(link);
141 rrset.setData(link.wireEncode());
142
143 return rrset;
144}
145
146Rrset
147RrsetFactory::generateTxtRrset(const Name& label,
148 const name::Component& type,
149 const uint64_t version,
150 time::seconds ttl,
151 const std::vector<std::string>& strings)
152{
153 if (!m_checked) {
154 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
155 }
156
157 if (ttl == DEFAULT_RR_TTL)
158 ttl = m_zone.getTtl();
159
160 Name name;
161 Rrset rrset;
162 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
163
164 std::vector<Block> rrs;
165 for (const auto& item : strings) {
166 rrs.push_back(makeBinaryBlock(ndns::tlv::RrData,
167 item.c_str(),
168 item.size()));
169 }
170
171 Data data(name);
172 data.setContent(wireEncode(rrs));
173
Yumin Xiaa484ba72016-11-10 20:40:12 -0800174 setContentType(data, NDNS_RESP, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700175 sign(data);
176 rrset.setData(data.wireEncode());
177
178 return rrset;
179}
180
181Rrset
182RrsetFactory::generateCertRrset(const Name& label,
183 const name::Component& type,
184 const uint64_t version,
185 time::seconds ttl,
Yumin Xia2c509c22017-02-09 14:37:36 -0800186 const ndn::security::v2::Certificate& cert)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700187{
188 if (!m_checked) {
189 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
190 }
191
192 if (ttl == DEFAULT_RR_TTL)
193 ttl = m_zone.getTtl();
194
195 Name name;
196 Rrset rrset;
197 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
198
199 Data data(name);
200 data.setContent(cert.wireEncode());
201
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800202 setContentType(data, NDNS_KEY, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700203 sign(data);
204 rrset.setData(data.wireEncode());
205
206 return rrset;
207}
208
Yumin Xiaacd21332016-11-28 22:54:48 -0800209Rrset
210RrsetFactory::generateAuthRrset(const Name& label,
211 const name::Component& type,
212 const uint64_t version,
213 time::seconds ttl)
214{
215 if (!m_checked) {
216 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
217 }
218
219 if (ttl == DEFAULT_RR_TTL)
220 ttl = m_zone.getTtl();
221
222 Name name;
223 Rrset rrset;
224 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
225
226 Data data(name);
227
228 setContentType(data, NDNS_AUTH, ttl);
229 sign(data);
230 rrset.setData(data.wireEncode());
231
232 return rrset;
233}
Yumin Xiaf853ad72016-11-03 21:14:07 -0700234
235void
236RrsetFactory::sign(Data& data)
237{
Yumin Xia2c509c22017-02-09 14:37:36 -0800238 m_keyChain.sign(data, signingByCertificate(m_dskCertName));
Yumin Xiaf853ad72016-11-03 21:14:07 -0700239}
240
241void
Yumin Xiaa484ba72016-11-10 20:40:12 -0800242RrsetFactory::setContentType(Data& data, NdnsContentType contentType,
243 const time::seconds& ttl)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700244{
Yumin Xiaa484ba72016-11-10 20:40:12 -0800245 data.setContentType(contentType);
246 data.setFreshnessPeriod(ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700247}
248
249template<encoding::Tag TAG>
250inline size_t
251RrsetFactory::wireEncode(EncodingImpl<TAG>& block, const std::vector<Block>& rrs) const
252{
253 // Content :: = CONTENT-TYPE TLV-LENGTH
254 // Block*
255
256 size_t totalLength = 0;
257 for (auto iter = rrs.rbegin(); iter != rrs.rend(); ++iter) {
258 totalLength += block.prependBlock(*iter);
259 }
260
261 totalLength += block.prependVarNumber(totalLength);
262 totalLength += block.prependVarNumber(::ndn::tlv::Content);
263
264 return totalLength;
265}
266
267const Block
268RrsetFactory::wireEncode(const std::vector<Block>& rrs) const
269{
270 EncodingEstimator estimator;
271 size_t estimatedSize = wireEncode(estimator, rrs);
272 EncodingBuffer buffer(estimatedSize, 0);
273 wireEncode(buffer, rrs);
274 return buffer.block();
275}
276
277std::vector<std::string>
278RrsetFactory::wireDecodeTxt(const Block& wire)
279{
280 std::vector<std::string> txts;
281 wire.parse();
282
Yumin Xiaa484ba72016-11-10 20:40:12 -0800283 for (const auto& e : wire.elements()) {
Yumin Xiaf853ad72016-11-03 21:14:07 -0700284 txts.push_back(std::string(reinterpret_cast<const char*>(e.value()),
285 e.value_size()));
286 }
287
288 return txts;
289}
290
291
292} // namespace ndns
293} // namespace ndn