blob: 09d192fdccdf21c84249b08fb0a17a34f6b5ff78 [file] [log] [blame]
Shock Jiangcde28712014-10-19 21:17:20 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014, Regents of the University of California.
4 *
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 "daemon/db-mgr.hpp"
21#include "daemon/name-server.hpp"
22#include "clients/response.hpp"
23#include "clients/query.hpp"
24#include "logger.hpp"
25
26#include "../database-test-data.hpp"
27#include "../../boost-test.hpp"
28
29#include <boost/filesystem.hpp>
30#include <ndn-cxx/face.hpp>
31#include <ndn-cxx/util/dummy-client-face.hpp>
32
33namespace ndn {
34namespace ndns {
35namespace tests {
36
37NDNS_LOG_INIT("NameServerTest");
38
39class NameServerFixture : public DbTestData
40{
41public:
42 NameServerFixture()
43 : face(ndn::util::makeDummyClientFace({ false, true }))
Shock Jiange1a81fd2014-11-20 20:25:49 -080044 , zone(m_root.getName())
Shock Jiangcde28712014-10-19 21:17:20 -070045 , validator(*face)
46 , server(zone, m_certName, *face, m_session, m_keyChain, validator)
47 {
48 // ensure prefix is registered
49 run();
50 }
51
52 void
53 run()
54 {
55 face->getIoService().poll();
56 face->getIoService().reset();
57 }
58
59public:
60 shared_ptr<ndn::util::DummyClientFace> face;
61 Name hint;
62 const Name& zone;
63 Validator validator;
64 ndns::NameServer server;
65};
66
67BOOST_FIXTURE_TEST_SUITE(NameServer, NameServerFixture)
68
69BOOST_AUTO_TEST_CASE(NdnsQuery)
70{
71 Query q(hint, zone, ndns::label::NDNS_ITERATIVE_QUERY);
Shock Jiange1a81fd2014-11-20 20:25:49 -080072 q.setRrLabel(Name("net"));
Shock Jiangcde28712014-10-19 21:17:20 -070073 q.setRrType(ndns::label::NS_RR_TYPE);
74
75 bool hasDataBack = false;
76
77 face->onData += [&] (const Data& data) {
78 hasDataBack = true;
79 NDNS_LOG_TRACE("get Data back");
80 BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
81
82 Response resp;
83 BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
84 BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP);
85 };
86
87 face->receive(q.toInterest());
88
89 run();
90
91 BOOST_CHECK_EQUAL(hasDataBack, true);
92}
93
94BOOST_AUTO_TEST_CASE(KeyQuery)
95{
96 Query q(hint, zone, ndns::label::NDNS_ITERATIVE_QUERY);
97 q.setQueryType(ndns::label::NDNS_CERT_QUERY);
98 q.setRrType(ndns::label::CERT_RR_TYPE);
99
100 size_t nDataBack = 0;
101
102 // will ask for non-existing record
103 face->onData += [&] (const Data& data) {
104 ++nDataBack;
105 NDNS_LOG_TRACE("get Data back");
106 BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
107
108 Response resp;
109 BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
110 BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_NACK);
111 };
112
113 face->receive(q.toInterest());
114 run();
115
116 // will ask for the existing record (will have type NDNS_RAW, as it is certificate)
117 face->onData.clear();
118 face->onData += [&] (const Data& data) {
119 ++nDataBack;
120 NDNS_LOG_TRACE("get Data back");
121 BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
122
123 Response resp;
124 BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
125 BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RAW);
126 };
127
Shock Jiange1a81fd2014-11-20 20:25:49 -0800128 q.setRrLabel("dsk-1");
Shock Jiangcde28712014-10-19 21:17:20 -0700129
130 face->receive(q.toInterest());
131 run();
132
133 BOOST_CHECK_EQUAL(nDataBack, 2);
134}
135
136BOOST_AUTO_TEST_CASE(UpdateReplaceRr)
137{
138 Response re;
139 re.setZone(zone);
140 re.setQueryType(label::NDNS_ITERATIVE_QUERY);
Shock Jiange1a81fd2014-11-20 20:25:49 -0800141 re.setRrLabel(Name("net"));
Shock Jiangcde28712014-10-19 21:17:20 -0700142 re.setRrType(label::NS_RR_TYPE);
143 re.setNdnsType(NDNS_RESP);
144
145 std::string str = "ns1.ndnsim.net";
146 re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
147 str = "ns2.ndnsim.net";
148 re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
149
150 shared_ptr<Data> data = re.toData();
151 m_keyChain.sign(*data, m_certName);
152
153 Query q(Name(hint), Name(zone), ndns::label::NDNS_ITERATIVE_QUERY);
154 const Block& block = data->wireEncode();
155 Name name;
156 name.append(block);
157
158 q.setRrLabel(name);
159 q.setRrType(label::NDNS_UPDATE_LABEL);
160
161 bool hasDataBack = false;
162
163 face->onData += [&] (const Data& data) {
164 hasDataBack = true;
165 NDNS_LOG_TRACE("get Data back");
166 BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
167 Response resp;
168
169 BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
Shock Jiangcde28712014-10-19 21:17:20 -0700170 BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
171 BOOST_CHECK_GT(resp.getRrs().size(), 0);
172 Block block = resp.getRrs()[0];
173 block.parse();
174 int ret = -1;
175 BOOST_CHECK_EQUAL(block.type(), ndns::tlv::RrData);
176 Block::element_const_iterator val = block.elements_begin();
177 BOOST_CHECK_EQUAL(val->type(), ndns::tlv::UpdateReturnCode); // the first must be return code
178 ret = readNonNegativeInteger(*val);
179 BOOST_CHECK_EQUAL(ret, 0);
180 };
181
182 face->receive(q.toInterest());
183 run();
184
185 BOOST_CHECK_EQUAL(hasDataBack, true);
186}
187
188BOOST_AUTO_TEST_CASE(UpdateInsertNewRr)
189{
190 Response re;
191 re.setZone(zone);
192 re.setQueryType(label::NDNS_ITERATIVE_QUERY);
Shock Jiange1a81fd2014-11-20 20:25:49 -0800193 re.setRrLabel(Name("net-XYZ")); // insert new records
Shock Jiangcde28712014-10-19 21:17:20 -0700194 re.setRrType(label::NS_RR_TYPE);
195 re.setNdnsType(NDNS_RESP);
196
197 std::string str = "ns1.ndnsim.net";
198 re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
199 str = "ns2.ndnsim.net";
200 re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
201
202 shared_ptr<Data> data = re.toData();
203 m_keyChain.sign(*data, m_certName);
204
205 Query q(Name(hint), Name(zone), ndns::label::NDNS_ITERATIVE_QUERY);
206 const Block& block = data->wireEncode();
207 Name name;
208 name.append(block);
209
210 q.setRrLabel(name);
211 q.setRrType(label::NDNS_UPDATE_LABEL);
212
213 bool hasDataBack = false;
214
215 face->onData += [&] (const Data& data) {
216 hasDataBack = true;
217 NDNS_LOG_TRACE("get Data back");
218 BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
219 Response resp;
220
221 BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
Shock Jiangcde28712014-10-19 21:17:20 -0700222 BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
223 BOOST_CHECK_GT(resp.getRrs().size(), 0);
224 Block block = resp.getRrs()[0];
225 block.parse();
226 int ret = -1;
227 BOOST_CHECK_EQUAL(block.type(), ndns::tlv::RrData);
228 Block::element_const_iterator val = block.elements_begin();
229 BOOST_CHECK_EQUAL(val->type(), ndns::tlv::UpdateReturnCode); // the first must be return code
230 ret = readNonNegativeInteger(*val);
231 BOOST_CHECK_EQUAL(ret, 0);
232 };
233
234 face->receive(q.toInterest());
235 run();
236
237 BOOST_CHECK_EQUAL(hasDataBack, true);
238}
239
Shock Jiange1a81fd2014-11-20 20:25:49 -0800240BOOST_AUTO_TEST_CASE(UpdateValidatorCannotFetchCert)
241{
242 Name dskName = m_keyChain.generateRsaKeyPair(TEST_IDENTITY_NAME, false);
243 std::vector<CertificateSubjectDescription> desc;
244 time::system_clock::TimePoint notBefore = time::system_clock::now();
245 time::system_clock::TimePoint notAfter = notBefore + time::days(365);
246 shared_ptr<IdentityCertificate> dskCert =
247 m_keyChain.prepareUnsignedIdentityCertificate(dskName, m_certName,
248 notBefore, notAfter, desc);
249
250 m_keyChain.sign(*dskCert, m_certName);
251 m_keyChain.addCertificateAsKeyDefault(*dskCert);
252 NDNS_LOG_TRACE("KeyChain: add cert: " << dskCert->getName() << ". KeyLocator: "
253 << dskCert->getSignature().getKeyLocator().getName());
254
255 Rrset rrset(&m_root);
256 Name label = dskCert->getName().getPrefix(-2).getSubName(m_root.getName().size() + 1);
257 rrset.setLabel(label);
258 rrset.setType(label::CERT_RR_TYPE);
259 rrset.setVersion(dskCert->getName().get(-1));
260 rrset.setTtl(m_root.getTtl());
261 rrset.setData(dskCert->wireEncode());
262 m_session.insert(rrset);
263 NDNS_LOG_TRACE("DB: zone " << m_root << " add a ID-CERT RR with name="
264 << dskCert->getName() << " rrLabel=" << label);
265
266 Response re;
267 re.setZone(zone);
268 re.setQueryType(label::NDNS_ITERATIVE_QUERY);
269 re.setRrLabel(Name("ndnsim-XYZ")); // insert new records
270 re.setRrType(label::NS_RR_TYPE);
271 re.setNdnsType(NDNS_RESP);
272
273 std::string str = "ns1.ndnsim.net";
274 re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
275 str = "ns2.ndnsim.net";
276 re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
277
278 shared_ptr<Data> data = re.toData();
279 m_keyChain.sign(*data, dskCert->getName());
280
281 Query q(Name(hint), Name(zone), ndns::label::NDNS_ITERATIVE_QUERY);
282 const Block& block = data->wireEncode();
283 Name name;
284 name.append(block);
285
286 q.setRrLabel(name);
287 q.setRrType(label::NDNS_UPDATE_LABEL);
288
289 bool hasDataBack = false;
290
291 // no data back, since the Update cannot pass verification
292 face->onData += [&] (const Data& data) {
293 hasDataBack = true;
294 BOOST_FAIL("UNEXPECTED");
295 };
296
297 face->receive(q.toInterest());
298 run();
299
300 BOOST_CHECK_EQUAL(hasDataBack, false);
301}
302
303class NameServerFixture2 : public DbTestData
304{
305public:
306 NameServerFixture2()
307 : face(ndn::util::makeDummyClientFace(io, { false, true }))
308 , validatorFace(ndn::util::makeDummyClientFace(io, { false, true }))
309 , zone(m_root.getName())
310 , validator(*validatorFace) // different face for validator
311 , server(zone, m_certName, *face, m_session, m_keyChain, validator)
312 {
313 // ensure prefix is registered
314 run();
315 validatorFace->onInterest += [&] (const Interest& interest) {
316 NDNS_LOG_TRACE("validatorFace get Interest: " << interest.getName());
317 face->receive(interest);
318 };
319 }
320
321 void
322 run()
323 {
324 io.poll();
325 io.reset();
326 }
327
328public:
329 boost::asio::io_service io;
330 shared_ptr<ndn::util::DummyClientFace> face;
331 shared_ptr<ndn::util::DummyClientFace> validatorFace;
332 Name hint;
333 const Name& zone;
334 Validator validator;
335 ndns::NameServer server;
336};
337
338BOOST_FIXTURE_TEST_CASE(UpdateValidatorFetchCert, NameServerFixture2)
339{
340 Name dskName = m_keyChain.generateRsaKeyPair(TEST_IDENTITY_NAME, false);
341 std::vector<CertificateSubjectDescription> desc;
342 time::system_clock::TimePoint notBefore = time::system_clock::now();
343 time::system_clock::TimePoint notAfter = notBefore + time::days(365);
344 shared_ptr<IdentityCertificate> dskCert =
345 m_keyChain.prepareUnsignedIdentityCertificate(dskName, m_certName,
346 notBefore, notAfter, desc);
347
348 m_keyChain.sign(*dskCert, m_certName);
349 m_keyChain.addCertificateAsKeyDefault(*dskCert);
350 NDNS_LOG_TRACE("KeyChain: add cert: " << dskCert->getName() << ". KeyLocator: "
351 << dskCert->getSignature().getKeyLocator().getName());
352
353 Rrset rrset(&m_root);
354 Name label = dskCert->getName().getPrefix(-2).getSubName(m_root.getName().size() + 1);
355 rrset.setLabel(label);
356 rrset.setType(label::CERT_RR_TYPE);
357 rrset.setVersion(dskCert->getName().get(-1));
358 rrset.setTtl(m_root.getTtl());
359 rrset.setData(dskCert->wireEncode());
360 m_session.insert(rrset);
361 NDNS_LOG_TRACE("DB: zone " << m_root << " add a ID-CERT RR with name="
362 << dskCert->getName() << " rrLabel=" << label);
363
364 Response re;
365 re.setZone(zone);
366 re.setQueryType(label::NDNS_ITERATIVE_QUERY);
367 re.setRrLabel(Name("ndnsim-XYZ")); // insert new records
368 re.setRrType(label::NS_RR_TYPE);
369 re.setNdnsType(NDNS_RESP);
370
371 std::string str = "ns1.ndnsim.net";
372 re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
373 str = "ns2.ndnsim.net";
374 re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
375
376 shared_ptr<Data> data = re.toData();
377 m_keyChain.sign(*data, dskCert->getName());
378
379 Query q(Name(hint), Name(zone), ndns::label::NDNS_ITERATIVE_QUERY);
380 const Block& block = data->wireEncode();
381 Name name;
382 name.append(block);
383
384 q.setRrLabel(name);
385 q.setRrType(label::NDNS_UPDATE_LABEL);
386
387 bool hasDataBack = false;
388
389 shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
390 face->onData += [&] (const Data& data) {
391 if (regex->match(data.getName())) {
392 validatorFace->receive(data); // It's data requested by validator
393 }
394 else {
395 // cert is requested by validator
396 hasDataBack = true;
397 NDNS_LOG_TRACE("get Data back");
398 BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
399 Response resp;
400
401 BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
Shock Jiange1a81fd2014-11-20 20:25:49 -0800402 BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
403 BOOST_CHECK_GT(resp.getRrs().size(), 0);
404 Block block = resp.getRrs()[0];
405 block.parse();
406 int ret = -1;
407 BOOST_CHECK_EQUAL(block.type(), ndns::tlv::RrData);
408 Block::element_const_iterator val = block.elements_begin();
409 BOOST_CHECK_EQUAL(val->type(), ndns::tlv::UpdateReturnCode); // the first must be return code
410 ret = readNonNegativeInteger(*val);
411 BOOST_CHECK_EQUAL(ret, 0);
412 }
413 };
414
415 face->receive(q.toInterest());
416 run();
417
418 BOOST_CHECK_EQUAL(hasDataBack, true);
419}
420
Shock Jiangcde28712014-10-19 21:17:20 -0700421BOOST_AUTO_TEST_SUITE_END()
422
423} // namespace tests
424} // namespace ndns
425} // namespace ndn