Annotation of embedaddon/strongswan/src/libstrongswan/credentials/certificates/certificate_printer.c, revision 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>