blob: 2adca8daa0ac662dc7d99bcc7a6dca2b9f015afd [file] [log] [blame]
Yingdi Yu8d7468f2014-02-21 14:49:45 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 * BSD license, See the LICENSE file for more information
5 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
6 */
7
8#ifndef NDNSEC_CERT_DUMP_HPP
9#define NDNSEC_CERT_DUMP_HPP
10
11#include "ndnsec-util.hpp"
12
13int
14ndnsec_cert_dump(int argc, char** argv)
15{
16 using namespace ndn;
17 namespace po = boost::program_options;
18
19 std::string name;
20 bool isKeyName = false;
21 bool isIdentityName = false;
22 bool isCertName = true;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070023 // bool isFileName = false;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080024 bool isPretty = false;
25 bool isStdOut = true;
26 bool isRepoOut = false;
27 std::string repoHost = "127.0.0.1";
28 std::string repoPort = "7376";
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070029 // bool isDnsOut = false;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080030
31 po::options_description desc("General Usage\n ndnsec cert-dump [-h] [-p] [-d] [-r [-H repo-host] [-P repor-port] ] [-i|k|f] name\nGeneral options");
32 desc.add_options()
33 ("help,h", "produce help message")
34 ("pretty,p", "optional, if specified, display certificate in human readable format")
35 ("identity,i", "optional, if specified, name is identity name (e.g. /ndn/edu/ucla/alice), otherwise certificate name")
36 ("key,k", "optional, if specified, name is key name (e.g. /ndn/edu/ucla/alice/KSK-123456789), otherwise certificate name")
37 ("file,f", "optional, if specified, name is file name, - for stdin")
38 ("repo-output,r", "optional, if specified, certificate is dumped (published) to repo")
39 ("repo-host,H", po::value<std::string>(&repoHost)->default_value("localhost"), "optional, the repo host if repo-output is specified")
40 ("repo-port,P", po::value<std::string>(&repoPort)->default_value("7376"), "optional, the repo port if repo-output is specified")
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070041 // ("dns-output,d", "optional, if specified, certificate is dumped (published) to DNS")
Yingdi Yu8d7468f2014-02-21 14:49:45 -080042 ("name,n", po::value<std::string>(&name), "certificate name, for example, /ndn/edu/ucla/KEY/cs/alice/ksk-1234567890/ID-CERT/%FD%FF%FF%FF%FF%FF%FF%FF")
43 ;
44
45 po::positional_options_description p;
46 p.add("name", 1);
47
48 po::variables_map vm;
49 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
50 po::notify(vm);
51
52 if (vm.count("help"))
53 {
54 std::cerr << desc << std::endl;
55 return 0;
56 }
57
58 if (0 == vm.count("name"))
59 {
60 std::cerr << "identity_name must be specified" << std::endl;
61 std::cerr << desc << std::endl;
62 return 1;
63 }
64
65 if (vm.count("key"))
66 {
67 isCertName = false;
68 isKeyName = true;
69 }
70 else if (vm.count("identity"))
71 {
72 isCertName = false;
73 isIdentityName = true;
74 }
75 else if (vm.count("file"))
76 {
77 isCertName = false;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070078 // isFileName = true;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080079 }
80
81 if (vm.count("pretty"))
82 isPretty = true;
83
84 if (vm.count("repo-output"))
85 {
86 isRepoOut = true;
87 isStdOut = false;
88 }
89 else if(vm.count("dns-output"))
90 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070091 // isDnsOut = true;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080092 isStdOut = false;
93 std::cerr << "Error: DNS output is not supported yet!" << std::endl;
94 return 1;
95 }
96
97 if (isPretty && !isStdOut)
98 {
99 std::cerr << "Error: pretty option can only be specified when other output option is specified" << std::endl;
100 return 1;
101 }
102
103 shared_ptr<IdentityCertificate> certificate;
104
105 try
106 {
107 KeyChain keyChain;
108
109 if(isIdentityName || isKeyName || isCertName)
110 {
111 if(isIdentityName)
112 {
113 Name certName = keyChain.getDefaultCertificateNameForIdentity(name);
114 certificate = keyChain.getCertificate(certName);
115 }
116 else if(isKeyName)
117 {
118 Name certName = keyChain.getDefaultCertificateNameForKey(name);
119 certificate = keyChain.getCertificate(certName);
120 }
121 else
122 certificate = keyChain.getCertificate(name);
123
124 if(NULL == certificate)
125 {
126 std::cerr << "No certificate found!" << std::endl;
127 return 1;
128 }
129 }
130 else
131 {
132 certificate = getIdentityCertificate(name);
133 if(!static_cast<bool>(certificate))
134 {
135 std::cerr << "No certificate read!" << std::endl;
136 return 1;
137 }
138 }
139 }
140 catch(SecPublicInfo::Error& e)
141 {
142 std::cerr << e.what() << std::endl;
143 return 1;
144 }
145 catch(SecTpm::Error& e)
146 {
147 std::cerr << "ERROR: " << e.what() << std::endl;
148 return 1;
149 }
150
151 if(isPretty)
152 {
153 std::cout << *certificate << std::endl;
154 // cout << "Certificate name: " << std::endl;
155 // cout << " " << certificate->getName() << std::endl;
156 // cout << "Validity: " << std::endl;
157 // cout << " NotBefore: " << boost::posix_time::to_simple_string(certificate->getNotBefore()) << std::endl;
158 // cout << " NotAfter: " << boost::posix_time::to_simple_string(certificate->getNotAfter()) << std::endl;
159 // cout << "Subject Description: " << std::endl;
160 // const vector<CertificateSubjectDescription>& SubDescriptionList = certificate->getSubjectDescriptionList();
161 // vector<CertificateSubjectDescription>::const_iterator it = SubDescriptionList.begin();
162 // for(; it != SubDescriptionList.end(); it++)
163 // cout << " " << it->getOidStr() << ": " << it->getValue() << std::endl;
164 // cout << "Public key bits: " << std::endl;
165 // const Blob& keyBlob = certificate->getPublicKeygetKeyBlob();
166 // std::string encoded;
167 // CryptoPP::StringSource ss(reinterpret_cast<const unsigned char *>(keyBlob.buf()), keyBlob.size(), true,
168 // new CryptoPP::Base64Encoder(new CryptoPP::StringSink(encoded), true, 64));
169 // cout << encoded;
170 }
171 else
172 {
173 if(isStdOut)
174 {
175 try
176 {
177 using namespace CryptoPP;
178 StringSource ss(certificate->wireEncode().wire(), certificate->wireEncode().size(), true,
179 new Base64Encoder(new FileSink(std::cout), true, 64));
180 return 0;
181 }
182 catch(CryptoPP::Exception& e)
183 {
184 std::cerr << e.what() << std::endl;
185 return 1;
186 }
187 }
188 if(isRepoOut)
189 {
190 using namespace boost::asio::ip;
191 tcp::iostream request_stream;
192#if (BOOST_VERSION >= 104700)
193 request_stream.expires_from_now(boost::posix_time::milliseconds(3000));
194#endif
195 request_stream.connect(repoHost,repoPort);
196 if(!request_stream)
197 {
198 std::cerr << "fail to open the stream!" << std::endl;
199 return 1;
200 }
201 request_stream.write(reinterpret_cast<const char*>(certificate->wireEncode().wire()), certificate->wireEncode().size());
202 return 0;
203 }
204 }
205 return 0;
206}
207
208#endif //NDNSEC_CERT_DUMP_HPP