blob: a72a3d8f571c11e8d3dce8c512047dce63e13d85 [file] [log] [blame]
Zhiyi Zhangf5246c42017-01-26 09:39:20 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento914d05f2019-07-13 16:20:19 -04002/*
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -07003 * Copyright (c) 2017-2019, Regents of the University of California.
Zhiyi Zhangf5246c42017-01-26 09:39:20 -08004 *
5 * This file is part of ndncert, a certificate management system based on NDN.
6 *
7 * ndncert is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License along with
16 * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * See AUTHORS.md for complete list of ndncert authors and contributors.
19 */
20
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080021#include "ca-module.hpp"
Zhiyi Zhangad6cf932017-10-26 16:19:15 -070022#include "database-fixture.hpp"
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080023#include "client-module.hpp"
24#include "challenge-module.hpp"
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070025#include "challenge-module/challenge-pin.hpp"
26#include "challenge-module/challenge-email.hpp"
Davide Pesavento914d05f2019-07-13 16:20:19 -040027
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080028#include <ndn-cxx/util/dummy-client-face.hpp>
29#include <ndn-cxx/security/signing-helpers.hpp>
30#include <ndn-cxx/security/transform/public-key.hpp>
31#include <ndn-cxx/security/verification-helpers.hpp>
32
33namespace ndn {
34namespace ndncert {
35namespace tests {
36
Zhiyi Zhangae123bf2017-04-14 12:24:53 -070037BOOST_FIXTURE_TEST_SUITE(TestCaModule, DatabaseFixture)
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080038
39BOOST_AUTO_TEST_CASE(Initialization)
40{
Zhiyi Zhang42d992d2019-07-07 16:46:50 -070041 util::DummyClientFace face(io, {true, true});
42 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Davide Pesavento914d05f2019-07-13 16:20:19 -040043 BOOST_CHECK_EQUAL(ca.getCaConf().m_caName, "/ndn");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080044
45 auto identity = addIdentity(Name("/ndn/site2"));
46 auto key = identity.getDefaultKey();
47 auto cert = key.getDefaultCertificate();
48 ca.getCaStorage()->addCertificate("111", cert);
49 BOOST_CHECK_EQUAL(ca.getCaStorage()->getCertificate("111").getIdentity(), Name("/ndn/site2"));
50
51 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070052 BOOST_CHECK_EQUAL(ca.m_registeredPrefixHandles.size(), 2);
53 BOOST_CHECK_EQUAL(ca.m_interestFilterHandles.size(), 4);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080054}
55
56BOOST_AUTO_TEST_CASE(HandleProbe)
57{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070058 auto identity = addIdentity(Name("/ndn"));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080059 auto key = identity.getDefaultKey();
60 auto cert = key.getDefaultCertificate();
61
Zhiyi Zhang42d992d2019-07-07 16:46:50 -070062 util::DummyClientFace face(io, {true, true});
63 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Yufeng Zhang424d0362019-06-12 16:48:27 -070064 ca.setProbeHandler([&] (const JsonSection& probeInfo) {
65 return "example";
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080066 });
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080067 advanceClocks(time::milliseconds(20), 60);
68
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070069 Interest interest("/ndn/CA/_PROBE");
70 interest.setCanBePrefix(false);
71 JsonSection paramJson;
72 paramJson.add(JSON_CLIENT_PROBE_INFO, "zhiyi");
73 interest.setApplicationParameters(ClientModule::paramFromJson(paramJson));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080074
75 int count = 0;
76 face.onSendData.connect([&] (const Data& response) {
77 count++;
78 BOOST_CHECK(security::verifySignature(response, cert));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070079 auto contentJson = ClientModule::getJsonFromData(response);
Yufeng Zhang424d0362019-06-12 16:48:27 -070080 BOOST_CHECK_EQUAL(contentJson.get<std::string>(JSON_CA_NAME), "/ndn/example");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070081 });
82 face.receive(interest);
83
84 advanceClocks(time::milliseconds(20), 60);
85 BOOST_CHECK_EQUAL(count, 1);
86}
87
88BOOST_AUTO_TEST_CASE(HandleProbeInfo)
89{
90 auto identity = addIdentity(Name("/ndn"));
91 auto key = identity.getDefaultKey();
92 auto cert = key.getDefaultCertificate();
93
Zhiyi Zhang42d992d2019-07-07 16:46:50 -070094 util::DummyClientFace face(io, {true, true});
95 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Yufeng Zhang424d0362019-06-12 16:48:27 -070096 ca.setProbeHandler([&] (const JsonSection& probeInfo) {
97 return "example";
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070098 });
99 advanceClocks(time::milliseconds(20), 60);
100
101 Interest interest("/ndn/CA/_PROBE/INFO");
102 interest.setCanBePrefix(false);
103
104 int count = 0;
105 face.onSendData.connect([&] (const Data& response) {
106 count++;
107 BOOST_CHECK(security::verifySignature(response, cert));
108 auto contentJson = ClientModule::getJsonFromData(response);
109 auto caItem = ClientConfig::extractCaItem(contentJson);
Davide Pesavento914d05f2019-07-13 16:20:19 -0400110 BOOST_CHECK_EQUAL(caItem.m_caName, "/ndn");
Zhiyi Zhanga1fc6232019-06-13 14:56:59 -0700111 BOOST_CHECK_EQUAL(caItem.m_probe, "");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700112 BOOST_CHECK_EQUAL(caItem.m_anchor.wireEncode(), cert.wireEncode());
113 BOOST_CHECK_EQUAL(caItem.m_caInfo, "ndn testbed ca");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800114 });
115 face.receive(interest);
116
117 advanceClocks(time::milliseconds(20), 60);
118 BOOST_CHECK_EQUAL(count, 1);
119}
120
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700121BOOST_AUTO_TEST_CASE(HandleProbeUsingDefaultHandler)
122{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700123 auto identity = addIdentity(Name("/ndn"));
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700124 auto key = identity.getDefaultKey();
125 auto cert = key.getDefaultCertificate();
126
Zhiyi Zhang42d992d2019-07-07 16:46:50 -0700127 util::DummyClientFace face(io, {true, true});
128 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700129 advanceClocks(time::milliseconds(20), 60);
130
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700131 Interest interest("/ndn/CA/_PROBE");
132 interest.setCanBePrefix(false);
133 JsonSection paramJson;
134 paramJson.add(JSON_CLIENT_PROBE_INFO, "zhiyi");
135 interest.setApplicationParameters(ClientModule::paramFromJson(paramJson));
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700136
137 int count = 0;
138 face.onSendData.connect([&] (const Data& response) {
139 count++;
140 BOOST_CHECK(security::verifySignature(response, cert));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700141 auto contentJson = ClientModule::getJsonFromData(response);
142 BOOST_CHECK(contentJson.get<std::string>(JSON_CA_NAME) != "");
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700143 });
144 face.receive(interest);
145
146 advanceClocks(time::milliseconds(20), 60);
147 BOOST_CHECK_EQUAL(count, 1);
148}
149
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800150BOOST_AUTO_TEST_CASE(HandleNew)
151{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700152 auto identity = addIdentity(Name("/ndn"));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800153 auto key = identity.getDefaultKey();
154 auto cert = key.getDefaultCertificate();
155
Zhiyi Zhang42d992d2019-07-07 16:46:50 -0700156 util::DummyClientFace face(io, {true, true});
157 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800158 advanceClocks(time::milliseconds(20), 60);
159
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700160 ClientModule client(m_keyChain);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800161 ClientCaItem item;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700162 item.m_caName = Name("/ndn");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800163 item.m_anchor = cert;
164 client.getClientConf().m_caItems.push_back(item);
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700165
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700166 auto interest = client.generateNewInterest(time::system_clock::now(),
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700167 time::system_clock::now() + time::days(10),
168 Name("/ndn/zhiyi"));
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800169
170 int count = 0;
171 face.onSendData.connect([&] (const Data& response) {
172 count++;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700173 BOOST_CHECK(security::verifySignature(response, cert));
174 auto contentJson = ClientModule::getJsonFromData(response);
175 BOOST_CHECK(contentJson.get<std::string>(JSON_CA_ECDH) != "");
176 BOOST_CHECK(contentJson.get<std::string>(JSON_CA_SALT) != "");
Zhiyi Zhangff4bcb62019-09-08 12:57:42 -0700177 BOOST_CHECK(contentJson.get<std::string>(JSON_CA_REQUEST_ID) != "");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700178 auto challengesJson = contentJson.get_child(JSON_CA_CHALLENGES);
179 BOOST_CHECK(challengesJson.size() != 0);
180
181 client.onNewResponse(response);
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800182 BOOST_CHECK_EQUAL_COLLECTIONS(client.m_aesKey, client.m_aesKey + sizeof(client.m_aesKey),
183 ca.m_aesKey, ca.m_aesKey + sizeof(ca.m_aesKey));
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800184 });
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700185 face.receive(*interest);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800186
187 advanceClocks(time::milliseconds(20), 60);
188 BOOST_CHECK_EQUAL(count, 1);
189}
190
Zhiyi Zhang1a735bc2019-07-04 21:36:49 -0700191BOOST_AUTO_TEST_CASE(HandleNewWithInvalidValidityPeriod1)
192{
193 auto identity = addIdentity(Name("/ndn"));
194 auto key = identity.getDefaultKey();
195 auto cert = key.getDefaultCertificate();
196
197 util::DummyClientFace face(io, {true, true});
198 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test");
199 advanceClocks(time::milliseconds(20), 60);
200
201 ClientModule client(m_keyChain);
202 ClientCaItem item;
203 item.m_caName = Name("/ndn");
204 item.m_anchor = cert;
205 client.getClientConf().m_caItems.push_back(item);
206 auto current_tp = time::system_clock::now();
207 auto interest1 = client.generateNewInterest(current_tp, current_tp - time::hours(1),
208 Name("/ndn/zhiyi"));
209 auto interest2 = client.generateNewInterest(current_tp, current_tp + time::days(361),
210 Name("/ndn/zhiyi"));
211 auto interest3 = client.generateNewInterest(current_tp - time::hours(1),
212 current_tp + time::hours(2),
213 Name("/ndn/zhiyi"));
214 face.onSendData.connect([&] (const Data& response) {
215 BOOST_CHECK(false);
216 });
217 face.receive(*interest1);
218 face.receive(*interest2);
219 face.receive(*interest3);
220
221 advanceClocks(time::milliseconds(20), 60);
222}
223
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700224BOOST_AUTO_TEST_CASE(HandleNewWithProbeToken)
225{
226 auto identity = addIdentity(Name("/ndn"));
227 auto key = identity.getDefaultKey();
228 auto cert = key.getDefaultCertificate();
229
Zhiyi Zhang42d992d2019-07-07 16:46:50 -0700230 util::DummyClientFace face(io, {true, true});
231 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Zhiyi Zhanga1fc6232019-06-13 14:56:59 -0700232 ca.m_config.m_probe = "email";
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700233 advanceClocks(time::milliseconds(20), 60);
234
235 ClientModule client(m_keyChain);
236 ClientCaItem item;
237 item.m_caName = Name("/ndn");
238 item.m_anchor = cert;
239 client.getClientConf().m_caItems.push_back(item);
240
Zhiyi Zhanga1fc6232019-06-13 14:56:59 -0700241 auto data = make_shared<Data>(Name("/ndn/CA/_PROBE/123"));
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700242 m_keyChain.sign(*data, signingByIdentity(ca.m_config.m_caName));
243
244 auto interest = client.generateNewInterest(time::system_clock::now(),
245 time::system_clock::now() + time::days(10),
246 Name("/ndn/zhiyi"), data);
247
248 int count = 0;
249 face.onSendData.connect([&] (const Data& response) {
250 count++;
251 BOOST_CHECK(security::verifySignature(response, cert));
252 });
253 face.receive(*interest);
254
255 advanceClocks(time::milliseconds(20), 60);
256 BOOST_CHECK_EQUAL(count, 1);
257}
258
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700259BOOST_AUTO_TEST_CASE(HandleChallenge)
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800260{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700261 auto identity = addIdentity(Name("/ndn"));
262 auto key = identity.getDefaultKey();
263 auto cert = key.getDefaultCertificate();
264
Zhiyi Zhang42d992d2019-07-07 16:46:50 -0700265 util::DummyClientFace face(io, {true, true});
266 CaModule ca(face, m_keyChain, "tests/unit-tests/ca.conf.test", "ca-storage-memory");
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800267 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700268
269 // generate NEW Interest
270 ClientModule client(m_keyChain);
271 ClientCaItem item;
272 item.m_caName = Name("/ndn");
273 item.m_anchor = cert;
274 client.getClientConf().m_caItems.push_back(item);
275 auto newInterest = client.generateNewInterest(time::system_clock::now(),
276 time::system_clock::now() + time::days(10), Name("/ndn/zhiyi"));
277
278 // generate CHALLENGE Interest
279 ChallengePin pinChallenge;
280 shared_ptr<Interest> challengeInterest = nullptr;
281 shared_ptr<Interest> challengeInterest2 = nullptr;
282 shared_ptr<Interest> challengeInterest3 = nullptr;
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800283
284 int count = 0;
285 face.onSendData.connect([&] (const Data& response) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700286 if (Name("/ndn/CA/_NEW").isPrefixOf(response.getName())) {
287 auto contentJson = ClientModule::getJsonFromData(response);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700288 client.onNewResponse(response);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700289 auto paramJson = pinChallenge.getRequirementForChallenge(client.m_status, client.m_challengeStatus);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700290 challengeInterest = client.generateChallengeInterest(pinChallenge.genChallengeRequestJson(client.m_status,
291 client.m_challengeStatus,
292 paramJson));
293 }
294 else if (Name("/ndn/CA/_CHALLENGE").isPrefixOf(response.getName()) && count == 0) {
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800295 count++;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700296 BOOST_CHECK(security::verifySignature(response, cert));
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800297
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700298 client.onChallengeResponse(response);
299 BOOST_CHECK_EQUAL(client.m_status, STATUS_CHALLENGE);
300 BOOST_CHECK_EQUAL(client.m_challengeStatus, ChallengePin::NEED_CODE);
Davide Pesavento914d05f2019-07-13 16:20:19 -0400301
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700302 auto paramJson = pinChallenge.getRequirementForChallenge(client.m_status, client.m_challengeStatus);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700303 challengeInterest2 = client.generateChallengeInterest(pinChallenge.genChallengeRequestJson(client.m_status,
304 client.m_challengeStatus,
305 paramJson));
306 }
307 else if (Name("/ndn/CA/_CHALLENGE").isPrefixOf(response.getName()) && count == 1) {
308 count++;
309 BOOST_CHECK(security::verifySignature(response, cert));
310
311 client.onChallengeResponse(response);
312 BOOST_CHECK_EQUAL(client.m_status, STATUS_CHALLENGE);
313 BOOST_CHECK_EQUAL(client.m_challengeStatus, ChallengePin::WRONG_CODE);
Davide Pesavento914d05f2019-07-13 16:20:19 -0400314
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700315 auto paramJson = pinChallenge.getRequirementForChallenge(client.m_status, client.m_challengeStatus);
316 auto request = ca.getCertificateRequest(*challengeInterest2);
317 auto secret = request.m_challengeSecrets.get(ChallengePin::JSON_PIN_CODE, "");
Davide Pesavento914d05f2019-07-13 16:20:19 -0400318 for (auto& i : paramJson) {
319 if (i.first == ChallengePin::JSON_PIN_CODE)
320 i.second.put("", secret);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700321 }
322 challengeInterest3 = client.generateChallengeInterest(pinChallenge.genChallengeRequestJson(client.m_status,
323 client.m_challengeStatus,
324 paramJson));
325 }
326 else if (Name("/ndn/CA/_CHALLENGE").isPrefixOf(response.getName()) && count == 2) {
327 count++;
328 BOOST_CHECK(security::verifySignature(response, cert));
329
330 client.onChallengeResponse(response);
331 BOOST_CHECK_EQUAL(client.m_status, STATUS_SUCCESS);
332 BOOST_CHECK_EQUAL(client.m_challengeStatus, CHALLENGE_STATUS_SUCCESS);
333 }
Davide Pesavento914d05f2019-07-13 16:20:19 -0400334 });
335
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700336 face.receive(*newInterest);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800337 advanceClocks(time::milliseconds(20), 60);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700338 face.receive(*challengeInterest);
339 advanceClocks(time::milliseconds(20), 60);
340 face.receive(*challengeInterest2);
341 advanceClocks(time::milliseconds(20), 60);
342 face.receive(*challengeInterest3);
343 advanceClocks(time::milliseconds(20), 60);
344 BOOST_CHECK_EQUAL(count, 3);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800345}
346
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800347BOOST_AUTO_TEST_SUITE_END() // TestCaModule
348
349} // namespace tests
350} // namespace ndncert
351} // namespace ndn