blob: fec4aa1b2e6148cf43d911a6c281f5d4ebc5fae1 [file] [log] [blame]
Zhiyi Zhang08e0e982017-03-01 10:10:42 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoe5b43692021-11-15 22:05:03 -05002/*
3 * Copyright (c) 2017-2021, Regents of the University of California.
Zhiyi Zhang08e0e982017-03-01 10:10:42 -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
tylerliu4140fe82021-01-27 15:45:44 -080021#include "requester-request.hpp"
Davide Pesaventoe5b43692021-11-15 22:05:03 -050022
Zhiyi Zhang90c75782020-10-06 15:04:03 -070023#include <ndn-cxx/security/verification-helpers.hpp>
Davide Pesaventoe5b43692021-11-15 22:05:03 -050024
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070025#include <boost/asio.hpp>
Davide Pesaventob48bbda2020-07-27 19:41:37 -040026#include <boost/program_options/options_description.hpp>
27#include <boost/program_options/parsers.hpp>
28#include <boost/program_options/variables_map.hpp>
Davide Pesaventoe5b43692021-11-15 22:05:03 -050029
Zhiyi Zhang48f23782020-09-28 12:11:24 -070030#include <iostream>
Zhiyi Zhang48f23782020-09-28 12:11:24 -070031
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080032namespace ndn {
33namespace ndncert {
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -070034namespace requester {
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080035
Zhiyi Zhang48f23782020-09-28 12:11:24 -070036static void
tylerliufeabfdc2020-10-03 15:09:58 -070037selectCaProfile(std::string configFilePath);
Davide Pesaventoe5b43692021-11-15 22:05:03 -050038
tylerliufeabfdc2020-10-03 15:09:58 -070039static void
40runProbe(CaProfile profile);
Davide Pesaventoe5b43692021-11-15 22:05:03 -050041
tylerliufeabfdc2020-10-03 15:09:58 -070042static void
43runNew(CaProfile profile, Name identityName);
Davide Pesaventoe5b43692021-11-15 22:05:03 -050044
tylerliufeabfdc2020-10-03 15:09:58 -070045static void
46runChallenge(const std::string& challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070047
Davide Pesaventoe5b43692021-11-15 22:05:03 -050048static size_t nStep = 1;
49static Face face;
50static security::KeyChain keyChain;
51static shared_ptr<Request> requesterState;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080052
Zhiyi Zhang46049832020-09-28 17:08:12 -070053static void
tylerliu40226332020-11-11 15:37:16 -080054captureParams(std::multimap<std::string, std::string>& requirement)
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080055{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070056 std::list<std::string> results;
Zhiyi Zhang46049832020-09-28 17:08:12 -070057 for (auto& item : requirement) {
58 std::cerr << std::get<1>(item) << std::endl;
59 std::string captured;
60 getline(std::cin, captured);
61 std::get<1>(item) = captured;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080062 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070063 std::cerr << "Got it. This is what you've provided:" << std::endl;
Zhiyi Zhang46049832020-09-28 17:08:12 -070064 for (const auto& item : requirement) {
65 std::cerr << std::get<0>(item) << " : " << std::get<1>(item) << std::endl;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080066 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070067}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080068
tylerliu40226332020-11-11 15:37:16 -080069static std::multimap<std::string, std::string>
Zhiyi Zhang2de4ea32020-12-13 17:45:25 -080070captureParams(const std::vector<std::string>& requirement)
Zhiyi Zhang547c8512019-06-18 23:46:14 -070071{
tylerliu40226332020-11-11 15:37:16 -080072 std::multimap<std::string, std::string> results;
tylerliufeabfdc2020-10-03 15:09:58 -070073 for (const auto& r : requirement) {
tylerliu40226332020-11-11 15:37:16 -080074 results.emplace(r, "Please input: " + r);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070075 }
tylerliufeabfdc2020-10-03 15:09:58 -070076 captureParams(results);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070077 return results;
78}
79
tylerliufeabfdc2020-10-03 15:09:58 -070080static int
Zhiyi Zhang36706832019-07-04 21:33:03 -070081captureValidityPeriod()
82{
Zhiyi Zhang837406d2020-10-05 22:01:31 -070083 std::cerr << "\n***************************************\n"
84 << "Step " << nStep++
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070085 << ": Please type in your expected validity period of your certificate."
86 << " Type the number of hours (168 for week, 730 for month, 8760 for year)."
87 << " The CA may reject your application if your expected period is too long." << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -080088 size_t count = 0;
89 while (true && count < 3) {
tylerliufeabfdc2020-10-03 15:09:58 -070090 std::string periodStr = "";
91 getline(std::cin, periodStr);
92 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -070093 return std::stoul(periodStr);
tylerliufeabfdc2020-10-03 15:09:58 -070094 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -070095 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -070096 std::cerr << "Your input is invalid. Try again: " << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -080097 count++;
tylerliufeabfdc2020-10-03 15:09:58 -070098 }
Zhiyi Zhang36706832019-07-04 21:33:03 -070099 }
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800100 std::cerr << "Invalid input for too many times, exit. " << std::endl;
101 exit(1);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700102}
103
104static void
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700105onNackCb()
106{
107 std::cerr << "Got NACK\n";
108}
109
110static void
111timeoutCb()
112{
113 std::cerr << "Interest sent time out\n";
114}
115
116static void
swa770cf1d8f72020-04-21 23:12:39 -0700117certFetchCb(const Data& reply)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700118{
tylerliu4140fe82021-01-27 15:45:44 -0800119 auto item = Request::onCertFetchResponse(reply);
tylerliufeabfdc2020-10-03 15:09:58 -0700120 if (item) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700121 keyChain.addCertificate(keyChain.getPib().getIdentity(item->getIdentity()).getKey(item->getKeyName()), *item);
tylerliufeabfdc2020-10-03 15:09:58 -0700122 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700123 std::cerr << "\n***************************************\n"
124 << "Step " << nStep++
125 << ": DONE\nCertificate with Name: " << reply.getName().toUri()
126 << "has already been installed to your local keychain" << std::endl
127 << "Exit now";
128 face.getIoService().stop();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700129}
130
131static void
132challengeCb(const Data& reply)
133{
tylerliufeabfdc2020-10-03 15:09:58 -0700134 try {
tylerliu4140fe82021-01-27 15:45:44 -0800135 requesterState->onChallengeResponse(reply);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700136 }
137 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700138 std::cerr << "Error when decoding challenge step: " << e.what() << std::endl;
139 exit(1);
140 }
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800141 if (requesterState->m_status == Status::SUCCESS) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700142 std::cerr << "Certificate has already been issued, downloading certificate..." << std::endl;
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500143 face.expressInterest(*requesterState->genCertFetchInterest(),
144 [] (const auto&, const auto& data) { certFetchCb(data); },
145 [] (auto&&...) { onNackCb(); },
146 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700147 return;
148 }
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800149 runChallenge(requesterState->m_challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700150}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800151
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700152static void
153newCb(const Data& reply)
154{
tylerliufeabfdc2020-10-03 15:09:58 -0700155 std::list<std::string> challengeList;
156 try {
tylerliu4140fe82021-01-27 15:45:44 -0800157 challengeList = requesterState->onNewRenewRevokeResponse(reply);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700158 }
159 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700160 std::cerr << "Error on decoding NEW step reply because: " << e.what() << std::endl;
161 exit(1);
162 }
163
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700164 size_t challengeIndex = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700165 if (challengeList.size() < 1) {
166 std::cerr << "There is no available challenge provided by the CA. Exit" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700167 exit(1);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800168 }
Zhiyi Zhang48f546f2020-12-24 17:31:02 -0800169 else if (challengeList.size() >= 1) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700170 std::cerr << "\n***************************************\n"
171 << "Step " << nStep++
172 << ": CHALLENGE SELECTION" << std::endl;
173 size_t count = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700174 std::string choice = "";
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700175 for (auto item : challengeList) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700176 std::cerr << "> Index: " << count++ << std::endl
177 << ">> Challenge:" << item << std::endl;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700178 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700179 std::cerr << "Please type in the challenge index that you want to perform:" << std::endl;
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800180 size_t inputCount = 0;
181 while (inputCount < 3) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700182 getline(std::cin, choice);
183 try {
184 challengeIndex = std::stoul(choice);
185 }
186 catch (const std::exception& e) {
187 std::cerr << "Your input is not valid. Try again:" << std::endl;
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800188 inputCount++;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700189 continue;
190 }
191 if (challengeIndex >= count) {
192 std::cerr << "Your input index is out of range. Try again:" << std::endl;
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800193 inputCount++;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700194 continue;
195 }
196 break;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700197 }
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800198 if (inputCount == 3) {
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800199 std::cerr << "Invalid input for too many times, exit. " << std::endl;
200 exit(1);
201 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700202 }
203 auto it = challengeList.begin();
204 std::advance(it, challengeIndex);
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700205 std::cerr << "The challenge has been selected: " << *it << std::endl;
206 runChallenge(*it);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700207}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800208
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700209static void
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500210infoCb(const Data& reply, const Name& certFullName)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700211{
Zhiyi Zhang997669a2020-10-28 21:15:40 -0700212 optional<CaProfile> profile;
tylerliufeabfdc2020-10-03 15:09:58 -0700213 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700214 if (certFullName.empty()) {
tylerliu4140fe82021-01-27 15:45:44 -0800215 profile = Request::onCaProfileResponse(reply);
tylerliufeabfdc2020-10-03 15:09:58 -0700216 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700217 else {
tylerliu4140fe82021-01-27 15:45:44 -0800218 profile = Request::onCaProfileResponseAfterRedirection(reply, certFullName);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700219 }
220 }
221 catch (const std::exception& e) {
222 std::cerr << "The fetched CA information cannot be used because: " << e.what() << std::endl;
223 return;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700224 }
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700225 std::cerr << "\n***************************************\n"
226 << "Step " << nStep++
227 << ": Will use a new trust anchor, please double check the identity info:" << std::endl
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800228 << "> New CA name: " << profile->caPrefix.toUri() << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700229 << "> This trust anchor information is signed by: " << reply.getSignatureInfo().getKeyLocator() << std::endl
Zhiyi Zhangec4aa3a2021-01-08 14:26:37 -0800230 << "> The certificate: " << *profile->cert << std::endl
Davide Pesaventob48bbda2020-07-27 19:41:37 -0400231 << "Do you trust the information? Type in YES or NO" << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700232
233 std::string answer;
234 getline(std::cin, answer);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700235 boost::algorithm::to_lower(answer);
236 if (answer == "yes") {
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800237 std::cerr << "You answered YES: new CA " << profile->caPrefix.toUri() << " will be used" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700238 runProbe(*profile);
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700239 // client.getClientConf().save(std::string(SYSCONFDIR) + "/ndncert/client.conf");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700240 }
241 else {
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800242 std::cerr << "You answered NO: new CA " << profile->caPrefix.toUri() << " will not be used" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700243 exit(0);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700244 }
245}
246
247static void
tylerliufeabfdc2020-10-03 15:09:58 -0700248probeCb(const Data& reply, CaProfile profile)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700249{
tylerliub47dad72020-10-08 21:36:55 -0700250 std::vector<std::pair<Name, int>> names;
tylerliufeabfdc2020-10-03 15:09:58 -0700251 std::vector<Name> redirects;
tylerliu4140fe82021-01-27 15:45:44 -0800252 Request::onProbeResponse(reply, profile, names, redirects);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700253 size_t count = 0;
254 std::cerr << "\n***************************************\n"
255 << "Step " << nStep++
256 << ": You can either select one of the following names suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700257 for (const auto& name : names) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700258 std::cerr << "> Index: " << count++ << std::endl
tylerliub47dad72020-10-08 21:36:55 -0700259 << ">> Suggested name: " << name.first.toUri() << std::endl
260 << ">> Corresponding Max sufiix length: " << name.second << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700261 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700262 std::cerr << "\nOr choose another trusted CA suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700263 for (const auto& redirect : redirects) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700264 std::cerr << "> Index: " << count++ << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700265 << ">> Suggested CA: " << security::extractIdentityFromCertName(redirect.getPrefix(-1)) << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700266 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700267 std::cerr << "Please type in the index of your choice:" << std::endl;
268 size_t index = 0;
tylerliufeabfdc2020-10-03 15:09:58 -0700269 try {
270 std::string input;
271 getline(std::cin, input);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700272 index = std::stoul(input);
tylerliufeabfdc2020-10-03 15:09:58 -0700273 }
274 catch (const std::exception& e) {
275 std::cerr << "Your input is Invalid. Exit" << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800276 exit(1);
tylerliufeabfdc2020-10-03 15:09:58 -0700277 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700278 if (index >= names.size() + redirects.size()) {
tylerliufeabfdc2020-10-03 15:09:58 -0700279 std::cerr << "Your input is not an existing index. Exit" << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800280 exit(1);
tylerliufeabfdc2020-10-03 15:09:58 -0700281 }
282 if (index < names.size()) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700283 //names
tylerliud82cc5c2020-12-21 23:58:39 -0800284 auto selectedName = names[index].first;
285 std::cerr << "You selected name: " << selectedName.toUri() << std::endl;
286 std::cerr << "Enter Suffix if you would like one (Enter to skip): ";
287 try {
288 std::string input;
289 getline(std::cin, input);
290 auto inputName = Name(input);
291 if (!inputName.empty()) {
292 selectedName.append(inputName);
293 std::cerr << "You are applying name: " << selectedName.toUri() << std::endl;
294 }
295 }
296 catch (const std::exception& e) {
297 std::cerr << "Your input is Invalid. Exit" << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800298 exit(1);
tylerliud82cc5c2020-12-21 23:58:39 -0800299 }
300 runNew(profile, selectedName);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700301 }
302 else {
303 //redirects
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700304 auto redirectedCaFullName = redirects[index - names.size()];
tylerliua7bea662020-10-08 18:51:02 -0700305 auto redirectedCaName = security::extractIdentityFromCertName(redirectedCaFullName.getPrefix(-1));
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700306 std::cerr << "You selected to be redirected to CA: " << redirectedCaName.toUri() << std::endl;
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700307 face.expressInterest(
tylerliu4140fe82021-01-27 15:45:44 -0800308 *Request::genCaProfileDiscoveryInterest(redirectedCaName),
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500309 [&] (const auto&, const auto& data) {
tylerliu4140fe82021-01-27 15:45:44 -0800310 auto fetchingInterest = Request::genCaProfileInterestFromDiscoveryResponse(data);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700311 face.expressInterest(*fetchingInterest,
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500312 [=] (const auto&, const auto& data2) { infoCb(data2, redirectedCaFullName); },
313 [] (auto&&...) { onNackCb(); },
314 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700315 },
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500316 [] (auto&&...) { onNackCb(); },
317 [] (auto&&...) { timeoutCb(); });
tylerliufeabfdc2020-10-03 15:09:58 -0700318 }
319}
320
321static void
322selectCaProfile(std::string configFilePath)
323{
Zhiyi Zhanga16b7582020-10-29 18:59:46 -0700324 ProfileStorage profileStorage;
tylerliufeabfdc2020-10-03 15:09:58 -0700325 try {
Zhiyi Zhanga16b7582020-10-29 18:59:46 -0700326 profileStorage.load(configFilePath);
tylerliufeabfdc2020-10-03 15:09:58 -0700327 }
328 catch (const std::exception& e) {
329 std::cerr << "Cannot load the configuration file: " << e.what() << std::endl;
330 exit(1);
331 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700332 size_t count = 0;
333 std::cerr << "***************************************\n"
334 << "Step " << nStep++ << ": CA SELECTION" << std::endl;
Zhiyi Zhang84e11842020-11-19 20:03:23 -0800335 for (auto item : profileStorage.getKnownProfiles()) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700336 std::cerr << "> Index: " << count++ << std::endl
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800337 << ">> CA prefix:" << item.caPrefix << std::endl
338 << ">> Introduction: " << item.caInfo << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700339 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700340 std::cerr << "Please type in the CA's index that you want to apply or type in NONE if your expected CA is not in the list:\n";
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700341
Zhiyi Zhang36706832019-07-04 21:33:03 -0700342 std::string caIndexS, caIndexSLower;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700343 getline(std::cin, caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700344 caIndexSLower = caIndexS;
345 boost::algorithm::to_lower(caIndexSLower);
346 if (caIndexSLower == "none") {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700347 std::cerr << "\n***************************************\n"
348 << "Step " << nStep << ": ADD NEW CA\nPlease type in the CA's Name:" << std::endl;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700349 std::string expectedCAName;
350 getline(std::cin, expectedCAName);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700351 face.expressInterest(
tylerliu4140fe82021-01-27 15:45:44 -0800352 *Request::genCaProfileDiscoveryInterest(Name(expectedCAName)),
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500353 [&] (const auto&, const auto& data) {
tylerliu4140fe82021-01-27 15:45:44 -0800354 auto fetchingInterest = Request::genCaProfileInterestFromDiscoveryResponse(data);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700355 face.expressInterest(*fetchingInterest,
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500356 [] (const auto&, const auto& data2) { infoCb(data2, {}); },
357 [] (auto&&...) { onNackCb(); },
358 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700359 },
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500360 [] (auto&&...) { onNackCb(); },
361 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700362 }
363 else {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700364 size_t caIndex;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700365 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700366 caIndex = std::stoul(caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700367 }
368 catch (const std::exception& e) {
369 std::cerr << "Your input is neither NONE nor a valid index. Exit" << std::endl;
370 return;
371 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700372 if (caIndex >= count) {
Zhiyi Zhang36706832019-07-04 21:33:03 -0700373 std::cerr << "Your input is not an existing index. Exit" << std::endl;
374 return;
375 }
Zhiyi Zhang84e11842020-11-19 20:03:23 -0800376 auto itemIterator = profileStorage.getKnownProfiles().cbegin();
tylerliufeabfdc2020-10-03 15:09:58 -0700377 std::advance(itemIterator, caIndex);
378 auto targetCaItem = *itemIterator;
379 runProbe(targetCaItem);
380 }
381}
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700382
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700383static void
384runProbe(CaProfile profile)
tylerliufeabfdc2020-10-03 15:09:58 -0700385{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700386 std::cerr << "\n***************************************\n"
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700387 << "Step " << nStep++
388 << ": Do you know your identity name to be certified by CA "
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800389 << profile.caPrefix.toUri()
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700390 << " already? Type in YES or NO" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700391 bool validAnswer = false;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800392 size_t count = 0;
393 while (!validAnswer && count < 3) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700394 std::string answer;
395 getline(std::cin, answer);
396 boost::algorithm::to_lower(answer);
397 if (answer == "yes") {
398 validAnswer = true;
399 std::cerr << "You answered YES" << std::endl;
400 std::cerr << "\n***************************************\n"
401 << "Step " << nStep++
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700402 << ": Please type in the full identity name you want to get (with CA prefix "
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800403 << profile.caPrefix.toUri()
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700404 << "):" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700405 std::string identityNameStr;
406 getline(std::cin, identityNameStr);
407 runNew(profile, Name(identityNameStr));
tylerliufeabfdc2020-10-03 15:09:58 -0700408 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700409 else if (answer == "no") {
410 validAnswer = true;
411 std::cerr << "You answered NO" << std::endl;
412 std::cerr << "\n***************************************\n"
413 << "Step " << nStep++ << ": Please provide information for name assignment" << std::endl;
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800414 auto capturedParams = captureParams(profile.probeParameterKeys);
tylerliu4140fe82021-01-27 15:45:44 -0800415 face.expressInterest(*Request::genProbeInterest(profile, std::move(capturedParams)),
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500416 [profile] (const auto&, const auto& data) { probeCb(data, profile); },
417 [] (auto&&...) { onNackCb(); },
418 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700419 }
420 else {
421 std::cerr << "Invalid answer. Type in YES or NO" << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800422 count++;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700423 }
424 }
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800425 if (count == 3) {
426 std::cerr << "Invalid input for too many times, exit. " << std::endl;
427 exit(1);
428 }
tylerliufeabfdc2020-10-03 15:09:58 -0700429}
430
431static void
432runNew(CaProfile profile, Name identityName)
433{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700434 int validityPeriod = captureValidityPeriod();
435 auto now = time::system_clock::now();
436 std::cerr << "The validity period of your certificate will be: " << validityPeriod << " hours" << std::endl;
tylerliu4140fe82021-01-27 15:45:44 -0800437 requesterState = std::make_shared<Request>(keyChain, profile, RequestType::NEW);
438 auto interest = requesterState->genNewInterest(identityName, now, now + time::hours(validityPeriod));
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700439 if (interest != nullptr) {
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500440 face.expressInterest(*interest,
441 [] (const auto&, const auto& data) { newCb(data); },
442 [] (auto&&...) { onNackCb(); },
443 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700444 }
445 else {
446 std::cerr << "Cannot generate the Interest for NEW step. Exit" << std::endl;
447 }
tylerliufeabfdc2020-10-03 15:09:58 -0700448}
449
450static void
451runChallenge(const std::string& challengeType)
452{
tylerliu40226332020-11-11 15:37:16 -0800453 std::multimap<std::string, std::string> requirement;
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700454 try {
tylerliu4140fe82021-01-27 15:45:44 -0800455 requirement = requesterState->selectOrContinueChallenge(challengeType);
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700456 }
457 catch (const std::exception& e) {
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500458 std::cerr << "Error. Cannot successfully load the Challenge Module with error: " << e.what()
459 << "\nExit." << std::endl;
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700460 exit(1);
461 }
tylerliufeabfdc2020-10-03 15:09:58 -0700462 if (requirement.size() > 0) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700463 std::cerr << "\n***************************************\n"
464 << "Step " << nStep
465 << ": Please provide parameters used for Identity Verification Challenge" << std::endl;
466 captureParams(requirement);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700467 }
tylerliu4140fe82021-01-27 15:45:44 -0800468 face.expressInterest(*requesterState->genChallengeInterest(std::move(requirement)),
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500469 [] (const auto&, const auto& data) { challengeCb(data); },
470 [] (auto&&...) { onNackCb(); },
471 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700472}
473
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700474static void
475handleSignal(const boost::system::error_code& error, int signalNum)
476{
477 if (error) {
478 return;
479 }
480 const char* signalName = ::strsignal(signalNum);
481 std::cerr << "Exiting on signal ";
482 if (signalName == nullptr) {
483 std::cerr << signalNum;
484 }
485 else {
486 std::cerr << signalName;
487 }
488 std::cerr << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700489 if (requesterState) {
tylerliu4140fe82021-01-27 15:45:44 -0800490 requesterState->endSession();
tylerliufeabfdc2020-10-03 15:09:58 -0700491 }
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700492 face.getIoService().stop();
tylerliufeabfdc2020-10-03 15:09:58 -0700493 exit(1);
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700494}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800495
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500496static int
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800497main(int argc, char* argv[])
498{
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700499 boost::asio::signal_set terminateSignals(face.getIoService());
500 terminateSignals.add(SIGINT);
501 terminateSignals.add(SIGTERM);
502 terminateSignals.async_wait(handleSignal);
503
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800504 namespace po = boost::program_options;
Zhiyi Zhang840afd92020-10-21 13:24:08 -0700505 std::string configFilePath = std::string(NDNCERT_SYSCONFDIR) + "/ndncert/client.conf";
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500506 po::options_description description("Usage: ndncert-client [-h] [-c FILE]\n");
507 description.add_options()
508 ("help,h", "produce help message")
509 ("config-file,c", po::value<std::string>(&configFilePath), "configuration file name")
510 ;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800511 po::positional_options_description p;
512
513 po::variables_map vm;
514 try {
515 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
516 po::notify(vm);
517 }
518 catch (const std::exception& e) {
519 std::cerr << "ERROR: " << e.what() << std::endl;
520 return 1;
521 }
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500522
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800523 if (vm.count("help") != 0) {
524 std::cerr << description << std::endl;
525 return 0;
526 }
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500527
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700528 selectCaProfile(configFilePath);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800529 face.processEvents();
530 return 0;
531}
532
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -0700533} // namespace requester
Zhiyi Zhange4891b72020-10-10 15:11:57 -0700534} // namespace ndncert
535} // namespace ndn
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800536
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700537int
538main(int argc, char* argv[])
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800539{
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -0700540 return ndn::ndncert::requester::main(argc, argv);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800541}