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