blob: 29b73c300f07f6ff5e81cb70de699453e2aec311 [file] [log] [blame]
Yingdi Yu5edf97d2014-06-15 11:35:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2014 Regents of the University of California.
4 *
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
24#ifndef NDNSEC_CERT_REVOKE_HPP
25#define NDNSEC_CERT_REVOKE_HPP
26
27#include "ndnsec-util.hpp"
28
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);
145 keyChain.sign(revocationCert, signingCertificateName);
146 }
147 else
148 {
149 std::cerr << "ERROR: Cannot find the signing key!" << std::endl;
150 return 1;
151 }
152
153 wire = revocationCert.wireEncode();
154 }
155 catch (Signature::Error& e)
156 {
157 std::cerr << "ERROR: No valid signature!" << std::endl;
158 return 1;
159 }
160 catch (KeyLocator::Error& e)
161 {
162 std::cerr << "ERROR: No valid KeyLocator!" << std::endl;
163 return 1;
164 }
165 catch (IdentityCertificate::Error& e)
166 {
167 std::cerr << "ERROR: Cannot determine the signing key!" << std::endl;
168 return 1;
169 }
Alexander Afanasyev7438a152014-10-15 18:34:43 -0700170 catch (SecPublicInfo::Error& e)
171 {
172 std::cerr << "ERROR: Incomplete or corrupted PIB (" << e.what() << ")" << std::endl;
173 return 1;
174 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700175
176 try
177 {
178 using namespace CryptoPP;
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700179 StringSource ss(wire.wire(), wire.size(), true,
Alexander Afanasyev7438a152014-10-15 18:34:43 -0700180 new Base64Encoder(new FileSink(std::cout), true, 64));
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700181 }
182 catch (const CryptoPP::Exception& e)
183 {
184 std::cerr << "ERROR: " << e.what() << std::endl;
185 return 1;
186 }
187
188 return 0;
189}
190
191#endif //NDNSEC_CERT_REVOKE_HPP