blob: f2aa498ffde99bdffbf01ab4ce9d89db475cec19 [file] [log] [blame]
Zhiyi Zhangf5246c42017-01-26 09:39:20 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2017, Regents of the University of California.
4 *
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
21#include "ca-module.hpp"
22#include "challenge-module.hpp"
23#include "logging.hpp"
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080024#include <ndn-cxx/util/io.hpp>
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080025#include <ndn-cxx/security/verification-helpers.hpp>
26#include <ndn-cxx/security/signing-helpers.hpp>
Junxiao Shi7c068032017-05-28 13:40:47 +000027#include <ndn-cxx/util/random.hpp>
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080028
29namespace ndn {
30namespace ndncert {
31
32_LOG_INIT(ndncert.ca);
33
34CaModule::CaModule(Face& face, security::v2::KeyChain& keyChain,
35 const std::string& configPath, const std::string& storageType)
36 : m_face(face)
37 , m_keyChain(keyChain)
38{
Zhiyi Zhanga63b7372017-05-17 14:14:34 -070039 // load the config and create storage
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080040 m_config.load(configPath);
41 m_storage = CaStorage::createCaStorage(storageType);
42
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080043 registerPrefix();
Zhiyi Zhangf5246c42017-01-26 09:39:20 -080044}
45
46CaModule::~CaModule()
47{
48 for (auto prefixId : m_interestFilterIds) {
49 m_face.unsetInterestFilter(prefixId);
50 }
51 for (auto prefixId : m_registeredPrefixIds) {
52 m_face.unregisterPrefix(prefixId, nullptr, nullptr);
53 }
54}
55
56void
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080057CaModule::registerPrefix()
58{
59 // register localhost list prefix
60 Name localProbePrefix("/localhost/CA/_LIST");
61 auto prefixId = m_face.setInterestFilter(InterestFilter(localProbePrefix),
62 bind(&CaModule::handleLocalhostList, this, _2),
63 bind(&CaModule::onRegisterFailed, this, _2));
64 m_registeredPrefixIds.push_back(prefixId);
65 _LOG_TRACE("Prefix " << localProbePrefix << " got registered");
66
67 // register prefixes for each CA
68 for (const auto& item : m_config.m_caItems) {
69 Name prefix = item.m_caName;
70 prefix.append("CA");
71
72 prefixId = m_face.registerPrefix(prefix,
73 [&] (const Name& name) {
74 // NEW
75 auto filterId = m_face.setInterestFilter(Name(name).append("_NEW"),
76 bind(&CaModule::handleNew, this, _2, item));
77 m_interestFilterIds.push_back(filterId);
78 // SELECT
79 filterId = m_face.setInterestFilter(Name(name).append("_SELECT"),
80 bind(&CaModule::handleSelect, this, _2, item));
81 m_interestFilterIds.push_back(filterId);
82 // VALIDATE
83 filterId = m_face.setInterestFilter(Name(name).append("_VALIDATE"),
84 bind(&CaModule::handleValidate, this, _2, item));
85 m_interestFilterIds.push_back(filterId);
86 // STATUS
87 filterId = m_face.setInterestFilter(Name(name).append("_STATUS"),
88 bind(&CaModule::handleStatus, this, _2, item));
89 m_interestFilterIds.push_back(filterId);
90 // DOWNLOAD
91 filterId = m_face.setInterestFilter(Name(name).append("_DOWNLOAD"),
92 bind(&CaModule::handleDownload, this, _2, item));
93 m_interestFilterIds.push_back(filterId);
94 // PROBE
95 if (item.m_probe != "") {
96 filterId = m_face.setInterestFilter(Name(name).append("_PROBE"),
97 bind(&CaModule::handleProbe, this, _2, item));
98 m_interestFilterIds.push_back(filterId);
99 }
100 // LIST
101 if (item.m_relatedCaList.size() > 0) {
102 filterId = m_face.setInterestFilter(Name(name).append("_LIST"),
103 bind(&CaModule::handleList, this, _2, item));
104 m_interestFilterIds.push_back(filterId);
105 }
106 _LOG_TRACE("Prefix " << name << " got registered");
107 },
108 bind(&CaModule::onRegisterFailed, this, _2));
109 m_registeredPrefixIds.push_back(prefixId);
110 }
111}
112
113void
Zhiyi Zhang7420cf52017-12-18 18:59:21 +0800114CaModule::setProbeHandler(const Name caName, const ProbeHandler& handler)
115{
116 for (auto& entry : m_config.m_caItems) {
117 if (entry.m_caName == caName) {
118 entry.m_probeHandler = handler;
119 }
120 }
121}
122
123void
124CaModule::setRecommendCaHandler(const Name caName, const RecommendCaHandler& handler)
125{
126 for (auto& entry : m_config.m_caItems) {
127 if (entry.m_caName == caName) {
128 entry.m_recommendCaHandler = handler;
129 }
130 }
131}
132
133void
134CaModule::setRequestUpdateCallback(const Name caName, const RequestUpdateCallback& onUpateCallback)
135{
136 for (auto& entry : m_config.m_caItems) {
137 if (entry.m_caName == caName) {
138 entry.m_requestUpdateCallback = onUpateCallback;
139 }
140 }
141}
142
143void
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800144CaModule::handleLocalhostList(const Interest& request)
145{
146 _LOG_TRACE("Got Localhost LIST request");
147
148 JsonSection root;
149 JsonSection caListSection;
150
151 for (const auto& entry : m_config.m_caItems) {
152 JsonSection caItem;
153
154 const auto& pib = m_keyChain.getPib();
155 auto identity = pib.getIdentity(entry.m_caName);
156 auto cert = identity.getDefaultKey().getDefaultCertificate();
157
158 // ca-prefix
159 Name caName = entry.m_caName;
160 caName.append("CA");
161 caItem.put("ca-prefix", caName.toUri());
162
163 // ca-info
164 std::string caInfo;
165 if (entry.m_caInfo == "") {
166 caInfo = "Issued by " + cert.getSignature().getKeyLocator().getName().toUri();
167 }
168 else {
169 caInfo = entry.m_caInfo;
170 }
171 caItem.put("ca-info", caInfo);
172
173 // probe is always false for local client
174
175 // ca-target list
176 caItem.put("target-list", entry.m_targetedList);
177
178 // certificate
179 std::stringstream ss;
180 io::save(cert, ss);
181 caItem.put("certificate", ss.str());
182
183 caListSection.push_back(std::make_pair("", caItem));
184 }
185 root.add_child("ca-list", caListSection);
186
187 Data result;
188 Name dataName = request.getName();
189 dataName.appendTimestamp();
190 result.setName(dataName);
191 result.setContent(dataContentFromJson(root));
192 m_keyChain.sign(result, signingByIdentity(m_keyChain.getPib().getDefaultIdentity().getName()));
193 m_face.put(result);
194}
195
196void
197CaModule::handleList(const Interest& request, const CaItem& caItem)
198{
199 _LOG_TRACE("Got LIST request");
200
201 bool getRecommendation = false;
202 Name recommendedCaName;
203 std::string identityName;
204
205 // LIST naming convention: /CA-prefix/CA/_LIST/[optional info]
206 if (readString(request.getName().at(-1)) != "_LIST" && caItem.m_recommendCaHandler) {
207 const auto& additionInfo = readString(request.getName().at(-1));
208 try {
209 std::tie(recommendedCaName, identityName) = caItem.m_recommendCaHandler(additionInfo, caItem.m_relatedCaList);
210 getRecommendation = true;
211 }
212 catch (const std::exception& e) {
213 _LOG_TRACE("Cannot recommend CA for LIST request. Degrade to non-target list." << e.what());
214 }
215 }
216
217 JsonSection root;
218 JsonSection caListSection;
219 if (getRecommendation) {
220 // JSON format
221 // {
222 // "recommended-ca": "/ndn/edu/ucla"
223 // "recommended-identity": "something"
224 // "trust-schema": "schema Data packet name"
225 // }
226 root.put("recommended-ca", recommendedCaName.toUri());
227 root.put("recommended-identity", identityName);
228 }
229 else {
230 // JSON format
231 // {
232 // "ca-list": [
233 // {"ca-prefix": "/ndn/edu/ucla"},
234 // {"ca-prefix": "/ndn/edu/memphis"},
235 // ...
236 // ]
237 // "trust-schema": "schema Data packet name"
238 // }
239 for (const auto& entry : caItem.m_relatedCaList) {
240 JsonSection caItem;
241 caItem.put("ca-prefix", entry.toUri());
242 caListSection.push_back(std::make_pair("", caItem));
243 }
244 root.add_child("ca-list", caListSection);
245 }
246
247 // TODO: add trust schema
248 std::string schemaDataName = "TODO: add trust schema";
249 root.put("trust-schema", schemaDataName);
250
251 Data result;
252 Name dataName = request.getName();
253 dataName.appendTimestamp();
254 result.setName(dataName);
255 result.setContent(dataContentFromJson(root));
256 m_keyChain.sign(result, signingByIdentity(caItem.m_caName));
257 m_face.put(result);
258}
259
260void
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800261CaModule::handleProbe(const Interest& request, const CaItem& caItem)
262{
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700263 // PROBE Naming Convention: /CA-prefix/CA/_PROBE/<Probe Information>
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800264 _LOG_TRACE("Handle PROBE request");
265
266 std::string identifier;
Zhiyi Zhang7420cf52017-12-18 18:59:21 +0800267 if (caItem.m_probeHandler) {
268 try {
269 identifier = caItem.m_probeHandler(readString(request.getName().at(caItem.m_caName.size() + 2)));
270 }
271 catch (const std::exception& e) {
272 _LOG_TRACE("Cannot generate identifier for PROBE request " << e.what());
273 return;
274 }
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800275 }
Zhiyi Zhang7420cf52017-12-18 18:59:21 +0800276 else {
277 identifier = readString(request.getName().at(caItem.m_caName.size() + 2));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800278 }
279 Name identityName = caItem.m_caName;
280 identityName.append(identifier);
281
282 Data result;
283 result.setName(request.getName());
284 result.setContent(dataContentFromJson(genResponseProbeJson(identityName, "")));
Zhiyi Zhangad6cf932017-10-26 16:19:15 -0700285 m_keyChain.sign(result, signingByIdentity(caItem.m_caName));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800286 m_face.put(result);
287
288 _LOG_TRACE("Handle PROBE: generate identity " << identityName);
289}
290
291void
292CaModule::handleNew(const Interest& request, const CaItem& caItem)
293{
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700294 // NEW Naming Convention: /CA-prefix/CA/_NEW/<certificate-request>/[signature]
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800295 _LOG_TRACE("Handle NEW request");
296
297 security::v2::Certificate clientCert;
298 try {
299 clientCert.wireDecode(request.getName().at(caItem.m_caName.size() + 2).blockFromValue());
300 }
301 catch (const std::exception& e) {
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700302 _LOG_ERROR("Unrecognized certificate request " << e.what());
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800303 return;
304 }
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700305
306 if (!security::verifySignature(clientCert, clientCert)) {
307 _LOG_TRACE("Cert request with bad signature.");
308 return;
309 }
310 if (!security::verifySignature(request, clientCert)) {
311 _LOG_TRACE("Interest with bad signature.");
312 return;
313 }
314
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800315 std::string requestId = std::to_string(random::generateWord64());
316 CertificateRequest certRequest(caItem.m_caName, requestId, clientCert);
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700317 certRequest.setStatus(ChallengeModule::WAIT_SELECTION);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800318 try {
319 m_storage->addRequest(certRequest);
320 }
321 catch (const std::exception& e) {
322 _LOG_TRACE("Cannot add new request instance " << e.what());
323 return;
324 }
325
326 Data result;
327 result.setName(request.getName());
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700328 result.setContent(dataContentFromJson(genResponseNewJson(requestId, certRequest.getStatus(),
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800329 caItem.m_supportedChallenges)));
Zhiyi Zhangad6cf932017-10-26 16:19:15 -0700330 m_keyChain.sign(result, signingByIdentity(caItem.m_caName));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800331 m_face.put(result);
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700332
Zhiyi Zhang7420cf52017-12-18 18:59:21 +0800333 if (caItem.m_requestUpdateCallback) {
334 caItem.m_requestUpdateCallback(certRequest);
335 }
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800336}
337
338void
339CaModule::handleSelect(const Interest& request, const CaItem& caItem)
340{
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700341 // SELECT Naming Convention: /CA-prefix/CA/_SELECT/{Request-ID JSON}/<ChallengeID>/
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800342 // {Param JSON}/[Signature components]
343 _LOG_TRACE("Handle SELECT request");
344
345 CertificateRequest certRequest = getCertificateRequest(request, caItem.m_caName);
346 if (certRequest.getRequestId().empty()) {
347 return;
348 }
349
350 if (!security::verifySignature(request, certRequest.getCert())) {
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700351 _LOG_TRACE("Interest with bad signature.");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800352 return;
353 }
354
355 std::string challengeType;
356 try {
357 challengeType = readString(request.getName().at(caItem.m_caName.size() + 3));
358 }
359 catch (const std::exception& e) {
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700360 _LOG_ERROR(e.what());
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800361 return;
362 }
Zhiyi Zhange30eb352017-04-13 15:26:14 -0700363 _LOG_TRACE("SELECT request choosing challenge " << challengeType);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800364 auto challenge = ChallengeModule::createChallengeModule(challengeType);
365 if (challenge == nullptr) {
366 _LOG_TRACE("Unrecognized challenge type " << challengeType);
367 return;
368 }
369 JsonSection contentJson = challenge->handleChallengeRequest(request, certRequest);
Zhiyi Zhanga9bda732017-05-20 22:58:55 -0700370 if (certRequest.getStatus() == ChallengeModule::FAILURE) {
371 m_storage->deleteRequest(certRequest.getRequestId());
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800372 }
Zhiyi Zhanga9bda732017-05-20 22:58:55 -0700373 else {
374 try {
375 m_storage->updateRequest(certRequest);
376 }
377 catch (const std::exception& e) {
378 _LOG_TRACE("Cannot update request instance " << e.what());
379 return;
380 }
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800381 }
382
383 Data result;
384 result.setName(request.getName());
385 result.setContent(dataContentFromJson(contentJson));
Zhiyi Zhangad6cf932017-10-26 16:19:15 -0700386 m_keyChain.sign(result, signingByIdentity(caItem.m_caName));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800387 m_face.put(result);
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700388
Zhiyi Zhang7420cf52017-12-18 18:59:21 +0800389 if (caItem.m_requestUpdateCallback) {
390 caItem.m_requestUpdateCallback(certRequest);
391 }
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800392}
393
394void
395CaModule::handleValidate(const Interest& request, const CaItem& caItem)
396{
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700397 // VALIDATE Naming Convention: /CA-prefix/CA/_VALIDATE/{Request-ID JSON}/<ChallengeID>/
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800398 // {Param JSON}/[Signature components]
399 _LOG_TRACE("Handle VALIDATE request");
400
401 CertificateRequest certRequest = getCertificateRequest(request, caItem.m_caName);
402 if (certRequest.getRequestId().empty()) {
403 return;
404 }
405
406 if (!security::verifySignature(request, certRequest.getCert())) {
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700407 _LOG_TRACE("Interest with bad signature.");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800408 return;
409 }
410
411 std::string challengeType = certRequest.getChallengeType();
412 auto challenge = ChallengeModule::createChallengeModule(challengeType);
413 if (challenge == nullptr) {
414 _LOG_TRACE("Unrecognized challenge type " << challengeType);
415 return;
416 }
417 JsonSection contentJson = challenge->handleChallengeRequest(request, certRequest);
Zhiyi Zhanga9bda732017-05-20 22:58:55 -0700418 if (certRequest.getStatus() == ChallengeModule::FAILURE) {
419 m_storage->deleteRequest(certRequest.getRequestId());
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800420 }
Zhiyi Zhanga9bda732017-05-20 22:58:55 -0700421 else {
422 try {
423 m_storage->updateRequest(certRequest);
424 }
425 catch (const std::exception& e) {
426 _LOG_TRACE("Cannot update request instance " << e.what());
427 return;
428 }
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800429 }
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800430 Data result;
431 result.setName(request.getName());
432 result.setContent(dataContentFromJson(contentJson));
Zhiyi Zhangad6cf932017-10-26 16:19:15 -0700433 m_keyChain.sign(result, signingByIdentity(caItem.m_caName));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800434 m_face.put(result);
435
Zhiyi Zhang7420cf52017-12-18 18:59:21 +0800436 if (caItem.m_requestUpdateCallback) {
437 caItem.m_requestUpdateCallback(certRequest);
438 }
Zhiyi Zhanga63b7372017-05-17 14:14:34 -0700439
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800440 if (certRequest.getStatus() == ChallengeModule::SUCCESS) {
441 issueCertificate(certRequest, caItem);
442 }
443}
444
445void
446CaModule::handleStatus(const Interest& request, const CaItem& caItem)
447{
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700448 // STATUS Naming Convention: /CA-prefix/CA/_STATUS/{Request-ID JSON}/[Signature components]
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800449 _LOG_TRACE("Handle STATUS request");
450
451 CertificateRequest certRequest = getCertificateRequest(request, caItem.m_caName);
452 if (certRequest.getRequestId().empty()) {
453 return;
454 }
455
456 if (!security::verifySignature(request, certRequest.getCert())) {
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700457 _LOG_TRACE("Interest with bad signature.");
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800458 return;
459 }
460
461 std::string challengeType = certRequest.getChallengeType();
462 auto challenge = ChallengeModule::createChallengeModule(challengeType);
463 if (challenge == nullptr) {
464 _LOG_TRACE("Unrecognized challenge type " << challengeType);
465 return;
466 }
467 JsonSection contentJson = challenge->handleChallengeRequest(request, certRequest);
468
469 Data result;
470 result.setName(request.getName());
471 result.setContent(dataContentFromJson(contentJson));
Zhiyi Zhangad6cf932017-10-26 16:19:15 -0700472 m_keyChain.sign(result, signingByIdentity(caItem.m_caName));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800473 m_face.put(result);
474}
475
476void
477CaModule::handleDownload(const Interest& request, const CaItem& caItem)
478{
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700479 // DOWNLOAD Naming Convention: /CA-prefix/CA/_DOWNLOAD/{Request-ID JSON}
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800480 _LOG_TRACE("Handle DOWNLOAD request");
481
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800482 Data result;
483 result.setName(request.getName());
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800484 if (readString(request.getName().at(-1)) == "ANCHOR") {
485 JsonSection contentJson;
486
487 const auto& pib = m_keyChain.getPib();
488 auto identity = pib.getIdentity(caItem.m_caName);
489 auto cert = identity.getDefaultKey().getDefaultCertificate();
490
491 // ca-prefix
492 Name caName = caItem.m_caName;
493 caName.append("CA");
494 contentJson.put("ca-prefix", caName.toUri());
495
496 // ca-info
497 std::string caInfo;
498 if (caItem.m_caInfo == "") {
499 caInfo = "Issued by " + cert.getSignature().getKeyLocator().getName().toUri();
500 }
501 else {
502 caInfo = caItem.m_caInfo;
503 }
504 contentJson.put("ca-info", caInfo);
505
506 // probe
507 contentJson.put("probe", caItem.m_probe);
508
509 // ca-target list
510 contentJson.put("target-list", caItem.m_targetedList);
511
512 // certificate
513 std::stringstream ss;
514 io::save(cert, ss);
515 contentJson.put("certificate", ss.str());
516
517 result.setContent(dataContentFromJson(contentJson));
518 }
519 else {
520 JsonSection requestIdJson = jsonFromNameComponent(request.getName(), caItem.m_caName.size() + 2);
521 std::string requestId = requestIdJson.get(JSON_REQUEST_ID, "");
522 security::v2::Certificate signedCert;
523 try {
524 signedCert = m_storage->getCertificate(requestId);
525 }
526 catch (const std::exception& e) {
527 _LOG_ERROR(e.what());
528 return;
529 }
530 result.setContent(signedCert.wireEncode());
531 }
Zhiyi Zhangad6cf932017-10-26 16:19:15 -0700532 m_keyChain.sign(result, signingByIdentity(caItem.m_caName));
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800533 m_face.put(result);
534}
535
536void
537CaModule::issueCertificate(const CertificateRequest& certRequest, const CaItem& caItem)
538{
539 Name certName = certRequest.getCert().getKeyName();
540 certName.append("NDNCERT").appendVersion();
541 security::v2::Certificate newCert;
542 newCert.setName(certName);
543 newCert.setContent(certRequest.getCert().getContent());
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700544 _LOG_TRACE("cert request content " << certRequest.getCert());
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800545 SignatureInfo signatureInfo;
546 security::ValidityPeriod period(time::system_clock::now(),
547 time::system_clock::now() + caItem.m_validityPeriod);
548 signatureInfo.setValidityPeriod(period);
Zhiyi Zhangad6cf932017-10-26 16:19:15 -0700549 security::SigningInfo signingInfo(security::SigningInfo::SIGNER_TYPE_ID,
550 caItem.m_caName, signatureInfo);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800551 newCert.setFreshnessPeriod(caItem.m_freshnessPeriod);
552
553 m_keyChain.sign(newCert, signingInfo);
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700554 _LOG_TRACE("new cert got signed" << newCert);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800555 try {
556 m_storage->addCertificate(certRequest.getRequestId(), newCert);
557 m_storage->deleteRequest(certRequest.getRequestId());
558 _LOG_TRACE("New Certificate Issued " << certName);
559 }
560 catch (const std::exception& e) {
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700561 _LOG_ERROR("Cannot add issued cert and remove the request " << e.what());
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800562 return;
563 }
564}
565
566CertificateRequest
567CaModule::getCertificateRequest(const Interest& request, const Name& caName)
568{
569 JsonSection requestIdJson = jsonFromNameComponent(request.getName(), caName.size() + 2);
570 std::string requestId = requestIdJson.get(JSON_REQUEST_ID, "");
571 CertificateRequest certRequest;
572 try {
573 certRequest = m_storage->getRequest(requestId);
574 }
575 catch (const std::exception& e) {
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700576 _LOG_ERROR(e.what());
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800577 }
578 return certRequest;
579}
580
581void
582CaModule::onRegisterFailed(const std::string& reason)
583{
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700584 _LOG_ERROR("Failed to register prefix in local hub's daemon, REASON: " << reason);
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800585}
586
587Block
588CaModule::dataContentFromJson(const JsonSection& jsonSection)
589{
590 std::stringstream ss;
591 boost::property_tree::write_json(ss, jsonSection);
592 return makeStringBlock(ndn::tlv::Content, ss.str());
593}
594
595JsonSection
596CaModule::jsonFromNameComponent(const Name& name, int pos)
597{
598 std::string jsonString;
599 try {
600 jsonString = encoding::readString(name.at(pos));
601 }
602 catch (const std::exception& e) {
Zhiyi Zhang693c1272017-05-20 22:58:55 -0700603 _LOG_ERROR(e.what());
Zhiyi Zhangf5246c42017-01-26 09:39:20 -0800604 return JsonSection();
605 }
606 std::istringstream ss(jsonString);
607 JsonSection json;
608 boost::property_tree::json_parser::read_json(ss, json);
609 return json;
610}
611
612} // namespace ndncert
613} // namespace ndn