Update the NDNCERT library to version NDNCERT v2
spec:[https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-new]
Change-Id: Ia480a8e70c4b38ca170dfe2fcf50d1265ab65f46
diff --git a/src/client-module.cpp b/src/client-module.cpp
index 0c9565e..5b03a23 100644
--- a/src/client-module.cpp
+++ b/src/client-module.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2017-2018, Regents of the University of California.
+ * Copyright (c) 2017-2019, Regents of the University of California.
*
* This file is part of ndncert, a certificate management system based on NDN.
*
@@ -20,511 +20,323 @@
#include "client-module.hpp"
#include "logging.hpp"
-#include "json-helper.hpp"
#include "challenge-module.hpp"
+#include "crypto-support/enc-tlv.hpp"
#include <ndn-cxx/util/io.hpp>
#include <ndn-cxx/security/signing-helpers.hpp>
#include <ndn-cxx/security/verification-helpers.hpp>
+#include <ndn-cxx/util/random.hpp>
+#include <ndn-cxx/security/transform/base64-encode.hpp>
+#include <ndn-cxx/security/transform/buffer-source.hpp>
+#include <ndn-cxx/security/transform/stream-sink.hpp>
namespace ndn {
namespace ndncert {
_LOG_INIT(ndncert.client);
-ClientModule::ClientModule(Face& face, security::v2::KeyChain& keyChain, size_t retryTimes)
- : m_face(face)
- , m_keyChain(keyChain)
- , m_retryTimes(retryTimes)
+ClientModule::ClientModule(security::v2::KeyChain& keyChain)
+ : m_keyChain(keyChain)
{
}
ClientModule::~ClientModule() = default;
-void
-ClientModule::requestCaTrustAnchor(const Name& caName, const DataCallback& trustAnchorCallback,
- const ErrorCallback& errorCallback)
+shared_ptr<Interest>
+ClientModule::generateProbeInfoInterest(const Name& caName)
{
Name interestName = caName;
- interestName.append("CA").append("_DOWNLOAD").append("ANCHOR");
- Interest interest(interestName);
- interest.setMustBeFresh(true);
-
- m_face.expressInterest(interest, trustAnchorCallback,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- trustAnchorCallback, errorCallback));
+ if (readString(caName.at(-1)) != "CA")
+ interestName.append("CA");
+ interestName.append("_PROBE").append("INFO");
+ auto interest = make_shared<Interest>(interestName);
+ interest->setMustBeFresh(true);
+ interest->setCanBePrefix(false);
+ return interest;
}
void
-ClientModule::requestLocalhostList(const LocalhostListCallback& listCallback,
- const ErrorCallback& errorCallback)
+ClientModule::onProbeInfoResponse(const Data& reply)
{
- Interest interest(Name("/localhost/CA/_LIST"));
- interest.setMustBeFresh(true);
- DataCallback dataCb = bind(&ClientModule::handleLocalhostListResponse,
- this, _1, _2, listCallback, errorCallback);
- m_face.expressInterest(interest, dataCb,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- dataCb, errorCallback));
-}
+ // parse the ca item
+ auto contentJson = getJsonFromData(reply);
+ auto caItem = ClientConfig::extractCaItem(contentJson);
-void
-ClientModule::handleLocalhostListResponse(const Interest& request, const Data& reply,
- const LocalhostListCallback& listCallback,
- const ErrorCallback& errorCallback)
-{
- // TODO: use the file path to replace the cert
- // const auto& pib = m_keyChain.getPib();
- // auto identity = pib.getDefaultIdentity();
- // auto key = identity.getDefaultKey();
- // auto cert = key.getDefaultCertificate();
-
- auto cert = *(io::load<security::v2::Certificate>(m_config.m_localNdncertAnchor));
-
- if (!security::verifySignature(reply, cert)) {
- errorCallback("Cannot verify data from localhost CA");
- return;
- };
-
- JsonSection contentJson = getJsonFromData(reply);
- ClientConfig clientConf;
- clientConf.load(contentJson);
- listCallback(clientConf);
-}
-
-void
-ClientModule::requestList(const ClientCaItem& ca, const std::string& additionalInfo,
- const ListCallback& listCallback, const ErrorCallback& errorCallback)
-{
- Name requestName(ca.m_caName);
- requestName.append("_LIST");
- if (additionalInfo != "") {
- requestName.append(additionalInfo);
- }
- Interest interest(requestName);
- interest.setMustBeFresh(true);
- DataCallback dataCb = bind(&ClientModule::handleListResponse,
- this, _1, _2, ca, listCallback, errorCallback);
- m_face.expressInterest(interest, dataCb,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- dataCb, errorCallback));
-}
-
-void
-ClientModule::handleListResponse(const Interest& request, const Data& reply,
- const ClientCaItem& ca,
- const ListCallback& listCallback,
- const ErrorCallback& errorCallback)
-{
- if (!security::verifySignature(reply, ca.m_anchor)) {
- errorCallback("Cannot verify data from " + ca.m_caName.toUri());
- return;
- };
-
- std::list<Name> caList;
- Name assignedName;
-
- JsonSection contentJson = getJsonFromData(reply);
- auto recommendedName = contentJson.get("recommended-identity", "");
- if (recommendedName == "") {
- // without recommendation
- auto caListJson = contentJson.get_child("ca-list");
- auto it = caListJson.begin();
- for(; it != caListJson.end(); it++) {
- caList.push_back(Name(it->second.get<std::string>("ca-prefix")));
+ // update the local config
+ bool findItem = false;
+ for (auto& item : m_config.m_caItems) {
+ if (item.m_caName == caItem.m_caName) {
+ findItem = true;
+ item = caItem;
}
}
- else {
- // with recommendation
- Name caName(contentJson.get<std::string>("recommended-ca"));
- caList.push_back(caName);
- assignedName = caName.append(recommendedName);
+ if (!findItem) {
+ m_config.m_caItems.push_back(caItem);
}
- Name schemaDataName(contentJson.get("trust-schema", ""));
- listCallback(caList, assignedName, schemaDataName);
-}
-void
-ClientModule::sendProbe(const ClientCaItem& ca, const std::string& probeInfo,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
-{
- Interest interest(Name(ca.m_caName).append("_PROBE").append(probeInfo));
- interest.setMustBeFresh(true);
- DataCallback dataCb = bind(&ClientModule::handleProbeResponse,
- this, _1, _2, ca, requestCallback, errorCallback);
- m_face.expressInterest(interest, dataCb,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- dataCb, errorCallback));
-
- _LOG_TRACE("PROBE interest sent with Probe info " << probeInfo);
-}
-
-void
-ClientModule::handleProbeResponse(const Interest& request, const Data& reply,
- const ClientCaItem& ca,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
-{
- if (!security::verifySignature(reply, ca.m_anchor)) {
- errorCallback("Cannot verify data from " + ca.m_caName.toUri());
- return;
- };
- JsonSection contentJson = getJsonFromData(reply);
- std::string identityNameString = contentJson.get(JSON_IDNENTIFIER, "");
- if (!identityNameString.empty()) {
- Name identityName(identityNameString);
- sendNew(ca, identityName, requestCallback, errorCallback);
-
- _LOG_TRACE("Got PROBE response with identity " << identityName);
- }
- else {
- errorCallback("The response does not carry required fields.");
+ // verify the probe Data's sig
+ if (!security::verifySignature(reply, caItem.m_anchor)) {
+ _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
return;
}
}
-void
-ClientModule::sendNew(const ClientCaItem& ca, const Name& identityName,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
+shared_ptr<Interest>
+ClientModule::generateProbeInterest(const ClientCaItem& ca, const std::string& probeInfo)
{
+ Name interestName = ca.m_caName;
+ interestName.append("CA").append("_PROBE");
+ auto interest = make_shared<Interest>(interestName);
+ interest->setMustBeFresh(true);
+ interest->setCanBePrefix(false);
+ auto paramJson = genProbeRequestJson(probeInfo);
+ interest->setApplicationParameters(paramFromJson(paramJson));
+
+ // update local state
+ m_ca = ca;
+ return interest;
+}
+
+void
+ClientModule::onProbeResponse(const Data& reply)
+{
+ if (!security::verifySignature(reply, m_ca.m_anchor)) {
+ _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
+ return;
+ }
+ auto contentJson = getJsonFromData(reply);
+
+ // read the available name and put it into the state
+ auto nameUri = contentJson.get<std::string>(JSON_CA_NAME, "");
+ if (nameUri != "") {
+ m_identityName = Name(nameUri);
+ }
+}
+
+shared_ptr<Interest>
+ClientModule::generateNewInterest(const time::system_clock::TimePoint& notBefore,
+ const time::system_clock::TimePoint& notAfter,
+ const Name& identityName)
+{
+ // Name requestedName = identityName;
+ if (!identityName.empty()) { // if identityName is not empty, find the corresponding CA
+ bool findCa = false;
+ for (const auto& caItem : m_config.m_caItems) {
+ if (caItem.m_caName.isPrefixOf(identityName)) {
+ m_ca = caItem;
+ findCa = true;
+ }
+ }
+ if (!findCa) { // if cannot find, cannot proceed
+ return nullptr;
+ }
+ m_identityName = identityName;
+ }
+ else { // if identityName is empty, check m_identityName or generate a random name
+ if (!m_identityName.empty()) {
+ // do nothing
+ }
+ else {
+ auto id = std::to_string(random::generateSecureWord64());
+ m_identityName = m_ca.m_caName;
+ m_identityName.append(id);
+ }
+ }
+
+ // generate a newly key pair or use an existing key
const auto& pib = m_keyChain.getPib();
-
- auto state = make_shared<RequestState>();
try {
- auto identity = pib.getIdentity(identityName);
- state->m_key = m_keyChain.createKey(identity);
+ auto identity = pib.getIdentity(m_identityName);
+ m_key = m_keyChain.createKey(identity);
}
catch (const security::Pib::Error& e) {
- auto identity = m_keyChain.createIdentity(identityName);
- state->m_key = identity.getDefaultKey();
+ auto identity = m_keyChain.createIdentity(m_identityName);
+ m_key = identity.getDefaultKey();
}
- state->m_ca = ca;
- state->m_isInstalled = false;
// generate certificate request
security::v2::Certificate certRequest;
- certRequest.setName(Name(state->m_key.getName()).append("cert-request").appendVersion());
+ certRequest.setName(Name(m_key.getName()).append("cert-request").appendVersion());
certRequest.setContentType(tlv::ContentType_Key);
certRequest.setFreshnessPeriod(time::hours(24));
- certRequest.setContent(state->m_key.getPublicKey().data(), state->m_key.getPublicKey().size());
+ certRequest.setContent(m_key.getPublicKey().data(), m_key.getPublicKey().size());
SignatureInfo signatureInfo;
- signatureInfo.setValidityPeriod(security::ValidityPeriod(time::system_clock::now(),
- time::system_clock::now() + time::days(10)));
- m_keyChain.sign(certRequest, signingByKey(state->m_key.getName()).setSignatureInfo(signatureInfo));
+ signatureInfo.setValidityPeriod(security::ValidityPeriod(notBefore, notAfter));
+ m_keyChain.sign(certRequest, signingByKey(m_key.getName()).setSignatureInfo(signatureInfo));
- // generate interest
- Interest interest(Name(ca.m_caName).append(Name("_NEW")).append(certRequest.wireEncode()));
- m_keyChain.sign(interest, signingByKey(state->m_key.getName()));
+ // generate Interest packet
+ Name interestName = m_ca.m_caName;
+ interestName.append("CA").append("_NEW");
+ auto interest = make_shared<Interest>(interestName);
+ interest->setMustBeFresh(true);
+ interest->setCanBePrefix(false);
+ interest->setApplicationParameters(paramFromJson(genNewRequestJson(m_ecdh.getBase64PubKey(), certRequest)));
- DataCallback dataCb = bind(&ClientModule::handleNewResponse,
- this, _1, _2, state, requestCallback, errorCallback);
- m_face.expressInterest(interest, dataCb,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- dataCb, errorCallback));
-
- _LOG_TRACE("NEW interest sent with identity " << identityName);
+ // sign the Interest packet
+ m_keyChain.sign(*interest, signingByKey(m_key.getName()));
+ return interest;
}
-void
-ClientModule::handleNewResponse(const Interest& request, const Data& reply,
- const shared_ptr<RequestState>& state,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
+std::list<std::string>
+ClientModule::onNewResponse(const Data& reply)
{
- if (!security::verifySignature(reply, state->m_ca.m_anchor)) {
- errorCallback("Cannot verify data from " + state->m_ca.m_caName.toUri());
- return;
+ if (!security::verifySignature(reply, m_ca.m_anchor)) {
+ _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
+ return std::list<std::string>();
}
+ auto contentJson = getJsonFromData(reply);
- const JsonSection& json = getJsonFromData(reply);
- state->m_status = json.get(JSON_STATUS, "");
- state->m_requestId = json.get(JSON_REQUEST_ID, "");
+ // ECDH
+ const auto& peerKeyBase64Str = contentJson.get<std::string>(JSON_CA_ECDH, "");
+ const auto& saltStr = contentJson.get<std::string>(JSON_CA_SALT, "");
+ uint64_t saltInt = std::stoull(saltStr);
+ uint8_t salt[sizeof(saltInt)];
+ std::memcpy(salt, &saltInt, sizeof(saltInt));
+ m_ecdh.deriveSecret(peerKeyBase64Str);
- if (!checkStatus(*state, json, errorCallback)) {
- return;
- }
+ // HKDF
+ hkdf(m_ecdh.context->sharedSecret, m_ecdh.context->sharedSecretLen, salt, sizeof(saltInt), m_aesKey, 32);
- JsonSection challengesJson = json.get_child(JSON_CHALLENGES);
- std::list<std::string> challengeList;
+ // update state
+ m_status = contentJson.get<int>(JSON_CA_STATUS);
+ m_requestId = contentJson.get<std::string>(JSON_CA_EQUEST_ID, "");
+
+ auto challengesJson = contentJson.get_child(JSON_CA_CHALLENGES);
+ m_challengeList.clear();
for (const auto& challengeJson : challengesJson) {
- challengeList.push_back(challengeJson.second.get<std::string>(JSON_CHALLENGE_TYPE));
+ m_challengeList.push_back(challengeJson.second.get<std::string>(JSON_CA_CHALLENGE_ID, ""));
}
- state->m_challengeList = challengeList;
+ return m_challengeList;
+}
- _LOG_TRACE("Got NEW response with requestID " << state->m_requestId
- << " with status " << state->m_status
- << " with challenge number " << challengeList.size());
+shared_ptr<Interest>
+ClientModule::generateChallengeInterest(const JsonSection& paramJson)
+{
+ m_challengeType = paramJson.get<std::string>(JSON_CLIENT_SELECTED_CHALLENGE);
- requestCallback(state);
+ Name interestName = m_ca.m_caName;
+ interestName.append("CA").append("_CHALLENGE").append(m_requestId);
+ auto interest = make_shared<Interest>(interestName);
+ interest->setMustBeFresh(true);
+ interest->setCanBePrefix(false);
+
+ // encrypt the Interest parameters
+ std::stringstream ss;
+ boost::property_tree::write_json(ss, paramJson);
+ auto payload = ss.str();
+ auto paramBlock = genEncBlock(tlv::ApplicationParameters, m_ecdh.context->sharedSecret, m_ecdh.context->sharedSecretLen,
+ (const uint8_t*)payload.c_str(), payload.size());
+ interest->setApplicationParameters(paramBlock);
+
+ m_keyChain.sign(*interest, signingByKey(m_key.getName()));
+ return interest;
}
void
-ClientModule::sendSelect(const shared_ptr<RequestState>& state,
- const std::string& challengeType,
- const JsonSection& selectParams,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
+ClientModule::onChallengeResponse(const Data& reply)
{
- JsonSection requestIdJson;
- requestIdJson.put(JSON_REQUEST_ID, state->m_requestId);
-
- state->m_challengeType = challengeType;
-
- Name interestName(state->m_ca.m_caName);
- interestName.append("_SELECT")
- .append(nameBlockFromJson(requestIdJson))
- .append(challengeType)
- .append(nameBlockFromJson(selectParams));
- Interest interest(interestName);
- m_keyChain.sign(interest, signingByKey(state->m_key.getName()));
-
- DataCallback dataCb = bind(&ClientModule::handleSelectResponse,
- this, _1, _2, state, requestCallback, errorCallback);
- m_face.expressInterest(interest, dataCb,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- dataCb, errorCallback));
-
- _LOG_TRACE("SELECT interest sent with challenge type " << challengeType);
-}
-
-void
-ClientModule::handleSelectResponse(const Interest& request,
- const Data& reply,
- const shared_ptr<RequestState>& state,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
-{
- if (!security::verifySignature(reply, state->m_ca.m_anchor)) {
- errorCallback("Cannot verify data from " + state->m_ca.m_caName.toUri());
+ if (!security::verifySignature(reply, m_ca.m_anchor)) {
+ _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
return;
}
+ auto result = parseEncBlock(m_ecdh.context->sharedSecret, m_ecdh.context->sharedSecretLen, reply.getContent());
+ std::string payload((const char*)result.data(), result.size());
+ std::istringstream ss(payload);
+ JsonSection contentJson;
+ boost::property_tree::json_parser::read_json(ss, contentJson);
- JsonSection json = getJsonFromData(reply);
+ // update state
+ m_status = contentJson.get<int>(JSON_CA_STATUS);
+ m_challengeStatus = contentJson.get<std::string>(JSON_CHALLENGE_STATUS);
+ m_remainingTries = contentJson.get<int>(JSON_CHALLENGE_REMAINING_TRIES);
+ m_freshBefore = time::system_clock::now() + time::seconds(contentJson.get<int>(JSON_CHALLENGE_REMAINING_TIME));
+}
- _LOG_TRACE("SELECT response would change the status from "
- << state->m_status << " to " + json.get<std::string>(JSON_STATUS));
+shared_ptr<Interest>
+ClientModule::generateDownloadInterest()
+{
+ Name interestName = m_ca.m_caName;
+ interestName.append("CA").append("_DOWNLOAD").append(m_requestId);
+ auto interest = make_shared<Interest>(interestName);
+ interest->setMustBeFresh(true);
+ interest->setCanBePrefix(false);
+ return interest;
+}
- state->m_status = json.get<std::string>(JSON_STATUS);
-
- if (!checkStatus(*state, json, errorCallback)) {
- return;
- }
-
- _LOG_TRACE("Got SELECT response with status " << state->m_status);
-
- requestCallback(state);
+shared_ptr<Interest>
+ClientModule::generateCertFetchInterest()
+{
+ Name interestName = m_identityName;
+ interestName.append("KEY").append(m_certId);
+ auto interest = make_shared<Interest>(interestName);
+ interest->setMustBeFresh(true);
+ interest->setCanBePrefix(false);
+ return interest;
}
void
-ClientModule::sendValidate(const shared_ptr<RequestState>& state,
- const JsonSection& validateParams,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
+ClientModule::onDownloadResponse(const Data& reply)
{
- JsonSection requestIdJson;
- requestIdJson.put(JSON_REQUEST_ID, state->m_requestId);
-
- Name interestName(state->m_ca.m_caName);
- interestName.append("_VALIDATE")
- .append(nameBlockFromJson(requestIdJson))
- .append(state->m_challengeType)
- .append(nameBlockFromJson(validateParams));
- Interest interest(interestName);
- m_keyChain.sign(interest, signingByKey(state->m_key.getName()));
-
- DataCallback dataCb = bind(&ClientModule::handleValidateResponse,
- this, _1, _2, state, requestCallback, errorCallback);
- m_face.expressInterest(interest, dataCb,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- dataCb, errorCallback));
-
- _LOG_TRACE("VALIDATE interest sent");
-}
-
-void
-ClientModule::handleValidateResponse(const Interest& request,
- const Data& reply,
- const shared_ptr<RequestState>& state,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
-{
- if (!security::verifySignature(reply, state->m_ca.m_anchor)) {
- errorCallback("Cannot verify data from " + state->m_ca.m_caName.toUri());
- return;
- }
-
- JsonSection json = getJsonFromData(reply);
- state->m_status = json.get<std::string>(JSON_STATUS);
-
- if (!checkStatus(*state, json, errorCallback)) {
- return;
- }
-
- _LOG_TRACE("Got VALIDATE response with status " << state->m_status);
-
- requestCallback(state);
-}
-
-
-void
-ClientModule::requestStatus(const shared_ptr<RequestState>& state,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
-{
- JsonSection requestIdJson;
- requestIdJson.put(JSON_REQUEST_ID, state->m_requestId);
-
- Name interestName(state->m_ca.m_caName);
- interestName.append("_STATUS").append(nameBlockFromJson(requestIdJson));
- Interest interest(interestName);
-
- m_keyChain.sign(interest, signingByKey(state->m_key.getName()));
-
- DataCallback dataCb = bind(&ClientModule::handleStatusResponse,
- this, _1, _2, state, requestCallback, errorCallback);
- m_face.expressInterest(interest, dataCb,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- dataCb, errorCallback));
-
- _LOG_TRACE("STATUS interest sent");
-}
-
-void
-ClientModule::handleStatusResponse(const Interest& request, const Data& reply,
- const shared_ptr<RequestState>& state,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
-{
- if (!security::verifySignature(reply, state->m_ca.m_anchor)) {
- errorCallback("Cannot verify data from " + state->m_ca.m_caName.toUri());
- return;
- }
-
- JsonSection json = getJsonFromData(reply);
- state->m_status = json.get<std::string>(JSON_STATUS);
-
- if (!checkStatus(*state, json, errorCallback)) {
- return;
- }
-
- _LOG_TRACE("Got STATUS response with status " << state->m_status);
-
- requestCallback(state);
-}
-
-void
-ClientModule::requestDownload(const shared_ptr<RequestState>& state,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
-{
- JsonSection requestIdJson;
- requestIdJson.put(JSON_REQUEST_ID, state->m_requestId);
-
- Name interestName(state->m_ca.m_caName);
- interestName.append("_DOWNLOAD").append(nameBlockFromJson(requestIdJson));
- Interest interest(interestName);
- interest.setMustBeFresh(true);
-
- DataCallback dataCb = bind(&ClientModule::handleDownloadResponse,
- this, _1, _2, state, requestCallback, errorCallback);
- m_face.expressInterest(interest, dataCb,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, m_retryTimes,
- dataCb, errorCallback));
-
- _LOG_TRACE("DOWNLOAD interest sent");
-}
-
-void
-ClientModule::handleDownloadResponse(const Interest& request, const Data& reply,
- const shared_ptr<RequestState>& state,
- const RequestCallback& requestCallback,
- const ErrorCallback& errorCallback)
-{
- if (!security::verifySignature(reply, state->m_ca.m_anchor)) {
- errorCallback("Cannot verify data from " + state->m_ca.m_caName.toUri());
- return;
- }
-
try {
security::v2::Certificate cert(reply.getContent().blockFromValue());
- m_keyChain.addCertificate(state->m_key, cert);
-
+ m_keyChain.addCertificate(m_key, cert);
_LOG_TRACE("Got DOWNLOAD response and installed the cert " << cert.getName());
}
catch (const std::exception& e) {
- errorCallback(std::string(e.what()));
+ _LOG_ERROR("Cannot add replied certificate into the keychain " << e.what());
return;
}
-
- state->m_isInstalled = true;
- requestCallback(state);
+ m_isCertInstalled = true;
}
void
-ClientModule::onTimeout(const Interest& interest, int nRetriesLeft, const DataCallback& dataCallback,
- const ErrorCallback& errorCallback)
+ClientModule::onCertFetchResponse(const Data& reply)
{
- if (nRetriesLeft > 0) {
- m_face.expressInterest(interest, dataCallback,
- bind(&ClientModule::onNack, this, _1, _2, errorCallback),
- bind(&ClientModule::onTimeout, this, _1, nRetriesLeft - 1,
- dataCallback, errorCallback));
- }
- else {
- errorCallback("Run out retries: still timeout");
- return;
- }
-}
-
-void
-ClientModule::onNack(const Interest& interest, const lp::Nack& nack, const ErrorCallback& errorCallback)
-{
- errorCallback("Got Nack");
+ onDownloadResponse(reply);
}
JsonSection
ClientModule::getJsonFromData(const Data& data)
{
- Block jsonBlock = data.getContent();
- std::string jsonString = encoding::readString(jsonBlock);
- std::istringstream ss(jsonString);
+ std::istringstream ss(encoding::readString(data.getContent()));
JsonSection json;
boost::property_tree::json_parser::read_json(ss, json);
return json;
}
+const JsonSection
+ClientModule::genProbeRequestJson(const std::string& probeInfo)
+{
+ JsonSection root;
+ root.put(JSON_CLIENT_PROBE_INFO, probeInfo);
+ return root;
+}
+
+const JsonSection
+ClientModule::genNewRequestJson(const std::string& ecdhPub, const security::v2::Certificate& certRequest)
+{
+ JsonSection root;
+ std::stringstream ss;
+ try {
+ security::transform::bufferSource(certRequest.wireEncode().wire(), certRequest.wireEncode().size())
+ >> security::transform::base64Encode(true)
+ >> security::transform::streamSink(ss);
+ }
+ catch (const security::transform::Error& e) {
+ _LOG_ERROR("Cannot convert self-signed cert into BASE64 string " << e.what());
+ return root;
+ }
+ root.put(JSON_CLIENT_ECDH, ecdhPub);
+ root.put(JSON_CLIENT_CERT_REQ, ss.str());
+ return root;
+}
+
Block
-ClientModule::nameBlockFromJson(const JsonSection& json)
+ClientModule::paramFromJson(const JsonSection& json)
{
std::stringstream ss;
boost::property_tree::write_json(ss, json);
- return makeStringBlock(ndn::tlv::GenericNameComponent, ss.str());
-}
-
-bool
-ClientModule::checkStatus(const RequestState& state, const JsonSection& json,
- const ErrorCallback& errorCallback)
-{
- if (state.m_status == ChallengeModule::FAILURE) {
- errorCallback(json.get(JSON_FAILURE_INFO, ""));
- return false;
- }
- if (state.m_requestId.empty() || state.m_status.empty()) {
- errorCallback("The response does not carry required fields. requestID: " + state.m_requestId
- + " status: " + state.m_status);
- return false;
- }
- return true;
+ return makeStringBlock(ndn::tlv::ApplicationParameters, ss.str());
}
} // namespace ndncert