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