af0c92cd47a25f8ee8c4ddd187b254600d333c8b
[strongswan.git] / src / pki / commands / print.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "pki.h"
17
18 #include <asn1/asn1.h>
19 #include <credentials/certificates/certificate.h>
20 #include <credentials/certificates/x509.h>
21 #include <credentials/certificates/crl.h>
22 #include <selectors/traffic_selector.h>
23
24 #include <time.h>
25
26 /**
27 * Print public key information
28 */
29 static void print_pubkey(public_key_t *key)
30 {
31 chunk_t chunk;
32
33 printf("pubkey: %N %d bits\n", key_type_names, key->get_type(key),
34 key->get_keysize(key));
35 if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
36 {
37 printf("keyid: %#B\n", &chunk);
38 }
39 if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &chunk))
40 {
41 printf("subjkey: %#B\n", &chunk);
42 }
43 }
44
45 /**
46 * Print private key information
47 */
48 static void print_key(private_key_t *key)
49 {
50 public_key_t *public;
51
52 public = key->get_public_key(key);
53 if (public)
54 {
55 printf("private key with:\n");
56 print_pubkey(public);
57 public->destroy(public);
58 }
59 else
60 {
61 printf("extracting public from private key failed\n");
62 }
63 }
64
65 /**
66 * Print X509 specific certificate information
67 */
68 static void print_x509(x509_t *x509)
69 {
70 enumerator_t *enumerator;
71 identification_t *id;
72 traffic_selector_t *block;
73 chunk_t chunk;
74 bool first;
75 char *uri;
76 int len;
77 x509_flag_t flags;
78 x509_cert_policy_t *policy;
79
80 chunk = x509->get_serial(x509);
81 printf("serial: %#B\n", &chunk);
82
83 first = TRUE;
84 enumerator = x509->create_subjectAltName_enumerator(x509);
85 while (enumerator->enumerate(enumerator, &id))
86 {
87 if (first)
88 {
89 printf("altNames: ");
90 first = FALSE;
91 }
92 else
93 {
94 printf(", ");
95 }
96 printf("%Y", id);
97 }
98 if (!first)
99 {
100 printf("\n");
101 }
102 enumerator->destroy(enumerator);
103
104 flags = x509->get_flags(x509);
105 printf("flags: ");
106 if (flags & X509_CA)
107 {
108 printf("CA ");
109 }
110 if (flags & X509_CRL_SIGN)
111 {
112 printf("CRLSign ");
113 }
114 if (flags & X509_AA)
115 {
116 printf("AA ");
117 }
118 if (flags & X509_OCSP_SIGNER)
119 {
120 printf("OCSP ");
121 }
122 if (flags & X509_AA)
123 {
124 printf("AA ");
125 }
126 if (flags & X509_SERVER_AUTH)
127 {
128 printf("serverAuth ");
129 }
130 if (flags & X509_CLIENT_AUTH)
131 {
132 printf("clientAuth ");
133 }
134 if (flags & X509_SELF_SIGNED)
135 {
136 printf("self-signed ");
137 }
138 printf("\n");
139
140 first = TRUE;
141 enumerator = x509->create_crl_uri_enumerator(x509);
142 while (enumerator->enumerate(enumerator, &uri, &id))
143 {
144 if (first)
145 {
146 printf("CRL URIs: %s", uri);
147 first = FALSE;
148 }
149 else
150 {
151 printf(" %s", uri);
152 }
153 if (id)
154 {
155 printf(" (CRL issuer: %Y)", id);
156 }
157 printf("\n");
158 }
159 enumerator->destroy(enumerator);
160
161 first = TRUE;
162 enumerator = x509->create_ocsp_uri_enumerator(x509);
163 while (enumerator->enumerate(enumerator, &uri))
164 {
165 if (first)
166 {
167 printf("OCSP URIs: %s\n", uri);
168 first = FALSE;
169 }
170 else
171 {
172 printf(" %s\n", uri);
173 }
174 }
175 enumerator->destroy(enumerator);
176
177 len = x509->get_pathLenConstraint(x509);
178 if (len != X509_NO_PATH_LEN_CONSTRAINT)
179 {
180 printf("pathlen: %d\n", len);
181 }
182
183 first = TRUE;
184 enumerator = x509->create_name_constraint_enumerator(x509, TRUE);
185 while (enumerator->enumerate(enumerator, &id))
186 {
187 if (first)
188 {
189 printf("Permitted NameConstraints:\n");
190 first = FALSE;
191 }
192 printf(" %Y\n", id);
193 }
194 enumerator->destroy(enumerator);
195 first = TRUE;
196 enumerator = x509->create_name_constraint_enumerator(x509, FALSE);
197 while (enumerator->enumerate(enumerator, &id))
198 {
199 if (first)
200 {
201 printf("Excluded NameConstraints:\n");
202 first = FALSE;
203 }
204 printf(" %Y\n", id);
205 }
206 enumerator->destroy(enumerator);
207
208 first = TRUE;
209 enumerator = x509->create_cert_policy_enumerator(x509);
210 while (enumerator->enumerate(enumerator, &policy))
211 {
212 char *oid;
213
214 if (first)
215 {
216 printf("CertificatePolicies:\n");
217 first = FALSE;
218 }
219 oid = asn1_oid_to_string(policy->oid);
220 if (oid)
221 {
222 printf(" %s\n", oid);
223 free(oid);
224 }
225 else
226 {
227 printf(" %#B\n", &policy->oid);
228 }
229 if (policy->cps_uri)
230 {
231 printf(" CPS: %s\n", policy->cps_uri);
232 }
233 if (policy->unotice_text)
234 {
235 printf(" Notice: %s\n", policy->unotice_text);
236
237 }
238 }
239 enumerator->destroy(enumerator);
240
241 chunk = x509->get_authKeyIdentifier(x509);
242 if (chunk.ptr)
243 {
244 printf("authkeyId: %#B\n", &chunk);
245 }
246
247 chunk = x509->get_subjectKeyIdentifier(x509);
248 if (chunk.ptr)
249 {
250 printf("subjkeyId: %#B\n", &chunk);
251 }
252 if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
253 {
254 first = TRUE;
255 printf("addresses: ");
256 enumerator = x509->create_ipAddrBlock_enumerator(x509);
257 while (enumerator->enumerate(enumerator, &block))
258 {
259 if (first)
260 {
261 first = FALSE;
262 }
263 else
264 {
265 printf(", ");
266 }
267 printf("%R", block);
268 }
269 enumerator->destroy(enumerator);
270 printf("\n");
271 }
272 }
273
274 /**
275 * Print CRL specific information
276 */
277 static void print_crl(crl_t *crl)
278 {
279 enumerator_t *enumerator;
280 time_t ts;
281 crl_reason_t reason;
282 chunk_t chunk;
283 int count = 0;
284 char buf[64];
285 struct tm tm;
286
287 chunk = crl->get_serial(crl);
288 printf("serial: %#B\n", &chunk);
289 chunk = crl->get_authKeyIdentifier(crl);
290 printf("authKeyId: %#B\n", &chunk);
291
292 enumerator = crl->create_enumerator(crl);
293 while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
294 {
295 count++;
296 }
297 enumerator->destroy(enumerator);
298
299 printf("%d revoked certificate%s%s\n", count,
300 count == 1 ? "" : "s", count ? ":" : "");
301 enumerator = crl->create_enumerator(crl);
302 while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
303 {
304 localtime_r(&ts, &tm);
305 strftime(buf, sizeof(buf), "%F %T", &tm);
306 printf(" %#B %N %s\n", &chunk, crl_reason_names, reason, buf);
307 count++;
308 }
309 enumerator->destroy(enumerator);
310 }
311
312 /**
313 * Print certificate information
314 */
315 static void print_cert(certificate_t *cert)
316 {
317 time_t now, notAfter, notBefore;
318 public_key_t *key;
319
320 now = time(NULL);
321
322 printf("cert: %N\n", certificate_type_names, cert->get_type(cert));
323 if (cert->get_type(cert) != CERT_X509_CRL)
324 {
325 printf("subject: \"%Y\"\n", cert->get_subject(cert));
326 }
327 printf("issuer: \"%Y\"\n", cert->get_issuer(cert));
328
329 cert->get_validity(cert, &now, &notBefore, &notAfter);
330 printf("validity: not before %T, ", &notBefore, FALSE);
331 if (now < notBefore)
332 {
333 printf("not valid yet (valid in %V)\n", &now, &notBefore);
334 }
335 else
336 {
337 printf("ok\n");
338 }
339 printf(" not after %T, ", &notAfter, FALSE);
340 if (now > notAfter)
341 {
342 printf("expired (%V ago)\n", &now, &notAfter);
343 }
344 else
345 {
346 printf("ok (expires in %V)\n", &now, &notAfter);
347 }
348
349 switch (cert->get_type(cert))
350 {
351 case CERT_X509:
352 print_x509((x509_t*)cert);
353 break;
354 case CERT_X509_CRL:
355 print_crl((crl_t*)cert);
356 break;
357 default:
358 printf("parsing certificate subtype %N not implemented\n",
359 certificate_type_names, cert->get_type(cert));
360 break;
361 }
362 key = cert->get_public_key(cert);
363 if (key)
364 {
365 print_pubkey(key);
366 key->destroy(key);
367 }
368 }
369
370 /**
371 * Print a credential in a human readable form
372 */
373 static int print()
374 {
375 credential_type_t type = CRED_CERTIFICATE;
376 int subtype = CERT_X509;
377 void *cred;
378 char *arg, *file = NULL;
379
380 while (TRUE)
381 {
382 switch (command_getopt(&arg))
383 {
384 case 'h':
385 return command_usage(NULL);
386 case 't':
387 if (streq(arg, "x509"))
388 {
389 type = CRED_CERTIFICATE;
390 subtype = CERT_X509;
391 }
392 else if (streq(arg, "crl"))
393 {
394 type = CRED_CERTIFICATE;
395 subtype = CERT_X509_CRL;
396 }
397 else if (streq(arg, "pub"))
398 {
399 type = CRED_PUBLIC_KEY;
400 subtype = KEY_ANY;
401 }
402 else if (streq(arg, "rsa-priv"))
403 {
404 type = CRED_PRIVATE_KEY;
405 subtype = KEY_RSA;
406 }
407 else if (streq(arg, "ecdsa-priv"))
408 {
409 type = CRED_PRIVATE_KEY;
410 subtype = KEY_ECDSA;
411 }
412 else
413 {
414 return command_usage( "invalid input type");
415 }
416 continue;
417 case 'i':
418 file = arg;
419 continue;
420 case EOF:
421 break;
422 default:
423 return command_usage("invalid --print option");
424 }
425 break;
426 }
427 if (file)
428 {
429 cred = lib->creds->create(lib->creds, type, subtype,
430 BUILD_FROM_FILE, file, BUILD_END);
431 }
432 else
433 {
434 cred = lib->creds->create(lib->creds, type, subtype,
435 BUILD_FROM_FD, 0, BUILD_END);
436 }
437 if (!cred)
438 {
439 fprintf(stderr, "parsing input failed\n");
440 return 1;
441 }
442
443 if (type == CRED_CERTIFICATE)
444 {
445 certificate_t *cert = (certificate_t*)cred;
446
447 print_cert(cert);
448 cert->destroy(cert);
449 }
450 if (type == CRED_PUBLIC_KEY)
451 {
452 public_key_t *key = (public_key_t*)cred;
453
454 print_pubkey(key);
455 key->destroy(key);
456 }
457 if (type == CRED_PRIVATE_KEY)
458 {
459 private_key_t *key = (private_key_t*)cred;
460
461 print_key(key);
462 key->destroy(key);
463 }
464 return 0;
465 }
466
467 /**
468 * Register the command.
469 */
470 static void __attribute__ ((constructor))reg()
471 {
472 command_register((command_t)
473 { print, 'a', "print",
474 "print a credential in a human readable form",
475 {"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl]"},
476 {
477 {"help", 'h', 0, "show usage information"},
478 {"in", 'i', 1, "input file, default: stdin"},
479 {"type", 't', 1, "type of credential, default: x509"},
480 }
481 });
482 }