blob: 169aa1a4b18513fcf12636d64ba5c705e16ce4c3 [file] [log] [blame]
Zhiyi Zhang08e0e982017-03-01 10:10:42 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventod4496f72019-01-19 20:23:50 -05002/*
Alexander Afanasyev7838cfd2020-06-03 14:16:43 -04003 * 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
21#include "ca-module.hpp"
Zhiyi Zhang90c75782020-10-06 15:04:03 -070022#include <boost/asio.hpp>
Davide Pesaventod4496f72019-01-19 20:23:50 -050023#include <boost/asio/ip/tcp.hpp>
Davide Pesaventod4496f72019-01-19 20:23:50 -050024#include <boost/program_options/options_description.hpp>
25#include <boost/program_options/parsers.hpp>
26#include <boost/program_options/variables_map.hpp>
Davide Pesaventod4496f72019-01-19 20:23:50 -050027#include <iostream>
tylerliu3ad68122020-10-17 12:10:34 -070028#include <chrono>
Zhiyi Zhang74c61142020-10-07 21:00:49 -070029#include <ndn-cxx/face.hpp>
30#include <ndn-cxx/security/key-chain.hpp>
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080031
32namespace ndn {
33namespace ndncert {
34
Zhiyi Zhang90c75782020-10-06 15:04:03 -070035Face face;
tylerliua7bea662020-10-08 18:51:02 -070036security::KeyChain keyChain;
Zhiyi Zhang74c61142020-10-07 21:00:49 -070037std::string repoHost = "localhost";
38std::string repoPort = "7376";
39
40static bool
41writeDataToRepo(const Data& data) {
42 boost::asio::ip::tcp::iostream requestStream;
tylerliu01e59632020-10-17 12:15:02 -070043#if BOOST_VERSION >= 106700
tylerliu9ea1f762020-10-17 11:53:36 -070044 requestStream.expires_after(std::chrono::seconds(3));
45#else
tylerliu01e59632020-10-17 12:15:02 -070046 requestStream.expires_from_now(boost::posix_time::seconds(3));
47#endif //BOOST_VERSION >= 106700
Zhiyi Zhang74c61142020-10-07 21:00:49 -070048 requestStream.connect(repoHost, repoPort);
49 if (!requestStream) {
50 std::cerr << "ERROR: Cannot publish certificate to repo-ng"
51 << " (" << requestStream.error().message() << ")" << std::endl;
52 return false;
53 }
54 requestStream.write(reinterpret_cast<const char*>(data.wireEncode().wire()),
55 data.wireEncode().size());
56 return true;
57}
Zhiyi Zhang90c75782020-10-06 15:04:03 -070058
59static void
60handleSignal(const boost::system::error_code& error, int signalNum)
61{
62 if (error) {
63 return;
64 }
65 const char* signalName = ::strsignal(signalNum);
66 std::cerr << "Exiting on signal ";
67 if (signalName == nullptr) {
68 std::cerr << signalNum;
69 }
70 else {
71 std::cerr << signalName;
72 }
73 std::cerr << std::endl;
74 face.getIoService().stop();
75 exit(1);
76}
77
Davide Pesaventod4496f72019-01-19 20:23:50 -050078static int
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080079main(int argc, char* argv[])
80{
Zhiyi Zhang90c75782020-10-06 15:04:03 -070081 boost::asio::signal_set terminateSignals(face.getIoService());
82 terminateSignals.add(SIGINT);
83 terminateSignals.add(SIGTERM);
84 terminateSignals.async_wait(handleSignal);
85
Davide Pesaventod4496f72019-01-19 20:23:50 -050086 std::string configFilePath(SYSCONFDIR "/ndncert/ca.conf");
Davide Pesaventod4496f72019-01-19 20:23:50 -050087 bool wantRepoOut = false;
Zhiyi Zhang343cdfb2018-01-17 12:04:28 -080088
89 namespace po = boost::program_options;
Davide Pesaventod4496f72019-01-19 20:23:50 -050090 po::options_description optsDesc("Options");
91 optsDesc.add_options()
Zhiyi Zhang74c61142020-10-07 21:00:49 -070092 ("help,h", "print this help message and exit")
93 ("config-file,c", po::value<std::string>(&configFilePath)->default_value(configFilePath), "path to configuration file")
94 ("repo-output,r", po::bool_switch(&wantRepoOut), "when enabled, all issued certificates will be published to repo-ng")
95 ("repo-host,H", po::value<std::string>(&repoHost)->default_value(repoHost), "repo-ng host")
96 ("repo-port,P", po::value<std::string>(&repoPort)->default_value(repoPort), "repo-ng port");
Zhiyi Zhang343cdfb2018-01-17 12:04:28 -080097
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080098 po::variables_map vm;
99 try {
Davide Pesaventod4496f72019-01-19 20:23:50 -0500100 po::store(po::parse_command_line(argc, argv, optsDesc), vm);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800101 po::notify(vm);
102 }
Davide Pesaventod4496f72019-01-19 20:23:50 -0500103 catch (const po::error& e) {
104 std::cerr << "ERROR: " << e.what() << std::endl;
105 return 2;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800106 }
Davide Pesaventod4496f72019-01-19 20:23:50 -0500107 catch (const boost::bad_any_cast& e) {
108 std::cerr << "ERROR: " << e.what() << std::endl;
109 return 2;
110 }
111
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800112 if (vm.count("help") != 0) {
Davide Pesaventod4496f72019-01-19 20:23:50 -0500113 std::cout << "Usage: " << argv[0] << " [options]\n"
114 << "\n"
115 << optsDesc;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800116 return 0;
117 }
118
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800119 CaModule ca(face, keyChain, configFilePath);
Zhiyi Zhang74c61142020-10-07 21:00:49 -0700120 std::map<Name, Data> cachedCertificates;
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700121 auto profileData = ca.getCaProfileData();
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800122
Davide Pesaventod4496f72019-01-19 20:23:50 -0500123 if (wantRepoOut) {
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700124 writeDataToRepo(profileData);
Zhiyi Zhang74c61142020-10-07 21:00:49 -0700125 ca.setStatusUpdateCallback([&](const CaState& request) {
tylerliu335e5222020-10-09 11:32:40 -0700126 if (request.m_status == Status::SUCCESS && request.m_requestType == RequestType::NEW) {
Zhiyi Zhang74c61142020-10-07 21:00:49 -0700127 writeDataToRepo(request.m_cert);
128 }
129 });
Zhiyi Zhang343cdfb2018-01-17 12:04:28 -0800130 }
Zhiyi Zhangd1d9f5a2020-10-05 18:04:23 -0700131 else {
Zhiyi Zhangb420e262020-10-05 20:34:54 -0700132 ca.setStatusUpdateCallback([&](const CaState& request) {
tylerliu335e5222020-10-09 11:32:40 -0700133 if (request.m_status == Status::SUCCESS && request.m_requestType == RequestType::NEW) {
Zhiyi Zhangb420e262020-10-05 20:34:54 -0700134 cachedCertificates[request.m_cert.getName()] = request.m_cert;
135 }
136 });
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700137 cachedCertificates[profileData.getName()] = profileData;
Zhiyi Zhangb420e262020-10-05 20:34:54 -0700138 face.setInterestFilter(
139 InterestFilter(ca.getCaConf().m_caItem.m_caPrefix),
140 [&](const InterestFilter&, const Interest& interest) {
141 auto search = cachedCertificates.find(interest.getName());
142 if (search != cachedCertificates.end()) {
143 face.put(search->second);
144 }
145 },
146 [](const Name&, const std::string& errorInfo) {
147 std::cerr << "ERROR: " << errorInfo << std::endl;
148 });
Zhiyi Zhangd1d9f5a2020-10-05 18:04:23 -0700149 }
Zhiyi Zhang343cdfb2018-01-17 12:04:28 -0800150
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800151 face.processEvents();
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800152 return 0;
153}
154
Zhiyi Zhange4891b72020-10-10 15:11:57 -0700155} // namespace ndncert
156} // namespace ndn
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800157
158int
159main(int argc, char* argv[])
160{
161 return ndn::ndncert::main(argc, argv);
162}