]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/pki/commands/print.c
pki: Switch to binary mode on Windows when reading/writing DER to FDs
[people/ms/strongswan.git] / src / pki / commands / print.c
CommitLineData
2e57b212
MW
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
6c3ac044 18#include <asn1/asn1.h>
20ea84da 19#include <asn1/oid.h>
2e57b212
MW
20#include <credentials/certificates/certificate.h>
21#include <credentials/certificates/x509.h>
21f80e9d 22#include <credentials/certificates/crl.h>
20ea84da 23#include <credentials/certificates/ac.h>
2e57b212
MW
24#include <selectors/traffic_selector.h>
25
26#include <time.h>
1c4a3459 27#include <errno.h>
2e57b212
MW
28
29/**
30 * Print public key information
31 */
32static 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),
a944d209 37 key->get_keysize(key));
da9724e6 38 if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
2e57b212
MW
39 {
40 printf("keyid: %#B\n", &chunk);
41 }
da9724e6 42 if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &chunk))
2e57b212
MW
43 {
44 printf("subjkey: %#B\n", &chunk);
45 }
46}
47
48/**
49 * Print private key information
50 */
51static 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 */
71static 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;
b3d359e5 79 int len, explicit, inhibit;
2e57b212 80 x509_flag_t flags;
a6478a04 81 x509_cdp_t *cdp;
6c3ac044 82 x509_cert_policy_t *policy;
3ffc9d9a 83 x509_policy_mapping_t *mapping;
2e57b212 84
e464894e 85 chunk = chunk_skip_zero(x509->get_serial(x509));
2e57b212
MW
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 }
bb0cda2f
MW
115 if (flags & X509_CRL_SIGN)
116 {
117 printf("CRLSign ");
118 }
2e57b212
MW
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 }
4bc4e8e1
TB
139 if (flags & X509_IKE_INTERMEDIATE)
140 {
141 printf("iKEIntermediate ");
142 }
98ae0492
AS
143 if (flags & X509_MS_SMARTCARD_LOGON)
144 {
145 printf("msSmartcardLogon ");
146 }
2e57b212
MW
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);
a6478a04 155 while (enumerator->enumerate(enumerator, &cdp))
2e57b212
MW
156 {
157 if (first)
158 {
a6478a04 159 printf("CRL URIs: %s", cdp->uri);
2e57b212
MW
160 first = FALSE;
161 }
162 else
163 {
a6478a04 164 printf(" %s", cdp->uri);
4e508517 165 }
a6478a04 166 if (cdp->issuer)
4e508517 167 {
a6478a04 168 printf(" (CRL issuer: %Y)", cdp->issuer);
2e57b212 169 }
4e508517 170 printf("\n");
2e57b212
MW
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
b3d359e5 190 len = x509->get_constraint(x509, X509_PATH_LEN);
5dba5852 191 if (len != X509_NO_CONSTRAINT)
2e57b212
MW
192 {
193 printf("pathlen: %d\n", len);
194 }
195
64bcaae2
MW
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
6c3ac044
MW
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
3ffc9d9a
MW
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
b3d359e5
MW
273 explicit = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY);
274 inhibit = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING);
6a339fff 275 len = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY);
b3d359e5 276
6a339fff
MW
277 if (explicit != X509_NO_CONSTRAINT || inhibit != X509_NO_CONSTRAINT ||
278 len != X509_NO_CONSTRAINT)
a864eb37
MW
279 {
280 printf("PolicyConstraints:\n");
b3d359e5 281 if (explicit != X509_NO_CONSTRAINT)
a864eb37 282 {
b3d359e5 283 printf(" requireExplicitPolicy: %d\n", explicit);
a864eb37 284 }
b3d359e5 285 if (inhibit != X509_NO_CONSTRAINT)
a864eb37 286 {
b3d359e5 287 printf(" inhibitPolicyMapping: %d\n", inhibit);
a864eb37 288 }
6a339fff
MW
289 if (len != X509_NO_CONSTRAINT)
290 {
291 printf(" inhibitAnyPolicy: %d\n", len);
292 }
a864eb37
MW
293 }
294
2e57b212
MW
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
21f80e9d
MW
328/**
329 * Print CRL specific information
330 */
331static 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;
de8521f6 338 bool first;
21f80e9d
MW
339 char buf[64];
340 struct tm tm;
de8521f6 341 x509_cdp_t *cdp;
21f80e9d 342
e464894e 343 chunk = chunk_skip_zero(crl->get_serial(crl));
21f80e9d 344 printf("serial: %#B\n", &chunk);
e464894e 345
de8521f6
MW
346 if (crl->is_delta_crl(crl, &chunk))
347 {
71c9565a 348 chunk = chunk_skip_zero(chunk);
de8521f6
MW
349 printf("delta CRL: for serial %#B\n", &chunk);
350 }
21f80e9d
MW
351 chunk = crl->get_authKeyIdentifier(crl);
352 printf("authKeyId: %#B\n", &chunk);
353
de8521f6
MW
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
21f80e9d
MW
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 {
e464894e 387 chunk = chunk_skip_zero(chunk);
21f80e9d
MW
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
20ea84da
MW
396/**
397 * Print AC specific information
398 */
399static 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);
297bc06c 448 free(str);
20ea84da
MW
449 }
450 else
451 {
452 printf("OID:%#B", &chunk);
453 }
454 }
455 else
456 {
457 printf("%s", oid_names[oid].name);
458 }
459 break;
460 case AC_GROUP_TYPE_OCTETS:
461 printf("%#B", &chunk);
462 break;
463 }
464 printf("\n");
465 }
466 groups->destroy(groups);
467
468 chunk = ac->get_authKeyIdentifier(ac);
469 if (chunk.ptr)
470 {
471 printf("authkey: %#B\n", &chunk);
472 }
473}
474
2e57b212
MW
475/**
476 * Print certificate information
477 */
478static void print_cert(certificate_t *cert)
479{
480 time_t now, notAfter, notBefore;
481 public_key_t *key;
482
483 now = time(NULL);
484
485 printf("cert: %N\n", certificate_type_names, cert->get_type(cert));
21f80e9d
MW
486 if (cert->get_type(cert) != CERT_X509_CRL)
487 {
488 printf("subject: \"%Y\"\n", cert->get_subject(cert));
489 }
2e57b212
MW
490 printf("issuer: \"%Y\"\n", cert->get_issuer(cert));
491
492 cert->get_validity(cert, &now, &notBefore, &notAfter);
493 printf("validity: not before %T, ", &notBefore, FALSE);
494 if (now < notBefore)
495 {
496 printf("not valid yet (valid in %V)\n", &now, &notBefore);
497 }
498 else
499 {
500 printf("ok\n");
501 }
502 printf(" not after %T, ", &notAfter, FALSE);
503 if (now > notAfter)
504 {
505 printf("expired (%V ago)\n", &now, &notAfter);
506 }
507 else
508 {
509 printf("ok (expires in %V)\n", &now, &notAfter);
510 }
511
512 switch (cert->get_type(cert))
513 {
514 case CERT_X509:
515 print_x509((x509_t*)cert);
516 break;
21f80e9d
MW
517 case CERT_X509_CRL:
518 print_crl((crl_t*)cert);
519 break;
20ea84da
MW
520 case CERT_X509_AC:
521 print_ac((ac_t*)cert);
522 break;
2e57b212
MW
523 default:
524 printf("parsing certificate subtype %N not implemented\n",
525 certificate_type_names, cert->get_type(cert));
526 break;
527 }
2e57b212
MW
528 key = cert->get_public_key(cert);
529 if (key)
530 {
531 print_pubkey(key);
532 key->destroy(key);
533 }
2e57b212
MW
534}
535
536/**
537 * Print a credential in a human readable form
538 */
539static int print()
540{
541 credential_type_t type = CRED_CERTIFICATE;
542 int subtype = CERT_X509;
543 void *cred;
544 char *arg, *file = NULL;
545
546 while (TRUE)
547 {
548 switch (command_getopt(&arg))
549 {
550 case 'h':
551 return command_usage(NULL);
552 case 't':
553 if (streq(arg, "x509"))
554 {
555 type = CRED_CERTIFICATE;
556 subtype = CERT_X509;
557 }
21f80e9d
MW
558 else if (streq(arg, "crl"))
559 {
560 type = CRED_CERTIFICATE;
561 subtype = CERT_X509_CRL;
562 }
20ea84da
MW
563 else if (streq(arg, "ac"))
564 {
565 type = CRED_CERTIFICATE;
566 subtype = CERT_X509_AC;
567 }
2e57b212
MW
568 else if (streq(arg, "pub"))
569 {
570 type = CRED_PUBLIC_KEY;
571 subtype = KEY_ANY;
572 }
573 else if (streq(arg, "rsa-priv"))
574 {
575 type = CRED_PRIVATE_KEY;
576 subtype = KEY_RSA;
577 }
578 else if (streq(arg, "ecdsa-priv"))
579 {
580 type = CRED_PRIVATE_KEY;
581 subtype = KEY_ECDSA;
582 }
583 else
584 {
585 return command_usage( "invalid input type");
586 }
587 continue;
588 case 'i':
589 file = arg;
590 continue;
591 case EOF:
592 break;
593 default:
594 return command_usage("invalid --print option");
595 }
596 break;
597 }
598 if (file)
599 {
600 cred = lib->creds->create(lib->creds, type, subtype,
601 BUILD_FROM_FILE, file, BUILD_END);
602 }
603 else
604 {
71c9565a
TB
605 chunk_t chunk;
606
13298719 607 set_file_mode(stdin, CERT_ASN1_DER);
1c4a3459
MW
608 if (!chunk_from_fd(0, &chunk))
609 {
610 fprintf(stderr, "reading input failed: %s\n", strerror(errno));
611 return 1;
612 }
2e57b212 613 cred = lib->creds->create(lib->creds, type, subtype,
71c9565a
TB
614 BUILD_BLOB, chunk, BUILD_END);
615 free(chunk.ptr);
2e57b212
MW
616 }
617 if (!cred)
618 {
619 fprintf(stderr, "parsing input failed\n");
620 return 1;
621 }
622
623 if (type == CRED_CERTIFICATE)
624 {
625 certificate_t *cert = (certificate_t*)cred;
626
627 print_cert(cert);
628 cert->destroy(cert);
629 }
630 if (type == CRED_PUBLIC_KEY)
631 {
632 public_key_t *key = (public_key_t*)cred;
633
634 print_pubkey(key);
635 key->destroy(key);
636 }
637 if (type == CRED_PRIVATE_KEY)
638 {
639 private_key_t *key = (private_key_t*)cred;
640
641 print_key(key);
642 key->destroy(key);
643 }
644 return 0;
645}
646
647/**
648 * Register the command.
649 */
650static void __attribute__ ((constructor))reg()
651{
652 command_register((command_t)
653 { print, 'a', "print",
654 "print a credential in a human readable form",
20ea84da 655 {"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl|ac]"},
2e57b212
MW
656 {
657 {"help", 'h', 0, "show usage information"},
658 {"in", 'i', 1, "input file, default: stdin"},
659 {"type", 't', 1, "type of credential, default: x509"},
660 }
661 });
662}