blob: 9757abcfc61dc31eeea4f4a7a555db93d99e8863 [file] [log] [blame]
Yumin Xiaf853ad72016-11-03 21:14:07 -07001/* -*- 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.
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"
22
23#include <boost/algorithm/string/join.hpp>
24
25namespace ndn {
26namespace ndns {
27
28NDNS_LOG_INIT("RrsetFactory")
29
Yumin Xiab87b9d92016-11-14 23:41:25 -080030RrsetFactory::RrsetFactory(const boost::filesystem::path& dbFile,
Yumin Xiaf853ad72016-11-03 21:14:07 -070031 const Name& zoneName,
32 KeyChain& keyChain,
33 const Name& inputDskCertName)
34 : m_keyChain(keyChain)
Yumin Xiab87b9d92016-11-14 23:41:25 -080035 , m_dbFile(dbFile.string())
Yumin Xiaf853ad72016-11-03 21:14:07 -070036 , m_zone(zoneName)
37 , m_dskCertName(inputDskCertName)
38 , m_checked(false)
39{
40 if (m_dskCertName == DEFAULT_CERT) {
41 m_dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
42 m_dskCertName = m_keyChain.getDefaultCertificateNameForKey(m_dskName);
43 }
44}
45
46void
47RrsetFactory::checkZoneKey()
48{
49 onlyCheckZone();
50 if (m_dskCertName != DEFAULT_CERT &&
51 !matchCertificate(m_dskCertName, m_zone.getName())) {
52 BOOST_THROW_EXCEPTION(Error("Cannot verify certificate"));
53 }
54}
55
56void
57RrsetFactory::onlyCheckZone()
58{
59 if (m_checked) {
60 return ;
61 }
62 m_checked = true;
63
64 DbMgr dbMgr(m_dbFile);
65 const Name& zoneName = m_zone.getName();
66 if (!dbMgr.find(m_zone)) {
67 BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is not presented in the NDNS db"));
68 }
69}
70
71
72std::pair<Rrset, Name>
73RrsetFactory::generateBaseRrset(const Name& label,
74 const name::Component& type,
75 const uint64_t version,
76 const time::seconds& ttl)
77{
78 Rrset rrset(&m_zone);
79
80 rrset.setLabel(label);
81 rrset.setType(type);
82 rrset.setTtl(ttl);
83
84 name::Component qType;
85 if (type == label::CERT_RR_TYPE) {
86 qType = label::NDNS_CERT_QUERY;
87 } else {
88 qType = label::NDNS_ITERATIVE_QUERY;
89 }
90
91 Name name;
92 name.append(m_zone.getName())
93 .append(qType)
94 .append(label)
95 .append(type);
96
97 if (version != VERSION_USE_UNIX_TIMESTAMP) {
98 name.append(name::Component::fromVersion(version));
99 } else {
100 name.appendVersion();
101 }
102
103 rrset.setVersion(name.get(-1));
104
105 return std::make_pair(rrset, name);
106}
107
108bool
109RrsetFactory::matchCertificate(const Name& certName, const Name& identity)
110{
111 if (!m_keyChain.doesCertificateExist(certName)) {
112 NDNS_LOG_WARN(certName.toUri() << " is not presented in KeyChain");
113 return false;
114 }
115
116 // Check its public key information
117 shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(certName);
118 Name keyName = cert->getPublicKeyName();
119
120 if (!identity.isPrefixOf(keyName) || identity.size() != keyName.size() - 1) {
121 NDNS_LOG_WARN(keyName.toUri() << " is not a key of " << identity.toUri());
122 return false;
123 }
124
125 if (!m_keyChain.doesKeyExistInTpm(keyName, KeyClass::PRIVATE)) {
126 NDNS_LOG_WARN("Private key: " << keyName.toUri() << " is not present in KeyChain");
127 return false;
128 }
129
130 return true;
131}
132
133Rrset
134RrsetFactory::generateNsRrset(const Name& label,
135 const name::Component& type,
136 const uint64_t version,
137 time::seconds ttl,
138 const ndn::Link::DelegationSet& delegations)
139{
140 if (!m_checked) {
141 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
142 }
143
144 if (ttl == DEFAULT_RR_TTL)
145 ttl = m_zone.getTtl();
146
147 std::pair<Rrset, Name> rrsetAndName = generateBaseRrset(label, type, version, ttl);
148 const Name& name = rrsetAndName.second;
149 Rrset& rrset = rrsetAndName.first;
150
151 Link link(name);
152 for (const auto& i : delegations) {
153 link.addDelegation(i.first, i.second);
154 }
155
Yumin Xiaa484ba72016-11-10 20:40:12 -0800156 setContentType(link, NDNS_LINK, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700157 sign(link);
158 rrset.setData(link.wireEncode());
159
160 return rrset;
161}
162
163Rrset
164RrsetFactory::generateTxtRrset(const Name& label,
165 const name::Component& type,
166 const uint64_t version,
167 time::seconds ttl,
168 const std::vector<std::string>& strings)
169{
170 if (!m_checked) {
171 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
172 }
173
174 if (ttl == DEFAULT_RR_TTL)
175 ttl = m_zone.getTtl();
176
177 Name name;
178 Rrset rrset;
179 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
180
181 std::vector<Block> rrs;
182 for (const auto& item : strings) {
183 rrs.push_back(makeBinaryBlock(ndns::tlv::RrData,
184 item.c_str(),
185 item.size()));
186 }
187
188 Data data(name);
189 data.setContent(wireEncode(rrs));
190
Yumin Xiaa484ba72016-11-10 20:40:12 -0800191 setContentType(data, NDNS_RESP, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700192 sign(data);
193 rrset.setData(data.wireEncode());
194
195 return rrset;
196}
197
198Rrset
199RrsetFactory::generateCertRrset(const Name& label,
200 const name::Component& type,
201 const uint64_t version,
202 time::seconds ttl,
203 const IdentityCertificate& cert)
204{
205 if (!m_checked) {
206 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
207 }
208
209 if (ttl == DEFAULT_RR_TTL)
210 ttl = m_zone.getTtl();
211
212 Name name;
213 Rrset rrset;
214 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
215
216 Data data(name);
217 data.setContent(cert.wireEncode());
218
Yumin Xia3c6b1fd2016-12-11 19:08:47 -0800219 setContentType(data, NDNS_KEY, ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700220 sign(data);
221 rrset.setData(data.wireEncode());
222
223 return rrset;
224}
225
Yumin Xiaacd21332016-11-28 22:54:48 -0800226Rrset
227RrsetFactory::generateAuthRrset(const Name& label,
228 const name::Component& type,
229 const uint64_t version,
230 time::seconds ttl)
231{
232 if (!m_checked) {
233 BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
234 }
235
236 if (ttl == DEFAULT_RR_TTL)
237 ttl = m_zone.getTtl();
238
239 Name name;
240 Rrset rrset;
241 std::tie(rrset, name) = generateBaseRrset(label, type, version, ttl);
242
243 Data data(name);
244
245 setContentType(data, NDNS_AUTH, ttl);
246 sign(data);
247 rrset.setData(data.wireEncode());
248
249 return rrset;
250}
Yumin Xiaf853ad72016-11-03 21:14:07 -0700251
252void
253RrsetFactory::sign(Data& data)
254{
255 m_keyChain.sign(data, m_dskCertName);
256}
257
258void
Yumin Xiaa484ba72016-11-10 20:40:12 -0800259RrsetFactory::setContentType(Data& data, NdnsContentType contentType,
260 const time::seconds& ttl)
Yumin Xiaf853ad72016-11-03 21:14:07 -0700261{
Yumin Xiaa484ba72016-11-10 20:40:12 -0800262 data.setContentType(contentType);
263 data.setFreshnessPeriod(ttl);
Yumin Xiaf853ad72016-11-03 21:14:07 -0700264}
265
266template<encoding::Tag TAG>
267inline size_t
268RrsetFactory::wireEncode(EncodingImpl<TAG>& block, const std::vector<Block>& rrs) const
269{
270 // Content :: = CONTENT-TYPE TLV-LENGTH
271 // Block*
272
273 size_t totalLength = 0;
274 for (auto iter = rrs.rbegin(); iter != rrs.rend(); ++iter) {
275 totalLength += block.prependBlock(*iter);
276 }
277
278 totalLength += block.prependVarNumber(totalLength);
279 totalLength += block.prependVarNumber(::ndn::tlv::Content);
280
281 return totalLength;
282}
283
284const Block
285RrsetFactory::wireEncode(const std::vector<Block>& rrs) const
286{
287 EncodingEstimator estimator;
288 size_t estimatedSize = wireEncode(estimator, rrs);
289 EncodingBuffer buffer(estimatedSize, 0);
290 wireEncode(buffer, rrs);
291 return buffer.block();
292}
293
294std::vector<std::string>
295RrsetFactory::wireDecodeTxt(const Block& wire)
296{
297 std::vector<std::string> txts;
298 wire.parse();
299
Yumin Xiaa484ba72016-11-10 20:40:12 -0800300 for (const auto& e : wire.elements()) {
Yumin Xiaf853ad72016-11-03 21:14:07 -0700301 txts.push_back(std::string(reinterpret_cast<const char*>(e.value()),
302 e.value_size()));
303 }
304
305 return txts;
306}
307
308
309} // namespace ndns
310} // namespace ndn