blob: 502d9095c84c8211c56e8fadf88080d7f49cf9ec [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 Pesavento9faf34b2022-06-12 22:44:07 -04003 * Copyright (c) 2013-2022 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
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080028namespace ndn {
29namespace ndnsec {
Davide Pesavento9faf34b2022-06-12 22:44:07 -040030namespace {
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080031
Davide Pesavento9faf34b2022-06-12 22:44:07 -040032// https://en.wikipedia.org/wiki/Box_Drawing
33// https://git.altlinux.org/people/legion/packages/kbd.git?p=kbd.git;a=blob;f=data/consolefonts/README.eurlatgr
34static const char GLYPH_HORIZONTAL[] = "\u2500 "; // "─ "
35static const char GLYPH_VERTICAL[] = "\u2502 "; // "│ "
36static const char GLYPH_VERTICAL_AND_RIGHT[] = "\u251c\u2500"; // "├─"
37static const char GLYPH_UP_AND_RIGHT[] = "\u2514\u2500"; // "└─"
38static const char GLYPH_SPACE[] = " ";
39static const char GLYPH_STAR[] = "* ";
40
41enum class Verbosity {
42 IDENTITY = 0,
43 KEY = 1,
44 CERT_NAME = 2,
45 CERT_FULL = 3,
46};
47
48class TreePrinter
Yingdi Yu3e8b52e2014-11-26 22:05:00 -080049{
Alexander Afanasyev35109a12017-01-04 15:39:06 -080050public:
Davide Pesaventob310efb2019-04-11 22:10:24 -040051 explicit
Davide Pesavento9faf34b2022-06-12 22:44:07 -040052 TreePrinter(std::ostream& output)
53 : m_out(output)
Alexander Afanasyev35109a12017-01-04 15:39:06 -080054 {
Yingdi Yu3e8b52e2014-11-26 22:05:00 -080055 }
Yingdi Yu3e8b52e2014-11-26 22:05:00 -080056
Davide Pesavento9faf34b2022-06-12 22:44:07 -040057 template<typename C, typename F>
58 void
59 forEachChild(const C& container, F fn) const
60 {
61 m_branches.push_back(false);
62
63 auto end = container.end();
64 for (auto it = container.begin(); it != end; ++it) {
65 bool isLast = std::next(it) == end;
66 if (isLast) {
67 m_branches.back() = true;
68 }
69 printBranches(m_out);
70 fn(*it);
71 }
72
73 m_branches.pop_back();
74 }
75
76 std::string
77 getIndent() const
78 {
79 std::ostringstream oss;
80 printBranches(oss, true);
81 return oss.str();
82 }
83
84private:
85 void
86 printBranches(std::ostream& os, bool ignoreLast = false) const
87 {
88 for (size_t i = 0; i < m_branches.size(); ++i) {
89 if (i == m_branches.size() - 1 && !ignoreLast) {
90 os << (m_branches[i] ? GLYPH_UP_AND_RIGHT : GLYPH_VERTICAL_AND_RIGHT);
91 }
92 else {
93 os << (m_branches[i] ? GLYPH_SPACE : GLYPH_VERTICAL) << GLYPH_SPACE;
94 }
95 }
96 }
97
98protected:
99 std::ostream& m_out;
100
101private:
102 mutable std::vector<bool> m_branches;
103};
104
105class Printer : private TreePrinter
106{
107public:
108 explicit
109 Printer(std::ostream& output, Verbosity verbosity)
110 : TreePrinter(output)
111 , m_verbosity(verbosity)
112 {
113 }
114
115 void
116 printPib(const security::Pib& pib) const
117 {
118 m_out << pib.getPibLocator() << std::endl;
119
120 security::Identity defaultIdentity;
121 try {
122 defaultIdentity = pib.getDefaultIdentity();
123 }
124 catch (const security::Pib::Error&) {
125 // no default identity
126 }
127
128 forEachChild(pib.getIdentities(), [&] (const auto& identity) {
129 printIdentity(identity, identity == defaultIdentity);
130 });
131 }
132
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800133 void
Davide Pesaventob310efb2019-04-11 22:10:24 -0400134 printIdentity(const security::Identity& identity, bool isDefault) const
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800135 {
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400136 printDefault(isDefault);
137 m_out << identity.getName() << std::endl;
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800138
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400139 if (m_verbosity >= Verbosity::KEY) {
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800140 security::Key defaultKey;
141 try {
142 defaultKey = identity.getDefaultKey();
143 }
144 catch (const security::Pib::Error&) {
145 // no default key
146 }
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800147
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400148 forEachChild(identity.getKeys(), [&] (const auto& key) {
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800149 printKey(key, key == defaultKey);
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400150 });
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800151 }
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800152 }
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800153
154 void
Davide Pesaventob310efb2019-04-11 22:10:24 -0400155 printKey(const security::Key& key, bool isDefault) const
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800156 {
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400157 printDefault(isDefault);
158 m_out << key.getName() << std::endl;
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800159
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400160 if (m_verbosity >= Verbosity::CERT_NAME) {
Davide Pesaventof2cae612021-03-24 18:47:05 -0400161 security::Certificate defaultCert;
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800162 try {
163 defaultCert = key.getDefaultCertificate();
164 }
165 catch (const security::Pib::Error&) {
166 // no default certificate
167 }
168
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400169 forEachChild(key.getCertificates(), [&] (const auto& cert) {
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800170 printCertificate(cert, cert == defaultCert);
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400171 });
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800172 }
173 }
174
175 void
Davide Pesaventof2cae612021-03-24 18:47:05 -0400176 printCertificate(const security::Certificate& cert, bool isDefault) const
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800177 {
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400178 printDefault(isDefault);
179 m_out << cert.getName() << std::endl;
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800180
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400181 if (m_verbosity >= Verbosity::CERT_FULL) {
182 util::IndentedStream os(m_out, getIndent() + GLYPH_SPACE);
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800183 os << cert;
184 }
185 }
186
187private:
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400188 void
189 printDefault(bool isDefault) const
190 {
191 m_out << (isDefault ? GLYPH_STAR : GLYPH_HORIZONTAL);
192 }
193
194private:
195 Verbosity m_verbosity;
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800196};
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800197
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400198} // namespace
199
Yingdi Yub61f5402014-02-26 17:46:11 -0800200int
201ndnsec_list(int argc, char** argv)
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800202{
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800203 namespace po = boost::program_options;
204
Davide Pesaventob310efb2019-04-11 22:10:24 -0400205 bool wantKey = false;
206 bool wantCert = false;
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400207 auto verboseLevel = to_underlying(Verbosity::IDENTITY);
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800208
Davide Pesaventob310efb2019-04-11 22:10:24 -0400209 po::options_description description(
210 "Usage: ndnsec list [-h] [-k] [-c] [-v]\n"
211 "\n"
212 "Options");
213 description.add_options()
214 ("help,h", "produce help message")
215 ("key,k", po::bool_switch(&wantKey), "list all keys associated with each identity")
216 ("cert,c", po::bool_switch(&wantCert), "list all certificates associated with each key")
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400217 ("verbose,v", accumulator<std::underlying_type_t<Verbosity>>(&verboseLevel),
Davide Pesaventob310efb2019-04-11 22:10:24 -0400218 "verbose mode, can be repeated for increased verbosity: -v is equivalent to -k, "
219 "-vv is equivalent to -c, -vvv shows detailed information for each certificate")
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800220 ;
221
222 po::variables_map vm;
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800223 try {
Davide Pesaventob310efb2019-04-11 22:10:24 -0400224 po::store(po::parse_command_line(argc, argv, description), vm);
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800225 po::notify(vm);
226 }
227 catch (const std::exception& e) {
Davide Pesaventob310efb2019-04-11 22:10:24 -0400228 std::cerr << "ERROR: " << e.what() << "\n\n"
229 << description << std::endl;
230 return 2;
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800231 }
Yingdi Yub61f5402014-02-26 17:46:11 -0800232
Davide Pesaventob310efb2019-04-11 22:10:24 -0400233 if (vm.count("help") > 0) {
234 std::cout << description << std::endl;
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800235 return 0;
236 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800237
Davide Pesaventof2cae612021-03-24 18:47:05 -0400238 KeyChain keyChain;
Yingdi Yub61f5402014-02-26 17:46:11 -0800239
Davide Pesavento9faf34b2022-06-12 22:44:07 -0400240 auto verbosity = std::max(static_cast<Verbosity>(verboseLevel),
241 wantCert ? Verbosity::CERT_NAME :
242 wantKey ? Verbosity::KEY :
243 Verbosity::IDENTITY);
244 Printer printer(std::cout, verbosity);
245 printer.printPib(keyChain.getPib());
Yingdi Yub61f5402014-02-26 17:46:11 -0800246
Yingdi Yu3e8b52e2014-11-26 22:05:00 -0800247 return 0;
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800248}
249
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800250} // namespace ndnsec
251} // namespace ndn