Return to certificate_printer.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / credentials / certificates |
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: }