blob: c2b20c86c344fbc806039e2f1c0ed4bc8853da8f [file] [log] [blame]
Yingdi Yu5edf97d2014-06-15 11:35:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyevaf99f462015-01-19 21:43:09 -08003 * Copyright (c) 2013-2015 Regents of the University of California.
Yingdi Yu5edf97d2014-06-15 11:35:12 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * 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.
20 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
22 */
23
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -080024#ifndef NDN_TOOLS_NDNSEC_CERT_REVOKE_HPP
25#define NDN_TOOLS_NDNSEC_CERT_REVOKE_HPP
Yingdi Yu5edf97d2014-06-15 11:35:12 -070026
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -080027#include "util.hpp"
Yingdi Yu5edf97d2014-06-15 11:35:12 -070028
29int
30ndnsec_cert_revoke(int argc, char** argv)
31{
32 using namespace ndn;
33 namespace po = boost::program_options;
34
Alexander Afanasyev7438a152014-10-15 18:34:43 -070035 KeyChain keyChain;
Yingdi Yu5edf97d2014-06-15 11:35:12 -070036
Alexander Afanasyev7438a152014-10-15 18:34:43 -070037 std::string requestFile("-");
38 Name signId = keyChain.getDefaultIdentity();
39 bool hasSignId = false;
40 Name certPrefix = KeyChain::DEFAULT_PREFIX;
41
42 po::options_description description("General Usage\n ndnsec cert-revoke [-h] request\n"
43 "General options");
Yingdi Yu5edf97d2014-06-15 11:35:12 -070044 description.add_options()
45 ("help,h", "produce help message")
Alexander Afanasyev7438a152014-10-15 18:34:43 -070046 ("sign-id,s", po::value<Name>(&signId),
47 "signing identity (default: use the same as in the revoked certificate)")
48 ("cert-prefix,p", po::value<Name>(&certPrefix),
49 "cert prefix, which is the part of certificate name before "
50 "KEY component (default: use the same as in the revoked certificate)")
51 ("request,r", po::value<std::string>(&requestFile)->default_value("-"),
52 "request file name, - for stdin")
Yingdi Yu5edf97d2014-06-15 11:35:12 -070053 ;
54
55 po::positional_options_description p;
56 p.add("request", 1);
57
58 po::variables_map vm;
59 try
60 {
61 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
62 vm);
63 po::notify(vm);
64 }
65 catch (const std::exception& e)
66 {
67 std::cerr << "ERROR: " << e.what() << std::endl;
68 return 1;
69 }
70
71 if (vm.count("help") != 0)
72 {
73 std::cerr << description << std::endl;
74 return 0;
75 }
76
Alexander Afanasyev7438a152014-10-15 18:34:43 -070077 hasSignId = (vm.count("sign-id") != 0);
78
Yingdi Yu5edf97d2014-06-15 11:35:12 -070079 if (vm.count("request") == 0)
80 {
81 std::cerr << "request file must be specified" << std::endl;
82 return 1;
83 }
84
85 shared_ptr<IdentityCertificate> revokedCertificate
86 = getIdentityCertificate(requestFile);
87
88 if (!static_cast<bool>(revokedCertificate))
89 {
90 std::cerr << "ERROR: input error" << std::endl;
91 return 1;
92 }
93
Yingdi Yu5edf97d2014-06-15 11:35:12 -070094 Block wire;
95
96 try
97 {
Alexander Afanasyev7438a152014-10-15 18:34:43 -070098 Name keyName;
99
100 if (hasSignId) {
101 keyName = keyChain.getDefaultKeyNameForIdentity(signId);
102 }
103 else {
104 const Signature& signature = revokedCertificate->getSignature();
105 if (!signature.hasKeyLocator() ||
106 signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name)
107 {
108 std::cerr << "ERROR: Invalid certificate to revoke" << std::endl;
109 return 1;
110 }
111
112 keyName = IdentityCertificate::certificateNameToPublicKeyName(
113 signature.getKeyLocator().getName());
114 }
115
116 Name certName;
117 if (certPrefix == KeyChain::DEFAULT_PREFIX) {
118 certName = revokedCertificate->getName().getPrefix(-1);
119 }
120 else {
121 Name revokedKeyName = revokedCertificate->getPublicKeyName();
122
123 if (certPrefix.isPrefixOf(revokedKeyName) && certPrefix != revokedKeyName) {
124 certName.append(certPrefix)
125 .append("KEY")
126 .append(revokedKeyName.getSubName(certPrefix.size()))
127 .append("ID-CERT");
128 }
129 else {
130 std::cerr << "ERROR: certificate prefix does not match the revoked certificate"
131 << std::endl;
132 return 1;
133 }
134 }
135 certName
136 .appendVersion()
137 .append("REVOKED");
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700138
139 Data revocationCert;
140 revocationCert.setName(certName);
141
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700142 if (keyChain.doesPublicKeyExist(keyName))
143 {
144 Name signingCertificateName = keyChain.getDefaultCertificateNameForKey(keyName);
Yingdi Yu1b0311c2015-06-10 14:58:47 -0700145 keyChain.sign(revocationCert,
146 security::SigningInfo(security::SigningInfo::SIGNER_TYPE_CERT,
147 signingCertificateName));
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700148 }
149 else
150 {
151 std::cerr << "ERROR: Cannot find the signing key!" << std::endl;
152 return 1;
153 }
154
155 wire = revocationCert.wireEncode();
156 }
157 catch (Signature::Error& e)
158 {
159 std::cerr << "ERROR: No valid signature!" << std::endl;
160 return 1;
161 }
162 catch (KeyLocator::Error& e)
163 {
164 std::cerr << "ERROR: No valid KeyLocator!" << std::endl;
165 return 1;
166 }
167 catch (IdentityCertificate::Error& e)
168 {
169 std::cerr << "ERROR: Cannot determine the signing key!" << std::endl;
170 return 1;
171 }
Alexander Afanasyev7438a152014-10-15 18:34:43 -0700172 catch (SecPublicInfo::Error& e)
173 {
174 std::cerr << "ERROR: Incomplete or corrupted PIB (" << e.what() << ")" << std::endl;
175 return 1;
176 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700177
178 try
179 {
180 using namespace CryptoPP;
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700181 StringSource ss(wire.wire(), wire.size(), true,
Alexander Afanasyev7438a152014-10-15 18:34:43 -0700182 new Base64Encoder(new FileSink(std::cout), true, 64));
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700183 }
184 catch (const CryptoPP::Exception& e)
185 {
186 std::cerr << "ERROR: " << e.what() << std::endl;
187 return 1;
188 }
189
190 return 0;
191}
192
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -0800193#endif // NDN_TOOLS_NDNSEC_CERT_REVOKE_HPP