blob: 24028332ac3454335add2d90e7aa6b8e6f79cab4 [file] [log] [blame]
Zhiyi Zhang08e0e982017-03-01 10:10:42 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
swa77020643ac2020-03-26 02:24:45 -07002/**
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -07003 * Copyright (c) 2017-2020, 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
Zhiyi Zhang837406d2020-10-05 22:01:31 -070021#include "requester.hpp"
Zhiyi Zhang90c75782020-10-06 15:04:03 -070022#include <ndn-cxx/security/verification-helpers.hpp>
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070023#include <boost/asio.hpp>
Davide Pesaventob48bbda2020-07-27 19:41:37 -040024#include <boost/program_options/options_description.hpp>
25#include <boost/program_options/parsers.hpp>
26#include <boost/program_options/variables_map.hpp>
Zhiyi Zhang48f23782020-09-28 12:11:24 -070027#include <iostream>
Zhiyi Zhang48f23782020-09-28 12:11:24 -070028#include <string>
29
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080030namespace ndn {
31namespace ndncert {
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -070032namespace requester {
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080033
Zhiyi Zhang48f23782020-09-28 12:11:24 -070034static void
tylerliufeabfdc2020-10-03 15:09:58 -070035selectCaProfile(std::string configFilePath);
36static void
37runProbe(CaProfile profile);
38static void
39runNew(CaProfile profile, Name identityName);
40static void
41runChallenge(const std::string& challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070042
Zhiyi Zhang837406d2020-10-05 22:01:31 -070043size_t nStep = 1;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070044Face face;
tylerliua7bea662020-10-08 18:51:02 -070045security::KeyChain keyChain;
tylerliubb630362020-11-10 11:31:35 -080046shared_ptr<RequestState> requesterState = nullptr;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080047
Zhiyi Zhang46049832020-09-28 17:08:12 -070048static void
tylerliu40226332020-11-11 15:37:16 -080049captureParams(std::multimap<std::string, std::string>& requirement)
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080050{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070051 std::list<std::string> results;
Zhiyi Zhang46049832020-09-28 17:08:12 -070052 for (auto& item : requirement) {
53 std::cerr << std::get<1>(item) << std::endl;
54 std::string captured;
55 getline(std::cin, captured);
56 std::get<1>(item) = captured;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080057 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070058 std::cerr << "Got it. This is what you've provided:" << std::endl;
Zhiyi Zhang46049832020-09-28 17:08:12 -070059 for (const auto& item : requirement) {
60 std::cerr << std::get<0>(item) << " : " << std::get<1>(item) << std::endl;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080061 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070062}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080063
tylerliu40226332020-11-11 15:37:16 -080064static std::multimap<std::string, std::string>
Zhiyi Zhang2de4ea32020-12-13 17:45:25 -080065captureParams(const std::vector<std::string>& requirement)
Zhiyi Zhang547c8512019-06-18 23:46:14 -070066{
tylerliu40226332020-11-11 15:37:16 -080067 std::multimap<std::string, std::string> results;
tylerliufeabfdc2020-10-03 15:09:58 -070068 for (const auto& r : requirement) {
tylerliu40226332020-11-11 15:37:16 -080069 results.emplace(r, "Please input: " + r);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070070 }
tylerliufeabfdc2020-10-03 15:09:58 -070071 captureParams(results);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070072 return results;
73}
74
tylerliufeabfdc2020-10-03 15:09:58 -070075static int
Zhiyi Zhang36706832019-07-04 21:33:03 -070076captureValidityPeriod()
77{
Zhiyi Zhang837406d2020-10-05 22:01:31 -070078 std::cerr << "\n***************************************\n"
79 << "Step " << nStep++
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070080 << ": Please type in your expected validity period of your certificate."
81 << " Type the number of hours (168 for week, 730 for month, 8760 for year)."
82 << " The CA may reject your application if your expected period is too long." << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -070083 while (true) {
84 std::string periodStr = "";
85 getline(std::cin, periodStr);
86 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -070087 return std::stoul(periodStr);
tylerliufeabfdc2020-10-03 15:09:58 -070088 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -070089 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -070090 std::cerr << "Your input is invalid. Try again: " << std::endl;
91 }
Zhiyi Zhang36706832019-07-04 21:33:03 -070092 }
93}
94
95static void
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070096onNackCb()
97{
98 std::cerr << "Got NACK\n";
99}
100
101static void
102timeoutCb()
103{
104 std::cerr << "Interest sent time out\n";
105}
106
107static void
swa770cf1d8f72020-04-21 23:12:39 -0700108certFetchCb(const Data& reply)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700109{
tylerliufeabfdc2020-10-03 15:09:58 -0700110 auto item = Requester::onCertFetchResponse(reply);
111 if (item) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700112 keyChain.addCertificate(keyChain.getPib().getIdentity(item->getIdentity()).getKey(item->getKeyName()), *item);
tylerliufeabfdc2020-10-03 15:09:58 -0700113 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700114 std::cerr << "\n***************************************\n"
115 << "Step " << nStep++
116 << ": DONE\nCertificate with Name: " << reply.getName().toUri()
117 << "has already been installed to your local keychain" << std::endl
118 << "Exit now";
119 face.getIoService().stop();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700120}
121
122static void
123challengeCb(const Data& reply)
124{
tylerliufeabfdc2020-10-03 15:09:58 -0700125 try {
126 Requester::onChallengeResponse(*requesterState, reply);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700127 }
128 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700129 std::cerr << "Error when decoding challenge step: " << e.what() << std::endl;
130 exit(1);
131 }
tylerliuf2e6bb52020-12-13 13:23:05 -0800132 if (requesterState->status == Status::SUCCESS) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700133 std::cerr << "Certificate has already been issued, downloading certificate..." << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700134 face.expressInterest(*Requester::genCertFetchInterest(*requesterState), bind(&certFetchCb, _2),
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700135 bind(&onNackCb), bind(&timeoutCb));
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700136 return;
137 }
tylerliuf2e6bb52020-12-13 13:23:05 -0800138 runChallenge(requesterState->challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700139}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800140
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700141static void
142newCb(const Data& reply)
143{
tylerliufeabfdc2020-10-03 15:09:58 -0700144 std::list<std::string> challengeList;
145 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700146 challengeList = Requester::onNewRenewRevokeResponse(*requesterState, reply);
147 }
148 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700149 std::cerr << "Error on decoding NEW step reply because: " << e.what() << std::endl;
150 exit(1);
151 }
152
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700153 size_t challengeIndex = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700154 if (challengeList.size() < 1) {
155 std::cerr << "There is no available challenge provided by the CA. Exit" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700156 exit(1);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800157 }
Zhiyi Zhang48f546f2020-12-24 17:31:02 -0800158 else if (challengeList.size() >= 1) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700159 std::cerr << "\n***************************************\n"
160 << "Step " << nStep++
161 << ": CHALLENGE SELECTION" << std::endl;
162 size_t count = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700163 std::string choice = "";
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700164 for (auto item : challengeList) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700165 std::cerr << "> Index: " << count++ << std::endl
166 << ">> Challenge:" << item << std::endl;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700167 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700168 std::cerr << "Please type in the challenge index that you want to perform:" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700169 while (true) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700170 getline(std::cin, choice);
171 try {
172 challengeIndex = std::stoul(choice);
173 }
174 catch (const std::exception& e) {
175 std::cerr << "Your input is not valid. Try again:" << std::endl;
176 continue;
177 }
178 if (challengeIndex >= count) {
179 std::cerr << "Your input index is out of range. Try again:" << std::endl;
180 continue;
181 }
182 break;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700183 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700184 }
185 auto it = challengeList.begin();
186 std::advance(it, challengeIndex);
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700187 std::cerr << "The challenge has been selected: " << *it << std::endl;
188 runChallenge(*it);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700189}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800190
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700191static void
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700192InfoCb(const Data& reply, const Name& certFullName)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700193{
Zhiyi Zhang997669a2020-10-28 21:15:40 -0700194 optional<CaProfile> profile;
tylerliufeabfdc2020-10-03 15:09:58 -0700195 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700196 if (certFullName.empty()) {
197 profile = Requester::onCaProfileResponse(reply);
tylerliufeabfdc2020-10-03 15:09:58 -0700198 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700199 else {
200 profile = Requester::onCaProfileResponseAfterRedirection(reply, certFullName);
201 }
202 }
203 catch (const std::exception& e) {
204 std::cerr << "The fetched CA information cannot be used because: " << e.what() << std::endl;
205 return;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700206 }
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700207 std::cerr << "\n***************************************\n"
208 << "Step " << nStep++
209 << ": Will use a new trust anchor, please double check the identity info:" << std::endl
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800210 << "> New CA name: " << profile->caPrefix.toUri() << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700211 << "> This trust anchor information is signed by: " << reply.getSignatureInfo().getKeyLocator() << std::endl
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800212 << "> The certificate: " << profile->cert << std::endl
Davide Pesaventob48bbda2020-07-27 19:41:37 -0400213 << "Do you trust the information? Type in YES or NO" << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700214
215 std::string answer;
216 getline(std::cin, answer);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700217 boost::algorithm::to_lower(answer);
218 if (answer == "yes") {
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800219 std::cerr << "You answered YES: new CA " << profile->caPrefix.toUri() << " will be used" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700220 runProbe(*profile);
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700221 // client.getClientConf().save(std::string(SYSCONFDIR) + "/ndncert/client.conf");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700222 }
223 else {
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800224 std::cerr << "You answered NO: new CA " << profile->caPrefix.toUri() << " will not be used" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700225 exit(0);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700226 }
227}
228
229static void
tylerliufeabfdc2020-10-03 15:09:58 -0700230probeCb(const Data& reply, CaProfile profile)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700231{
tylerliub47dad72020-10-08 21:36:55 -0700232 std::vector<std::pair<Name, int>> names;
tylerliufeabfdc2020-10-03 15:09:58 -0700233 std::vector<Name> redirects;
234 Requester::onProbeResponse(reply, profile, names, redirects);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700235 size_t count = 0;
236 std::cerr << "\n***************************************\n"
237 << "Step " << nStep++
238 << ": You can either select one of the following names suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700239 for (const auto& name : names) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700240 std::cerr << "> Index: " << count++ << std::endl
tylerliub47dad72020-10-08 21:36:55 -0700241 << ">> Suggested name: " << name.first.toUri() << std::endl
242 << ">> Corresponding Max sufiix length: " << name.second << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700243 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700244 std::cerr << "\nOr choose another trusted CA suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700245 for (const auto& redirect : redirects) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700246 std::cerr << "> Index: " << count++ << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700247 << ">> Suggested CA: " << security::extractIdentityFromCertName(redirect.getPrefix(-1)) << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700248 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700249 std::cerr << "Please type in the index of your choice:" << std::endl;
250 size_t index = 0;
tylerliufeabfdc2020-10-03 15:09:58 -0700251 try {
252 std::string input;
253 getline(std::cin, input);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700254 index = std::stoul(input);
tylerliufeabfdc2020-10-03 15:09:58 -0700255 }
256 catch (const std::exception& e) {
257 std::cerr << "Your input is Invalid. Exit" << std::endl;
258 exit(0);
259 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700260 if (index >= names.size() + redirects.size()) {
tylerliufeabfdc2020-10-03 15:09:58 -0700261 std::cerr << "Your input is not an existing index. Exit" << std::endl;
262 return;
263 }
264 if (index < names.size()) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700265 //names
tylerliud82cc5c2020-12-21 23:58:39 -0800266 auto selectedName = names[index].first;
267 std::cerr << "You selected name: " << selectedName.toUri() << std::endl;
268 std::cerr << "Enter Suffix if you would like one (Enter to skip): ";
269 try {
270 std::string input;
271 getline(std::cin, input);
272 auto inputName = Name(input);
273 if (!inputName.empty()) {
274 selectedName.append(inputName);
275 std::cerr << "You are applying name: " << selectedName.toUri() << std::endl;
276 }
277 }
278 catch (const std::exception& e) {
279 std::cerr << "Your input is Invalid. Exit" << std::endl;
280 exit(0);
281 }
282 runNew(profile, selectedName);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700283 }
284 else {
285 //redirects
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700286 auto redirectedCaFullName = redirects[index - names.size()];
tylerliua7bea662020-10-08 18:51:02 -0700287 auto redirectedCaName = security::extractIdentityFromCertName(redirectedCaFullName.getPrefix(-1));
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700288 std::cerr << "You selected to be redirected to CA: " << redirectedCaName.toUri() << std::endl;
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700289 face.expressInterest(
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700290 *Requester::genCaProfileDiscoveryInterest(redirectedCaName),
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700291 [&](const Interest&, const Data& data) {
292 auto fetchingInterest = Requester::genCaProfileInterestFromDiscoveryResponse(data);
293 face.expressInterest(*fetchingInterest,
294 bind(&InfoCb, _2, redirectedCaFullName),
295 bind(&onNackCb),
296 bind(&timeoutCb));
297 },
298 bind(&onNackCb),
299 bind(&timeoutCb));
tylerliufeabfdc2020-10-03 15:09:58 -0700300 }
301}
302
303static void
304selectCaProfile(std::string configFilePath)
305{
Zhiyi Zhanga16b7582020-10-29 18:59:46 -0700306 ProfileStorage profileStorage;
tylerliufeabfdc2020-10-03 15:09:58 -0700307 try {
Zhiyi Zhanga16b7582020-10-29 18:59:46 -0700308 profileStorage.load(configFilePath);
tylerliufeabfdc2020-10-03 15:09:58 -0700309 }
310 catch (const std::exception& e) {
311 std::cerr << "Cannot load the configuration file: " << e.what() << std::endl;
312 exit(1);
313 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700314 size_t count = 0;
315 std::cerr << "***************************************\n"
316 << "Step " << nStep++ << ": CA SELECTION" << std::endl;
Zhiyi Zhang84e11842020-11-19 20:03:23 -0800317 for (auto item : profileStorage.getKnownProfiles()) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700318 std::cerr << "> Index: " << count++ << std::endl
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800319 << ">> CA prefix:" << item.caPrefix << std::endl
320 << ">> Introduction: " << item.caInfo << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700321 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700322 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 -0700323
Zhiyi Zhang36706832019-07-04 21:33:03 -0700324 std::string caIndexS, caIndexSLower;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700325 getline(std::cin, caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700326 caIndexSLower = caIndexS;
327 boost::algorithm::to_lower(caIndexSLower);
328 if (caIndexSLower == "none") {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700329 std::cerr << "\n***************************************\n"
330 << "Step " << nStep << ": ADD NEW CA\nPlease type in the CA's Name:" << std::endl;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700331 std::string expectedCAName;
332 getline(std::cin, expectedCAName);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700333 face.expressInterest(
334 *Requester::genCaProfileDiscoveryInterest(Name(expectedCAName)),
335 [&](const Interest&, const Data& data) {
336 auto fetchingInterest = Requester::genCaProfileInterestFromDiscoveryResponse(data);
337 face.expressInterest(*fetchingInterest,
338 bind(&InfoCb, _2, Name()),
339 bind(&onNackCb),
340 bind(&timeoutCb));
341 },
342 bind(&onNackCb),
343 bind(&timeoutCb));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700344 }
345 else {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700346 size_t caIndex;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700347 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700348 caIndex = std::stoul(caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700349 }
350 catch (const std::exception& e) {
351 std::cerr << "Your input is neither NONE nor a valid index. Exit" << std::endl;
352 return;
353 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700354 if (caIndex >= count) {
Zhiyi Zhang36706832019-07-04 21:33:03 -0700355 std::cerr << "Your input is not an existing index. Exit" << std::endl;
356 return;
357 }
Zhiyi Zhang84e11842020-11-19 20:03:23 -0800358 auto itemIterator = profileStorage.getKnownProfiles().cbegin();
tylerliufeabfdc2020-10-03 15:09:58 -0700359 std::advance(itemIterator, caIndex);
360 auto targetCaItem = *itemIterator;
361 runProbe(targetCaItem);
362 }
363}
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700364
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700365static void
366runProbe(CaProfile profile)
tylerliufeabfdc2020-10-03 15:09:58 -0700367{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700368 std::cerr << "\n***************************************\n"
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700369 << "Step " << nStep++
370 << ": Do you know your identity name to be certified by CA "
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800371 << profile.caPrefix.toUri()
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700372 << " already? Type in YES or NO" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700373 bool validAnswer = false;
374 while (!validAnswer) {
375 std::string answer;
376 getline(std::cin, answer);
377 boost::algorithm::to_lower(answer);
378 if (answer == "yes") {
379 validAnswer = true;
380 std::cerr << "You answered YES" << std::endl;
381 std::cerr << "\n***************************************\n"
382 << "Step " << nStep++
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700383 << ": Please type in the full identity name you want to get (with CA prefix "
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800384 << profile.caPrefix.toUri()
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700385 << "):" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700386 std::string identityNameStr;
387 getline(std::cin, identityNameStr);
388 runNew(profile, Name(identityNameStr));
tylerliufeabfdc2020-10-03 15:09:58 -0700389 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700390 else if (answer == "no") {
391 validAnswer = true;
392 std::cerr << "You answered NO" << std::endl;
393 std::cerr << "\n***************************************\n"
394 << "Step " << nStep++ << ": Please provide information for name assignment" << std::endl;
Zhiyi Zhang44c6a352020-12-14 10:57:17 -0800395 auto capturedParams = captureParams(profile.probeParameterKeys);
Zhiyi Zhangdb1ec762020-10-30 08:58:39 -0700396 face.expressInterest(*Requester::genProbeInterest(profile, std::move(capturedParams)),
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700397 bind(&probeCb, _2, profile), bind(&onNackCb), bind(&timeoutCb));
398 }
399 else {
400 std::cerr << "Invalid answer. Type in YES or NO" << std::endl;
401 }
402 }
tylerliufeabfdc2020-10-03 15:09:58 -0700403}
404
405static void
406runNew(CaProfile profile, Name identityName)
407{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700408 int validityPeriod = captureValidityPeriod();
409 auto now = time::system_clock::now();
410 std::cerr << "The validity period of your certificate will be: " << validityPeriod << " hours" << std::endl;
Zhiyi Zhang48f546f2020-12-24 17:31:02 -0800411 requesterState = std::make_shared<RequestState>(keyChain, profile, RequestType::NEW);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700412 auto interest = Requester::genNewInterest(*requesterState, identityName, now, now + time::hours(validityPeriod));
413 if (interest != nullptr) {
414 face.expressInterest(*interest, bind(&newCb, _2), bind(&onNackCb), bind(&timeoutCb));
415 }
416 else {
417 std::cerr << "Cannot generate the Interest for NEW step. Exit" << std::endl;
418 }
tylerliufeabfdc2020-10-03 15:09:58 -0700419}
420
421static void
422runChallenge(const std::string& challengeType)
423{
tylerliu40226332020-11-11 15:37:16 -0800424 std::multimap<std::string, std::string> requirement;
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700425 try {
426 requirement = Requester::selectOrContinueChallenge(*requesterState, challengeType);
427 }
428 catch (const std::exception& e) {
429 std::cerr << "Error. Cannot successfully load the Challenge Module with error: " << std::string(e.what())
430 << "Exit." << std::endl;
431 exit(1);
432 }
tylerliufeabfdc2020-10-03 15:09:58 -0700433 if (requirement.size() > 0) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700434 std::cerr << "\n***************************************\n"
435 << "Step " << nStep
436 << ": Please provide parameters used for Identity Verification Challenge" << std::endl;
437 captureParams(requirement);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700438 }
tylerliufeabfdc2020-10-03 15:09:58 -0700439 face.expressInterest(*Requester::genChallengeInterest(*requesterState, std::move(requirement)),
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700440 bind(&challengeCb, _2), bind(&onNackCb), bind(&timeoutCb));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700441}
442
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700443static void
444handleSignal(const boost::system::error_code& error, int signalNum)
445{
446 if (error) {
447 return;
448 }
449 const char* signalName = ::strsignal(signalNum);
450 std::cerr << "Exiting on signal ";
451 if (signalName == nullptr) {
452 std::cerr << signalNum;
453 }
454 else {
455 std::cerr << signalName;
456 }
457 std::cerr << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700458 if (requesterState) {
459 Requester::endSession(*requesterState);
460 }
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700461 face.getIoService().stop();
tylerliufeabfdc2020-10-03 15:09:58 -0700462 exit(1);
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700463}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800464
465int
466main(int argc, char* argv[])
467{
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700468 boost::asio::signal_set terminateSignals(face.getIoService());
469 terminateSignals.add(SIGINT);
470 terminateSignals.add(SIGTERM);
471 terminateSignals.async_wait(handleSignal);
472
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800473 namespace po = boost::program_options;
Zhiyi Zhang840afd92020-10-21 13:24:08 -0700474 std::string configFilePath = std::string(NDNCERT_SYSCONFDIR) + "/ndncert/client.conf";
Zhiyi Zhang36706832019-07-04 21:33:03 -0700475 po::options_description description("General Usage\n ndncert-client [-h] [-c] [-v]\n");
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700476 description.add_options()("help,h", "produce help message")("config-file,c", po::value<std::string>(&configFilePath), "configuration file name");
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800477 po::positional_options_description p;
478
479 po::variables_map vm;
480 try {
481 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
482 po::notify(vm);
483 }
484 catch (const std::exception& e) {
485 std::cerr << "ERROR: " << e.what() << std::endl;
486 return 1;
487 }
488 if (vm.count("help") != 0) {
489 std::cerr << description << std::endl;
490 return 0;
491 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700492 selectCaProfile(configFilePath);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800493 face.processEvents();
494 return 0;
495}
496
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -0700497} // namespace requester
Zhiyi Zhange4891b72020-10-10 15:11:57 -0700498} // namespace ndncert
499} // namespace ndn
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800500
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700501int
502main(int argc, char* argv[])
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800503{
Zhiyi Zhang3002e6b2020-10-29 18:54:07 -0700504 return ndn::ndncert::requester::main(argc, argv);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800505}