blob: 30c74542102e752b7395b1c9e2862001bd6c261d [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
Davide Pesavento0dc02012021-11-23 22:55:03 -050023#include <ndn-cxx/face.hpp>
24#include <ndn-cxx/security/key-chain.hpp>
Zhiyi Zhang90c75782020-10-06 15:04:03 -070025#include <ndn-cxx/security/verification-helpers.hpp>
Davide Pesaventoe5b43692021-11-15 22:05:03 -050026
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070027#include <boost/asio.hpp>
Davide Pesaventob48bbda2020-07-27 19:41:37 -040028#include <boost/program_options/options_description.hpp>
29#include <boost/program_options/parsers.hpp>
30#include <boost/program_options/variables_map.hpp>
Davide Pesaventoe5b43692021-11-15 22:05:03 -050031
Zhiyi Zhang48f23782020-09-28 12:11:24 -070032#include <iostream>
Zhiyi Zhang48f23782020-09-28 12:11:24 -070033
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080034namespace ndncert {
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -070035namespace requester {
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080036
Zhiyi Zhang48f23782020-09-28 12:11:24 -070037static void
tylerliufeabfdc2020-10-03 15:09:58 -070038selectCaProfile(std::string configFilePath);
Davide Pesaventoe5b43692021-11-15 22:05:03 -050039
tylerliufeabfdc2020-10-03 15:09:58 -070040static void
41runProbe(CaProfile profile);
Davide Pesaventoe5b43692021-11-15 22:05:03 -050042
tylerliufeabfdc2020-10-03 15:09:58 -070043static void
44runNew(CaProfile profile, Name identityName);
Davide Pesaventoe5b43692021-11-15 22:05:03 -050045
tylerliufeabfdc2020-10-03 15:09:58 -070046static void
47runChallenge(const std::string& challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070048
Davide Pesaventoe5b43692021-11-15 22:05:03 -050049static size_t nStep = 1;
Davide Pesavento0dc02012021-11-23 22:55:03 -050050static ndn::Face face;
51static ndn::KeyChain keyChain;
52static std::shared_ptr<Request> requesterState;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080053
Zhiyi Zhang46049832020-09-28 17:08:12 -070054static void
tylerliu40226332020-11-11 15:37:16 -080055captureParams(std::multimap<std::string, std::string>& requirement)
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080056{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070057 std::list<std::string> results;
Zhiyi Zhang46049832020-09-28 17:08:12 -070058 for (auto& item : requirement) {
59 std::cerr << std::get<1>(item) << std::endl;
60 std::string captured;
61 getline(std::cin, captured);
62 std::get<1>(item) = captured;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080063 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070064 std::cerr << "Got it. This is what you've provided:" << std::endl;
Zhiyi Zhang46049832020-09-28 17:08:12 -070065 for (const auto& item : requirement) {
66 std::cerr << std::get<0>(item) << " : " << std::get<1>(item) << std::endl;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080067 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070068}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080069
tylerliu40226332020-11-11 15:37:16 -080070static std::multimap<std::string, std::string>
Zhiyi Zhang2de4ea32020-12-13 17:45:25 -080071captureParams(const std::vector<std::string>& requirement)
Zhiyi Zhang547c8512019-06-18 23:46:14 -070072{
tylerliu40226332020-11-11 15:37:16 -080073 std::multimap<std::string, std::string> results;
tylerliufeabfdc2020-10-03 15:09:58 -070074 for (const auto& r : requirement) {
tylerliu40226332020-11-11 15:37:16 -080075 results.emplace(r, "Please input: " + r);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070076 }
tylerliufeabfdc2020-10-03 15:09:58 -070077 captureParams(results);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070078 return results;
79}
80
tylerliufeabfdc2020-10-03 15:09:58 -070081static int
Zhiyi Zhang36706832019-07-04 21:33:03 -070082captureValidityPeriod()
83{
Zhiyi Zhang837406d2020-10-05 22:01:31 -070084 std::cerr << "\n***************************************\n"
85 << "Step " << nStep++
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070086 << ": Please type in your expected validity period of your certificate."
87 << " Type the number of hours (168 for week, 730 for month, 8760 for year)."
88 << " The CA may reject your application if your expected period is too long." << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -080089 size_t count = 0;
90 while (true && count < 3) {
tylerliufeabfdc2020-10-03 15:09:58 -070091 std::string periodStr = "";
92 getline(std::cin, periodStr);
93 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -070094 return std::stoul(periodStr);
tylerliufeabfdc2020-10-03 15:09:58 -070095 }
Davide Pesavento0dc02012021-11-23 22:55:03 -050096 catch (const std::exception&) {
tylerliufeabfdc2020-10-03 15:09:58 -070097 std::cerr << "Your input is invalid. Try again: " << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -080098 count++;
tylerliufeabfdc2020-10-03 15:09:58 -070099 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700100 }
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800101 std::cerr << "Invalid input for too many times, exit. " << std::endl;
102 exit(1);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700103}
104
105static void
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700106onNackCb()
107{
108 std::cerr << "Got NACK\n";
109}
110
111static void
112timeoutCb()
113{
114 std::cerr << "Interest sent time out\n";
115}
116
117static void
swa770cf1d8f72020-04-21 23:12:39 -0700118certFetchCb(const Data& reply)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700119{
tylerliu4140fe82021-01-27 15:45:44 -0800120 auto item = Request::onCertFetchResponse(reply);
tylerliufeabfdc2020-10-03 15:09:58 -0700121 if (item) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700122 keyChain.addCertificate(keyChain.getPib().getIdentity(item->getIdentity()).getKey(item->getKeyName()), *item);
tylerliufeabfdc2020-10-03 15:09:58 -0700123 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700124 std::cerr << "\n***************************************\n"
125 << "Step " << nStep++
126 << ": DONE\nCertificate with Name: " << reply.getName().toUri()
127 << "has already been installed to your local keychain" << std::endl
128 << "Exit now";
129 face.getIoService().stop();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700130}
131
132static void
133challengeCb(const Data& reply)
134{
tylerliufeabfdc2020-10-03 15:09:58 -0700135 try {
tylerliu4140fe82021-01-27 15:45:44 -0800136 requesterState->onChallengeResponse(reply);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700137 }
138 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700139 std::cerr << "Error when decoding challenge step: " << e.what() << std::endl;
140 exit(1);
141 }
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800142 if (requesterState->m_status == Status::SUCCESS) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700143 std::cerr << "Certificate has already been issued, downloading certificate..." << std::endl;
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500144 face.expressInterest(*requesterState->genCertFetchInterest(),
145 [] (const auto&, const auto& data) { certFetchCb(data); },
146 [] (auto&&...) { onNackCb(); },
147 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700148 return;
149 }
Zhiyi Zhang6499edd2021-02-17 22:37:21 -0800150 runChallenge(requesterState->m_challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700151}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800152
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700153static void
154newCb(const Data& reply)
155{
tylerliufeabfdc2020-10-03 15:09:58 -0700156 std::list<std::string> challengeList;
157 try {
tylerliu4140fe82021-01-27 15:45:44 -0800158 challengeList = requesterState->onNewRenewRevokeResponse(reply);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700159 }
160 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700161 std::cerr << "Error on decoding NEW step reply because: " << e.what() << std::endl;
162 exit(1);
163 }
164
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700165 size_t challengeIndex = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700166 if (challengeList.size() < 1) {
167 std::cerr << "There is no available challenge provided by the CA. Exit" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700168 exit(1);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800169 }
Zhiyi Zhang48f546f2020-12-24 17:31:02 -0800170 else if (challengeList.size() >= 1) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700171 std::cerr << "\n***************************************\n"
172 << "Step " << nStep++
173 << ": CHALLENGE SELECTION" << std::endl;
174 size_t count = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700175 std::string choice = "";
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700176 for (auto item : challengeList) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700177 std::cerr << "> Index: " << count++ << std::endl
178 << ">> Challenge:" << item << std::endl;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700179 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700180 std::cerr << "Please type in the challenge index that you want to perform:" << std::endl;
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800181 size_t inputCount = 0;
182 while (inputCount < 3) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700183 getline(std::cin, choice);
184 try {
185 challengeIndex = std::stoul(choice);
186 }
Davide Pesavento0dc02012021-11-23 22:55:03 -0500187 catch (const std::exception&) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700188 std::cerr << "Your input is not valid. Try again:" << std::endl;
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800189 inputCount++;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700190 continue;
191 }
192 if (challengeIndex >= count) {
193 std::cerr << "Your input index is out of range. Try again:" << std::endl;
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800194 inputCount++;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700195 continue;
196 }
197 break;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700198 }
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800199 if (inputCount == 3) {
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800200 std::cerr << "Invalid input for too many times, exit. " << std::endl;
201 exit(1);
202 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700203 }
204 auto it = challengeList.begin();
205 std::advance(it, challengeIndex);
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700206 std::cerr << "The challenge has been selected: " << *it << std::endl;
207 runChallenge(*it);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700208}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800209
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700210static void
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500211infoCb(const Data& reply, const Name& certFullName)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700212{
Zhiyi Zhang997669a2020-10-28 21:15:40 -0700213 optional<CaProfile> profile;
tylerliufeabfdc2020-10-03 15:09:58 -0700214 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700215 if (certFullName.empty()) {
tylerliu4140fe82021-01-27 15:45:44 -0800216 profile = Request::onCaProfileResponse(reply);
tylerliufeabfdc2020-10-03 15:09:58 -0700217 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700218 else {
tylerliu4140fe82021-01-27 15:45:44 -0800219 profile = Request::onCaProfileResponseAfterRedirection(reply, certFullName);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700220 }
221 }
222 catch (const std::exception& e) {
223 std::cerr << "The fetched CA information cannot be used because: " << e.what() << std::endl;
224 return;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700225 }
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700226 std::cerr << "\n***************************************\n"
227 << "Step " << nStep++
228 << ": Will use a new trust anchor, please double check the identity info:" << std::endl
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800229 << "> New CA name: " << profile->caPrefix.toUri() << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700230 << "> This trust anchor information is signed by: " << reply.getSignatureInfo().getKeyLocator() << std::endl
Zhiyi Zhangec4aa3a2021-01-08 14:26:37 -0800231 << "> The certificate: " << *profile->cert << std::endl
Davide Pesaventob48bbda2020-07-27 19:41:37 -0400232 << "Do you trust the information? Type in YES or NO" << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700233
234 std::string answer;
235 getline(std::cin, answer);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700236 boost::algorithm::to_lower(answer);
237 if (answer == "yes") {
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800238 std::cerr << "You answered YES: new CA " << profile->caPrefix.toUri() << " will be used" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700239 runProbe(*profile);
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700240 // client.getClientConf().save(std::string(SYSCONFDIR) + "/ndncert/client.conf");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700241 }
242 else {
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800243 std::cerr << "You answered NO: new CA " << profile->caPrefix.toUri() << " will not be used" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700244 exit(0);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700245 }
246}
247
248static void
tylerliufeabfdc2020-10-03 15:09:58 -0700249probeCb(const Data& reply, CaProfile profile)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700250{
tylerliub47dad72020-10-08 21:36:55 -0700251 std::vector<std::pair<Name, int>> names;
tylerliufeabfdc2020-10-03 15:09:58 -0700252 std::vector<Name> redirects;
tylerliu4140fe82021-01-27 15:45:44 -0800253 Request::onProbeResponse(reply, profile, names, redirects);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700254 size_t count = 0;
255 std::cerr << "\n***************************************\n"
256 << "Step " << nStep++
257 << ": You can either select one of the following names suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700258 for (const auto& name : names) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700259 std::cerr << "> Index: " << count++ << std::endl
tylerliub47dad72020-10-08 21:36:55 -0700260 << ">> Suggested name: " << name.first.toUri() << std::endl
261 << ">> Corresponding Max sufiix length: " << name.second << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700262 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700263 std::cerr << "\nOr choose another trusted CA suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700264 for (const auto& redirect : redirects) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700265 std::cerr << "> Index: " << count++ << std::endl
Davide Pesavento0dc02012021-11-23 22:55:03 -0500266 << ">> Suggested CA: " << ndn::security::extractIdentityFromCertName(redirect.getPrefix(-1))
267 << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700268 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700269 std::cerr << "Please type in the index of your choice:" << std::endl;
270 size_t index = 0;
tylerliufeabfdc2020-10-03 15:09:58 -0700271 try {
272 std::string input;
273 getline(std::cin, input);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700274 index = std::stoul(input);
tylerliufeabfdc2020-10-03 15:09:58 -0700275 }
Davide Pesavento0dc02012021-11-23 22:55:03 -0500276 catch (const std::exception&) {
tylerliufeabfdc2020-10-03 15:09:58 -0700277 std::cerr << "Your input is Invalid. Exit" << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800278 exit(1);
tylerliufeabfdc2020-10-03 15:09:58 -0700279 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700280 if (index >= names.size() + redirects.size()) {
tylerliufeabfdc2020-10-03 15:09:58 -0700281 std::cerr << "Your input is not an existing index. Exit" << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800282 exit(1);
tylerliufeabfdc2020-10-03 15:09:58 -0700283 }
284 if (index < names.size()) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700285 //names
tylerliud82cc5c2020-12-21 23:58:39 -0800286 auto selectedName = names[index].first;
287 std::cerr << "You selected name: " << selectedName.toUri() << std::endl;
288 std::cerr << "Enter Suffix if you would like one (Enter to skip): ";
289 try {
290 std::string input;
291 getline(std::cin, input);
292 auto inputName = Name(input);
293 if (!inputName.empty()) {
294 selectedName.append(inputName);
295 std::cerr << "You are applying name: " << selectedName.toUri() << std::endl;
296 }
297 }
Davide Pesavento0dc02012021-11-23 22:55:03 -0500298 catch (const std::exception&) {
tylerliud82cc5c2020-12-21 23:58:39 -0800299 std::cerr << "Your input is Invalid. Exit" << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800300 exit(1);
tylerliud82cc5c2020-12-21 23:58:39 -0800301 }
302 runNew(profile, selectedName);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700303 }
304 else {
305 //redirects
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700306 auto redirectedCaFullName = redirects[index - names.size()];
Davide Pesavento0dc02012021-11-23 22:55:03 -0500307 auto redirectedCaName = ndn::security::extractIdentityFromCertName(redirectedCaFullName.getPrefix(-1));
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700308 std::cerr << "You selected to be redirected to CA: " << redirectedCaName.toUri() << std::endl;
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700309 face.expressInterest(
tylerliu4140fe82021-01-27 15:45:44 -0800310 *Request::genCaProfileDiscoveryInterest(redirectedCaName),
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500311 [&] (const auto&, const auto& data) {
tylerliu4140fe82021-01-27 15:45:44 -0800312 auto fetchingInterest = Request::genCaProfileInterestFromDiscoveryResponse(data);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700313 face.expressInterest(*fetchingInterest,
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500314 [=] (const auto&, const auto& data2) { infoCb(data2, redirectedCaFullName); },
315 [] (auto&&...) { onNackCb(); },
316 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700317 },
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500318 [] (auto&&...) { onNackCb(); },
319 [] (auto&&...) { timeoutCb(); });
tylerliufeabfdc2020-10-03 15:09:58 -0700320 }
321}
322
323static void
324selectCaProfile(std::string configFilePath)
325{
Zhiyi Zhanga16b7582020-10-29 18:59:46 -0700326 ProfileStorage profileStorage;
tylerliufeabfdc2020-10-03 15:09:58 -0700327 try {
Zhiyi Zhanga16b7582020-10-29 18:59:46 -0700328 profileStorage.load(configFilePath);
tylerliufeabfdc2020-10-03 15:09:58 -0700329 }
330 catch (const std::exception& e) {
331 std::cerr << "Cannot load the configuration file: " << e.what() << std::endl;
332 exit(1);
333 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700334 size_t count = 0;
335 std::cerr << "***************************************\n"
336 << "Step " << nStep++ << ": CA SELECTION" << std::endl;
Zhiyi Zhang84e11842020-11-19 20:03:23 -0800337 for (auto item : profileStorage.getKnownProfiles()) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700338 std::cerr << "> Index: " << count++ << std::endl
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800339 << ">> CA prefix:" << item.caPrefix << std::endl
340 << ">> Introduction: " << item.caInfo << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700341 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700342 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 -0700343
Zhiyi Zhang36706832019-07-04 21:33:03 -0700344 std::string caIndexS, caIndexSLower;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700345 getline(std::cin, caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700346 caIndexSLower = caIndexS;
347 boost::algorithm::to_lower(caIndexSLower);
348 if (caIndexSLower == "none") {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700349 std::cerr << "\n***************************************\n"
350 << "Step " << nStep << ": ADD NEW CA\nPlease type in the CA's Name:" << std::endl;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700351 std::string expectedCAName;
352 getline(std::cin, expectedCAName);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700353 face.expressInterest(
tylerliu4140fe82021-01-27 15:45:44 -0800354 *Request::genCaProfileDiscoveryInterest(Name(expectedCAName)),
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500355 [&] (const auto&, const auto& data) {
tylerliu4140fe82021-01-27 15:45:44 -0800356 auto fetchingInterest = Request::genCaProfileInterestFromDiscoveryResponse(data);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700357 face.expressInterest(*fetchingInterest,
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500358 [] (const auto&, const auto& data2) { infoCb(data2, {}); },
359 [] (auto&&...) { onNackCb(); },
360 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700361 },
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500362 [] (auto&&...) { onNackCb(); },
363 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700364 }
365 else {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700366 size_t caIndex;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700367 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700368 caIndex = std::stoul(caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700369 }
Davide Pesavento0dc02012021-11-23 22:55:03 -0500370 catch (const std::exception&) {
Zhiyi Zhang36706832019-07-04 21:33:03 -0700371 std::cerr << "Your input is neither NONE nor a valid index. Exit" << std::endl;
372 return;
373 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700374 if (caIndex >= count) {
Zhiyi Zhang36706832019-07-04 21:33:03 -0700375 std::cerr << "Your input is not an existing index. Exit" << std::endl;
376 return;
377 }
Zhiyi Zhang84e11842020-11-19 20:03:23 -0800378 auto itemIterator = profileStorage.getKnownProfiles().cbegin();
tylerliufeabfdc2020-10-03 15:09:58 -0700379 std::advance(itemIterator, caIndex);
380 auto targetCaItem = *itemIterator;
381 runProbe(targetCaItem);
382 }
383}
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700384
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700385static void
386runProbe(CaProfile profile)
tylerliufeabfdc2020-10-03 15:09:58 -0700387{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700388 std::cerr << "\n***************************************\n"
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700389 << "Step " << nStep++
390 << ": Do you know your identity name to be certified by CA "
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800391 << profile.caPrefix.toUri()
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700392 << " already? Type in YES or NO" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700393 bool validAnswer = false;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800394 size_t count = 0;
395 while (!validAnswer && count < 3) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700396 std::string answer;
397 getline(std::cin, answer);
398 boost::algorithm::to_lower(answer);
399 if (answer == "yes") {
400 validAnswer = true;
401 std::cerr << "You answered YES" << std::endl;
402 std::cerr << "\n***************************************\n"
403 << "Step " << nStep++
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700404 << ": Please type in the full identity name you want to get (with CA prefix "
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800405 << profile.caPrefix.toUri()
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700406 << "):" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700407 std::string identityNameStr;
408 getline(std::cin, identityNameStr);
409 runNew(profile, Name(identityNameStr));
tylerliufeabfdc2020-10-03 15:09:58 -0700410 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700411 else if (answer == "no") {
412 validAnswer = true;
413 std::cerr << "You answered NO" << std::endl;
414 std::cerr << "\n***************************************\n"
415 << "Step " << nStep++ << ": Please provide information for name assignment" << std::endl;
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800416 auto capturedParams = captureParams(profile.probeParameterKeys);
tylerliu4140fe82021-01-27 15:45:44 -0800417 face.expressInterest(*Request::genProbeInterest(profile, std::move(capturedParams)),
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500418 [profile] (const auto&, const auto& data) { probeCb(data, profile); },
419 [] (auto&&...) { onNackCb(); },
420 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700421 }
422 else {
423 std::cerr << "Invalid answer. Type in YES or NO" << std::endl;
Zhiyi Zhang87ded732021-01-08 14:05:24 -0800424 count++;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700425 }
426 }
Zhiyi Zhang17720f22021-01-08 14:12:56 -0800427 if (count == 3) {
428 std::cerr << "Invalid input for too many times, exit. " << std::endl;
429 exit(1);
430 }
tylerliufeabfdc2020-10-03 15:09:58 -0700431}
432
433static void
434runNew(CaProfile profile, Name identityName)
435{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700436 int validityPeriod = captureValidityPeriod();
437 auto now = time::system_clock::now();
438 std::cerr << "The validity period of your certificate will be: " << validityPeriod << " hours" << std::endl;
tylerliu4140fe82021-01-27 15:45:44 -0800439 requesterState = std::make_shared<Request>(keyChain, profile, RequestType::NEW);
440 auto interest = requesterState->genNewInterest(identityName, now, now + time::hours(validityPeriod));
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700441 if (interest != nullptr) {
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500442 face.expressInterest(*interest,
443 [] (const auto&, const auto& data) { newCb(data); },
444 [] (auto&&...) { onNackCb(); },
445 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700446 }
447 else {
448 std::cerr << "Cannot generate the Interest for NEW step. Exit" << std::endl;
449 }
tylerliufeabfdc2020-10-03 15:09:58 -0700450}
451
452static void
453runChallenge(const std::string& challengeType)
454{
tylerliu40226332020-11-11 15:37:16 -0800455 std::multimap<std::string, std::string> requirement;
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700456 try {
tylerliu4140fe82021-01-27 15:45:44 -0800457 requirement = requesterState->selectOrContinueChallenge(challengeType);
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700458 }
459 catch (const std::exception& e) {
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500460 std::cerr << "Error. Cannot successfully load the Challenge Module with error: " << e.what()
461 << "\nExit." << std::endl;
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700462 exit(1);
463 }
tylerliufeabfdc2020-10-03 15:09:58 -0700464 if (requirement.size() > 0) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700465 std::cerr << "\n***************************************\n"
466 << "Step " << nStep
467 << ": Please provide parameters used for Identity Verification Challenge" << std::endl;
468 captureParams(requirement);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700469 }
tylerliu4140fe82021-01-27 15:45:44 -0800470 face.expressInterest(*requesterState->genChallengeInterest(std::move(requirement)),
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500471 [] (const auto&, const auto& data) { challengeCb(data); },
472 [] (auto&&...) { onNackCb(); },
473 [] (auto&&...) { timeoutCb(); });
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700474}
475
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700476static void
477handleSignal(const boost::system::error_code& error, int signalNum)
478{
479 if (error) {
480 return;
481 }
482 const char* signalName = ::strsignal(signalNum);
483 std::cerr << "Exiting on signal ";
484 if (signalName == nullptr) {
485 std::cerr << signalNum;
486 }
487 else {
488 std::cerr << signalName;
489 }
490 std::cerr << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700491 if (requesterState) {
tylerliu4140fe82021-01-27 15:45:44 -0800492 requesterState->endSession();
tylerliufeabfdc2020-10-03 15:09:58 -0700493 }
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700494 face.getIoService().stop();
tylerliufeabfdc2020-10-03 15:09:58 -0700495 exit(1);
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700496}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800497
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500498static int
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800499main(int argc, char* argv[])
500{
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700501 boost::asio::signal_set terminateSignals(face.getIoService());
502 terminateSignals.add(SIGINT);
503 terminateSignals.add(SIGTERM);
504 terminateSignals.async_wait(handleSignal);
505
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800506 namespace po = boost::program_options;
Zhiyi Zhang840afd92020-10-21 13:24:08 -0700507 std::string configFilePath = std::string(NDNCERT_SYSCONFDIR) + "/ndncert/client.conf";
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500508 po::options_description description("Usage: ndncert-client [-h] [-c FILE]\n");
509 description.add_options()
510 ("help,h", "produce help message")
511 ("config-file,c", po::value<std::string>(&configFilePath), "configuration file name")
512 ;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800513 po::positional_options_description p;
514
515 po::variables_map vm;
516 try {
517 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
518 po::notify(vm);
519 }
520 catch (const std::exception& e) {
521 std::cerr << "ERROR: " << e.what() << std::endl;
522 return 1;
523 }
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500524
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800525 if (vm.count("help") != 0) {
526 std::cerr << description << std::endl;
527 return 0;
528 }
Davide Pesaventoe5b43692021-11-15 22:05:03 -0500529
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700530 selectCaProfile(configFilePath);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800531 face.processEvents();
532 return 0;
533}
534
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -0700535} // namespace requester
Zhiyi Zhange4891b72020-10-10 15:11:57 -0700536} // namespace ndncert
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800537
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700538int
539main(int argc, char* argv[])
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800540{
Davide Pesavento0dc02012021-11-23 22:55:03 -0500541 return ndncert::requester::main(argc, argv);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800542}