blob: 7de32f05f14dc93640b23b53b59b37dbdeee6071 [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 Zhang65ba9322017-01-19 14:15:03 -080030NDNCERT_REGISTER_CHALLENGE(ChallengePin, "PIN");
31
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)
37 : ChallengeModule("PIN")
38 , 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 Zhangaf7c2902019-03-14 22:13:21 -070047 if (request.m_challengeStatus == "") {
48 _LOG_TRACE("Challenge Interest arrives. Init the challenge");
49 // for the first time, init the challenge
50 request.m_status = STATUS_CHALLENGE;
51 request.m_challengeStatus = NEED_CODE;
52 request.m_challengeType = CHALLENGE_TYPE;
53 std::string secretCode = generateSecretCode();
54 JsonSection secretJson;
55 secretJson.add(JSON_PIN_CODE, secretCode);
56 request.m_challengeSecrets = secretJson;
57 request.m_challengeTp = time::toIsoString(time::system_clock::now());
58 request.m_remainingTime = m_secretLifetime.count();
59 request.m_remainingTries = m_maxAttemptTimes;
60 _LOG_TRACE("Secret for request " << request.m_requestId << " : " << secretCode);
61 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080062 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070063 else if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
64 _LOG_TRACE("Challenge Interest arrives. Challenge Status: " << request.m_challengeStatus);
65 // the incoming interest should bring the pin code
66 std::string givenCode = params.get<std::string>(JSON_PIN_CODE);
67 const auto realCode = request.m_challengeSecrets.get<std::string>(JSON_PIN_CODE);
68 if (time::system_clock::now() - time::fromIsoString(request.m_challengeTp) >= m_secretLifetime) {
69 // secret expires
70 request.m_status = STATUS_FAILURE;
71 request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_TIMEOUT;
72 updateRequestOnChallengeEnd(request);
73 _LOG_TRACE("Secret expired. Challenge failed.");
74 return;
75 }
76 else if (givenCode == realCode) {
77 // the code is correct
78 request.m_status = STATUS_PENDING;
79 request.m_challengeStatus = CHALLENGE_STATUS_SUCCESS;
80 updateRequestOnChallengeEnd(request);
81 _LOG_TRACE("PIN code matched. Challenge succeeded.");
82 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080083 }
84 else {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070085 // check rest attempt times
86 if (request.m_remainingTries > 1) {
87 request.m_challengeStatus = WRONG_CODE;
88 request.m_remainingTries = request.m_remainingTries - 1;
89 auto remainTime = m_secretLifetime - (time::system_clock::now() - time::fromIsoString(request.m_challengeTp));
90 request.m_remainingTime = remainTime.count();
91 _LOG_TRACE("PIN code didn't match. Remaining Tries - 1.");
92 return;
93 }
94 else {
95 // run out times
96 request.m_status = STATUS_FAILURE;
97 request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_MAXRETRY;
98 updateRequestOnChallengeEnd(request);
99 _LOG_TRACE("PIN code didn't match. Ran out tires. Challenge failed.");
100 return;
101 }
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800102 }
103 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700104 else {
105 _LOG_ERROR("The challenge status is wrong");
106 request.m_status = STATUS_FAILURE;
107 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800108 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700109}
110
111// For Client
112JsonSection
113ChallengePin::getRequirementForChallenge(int status, const std::string& challengeStatus)
114{
115 JsonSection result;
116 if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
117 // do nothing
118 }
119 else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
120 result.put(JSON_PIN_CODE, "Please_input_your_verification_code");
121 }
122 else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
123 result.put(JSON_PIN_CODE, "Incorrect_PIN_code_please_try_again");
124 }
125 else {
126 _LOG_ERROR("Client's status and challenge status are wrong");
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800127 }
128 return result;
129}
130
131JsonSection
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700132ChallengePin::genChallengeRequestJson(int status, const std::string& challengeStatus, const JsonSection& params)
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800133{
134 JsonSection result;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700135 if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
136 // do nothing
137 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
138 }
139 else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
140 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
141 result.put(JSON_PIN_CODE, params.get<std::string>(JSON_PIN_CODE, ""));
142 }
143 else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
144 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
145 result.put(JSON_PIN_CODE, params.get<std::string>(JSON_PIN_CODE, ""));
146 }
147 else {
148 _LOG_ERROR("Client's status and challenge status are wrong");
149 }
Zhiyi Zhangf72c0542017-03-16 14:45:30 -0700150 return result;
151}
152
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800153} // namespace ndncert
154} // namespace ndn