remove JSON parameter list from challenge module and add unified return interfaces for challenge modules
Change-Id: I0e69f7f8ef2ea36f38f11815aa980928b049cdc7
diff --git a/src/ca-config.cpp b/src/ca-config.cpp
index e6ab0f6..c8bc298 100644
--- a/src/ca-config.cpp
+++ b/src/ca-config.cpp
@@ -97,7 +97,7 @@
if (challengeType == "") {
BOOST_THROW_EXCEPTION(std::runtime_error("Cannot read type in supported-challenges from the config file"));
}
- if (!ChallengeModule::supportChallenge(challengeType)) {
+ if (!ChallengeModule::isChallengeSupported(challengeType)) {
BOOST_THROW_EXCEPTION(std::runtime_error("Does not support challenge read from the config file"));
}
m_supportedChallenges.push_back(challengeType);
diff --git a/src/challenge-module.cpp b/src/challenge-module.cpp
index 9288330..47dca5d 100644
--- a/src/challenge-module.cpp
+++ b/src/challenge-module.cpp
@@ -32,7 +32,7 @@
ChallengeModule::~ChallengeModule() = default;
bool
-ChallengeModule::supportChallenge(const std::string& challengeType)
+ChallengeModule::isChallengeSupported(const std::string& challengeType)
{
ChallengeFactory& factory = getFactory();
auto i = factory.find(challengeType);
@@ -70,16 +70,45 @@
return result;
}
-void
-ChallengeModule::updateRequestOnChallengeEnd(CertificateRequest& request)
+std::tuple<Error, std::string>
+ChallengeModule::returnWithError(CertificateRequest& request, Error errorCode, std::string&& errorInfo)
{
+ request.m_status = Status::FAILURE;
+ request.m_challengeType = "";
+ request.m_challengeStatus = "";
request.m_challengeSecrets = JsonSection();
request.m_challengeTp = "";
- request.m_challengeType = "";
request.m_remainingTime = 0;
request.m_remainingTries = 0;
+ return std::make_tuple(errorCode, std::move(errorInfo));
}
+std::tuple<Error, std::string>
+ChallengeModule::returnWithNewChallengeStatus(CertificateRequest& request, const std::string& challengeStatus,
+ JsonSection&& challengeSecret, size_t remainingTries, size_t remainingTime)
+{
+ request.m_status = Status::CHALLENGE;
+ request.m_challengeType = CHALLENGE_TYPE;
+ request.m_challengeStatus = std::move(challengeStatus);
+ request.m_challengeSecrets = std::move(challengeSecret);
+ request.m_challengeTp = time::toIsoString(time::system_clock::now());
+ request.m_remainingTime = remainingTries;
+ request.m_remainingTries = remainingTime;
+ return std::make_tuple(Error::NO_ERROR, "");
+}
+
+std::tuple<Error, std::string>
+ChallengeModule::returnWithSuccess(CertificateRequest& request)
+{
+ request.m_status = Status::PENDING;
+ request.m_challengeType = CHALLENGE_TYPE;
+ request.m_challengeStatus = "";
+ request.m_challengeSecrets = JsonSection();
+ request.m_challengeTp = "";
+ request.m_remainingTime = 0;
+ request.m_remainingTries = 0;
+ return std::make_tuple(Error::NO_ERROR, "");
+}
} // namespace ndncert
} // namespace ndn
diff --git a/src/challenge-module.hpp b/src/challenge-module.hpp
index fb687e1..660ff15 100644
--- a/src/challenge-module.hpp
+++ b/src/challenge-module.hpp
@@ -21,35 +21,21 @@
#ifndef NDNCERT_CHALLENGE_MODULE_HPP
#define NDNCERT_CHALLENGE_MODULE_HPP
-#include "ndncert-common.hpp"
+#include <tuple>
+
#include "certificate-request.hpp"
+#include "ndncert-common.hpp"
namespace ndn {
namespace ndncert {
-class ChallengeModule : noncopyable
-{
+class ChallengeModule : noncopyable {
public:
- /**
- * @brief Error that can be thrown from ChallengeModule
- *
- * ChallengeModule should throw Error to notice CA there's an Error. In this case, CA will
- * generate an Error JSON file back to end entity.
- */
- class Error : public std::runtime_error
- {
- public:
- using std::runtime_error::runtime_error;
- };
+ explicit ChallengeModule(const std::string& uniqueType);
-public:
- explicit
- ChallengeModule(const std::string& uniqueType);
+ virtual ~ChallengeModule();
- virtual
- ~ChallengeModule();
-
- template<class ChallengeType>
+ template <class ChallengeType>
static void
registerChallengeModule(const std::string& typeName)
{
@@ -59,56 +45,60 @@
}
static bool
- supportChallenge(const std::string& challengeType);
+ isChallengeSupported(const std::string& challengeType);
static unique_ptr<ChallengeModule>
createChallengeModule(const std::string& challengeType);
// For CA
- virtual void
+ virtual std::tuple<Error, std::string>
handleChallengeRequest(const Block& params, CertificateRequest& request) = 0;
// For Client
- virtual JsonSection
- getRequirementForChallenge(Status status, const std::string& challengeStatus) = 0;
-
- virtual JsonSection
- genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params) = 0;
+ virtual std::vector<std::tuple<std::string, std::string>>
+ getRequestedParameterList(Status status, const std::string& challengeStatus) = 0;
virtual Block
- genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params) = 0;
+ genChallengeRequestTLV(Status status, const std::string& challengeStatus,
+ std::vector<std::tuple<std::string, std::string>>&& params) = 0;
// helpers
static std::string
generateSecretCode();
protected:
+ // used by challenge modules
+ std::tuple<Error, std::string>
+ returnWithError(CertificateRequest& request, Error errorCode, std::string&& errorInfo);
- void
- updateRequestOnChallengeEnd(CertificateRequest& request);
+ std::tuple<Error, std::string>
+ returnWithNewChallengeStatus(CertificateRequest& request, const std::string& challengeStatus,
+ JsonSection&& challengeSecret, size_t remainingTries, size_t remainingTime);
+
+ std::tuple<Error, std::string>
+ returnWithSuccess(CertificateRequest& request);
public:
const std::string CHALLENGE_TYPE;
private:
- typedef function<unique_ptr<ChallengeModule> ()> ChallengeCreateFunc;
+ typedef function<unique_ptr<ChallengeModule>()> ChallengeCreateFunc;
typedef std::map<std::string, ChallengeCreateFunc> ChallengeFactory;
static ChallengeFactory&
getFactory();
};
-#define NDNCERT_REGISTER_CHALLENGE(C, T) \
-static class NdnCert ## C ## ChallengeRegistrationClass \
-{ \
-public: \
- NdnCert ## C ## ChallengeRegistrationClass() \
- { \
- ::ndn::ndncert::ChallengeModule::registerChallengeModule<C>(T);\
- } \
-} g_NdnCert ## C ## ChallengeRegistrationVariable
+#define NDNCERT_REGISTER_CHALLENGE(C, T) \
+ static class NdnCert##C##ChallengeRegistrationClass { \
+ public: \
+ NdnCert##C##ChallengeRegistrationClass() \
+ { \
+ ::ndn::ndncert::ChallengeModule::registerChallengeModule<C>(T); \
+ } \
+ } g_NdnCert##C##ChallengeRegistrationVariable
-} // namespace ndncert
-} // namespace ndn
+} // namespace ndncert
+} // namespace ndn
-#endif // NDNCERT_CHALLENGE_MODULE_HPP
+#endif // NDNCERT_CHALLENGE_MODULE_HPP
diff --git a/src/challenge-module/challenge-credential.cpp b/src/challenge-module/challenge-credential.cpp
index da24fef..fe120eb 100644
--- a/src/challenge-module/challenge-credential.cpp
+++ b/src/challenge-module/challenge-credential.cpp
@@ -28,15 +28,11 @@
namespace ndn {
namespace ndncert {
-_LOG_INIT(ndncert.ChallengeCredential);
-
+_LOG_INIT(ndncert.challenge.credential);
NDNCERT_REGISTER_CHALLENGE(ChallengeCredential, "Credential");
-const std::string ChallengeCredential::FAILURE_INVALID_FORMAT_CREDENTIAL = "failure-cannot-parse-credential";
-const std::string ChallengeCredential::FAILURE_INVALID_FORMAT_SELF_SIGNED = "failure-cannot-parse-self-signed";
-const std::string ChallengeCredential::FAILURE_INVALID_CREDENTIAL = "failure-invalid-credential";
-const std::string ChallengeCredential::JSON_CREDENTIAL_CERT = "issued-cert";
-const std::string ChallengeCredential::JSON_PROOF_OF_PRIVATE_KEY = "proof-of-private-key";
+const std::string ChallengeCredential::PARAMETER_KEY_CREDENTIAL_CERT = "issued-cert";
+const std::string ChallengeCredential::PARAMETER_KEY_PROOF_OF_PRIVATE_KEY = "proof-of-private-key";
ChallengeCredential::ChallengeCredential(const std::string& configPath)
: ChallengeModule("Credential")
@@ -57,12 +53,12 @@
boost::property_tree::read_json(m_configFile, config);
}
catch (const boost::property_tree::info_parser_error& error) {
- BOOST_THROW_EXCEPTION(Error("Failed to parse configuration file " + m_configFile +
- " " + error.message() + " line " + std::to_string(error.line())));
+ BOOST_THROW_EXCEPTION(std::runtime_error("Failed to parse configuration file " + m_configFile +
+ " " + error.message() + " line " + std::to_string(error.line())));
}
if (config.begin() == config.end()) {
- BOOST_THROW_EXCEPTION(Error("Error processing configuration file: " + m_configFile + " no data"));
+ BOOST_THROW_EXCEPTION(std::runtime_error("Error processing configuration file: " + m_configFile + " no data"));
}
m_trustAnchors.clear();
@@ -80,7 +76,7 @@
}
// For CA
-void
+std::tuple<Error, std::string>
ChallengeCredential::handleChallengeRequest(const Block& params, CertificateRequest& request)
{
params.parse();
@@ -91,26 +87,20 @@
auto& elements = params.elements();
for (size_t i = 0; i < elements.size(); i++) {
if (elements[i].type() == tlv_parameter_key) {
- if (readString(elements[i]) == JSON_CREDENTIAL_CERT) {
+ if (readString(elements[i]) == PARAMETER_KEY_CREDENTIAL_CERT) {
std::istringstream ss(readString(params.elements()[i + 1]));
credential = io::load<security::v2::Certificate>(ss);
if (credential == nullptr) {
- _LOG_ERROR("Cannot load credential parameter: cert");
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = FAILURE_INVALID_FORMAT_CREDENTIAL;
- updateRequestOnChallengeEnd(request);
- return;
+ _LOG_ERROR("Cannot load challenge parameter: credential");
+ return returnWithError(request, Error::INVALID_PARAMETER, "Cannot challenge credential: credential.");
}
}
- else if (readString(elements[i]) == JSON_PROOF_OF_PRIVATE_KEY) {
+ else if (readString(elements[i]) == PARAMETER_KEY_PROOF_OF_PRIVATE_KEY) {
std::istringstream ss(readString(params.elements()[i + 1]));
selfSigned = io::load<security::v2::Certificate>(ss);
if (selfSigned == nullptr) {
- _LOG_ERROR("Cannot load credential parameter: cert");
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = FAILURE_INVALID_FORMAT_SELF_SIGNED;
- updateRequestOnChallengeEnd(request);
- return;
+ _LOG_ERROR("Cannot load challenge parameter: proof of private key");
+ return returnWithError(request, Error::INVALID_PARAMETER, "Cannot load challenge parameter: proof of private key.");
}
}
else {
@@ -126,63 +116,56 @@
if (security::verifySignature(*selfSigned, anchor) &&
security::verifySignature(*selfSigned, *credential) &&
readString(selfSigned->getContent()) == request.m_requestId) {
- request.m_status = Status::PENDING;
- request.m_challengeStatus = CHALLENGE_STATUS_SUCCESS;
- updateRequestOnChallengeEnd(request);
- return;
+ return returnWithSuccess(request);
}
}
}
- _LOG_TRACE("Cannot verify the credential + self-signed Data + data content");
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = FAILURE_INVALID_CREDENTIAL;
- updateRequestOnChallengeEnd(request);
- return;
+ _LOG_TRACE("Cannot verify the proof of private key against credential");
+ return returnWithError(request, Error::INVALID_PARAMETER, "Cannot verify the proof of private key against credential.");
}
// For Client
-JsonSection
-ChallengeCredential::getRequirementForChallenge(Status status, const std::string& challengeStatus)
+std::vector<std::tuple<std::string, std::string>>
+ChallengeCredential::getRequestedParameterList(Status status, const std::string& challengeStatus)
{
- JsonSection result;
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- result.put(JSON_CREDENTIAL_CERT, "Please_copy_anchor_signed_cert_here");
- result.put(JSON_PROOF_OF_PRIVATE_KEY, "Please_copy_key_signed_request_id_data_here");
+ std::vector<std::tuple<std::string, std::string>> result;
+ if (status == Status::BEFORE_CHALLENGE) {
+ result.push_back(std::make_tuple(PARAMETER_KEY_CREDENTIAL_CERT, "Please provide the certificate issued by a trusted CA."));
+ result.push_back(std::make_tuple(PARAMETER_KEY_PROOF_OF_PRIVATE_KEY, "Please sign a Data packet with request ID as the content."));
}
else {
- _LOG_ERROR("Client's status and challenge status are wrong");
- }
- return result;
-}
-
-JsonSection
-ChallengeCredential::genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params)
-{
- JsonSection result;
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- result.put(JSON_CREDENTIAL_CERT, params.get(JSON_CREDENTIAL_CERT, ""));
- result.put(JSON_PROOF_OF_PRIVATE_KEY, params.get(JSON_PROOF_OF_PRIVATE_KEY, ""));
- }
- else {
- _LOG_ERROR("Client's status and challenge status are wrong");
+ BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
}
return result;
}
Block
-ChallengeCredential::genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params)
+ChallengeCredential::genChallengeRequestTLV(Status status, const std::string& challengeStatus,
+ std::vector<std::tuple<std::string, std::string>>&& params)
{
Block request = makeEmptyBlock(tlv_encrypted_payload);
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
+ if (status == Status::BEFORE_CHALLENGE) {
+ if (params.size() != 2) {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Wrong parameter provided."));
+ }
request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
- request.push_back(makeStringBlock(tlv_parameter_key, JSON_CREDENTIAL_CERT));
- request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_CREDENTIAL_CERT, "")));
- request.push_back(makeStringBlock(tlv_parameter_key, JSON_PROOF_OF_PRIVATE_KEY));
- request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_PROOF_OF_PRIVATE_KEY, "")));
+ for (const auto& item : params) {
+ if (std::get<0>(item) == PARAMETER_KEY_CREDENTIAL_CERT) {
+ request.push_back(makeStringBlock(tlv_parameter_key, PARAMETER_KEY_CREDENTIAL_CERT));
+ request.push_back(makeStringBlock(tlv_parameter_value, std::get<1>(item)));
+ }
+ else if (std::get<0>(item) == PARAMETER_KEY_PROOF_OF_PRIVATE_KEY) {
+ request.push_back(makeStringBlock(tlv_parameter_key, PARAMETER_KEY_PROOF_OF_PRIVATE_KEY));
+ request.push_back(makeStringBlock(tlv_parameter_value, std::get<1>(item)));
+ }
+ else {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Wrong parameter provided."));
+ }
+ }
}
else {
- _LOG_ERROR("Client's status and challenge status are wrong");
+ BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
}
request.encode();
return request;
diff --git a/src/challenge-module/challenge-credential.hpp b/src/challenge-module/challenge-credential.hpp
index c0e0e48..2afe38e 100644
--- a/src/challenge-module/challenge-credential.hpp
+++ b/src/challenge-module/challenge-credential.hpp
@@ -52,31 +52,26 @@
ChallengeCredential(const std::string& configPath = "");
// For CA
- void
+ std::tuple<Error, std::string>
handleChallengeRequest(const Block& params, CertificateRequest& request) override;
// For Client
- JsonSection
- getRequirementForChallenge(Status status, const std::string& challengeStatus) override;
-
- JsonSection
- genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params) override;
+ std::vector<std::tuple<std::string, std::string>>
+ getRequestedParameterList(Status status, const std::string& challengeStatus) override;
Block
- genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params) override;
+ genChallengeRequestTLV(Status status, const std::string& challengeStatus,
+ std::vector<std::tuple<std::string, std::string>>&& params) override;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
parseConfigFile();
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
- static const std::string FAILURE_INVALID_CREDENTIAL;
- static const std::string FAILURE_INVALID_FORMAT_CREDENTIAL;
- static const std::string FAILURE_INVALID_FORMAT_SELF_SIGNED;
- static const std::string JSON_CREDENTIAL_CERT;
- static const std::string JSON_PROOF_OF_PRIVATE_KEY;
+ // parameters
+ static const std::string PARAMETER_KEY_CREDENTIAL_CERT;
+ static const std::string PARAMETER_KEY_PROOF_OF_PRIVATE_KEY;
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
std::list<security::v2::Certificate> m_trustAnchors;
std::string m_configFile;
};
diff --git a/src/challenge-module/challenge-email.cpp b/src/challenge-module/challenge-email.cpp
index cd08d9b..7e0134a 100644
--- a/src/challenge-module/challenge-email.cpp
+++ b/src/challenge-module/challenge-email.cpp
@@ -19,187 +19,130 @@
*/
#include "challenge-email.hpp"
+
+#include <regex>
+
#include "../ca-module.hpp"
#include "../logging.hpp"
-#include <regex>
namespace ndn {
namespace ndncert {
-_LOG_INIT(ndncert.ChallengeEmail);
-
+_LOG_INIT(ndncert.challenge.email);
NDNCERT_REGISTER_CHALLENGE(ChallengeEmail, "email");
const std::string ChallengeEmail::NEED_CODE = "need-code";
const std::string ChallengeEmail::WRONG_CODE = "wrong-code";
-const std::string ChallengeEmail::FAILURE_INVALID_EMAIL = "failure-invalid-email";
-const std::string ChallengeEmail::JSON_EMAIL = "email";
-const std::string ChallengeEmail::JSON_CODE = "code";
+const std::string ChallengeEmail::PARAMETER_KEY_EMAIL = "email";
+const std::string ChallengeEmail::PARAMETER_KEY_CODE = "code";
ChallengeEmail::ChallengeEmail(const std::string& scriptPath,
const size_t& maxAttemptTimes,
const time::seconds secretLifetime)
- : ChallengeModule("email")
- , m_sendEmailScript(scriptPath)
- , m_maxAttemptTimes(maxAttemptTimes)
- , m_secretLifetime(secretLifetime)
+ : ChallengeModule("email")
+ , m_sendEmailScript(scriptPath)
+ , m_maxAttemptTimes(maxAttemptTimes)
+ , m_secretLifetime(secretLifetime)
{
}
// For CA
-void
+std::tuple<Error, std::string>
ChallengeEmail::handleChallengeRequest(const Block& params, CertificateRequest& request)
{
params.parse();
auto currentTime = time::system_clock::now();
- if (request.m_challengeStatus == "") {
+ if (request.m_status == Status::BEFORE_CHALLENGE) {
// for the first time, init the challenge
std::string emailAddress = readString(params.get(tlv_parameter_value));
if (!isValidEmailAddress(emailAddress)) {
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = FAILURE_INVALID_EMAIL;
- return;
+ return returnWithError(request, Error::INVALID_PARAMETER, "Invalid email address format.");
}
- // check whether this email is the same as the one used in PROBE
- if (request.m_probeToken != nullptr) {
- const auto& content = request.m_probeToken->getContent();
- const auto& json = CaModule::jsonFromBlock(content);
- const auto& expectedEmail = json.get("email", "");
- Name expectedPrefix(json.get(JSON_CA_NAME, ""));
- if (expectedEmail != emailAddress || !expectedPrefix.isPrefixOf(request.m_cert.getName())) {
- _LOG_ERROR("Cannot match with the PROBE token. Input email: " << emailAddress
- << " Email in Token: " << expectedEmail
- << " Requested Cert Name: " << request.m_cert.getName()
- << " Identity Name got from Token: " << expectedPrefix);
- return;
- }
+ auto lastComponentRequested = readString(request.m_cert.getIdentity().get(-1));
+ if (lastComponentRequested != emailAddress) {
+ _LOG_TRACE("Email and requested name do not match. Email " << emailAddress << "requested last component " << lastComponentRequested);
}
- request.m_status = Status::CHALLENGE;
- request.m_challengeStatus = NEED_CODE;
- request.m_challengeType = CHALLENGE_TYPE;
std::string emailCode = generateSecretCode();
JsonSection secretJson;
- secretJson.add(JSON_CODE, emailCode);
- request.m_challengeSecrets = secretJson;
- request.m_challengeTp = time::toIsoString(currentTime);
- request.m_remainingTime = m_secretLifetime.count();
- request.m_remainingTries = m_maxAttemptTimes;
+ secretJson.add(PARAMETER_KEY_CODE, emailCode);
// send out the email
sendEmail(emailAddress, emailCode, request);
_LOG_TRACE("Secret for request " << request.m_requestId << " : " << emailCode);
- return;
+ return returnWithNewChallengeStatus(request, NEED_CODE, std::move(secretJson), m_maxAttemptTimes, m_secretLifetime.count());
}
- else if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
+
+ if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
_LOG_TRACE("Challenge Interest arrives. Challenge Status: " << request.m_challengeStatus);
// the incoming interest should bring the pin code
std::string givenCode = readString(params.get(tlv_parameter_value));
- const auto realCode = request.m_challengeSecrets.get<std::string>(JSON_CODE);
+ auto secret = request.m_challengeSecrets;
+ // check if run out of time
if (currentTime - time::fromIsoString(request.m_challengeTp) >= m_secretLifetime) {
- // secret expires
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_TIMEOUT;
- updateRequestOnChallengeEnd(request);
- _LOG_TRACE("Secret expired. Challenge failed.");
- return;
+ return returnWithError(request, Error::OUT_OF_TIME, "Secret expired.");
}
- else if (givenCode == realCode) {
+ // check if provided secret is correct
+ if (givenCode == secret.get<std::string>(PARAMETER_KEY_CODE)) {
// the code is correct
- request.m_status = Status::PENDING;
- request.m_challengeStatus = CHALLENGE_STATUS_SUCCESS;
- updateRequestOnChallengeEnd(request);
- _LOG_TRACE("Secret code matched. Challenge succeeded.");
- return;
+ _LOG_TRACE("Correct secret code. Challenge succeeded.");
+ return returnWithSuccess(request);
+ }
+ // otherwise, check remaining attempt times
+ if (request.m_remainingTries > 1) {
+ auto remainTime = m_secretLifetime - (currentTime - time::fromIsoString(request.m_challengeTp));
+ _LOG_TRACE("Wrong secret code provided. Remaining Tries - 1.");
+ return returnWithNewChallengeStatus(request, WRONG_CODE, std::move(secret), request.m_remainingTries - 1, remainTime.count());
}
else {
- // check rest attempt times
- if (request.m_remainingTries > 1) {
- request.m_challengeStatus = WRONG_CODE;
- request.m_remainingTries = request.m_remainingTries - 1;
- auto remainTime = m_secretLifetime - (currentTime - time::fromIsoString(request.m_challengeTp));
- request.m_remainingTime = remainTime.count();
- _LOG_TRACE("Secret code didn't match. Remaining Tries - 1.");
- return;
- }
- else {
- // run out times
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_MAXRETRY;
- updateRequestOnChallengeEnd(request);
- _LOG_TRACE("Secret code didn't match. Ran out tires. Challenge failed.");
- return;
- }
+ // run out times
+ _LOG_TRACE("Wrong secret code provided. Ran out tires. Challenge failed.");
+ return returnWithError(request, Error::OUT_OF_TRIES, "Ran out tires.");
}
}
- else {
- _LOG_ERROR("The challenge status is wrong");
- request.m_status = Status::FAILURE;
- return;
- }
+ return returnWithError(request, Error::INVALID_PARAMETER, "Unexpected status or challenge status");
}
// For Client
-JsonSection
-ChallengeEmail::getRequirementForChallenge(Status status, const std::string& challengeStatus)
+std::vector<std::tuple<std::string, std::string>>
+ChallengeEmail::getRequestedParameterList(Status status, const std::string& challengeStatus)
{
- JsonSection result;
+ std::vector<std::tuple<std::string, std::string>> result;
if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- result.put(JSON_EMAIL, "Please_input_your_email_address");
+ result.push_back(std::make_tuple(PARAMETER_KEY_EMAIL, "Please input your email address"));
}
else if (status == Status::CHALLENGE && challengeStatus == NEED_CODE) {
- result.put(JSON_CODE, "Please_input_your_verification_code");
+ result.push_back(std::make_tuple(PARAMETER_KEY_CODE, "Please input your verification code"));
}
else if (status == Status::CHALLENGE && challengeStatus == WRONG_CODE) {
- result.put(JSON_CODE, "Incorrect_code_please_try_again");
+ result.push_back(std::make_tuple(PARAMETER_KEY_CODE, "Incorrect code, please try again"));
}
else {
- _LOG_ERROR("CA's status and challenge status are wrong");
- }
- return result;
-}
-
-JsonSection
-ChallengeEmail::genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params)
-{
- JsonSection result;
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
- result.put(JSON_EMAIL, params.get(JSON_EMAIL, ""));
- }
- else if (status == Status::CHALLENGE && challengeStatus == NEED_CODE) {
- result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
- result.put(JSON_CODE, params.get(JSON_CODE, ""));
- }
- else if (status == Status::CHALLENGE && challengeStatus == WRONG_CODE) {
- result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
- result.put(JSON_CODE, params.get(JSON_CODE, ""));
- }
- else {
- _LOG_ERROR("Client's status and challenge status are wrong");
+ BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
}
return result;
}
Block
-ChallengeEmail::genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params)
+ChallengeEmail::genChallengeRequestTLV(Status status, const std::string& challengeStatus, std::vector<std::tuple<std::string, std::string>>&& params)
{
Block request = makeEmptyBlock(tlv_encrypted_payload);
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
+ if (status == Status::BEFORE_CHALLENGE) {
+ if (params.size() != 1 || std::get<0>(params[0]) != PARAMETER_KEY_EMAIL) {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Wrong parameter provided."));
+ }
request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
- request.push_back(makeStringBlock(tlv_parameter_key, JSON_EMAIL));
- request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_EMAIL,"")));
+ request.push_back(makeStringBlock(tlv_parameter_key, PARAMETER_KEY_EMAIL));
+ request.push_back(makeStringBlock(tlv_parameter_value, std::get<1>(params[0])));
}
- else if (status == Status::CHALLENGE && challengeStatus == NEED_CODE) {
+ else if (status == Status::CHALLENGE && (challengeStatus == NEED_CODE || challengeStatus == WRONG_CODE)) {
+ if (params.size() != 1 || std::get<0>(params[0]) != PARAMETER_KEY_CODE) {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Wrong parameter provided."));
+ }
request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
- request.push_back(makeStringBlock(tlv_parameter_key, JSON_CODE));
- request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_CODE,"")));
- }
- else if (status == Status::CHALLENGE && challengeStatus == WRONG_CODE) {
- request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
- request.push_back(makeStringBlock(tlv_parameter_key, JSON_CODE));
- request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_CODE,"")));
+ request.push_back(makeStringBlock(tlv_parameter_key, PARAMETER_KEY_CODE));
+ request.push_back(makeStringBlock(tlv_parameter_value, std::get<1>(params[0])));
}
else {
- _LOG_ERROR("Client's status and challenge status are wrong");
+ BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
}
request.encode();
return request;
@@ -218,8 +161,7 @@
const CertificateRequest& request) const
{
std::string command = m_sendEmailScript;
- command += " \"" + emailAddress + "\" \"" + secret + "\" \""
- + request.m_caPrefix.toUri() + "\" \"" + request.m_cert.getName().toUri() + "\"";
+ command += " \"" + emailAddress + "\" \"" + secret + "\" \"" + request.m_caPrefix.toUri() + "\" \"" + request.m_cert.getName().toUri() + "\"";
int result = system(command.c_str());
if (result == -1) {
_LOG_TRACE("EmailSending Script " + m_sendEmailScript + " fails.");
@@ -229,5 +171,5 @@
return;
}
-} // namespace ndncert
-} // namespace ndn
+} // namespace ndncert
+} // namespace ndn
diff --git a/src/challenge-module/challenge-email.hpp b/src/challenge-module/challenge-email.hpp
index b43a3de..f148d06 100644
--- a/src/challenge-module/challenge-email.hpp
+++ b/src/challenge-module/challenge-email.hpp
@@ -58,18 +58,16 @@
const time::seconds secretLifetime = time::minutes(20));
// For CA
- void
+ std::tuple<Error, std::string>
handleChallengeRequest(const Block& params, CertificateRequest& request) override;
// For Client
- JsonSection
- getRequirementForChallenge(Status status, const std::string& challengeStatus) override;
-
- JsonSection
- genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params) override;
+ std::vector<std::tuple<std::string, std::string>>
+ getRequestedParameterList(Status status, const std::string& challengeStatus) override;
Block
- genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params) override;
+ genChallengeRequestTLV(Status status, const std::string& challengeStatus,
+ std::vector<std::tuple<std::string, std::string>>&& params) override;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
static bool
@@ -83,10 +81,9 @@
// challenge status
static const std::string NEED_CODE;
static const std::string WRONG_CODE;
- static const std::string FAILURE_INVALID_EMAIL;
- // JSON attribute
- static const std::string JSON_EMAIL;
- static const std::string JSON_CODE;
+ // parameters
+ static const std::string PARAMETER_KEY_EMAIL;
+ static const std::string PARAMETER_KEY_CODE;
private:
std::string m_sendEmailScript;
diff --git a/src/challenge-module/challenge-pin.cpp b/src/challenge-module/challenge-pin.cpp
index 55b9435..cd20c51 100644
--- a/src/challenge-module/challenge-pin.cpp
+++ b/src/challenge-module/challenge-pin.cpp
@@ -19,162 +19,111 @@
*/
#include "challenge-pin.hpp"
-#include "logging.hpp"
+
#include <ndn-cxx/util/random.hpp>
+#include "logging.hpp"
+
namespace ndn {
namespace ndncert {
-_LOG_INIT(ndncert.challenge-pin);
-
+_LOG_INIT(ndncert.challenge.pin);
NDNCERT_REGISTER_CHALLENGE(ChallengePin, "pin");
const std::string ChallengePin::NEED_CODE = "need-code";
const std::string ChallengePin::WRONG_CODE = "wrong-code";
-const std::string ChallengePin::JSON_PIN_CODE = "pin-code";
+const std::string ChallengePin::PARAMETER_KEY_CODE = "pin-code";
ChallengePin::ChallengePin(const size_t& maxAttemptTimes, const time::seconds& secretLifetime)
- : ChallengeModule("pin")
- , m_secretLifetime(secretLifetime)
- , m_maxAttemptTimes(maxAttemptTimes)
+ : ChallengeModule("pin")
+ , m_secretLifetime(secretLifetime)
+ , m_maxAttemptTimes(maxAttemptTimes)
{
}
// For CA
-void
+std::tuple<Error, std::string>
ChallengePin::handleChallengeRequest(const Block& params, CertificateRequest& request)
{
params.parse();
auto currentTime = time::system_clock::now();
- if (request.m_challengeStatus == "") {
+ if (request.m_status == Status::BEFORE_CHALLENGE) {
_LOG_TRACE("Challenge Interest arrives. Init the challenge");
// for the first time, init the challenge
- request.m_status = Status::CHALLENGE;
- request.m_challengeStatus = NEED_CODE;
- request.m_challengeType = CHALLENGE_TYPE;
std::string secretCode = generateSecretCode();
JsonSection secretJson;
- secretJson.add(JSON_PIN_CODE, secretCode);
- request.m_challengeSecrets = secretJson;
- request.m_challengeTp = time::toIsoString(currentTime);
- request.m_remainingTime = m_secretLifetime.count();
- request.m_remainingTries = m_maxAttemptTimes;
+ secretJson.add(PARAMETER_KEY_CODE, secretCode);
_LOG_TRACE("Secret for request " << request.m_requestId << " : " << secretCode);
- return;
+ return returnWithNewChallengeStatus(request, NEED_CODE, std::move(secretJson), m_maxAttemptTimes, m_secretLifetime.count());
}
- else if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
+
+ if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
_LOG_TRACE("Challenge Interest arrives. Challenge Status: " << request.m_challengeStatus);
// the incoming interest should bring the pin code
std::string givenCode = readString(params.get(tlv_parameter_value));
- const auto realCode = request.m_challengeSecrets.get<std::string>(JSON_PIN_CODE);
+ auto secret = request.m_challengeSecrets;
if (currentTime - time::fromIsoString(request.m_challengeTp) >= m_secretLifetime) {
- // secret expires
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_TIMEOUT;
- updateRequestOnChallengeEnd(request);
- _LOG_TRACE("Secret expired. Challenge failed.");
- return;
+ return returnWithError(request, Error::OUT_OF_TIME, "Secret expired.");
}
- else if (givenCode == realCode) {
- // the code is correct
- request.m_status = Status::PENDING;
- request.m_challengeStatus = CHALLENGE_STATUS_SUCCESS;
- updateRequestOnChallengeEnd(request);
- _LOG_TRACE("PIN code matched. Challenge succeeded.");
- return;
+ if (givenCode == secret.get<std::string>(PARAMETER_KEY_CODE)) {
+ _LOG_TRACE("Correct PIN code. Challenge succeeded.");
+ return returnWithSuccess(request);
+ }
+ // check rest attempt times
+ if (request.m_remainingTries > 1) {
+ auto remainTime = m_secretLifetime - (currentTime - time::fromIsoString(request.m_challengeTp));
+ _LOG_TRACE("Wrong PIN code provided. Remaining Tries - 1.");
+ return returnWithNewChallengeStatus(request, WRONG_CODE, std::move(secret), request.m_remainingTries - 1, remainTime.count());
}
else {
- // check rest attempt times
- if (request.m_remainingTries > 1) {
- request.m_challengeStatus = WRONG_CODE;
- request.m_remainingTries = request.m_remainingTries - 1;
- auto remainTime = m_secretLifetime - (currentTime - time::fromIsoString(request.m_challengeTp));
- request.m_remainingTime = remainTime.count();
- _LOG_TRACE("PIN code didn't match. Remaining Tries - 1.");
- return;
- }
- else {
- // run out times
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_MAXRETRY;
- updateRequestOnChallengeEnd(request);
- _LOG_TRACE("PIN code didn't match. Ran out tires. Challenge failed.");
- return;
- }
+ // run out times
+ _LOG_TRACE("Wrong PIN code provided. Ran out tires. Challenge failed.");
+ return returnWithError(request, Error::OUT_OF_TRIES, "Ran out tires.");
}
}
- else {
- _LOG_ERROR("The challenge status is wrong");
- request.m_status = Status::FAILURE;
- return;
- }
+ return returnWithError(request, Error::INVALID_PARAMETER, "Unexpected status or challenge status");
}
// For Client
-JsonSection
-ChallengePin::getRequirementForChallenge(Status status, const std::string& challengeStatus)
+std::vector<std::tuple<std::string, std::string>>
+ChallengePin::getRequestedParameterList(Status status, const std::string& challengeStatus)
{
- JsonSection result;
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
+ std::vector<std::tuple<std::string, std::string>> result;
+ if (status == Status::BEFORE_CHALLENGE) {
// do nothing
}
else if (status == Status::CHALLENGE && challengeStatus == NEED_CODE) {
- result.put(JSON_PIN_CODE, "Please_input_your_verification_code");
+ result.push_back(std::make_tuple(PARAMETER_KEY_CODE, "Please input your PIN code"));
}
else if (status == Status::CHALLENGE && challengeStatus == WRONG_CODE) {
- result.put(JSON_PIN_CODE, "Incorrect_PIN_code_please_try_again");
+ result.push_back(std::make_tuple(PARAMETER_KEY_CODE, "Incorrect PIN code, please try again"));
}
else {
- _LOG_ERROR("Client's status and challenge status are wrong");
- }
- return result;
-}
-
-JsonSection
-ChallengePin::genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params)
-{
- JsonSection result;
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- // do nothing
- result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
- }
- else if (status == Status::CHALLENGE && challengeStatus == NEED_CODE) {
- result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
- result.put(JSON_PIN_CODE, params.get(JSON_PIN_CODE, ""));
- }
- else if (status == Status::CHALLENGE && challengeStatus == WRONG_CODE) {
- result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
- result.put(JSON_PIN_CODE, params.get(JSON_PIN_CODE, ""));
- }
- else {
- _LOG_ERROR("Client's status and challenge status are wrong");
+ BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
}
return result;
}
Block
-ChallengePin::genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params)
+ChallengePin::genChallengeRequestTLV(Status status, const std::string& challengeStatus, std::vector<std::tuple<std::string, std::string>>&& params)
{
Block request = makeEmptyBlock(tlv_encrypted_payload);
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- // do nothing
+ if (status == Status::BEFORE_CHALLENGE) {
request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
}
- else if (status == Status::CHALLENGE && challengeStatus == NEED_CODE) {
+ else if (status == Status::CHALLENGE && (challengeStatus == NEED_CODE || challengeStatus == WRONG_CODE)) {
+ if (params.size() != 1 || std::get<0>(params[0]) != PARAMETER_KEY_CODE) {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Wrong parameter provided."));
+ }
request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
- request.push_back(makeStringBlock(tlv_parameter_key, JSON_PIN_CODE));
- request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_PIN_CODE,"")));
- }
- else if (status == Status::CHALLENGE && challengeStatus == WRONG_CODE) {
- request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
- request.push_back(makeStringBlock(tlv_parameter_key, JSON_PIN_CODE));
- request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_PIN_CODE,"")));
+ request.push_back(makeStringBlock(tlv_parameter_key, PARAMETER_KEY_CODE));
+ request.push_back(makeStringBlock(tlv_parameter_value, std::get<1>(params[0])));
}
else {
- _LOG_ERROR("Client's status and challenge status are wrong");
+ BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
}
request.encode();
return request;
}
-} // namespace ndncert
-} // namespace ndn
+} // namespace ndncert
+} // namespace ndn
diff --git a/src/challenge-module/challenge-pin.hpp b/src/challenge-module/challenge-pin.hpp
index 44db7d8..88cf9bd 100644
--- a/src/challenge-module/challenge-pin.hpp
+++ b/src/challenge-module/challenge-pin.hpp
@@ -52,26 +52,24 @@
const time::seconds& secretLifetime = time::seconds(3600));
// For CA
- void
+ std::tuple<Error, std::string>
handleChallengeRequest(const Block& params, CertificateRequest& request) override;
// For Client
- JsonSection
- getRequirementForChallenge(Status status, const std::string& challengeStatus) override;
-
- JsonSection
- genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params) override;
+ std::vector<std::tuple<std::string, std::string>>
+ getRequestedParameterList(Status status, const std::string& challengeStatus) override;
Block
- genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params) override;
+ genChallengeRequestTLV(Status status, const std::string& challengeStatus,
+ std::vector<std::tuple<std::string, std::string>>&& params) override;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
// challenge status
static const std::string NEED_CODE;
static const std::string WRONG_CODE;
- // JSON attribute
- static const std::string JSON_PIN_CODE;
+ // parameters
+ static const std::string PARAMETER_KEY_CODE;
private:
time::seconds m_secretLifetime;
diff --git a/src/challenge-module/challenge-private-key.cpp b/src/challenge-module/challenge-private-key.cpp
deleted file mode 100644
index 74af413..0000000
--- a/src/challenge-module/challenge-private-key.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2017-2020, Regents of the University of California.
- *
- * This file is part of ndncert, a certificate management system based on NDN.
- *
- * ndncert is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received copies of the GNU General Public License along with
- * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndncert authors and contributors.
- */
-
-#include "challenge-private-key.hpp"
-
-#include <iostream>
-#include <ndn-cxx/security/verification-helpers.hpp>
-#include <ndn-cxx/util/io.hpp>
-
-#include "../logging.hpp"
-
-namespace ndn {
-namespace ndncert {
-
-_LOG_INIT(ndncert.ChallengePrivateKey);
-
-NDNCERT_REGISTER_CHALLENGE(ChallengePrivateKey, "Private");
-
-const std::string ChallengePrivateKey::FAILURE_INVALID_REQUEST_TYPE = "failure-invalid-request-type";
-const std::string ChallengePrivateKey::FAILURE_INVALID_FORMAT_SELF_SIGNED = "failure-cannot-parse-self-signed";
-const std::string ChallengePrivateKey::FAILURE_INVALID_CREDENTIAL = "failure-invalid-credential";
-const std::string ChallengePrivateKey::JSON_PROOF_OF_PRIVATE_KEY = "proof-of-private-key";
-
-ChallengePrivateKey::ChallengePrivateKey()
- : ChallengeModule("PrivateKey")
-{
-}
-
-// For CA
-void
-ChallengePrivateKey::handleChallengeRequest(const Block& params, CertificateRequest& request)
-{
- if (request.m_requestType == REQUEST_TYPE_NEW) {
- _LOG_TRACE("Cannot use this private key challenge for new certificate request");
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = FAILURE_INVALID_REQUEST_TYPE;
- updateRequestOnChallengeEnd(request);
- }
- params.parse();
- shared_ptr<security::v2::Certificate> selfSigned;
- auto& elements = params.elements();
- for (size_t i = 0; i < elements.size(); i++) {
- if (elements[i].type() == tlv_parameter_key) {
- if (readString(elements[i]) == JSON_PROOF_OF_PRIVATE_KEY) {
- std::istringstream ss(readString(params.elements()[i + 1]));
- selfSigned = io::load<security::v2::Certificate>(ss);
- if (selfSigned == nullptr) {
- _LOG_ERROR("Cannot load credential parameter: cert");
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = FAILURE_INVALID_FORMAT_SELF_SIGNED;
- updateRequestOnChallengeEnd(request);
- return;
- }
- }
- else {
- continue;
- }
- }
- }
-
- // verify the credential and the self-signed cert
- if (security::verifySignature(*selfSigned, request.m_cert) &&
- readString(selfSigned->getContent()) == request.m_requestId) {
- request.m_status = Status::PENDING;
- request.m_challengeStatus = CHALLENGE_STATUS_SUCCESS;
- updateRequestOnChallengeEnd(request);
- return;
- }
-
- _LOG_TRACE("Cannot verify the credential + self-signed Data + data content");
- request.m_status = Status::FAILURE;
- request.m_challengeStatus = FAILURE_INVALID_CREDENTIAL;
- updateRequestOnChallengeEnd(request);
-}
-
-// For Client
-JsonSection
-ChallengePrivateKey::getRequirementForChallenge(Status status, const std::string& challengeStatus)
-{
- JsonSection result;
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- result.put(JSON_PROOF_OF_PRIVATE_KEY, "Please_copy_key_signed_request_id_data_here");
- }
- else {
- _LOG_ERROR("Client's status and challenge status are wrong");
- }
- return result;
-}
-
-JsonSection
-ChallengePrivateKey::genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params)
-{
- JsonSection result;
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- result.put(JSON_PROOF_OF_PRIVATE_KEY, params.get(JSON_PROOF_OF_PRIVATE_KEY, ""));
- }
- else {
- _LOG_ERROR("Client's status and challenge status are wrong");
- }
- return result;
-}
-
-Block
-ChallengePrivateKey::genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params)
-{
- Block request = makeEmptyBlock(tlv_encrypted_payload);
- if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
- request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
- request.push_back(makeStringBlock(tlv_parameter_key, JSON_PROOF_OF_PRIVATE_KEY));
- request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_PROOF_OF_PRIVATE_KEY, "")));
- }
- else {
- _LOG_ERROR("Client's status and challenge status are wrong");
- }
- request.encode();
- return request;
-}
-} // namespace ndncert
-} // namespace ndn
diff --git a/src/challenge-module/challenge-private-key.hpp b/src/challenge-module/challenge-private-key.hpp
deleted file mode 100644
index 5f0b936..0000000
--- a/src/challenge-module/challenge-private-key.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright (c) 2017-2020, Regents of the University of California.
- *
- * This file is part of ndncert, a certificate management system based on NDN.
- *
- * ndncert is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received copies of the GNU General Public License along with
- * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndncert authors and contributors.
- */
-
-#ifndef NDNCERT_CHALLENGE_PRIVATE_KEY_HPP
-#define NDNCERT_CHALLENGE_PRIVATE_KEY_HPP
-
-#include "../challenge-module.hpp"
-
-namespace ndn {
-namespace ndncert {
-
-/**
- * @brief Private Key based challenge (for renewal and revocation)
- *
- * Once the requester could proof his/her possession of the private key corresponds to
- * the current CA's previous issued certificate, the requester could finish the challenge.
- *
- * The requester needs to provide the proof of the possession the private for the certificate
- * for the previous cerificate. The challenge require the requester to a BASE64 Data packet
- * signed by the credential pub key and whose content is the request id.
- *
- * The main process of this challenge module is:
- * 1. The requester sign a Data packet which content is the request id.
- * 2. The challenge module will verify the signature of the credential.
- *
- * Failure info when application fails:
- * FAILURE_INVALID_CREDENTIAL: When the signature cannot be validated.
- * FAILURE_INVALID_FORMAT: When the credential format is wrong.
- */
-class ChallengePrivateKey : public ChallengeModule
-{
-public:
- ChallengePrivateKey();
-
- // For CA
- void
- handleChallengeRequest(const Block& params, CertificateRequest& request) override;
-
- // For Client
- JsonSection
- getRequirementForChallenge(Status status, const std::string& challengeStatus) override;
-
- JsonSection
- genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params) override;
-
- Block
- genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params) override;
-
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
- static const std::string FAILURE_INVALID_REQUEST_TYPE;
- static const std::string FAILURE_INVALID_CREDENTIAL;
- static const std::string FAILURE_INVALID_FORMAT_SELF_SIGNED;
- static const std::string JSON_PROOF_OF_PRIVATE_KEY;
-};
-
-} // namespace ndncert
-} // namespace ndn
-
-#endif // NDNCERT_CHALLENGE_PRIVATE_KEY_HPP
diff --git a/src/ndncert-common.hpp b/src/ndncert-common.hpp
index cbbba39..6727a88 100644
--- a/src/ndncert-common.hpp
+++ b/src/ndncert-common.hpp
@@ -149,6 +149,7 @@
std::string statusToString(Status status);
enum class Error : uint16_t {
+ NO_ERROR = 0,
BAD_INTEREST_FORMAT = 1,
BAD_PARAMETER_FORMAT = 2,
BAD_SIGNATURE = 3,
diff --git a/src/protocol-detail/error.cpp b/src/protocol-detail/error.cpp
new file mode 100644
index 0000000..0b24eec
--- /dev/null
+++ b/src/protocol-detail/error.cpp
@@ -0,0 +1,46 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2017-2020, Regents of the University of California.
+ *
+ * This file is part of ndncert, a certificate management system based on NDN.
+ *
+ * ndncert is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndncert authors and contributors.
+ */
+
+#include "error.hpp"
+
+namespace ndn {
+namespace ndncert {
+
+Block
+ERROR::encodeDataContent(Error errorCode, const std::string& description)
+{
+ Block response = makeEmptyBlock(tlv::Content);
+ response.push_back(makeNonNegativeIntegerBlock(tlv_error_code, static_cast<size_t>(errorCode)));
+ response.push_back(makeStringBlock(tlv_error_info, description));
+ response.encode();
+ return response;
+}
+
+std::tuple<Error, std::string>
+ERROR::decodefromDataContent(const Block& block)
+{
+ block.parse();
+ Error error = static_cast<Error>(readNonNegativeInteger(block.get(tlv_error_code)));
+ auto description = readString(block.get(tlv_error_info));
+ return std::make_tuple(error, description);
+}
+
+} // namespace ndncert
+} // namespace ndn
diff --git a/src/protocol-detail/error.hpp b/src/protocol-detail/error.hpp
new file mode 100644
index 0000000..c03ec05
--- /dev/null
+++ b/src/protocol-detail/error.hpp
@@ -0,0 +1,48 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2017-2020, Regents of the University of California.
+ *
+ * This file is part of ndncert, a certificate management system based on NDN.
+ *
+ * ndncert is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndncert authors and contributors.
+ */
+
+#ifndef NDNCERT_PROTOCOL_DETAIL_ERROR_HPP
+#define NDNCERT_PROTOCOL_DETAIL_ERROR_HPP
+
+#include "../ca-config.hpp"
+#include "../client-config.hpp"
+
+namespace ndn {
+namespace ndncert {
+
+class ERROR {
+public:
+ /**
+ * Encode error information into a Data content TLV
+ */
+ static Block
+ encodeDataContent(Error errorCode, const std::string& description);
+
+ /**
+ * Decode error information from Data content TLV
+ */
+ static std::tuple<Error, std::string>
+ decodefromDataContent(const Block& block);
+};
+
+} // namespace ndncert
+} // namespace ndn
+
+#endif // NDNCERT_PROTOCOL_ERROR_HPP
\ No newline at end of file