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