pki: Properly clean up if output format for --pkcs12 is wrong
[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 <asn1/oid.h>
20 #include <credentials/certificates/certificate.h>
21 #include <credentials/certificates/x509.h>
22 #include <credentials/certificates/crl.h>
23 #include <credentials/certificates/ac.h>
24 #include <selectors/traffic_selector.h>
25
26 #include <time.h>
27 #include <errno.h>
28
29 /**
30 * Print public key information
31 */
32 static void print_pubkey(public_key_t *key)
33 {
34 chunk_t chunk;
35 key_type_t type;
36
37 type = key->get_type(key);
38 printf("pubkey: %N %d bits%s\n", key_type_names, type,
39 key->get_keysize(key), (type == KEY_BLISS) ? " strength" : "");
40
41 if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
42 {
43 printf("keyid: %#B\n", &chunk);
44 }
45 if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &chunk))
46 {
47 printf("subjkey: %#B\n", &chunk);
48 }
49 }
50
51 /**
52 * Print private key information
53 */
54 static void print_key(private_key_t *key)
55 {
56 public_key_t *public;
57
58 public = key->get_public_key(key);
59 if (public)
60 {
61 printf("private key with:\n");
62 print_pubkey(public);
63 public->destroy(public);
64 }
65 else
66 {
67 printf("extracting public from private key failed\n");
68 }
69 }
70
71 /**
72 * Get a prefix for a named constraint identity type
73 */
74 static char* get_type_pfx(identification_t *id)
75 {
76 switch (id->get_type(id))
77 {
78 case ID_RFC822_ADDR:
79 return "email:";
80 case ID_FQDN:
81 return "dns:";
82 default:
83 return "";
84 }
85 }
86
87 /**
88 * Print X509 specific certificate information
89 */
90 static void print_x509(x509_t *x509)
91 {
92 enumerator_t *enumerator;
93 identification_t *id;
94 traffic_selector_t *block;
95 chunk_t chunk;
96 bool first;
97 char *uri;
98 int len, explicit, inhibit;
99 x509_flag_t flags;
100 x509_cdp_t *cdp;
101 x509_cert_policy_t *policy;
102 x509_policy_mapping_t *mapping;
103
104 chunk = chunk_skip_zero(x509->get_serial(x509));
105 printf("serial: %#B\n", &chunk);
106
107 first = TRUE;
108 enumerator = x509->create_subjectAltName_enumerator(x509);
109 while (enumerator->enumerate(enumerator, &id))
110 {
111 if (first)
112 {
113 printf("altNames: ");
114 first = FALSE;
115 }
116 else
117 {
118 printf(", ");
119 }
120 printf("%Y", id);
121 }
122 if (!first)
123 {
124 printf("\n");
125 }
126 enumerator->destroy(enumerator);
127
128 flags = x509->get_flags(x509);
129 printf("flags: ");
130 if (flags & X509_CA)
131 {
132 printf("CA ");
133 }
134 if (flags & X509_CRL_SIGN)
135 {
136 printf("CRLSign ");
137 }
138 if (flags & X509_AA)
139 {
140 printf("AA ");
141 }
142 if (flags & X509_OCSP_SIGNER)
143 {
144 printf("OCSP ");
145 }
146 if (flags & X509_AA)
147 {
148 printf("AA ");
149 }
150 if (flags & X509_SERVER_AUTH)
151 {
152 printf("serverAuth ");
153 }
154 if (flags & X509_CLIENT_AUTH)
155 {
156 printf("clientAuth ");
157 }
158 if (flags & X509_IKE_INTERMEDIATE)
159 {
160 printf("iKEIntermediate ");
161 }
162 if (flags & X509_MS_SMARTCARD_LOGON)
163 {
164 printf("msSmartcardLogon ");
165 }
166 if (flags & X509_SELF_SIGNED)
167 {
168 printf("self-signed ");
169 }
170 printf("\n");
171
172 first = TRUE;
173 enumerator = x509->create_crl_uri_enumerator(x509);
174 while (enumerator->enumerate(enumerator, &cdp))
175 {
176 if (first)
177 {
178 printf("CRL URIs: %s", cdp->uri);
179 first = FALSE;
180 }
181 else
182 {
183 printf(" %s", cdp->uri);
184 }
185 if (cdp->issuer)
186 {
187 printf(" (CRL issuer: %Y)", cdp->issuer);
188 }
189 printf("\n");
190 }
191 enumerator->destroy(enumerator);
192
193 first = TRUE;
194 enumerator = x509->create_ocsp_uri_enumerator(x509);
195 while (enumerator->enumerate(enumerator, &uri))
196 {
197 if (first)
198 {
199 printf("OCSP URIs: %s\n", uri);
200 first = FALSE;
201 }
202 else
203 {
204 printf(" %s\n", uri);
205 }
206 }
207 enumerator->destroy(enumerator);
208
209 len = x509->get_constraint(x509, X509_PATH_LEN);
210 if (len != X509_NO_CONSTRAINT)
211 {
212 printf("pathlen: %d\n", len);
213 }
214
215 first = TRUE;
216 enumerator = x509->create_name_constraint_enumerator(x509, TRUE);
217 while (enumerator->enumerate(enumerator, &id))
218 {
219 if (first)
220 {
221 printf("Permitted NameConstraints:\n");
222 first = FALSE;
223 }
224 printf(" %s%Y\n", get_type_pfx(id), id);
225 }
226 enumerator->destroy(enumerator);
227 first = TRUE;
228 enumerator = x509->create_name_constraint_enumerator(x509, FALSE);
229 while (enumerator->enumerate(enumerator, &id))
230 {
231 if (first)
232 {
233 printf("Excluded NameConstraints:\n");
234 first = FALSE;
235 }
236 printf(" %s%Y\n", get_type_pfx(id), id);
237 }
238 enumerator->destroy(enumerator);
239
240 first = TRUE;
241 enumerator = x509->create_cert_policy_enumerator(x509);
242 while (enumerator->enumerate(enumerator, &policy))
243 {
244 char *oid;
245
246 if (first)
247 {
248 printf("CertificatePolicies:\n");
249 first = FALSE;
250 }
251 oid = asn1_oid_to_string(policy->oid);
252 if (oid)
253 {
254 printf(" %s\n", oid);
255 free(oid);
256 }
257 else
258 {
259 printf(" %#B\n", &policy->oid);
260 }
261 if (policy->cps_uri)
262 {
263 printf(" CPS: %s\n", policy->cps_uri);
264 }
265 if (policy->unotice_text)
266 {
267 printf(" Notice: %s\n", policy->unotice_text);
268
269 }
270 }
271 enumerator->destroy(enumerator);
272
273 first = TRUE;
274 enumerator = x509->create_policy_mapping_enumerator(x509);
275 while (enumerator->enumerate(enumerator, &mapping))
276 {
277 char *issuer_oid, *subject_oid;
278
279 if (first)
280 {
281 printf("PolicyMappings:\n");
282 first = FALSE;
283 }
284 issuer_oid = asn1_oid_to_string(mapping->issuer);
285 subject_oid = asn1_oid_to_string(mapping->subject);
286 printf(" %s => %s\n", issuer_oid, subject_oid);
287 free(issuer_oid);
288 free(subject_oid);
289 }
290 enumerator->destroy(enumerator);
291
292 explicit = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY);
293 inhibit = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING);
294 len = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY);
295
296 if (explicit != X509_NO_CONSTRAINT || inhibit != X509_NO_CONSTRAINT ||
297 len != X509_NO_CONSTRAINT)
298 {
299 printf("PolicyConstraints:\n");
300 if (explicit != X509_NO_CONSTRAINT)
301 {
302 printf(" requireExplicitPolicy: %d\n", explicit);
303 }
304 if (inhibit != X509_NO_CONSTRAINT)
305 {
306 printf(" inhibitPolicyMapping: %d\n", inhibit);
307 }
308 if (len != X509_NO_CONSTRAINT)
309 {
310 printf(" inhibitAnyPolicy: %d\n", len);
311 }
312 }
313
314 chunk = x509->get_authKeyIdentifier(x509);
315 if (chunk.ptr)
316 {
317 printf("authkeyId: %#B\n", &chunk);
318 }
319
320 chunk = x509->get_subjectKeyIdentifier(x509);
321 if (chunk.ptr)
322 {
323 printf("subjkeyId: %#B\n", &chunk);
324 }
325 if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
326 {
327 first = TRUE;
328 printf("addresses: ");
329 enumerator = x509->create_ipAddrBlock_enumerator(x509);
330 while (enumerator->enumerate(enumerator, &block))
331 {
332 if (first)
333 {
334 first = FALSE;
335 }
336 else
337 {
338 printf(", ");
339 }
340 printf("%R", block);
341 }
342 enumerator->destroy(enumerator);
343 printf("\n");
344 }
345 }
346
347 /**
348 * Print CRL specific information
349 */
350 static void print_crl(crl_t *crl)
351 {
352 enumerator_t *enumerator;
353 time_t ts;
354 crl_reason_t reason;
355 chunk_t chunk;
356 int count = 0;
357 bool first;
358 char buf[64];
359 struct tm tm;
360 x509_cdp_t *cdp;
361
362 chunk = chunk_skip_zero(crl->get_serial(crl));
363 printf("serial: %#B\n", &chunk);
364
365 if (crl->is_delta_crl(crl, &chunk))
366 {
367 chunk = chunk_skip_zero(chunk);
368 printf("delta CRL: for serial %#B\n", &chunk);
369 }
370 chunk = crl->get_authKeyIdentifier(crl);
371 printf("authKeyId: %#B\n", &chunk);
372
373 first = TRUE;
374 enumerator = crl->create_delta_crl_uri_enumerator(crl);
375 while (enumerator->enumerate(enumerator, &cdp))
376 {
377 if (first)
378 {
379 printf("freshest: %s", cdp->uri);
380 first = FALSE;
381 }
382 else
383 {
384 printf(" %s", cdp->uri);
385 }
386 if (cdp->issuer)
387 {
388 printf(" (CRL issuer: %Y)", cdp->issuer);
389 }
390 printf("\n");
391 }
392 enumerator->destroy(enumerator);
393
394 enumerator = crl->create_enumerator(crl);
395 while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
396 {
397 count++;
398 }
399 enumerator->destroy(enumerator);
400
401 printf("%d revoked certificate%s%s\n", count,
402 count == 1 ? "" : "s", count ? ":" : "");
403 enumerator = crl->create_enumerator(crl);
404 while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
405 {
406 chunk = chunk_skip_zero(chunk);
407 localtime_r(&ts, &tm);
408 strftime(buf, sizeof(buf), "%F %T", &tm);
409 printf(" %#B %N %s\n", &chunk, crl_reason_names, reason, buf);
410 count++;
411 }
412 enumerator->destroy(enumerator);
413 }
414
415 /**
416 * Print AC specific information
417 */
418 static void print_ac(ac_t *ac)
419 {
420 ac_group_type_t type;
421 identification_t *id;
422 enumerator_t *groups;
423 chunk_t chunk;
424 bool first = TRUE;
425
426 chunk = chunk_skip_zero(ac->get_serial(ac));
427 printf("serial: %#B\n", &chunk);
428
429 id = ac->get_holderIssuer(ac);
430 if (id)
431 {
432 printf("hissuer: \"%Y\"\n", id);
433 }
434 chunk = chunk_skip_zero(ac->get_holderSerial(ac));
435 if (chunk.ptr)
436 {
437 printf("hserial: %#B\n", &chunk);
438 }
439 groups = ac->create_group_enumerator(ac);
440 while (groups->enumerate(groups, &type, &chunk))
441 {
442 int oid;
443 char *str;
444
445 if (first)
446 {
447 printf("groups: ");
448 first = FALSE;
449 }
450 else
451 {
452 printf(" ");
453 }
454 switch (type)
455 {
456 case AC_GROUP_TYPE_STRING:
457 printf("%.*s", (int)chunk.len, chunk.ptr);
458 break;
459 case AC_GROUP_TYPE_OID:
460 oid = asn1_known_oid(chunk);
461 if (oid == OID_UNKNOWN)
462 {
463 str = asn1_oid_to_string(chunk);
464 if (str)
465 {
466 printf("%s", str);
467 free(str);
468 }
469 else
470 {
471 printf("OID:%#B", &chunk);
472 }
473 }
474 else
475 {
476 printf("%s", oid_names[oid].name);
477 }
478 break;
479 case AC_GROUP_TYPE_OCTETS:
480 printf("%#B", &chunk);
481 break;
482 }
483 printf("\n");
484 }
485 groups->destroy(groups);
486
487 chunk = ac->get_authKeyIdentifier(ac);
488 if (chunk.ptr)
489 {
490 printf("authkey: %#B\n", &chunk);
491 }
492 }
493
494 /**
495 * Print certificate information
496 */
497 static void print_cert(certificate_t *cert)
498 {
499 time_t now, notAfter, notBefore;
500 public_key_t *key;
501
502 now = time(NULL);
503
504 printf("cert: %N\n", certificate_type_names, cert->get_type(cert));
505 if (cert->get_type(cert) != CERT_X509_CRL)
506 {
507 printf("subject: \"%Y\"\n", cert->get_subject(cert));
508 }
509 printf("issuer: \"%Y\"\n", cert->get_issuer(cert));
510
511 cert->get_validity(cert, &now, &notBefore, &notAfter);
512 printf("validity: not before %T, ", &notBefore, FALSE);
513 if (now < notBefore)
514 {
515 printf("not valid yet (valid in %V)\n", &now, &notBefore);
516 }
517 else
518 {
519 printf("ok\n");
520 }
521 printf(" not after %T, ", &notAfter, FALSE);
522 if (now > notAfter)
523 {
524 printf("expired (%V ago)\n", &now, &notAfter);
525 }
526 else
527 {
528 printf("ok (expires in %V)\n", &now, &notAfter);
529 }
530
531 switch (cert->get_type(cert))
532 {
533 case CERT_X509:
534 print_x509((x509_t*)cert);
535 break;
536 case CERT_X509_CRL:
537 print_crl((crl_t*)cert);
538 break;
539 case CERT_X509_AC:
540 print_ac((ac_t*)cert);
541 break;
542 default:
543 printf("parsing certificate subtype %N not implemented\n",
544 certificate_type_names, cert->get_type(cert));
545 break;
546 }
547 key = cert->get_public_key(cert);
548 if (key)
549 {
550 print_pubkey(key);
551 key->destroy(key);
552 }
553 }
554
555 /**
556 * Print a credential in a human readable form
557 */
558 static int print()
559 {
560 credential_type_t type = CRED_CERTIFICATE;
561 int subtype = CERT_X509;
562 void *cred;
563 char *arg, *file = NULL;
564
565 while (TRUE)
566 {
567 switch (command_getopt(&arg))
568 {
569 case 'h':
570 return command_usage(NULL);
571 case 't':
572 if (streq(arg, "x509"))
573 {
574 type = CRED_CERTIFICATE;
575 subtype = CERT_X509;
576 }
577 else if (streq(arg, "crl"))
578 {
579 type = CRED_CERTIFICATE;
580 subtype = CERT_X509_CRL;
581 }
582 else if (streq(arg, "ac"))
583 {
584 type = CRED_CERTIFICATE;
585 subtype = CERT_X509_AC;
586 }
587 else if (streq(arg, "pub"))
588 {
589 type = CRED_PUBLIC_KEY;
590 subtype = KEY_ANY;
591 }
592 else if (streq(arg, "rsa-priv"))
593 {
594 type = CRED_PRIVATE_KEY;
595 subtype = KEY_RSA;
596 }
597 else if (streq(arg, "ecdsa-priv"))
598 {
599 type = CRED_PRIVATE_KEY;
600 subtype = KEY_ECDSA;
601 }
602 else if (streq(arg, "bliss-priv"))
603 {
604 type = CRED_PRIVATE_KEY;
605 subtype = KEY_BLISS;
606 }
607 else
608 {
609 return command_usage( "invalid input type");
610 }
611 continue;
612 case 'i':
613 file = arg;
614 continue;
615 case EOF:
616 break;
617 default:
618 return command_usage("invalid --print option");
619 }
620 break;
621 }
622 if (file)
623 {
624 cred = lib->creds->create(lib->creds, type, subtype,
625 BUILD_FROM_FILE, file, BUILD_END);
626 }
627 else
628 {
629 chunk_t chunk;
630
631 set_file_mode(stdin, CERT_ASN1_DER);
632 if (!chunk_from_fd(0, &chunk))
633 {
634 fprintf(stderr, "reading input failed: %s\n", strerror(errno));
635 return 1;
636 }
637 cred = lib->creds->create(lib->creds, type, subtype,
638 BUILD_BLOB, chunk, BUILD_END);
639 free(chunk.ptr);
640 }
641 if (!cred)
642 {
643 fprintf(stderr, "parsing input failed\n");
644 return 1;
645 }
646
647 if (type == CRED_CERTIFICATE)
648 {
649 certificate_t *cert = (certificate_t*)cred;
650
651 print_cert(cert);
652 cert->destroy(cert);
653 }
654 if (type == CRED_PUBLIC_KEY)
655 {
656 public_key_t *key = (public_key_t*)cred;
657
658 print_pubkey(key);
659 key->destroy(key);
660 }
661 if (type == CRED_PRIVATE_KEY)
662 {
663 private_key_t *key = (private_key_t*)cred;
664
665 print_key(key);
666 key->destroy(key);
667 }
668 return 0;
669 }
670
671 /**
672 * Register the command.
673 */
674 static void __attribute__ ((constructor))reg()
675 {
676 command_register((command_t)
677 { print, 'a', "print",
678 "print a credential in a human readable form",
679 {"[--in file] [--type rsa-priv|ecdsa-priv|bliss-priv|pub|x509|crl|ac]"},
680 {
681 {"help", 'h', 0, "show usage information"},
682 {"in", 'i', 1, "input file, default: stdin"},
683 {"type", 't', 1, "type of credential, default: x509"},
684 }
685 });
686 }