blob: 5c712a60a332d5b3227d795111d614f79e67b567 [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 {
32
Zhiyi Zhang48f23782020-09-28 12:11:24 -070033static void
tylerliufeabfdc2020-10-03 15:09:58 -070034selectCaProfile(std::string configFilePath);
35static void
36runProbe(CaProfile profile);
37static void
38runNew(CaProfile profile, Name identityName);
39static void
40runChallenge(const std::string& challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070041
Zhiyi Zhang837406d2020-10-05 22:01:31 -070042size_t nStep = 1;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070043Face face;
tylerliua7bea662020-10-08 18:51:02 -070044security::KeyChain keyChain;
tylerliufeabfdc2020-10-03 15:09:58 -070045shared_ptr<RequesterState> requesterState = nullptr;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080046
Zhiyi Zhang46049832020-09-28 17:08:12 -070047static void
48captureParams(std::vector<std::tuple<std::string, std::string>>& requirement)
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080049{
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070050 std::list<std::string> results;
Zhiyi Zhang46049832020-09-28 17:08:12 -070051 for (auto& item : requirement) {
52 std::cerr << std::get<1>(item) << std::endl;
53 std::string captured;
54 getline(std::cin, captured);
55 std::get<1>(item) = captured;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080056 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070057 std::cerr << "Got it. This is what you've provided:" << std::endl;
Zhiyi Zhang46049832020-09-28 17:08:12 -070058 for (const auto& item : requirement) {
59 std::cerr << std::get<0>(item) << " : " << std::get<1>(item) << std::endl;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080060 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070061}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080062
Zhiyi Zhang9829da92020-09-30 16:19:34 -070063static std::vector<std::tuple<std::string, std::string>>
64captureParams(const std::list<std::string>& requirement)
Zhiyi Zhang547c8512019-06-18 23:46:14 -070065{
Zhiyi Zhang9829da92020-09-30 16:19:34 -070066 std::vector<std::tuple<std::string, std::string>> results;
tylerliufeabfdc2020-10-03 15:09:58 -070067 for (const auto& r : requirement) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -070068 results.emplace_back(r, "Please input: " + r);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070069 }
tylerliufeabfdc2020-10-03 15:09:58 -070070 captureParams(results);
Zhiyi Zhang547c8512019-06-18 23:46:14 -070071 return results;
72}
73
tylerliufeabfdc2020-10-03 15:09:58 -070074static int
Zhiyi Zhang36706832019-07-04 21:33:03 -070075captureValidityPeriod()
76{
Zhiyi Zhang837406d2020-10-05 22:01:31 -070077 std::cerr << "\n***************************************\n"
78 << "Step " << nStep++
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -070079 << ": Please type in your expected validity period of your certificate."
80 << " Type the number of hours (168 for week, 730 for month, 8760 for year)."
81 << " The CA may reject your application if your expected period is too long." << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -070082 while (true) {
83 std::string periodStr = "";
84 getline(std::cin, periodStr);
85 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -070086 return std::stoul(periodStr);
tylerliufeabfdc2020-10-03 15:09:58 -070087 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -070088 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -070089 std::cerr << "Your input is invalid. Try again: " << std::endl;
90 }
Zhiyi Zhang36706832019-07-04 21:33:03 -070091 }
92}
93
94static void
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070095onNackCb()
96{
97 std::cerr << "Got NACK\n";
98}
99
100static void
101timeoutCb()
102{
103 std::cerr << "Interest sent time out\n";
104}
105
106static void
swa770cf1d8f72020-04-21 23:12:39 -0700107certFetchCb(const Data& reply)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700108{
tylerliufeabfdc2020-10-03 15:09:58 -0700109 auto item = Requester::onCertFetchResponse(reply);
110 if (item) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700111 keyChain.addCertificate(keyChain.getPib().getIdentity(item->getIdentity()).getKey(item->getKeyName()), *item);
tylerliufeabfdc2020-10-03 15:09:58 -0700112 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700113 std::cerr << "\n***************************************\n"
114 << "Step " << nStep++
115 << ": DONE\nCertificate with Name: " << reply.getName().toUri()
116 << "has already been installed to your local keychain" << std::endl
117 << "Exit now";
118 face.getIoService().stop();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700119}
120
121static void
122challengeCb(const Data& reply)
123{
tylerliufeabfdc2020-10-03 15:09:58 -0700124 try {
125 Requester::onChallengeResponse(*requesterState, reply);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700126 }
127 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700128 std::cerr << "Error when decoding challenge step: " << e.what() << std::endl;
129 exit(1);
130 }
131 if (requesterState->m_status == Status::SUCCESS) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700132 std::cerr << "Certificate has already been issued, downloading certificate..." << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700133 face.expressInterest(*Requester::genCertFetchInterest(*requesterState), bind(&certFetchCb, _2),
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700134 bind(&onNackCb), bind(&timeoutCb));
Zhiyi Zhang4d89fe02017-04-28 18:51:51 -0700135 return;
136 }
tylerliufeabfdc2020-10-03 15:09:58 -0700137 runChallenge(requesterState->m_challengeType);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700138}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800139
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700140static void
141newCb(const Data& reply)
142{
tylerliufeabfdc2020-10-03 15:09:58 -0700143 std::list<std::string> challengeList;
144 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700145 challengeList = Requester::onNewRenewRevokeResponse(*requesterState, reply);
146 }
147 catch (const std::exception& e) {
tylerliufeabfdc2020-10-03 15:09:58 -0700148 std::cerr << "Error on decoding NEW step reply because: " << e.what() << std::endl;
149 exit(1);
150 }
151
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700152 size_t challengeIndex = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700153 if (challengeList.size() < 1) {
154 std::cerr << "There is no available challenge provided by the CA. Exit" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700155 exit(1);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800156 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700157 else if (challengeList.size() > 1) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700158 std::cerr << "\n***************************************\n"
159 << "Step " << nStep++
160 << ": CHALLENGE SELECTION" << std::endl;
161 size_t count = 0;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700162 std::string choice = "";
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700163 for (auto item : challengeList) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700164 std::cerr << "> Index: " << count++ << std::endl
165 << ">> Challenge:" << item << std::endl;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700166 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700167 std::cerr << "Please type in the challenge index that you want to perform:" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700168 while (true) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700169 getline(std::cin, choice);
170 try {
171 challengeIndex = std::stoul(choice);
172 }
173 catch (const std::exception& e) {
174 std::cerr << "Your input is not valid. Try again:" << std::endl;
175 continue;
176 }
177 if (challengeIndex >= count) {
178 std::cerr << "Your input index is out of range. Try again:" << std::endl;
179 continue;
180 }
181 break;
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700182 }
Zhiyi Zhang36706832019-07-04 21:33:03 -0700183 }
184 auto it = challengeList.begin();
185 std::advance(it, challengeIndex);
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700186 std::cerr << "The challenge has been selected: " << *it << std::endl;
187 runChallenge(*it);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700188}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800189
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700190static void
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700191InfoCb(const Data& reply, const Name& certFullName)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700192{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700193 boost::optional<CaProfile> profile;
tylerliufeabfdc2020-10-03 15:09:58 -0700194 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700195 if (certFullName.empty()) {
196 profile = Requester::onCaProfileResponse(reply);
tylerliufeabfdc2020-10-03 15:09:58 -0700197 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700198 else {
199 profile = Requester::onCaProfileResponseAfterRedirection(reply, certFullName);
200 }
201 }
202 catch (const std::exception& e) {
203 std::cerr << "The fetched CA information cannot be used because: " << e.what() << std::endl;
204 return;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700205 }
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700206 std::cerr << "\n***************************************\n"
207 << "Step " << nStep++
208 << ": Will use a new trust anchor, please double check the identity info:" << std::endl
209 << "> New CA name: " << profile->m_caPrefix.toUri() << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700210 << "> This trust anchor information is signed by: " << reply.getSignatureInfo().getKeyLocator() << std::endl
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700211 << "> The certificate: " << profile->m_cert << std::endl
Davide Pesaventob48bbda2020-07-27 19:41:37 -0400212 << "Do you trust the information? Type in YES or NO" << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700213
214 std::string answer;
215 getline(std::cin, answer);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700216 boost::algorithm::to_lower(answer);
217 if (answer == "yes") {
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700218 std::cerr << "You answered YES: new CA " << profile->m_caPrefix.toUri() << " will be used" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700219 runProbe(*profile);
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700220 // client.getClientConf().save(std::string(SYSCONFDIR) + "/ndncert/client.conf");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700221 }
222 else {
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700223 std::cerr << "You answered NO: new CA " << profile->m_caPrefix.toUri() << " will not be used" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700224 exit(0);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700225 }
226}
227
228static void
tylerliufeabfdc2020-10-03 15:09:58 -0700229probeCb(const Data& reply, CaProfile profile)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700230{
tylerliub47dad72020-10-08 21:36:55 -0700231 std::vector<std::pair<Name, int>> names;
tylerliufeabfdc2020-10-03 15:09:58 -0700232 std::vector<Name> redirects;
233 Requester::onProbeResponse(reply, profile, names, redirects);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700234 size_t count = 0;
235 std::cerr << "\n***************************************\n"
236 << "Step " << nStep++
237 << ": You can either select one of the following names suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700238 for (const auto& name : names) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700239 std::cerr << "> Index: " << count++ << std::endl
tylerliub47dad72020-10-08 21:36:55 -0700240 << ">> Suggested name: " << name.first.toUri() << std::endl
241 << ">> Corresponding Max sufiix length: " << name.second << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700242 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700243 std::cerr << "\nOr choose another trusted CA suggested by the CA: " << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700244 for (const auto& redirect : redirects) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700245 std::cerr << "> Index: " << count++ << std::endl
tylerliua7bea662020-10-08 18:51:02 -0700246 << ">> Suggested CA: " << security::extractIdentityFromCertName(redirect.getPrefix(-1)) << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700247 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700248 std::cerr << "Please type in the index of your choice:" << std::endl;
249 size_t index = 0;
tylerliufeabfdc2020-10-03 15:09:58 -0700250 try {
251 std::string input;
252 getline(std::cin, input);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700253 index = std::stoul(input);
tylerliufeabfdc2020-10-03 15:09:58 -0700254 }
255 catch (const std::exception& e) {
256 std::cerr << "Your input is Invalid. Exit" << std::endl;
257 exit(0);
258 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700259 if (index >= names.size() + redirects.size()) {
tylerliufeabfdc2020-10-03 15:09:58 -0700260 std::cerr << "Your input is not an existing index. Exit" << std::endl;
261 return;
262 }
263 if (index < names.size()) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700264 //names
tylerliub47dad72020-10-08 21:36:55 -0700265 std::cerr << "You selected name: " << names[index].first.toUri() << std::endl;
266 //TODO add prompt to "add suffix"
267 runNew(profile, names[index].first);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700268 }
269 else {
270 //redirects
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700271 auto redirectedCaFullName = redirects[index - names.size()];
tylerliua7bea662020-10-08 18:51:02 -0700272 auto redirectedCaName = security::extractIdentityFromCertName(redirectedCaFullName.getPrefix(-1));
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700273 std::cerr << "You selected to be redirected to CA: " << redirectedCaName.toUri() << std::endl;
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700274 face.expressInterest(
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700275 *Requester::genCaProfileDiscoveryInterest(redirectedCaName),
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700276 [&](const Interest&, const Data& data) {
277 auto fetchingInterest = Requester::genCaProfileInterestFromDiscoveryResponse(data);
278 face.expressInterest(*fetchingInterest,
279 bind(&InfoCb, _2, redirectedCaFullName),
280 bind(&onNackCb),
281 bind(&timeoutCb));
282 },
283 bind(&onNackCb),
284 bind(&timeoutCb));
tylerliufeabfdc2020-10-03 15:09:58 -0700285 }
286}
287
288static void
289selectCaProfile(std::string configFilePath)
290{
291 RequesterCaCache caCache;
292 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700293 caCache.load(configFilePath);
tylerliufeabfdc2020-10-03 15:09:58 -0700294 }
295 catch (const std::exception& e) {
296 std::cerr << "Cannot load the configuration file: " << e.what() << std::endl;
297 exit(1);
298 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700299 size_t count = 0;
300 std::cerr << "***************************************\n"
301 << "Step " << nStep++ << ": CA SELECTION" << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700302 for (auto item : caCache.m_caItems) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700303 std::cerr << "> Index: " << count++ << std::endl
304 << ">> CA prefix:" << item.m_caPrefix << std::endl
305 << ">> Introduction: " << item.m_caInfo << std::endl;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700306 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700307 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 -0700308
Zhiyi Zhang36706832019-07-04 21:33:03 -0700309 std::string caIndexS, caIndexSLower;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700310 getline(std::cin, caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700311 caIndexSLower = caIndexS;
312 boost::algorithm::to_lower(caIndexSLower);
313 if (caIndexSLower == "none") {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700314 std::cerr << "\n***************************************\n"
315 << "Step " << nStep << ": ADD NEW CA\nPlease type in the CA's Name:" << std::endl;
Zhiyi Zhangcaab5462019-10-18 13:41:02 -0700316 std::string expectedCAName;
317 getline(std::cin, expectedCAName);
Zhiyi Zhangfbcab842020-10-07 15:17:13 -0700318 face.expressInterest(
319 *Requester::genCaProfileDiscoveryInterest(Name(expectedCAName)),
320 [&](const Interest&, const Data& data) {
321 auto fetchingInterest = Requester::genCaProfileInterestFromDiscoveryResponse(data);
322 face.expressInterest(*fetchingInterest,
323 bind(&InfoCb, _2, Name()),
324 bind(&onNackCb),
325 bind(&timeoutCb));
326 },
327 bind(&onNackCb),
328 bind(&timeoutCb));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700329 }
330 else {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700331 size_t caIndex;
Zhiyi Zhang36706832019-07-04 21:33:03 -0700332 try {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700333 caIndex = std::stoul(caIndexS);
Zhiyi Zhang36706832019-07-04 21:33:03 -0700334 }
335 catch (const std::exception& e) {
336 std::cerr << "Your input is neither NONE nor a valid index. Exit" << std::endl;
337 return;
338 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700339 if (caIndex >= count) {
Zhiyi Zhang36706832019-07-04 21:33:03 -0700340 std::cerr << "Your input is not an existing index. Exit" << std::endl;
341 return;
342 }
tylerliufeabfdc2020-10-03 15:09:58 -0700343 auto itemIterator = caCache.m_caItems.cbegin();
344 std::advance(itemIterator, caIndex);
345 auto targetCaItem = *itemIterator;
346 runProbe(targetCaItem);
347 }
348}
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700349
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700350static void
351runProbe(CaProfile profile)
tylerliufeabfdc2020-10-03 15:09:58 -0700352{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700353 std::cerr << "\n***************************************\n"
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700354 << "Step " << nStep++
355 << ": Do you know your identity name to be certified by CA "
356 << profile.m_caPrefix.toUri()
357 << " already? Type in YES or NO" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700358 bool validAnswer = false;
359 while (!validAnswer) {
360 std::string answer;
361 getline(std::cin, answer);
362 boost::algorithm::to_lower(answer);
363 if (answer == "yes") {
364 validAnswer = true;
365 std::cerr << "You answered YES" << std::endl;
366 std::cerr << "\n***************************************\n"
367 << "Step " << nStep++
Zhiyi Zhang6bb1d082020-10-08 14:25:21 -0700368 << ": Please type in the full identity name you want to get (with CA prefix "
369 << profile.m_caPrefix.toUri()
370 << "):" << std::endl;
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700371 std::string identityNameStr;
372 getline(std::cin, identityNameStr);
373 runNew(profile, Name(identityNameStr));
tylerliufeabfdc2020-10-03 15:09:58 -0700374 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700375 else if (answer == "no") {
376 validAnswer = true;
377 std::cerr << "You answered NO" << std::endl;
378 std::cerr << "\n***************************************\n"
379 << "Step " << nStep++ << ": Please provide information for name assignment" << std::endl;
380 auto capturedParams = captureParams(profile.m_probeParameterKeys);
381 face.expressInterest(*Requester::genProbeInterest(profile, std::move(capturedParams)),
382 bind(&probeCb, _2, profile), bind(&onNackCb), bind(&timeoutCb));
383 }
384 else {
385 std::cerr << "Invalid answer. Type in YES or NO" << std::endl;
386 }
387 }
tylerliufeabfdc2020-10-03 15:09:58 -0700388}
389
390static void
391runNew(CaProfile profile, Name identityName)
392{
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700393 int validityPeriod = captureValidityPeriod();
394 auto now = time::system_clock::now();
395 std::cerr << "The validity period of your certificate will be: " << validityPeriod << " hours" << std::endl;
Zhiyi Zhang32437282020-10-10 16:15:37 -0700396 requesterState =std::make_shared<RequesterState>(keyChain, profile, RequestType::NEW);
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700397 auto interest = Requester::genNewInterest(*requesterState, identityName, now, now + time::hours(validityPeriod));
398 if (interest != nullptr) {
399 face.expressInterest(*interest, bind(&newCb, _2), bind(&onNackCb), bind(&timeoutCb));
400 }
401 else {
402 std::cerr << "Cannot generate the Interest for NEW step. Exit" << std::endl;
403 }
tylerliufeabfdc2020-10-03 15:09:58 -0700404}
405
406static void
407runChallenge(const std::string& challengeType)
408{
Zhiyi Zhangc5d93a92020-10-14 17:07:35 -0700409 std::vector<std::tuple<std::string, std::string>> requirement;
410 try {
411 requirement = Requester::selectOrContinueChallenge(*requesterState, challengeType);
412 }
413 catch (const std::exception& e) {
414 std::cerr << "Error. Cannot successfully load the Challenge Module with error: " << std::string(e.what())
415 << "Exit." << std::endl;
416 exit(1);
417 }
tylerliufeabfdc2020-10-03 15:09:58 -0700418 if (requirement.size() > 0) {
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700419 std::cerr << "\n***************************************\n"
420 << "Step " << nStep
421 << ": Please provide parameters used for Identity Verification Challenge" << std::endl;
422 captureParams(requirement);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700423 }
tylerliufeabfdc2020-10-03 15:09:58 -0700424 face.expressInterest(*Requester::genChallengeInterest(*requesterState, std::move(requirement)),
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700425 bind(&challengeCb, _2), bind(&onNackCb), bind(&timeoutCb));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700426}
427
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700428static void
429handleSignal(const boost::system::error_code& error, int signalNum)
430{
431 if (error) {
432 return;
433 }
434 const char* signalName = ::strsignal(signalNum);
435 std::cerr << "Exiting on signal ";
436 if (signalName == nullptr) {
437 std::cerr << signalNum;
438 }
439 else {
440 std::cerr << signalName;
441 }
442 std::cerr << std::endl;
tylerliufeabfdc2020-10-03 15:09:58 -0700443 if (requesterState) {
444 Requester::endSession(*requesterState);
445 }
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700446 face.getIoService().stop();
tylerliufeabfdc2020-10-03 15:09:58 -0700447 exit(1);
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700448}
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800449
450int
451main(int argc, char* argv[])
452{
Zhiyi Zhangad9e04f2020-03-27 12:04:31 -0700453 boost::asio::signal_set terminateSignals(face.getIoService());
454 terminateSignals.add(SIGINT);
455 terminateSignals.add(SIGTERM);
456 terminateSignals.async_wait(handleSignal);
457
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800458 namespace po = boost::program_options;
459 std::string configFilePath = std::string(SYSCONFDIR) + "/ndncert/client.conf";
Zhiyi Zhang36706832019-07-04 21:33:03 -0700460 po::options_description description("General Usage\n ndncert-client [-h] [-c] [-v]\n");
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700461 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 -0800462 po::positional_options_description p;
463
464 po::variables_map vm;
465 try {
466 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
467 po::notify(vm);
468 }
469 catch (const std::exception& e) {
470 std::cerr << "ERROR: " << e.what() << std::endl;
471 return 1;
472 }
473 if (vm.count("help") != 0) {
474 std::cerr << description << std::endl;
475 return 0;
476 }
Zhiyi Zhang837406d2020-10-05 22:01:31 -0700477 selectCaProfile(configFilePath);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800478 face.processEvents();
479 return 0;
480}
481
Zhiyi Zhange4891b72020-10-10 15:11:57 -0700482} // namespace ndncert
483} // namespace ndn
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800484
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700485int
486main(int argc, char* argv[])
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800487{
488 return ndn::ndncert::main(argc, argv);
489}