blob: cda5e06d0fe4fa2465cf5dc9cb144d65eae040ec [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
Shock Jiang0e2aee02014-11-17 11:19:36 -080062 m_face->onInterest += 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);
Shock Jiang0e2aee02014-11-17 11:19:36 -0800135 m_face->receive<Data>(*cert);
Shock Jiang0b165f42014-10-24 09:08:09 -0700136 }
137
138public:
139 Name m_testId1;
140 Name m_testId2;
141 Name m_testId3;
142 Name m_randomId;
143
144 Name m_rootCert;
145
146 KeyChain m_keyChain;
147
148 Name m_dsk1;
149 Name m_dsk2;
150 Name m_dsk3;
151
152 Name m_selfSignCert;
153
154 Name m_randomDsk;
155
156 name::Component m_version;
157
Shock Jiang0e2aee02014-11-17 11:19:36 -0800158 shared_ptr<ndn::util::DummyClientFace> m_face;
Shock Jiang0b165f42014-10-24 09:08:09 -0700159};
160
161
162BOOST_FIXTURE_TEST_CASE(Basic, Fixture)
163{
164 // validator must be created after root key is saved to the target
165 ndns::Validator validator(*m_face, TEST_CONFIG_PATH "/" "validator.conf");
166
167 Name dataName(m_testId3);
168 dataName.append("NDNS")
169 .append("rrLabel")
170 .append("rrType")
171 .appendVersion();
172 shared_ptr<Data> data = make_shared<Data>(dataName);
173 m_keyChain.sign(*data, m_dsk3);
174
175 bool hasValidated = false;
176 validator.validate(*data,
177 [&] (const shared_ptr<const Data>& data) {
178 hasValidated = true;
179 BOOST_CHECK(true);
180 },
181 [&] (const shared_ptr<const Data>& data, const std::string& str) {
182 hasValidated = true;
183 BOOST_CHECK(false);
184 });
185
186 m_face->processEvents(time::milliseconds(-1));
187
188 BOOST_CHECK_EQUAL(hasValidated, true);
189
190
191 dataName = m_testId2;
192 dataName.append("KEY")
193 .append("rrLabel")
194 .append("ID-CERT")
195 .appendVersion();
196 data = make_shared<Data>(dataName);
197 m_keyChain.sign(*data, m_dsk3); // key's owner's name is longer than data owner's
198
199 hasValidated = false;
200 validator.validate(*data,
201 [&] (const shared_ptr<const Data>& data) {
202 hasValidated = true;
203 BOOST_CHECK(false);
204 },
205 [&] (const shared_ptr<const Data>& data, const std::string& str) {
206 hasValidated = true;
207 BOOST_CHECK(true);
208 });
209
210 m_face->processEvents(time::milliseconds(-1));
211 // cannot pass verification due to key's owner's name is longer than data owner's
212 BOOST_CHECK_EQUAL(hasValidated, true);
213
214
215 dataName = m_testId3;
216 dataName.append("KEY")
217 .append("rrLabel")
218 .append("ID-CERT")
219 .appendVersion();
220 data = make_shared<Data>(dataName);
221 m_keyChain.sign(*data, m_selfSignCert);
222
223 hasValidated = false;
224 validator.validate(*data,
225 [&] (const shared_ptr<const Data>& data) {
226 hasValidated = true;
227 BOOST_CHECK(false);
228 },
229 [&] (const shared_ptr<const Data>& data, const std::string& str) {
230 hasValidated = true;
231 BOOST_CHECK(true);
232 });
233
234 m_face->processEvents(time::milliseconds(-1));
235 // cannot pass due to self-sign cert is used
236 BOOST_CHECK_EQUAL(hasValidated, true);
237
238 dataName = m_testId2;
239 dataName.append("KEY")
240 .append("rrLabel")
241 .append("ID-CERT")
242 .appendVersion();
243 data = make_shared<Data>(dataName);
244 m_keyChain.sign(*data, m_randomDsk);
245
246 hasValidated = false;
247 validator.validate(*data,
248 [&] (const shared_ptr<const Data>& data) {
249 hasValidated = true;
250 BOOST_CHECK(false);
251 },
252 [&] (const shared_ptr<const Data>& data, const std::string& str) {
253 hasValidated = true;
254 BOOST_CHECK(true);
255 });
256
257 m_face->processEvents(time::milliseconds(-1));
258 // cannot pass due to a totally mismatched key
259 BOOST_CHECK_EQUAL(hasValidated, true);
260}
261
262BOOST_AUTO_TEST_SUITE_END()
263
264} // namespace tests
265} // namespace ndns
266} // namespace ndn