blob: ed078a7a025704e6973cf1dabdd34d0706a3102a [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 Zhangdbd9d432020-10-07 15:56:27 -070021#include "identity-challenge/challenge-module.hpp"
Zhiyi Zhangc87d52b2020-09-28 22:07:18 -070022#include "protocol-detail/info.hpp"
Zhiyi Zhang837406d2020-10-05 22:01:31 -070023#include "requester.hpp"
Zhiyi Zhang90c75782020-10-06 15:04:03 -070024#include <ndn-cxx/security/verification-helpers.hpp>
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>
Zhiyi Zhang48f23782020-09-28 12:11:24 -070029#include <iostream>
Zhiyi Zhang48f23782020-09-28 12:11:24 -070030#include <string>
31
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080032namespace ndn {
33namespace ndncert {
34
Zhiyi Zhang48f23782020-09-28 12:11:24 -070035static void
tylerliufeabfdc2020-10-03 15:09:58 -070036selectCaProfile(std::string configFilePath);
37static void
38runProbe(CaProfile profile);
39static void
40runNew(CaProfile profile, Name identityName);
41static void
42runChallenge(const std::string& challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070043
Zhiyi Zhang837406d2020-10-05 22:01:31 -070044size_t nStep = 1;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070045Face face;
tylerliua7bea662020-10-08 18:51:02 -070046security::KeyChain keyChain;
tylerliufeabfdc2020-10-03 15:09:58 -070047shared_ptr<RequesterState> requesterState = nullptr;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080048
Zhiyi Zhang46049832020-09-28 17:08:12 -070049static void
50captureParams(std::vector<std::tuple<std::string, std::string>>& requirement)
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080051{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070052 std::list<std::string> results;
Zhiyi Zhang46049832020-09-28 17:08:12 -070053 for (auto& item : requirement) {
54 std::cerr << std::get<1>(item) << std::endl;
55 std::string captured;
56 getline(std::cin, captured);
57 std::get<1>(item) = captured;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080058 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070059 std::cerr << "Got it. This is what you've provided:" << std::endl;
Zhiyi Zhang46049832020-09-28 17:08:12 -070060 for (const auto& item : requirement) {
61 std::cerr << std::get<0>(item) << " : " << std::get<1>(item) << std::endl;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080062 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070063}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080064
Zhiyi Zhang9829da92020-09-30 16:19:34 -070065static std::vector<std::tuple<std::string, std::string>>
66captureParams(const std::list<std::string>& requirement)
Zhiyi Zhang547c8512019-06-18 23:46:14 -070067{
Zhiyi Zhang9829da92020-09-30 16:19:34 -070068 std::vector<std::tuple<std::string, std::string>> results;
tylerliufeabfdc2020-10-03 15:09:58 -070069 for (const auto& r : requirement) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -070070 results.emplace_back(r, "Please input: " + r);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070071 }
tylerliufeabfdc2020-10-03 15:09:58 -070072 captureParams(results);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070073 return results;
74}
75
tylerliufeabfdc2020-10-03 15:09:58 -070076static int
Zhiyi Zhang36706832019-07-04 21:33:03 -070077captureValidityPeriod()
78{
Zhiyi Zhang837406d2020-10-05 22:01:31 -070079 std::cerr << "\n***************************************\n"
80 << "Step " << nStep++
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070081 << ": Please type in your expected validity period of your certificate."
82 << " Type the number of hours (168 for week, 730 for month, 8760 for year)."
83 << " The CA may reject your application if your expected period is too long." << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -070084 while (true) {
85 std::string periodStr = "";
86 getline(std::cin, periodStr);
87 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -070088 return std::stoul(periodStr);
tylerliufeabfdc2020-10-03 15:09:58 -070089 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -070090 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -070091 std::cerr << "Your input is invalid. Try again: " << std::endl;
92 }
Zhiyi Zhang36706832019-07-04 21:33:03 -070093 }
94}
95
96static void
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070097onNackCb()
98{
99 std::cerr << "Got NACK\n";
100}
101
102static void
103timeoutCb()
104{
105 std::cerr << "Interest sent time out\n";
106}
107
108static void
swa770cf1d8f72020-04-21 23:12:39 -0700109certFetchCb(const Data& reply)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700110{
tylerliufeabfdc2020-10-03 15:09:58 -0700111 auto item = Requester::onCertFetchResponse(reply);
112 if (item) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700113 keyChain.addCertificate(keyChain.getPib().getIdentity(item->getIdentity()).getKey(item->getKeyName()), *item);
tylerliufeabfdc2020-10-03 15:09:58 -0700114 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700115 std::cerr << "\n***************************************\n"
116 << "Step " << nStep++
117 << ": DONE\nCertificate with Name: " << reply.getName().toUri()
118 << "has already been installed to your local keychain" << std::endl
119 << "Exit now";
120 face.getIoService().stop();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700121}
122
123static void
124challengeCb(const Data& reply)
125{
tylerliufeabfdc2020-10-03 15:09:58 -0700126 try {
127 Requester::onChallengeResponse(*requesterState, reply);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700128 }
129 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700130 std::cerr << "Error when decoding challenge step: " << e.what() << std::endl;
131 exit(1);
132 }
133 if (requesterState->m_status == Status::SUCCESS) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700134 std::cerr << "Certificate has already been issued, downloading certificate..." << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700135 face.expressInterest(*Requester::genCertFetchInterest(*requesterState), bind(&certFetchCb, _2),
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700136 bind(&onNackCb), bind(&timeoutCb));
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700137 return;
138 }
139
tylerliufeabfdc2020-10-03 15:09:58 -0700140 runChallenge(requesterState->m_challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700141}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800142
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700143static void
144newCb(const Data& reply)
145{
tylerliufeabfdc2020-10-03 15:09:58 -0700146 std::list<std::string> challengeList;
147 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700148 challengeList = Requester::onNewRenewRevokeResponse(*requesterState, reply);
149 }
150 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700151 std::cerr << "Error on decoding NEW step reply because: " << e.what() << std::endl;
152 exit(1);
153 }
154
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700155 size_t challengeIndex = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700156 if (challengeList.size() < 1) {
157 std::cerr << "There is no available challenge provided by the CA. Exit" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700158 exit(1);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800159 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700160 else if (challengeList.size() > 1) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700161 std::cerr << "\n***************************************\n"
162 << "Step " << nStep++
163 << ": CHALLENGE SELECTION" << std::endl;
164 size_t count = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700165 std::string choice = "";
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700166 for (auto item : challengeList) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700167 std::cerr << "> Index: " << count++ << std::endl
168 << ">> Challenge:" << item << std::endl;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700169 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700170 std::cerr << "Please type in the challenge index that you want to perform:" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700171 while (true) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700172 getline(std::cin, choice);
173 try {
174 challengeIndex = std::stoul(choice);
175 }
176 catch (const std::exception& e) {
177 std::cerr << "Your input is not valid. Try again:" << std::endl;
178 continue;
179 }
180 if (challengeIndex >= count) {
181 std::cerr << "Your input index is out of range. Try again:" << std::endl;
182 continue;
183 }
184 break;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700185 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700186 }
187 auto it = challengeList.begin();
188 std::advance(it, challengeIndex);
189 unique_ptr<ChallengeModule> challenge = ChallengeModule::createChallengeModule(*it);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700190 if (challenge != nullptr) {
tylerliufeabfdc2020-10-03 15:09:58 -0700191 std::cerr << "The challenge has been selected: " << *it << std::endl;
192 runChallenge(*it);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800193 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700194 else {
Zhiyi Zhang36706832019-07-04 21:33:03 -0700195 std::cerr << "Error. Cannot load selected Challenge Module. Exit." << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700196 exit(1);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700197 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700198}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800199
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700200static void
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700201InfoCb(const Data& reply, const Name& certFullName)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700202{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700203 boost::optional<CaProfile> profile;
tylerliufeabfdc2020-10-03 15:09:58 -0700204 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700205 if (certFullName.empty()) {
206 profile = Requester::onCaProfileResponse(reply);
tylerliufeabfdc2020-10-03 15:09:58 -0700207 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700208 else {
209 profile = Requester::onCaProfileResponseAfterRedirection(reply, certFullName);
210 }
211 }
212 catch (const std::exception& e) {
213 std::cerr << "The fetched CA information cannot be used because: " << e.what() << std::endl;
214 return;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700215 }
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700216 std::cerr << "\n***************************************\n"
217 << "Step " << nStep++
218 << ": Will use a new trust anchor, please double check the identity info:" << std::endl
219 << "> New CA name: " << profile->m_caPrefix.toUri() << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700220 << "> This trust anchor information is signed by: " << reply.getSignatureInfo().getKeyLocator() << std::endl
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700221 << "> The certificate: " << profile->m_cert << std::endl
Davide Pesaventob48bbda2020-07-27 19:41:37 -0400222 << "Do you trust the information? Type in YES or NO" << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700223
224 std::string answer;
225 getline(std::cin, answer);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700226 boost::algorithm::to_lower(answer);
227 if (answer == "yes") {
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700228 std::cerr << "You answered YES: new CA " << profile->m_caPrefix.toUri() << " will be used" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700229 runProbe(*profile);
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700230 // client.getClientConf().save(std::string(SYSCONFDIR) + "/ndncert/client.conf");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700231 }
232 else {
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700233 std::cerr << "You answered NO: new CA " << profile->m_caPrefix.toUri() << " will not be used" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700234 exit(0);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700235 }
236}
237
238static void
tylerliufeabfdc2020-10-03 15:09:58 -0700239probeCb(const Data& reply, CaProfile profile)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700240{
tylerliub47dad72020-10-08 21:36:55 -0700241 std::vector<std::pair<Name, int>> names;
tylerliufeabfdc2020-10-03 15:09:58 -0700242 std::vector<Name> redirects;
243 Requester::onProbeResponse(reply, profile, names, redirects);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700244 size_t count = 0;
245 std::cerr << "\n***************************************\n"
246 << "Step " << nStep++
247 << ": You can either select one of the following names suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700248 for (const auto& name : names) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700249 std::cerr << "> Index: " << count++ << std::endl
tylerliub47dad72020-10-08 21:36:55 -0700250 << ">> Suggested name: " << name.first.toUri() << std::endl
251 << ">> Corresponding Max sufiix length: " << name.second << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700252 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700253 std::cerr << "\nOr choose another trusted CA suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700254 for (const auto& redirect : redirects) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700255 std::cerr << "> Index: " << count++ << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700256 << ">> Suggested CA: " << security::extractIdentityFromCertName(redirect.getPrefix(-1)) << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700257 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700258 std::cerr << "Please type in the index of your choice:" << std::endl;
259 size_t index = 0;
tylerliufeabfdc2020-10-03 15:09:58 -0700260 try {
261 std::string input;
262 getline(std::cin, input);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700263 index = std::stoul(input);
tylerliufeabfdc2020-10-03 15:09:58 -0700264 }
265 catch (const std::exception& e) {
266 std::cerr << "Your input is Invalid. Exit" << std::endl;
267 exit(0);
268 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700269 if (index >= names.size() + redirects.size()) {
tylerliufeabfdc2020-10-03 15:09:58 -0700270 std::cerr << "Your input is not an existing index. Exit" << std::endl;
271 return;
272 }
273 if (index < names.size()) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700274 //names
tylerliub47dad72020-10-08 21:36:55 -0700275 std::cerr << "You selected name: " << names[index].first.toUri() << std::endl;
276 //TODO add prompt to "add suffix"
277 runNew(profile, names[index].first);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700278 }
279 else {
280 //redirects
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700281 auto redirectedCaFullName = redirects[index - names.size()];
tylerliua7bea662020-10-08 18:51:02 -0700282 auto redirectedCaName = security::extractIdentityFromCertName(redirectedCaFullName.getPrefix(-1));
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700283 std::cerr << "You selected to be redirected to CA: " << redirectedCaName.toUri() << std::endl;
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700284 face.expressInterest(
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700285 *Requester::genCaProfileDiscoveryInterest(redirectedCaName),
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700286 [&](const Interest&, const Data& data) {
287 auto fetchingInterest = Requester::genCaProfileInterestFromDiscoveryResponse(data);
288 face.expressInterest(*fetchingInterest,
289 bind(&InfoCb, _2, redirectedCaFullName),
290 bind(&onNackCb),
291 bind(&timeoutCb));
292 },
293 bind(&onNackCb),
294 bind(&timeoutCb));
tylerliufeabfdc2020-10-03 15:09:58 -0700295 }
296}
297
298static void
299selectCaProfile(std::string configFilePath)
300{
301 RequesterCaCache caCache;
302 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700303 caCache.load(configFilePath);
tylerliufeabfdc2020-10-03 15:09:58 -0700304 }
305 catch (const std::exception& e) {
306 std::cerr << "Cannot load the configuration file: " << e.what() << std::endl;
307 exit(1);
308 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700309 size_t count = 0;
310 std::cerr << "***************************************\n"
311 << "Step " << nStep++ << ": CA SELECTION" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700312 for (auto item : caCache.m_caItems) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700313 std::cerr << "> Index: " << count++ << std::endl
314 << ">> CA prefix:" << item.m_caPrefix << std::endl
315 << ">> Introduction: " << item.m_caInfo << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700316 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700317 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 -0700318
Zhiyi Zhang36706832019-07-04 21:33:03 -0700319 std::string caIndexS, caIndexSLower;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700320 getline(std::cin, caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700321 caIndexSLower = caIndexS;
322 boost::algorithm::to_lower(caIndexSLower);
323 if (caIndexSLower == "none") {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700324 std::cerr << "\n***************************************\n"
325 << "Step " << nStep << ": ADD NEW CA\nPlease type in the CA's Name:" << std::endl;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700326 std::string expectedCAName;
327 getline(std::cin, expectedCAName);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700328 face.expressInterest(
329 *Requester::genCaProfileDiscoveryInterest(Name(expectedCAName)),
330 [&](const Interest&, const Data& data) {
331 auto fetchingInterest = Requester::genCaProfileInterestFromDiscoveryResponse(data);
332 face.expressInterest(*fetchingInterest,
333 bind(&InfoCb, _2, Name()),
334 bind(&onNackCb),
335 bind(&timeoutCb));
336 },
337 bind(&onNackCb),
338 bind(&timeoutCb));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700339 }
340 else {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700341 size_t caIndex;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700342 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700343 caIndex = std::stoul(caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700344 }
345 catch (const std::exception& e) {
346 std::cerr << "Your input is neither NONE nor a valid index. Exit" << std::endl;
347 return;
348 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700349 if (caIndex >= count) {
Zhiyi Zhang36706832019-07-04 21:33:03 -0700350 std::cerr << "Your input is not an existing index. Exit" << std::endl;
351 return;
352 }
tylerliufeabfdc2020-10-03 15:09:58 -0700353 auto itemIterator = caCache.m_caItems.cbegin();
354 std::advance(itemIterator, caIndex);
355 auto targetCaItem = *itemIterator;
356 runProbe(targetCaItem);
357 }
358}
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700359
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700360static void
361runProbe(CaProfile profile)
tylerliufeabfdc2020-10-03 15:09:58 -0700362{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700363 std::cerr << "\n***************************************\n"
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700364 << "Step " << nStep++
365 << ": Do you know your identity name to be certified by CA "
366 << profile.m_caPrefix.toUri()
367 << " already? Type in YES or NO" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700368 bool validAnswer = false;
369 while (!validAnswer) {
370 std::string answer;
371 getline(std::cin, answer);
372 boost::algorithm::to_lower(answer);
373 if (answer == "yes") {
374 validAnswer = true;
375 std::cerr << "You answered YES" << std::endl;
376 std::cerr << "\n***************************************\n"
377 << "Step " << nStep++
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700378 << ": Please type in the full identity name you want to get (with CA prefix "
379 << profile.m_caPrefix.toUri()
380 << "):" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700381 std::string identityNameStr;
382 getline(std::cin, identityNameStr);
383 runNew(profile, Name(identityNameStr));
tylerliufeabfdc2020-10-03 15:09:58 -0700384 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700385 else if (answer == "no") {
386 validAnswer = true;
387 std::cerr << "You answered NO" << std::endl;
388 std::cerr << "\n***************************************\n"
389 << "Step " << nStep++ << ": Please provide information for name assignment" << std::endl;
390 auto capturedParams = captureParams(profile.m_probeParameterKeys);
391 face.expressInterest(*Requester::genProbeInterest(profile, std::move(capturedParams)),
392 bind(&probeCb, _2, profile), bind(&onNackCb), bind(&timeoutCb));
393 }
394 else {
395 std::cerr << "Invalid answer. Type in YES or NO" << std::endl;
396 }
397 }
tylerliufeabfdc2020-10-03 15:09:58 -0700398}
399
400static void
401runNew(CaProfile profile, Name identityName)
402{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700403 int validityPeriod = captureValidityPeriod();
404 auto now = time::system_clock::now();
405 std::cerr << "The validity period of your certificate will be: " << validityPeriod << " hours" << std::endl;
Zhiyi Zhang32437282020-10-10 16:15:37 -0700406 requesterState =std::make_shared<RequesterState>(keyChain, profile, RequestType::NEW);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700407 auto interest = Requester::genNewInterest(*requesterState, identityName, now, now + time::hours(validityPeriod));
408 if (interest != nullptr) {
409 face.expressInterest(*interest, bind(&newCb, _2), bind(&onNackCb), bind(&timeoutCb));
410 }
411 else {
412 std::cerr << "Cannot generate the Interest for NEW step. Exit" << std::endl;
413 }
tylerliufeabfdc2020-10-03 15:09:58 -0700414}
415
416static void
417runChallenge(const std::string& challengeType)
418{
419 auto requirement = Requester::selectOrContinueChallenge(*requesterState, challengeType);
420 if (requirement.size() > 0) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700421 std::cerr << "\n***************************************\n"
422 << "Step " << nStep
423 << ": Please provide parameters used for Identity Verification Challenge" << std::endl;
424 captureParams(requirement);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700425 }
tylerliufeabfdc2020-10-03 15:09:58 -0700426 face.expressInterest(*Requester::genChallengeInterest(*requesterState, std::move(requirement)),
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700427 bind(&challengeCb, _2), bind(&onNackCb), bind(&timeoutCb));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700428}
429
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700430static void
431handleSignal(const boost::system::error_code& error, int signalNum)
432{
433 if (error) {
434 return;
435 }
436 const char* signalName = ::strsignal(signalNum);
437 std::cerr << "Exiting on signal ";
438 if (signalName == nullptr) {
439 std::cerr << signalNum;
440 }
441 else {
442 std::cerr << signalName;
443 }
444 std::cerr << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700445 if (requesterState) {
446 Requester::endSession(*requesterState);
447 }
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700448 face.getIoService().stop();
tylerliufeabfdc2020-10-03 15:09:58 -0700449 exit(1);
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700450}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800451
452int
453main(int argc, char* argv[])
454{
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700455 boost::asio::signal_set terminateSignals(face.getIoService());
456 terminateSignals.add(SIGINT);
457 terminateSignals.add(SIGTERM);
458 terminateSignals.async_wait(handleSignal);
459
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800460 namespace po = boost::program_options;
461 std::string configFilePath = std::string(SYSCONFDIR) + "/ndncert/client.conf";
Zhiyi Zhang36706832019-07-04 21:33:03 -0700462 po::options_description description("General Usage\n ndncert-client [-h] [-c] [-v]\n");
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700463 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 -0800464 po::positional_options_description p;
465
466 po::variables_map vm;
467 try {
468 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
469 po::notify(vm);
470 }
471 catch (const std::exception& e) {
472 std::cerr << "ERROR: " << e.what() << std::endl;
473 return 1;
474 }
475 if (vm.count("help") != 0) {
476 std::cerr << description << std::endl;
477 return 0;
478 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700479 selectCaProfile(configFilePath);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800480 face.processEvents();
481 return 0;
482}
483
Zhiyi Zhange4891b72020-10-10 15:11:57 -0700484} // namespace ndncert
485} // namespace ndn
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800486
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700487int
488main(int argc, char* argv[])
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800489{
490 return ndn::ndncert::main(argc, argv);
491}