84dab8566e49183e81e601ba54d9bae6ac64a4d3
[strongswan.git] / src / libstrongswan / credentials / certificates / certificate_printer.c
1 /*
2 * Copyright (C) 2015 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "certificate_printer.h"
20 #include "x509.h"
21 #include "crl.h"
22 #include "ac.h"
23
24 #include <asn1/asn1.h>
25 #include <asn1/oid.h>
26 #include <selectors/traffic_selector.h>
27
28 #include <time.h>
29
30 typedef struct private_certificate_printer_t private_certificate_printer_t;
31
32 /**
33 * Private data of an certificate_printer_t object.
34 */
35 struct private_certificate_printer_t {
36
37 /**
38 * Public certificate_printer_t interface.
39 */
40 certificate_printer_t public;
41
42 /**
43 * File to print to
44 */
45 FILE *f;
46
47 /**
48 * Print detailed certificate information
49 */
50 bool detailed;
51
52 /**
53 * Print time information in UTC
54 */
55 bool utc;
56 };
57
58 /**
59 * Print X509 specific certificate information
60 */
61 static void print_x509(private_certificate_printer_t *this, x509_t *x509)
62 {
63 enumerator_t *enumerator;
64 identification_t *id;
65 traffic_selector_t *block;
66 chunk_t chunk;
67 bool first;
68 char *uri;
69 int len, explicit, inhibit;
70 x509_flag_t flags;
71 x509_cdp_t *cdp;
72 x509_cert_policy_t *policy;
73 x509_policy_mapping_t *mapping;
74 FILE *f = this->f;
75
76 chunk = chunk_skip_zero(x509->get_serial(x509));
77 fprintf(f, " serial: %#B\n", &chunk);
78
79 first = TRUE;
80 enumerator = x509->create_subjectAltName_enumerator(x509);
81 while (enumerator->enumerate(enumerator, &id))
82 {
83 if (first)
84 {
85 fprintf(f, " altNames: ");
86 first = FALSE;
87 }
88 else
89 {
90 fprintf(f, ", ");
91 }
92 fprintf(f, "%Y", id);
93 }
94 if (!first)
95 {
96 fprintf(f, "\n");
97 }
98 enumerator->destroy(enumerator);
99
100 if (this->detailed)
101 {
102 flags = x509->get_flags(x509);
103 if (flags != X509_NONE)
104 {
105 fprintf(f, " flags: ");
106 if (flags & X509_CA)
107 {
108 fprintf(f, "CA ");
109 }
110 if (flags & X509_CRL_SIGN)
111 {
112 fprintf(f, "CRLSign ");
113 }
114 if (flags & X509_OCSP_SIGNER)
115 {
116 fprintf(f, "ocspSigning ");
117 }
118 if (flags & X509_SERVER_AUTH)
119 {
120 fprintf(f, "serverAuth ");
121 }
122 if (flags & X509_CLIENT_AUTH)
123 {
124 fprintf(f, "clientAuth ");
125 }
126 if (flags & X509_IKE_INTERMEDIATE)
127 {
128 fprintf(f, "ikeIntermediate ");
129 }
130 if (flags & X509_MS_SMARTCARD_LOGON)
131 {
132 fprintf(f, "msSmartcardLogon");
133 }
134 if (flags & X509_SELF_SIGNED)
135 {
136 fprintf(f, "self-signed ");
137 }
138 fprintf(f, "\n");
139 }
140
141 first = TRUE;
142 enumerator = x509->create_crl_uri_enumerator(x509);
143 while (enumerator->enumerate(enumerator, &cdp))
144 {
145 if (first)
146 {
147 fprintf(f, " CRL URIs: %s", cdp->uri);
148 first = FALSE;
149 }
150 else
151 {
152 fprintf(f, " %s", cdp->uri);
153 }
154 if (cdp->issuer)
155 {
156 fprintf(f, " (CRL issuer: %Y)", cdp->issuer);
157 }
158 fprintf(f, "\n");
159 }
160 enumerator->destroy(enumerator);
161
162 first = TRUE;
163 enumerator = x509->create_ocsp_uri_enumerator(x509);
164 while (enumerator->enumerate(enumerator, &uri))
165 {
166 if (first)
167 {
168 fprintf(f, " OCSP URIs: %s\n", uri);
169 first = FALSE;
170 }
171 else
172 {
173 fprintf(f, " %s\n", uri);
174 }
175 }
176 enumerator->destroy(enumerator);
177
178 len = x509->get_constraint(x509, X509_PATH_LEN);
179 if (len != X509_NO_CONSTRAINT)
180 {
181 fprintf(f, " pathlen: %d\n", len);
182 }
183
184 first = TRUE;
185 enumerator = x509->create_name_constraint_enumerator(x509, TRUE);
186 while (enumerator->enumerate(enumerator, &id))
187 {
188 if (first)
189 {
190 fprintf(f, " permitted nameConstraints:\n");
191 first = FALSE;
192 }
193 fprintf(f, " %Y\n", id);
194 }
195 enumerator->destroy(enumerator);
196
197 first = TRUE;
198 enumerator = x509->create_name_constraint_enumerator(x509, FALSE);
199 while (enumerator->enumerate(enumerator, &id))
200 {
201 if (first)
202 {
203 fprintf(f, " excluded nameConstraints:\n");
204 first = FALSE;
205 }
206 fprintf(f, " %Y\n", id);
207 }
208 enumerator->destroy(enumerator);
209
210 first = TRUE;
211 enumerator = x509->create_cert_policy_enumerator(x509);
212 while (enumerator->enumerate(enumerator, &policy))
213 {
214 char *oid;
215
216 if (first)
217 {
218 fprintf(f, " certificatePolicies:\n");
219 first = FALSE;
220 }
221 oid = asn1_oid_to_string(policy->oid);
222 if (oid)
223 {
224 fprintf(f, " %s\n", oid);
225 free(oid);
226 }
227 else
228 {
229 fprintf(f, " %#B\n", &policy->oid);
230 }
231 if (policy->cps_uri)
232 {
233 fprintf(f, " CPS: %s\n", policy->cps_uri);
234 }
235 if (policy->unotice_text)
236 {
237 fprintf(f, " Notice: %s\n", policy->unotice_text);
238 }
239 }
240 enumerator->destroy(enumerator);
241
242 first = TRUE;
243 enumerator = x509->create_policy_mapping_enumerator(x509);
244 while (enumerator->enumerate(enumerator, &mapping))
245 {
246 char *issuer_oid, *subject_oid;
247
248 if (first)
249 {
250 fprintf(f, " policyMappings:\n");
251 first = FALSE;
252 }
253 issuer_oid = asn1_oid_to_string(mapping->issuer);
254 subject_oid = asn1_oid_to_string(mapping->subject);
255 fprintf(f, " %s => %s\n", issuer_oid, subject_oid);
256 free(issuer_oid);
257 free(subject_oid);
258 }
259 enumerator->destroy(enumerator);
260
261 explicit = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY);
262 inhibit = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING);
263 len = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY);
264
265 if (explicit != X509_NO_CONSTRAINT || inhibit != X509_NO_CONSTRAINT ||
266 len != X509_NO_CONSTRAINT)
267 {
268 fprintf(f, " policyConstraints:\n");
269 if (explicit != X509_NO_CONSTRAINT)
270 {
271 fprintf(f, " requireExplicitPolicy: %d\n", explicit);
272 }
273 if (inhibit != X509_NO_CONSTRAINT)
274 {
275 fprintf(f, " inhibitPolicyMapping: %d\n", inhibit);
276 }
277 if (len != X509_NO_CONSTRAINT)
278 {
279 fprintf(f, " inhibitAnyPolicy: %d\n", len);
280 }
281 }
282
283 if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
284 {
285 first = TRUE;
286 fprintf(f, " addresses: ");
287 enumerator = x509->create_ipAddrBlock_enumerator(x509);
288 while (enumerator->enumerate(enumerator, &block))
289 {
290 if (first)
291 {
292 first = FALSE;
293 }
294 else
295 {
296 fprintf(f, ", ");
297 }
298 fprintf(f, "%R", block);
299 }
300 enumerator->destroy(enumerator);
301 fprintf(f, "\n");
302 }
303 }
304
305 chunk = x509->get_authKeyIdentifier(x509);
306 if (chunk.ptr)
307 {
308 fprintf(f, " authkeyId: %#B\n", &chunk);
309 }
310
311 chunk = x509->get_subjectKeyIdentifier(x509);
312 if (chunk.ptr)
313 {
314 fprintf(f, " subjkeyId: %#B\n", &chunk);
315 }
316 }
317
318 /**
319 * Print CRL specific information
320 */
321 static void print_crl(private_certificate_printer_t *this, crl_t *crl)
322 {
323 enumerator_t *enumerator;
324 time_t ts;
325 crl_reason_t reason;
326 chunk_t chunk;
327 int count = 0;
328 bool first;
329 char buf[64];
330 x509_cdp_t *cdp;
331 FILE *f = this->f;
332
333 chunk = chunk_skip_zero(crl->get_serial(crl));
334 fprintf(f, " serial: %#B\n", &chunk);
335
336 if (crl->is_delta_crl(crl, &chunk))
337 {
338 chunk = chunk_skip_zero(chunk);
339 fprintf(f, " delta CRL: for serial %#B\n", &chunk);
340 }
341 chunk = crl->get_authKeyIdentifier(crl);
342 fprintf(f, " authKeyId: %#B\n", &chunk);
343
344 first = TRUE;
345 enumerator = crl->create_delta_crl_uri_enumerator(crl);
346 while (enumerator->enumerate(enumerator, &cdp))
347 {
348 if (first)
349 {
350 fprintf(f, " freshest: %s", cdp->uri);
351 first = FALSE;
352 }
353 else
354 {
355 fprintf(f, " %s", cdp->uri);
356 }
357 if (cdp->issuer)
358 {
359 fprintf(f, " (CRL issuer: %Y)", cdp->issuer);
360 }
361 fprintf(f, "\n");
362 }
363 enumerator->destroy(enumerator);
364
365 enumerator = crl->create_enumerator(crl);
366 while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
367 {
368 count++;
369 }
370 enumerator->destroy(enumerator);
371
372 fprintf(f, " %d revoked certificate%s%s\n", count, (count == 1) ? "" : "s",
373 (count && this->detailed) ? ":" : "");
374
375 if (this->detailed)
376 {
377 enumerator = crl->create_enumerator(crl);
378 while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
379 {
380 chunk = chunk_skip_zero(chunk);
381 fprintf(f, " %#B: %T, %N\n", &chunk, &ts, this->utc,
382 crl_reason_names, reason);
383 }
384 enumerator->destroy(enumerator);
385 }
386 }
387
388 /**
389 * Print AC specific information
390 */
391 static void print_ac(private_certificate_printer_t *this, ac_t *ac)
392 {
393 ac_group_type_t type;
394 identification_t *id;
395 enumerator_t *groups;
396 chunk_t chunk;
397 bool first = TRUE;
398 FILE *f = this->f;
399
400 chunk = chunk_skip_zero(ac->get_serial(ac));
401 fprintf(f, " serial: %#B\n", &chunk);
402
403 id = ac->get_holderIssuer(ac);
404 if (id)
405 {
406 fprintf(f, " hissuer: \"%Y\"\n", id);
407 }
408 chunk = chunk_skip_zero(ac->get_holderSerial(ac));
409 if (chunk.ptr)
410 {
411 fprintf(f, " hserial: %#B\n", &chunk);
412 }
413 groups = ac->create_group_enumerator(ac);
414 while (groups->enumerate(groups, &type, &chunk))
415 {
416 int oid;
417 char *str;
418
419 if (first)
420 {
421 fprintf(f, " groups: ");
422 first = FALSE;
423 }
424 else
425 {
426 fprintf(f, " ");
427 }
428 switch (type)
429 {
430 case AC_GROUP_TYPE_STRING:
431 fprintf(f, "%.*s", (int)chunk.len, chunk.ptr);
432 break;
433 case AC_GROUP_TYPE_OID:
434 oid = asn1_known_oid(chunk);
435 if (oid == OID_UNKNOWN)
436 {
437 str = asn1_oid_to_string(chunk);
438 if (str)
439 {
440 fprintf(f, "%s", str);
441 free(str);
442 }
443 else
444 {
445 fprintf(f, "OID:%#B", &chunk);
446 }
447 }
448 else
449 {
450 fprintf(f, "%s", oid_names[oid].name);
451 }
452 break;
453 case AC_GROUP_TYPE_OCTETS:
454 fprintf(f, "%#B", &chunk);
455 break;
456 }
457 fprintf(f, "\n");
458 }
459 groups->destroy(groups);
460
461 chunk = ac->get_authKeyIdentifier(ac);
462 if (chunk.ptr)
463 {
464 fprintf(f, " authkey: %#B\n", &chunk);
465 }
466 }
467
468 /**
469 * Print public key information
470 */
471 static void print_pubkey(private_certificate_printer_t *this, public_key_t *key,
472 bool has_privkey)
473 {
474 chunk_t chunk;
475 FILE *f = this->f;
476
477 fprintf(f, " pubkey: %N %d bits", key_type_names, key->get_type(key),
478 key->get_keysize(key));
479 if (has_privkey)
480 {
481 fprintf(f, ", has private key");
482 }
483 fprintf(f, "\n");
484 if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
485 {
486 fprintf(f, " keyid: %#B\n", &chunk);
487 }
488 if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &chunk))
489 {
490 fprintf(f, " subjkey: %#B\n", &chunk);
491 }
492 }
493
494 METHOD(certificate_printer_t, print, void,
495 private_certificate_printer_t *this, certificate_t *cert, bool has_privkey)
496 {
497 time_t now, notAfter, notBefore;
498 certificate_type_t type;
499 identification_t *subject;
500 public_key_t *key;
501 FILE *f = this->f;
502
503 now = time(NULL);
504 type = cert->get_type(cert);
505 subject = cert->get_subject(cert);
506
507 if ((type != CERT_X509_CRL && type != CERT_X509_OCSP_RESPONSE &&
508 type != CERT_TRUSTED_PUBKEY) ||
509 (type == CERT_TRUSTED_PUBKEY && subject->get_type(subject) != ID_KEY_ID))
510 {
511 fprintf(f, " subject: \"%Y\"\n", subject);
512 }
513 if (cert->get_type(cert) != CERT_TRUSTED_PUBKEY)
514 {
515 fprintf(f, " issuer: \"%Y\"\n", cert->get_issuer(cert));
516 }
517
518 /* list validity if set */
519 cert->get_validity(cert, &now, &notBefore, &notAfter);
520 if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME)
521 {
522 fprintf(f, " validity: not before %T, ", &notBefore, this->utc);
523 if (now < notBefore)
524 {
525 fprintf(f, "not valid yet (valid in %V)\n", &now, &notBefore);
526 }
527 else
528 {
529 fprintf(f, "ok\n");
530 }
531 fprintf(f, " not after %T, ", &notAfter, this->utc);
532 if (now > notAfter)
533 {
534 fprintf(f, "expired (%V ago)\n", &now, &notAfter);
535 }
536 else
537 {
538 fprintf(f, "ok (expires in %V)\n", &now, &notAfter);
539 }
540 }
541
542 switch (cert->get_type(cert))
543 {
544 case CERT_X509:
545 print_x509(this, (x509_t*)cert);
546 break;
547 case CERT_X509_CRL:
548 print_crl(this, (crl_t*)cert);
549 break;
550 case CERT_X509_AC:
551 print_ac(this, (ac_t*)cert);
552 break;
553 case CERT_X509_OCSP_RESPONSE:
554 case CERT_TRUSTED_PUBKEY:
555 default:
556 break;
557 }
558 key = cert->get_public_key(cert);
559 if (key)
560 {
561 print_pubkey(this, key, has_privkey);
562 key->destroy(key);
563 }
564 }
565
566 METHOD(certificate_printer_t, destroy, void,
567 private_certificate_printer_t *this)
568 {
569 free(this);
570 }
571
572 /**
573 * See header
574 */
575 certificate_printer_t *certificate_printer_create(FILE *f, bool detailed,
576 bool utc)
577 {
578 private_certificate_printer_t *this;
579
580 INIT(this,
581 .public = {
582 .print = _print,
583 .destroy = _destroy,
584 },
585 .f = f,
586 .detailed = detailed,
587 .utc = utc,
588 );
589
590 return &this->public;
591 }