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