blob: 2525113c88984602058b8c174a6a3a15cfad85df [file] [log] [blame]
Shock Jiang0b165f42014-10-24 09:08:09 -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 "validator.hpp"
Shock Jiang0b165f42014-10-24 09:08:09 -070021#include "../boost-test.hpp"
Shock Jiang0e2aee02014-11-17 11:19:36 -080022#include <ndn-cxx/util/dummy-client-face.hpp>
23#include <ndn-cxx/security/key-chain.hpp>
24#include <boost/asio.hpp>
Shock Jiang0b165f42014-10-24 09:08:09 -070025
26namespace ndn {
27namespace ndns {
28namespace tests {
29NDNS_LOG_INIT("ValidatorTest");
30
31BOOST_AUTO_TEST_SUITE(Validator)
32
33class Fixture
34{
35public:
36 Fixture()
37 : m_testId1("/test02")
38 , m_testId2("/test02/ndn")
39 , m_testId3("/test02/ndn/edu")
40 , m_randomId("/test03")
41 , m_version(name::Component::fromVersion(0))
Shock Jiang0e2aee02014-11-17 11:19:36 -080042 , m_face(ndn::util::makeDummyClientFace(ndn::util::DummyClientFace::Options { false, true }))
Shock Jiang0b165f42014-10-24 09:08:09 -070043 {
44 m_keyChain.deleteIdentity(m_testId1);
45 m_keyChain.deleteIdentity(m_testId2);
46 m_keyChain.deleteIdentity(m_testId3);
47 m_keyChain.deleteIdentity(m_randomId);
48
49 m_randomDsk = createRoot(m_randomId); // generate a root cert
50
51 m_dsk1 = createRoot(m_testId1); // replace to root cert
52 m_dsk2 = createIdentity(m_testId2, m_dsk1);
53 m_dsk3 = createIdentity(m_testId3, m_dsk2);
54
55 m_selfSignCert = m_keyChain.generateRsaKeyPair(m_testId3, false);
56 shared_ptr<IdentityCertificate> cert = m_keyChain.selfSign(m_selfSignCert);
57 m_selfSignCert = cert->getName();
58 m_keyChain.addCertificate(*cert);
59 NDNS_LOG_TRACE("add cert: " << cert->getName() << " to KeyChain");
60
Shock Jiang0e2aee02014-11-17 11:19:36 -080061 m_face->onInterest += bind(&Fixture::respondInterest, this, _1);
Shock Jiang0b165f42014-10-24 09:08:09 -070062 }
63
64 ~Fixture()
65 {
66 m_face->getIoService().stop();
67 m_face->shutdown();
68 m_keyChain.deleteIdentity(m_testId1);
69 m_keyChain.deleteIdentity(m_testId2);
70 m_keyChain.deleteIdentity(m_testId3);
71 m_keyChain.deleteIdentity(m_randomId);
72 }
73
74 const Name
75 createIdentity(const Name& id, const Name& parentCertName)
76 {
77 Name kskCertName = m_keyChain.createIdentity(id);
78 Name kskName = m_keyChain.getDefaultKeyNameForIdentity(id);
79 m_keyChain.deleteCertificate(kskCertName);
80 auto kskCert = createCertificate(kskName, parentCertName);
81
82 Name dskName = m_keyChain.generateRsaKeyPair(id, false);
83 auto dskCert = createCertificate(dskName, kskCert);
84 return dskCert;
85 }
86
87 const Name
88 createRoot(const Name& root)
89 {
90 m_rootCert = m_keyChain.createIdentity(root);
91 ndn::io::save(*(m_keyChain.getCertificate(m_rootCert)), TEST_CONFIG_PATH "/anchors/root.cert");
92 NDNS_LOG_TRACE("save root cert "<< m_rootCert <<
93 " to: " << TEST_CONFIG_PATH "/anchors/root.cert");
94 Name dsk = m_keyChain.generateRsaKeyPair(root, false);
95 auto cert = createCertificate(dsk, m_rootCert);
96 return cert;
97 }
98
99
100 const Name
101 createCertificate(const Name& keyName, const Name& parentCertName)
102 {
103 std::vector<CertificateSubjectDescription> desc;
104 time::system_clock::TimePoint notBefore = time::system_clock::now();
105 time::system_clock::TimePoint notAfter = notBefore + time::days(365);
106 desc.push_back(CertificateSubjectDescription(oid::ATTRIBUTE_NAME,
107 "Signer: " + parentCertName.toUri()));
108 shared_ptr<IdentityCertificate> cert =
109 m_keyChain.prepareUnsignedIdentityCertificate(keyName, parentCertName,
110 notBefore, notAfter, desc);
111
112 Name tmp = cert->getName().getPrefix(-1).append(m_version);
113 cert->setName(tmp);
114 m_keyChain.sign(*cert, parentCertName);
115 m_keyChain.addCertificateAsKeyDefault(*cert);
116 NDNS_LOG_TRACE("add cert: " << cert->getName() << " to KeyChain");
117 return cert->getName();
118 }
119
120
121 void
Shock Jiang0e2aee02014-11-17 11:19:36 -0800122 respondInterest(const Interest& interest)
Shock Jiang0b165f42014-10-24 09:08:09 -0700123 {
124 Name certName = interest.getName();
125 if (certName.isPrefixOf(m_selfSignCert)) {
126 // self-sign cert's version number is not m_version
127 certName = m_selfSignCert;
128 } else {
129 certName.append(m_version);
130 }
131 NDNS_LOG_TRACE("validator needs: " << certName);
132 BOOST_CHECK_EQUAL(m_keyChain.doesCertificateExist(certName), true);
133 auto cert = m_keyChain.getCertificate(certName);
Shock Jiang0e2aee02014-11-17 11:19:36 -0800134 m_face->receive<Data>(*cert);
Shock Jiang0b165f42014-10-24 09:08:09 -0700135 }
136
137public:
138 Name m_testId1;
139 Name m_testId2;
140 Name m_testId3;
141 Name m_randomId;
142
143 Name m_rootCert;
144
145 KeyChain m_keyChain;
146
147 Name m_dsk1;
148 Name m_dsk2;
149 Name m_dsk3;
150
151 Name m_selfSignCert;
152
153 Name m_randomDsk;
154
155 name::Component m_version;
156
Shock Jiang0e2aee02014-11-17 11:19:36 -0800157 shared_ptr<ndn::util::DummyClientFace> m_face;
Shock Jiang0b165f42014-10-24 09:08:09 -0700158};
159
160
161BOOST_FIXTURE_TEST_CASE(Basic, Fixture)
162{
163 // validator must be created after root key is saved to the target
164 ndns::Validator validator(*m_face, TEST_CONFIG_PATH "/" "validator.conf");
165
166 Name dataName(m_testId3);
167 dataName.append("NDNS")
168 .append("rrLabel")
169 .append("rrType")
170 .appendVersion();
171 shared_ptr<Data> data = make_shared<Data>(dataName);
172 m_keyChain.sign(*data, m_dsk3);
173
174 bool hasValidated = false;
175 validator.validate(*data,
176 [&] (const shared_ptr<const Data>& data) {
177 hasValidated = true;
178 BOOST_CHECK(true);
179 },
180 [&] (const shared_ptr<const Data>& data, const std::string& str) {
181 hasValidated = true;
182 BOOST_CHECK(false);
183 });
184
185 m_face->processEvents(time::milliseconds(-1));
186
187 BOOST_CHECK_EQUAL(hasValidated, true);
188
189
190 dataName = m_testId2;
191 dataName.append("KEY")
192 .append("rrLabel")
193 .append("ID-CERT")
194 .appendVersion();
195 data = make_shared<Data>(dataName);
196 m_keyChain.sign(*data, m_dsk3); // key's owner's name is longer than data owner's
197
198 hasValidated = false;
199 validator.validate(*data,
200 [&] (const shared_ptr<const Data>& data) {
201 hasValidated = true;
202 BOOST_CHECK(false);
203 },
204 [&] (const shared_ptr<const Data>& data, const std::string& str) {
205 hasValidated = true;
206 BOOST_CHECK(true);
207 });
208
209 m_face->processEvents(time::milliseconds(-1));
210 // cannot pass verification due to key's owner's name is longer than data owner's
211 BOOST_CHECK_EQUAL(hasValidated, true);
212
213
214 dataName = m_testId3;
215 dataName.append("KEY")
216 .append("rrLabel")
217 .append("ID-CERT")
218 .appendVersion();
219 data = make_shared<Data>(dataName);
220 m_keyChain.sign(*data, m_selfSignCert);
221
222 hasValidated = false;
223 validator.validate(*data,
224 [&] (const shared_ptr<const Data>& data) {
225 hasValidated = true;
226 BOOST_CHECK(false);
227 },
228 [&] (const shared_ptr<const Data>& data, const std::string& str) {
229 hasValidated = true;
230 BOOST_CHECK(true);
231 });
232
233 m_face->processEvents(time::milliseconds(-1));
234 // cannot pass due to self-sign cert is used
235 BOOST_CHECK_EQUAL(hasValidated, true);
236
237 dataName = m_testId2;
238 dataName.append("KEY")
239 .append("rrLabel")
240 .append("ID-CERT")
241 .appendVersion();
242 data = make_shared<Data>(dataName);
243 m_keyChain.sign(*data, m_randomDsk);
244
245 hasValidated = false;
246 validator.validate(*data,
247 [&] (const shared_ptr<const Data>& data) {
248 hasValidated = true;
249 BOOST_CHECK(false);
250 },
251 [&] (const shared_ptr<const Data>& data, const std::string& str) {
252 hasValidated = true;
253 BOOST_CHECK(true);
254 });
255
256 m_face->processEvents(time::milliseconds(-1));
257 // cannot pass due to a totally mismatched key
258 BOOST_CHECK_EQUAL(hasValidated, true);
259}
260
261BOOST_AUTO_TEST_SUITE_END()
262
263} // namespace tests
264} // namespace ndns
265} // namespace ndn