blob: 6aa8d02d95d2ef6a3b8392885132008615db5361 [file] [log] [blame]
Yingdi Yu5edf97d2014-06-15 11:35:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev2fa59392016-07-29 17:24:23 -07003 * Copyright (c) 2013-2016 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;
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070033 using namespace ndn::security;
Yingdi Yu5edf97d2014-06-15 11:35:12 -070034 namespace po = boost::program_options;
35
Alexander Afanasyev7438a152014-10-15 18:34:43 -070036 KeyChain keyChain;
Yingdi Yu5edf97d2014-06-15 11:35:12 -070037
Alexander Afanasyev7438a152014-10-15 18:34:43 -070038 std::string requestFile("-");
39 Name signId = keyChain.getDefaultIdentity();
40 bool hasSignId = false;
41 Name certPrefix = KeyChain::DEFAULT_PREFIX;
42
43 po::options_description description("General Usage\n ndnsec cert-revoke [-h] request\n"
44 "General options");
Yingdi Yu5edf97d2014-06-15 11:35:12 -070045 description.add_options()
46 ("help,h", "produce help message")
Alexander Afanasyev7438a152014-10-15 18:34:43 -070047 ("sign-id,s", po::value<Name>(&signId),
48 "signing identity (default: use the same as in the revoked certificate)")
49 ("cert-prefix,p", po::value<Name>(&certPrefix),
50 "cert prefix, which is the part of certificate name before "
51 "KEY component (default: use the same as in the revoked certificate)")
52 ("request,r", po::value<std::string>(&requestFile)->default_value("-"),
53 "request file name, - for stdin")
Yingdi Yu5edf97d2014-06-15 11:35:12 -070054 ;
55
56 po::positional_options_description p;
57 p.add("request", 1);
58
59 po::variables_map vm;
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070060 try {
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 std::cerr << "ERROR: " << e.what() << std::endl;
67 return 1;
68 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -070069
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070070 if (vm.count("help") != 0) {
71 std::cerr << description << std::endl;
72 return 0;
73 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -070074
Alexander Afanasyev7438a152014-10-15 18:34:43 -070075 hasSignId = (vm.count("sign-id") != 0);
76
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070077 if (vm.count("request") == 0) {
78 std::cerr << "request file must be specified" << std::endl;
79 return 1;
80 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -070081
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070082 shared_ptr<v1::IdentityCertificate> revokedCertificate = getIdentityCertificate(requestFile);
Yingdi Yu5edf97d2014-06-15 11:35:12 -070083
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070084 if (!static_cast<bool>(revokedCertificate)) {
85 std::cerr << "ERROR: input error" << std::endl;
86 return 1;
87 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -070088
Yingdi Yu5edf97d2014-06-15 11:35:12 -070089 Block wire;
90
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070091 try {
92 Name keyName;
Alexander Afanasyev7438a152014-10-15 18:34:43 -070093
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070094 if (hasSignId) {
95 keyName = keyChain.getDefaultKeyNameForIdentity(signId);
96 }
97 else {
98 const Signature& signature = revokedCertificate->getSignature();
99 if (!signature.hasKeyLocator() ||
100 signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name)
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700101 {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700102 std::cerr << "ERROR: Invalid certificate to revoke" << std::endl;
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700103 return 1;
104 }
105
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700106 keyName = v1::IdentityCertificate::certificateNameToPublicKeyName(
107 signature.getKeyLocator().getName());
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700108 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700109
110 Name certName;
111 if (certPrefix == KeyChain::DEFAULT_PREFIX) {
112 certName = revokedCertificate->getName().getPrefix(-1);
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700113 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700114 else {
115 Name revokedKeyName = revokedCertificate->getPublicKeyName();
116
117 if (certPrefix.isPrefixOf(revokedKeyName) && certPrefix != revokedKeyName) {
118 certName.append(certPrefix)
119 .append("KEY")
120 .append(revokedKeyName.getSubName(certPrefix.size()))
121 .append("ID-CERT");
122 }
123 else {
124 std::cerr << "ERROR: certificate prefix does not match the revoked certificate"
125 << std::endl;
126 return 1;
127 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700128 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700129 certName
130 .appendVersion()
131 .append("REVOKED");
132
133 Data revocationCert;
134 revocationCert.setName(certName);
135
136 if (keyChain.doesPublicKeyExist(keyName)) {
137 Name signingCertificateName = keyChain.getDefaultCertificateNameForKey(keyName);
138 keyChain.sign(revocationCert,
139 SigningInfo(SigningInfo::SIGNER_TYPE_CERT, signingCertificateName));
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700140 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700141 else {
142 std::cerr << "ERROR: Cannot find the signing key!" << std::endl;
Alexander Afanasyev7438a152014-10-15 18:34:43 -0700143 return 1;
144 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700145
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700146 wire = revocationCert.wireEncode();
147 }
148 catch (const Signature::Error& e) {
149 std::cerr << "ERROR: No valid signature!" << std::endl;
150 return 1;
151 }
152 catch (const KeyLocator::Error& e) {
153 std::cerr << "ERROR: No valid KeyLocator!" << std::endl;
154 return 1;
155 }
156 catch (const v1::IdentityCertificate::Error& e) {
157 std::cerr << "ERROR: Cannot determine the signing key!" << std::endl;
158 return 1;
159 }
160 catch (const SecPublicInfo::Error& e) {
161 std::cerr << "ERROR: Incomplete or corrupted PIB (" << e.what() << ")" << std::endl;
162 return 1;
163 }
164
165 try {
166 transform::bufferSource(wire.wire(), wire.size()) >> transform::base64Encode(true) >> transform::streamSink(std::cout);
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700167 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700168 catch (const transform::Error& e) {
169 std::cerr << "ERROR: " << e.what() << std::endl;
170 return 1;
171 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700172
173 return 0;
174}
175
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -0800176#endif // NDN_TOOLS_NDNSEC_CERT_REVOKE_HPP