Annotation of embedaddon/strongswan/src/libstrongswan/credentials/certificates/certificate_printer.c, revision 1.1.1.1
1.1 misho 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 "credentials/certificates/x509.h"
21: #include "credentials/certificates/crl.h"
22: #include "credentials/certificates/ac.h"
23: #include "credentials/certificates/ocsp_response.h"
24: #include "credentials/certificates/pgp_certificate.h"
25:
26: #include <asn1/asn1.h>
27: #include <asn1/oid.h>
28: #include <selectors/traffic_selector.h>
29:
30: #include <time.h>
31:
32: typedef struct private_certificate_printer_t private_certificate_printer_t;
33:
34: /**
35: * Private data of an certificate_printer_t object.
36: */
37: struct private_certificate_printer_t {
38:
39: /**
40: * Public certificate_printer_t interface.
41: */
42: certificate_printer_t public;
43:
44: /**
45: * File to print to
46: */
47: FILE *f;
48:
49: /**
50: * Print detailed certificate information
51: */
52: bool detailed;
53:
54: /**
55: * Print time information in UTC
56: */
57: bool utc;
58:
59: /**
60: * Previous certificate type
61: */
62: certificate_type_t type;
63:
64: /**
65: * Previous X.509 certificate flag
66: */
67: x509_flag_t flag;
68:
69: };
70:
71: /**
72: * Print X509 specific certificate information
73: */
74: static void print_x509(private_certificate_printer_t *this, x509_t *x509)
75: {
76: enumerator_t *enumerator;
77: identification_t *id;
78: traffic_selector_t *block;
79: chunk_t chunk;
80: bool first;
81: char *uri;
82: int len, explicit, inhibit;
83: x509_flag_t flags;
84: x509_cdp_t *cdp;
85: x509_cert_policy_t *policy;
86: x509_policy_mapping_t *mapping;
87: FILE *f = this->f;
88:
89: chunk = chunk_skip_zero(x509->get_serial(x509));
90: fprintf(f, " serial: %#B\n", &chunk);
91:
92: first = TRUE;
93: enumerator = x509->create_subjectAltName_enumerator(x509);
94: while (enumerator->enumerate(enumerator, &id))
95: {
96: if (first)
97: {
98: fprintf(f, " altNames: ");
99: first = FALSE;
100: }
101: else
102: {
103: fprintf(f, ", ");
104: }
105: fprintf(f, "%Y", id);
106: }
107: if (!first)
108: {
109: fprintf(f, "\n");
110: }
111: enumerator->destroy(enumerator);
112:
113: if (this->detailed)
114: {
115: flags = x509->get_flags(x509);
116: if (flags != X509_NONE)
117: {
118: fprintf(f, " flags: ");
119: if (flags & X509_CA)
120: {
121: fprintf(f, "CA ");
122: }
123: if (flags & X509_CRL_SIGN)
124: {
125: fprintf(f, "CRLSign ");
126: }
127: if (flags & X509_OCSP_SIGNER)
128: {
129: fprintf(f, "ocspSigning ");
130: }
131: if (flags & X509_SERVER_AUTH)
132: {
133: fprintf(f, "serverAuth ");
134: }
135: if (flags & X509_CLIENT_AUTH)
136: {
137: fprintf(f, "clientAuth ");
138: }
139: if (flags & X509_IKE_INTERMEDIATE)
140: {
141: fprintf(f, "ikeIntermediate ");
142: }
143: if (flags & X509_MS_SMARTCARD_LOGON)
144: {
145: fprintf(f, "msSmartcardLogon");
146: }
147: if (flags & X509_SELF_SIGNED)
148: {
149: fprintf(f, "self-signed ");
150: }
151: fprintf(f, "\n");
152: }
153:
154: first = TRUE;
155: enumerator = x509->create_crl_uri_enumerator(x509);
156: while (enumerator->enumerate(enumerator, &cdp))
157: {
158: if (first)
159: {
160: fprintf(f, " CRL URIs: %s", cdp->uri);
161: first = FALSE;
162: }
163: else
164: {
165: fprintf(f, " %s", cdp->uri);
166: }
167: if (cdp->issuer)
168: {
169: fprintf(f, " (CRL issuer: %Y)", cdp->issuer);
170: }
171: fprintf(f, "\n");
172: }
173: enumerator->destroy(enumerator);
174:
175: first = TRUE;
176: enumerator = x509->create_ocsp_uri_enumerator(x509);
177: while (enumerator->enumerate(enumerator, &uri))
178: {
179: if (first)
180: {
181: fprintf(f, " OCSP URIs: %s\n", uri);
182: first = FALSE;
183: }
184: else
185: {
186: fprintf(f, " %s\n", uri);
187: }
188: }
189: enumerator->destroy(enumerator);
190:
191: len = x509->get_constraint(x509, X509_PATH_LEN);
192: if (len != X509_NO_CONSTRAINT)
193: {
194: fprintf(f, " pathlen: %d\n", len);
195: }
196:
197: first = TRUE;
198: enumerator = x509->create_name_constraint_enumerator(x509, TRUE);
199: while (enumerator->enumerate(enumerator, &id))
200: {
201: if (first)
202: {
203: fprintf(f, " permitted 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_name_constraint_enumerator(x509, FALSE);
212: while (enumerator->enumerate(enumerator, &id))
213: {
214: if (first)
215: {
216: fprintf(f, " excluded nameConstraints:\n");
217: first = FALSE;
218: }
219: fprintf(f, " %Y\n", id);
220: }
221: enumerator->destroy(enumerator);
222:
223: first = TRUE;
224: enumerator = x509->create_cert_policy_enumerator(x509);
225: while (enumerator->enumerate(enumerator, &policy))
226: {
227: char *oid;
228:
229: if (first)
230: {
231: fprintf(f, " certificatePolicies:\n");
232: first = FALSE;
233: }
234: oid = asn1_oid_to_string(policy->oid);
235: if (oid)
236: {
237: fprintf(f, " %s\n", oid);
238: free(oid);
239: }
240: else
241: {
242: fprintf(f, " %#B\n", &policy->oid);
243: }
244: if (policy->cps_uri)
245: {
246: fprintf(f, " CPS: %s\n", policy->cps_uri);
247: }
248: if (policy->unotice_text)
249: {
250: fprintf(f, " Notice: %s\n", policy->unotice_text);
251: }
252: }
253: enumerator->destroy(enumerator);
254:
255: first = TRUE;
256: enumerator = x509->create_policy_mapping_enumerator(x509);
257: while (enumerator->enumerate(enumerator, &mapping))
258: {
259: char *issuer_oid, *subject_oid;
260:
261: if (first)
262: {
263: fprintf(f, " policyMappings:\n");
264: first = FALSE;
265: }
266: issuer_oid = asn1_oid_to_string(mapping->issuer);
267: subject_oid = asn1_oid_to_string(mapping->subject);
268: fprintf(f, " %s => %s\n", issuer_oid, subject_oid);
269: free(issuer_oid);
270: free(subject_oid);
271: }
272: enumerator->destroy(enumerator);
273:
274: explicit = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY);
275: inhibit = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING);
276: len = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY);
277:
278: if (explicit != X509_NO_CONSTRAINT || inhibit != X509_NO_CONSTRAINT ||
279: len != X509_NO_CONSTRAINT)
280: {
281: fprintf(f, " policyConstraints:\n");
282: if (explicit != X509_NO_CONSTRAINT)
283: {
284: fprintf(f, " requireExplicitPolicy: %d\n", explicit);
285: }
286: if (inhibit != X509_NO_CONSTRAINT)
287: {
288: fprintf(f, " inhibitPolicyMapping: %d\n", inhibit);
289: }
290: if (len != X509_NO_CONSTRAINT)
291: {
292: fprintf(f, " inhibitAnyPolicy: %d\n", len);
293: }
294: }
295:
296: if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
297: {
298: first = TRUE;
299: fprintf(f, " addresses: ");
300: enumerator = x509->create_ipAddrBlock_enumerator(x509);
301: while (enumerator->enumerate(enumerator, &block))
302: {
303: if (first)
304: {
305: first = FALSE;
306: }
307: else
308: {
309: fprintf(f, ", ");
310: }
311: fprintf(f, "%R", block);
312: }
313: enumerator->destroy(enumerator);
314: fprintf(f, "\n");
315: }
316: }
317:
318: chunk = x509->get_authKeyIdentifier(x509);
319: if (chunk.ptr)
320: {
321: fprintf(f, " authkeyId: %#B\n", &chunk);
322: }
323:
324: chunk = x509->get_subjectKeyIdentifier(x509);
325: if (chunk.ptr)
326: {
327: fprintf(f, " subjkeyId: %#B\n", &chunk);
328: }
329: }
330:
331: /**
332: * Print CRL specific information
333: */
334: static void print_crl(private_certificate_printer_t *this, crl_t *crl)
335: {
336: enumerator_t *enumerator;
337: time_t ts;
338: crl_reason_t reason;
339: chunk_t chunk;
340: int count = 0;
341: bool first;
342: x509_cdp_t *cdp;
343: FILE *f = this->f;
344:
345: chunk = chunk_skip_zero(crl->get_serial(crl));
346: fprintf(f, " serial: %#B\n", &chunk);
347:
348: if (crl->is_delta_crl(crl, &chunk))
349: {
350: chunk = chunk_skip_zero(chunk);
351: fprintf(f, " delta CRL: for serial %#B\n", &chunk);
352: }
353: chunk = crl->get_authKeyIdentifier(crl);
354: fprintf(f, " authKeyId: %#B\n", &chunk);
355:
356: first = TRUE;
357: enumerator = crl->create_delta_crl_uri_enumerator(crl);
358: while (enumerator->enumerate(enumerator, &cdp))
359: {
360: if (first)
361: {
362: fprintf(f, " freshest: %s", cdp->uri);
363: first = FALSE;
364: }
365: else
366: {
367: fprintf(f, " %s", cdp->uri);
368: }
369: if (cdp->issuer)
370: {
371: fprintf(f, " (CRL issuer: %Y)", cdp->issuer);
372: }
373: fprintf(f, "\n");
374: }
375: enumerator->destroy(enumerator);
376:
377: enumerator = crl->create_enumerator(crl);
378: while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
379: {
380: count++;
381: }
382: enumerator->destroy(enumerator);
383:
384: fprintf(f, " %d revoked certificate%s%s\n", count, (count == 1) ? "" : "s",
385: (count && this->detailed) ? ":" : "");
386:
387: if (this->detailed)
388: {
389: enumerator = crl->create_enumerator(crl);
390: while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
391: {
392: chunk = chunk_skip_zero(chunk);
393: fprintf(f, " %#B: %T, %N\n", &chunk, &ts, this->utc,
394: crl_reason_names, reason);
395: }
396: enumerator->destroy(enumerator);
397: }
398: }
399:
400: /**
401: * Print AC specific information
402: */
403: static void print_ac(private_certificate_printer_t *this, ac_t *ac)
404: {
405: ac_group_type_t type;
406: identification_t *id;
407: enumerator_t *groups;
408: chunk_t chunk;
409: bool first = TRUE;
410: FILE *f = this->f;
411:
412: chunk = chunk_skip_zero(ac->get_serial(ac));
413: fprintf(f, " serial: %#B\n", &chunk);
414:
415: id = ac->get_holderIssuer(ac);
416: if (id)
417: {
418: fprintf(f, " hissuer: \"%Y\"\n", id);
419: }
420: chunk = chunk_skip_zero(ac->get_holderSerial(ac));
421: if (chunk.ptr)
422: {
423: fprintf(f, " hserial: %#B\n", &chunk);
424: }
425: groups = ac->create_group_enumerator(ac);
426: while (groups->enumerate(groups, &type, &chunk))
427: {
428: int oid;
429: char *str;
430:
431: if (first)
432: {
433: fprintf(f, " groups: ");
434: first = FALSE;
435: }
436: else
437: {
438: fprintf(f, " ");
439: }
440: switch (type)
441: {
442: case AC_GROUP_TYPE_STRING:
443: fprintf(f, "%.*s", (int)chunk.len, chunk.ptr);
444: break;
445: case AC_GROUP_TYPE_OID:
446: oid = asn1_known_oid(chunk);
447: if (oid == OID_UNKNOWN)
448: {
449: str = asn1_oid_to_string(chunk);
450: if (str)
451: {
452: fprintf(f, "%s", str);
453: free(str);
454: }
455: else
456: {
457: fprintf(f, "OID:%#B", &chunk);
458: }
459: }
460: else
461: {
462: fprintf(f, "%s", oid_names[oid].name);
463: }
464: break;
465: case AC_GROUP_TYPE_OCTETS:
466: fprintf(f, "%#B", &chunk);
467: break;
468: }
469: fprintf(f, "\n");
470: }
471: groups->destroy(groups);
472:
473: chunk = ac->get_authKeyIdentifier(ac);
474: if (chunk.ptr)
475: {
476: fprintf(f, " authkey: %#B\n", &chunk);
477: }
478: }
479:
480: /**
481: * Print OCSP response specific information
482: */
483: static void print_ocsp_response(private_certificate_printer_t *this,
484: ocsp_response_t *ocsp_response)
485: {
486: enumerator_t *enumerator;
487: chunk_t serialNumber;
488: cert_validation_t status;
489: char *status_text;
490: time_t revocationTime;
491: crl_reason_t *revocationReason;
492: bool first = TRUE;
493: FILE *f = this->f;
494:
495: if (this->detailed)
496: {
497: fprintf(f, " responses: ");
498:
499: enumerator = ocsp_response->create_response_enumerator(ocsp_response);
500: while (enumerator->enumerate(enumerator, &serialNumber, &status,
501: &revocationTime, &revocationReason))
502: {
503: if (first)
504: {
505: first = FALSE;
506: }
507: else
508: {
509: fprintf(f, " ");
510: }
511: serialNumber = chunk_skip_zero(serialNumber);
512:
513: switch (status)
514: {
515: case VALIDATION_GOOD:
516: status_text = "good";
517: break;
518: case VALIDATION_REVOKED:
519: status_text = "revoked";
520: break;
521: default:
522: status_text = "unknown";
523: }
524: fprintf(f, "%#B: %s", &serialNumber, status_text);
525:
526: if (status == VALIDATION_REVOKED)
527: {
528: fprintf(f, " on %T, %N", &revocationTime, this->utc,
529: crl_reason_names, revocationReason);
530: }
531: fprintf(f, "\n");
532: }
533: enumerator->destroy(enumerator);
534: }
535: }
536:
537: /**
538: * Print public key information
539: */
540: static void print_pubkey(private_certificate_printer_t *this, public_key_t *key,
541: bool has_privkey)
542: {
543: chunk_t chunk;
544: FILE *f = this->f;
545:
546: fprintf(f, " pubkey: %N %d bits", key_type_names, key->get_type(key),
547: key->get_keysize(key));
548: if (has_privkey)
549: {
550: fprintf(f, ", has private key");
551: }
552: fprintf(f, "\n");
553: if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
554: {
555: fprintf(f, " keyid: %#B\n", &chunk);
556: }
557: if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &chunk))
558: {
559: fprintf(f, " subjkey: %#B\n", &chunk);
560: }
561: }
562:
563: METHOD(certificate_printer_t, print, void,
564: private_certificate_printer_t *this, certificate_t *cert, bool has_privkey)
565: {
566: time_t now, notAfter, notBefore;
567: certificate_type_t type;
568: identification_t *subject;
569: char *t0, *t1, *t2;
570: public_key_t *key;
571: FILE *f = this->f;
572:
573: now = time(NULL);
574: type = cert->get_type(cert);
575: subject = cert->get_subject(cert);
576:
577: if ((type != CERT_X509_CRL && type != CERT_X509_OCSP_RESPONSE &&
578: type != CERT_TRUSTED_PUBKEY) ||
579: (type == CERT_TRUSTED_PUBKEY && subject->get_type(subject) != ID_KEY_ID))
580: {
581: fprintf(f, " subject: \"%Y\"\n", subject);
582: }
583: if (type != CERT_TRUSTED_PUBKEY && type != CERT_GPG)
584: {
585: fprintf(f, " issuer: \"%Y\"\n", cert->get_issuer(cert));
586: }
587:
588: /* list validity if set */
589: cert->get_validity(cert, &now, ¬Before, ¬After);
590: if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME)
591: {
592: if (type == CERT_GPG)
593: {
594: fprintf(f, " created: %T\n", ¬Before, this->utc);
595: fprintf(f, " until: %T%s\n", ¬After, this->utc,
596: (notAfter == TIME_32_BIT_SIGNED_MAX) ?" expires never" : "");
597: }
598: else
599: {
600: if (type == CERT_X509_CRL || type == CERT_X509_OCSP_RESPONSE)
601: {
602: t0 = "update: ";
603: t1 = "this on";
604: t2 = "next on";
605: }
606: else
607: {
608: t0 = "validity:";
609: t1 = "not before";
610: t2 = "not after ";
611: }
612: fprintf(f, " %s %s %T, ", t0, t1, ¬Before, this->utc);
613: if (now < notBefore)
614: {
615: fprintf(f, "not valid yet (valid in %V)\n", &now, ¬Before);
616: }
617: else
618: {
619: fprintf(f, "ok\n");
620: }
621: fprintf(f, " %s %T, ", t2, ¬After, this->utc);
622: if (now > notAfter)
623: {
624: fprintf(f, "expired (%V ago)\n", &now, ¬After);
625: }
626: else
627: {
628: fprintf(f, "ok (expires in %V)\n", &now, ¬After);
629: }
630: }
631: }
632:
633: switch (cert->get_type(cert))
634: {
635: case CERT_X509:
636: print_x509(this, (x509_t*)cert);
637: break;
638: case CERT_X509_CRL:
639: print_crl(this, (crl_t*)cert);
640: break;
641: case CERT_X509_AC:
642: print_ac(this, (ac_t*)cert);
643: break;
644: case CERT_X509_OCSP_RESPONSE:
645: print_ocsp_response(this, (ocsp_response_t*)cert);
646: break;
647: case CERT_TRUSTED_PUBKEY:
648: default:
649: break;
650: }
651: if (type == CERT_GPG)
652: {
653: pgp_certificate_t *pgp_cert = (pgp_certificate_t*)cert;
654: chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
655:
656: fprintf(f, " pgpDigest: %#B\n", &fingerprint);
657: }
658: key = cert->get_public_key(cert);
659: if (key)
660: {
661: print_pubkey(this, key, has_privkey);
662: key->destroy(key);
663: }
664: }
665:
666: METHOD(certificate_printer_t, print_caption, void,
667: private_certificate_printer_t *this, certificate_type_t type,
668: x509_flag_t flag)
669: {
670: char *caption;
671:
672: if (type != this->type || (type == CERT_X509 && flag != this->flag))
673: {
674: switch (type)
675: {
676: case CERT_X509:
677: switch (flag)
678: {
679: case X509_NONE:
680: caption = "X.509 End Entity Certificate";
681: break;
682: case X509_CA:
683: caption = "X.509 CA Certificate";
684: break;
685: case X509_AA:
686: caption = "X.509 AA Certificate";
687: break;
688: case X509_OCSP_SIGNER:
689: caption = "X.509 OCSP Signer Certificate";
690: break;
691: default:
692: return;
693: }
694: break;
695: case CERT_X509_AC:
696: caption = "X.509 Attribute Certificate";
697: break;
698: case CERT_X509_CRL:
699: caption = "X.509 CRL";
700: break;
701: case CERT_X509_OCSP_RESPONSE:
702: caption = "OCSP Response";
703: break;
704: case CERT_TRUSTED_PUBKEY:
705: caption = "Raw Public Key";
706: break;
707: case CERT_GPG:
708: caption = "PGP End Entity Certificate";
709: break;
710: default:
711: return;
712: }
713: fprintf(this->f, "\nList of %ss\n", caption);
714:
715: /* Update to current type and flag value */
716: this->type = type;
717: if (type == CERT_X509)
718: {
719: this->flag = flag;
720: }
721: }
722: fprintf(this->f, "\n");
723: }
724:
725: METHOD(certificate_printer_t, destroy, void,
726: private_certificate_printer_t *this)
727: {
728: free(this);
729: }
730:
731: /**
732: * See header
733: */
734: certificate_printer_t *certificate_printer_create(FILE *f, bool detailed,
735: bool utc)
736: {
737: private_certificate_printer_t *this;
738:
739: INIT(this,
740: .public = {
741: .print = _print,
742: .print_caption = _print_caption,
743: .destroy = _destroy,
744: },
745: .f = f,
746: .detailed = detailed,
747: .utc = utc,
748: .type = CERT_ANY,
749: .flag = X509_ANY,
750: );
751:
752: return &this->public;
753: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>