blob: f7de1481df600be42ff13466c079f396243ebfc0 [file] [log] [blame]
Yingdi Yu5edf97d2014-06-15 11:35:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev4c9a3d52017-01-03 17:45:19 -08003 * Copyright (c) 2013-2017 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.
Yingdi Yu5edf97d2014-06-15 11:35:12 -070020 */
21
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080022#include "ndnsec.hpp"
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -080023#include "util.hpp"
Yingdi Yu5edf97d2014-06-15 11:35:12 -070024
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080025namespace ndn {
26namespace ndnsec {
27
Yingdi Yu5edf97d2014-06-15 11:35:12 -070028int
29ndnsec_cert_revoke(int argc, char** argv)
30{
31 using namespace ndn;
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070032 using namespace ndn::security;
Yingdi Yu5edf97d2014-06-15 11:35:12 -070033 namespace po = boost::program_options;
34
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080035 security::v1::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;
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080040 Name certPrefix = security::v1::KeyChain::DEFAULT_PREFIX;
Alexander Afanasyev7438a152014-10-15 18:34:43 -070041
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;
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070059 try {
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080060 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070061 po::notify(vm);
62 }
63 catch (const std::exception& e) {
64 std::cerr << "ERROR: " << e.what() << std::endl;
65 return 1;
66 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -070067
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070068 if (vm.count("help") != 0) {
69 std::cerr << description << std::endl;
70 return 0;
71 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -070072
Alexander Afanasyev7438a152014-10-15 18:34:43 -070073 hasSignId = (vm.count("sign-id") != 0);
74
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070075 if (vm.count("request") == 0) {
76 std::cerr << "request file must be specified" << std::endl;
77 return 1;
78 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -070079
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080080 shared_ptr<security::v1::IdentityCertificate> revokedCertificate = getIdentityCertificate(requestFile);
Yingdi Yu5edf97d2014-06-15 11:35:12 -070081
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080082 if (revokedCertificate == nullptr) {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070083 std::cerr << "ERROR: input error" << std::endl;
84 return 1;
85 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -070086
Yingdi Yu5edf97d2014-06-15 11:35:12 -070087 Block wire;
88
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070089 try {
90 Name keyName;
Alexander Afanasyev7438a152014-10-15 18:34:43 -070091
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070092 if (hasSignId) {
93 keyName = keyChain.getDefaultKeyNameForIdentity(signId);
94 }
95 else {
96 const Signature& signature = revokedCertificate->getSignature();
97 if (!signature.hasKeyLocator() ||
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080098 signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name) {
99 std::cerr << "ERROR: Invalid certificate to revoke" << std::endl;
100 return 1;
101 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700102
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800103 keyName = security::v1::IdentityCertificate::certificateNameToPublicKeyName(signature.getKeyLocator().getName());
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700104 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700105
106 Name certName;
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800107 if (certPrefix == security::v1::KeyChain::DEFAULT_PREFIX) {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700108 certName = revokedCertificate->getName().getPrefix(-1);
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700109 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700110 else {
111 Name revokedKeyName = revokedCertificate->getPublicKeyName();
112
113 if (certPrefix.isPrefixOf(revokedKeyName) && certPrefix != revokedKeyName) {
114 certName.append(certPrefix)
115 .append("KEY")
116 .append(revokedKeyName.getSubName(certPrefix.size()))
117 .append("ID-CERT");
118 }
119 else {
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800120 std::cerr << "ERROR: certificate prefix does not match the revoked certificate" << std::endl;
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700121 return 1;
122 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700123 }
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800124 certName.appendVersion().append("REVOKED");
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700125
126 Data revocationCert;
127 revocationCert.setName(certName);
128
129 if (keyChain.doesPublicKeyExist(keyName)) {
130 Name signingCertificateName = keyChain.getDefaultCertificateNameForKey(keyName);
131 keyChain.sign(revocationCert,
132 SigningInfo(SigningInfo::SIGNER_TYPE_CERT, signingCertificateName));
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700133 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700134 else {
135 std::cerr << "ERROR: Cannot find the signing key!" << std::endl;
Alexander Afanasyev7438a152014-10-15 18:34:43 -0700136 return 1;
137 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700138
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700139 wire = revocationCert.wireEncode();
140 }
141 catch (const Signature::Error& e) {
142 std::cerr << "ERROR: No valid signature!" << std::endl;
143 return 1;
144 }
145 catch (const KeyLocator::Error& e) {
146 std::cerr << "ERROR: No valid KeyLocator!" << std::endl;
147 return 1;
148 }
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800149 catch (const security::v1::IdentityCertificate::Error& e) {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700150 std::cerr << "ERROR: Cannot determine the signing key!" << std::endl;
151 return 1;
152 }
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800153 catch (const security::v1::SecPublicInfo::Error& e) {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700154 std::cerr << "ERROR: Incomplete or corrupted PIB (" << e.what() << ")" << std::endl;
155 return 1;
156 }
157
158 try {
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800159 transform::bufferSource(wire.wire(), wire.size()) >> transform::base64Encode(true) >>
160 transform::streamSink(std::cout);
161 }
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700162 catch (const transform::Error& e) {
163 std::cerr << "ERROR: " << e.what() << std::endl;
164 return 1;
165 }
Yingdi Yu5edf97d2014-06-15 11:35:12 -0700166
167 return 0;
168}
169
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800170} // namespace ndnsec
171} // namespace ndn