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/challenge-module/challenge-email.cpp b/src/challenge-module/challenge-email.cpp
index b65d331..dbd3b2c 100644
--- a/src/challenge-module/challenge-email.cpp
+++ b/src/challenge-module/challenge-email.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.
*
@@ -31,15 +31,9 @@
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::FAILURE_TIMEOUT = "timeout";
-const std::string ChallengeEmail::FAILURE_MAXRETRY = "max-retry";
-
const std::string ChallengeEmail::JSON_EMAIL = "email";
-const std::string ChallengeEmail::JSON_CODE_TP = "code-timepoint";
const std::string ChallengeEmail::JSON_CODE = "code";
-const std::string ChallengeEmail::JSON_ATTEMPT_TIMES = "attempt-times";
ChallengeEmail::ChallengeEmail(const std::string& scriptPath,
const size_t& maxAttemptTimes,
@@ -51,131 +45,123 @@
{
}
-JsonSection
-ChallengeEmail::processSelectInterest(const Interest& interest, CertificateRequest& request)
+// For CA
+void
+ChallengeEmail::handleChallengeRequest(const JsonSection& params, CertificateRequest& request)
{
- // interest format: /caName/CA/_SELECT/{"request-id":"id"}/EMAIL/{"Email":"email"}/<signature>
- JsonSection emailJson = getJsonFromNameComponent(interest.getName(),
- request.getCaName().size() + 4);
- std::string emailAddress = emailJson.get<std::string>(JSON_EMAIL);
- if (!isValidEmailAddress(emailAddress)) {
- request.setStatus(FAILURE_INVALID_EMAIL);
- request.setChallengeType(CHALLENGE_TYPE);
- return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_INVALID_EMAIL);
+ if (request.m_challengeStatus == "") {
+ // for the first time, init the challenge
+ std::string emailAddress = params.get<std::string>(JSON_EMAIL);
+ if (!isValidEmailAddress(emailAddress)) {
+ request.m_status = STATUS_FAILURE;
+ request.m_challengeStatus = FAILURE_INVALID_EMAIL;
+ return;
+ }
+ 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(time::system_clock::now());
+ request.m_remainingTime = m_secretLifetime.count();
+ request.m_remainingTries = m_maxAttemptTimes;
+ // send out the email
+ sendEmail(emailAddress, emailCode, request);
+ _LOG_TRACE("Secret for request " << request.m_requestId << " : " << emailCode);
+ return;
}
-
- std::string emailCode = generateSecretCode();
- sendEmail(emailAddress, emailCode, request.getCaName().toUri());
-
- request.setStatus(NEED_CODE);
- request.setChallengeType(CHALLENGE_TYPE);
- request.setChallengeSecrets(generateStoredSecrets(time::system_clock::now(),
- emailCode, m_maxAttemptTimes));
- return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, NEED_CODE);
-}
-
-JsonSection
-ChallengeEmail::processValidateInterest(const Interest& interest, CertificateRequest& request)
-{
- // interest format: /caName/CA/_VALIDATION/{"request-id":"id"}/EMAIL/{"code":"code"}/<signature>
- JsonSection infoJson = getJsonFromNameComponent(interest.getName(), request.getCaName().size() + 4);
- std::string givenCode = infoJson.get<std::string>(JSON_CODE);
-
- const auto parsedSecret = parseStoredSecrets(request.getChallengeSecrets());
- if (time::system_clock::now() - std::get<0>(parsedSecret) >= m_secretLifetime) {
- // secret expires
- request.setStatus(FAILURE_TIMEOUT);
- request.setChallengeSecrets(JsonSection());
- return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_TIMEOUT);
- }
- else if (givenCode == std::get<1>(parsedSecret)) {
- request.setStatus(SUCCESS);
- request.setChallengeSecrets(JsonSection());
- Name downloadName = genDownloadName(request.getCaName(), request.getRequestId());
- return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, SUCCESS, downloadName);
- }
- else {
- // check rest attempt times
- if (std::get<2>(parsedSecret) > 1) {
- int restAttemptTimes = std::get<2>(parsedSecret) - 1;
- request.setStatus(WRONG_CODE);
- request.setChallengeSecrets(generateStoredSecrets(std::get<0>(parsedSecret),
- std::get<1>(parsedSecret),
- restAttemptTimes));
- return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, WRONG_CODE);
+ else 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 = params.get<std::string>(JSON_CODE);
+ const auto realCode = request.m_challengeSecrets.get<std::string>(JSON_CODE);
+ if (time::system_clock::now() - 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;
+ }
+ else if (givenCode == realCode) {
+ // 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;
}
else {
- // run out times
- request.setStatus(FAILURE_MAXRETRY);
- request.setChallengeSecrets(JsonSection());
- return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_MAXRETRY);
+ // 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 - (time::system_clock::now() - 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;
+ }
}
}
-}
-
-std::list<std::string>
-ChallengeEmail::getSelectRequirements()
-{
- std::list<std::string> result;
- result.push_back("Please input your email address:");
- return result;
-}
-
-std::list<std::string>
-ChallengeEmail::getValidateRequirements(const std::string& status)
-{
- std::list<std::string> result;
- if (status == NEED_CODE) {
- result.push_back("Please input your verification code:");
+ else {
+ _LOG_ERROR("The challenge status is wrong");
+ request.m_status = STATUS_FAILURE;
+ return;
}
- else if (status == WRONG_CODE) {
- result.push_back("Incorrect PIN code, please try again and input your verification code:");
+}
+
+// For Client
+JsonSection
+ChallengeEmail::getRequirementForChallenge(int status, const std::string& challengeStatus)
+{
+ JsonSection result;
+ if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
+ result.put(JSON_EMAIL, "Please_input_your_email_address");
+ }
+ else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
+ result.put(JSON_CODE, "Please_input_your_verification_code");
+ }
+ else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
+ result.put(JSON_CODE, "Incorrect_code_please_try_again");
+ }
+ else {
+ _LOG_ERROR("CA's status and challenge status are wrong");
}
return result;
}
JsonSection
-ChallengeEmail::doGenSelectParamsJson(const std::string& status,
- const std::list<std::string>& paramList)
+ChallengeEmail::genChallengeRequestJson(int status, const std::string& challengeStatus, const JsonSection& params)
{
JsonSection result;
- BOOST_ASSERT(status == WAIT_SELECTION);
- BOOST_ASSERT(paramList.size() == 1);
- result.put(JSON_EMAIL, paramList.front());
+ if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
+ result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
+ result.put(JSON_EMAIL, params.get<std::string>(JSON_EMAIL, ""));
+ }
+ else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
+ result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
+ result.put(JSON_CODE, params.get<std::string>(JSON_CODE, ""));
+ }
+ else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
+ result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
+ result.put(JSON_CODE, params.get<std::string>(JSON_CODE, ""));
+ }
+ else {
+ _LOG_ERROR("Client's status and challenge status are wrong");
+ }
return result;
}
-JsonSection
-ChallengeEmail::doGenValidateParamsJson(const std::string& status,
- const std::list<std::string>& paramList)
-{
- JsonSection result;
- BOOST_ASSERT(paramList.size() == 1);
- result.put(JSON_CODE, paramList.front());
- return result;
-}
-
-std::tuple<time::system_clock::TimePoint, std::string, int>
-ChallengeEmail::parseStoredSecrets(const JsonSection& storedSecrets)
-{
- auto tp = time::fromIsoString(storedSecrets.get<std::string>(JSON_CODE_TP));
- std::string rightCode= storedSecrets.get<std::string>(JSON_CODE);
- int attemptTimes = std::stoi(storedSecrets.get<std::string>(JSON_ATTEMPT_TIMES));
-
- return std::make_tuple(tp, rightCode, attemptTimes);
-}
-
-JsonSection
-ChallengeEmail::generateStoredSecrets(const time::system_clock::TimePoint& tp,
- const std::string& secretCode, int attempTimes)
-{
- JsonSection json;
- json.put(JSON_CODE_TP, time::toIsoString(tp));
- json.put(JSON_CODE, secretCode);
- json.put(JSON_ATTEMPT_TIMES, std::to_string(attempTimes));
- return json;
-}
-
bool
ChallengeEmail::isValidEmailAddress(const std::string& emailAddress)
{
@@ -186,10 +172,10 @@
void
ChallengeEmail::sendEmail(const std::string& emailAddress, const std::string& secret,
- const std::string& caName) const
+ const CertificateRequest& request) const
{
std::string command = m_sendEmailScript;
- command += " \"" + emailAddress + "\" \"" + secret + "\" \"" + caName + "\"";
+ command += " \"" + emailAddress + "\" \"" + secret + "\" \"" + request.m_caName.toUri() + "\"";
int result = system(command.c_str());
if (result == -1) {
_LOG_TRACE("EmailSending Script " + m_sendEmailScript + " fails.");