blob: 069d796355639c564507ceec7c3d38e919f90413 [file] [log] [blame]
Zhiyi Zhang23564c82017-03-01 10:22:22 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -07003 * Copyright (c) 2017-2020, Regents of the University of California.
Zhiyi Zhang23564c82017-03-01 10:22:22 -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
21#include "client-module.hpp"
22#include "logging.hpp"
Zhiyi Zhanga9bda732017-05-20 22:58:55 -070023#include "challenge-module.hpp"
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070024#include "crypto-support/enc-tlv.hpp"
Suyong Won19fba4d2020-05-09 13:39:46 -070025#include "protocol-detail/info.hpp"
26#include "protocol-detail/probe.hpp"
27#include "protocol-detail/new.hpp"
28#include "protocol-detail/challenge.hpp"
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080029#include <ndn-cxx/util/io.hpp>
Zhiyi Zhang23564c82017-03-01 10:22:22 -080030#include <ndn-cxx/security/signing-helpers.hpp>
31#include <ndn-cxx/security/verification-helpers.hpp>
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070032#include <ndn-cxx/util/random.hpp>
33#include <ndn-cxx/security/transform/base64-encode.hpp>
34#include <ndn-cxx/security/transform/buffer-source.hpp>
35#include <ndn-cxx/security/transform/stream-sink.hpp>
Zhiyi Zhang23564c82017-03-01 10:22:22 -080036
37namespace ndn {
38namespace ndncert {
39
40_LOG_INIT(ndncert.client);
41
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070042ClientModule::ClientModule(security::v2::KeyChain& keyChain)
43 : m_keyChain(keyChain)
Zhiyi Zhang23564c82017-03-01 10:22:22 -080044{
45}
46
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070047ClientModule::~ClientModule()
48{
49 endSession();
50}
Davide Pesavento08994782018-01-22 12:13:41 -050051
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070052shared_ptr<Interest>
swa77020643ac2020-03-26 02:24:45 -070053ClientModule::generateInfoInterest(const Name& caName)
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080054{
55 Name interestName = caName;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070056 if (readString(caName.at(-1)) != "CA")
57 interestName.append("CA");
swa77020643ac2020-03-26 02:24:45 -070058 interestName.append("INFO");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070059 auto interest = make_shared<Interest>(interestName);
60 interest->setMustBeFresh(true);
61 interest->setCanBePrefix(false);
62 return interest;
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080063}
64
Zhiyi Zhangcaab5462019-10-18 13:41:02 -070065bool
Suyong Won19fba4d2020-05-09 13:39:46 -070066ClientModule::verifyInfoResponse(const Data& reply)
Zhiyi Zhangcaab5462019-10-18 13:41:02 -070067{
68 // parse the ca item
Suyong Won19fba4d2020-05-09 13:39:46 -070069 auto caItem = INFO::decodeClientConfigFromContent(reply.getContent());
Zhiyi Zhangcaab5462019-10-18 13:41:02 -070070
71 // verify the probe Data's sig
72 if (!security::verifySignature(reply, caItem.m_anchor)) {
Suyong Won256c9062020-05-11 02:45:56 -070073 _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caPrefix.toUri());
Zhiyi Zhangcaab5462019-10-18 13:41:02 -070074 return false;
75 }
76 return true;
77}
78
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080079void
Suyong Won19fba4d2020-05-09 13:39:46 -070080ClientModule::addCaFromInfoResponse(const Data& reply)
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080081{
Suyong Won57462ca2020-05-05 22:20:09 -070082 const Block& contentBlock = reply.getContent();
83
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070084 // parse the ca item
Suyong Won19fba4d2020-05-09 13:39:46 -070085 auto caItem = INFO::decodeClientConfigFromContent(contentBlock);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080086
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070087 // update the local config
88 bool findItem = false;
89 for (auto& item : m_config.m_caItems) {
Suyong Won256c9062020-05-11 02:45:56 -070090 if (item.m_caPrefix == caItem.m_caPrefix) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070091 findItem = true;
92 item = caItem;
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080093 }
94 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070095 if (!findItem) {
96 m_config.m_caItems.push_back(caItem);
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +080097 }
Zhiyi Zhang23564c82017-03-01 10:22:22 -080098}
99
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700100shared_ptr<Interest>
101ClientModule::generateProbeInterest(const ClientCaItem& ca, const std::string& probeInfo)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800102{
Suyong Won256c9062020-05-11 02:45:56 -0700103 Name interestName = ca.m_caPrefix;
swa770de007bc2020-03-24 21:26:21 -0700104 interestName.append("CA").append("PROBE");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700105 auto interest = make_shared<Interest>(interestName);
106 interest->setMustBeFresh(true);
107 interest->setCanBePrefix(false);
Suyong Won19fba4d2020-05-09 13:39:46 -0700108 interest->setApplicationParameters(
109 PROBE::encodeApplicationParametersFromProbeInfo(ca, probeInfo)
110 );
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700111
112 // update local state
113 m_ca = ca;
114 return interest;
115}
116
117void
118ClientModule::onProbeResponse(const Data& reply)
119{
120 if (!security::verifySignature(reply, m_ca.m_anchor)) {
Suyong Won256c9062020-05-11 02:45:56 -0700121 _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caPrefix.toUri());
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700122 return;
123 }
Suyong Won19fba4d2020-05-09 13:39:46 -0700124
125 auto contentTLV = reply.getContent();
Suyong Won44d0cce2020-05-10 04:07:43 -0700126 contentTLV.parse();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700127
128 // read the available name and put it into the state
Suyong Won19fba4d2020-05-09 13:39:46 -0700129 if (contentTLV.get(tlv_probe_response).hasValue()) {
Suyong Wonb29e0da2020-05-12 01:59:15 -0700130 Block probeResponseBlock = contentTLV.get(tlv_probe_response);
131 probeResponseBlock.parse();
132 m_identityName.wireDecode(probeResponseBlock.get(tlv::Name));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700133 }
Zhiyi Zhang781a5602019-06-26 19:05:04 -0700134 else {
135 NDN_LOG_TRACE("The JSON_CA_NAME is empty.");
136 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700137}
138
139shared_ptr<Interest>
140ClientModule::generateNewInterest(const time::system_clock::TimePoint& notBefore,
141 const time::system_clock::TimePoint& notAfter,
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700142 const Name& identityName, const shared_ptr<Data>& probeToken)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700143{
144 // Name requestedName = identityName;
145 if (!identityName.empty()) { // if identityName is not empty, find the corresponding CA
146 bool findCa = false;
147 for (const auto& caItem : m_config.m_caItems) {
Suyong Won256c9062020-05-11 02:45:56 -0700148 if (caItem.m_caPrefix.isPrefixOf(identityName)) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700149 m_ca = caItem;
150 findCa = true;
151 }
152 }
153 if (!findCa) { // if cannot find, cannot proceed
154 return nullptr;
155 }
156 m_identityName = identityName;
157 }
158 else { // if identityName is empty, check m_identityName or generate a random name
159 if (!m_identityName.empty()) {
160 // do nothing
161 }
162 else {
Zhiyi Zhang781a5602019-06-26 19:05:04 -0700163 NDN_LOG_TRACE("Randomly create a new name because m_identityName is empty and the param is empty.");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700164 auto id = std::to_string(random::generateSecureWord64());
Suyong Won256c9062020-05-11 02:45:56 -0700165 m_identityName = m_ca.m_caPrefix;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700166 m_identityName.append(id);
167 }
168 }
169
170 // generate a newly key pair or use an existing key
Zhiyi Zhang10130782018-02-01 18:28:49 -0800171 const auto& pib = m_keyChain.getPib();
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700172 security::pib::Identity identity;
Zhiyi Zhang10130782018-02-01 18:28:49 -0800173 try {
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700174 identity = pib.getIdentity(m_identityName);
Zhiyi Zhang10130782018-02-01 18:28:49 -0800175 }
176 catch (const security::Pib::Error& e) {
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700177 identity = m_keyChain.createIdentity(m_identityName);
178 m_isNewlyCreatedIdentity = true;
179 m_isNewlyCreatedKey = true;
180 }
181 try {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700182 m_key = identity.getDefaultKey();
Zhiyi Zhang10130782018-02-01 18:28:49 -0800183 }
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700184 catch (const security::Pib::Error& e) {
185 m_key = m_keyChain.createKey(identity);
186 m_isNewlyCreatedKey = true;
187 }
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800188
189 // generate certificate request
190 security::v2::Certificate certRequest;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700191 certRequest.setName(Name(m_key.getName()).append("cert-request").appendVersion());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800192 certRequest.setContentType(tlv::ContentType_Key);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700193 certRequest.setContent(m_key.getPublicKey().data(), m_key.getPublicKey().size());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800194 SignatureInfo signatureInfo;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700195 signatureInfo.setValidityPeriod(security::ValidityPeriod(notBefore, notAfter));
196 m_keyChain.sign(certRequest, signingByKey(m_key.getName()).setSignatureInfo(signatureInfo));
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800197
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700198 // generate Interest packet
Suyong Won256c9062020-05-11 02:45:56 -0700199 Name interestName = m_ca.m_caPrefix;
swa770de007bc2020-03-24 21:26:21 -0700200 interestName.append("CA").append("NEW");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700201 auto interest = make_shared<Interest>(interestName);
202 interest->setMustBeFresh(true);
203 interest->setCanBePrefix(false);
Suyong Won19fba4d2020-05-09 13:39:46 -0700204 interest->setApplicationParameters(
205 NEW::encodeApplicationParameters(m_ecdh.getBase64PubKey(), certRequest, probeToken)
206 );
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800207
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700208 // sign the Interest packet
209 m_keyChain.sign(*interest, signingByKey(m_key.getName()));
210 return interest;
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800211}
212
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700213std::list<std::string>
214ClientModule::onNewResponse(const Data& reply)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800215{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700216 if (!security::verifySignature(reply, m_ca.m_anchor)) {
Suyong Won256c9062020-05-11 02:45:56 -0700217 _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caPrefix.toUri());
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700218 return std::list<std::string>();
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800219 }
Suyong Won19fba4d2020-05-09 13:39:46 -0700220 auto contentTLV = reply.getContent();
Suyong Won44d0cce2020-05-10 04:07:43 -0700221 contentTLV.parse();
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800222
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700223 // ECDH
Suyong Won19fba4d2020-05-09 13:39:46 -0700224 const auto& peerKeyBase64Str = readString(contentTLV.get(tlv_ecdh_pub));
225 const auto& saltStr = readString(contentTLV.get(tlv_salt));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700226 uint64_t saltInt = std::stoull(saltStr);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700227 m_ecdh.deriveSecret(peerKeyBase64Str);
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800228
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700229 // HKDF
Zhiyi Zhang36706832019-07-04 21:33:03 -0700230 hkdf(m_ecdh.context->sharedSecret, m_ecdh.context->sharedSecretLen,
231 (uint8_t*)&saltInt, sizeof(saltInt), m_aesKey, sizeof(m_aesKey));
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800232
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700233 // update state
Suyong Won19fba4d2020-05-09 13:39:46 -0700234 m_status = readNonNegativeInteger(contentTLV.get(tlv_status));
235 m_requestId = readString(contentTLV.get(tlv_request_id));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700236 m_challengeList.clear();
Suyong Won19fba4d2020-05-09 13:39:46 -0700237 for (auto const& element : contentTLV.elements()) {
238 if (element.type() == tlv_challenge) {
239 m_challengeList.push_back(readString(element));
240 }
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800241 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700242 return m_challengeList;
243}
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800244
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700245shared_ptr<Interest>
Suyong Won19fba4d2020-05-09 13:39:46 -0700246ClientModule::generateChallengeInterest(const Block& challengeRequest)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700247{
Suyong Won44d0cce2020-05-10 04:07:43 -0700248 challengeRequest.parse();
Suyong Won19fba4d2020-05-09 13:39:46 -0700249 m_challengeType = readString(challengeRequest.get(tlv_selected_challenge));
Suyong Won44d0cce2020-05-10 04:07:43 -0700250
Suyong Won256c9062020-05-11 02:45:56 -0700251 Name interestName = m_ca.m_caPrefix;
swa770de007bc2020-03-24 21:26:21 -0700252 interestName.append("CA").append("CHALLENGE").append(m_requestId);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700253 auto interest = make_shared<Interest>(interestName);
254 interest->setMustBeFresh(true);
255 interest->setCanBePrefix(false);
256
257 // encrypt the Interest parameters
Suyong Won7968f7a2020-05-12 01:01:25 -0700258 auto paramBlock = encodeBlockWithAesGcm128(tlv::ApplicationParameters, m_aesKey,
259 challengeRequest.value(), challengeRequest.value_size(), (const uint8_t*)"test", strlen("test"));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700260 interest->setApplicationParameters(paramBlock);
261
262 m_keyChain.sign(*interest, signingByKey(m_key.getName()));
263 return interest;
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800264}
265
266void
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700267ClientModule::onChallengeResponse(const Data& reply)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800268{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700269 if (!security::verifySignature(reply, m_ca.m_anchor)) {
Suyong Won256c9062020-05-11 02:45:56 -0700270 _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caPrefix.toUri());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800271 return;
272 }
Zhiyi Zhangb8cb0472020-05-05 20:55:05 -0700273 auto result = decodeBlockWithAesGcm128(reply.getContent(), m_aesKey, (const uint8_t*)"test", strlen("test"));
Suyong Won19fba4d2020-05-09 13:39:46 -0700274
Suyong Won44d0cce2020-05-10 04:07:43 -0700275 Block contentTLV = makeBinaryBlock(tlv_encrypted_payload, result.data(), result.size());
276 contentTLV.parse();
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800277
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700278 // update state
Suyong Won19fba4d2020-05-09 13:39:46 -0700279 m_status = readNonNegativeInteger(contentTLV.get(tlv_status));
280 m_challengeStatus = readString(contentTLV.get(tlv_challenge_status));
281 m_remainingTries = readNonNegativeInteger(contentTLV.get(tlv_remaining_tries));
282 m_freshBefore = time::system_clock::now() +
283 time::seconds(readNonNegativeInteger(contentTLV.get(tlv_remaining_time)));
284
Suyong Won7968f7a2020-05-12 01:01:25 -0700285 if (contentTLV.find(tlv_issued_cert_name) != contentTLV.elements_end()) {
286 Block issuedCertNameBlock = contentTLV.get(tlv_issued_cert_name);
287 issuedCertNameBlock.parse();
288 m_issuedCertName.wireDecode(issuedCertNameBlock.get(tlv::Name));
289 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700290}
Zhiyi Zhange30eb352017-04-13 15:26:14 -0700291
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700292shared_ptr<Interest>
293ClientModule::generateDownloadInterest()
294{
Suyong Won256c9062020-05-11 02:45:56 -0700295 Name interestName = m_ca.m_caPrefix;
swa770de007bc2020-03-24 21:26:21 -0700296 interestName.append("CA").append("DOWNLOAD").append(m_requestId);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700297 auto interest = make_shared<Interest>(interestName);
298 interest->setMustBeFresh(true);
299 interest->setCanBePrefix(false);
300 return interest;
301}
Zhiyi Zhange30eb352017-04-13 15:26:14 -0700302
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700303shared_ptr<Interest>
304ClientModule::generateCertFetchInterest()
305{
swa770cf1d8f72020-04-21 23:12:39 -0700306 Name interestName = m_issuedCertName;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700307 auto interest = make_shared<Interest>(interestName);
308 interest->setMustBeFresh(true);
309 interest->setCanBePrefix(false);
310 return interest;
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800311}
312
swa770cf1d8f72020-04-21 23:12:39 -0700313void
314ClientModule::onCertFetchResponse(const Data& reply)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800315{
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800316 try {
317 security::v2::Certificate cert(reply.getContent().blockFromValue());
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700318 m_keyChain.addCertificate(m_key, cert);
swa770cf1d8f72020-04-21 23:12:39 -0700319 _LOG_TRACE("Fetched and installed the cert " << cert.getName());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800320 }
321 catch (const std::exception& e) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700322 _LOG_ERROR("Cannot add replied certificate into the keychain " << e.what());
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700323 return nullptr;
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800324 }
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800325}
326
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800327JsonSection
328ClientModule::getJsonFromData(const Data& data)
329{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700330 std::istringstream ss(encoding::readString(data.getContent()));
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800331 JsonSection json;
332 boost::property_tree::json_parser::read_json(ss, json);
333 return json;
334}
335
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700336std::vector<std::string>
337ClientModule::parseProbeComponents(const std::string& probe)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700338{
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700339 std::vector<std::string> components;
Yufeng Zhang424d0362019-06-12 16:48:27 -0700340 std::string delimiter = ":";
341 size_t last = 0;
342 size_t next = 0;
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700343 while ((next = probe.find(delimiter, last)) != std::string::npos) {
344 components.push_back(probe.substr(last, next - last));
345 last = next + 1;
346 }
347 components.push_back(probe.substr(last));
348 return components;
349}
Yufeng Zhang424d0362019-06-12 16:48:27 -0700350
swa77020643ac2020-03-26 02:24:45 -0700351JsonSection
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700352ClientModule::genProbeRequestJson(const ClientCaItem& ca, const std::string& probeInfo)
353{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700354 JsonSection root;
Zhiyi Zhang547c8512019-06-18 23:46:14 -0700355 std::vector<std::string> fields = parseProbeComponents(ca.m_probe);
356 std::vector<std::string> arguments = parseProbeComponents(probeInfo);;
Yufeng Zhang424d0362019-06-12 16:48:27 -0700357
358 if (arguments.size() != fields.size()) {
359 BOOST_THROW_EXCEPTION(Error("Error in genProbeRequestJson: argument list does not match field list in the config file."));
360 }
Yufeng Zhang424d0362019-06-12 16:48:27 -0700361 for (size_t i = 0; i < fields.size(); ++i) {
362 root.put(fields.at(i), arguments.at(i));
363 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700364 return root;
365}
366
swa77020643ac2020-03-26 02:24:45 -0700367JsonSection
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700368ClientModule::genNewRequestJson(const std::string& ecdhPub, const security::v2::Certificate& certRequest,
369 const shared_ptr<Data>& probeToken)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700370{
371 JsonSection root;
372 std::stringstream ss;
373 try {
374 security::transform::bufferSource(certRequest.wireEncode().wire(), certRequest.wireEncode().size())
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800375 >> security::transform::base64Encode(false)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700376 >> security::transform::streamSink(ss);
377 }
378 catch (const security::transform::Error& e) {
379 _LOG_ERROR("Cannot convert self-signed cert into BASE64 string " << e.what());
380 return root;
381 }
382 root.put(JSON_CLIENT_ECDH, ecdhPub);
383 root.put(JSON_CLIENT_CERT_REQ, ss.str());
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700384 if (probeToken != nullptr) {
385 // clear the stringstream
386 ss.str("");
387 ss.clear();
388 // transform the probe data into a base64 string
389 try {
390 security::transform::bufferSource(probeToken->wireEncode().wire(), probeToken->wireEncode().size())
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800391 >> security::transform::base64Encode(false)
Zhiyi Zhang5f749a22019-06-12 17:02:33 -0700392 >> security::transform::streamSink(ss);
393 }
394 catch (const security::transform::Error& e) {
395 _LOG_ERROR("Cannot convert self-signed cert into BASE64 string " << e.what());
396 return root;
397 }
398 // add the token into the JSON
399 root.put("probe-token", ss.str());
400 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700401 return root;
402}
403
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800404Block
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700405ClientModule::paramFromJson(const JsonSection& json)
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800406{
407 std::stringstream ss;
408 boost::property_tree::write_json(ss, json);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700409 return makeStringBlock(ndn::tlv::ApplicationParameters, ss.str());
Zhiyi Zhang23564c82017-03-01 10:22:22 -0800410}
411
412} // namespace ndncert
413} // namespace ndn