blob: 1bdb2692d39885da4c1fd84c43cd4404c7dbbde9 [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/*
Tianyuan Yu42bc63e2024-10-18 10:18:38 -07003 * Copyright (c) 2017-2024, 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"
Davide Pesavento0dc02012021-11-23 22:55:03 -050022
Davide Pesaventod4496f72019-01-19 20:23:50 -050023#include <boost/asio/ip/tcp.hpp>
Davide Pesaventoa3dbb942023-09-16 22:30:35 -040024#include <boost/asio/signal_set.hpp>
Davide Pesaventod4496f72019-01-19 20:23:50 -050025#include <boost/program_options/options_description.hpp>
26#include <boost/program_options/parsers.hpp>
27#include <boost/program_options/variables_map.hpp>
Davide Pesavento0d1d11c2022-04-11 22:11:34 -040028
tylerliu3ad68122020-10-17 12:10:34 -070029#include <chrono>
Zhiyi Zhangaa60c962021-01-22 10:57:41 -080030#include <deque>
Davide Pesavento0d1d11c2022-04-11 22:11:34 -040031#include <iostream>
Davide Pesavento0dc02012021-11-23 22:55:03 -050032
Zhiyi Zhang74c61142020-10-07 21:00:49 -070033#include <ndn-cxx/face.hpp>
34#include <ndn-cxx/security/key-chain.hpp>
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080035
Davide Pesavento0d1d11c2022-04-11 22:11:34 -040036namespace ndncert::ca {
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080037
Davide Pesavento0dc02012021-11-23 22:55:03 -050038static ndn::Face face;
39static ndn::KeyChain keyChain;
Tianyuan Yu42bc63e2024-10-18 10:18:38 -070040static std::string repoHost;
Davide Pesavento0dc02012021-11-23 22:55:03 -050041static std::string repoPort = "7376";
Davide Pesaventof48e1632023-04-24 22:00:26 -040042constexpr size_t MAX_CACHED_CERT_NUM = 100;
Zhiyi Zhang74c61142020-10-07 21:00:49 -070043
44static bool
Davide Pesavento0d1d11c2022-04-11 22:11:34 -040045writeDataToRepo(const Data& data)
46{
Zhiyi Zhang74c61142020-10-07 21:00:49 -070047 boost::asio::ip::tcp::iostream requestStream;
Davide Pesaventof48e1632023-04-24 22:00:26 -040048 requestStream.expires_after(std::chrono::seconds(5));
Zhiyi Zhang74c61142020-10-07 21:00:49 -070049 requestStream.connect(repoHost, repoPort);
50 if (!requestStream) {
Tianyuan Yu42bc63e2024-10-18 10:18:38 -070051 std::cerr << "ERROR: Cannot publish the certificate to repo"
Zhiyi Zhang74c61142020-10-07 21:00:49 -070052 << " (" << requestStream.error().message() << ")" << std::endl;
53 return false;
54 }
Davide Pesaventof48e1632023-04-24 22:00:26 -040055 requestStream.write(reinterpret_cast<const char*>(data.wireEncode().data()),
Zhiyi Zhang74c61142020-10-07 21:00:49 -070056 data.wireEncode().size());
57 return true;
58}
Zhiyi Zhang90c75782020-10-06 15:04:03 -070059
60static void
61handleSignal(const boost::system::error_code& error, int signalNum)
62{
63 if (error) {
64 return;
65 }
66 const char* signalName = ::strsignal(signalNum);
67 std::cerr << "Exiting on signal ";
68 if (signalName == nullptr) {
69 std::cerr << signalNum;
70 }
71 else {
72 std::cerr << signalName;
73 }
74 std::cerr << std::endl;
Davide Pesavento3e481842023-11-11 18:01:32 -050075 face.getIoContext().stop();
Zhiyi Zhang90c75782020-10-06 15:04:03 -070076 exit(1);
77}
78
Davide Pesaventod4496f72019-01-19 20:23:50 -050079static int
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080080main(int argc, char* argv[])
81{
Davide Pesavento3e481842023-11-11 18:01:32 -050082 boost::asio::signal_set terminateSignals(face.getIoContext());
Zhiyi Zhang90c75782020-10-06 15:04:03 -070083 terminateSignals.add(SIGINT);
84 terminateSignals.add(SIGTERM);
85 terminateSignals.async_wait(handleSignal);
86
Zhiyi Zhang840afd92020-10-21 13:24:08 -070087 std::string configFilePath(NDNCERT_SYSCONFDIR "/ndncert/ca.conf");
Davide Pesaventod4496f72019-01-19 20:23:50 -050088 bool wantRepoOut = false;
Zhiyi Zhang343cdfb2018-01-17 12:04:28 -080089
90 namespace po = boost::program_options;
Davide Pesaventod4496f72019-01-19 20:23:50 -050091 po::options_description optsDesc("Options");
92 optsDesc.add_options()
Zhiyi Zhang74c61142020-10-07 21:00:49 -070093 ("help,h", "print this help message and exit")
94 ("config-file,c", po::value<std::string>(&configFilePath)->default_value(configFilePath), "path to configuration file")
Tianyuan Yu42bc63e2024-10-18 10:18:38 -070095 ("repo-host,H", po::value<std::string>(&repoHost)->default_value(repoHost),
96 "repo host (if empty or unspecified, issued certificates will not be published to a repo)")
97 ("repo-port,P", po::value<std::string>(&repoPort)->default_value(repoPort), "repo port");
Zhiyi Zhang343cdfb2018-01-17 12:04:28 -080098
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080099 po::variables_map vm;
100 try {
Davide Pesaventod4496f72019-01-19 20:23:50 -0500101 po::store(po::parse_command_line(argc, argv, optsDesc), vm);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800102 po::notify(vm);
103 }
Davide Pesaventod4496f72019-01-19 20:23:50 -0500104 catch (const po::error& e) {
105 std::cerr << "ERROR: " << e.what() << std::endl;
106 return 2;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800107 }
Davide Pesaventod4496f72019-01-19 20:23:50 -0500108 catch (const boost::bad_any_cast& e) {
109 std::cerr << "ERROR: " << e.what() << std::endl;
110 return 2;
111 }
112
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800113 if (vm.count("help") != 0) {
Davide Pesaventod4496f72019-01-19 20:23:50 -0500114 std::cout << "Usage: " << argv[0] << " [options]\n"
115 << "\n"
116 << optsDesc;
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800117 return 0;
118 }
119
Tianyuan Yu42bc63e2024-10-18 10:18:38 -0700120 if (!repoHost.empty()) {
121 wantRepoOut = true;
122 }
123
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800124 CaModule ca(face, keyChain, configFilePath);
Zhiyi Zhangaa60c962021-01-22 10:57:41 -0800125 std::deque<Data> cachedCertificates;
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700126 auto profileData = ca.getCaProfileData();
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800127
Davide Pesaventod4496f72019-01-19 20:23:50 -0500128 if (wantRepoOut) {
Zhiyi Zhang696cd042020-10-07 21:27:36 -0700129 writeDataToRepo(profileData);
Zhiyi Zhang32d4b4e2020-10-28 22:10:49 -0700130 ca.setStatusUpdateCallback([&](const RequestState& request) {
tylerliu7b9185c2020-11-24 12:15:18 -0800131 if (request.status == Status::SUCCESS && request.requestType == RequestType::NEW) {
132 writeDataToRepo(request.cert);
Zhiyi Zhang74c61142020-10-07 21:00:49 -0700133 }
134 });
Zhiyi Zhang343cdfb2018-01-17 12:04:28 -0800135 }
Zhiyi Zhangd1d9f5a2020-10-05 18:04:23 -0700136 else {
Zhiyi Zhang32d4b4e2020-10-28 22:10:49 -0700137 ca.setStatusUpdateCallback([&](const RequestState& request) {
tylerliu7b9185c2020-11-24 12:15:18 -0800138 if (request.status == Status::SUCCESS && request.requestType == RequestType::NEW) {
Zhiyi Zhangaa60c962021-01-22 10:57:41 -0800139 cachedCertificates.push_front(request.cert);
140 if (cachedCertificates.size() > MAX_CACHED_CERT_NUM) {
141 cachedCertificates.pop_back();
142 }
Zhiyi Zhangb420e262020-10-05 20:34:54 -0700143 }
144 });
145 face.setInterestFilter(
Davide Pesavento0dc02012021-11-23 22:55:03 -0500146 ndn::InterestFilter(ca.getCaConf().caProfile.caPrefix),
147 [&](const auto&, const auto& interest) {
Zhiyi Zhangaa60c962021-01-22 10:57:41 -0800148 const auto& interestName = interest.getName();
149 if (interestName.isPrefixOf(profileData.getName())) {
150 face.put(profileData);
151 return;
152 }
153 for (const auto& item : cachedCertificates) {
Zhiyi Zhangd35bc5f2021-01-22 17:02:41 -0800154 if (interestName.isPrefixOf(item.getFullName())) {
Zhiyi Zhangaa60c962021-01-22 10:57:41 -0800155 face.put(item);
156 return;
157 }
Zhiyi Zhangb420e262020-10-05 20:34:54 -0700158 }
Zhiyi Zhangb420e262020-10-05 20:34:54 -0700159 });
Zhiyi Zhangd1d9f5a2020-10-05 18:04:23 -0700160 }
Zhiyi Zhang343cdfb2018-01-17 12:04:28 -0800161
Zhiyi Zhang1c0bd372017-12-18 18:32:55 +0800162 face.processEvents();
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800163 return 0;
164}
165
Davide Pesavento0d1d11c2022-04-11 22:11:34 -0400166} // namespace ndncert::ca
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800167
168int
169main(int argc, char* argv[])
170{
Davide Pesavento0dc02012021-11-23 22:55:03 -0500171 return ndncert::ca::main(argc, argv);
Zhiyi Zhang08e0e982017-03-01 10:10:42 -0800172}