blob: 87f36cc3a80d7e7fa58410fcb6ec0c3acc8662b6 [file] [log] [blame]
Zhiyi Zhang65ba9322017-01-19 14:15:03 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -07003 * Copyright (c) 2017-2019, Regents of the University of California.
Zhiyi Zhang65ba9322017-01-19 14:15:03 -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 "challenge-pin.hpp"
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080022#include "logging.hpp"
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080023#include <ndn-cxx/util/random.hpp>
24
25namespace ndn {
26namespace ndncert {
27
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080028_LOG_INIT(ndncert.challenge-pin);
29
Zhiyi Zhang36706832019-07-04 21:33:03 -070030NDNCERT_REGISTER_CHALLENGE(ChallengePin, "pin");
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080031
32const std::string ChallengePin::NEED_CODE = "need-code";
33const std::string ChallengePin::WRONG_CODE = "wrong-code";
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070034const std::string ChallengePin::JSON_PIN_CODE = "pin-code";
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080035
36ChallengePin::ChallengePin(const size_t& maxAttemptTimes, const time::seconds& secretLifetime)
Zhiyi Zhang36706832019-07-04 21:33:03 -070037 : ChallengeModule("pin")
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080038 , m_secretLifetime(secretLifetime)
39 , m_maxAttemptTimes(maxAttemptTimes)
40{
41}
42
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070043// For CA
44void
45ChallengePin::handleChallengeRequest(const JsonSection& params, CertificateRequest& request)
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080046{
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080047 auto currentTime = time::system_clock::now();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070048 if (request.m_challengeStatus == "") {
49 _LOG_TRACE("Challenge Interest arrives. Init the challenge");
50 // for the first time, init the challenge
51 request.m_status = STATUS_CHALLENGE;
52 request.m_challengeStatus = NEED_CODE;
53 request.m_challengeType = CHALLENGE_TYPE;
54 std::string secretCode = generateSecretCode();
55 JsonSection secretJson;
56 secretJson.add(JSON_PIN_CODE, secretCode);
57 request.m_challengeSecrets = secretJson;
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080058 request.m_challengeTp = time::toIsoString(currentTime);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070059 request.m_remainingTime = m_secretLifetime.count();
60 request.m_remainingTries = m_maxAttemptTimes;
61 _LOG_TRACE("Secret for request " << request.m_requestId << " : " << secretCode);
62 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080063 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070064 else if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
65 _LOG_TRACE("Challenge Interest arrives. Challenge Status: " << request.m_challengeStatus);
66 // the incoming interest should bring the pin code
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080067 std::string givenCode = params.get(JSON_PIN_CODE, "");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070068 const auto realCode = request.m_challengeSecrets.get<std::string>(JSON_PIN_CODE);
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080069 if (currentTime - time::fromIsoString(request.m_challengeTp) >= m_secretLifetime) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070070 // secret expires
71 request.m_status = STATUS_FAILURE;
72 request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_TIMEOUT;
73 updateRequestOnChallengeEnd(request);
74 _LOG_TRACE("Secret expired. Challenge failed.");
75 return;
76 }
77 else if (givenCode == realCode) {
78 // the code is correct
79 request.m_status = STATUS_PENDING;
80 request.m_challengeStatus = CHALLENGE_STATUS_SUCCESS;
81 updateRequestOnChallengeEnd(request);
82 _LOG_TRACE("PIN code matched. Challenge succeeded.");
83 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080084 }
85 else {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070086 // check rest attempt times
87 if (request.m_remainingTries > 1) {
88 request.m_challengeStatus = WRONG_CODE;
89 request.m_remainingTries = request.m_remainingTries - 1;
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080090 auto remainTime = m_secretLifetime - (currentTime - time::fromIsoString(request.m_challengeTp));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070091 request.m_remainingTime = remainTime.count();
92 _LOG_TRACE("PIN code didn't match. Remaining Tries - 1.");
93 return;
94 }
95 else {
96 // run out times
97 request.m_status = STATUS_FAILURE;
98 request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_MAXRETRY;
99 updateRequestOnChallengeEnd(request);
100 _LOG_TRACE("PIN code didn't match. Ran out tires. Challenge failed.");
101 return;
102 }
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800103 }
104 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700105 else {
106 _LOG_ERROR("The challenge status is wrong");
107 request.m_status = STATUS_FAILURE;
108 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800109 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700110}
111
112// For Client
113JsonSection
114ChallengePin::getRequirementForChallenge(int status, const std::string& challengeStatus)
115{
116 JsonSection result;
117 if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
118 // do nothing
119 }
120 else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
121 result.put(JSON_PIN_CODE, "Please_input_your_verification_code");
122 }
123 else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
124 result.put(JSON_PIN_CODE, "Incorrect_PIN_code_please_try_again");
125 }
126 else {
127 _LOG_ERROR("Client's status and challenge status are wrong");
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800128 }
129 return result;
130}
131
132JsonSection
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700133ChallengePin::genChallengeRequestJson(int status, const std::string& challengeStatus, const JsonSection& params)
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800134{
135 JsonSection result;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700136 if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
137 // do nothing
138 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
139 }
140 else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
141 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800142 result.put(JSON_PIN_CODE, params.get(JSON_PIN_CODE, ""));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700143 }
144 else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
145 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800146 result.put(JSON_PIN_CODE, params.get(JSON_PIN_CODE, ""));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700147 }
148 else {
149 _LOG_ERROR("Client's status and challenge status are wrong");
150 }
Zhiyi Zhangf72c0542017-03-16 14:45:30 -0700151 return result;
152}
153
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800154} // namespace ndncert
155} // namespace ndn