blob: 3b02b80730dfda59dd4d87f2caeec0bbb76bdcee [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi5759be32017-10-15 00:00:52 +00002/*
Davide Pesavento47ce2ee2023-05-09 01:33:33 -04003 * Copyright (c) 2013-2023 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library 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 Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Yingdi Yu8d7468f2014-02-21 14:49:45 -080020 */
21
Davide Pesavento25d4f1c2020-04-29 23:31:04 -040022#include "accumulator.hpp"
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080023#include "ndnsec.hpp"
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -080024#include "util.hpp"
Davide Pesavento19442812018-11-23 14:00:04 -050025
Davide Pesavento7e780642018-11-24 15:51:34 -050026#include "ndn-cxx/util/indented-stream.hpp"
Yingdi Yu8d7468f2014-02-21 14:49:45 -080027
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040028namespace ndn::ndnsec {
Davide Pesavento9faf34b2022-06-12 22:44:07 -040029namespace {
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080030
Davide Pesavento9faf34b2022-06-12 22:44:07 -040031// https://en.wikipedia.org/wiki/Box_Drawing
32// https://git.altlinux.org/people/legion/packages/kbd.git?p=kbd.git;a=blob;f=data/consolefonts/README.eurlatgr
33static const char GLYPH_HORIZONTAL[] = "\u2500 "; // "─ "
34static const char GLYPH_VERTICAL[] = "\u2502 "; // "│ "
35static const char GLYPH_VERTICAL_AND_RIGHT[] = "\u251c\u2500"; // "├─"
36static const char GLYPH_UP_AND_RIGHT[] = "\u2514\u2500"; // "└─"
37static const char GLYPH_SPACE[] = " ";
38static const char GLYPH_STAR[] = "* ";
39
40enum class Verbosity {
41 IDENTITY = 0,
42 KEY = 1,
43 CERT_NAME = 2,
44 CERT_FULL = 3,
45};
46
47class TreePrinter
Yingdi Yu3e8b52e2014-11-26 22:05:00 -080048{
Alexander Afanasyev35109a12017-01-04 15:39:06 -080049public:
Davide Pesaventob310efb2019-04-11 22:10:24 -040050 explicit
Davide Pesavento9faf34b2022-06-12 22:44:07 -040051 TreePrinter(std::ostream& output)
52 : m_out(output)
Alexander Afanasyev35109a12017-01-04 15:39:06 -080053 {
Yingdi Yu3e8b52e2014-11-26 22:05:00 -080054 }
Yingdi Yu3e8b52e2014-11-26 22:05:00 -080055
Davide Pesavento9faf34b2022-06-12 22:44:07 -040056 template<typename C, typename F>
57 void
58 forEachChild(const C& container, F fn) const
59 {
60 m_branches.push_back(false);
61
62 auto end = container.end();
63 for (auto it = container.begin(); it != end; ++it) {
64 bool isLast = std::next(it) == end;
65 if (isLast) {
66 m_branches.back() = true;
67 }
68 printBranches(m_out);
69 fn(*it);
70 }
71
72 m_branches.pop_back();
73 }
74
75 std::string
76 getIndent() const
77 {
78 std::ostringstream oss;
79 printBranches(oss, true);
80 return oss.str();
81 }
82
83private:
84 void
85 printBranches(std::ostream& os, bool ignoreLast = false) const
86 {
87 for (size_t i = 0; i < m_branches.size(); ++i) {
88 if (i == m_branches.size() - 1 && !ignoreLast) {
89 os << (m_branches[i] ? GLYPH_UP_AND_RIGHT : GLYPH_VERTICAL_AND_RIGHT);
90 }
91 else {
92 os << (m_branches[i] ? GLYPH_SPACE : GLYPH_VERTICAL) << GLYPH_SPACE;
93 }
94 }
95 }
96
97protected:
98 std::ostream& m_out;
99
100private:
101 mutable std::vector<bool> m_branches;
102};
103
104class Printer : private TreePrinter
105{
106public:
107 explicit
108 Printer(std::ostream& output, Verbosity verbosity)
109 : TreePrinter(output)
110 , m_verbosity(verbosity)
111 {
112 }
113
114 void
115 printPib(const security::Pib& pib) const
116 {
117 m_out << pib.getPibLocator() << std::endl;
118
119 security::Identity defaultIdentity;
120 try {
121 defaultIdentity = pib.getDefaultIdentity();
122 }
123 catch (const security::Pib::Error&) {
124 // no default identity
125 }
126
127 forEachChild(pib.getIdentities(), [&] (const auto& identity) {
128 printIdentity(identity, identity == defaultIdentity);
129 });
130 }
131
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800132 void
Davide Pesaventob310efb2019-04-11 22:10:24 -0400133 printIdentity(const security::Identity& identity, bool isDefault) const
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800134 {
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400135 printDefault(isDefault);
136 m_out << identity.getName() << std::endl;
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800137
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400138 if (m_verbosity >= Verbosity::KEY) {
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800139 security::Key defaultKey;
140 try {
141 defaultKey = identity.getDefaultKey();
142 }
143 catch (const security::Pib::Error&) {
144 // no default key
145 }
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800146
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400147 forEachChild(identity.getKeys(), [&] (const auto& key) {
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800148 printKey(key, key == defaultKey);
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400149 });
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800150 }
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800151 }
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800152
153 void
Davide Pesaventob310efb2019-04-11 22:10:24 -0400154 printKey(const security::Key& key, bool isDefault) const
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800155 {
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400156 printDefault(isDefault);
157 m_out << key.getName() << std::endl;
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800158
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400159 if (m_verbosity >= Verbosity::CERT_NAME) {
Davide Pesaventof2cae612021-03-24 18:47:05 -0400160 security::Certificate defaultCert;
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800161 try {
162 defaultCert = key.getDefaultCertificate();
163 }
164 catch (const security::Pib::Error&) {
165 // no default certificate
166 }
167
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400168 forEachChild(key.getCertificates(), [&] (const auto& cert) {
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800169 printCertificate(cert, cert == defaultCert);
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400170 });
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800171 }
172 }
173
174 void
Davide Pesaventof2cae612021-03-24 18:47:05 -0400175 printCertificate(const security::Certificate& cert, bool isDefault) const
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800176 {
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400177 printDefault(isDefault);
178 m_out << cert.getName() << std::endl;
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800179
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400180 if (m_verbosity >= Verbosity::CERT_FULL) {
181 util::IndentedStream os(m_out, getIndent() + GLYPH_SPACE);
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800182 os << cert;
183 }
184 }
185
186private:
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400187 void
188 printDefault(bool isDefault) const
189 {
190 m_out << (isDefault ? GLYPH_STAR : GLYPH_HORIZONTAL);
191 }
192
193private:
194 Verbosity m_verbosity;
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800195};
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800196
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400197} // namespace
198
Yingdi Yub61f5402014-02-26 17:46:11 -0800199int
200ndnsec_list(int argc, char** argv)
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800201{
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800202 namespace po = boost::program_options;
203
Davide Pesaventob310efb2019-04-11 22:10:24 -0400204 bool wantKey = false;
205 bool wantCert = false;
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400206 auto verboseLevel = to_underlying(Verbosity::IDENTITY);
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800207
Davide Pesaventob310efb2019-04-11 22:10:24 -0400208 po::options_description description(
209 "Usage: ndnsec list [-h] [-k] [-c] [-v]\n"
210 "\n"
211 "Options");
212 description.add_options()
213 ("help,h", "produce help message")
214 ("key,k", po::bool_switch(&wantKey), "list all keys associated with each identity")
215 ("cert,c", po::bool_switch(&wantCert), "list all certificates associated with each key")
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400216 ("verbose,v", accumulator<std::underlying_type_t<Verbosity>>(&verboseLevel),
Davide Pesaventob310efb2019-04-11 22:10:24 -0400217 "verbose mode, can be repeated for increased verbosity: -v is equivalent to -k, "
218 "-vv is equivalent to -c, -vvv shows detailed information for each certificate")
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800219 ;
220
221 po::variables_map vm;
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800222 try {
Davide Pesaventob310efb2019-04-11 22:10:24 -0400223 po::store(po::parse_command_line(argc, argv, description), vm);
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800224 po::notify(vm);
225 }
226 catch (const std::exception& e) {
Davide Pesaventob310efb2019-04-11 22:10:24 -0400227 std::cerr << "ERROR: " << e.what() << "\n\n"
228 << description << std::endl;
229 return 2;
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800230 }
Yingdi Yub61f5402014-02-26 17:46:11 -0800231
Davide Pesaventob310efb2019-04-11 22:10:24 -0400232 if (vm.count("help") > 0) {
233 std::cout << description << std::endl;
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800234 return 0;
235 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800236
Davide Pesaventof2cae612021-03-24 18:47:05 -0400237 KeyChain keyChain;
Yingdi Yub61f5402014-02-26 17:46:11 -0800238
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400239 auto verbosity = std::max(static_cast<Verbosity>(verboseLevel),
240 wantCert ? Verbosity::CERT_NAME :
241 wantKey ? Verbosity::KEY :
242 Verbosity::IDENTITY);
243 Printer printer(std::cout, verbosity);
244 printer.printPib(keyChain.getPib());
Yingdi Yub61f5402014-02-26 17:46:11 -0800245
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800246 return 0;
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800247}
248
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400249} // namespace ndn::ndnsec