1 /* 2 * Copyright (c) 2004 - 2007 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "hx_locl.h" 35 RCSID("$Id: print.c 22420 2008-01-13 09:42:35Z lha $"); 36 37 /** 38 * @page page_print Hx509 printing functions 39 * 40 * See the library functions here: @ref hx509_print 41 */ 42 43 struct hx509_validate_ctx_data { 44 int flags; 45 hx509_vprint_func vprint_func; 46 void *ctx; 47 }; 48 49 struct cert_status { 50 unsigned int selfsigned:1; 51 unsigned int isca:1; 52 unsigned int isproxy:1; 53 unsigned int haveSAN:1; 54 unsigned int haveIAN:1; 55 unsigned int haveSKI:1; 56 unsigned int haveAKI:1; 57 unsigned int haveCRLDP:1; 58 }; 59 60 61 /* 62 * 63 */ 64 65 static int 66 Time2string(const Time *T, char **str) 67 { 68 time_t t; 69 char *s; 70 struct tm *tm; 71 72 *str = NULL; 73 t = _hx509_Time2time_t(T); 74 tm = gmtime (&t); 75 s = malloc(30); 76 if (s == NULL) 77 return ENOMEM; 78 strftime(s, 30, "%Y-%m-%d %H:%M:%S", tm); 79 *str = s; 80 return 0; 81 } 82 83 /** 84 * Helper function to print on stdout for: 85 * - hx509_oid_print(), 86 * - hx509_bitstring_print(), 87 * - hx509_validate_ctx_set_print(). 88 * 89 * @param ctx the context to the print function. If the ctx is NULL, 90 * stdout is used. 91 * @param fmt the printing format. 92 * @param va the argumet list. 93 * 94 * @ingroup hx509_print 95 */ 96 97 void 98 hx509_print_stdout(void *ctx, const char *fmt, va_list va) 99 { 100 FILE *f = ctx; 101 if (f == NULL) 102 f = stdout; 103 vfprintf(f, fmt, va); 104 } 105 106 static void 107 print_func(hx509_vprint_func func, void *ctx, const char *fmt, ...) 108 { 109 va_list va; 110 va_start(va, fmt); 111 (*func)(ctx, fmt, va); 112 va_end(va); 113 } 114 115 /** 116 * Print a oid to a string. 117 * 118 * @param oid oid to print 119 * @param str allocated string, free with hx509_xfree(). 120 * 121 * @return An hx509 error code, see hx509_get_error_string(). 122 * 123 * @ingroup hx509_print 124 */ 125 126 int 127 hx509_oid_sprint(const heim_oid *oid, char **str) 128 { 129 return der_print_heim_oid(oid, '.', str); 130 } 131 132 /** 133 * Print a oid using a hx509_vprint_func function. To print to stdout 134 * use hx509_print_stdout(). 135 * 136 * @param oid oid to print 137 * @param func hx509_vprint_func to print with. 138 * @param ctx context variable to hx509_vprint_func function. 139 * 140 * @ingroup hx509_print 141 */ 142 143 void 144 hx509_oid_print(const heim_oid *oid, hx509_vprint_func func, void *ctx) 145 { 146 char *str; 147 hx509_oid_sprint(oid, &str); 148 print_func(func, ctx, "%s", str); 149 free(str); 150 } 151 152 /** 153 * Print a bitstring using a hx509_vprint_func function. To print to 154 * stdout use hx509_print_stdout(). 155 * 156 * @param b bit string to print. 157 * @param func hx509_vprint_func to print with. 158 * @param ctx context variable to hx509_vprint_func function. 159 * 160 * @ingroup hx509_print 161 */ 162 163 void 164 hx509_bitstring_print(const heim_bit_string *b, 165 hx509_vprint_func func, void *ctx) 166 { 167 int i; 168 print_func(func, ctx, "\tlength: %d\n\t", b->length); 169 for (i = 0; i < (b->length + 7) / 8; i++) 170 print_func(func, ctx, "%02x%s%s", 171 ((unsigned char *)b->data)[i], 172 i < (b->length - 7) / 8 173 && (i == 0 || (i % 16) != 15) ? ":" : "", 174 i != 0 && (i % 16) == 15 ? 175 (i <= ((b->length + 7) / 8 - 2) ? "\n\t" : "\n"):""); 176 } 177 178 /** 179 * Print certificate usage for a certificate to a string. 180 * 181 * @param context A hx509 context. 182 * @param c a certificate print the keyusage for. 183 * @param s the return string with the keysage printed in to, free 184 * with hx509_xfree(). 185 * 186 * @return An hx509 error code, see hx509_get_error_string(). 187 * 188 * @ingroup hx509_print 189 */ 190 191 int 192 hx509_cert_keyusage_print(hx509_context context, hx509_cert c, char **s) 193 { 194 KeyUsage ku; 195 char buf[256]; 196 int ret; 197 198 *s = NULL; 199 200 ret = _hx509_cert_get_keyusage(context, c, &ku); 201 if (ret) 202 return ret; 203 unparse_flags(KeyUsage2int(ku), asn1_KeyUsage_units(), buf, sizeof(buf)); 204 *s = strdup(buf); 205 if (*s == NULL) { 206 hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 207 return ENOMEM; 208 } 209 210 return 0; 211 } 212 213 /* 214 * 215 */ 216 217 static void 218 validate_vprint(void *c, const char *fmt, va_list va) 219 { 220 hx509_validate_ctx ctx = c; 221 if (ctx->vprint_func == NULL) 222 return; 223 (ctx->vprint_func)(ctx->ctx, fmt, va); 224 } 225 226 static void 227 validate_print(hx509_validate_ctx ctx, int flags, const char *fmt, ...) 228 { 229 va_list va; 230 if ((ctx->flags & flags) == 0) 231 return; 232 va_start(va, fmt); 233 validate_vprint(ctx, fmt, va); 234 va_end(va); 235 } 236 237 /* 238 * Dont Care, SHOULD critical, SHOULD NOT critical, MUST critical, 239 * MUST NOT critical 240 */ 241 enum critical_flag { D_C = 0, S_C, S_N_C, M_C, M_N_C }; 242 243 static int 244 check_Null(hx509_validate_ctx ctx, 245 struct cert_status *status, 246 enum critical_flag cf, const Extension *e) 247 { 248 switch(cf) { 249 case D_C: 250 break; 251 case S_C: 252 if (!e->critical) 253 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 254 "\tCritical not set on SHOULD\n"); 255 break; 256 case S_N_C: 257 if (e->critical) 258 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 259 "\tCritical set on SHOULD NOT\n"); 260 break; 261 case M_C: 262 if (!e->critical) 263 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 264 "\tCritical not set on MUST\n"); 265 break; 266 case M_N_C: 267 if (e->critical) 268 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 269 "\tCritical set on MUST NOT\n"); 270 break; 271 default: 272 _hx509_abort("internal check_Null state error"); 273 } 274 return 0; 275 } 276 277 static int 278 check_subjectKeyIdentifier(hx509_validate_ctx ctx, 279 struct cert_status *status, 280 enum critical_flag cf, 281 const Extension *e) 282 { 283 SubjectKeyIdentifier si; 284 size_t size; 285 int ret; 286 287 status->haveSKI = 1; 288 check_Null(ctx, status, cf, e); 289 290 ret = decode_SubjectKeyIdentifier(e->extnValue.data, 291 e->extnValue.length, 292 &si, &size); 293 if (ret) { 294 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 295 "Decoding SubjectKeyIdentifier failed: %d", ret); 296 return 1; 297 } 298 if (size != e->extnValue.length) { 299 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 300 "Decoding SKI ahve extra bits on the end"); 301 return 1; 302 } 303 if (si.length == 0) 304 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 305 "SKI is too short (0 bytes)"); 306 if (si.length > 20) 307 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 308 "SKI is too long"); 309 310 { 311 char *id; 312 hex_encode(si.data, si.length, &id); 313 if (id) { 314 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 315 "\tsubject key id: %s\n", id); 316 free(id); 317 } 318 } 319 320 free_SubjectKeyIdentifier(&si); 321 322 return 0; 323 } 324 325 static int 326 check_authorityKeyIdentifier(hx509_validate_ctx ctx, 327 struct cert_status *status, 328 enum critical_flag cf, 329 const Extension *e) 330 { 331 AuthorityKeyIdentifier ai; 332 size_t size; 333 int ret; 334 335 status->haveAKI = 1; 336 check_Null(ctx, status, cf, e); 337 338 status->haveSKI = 1; 339 check_Null(ctx, status, cf, e); 340 341 ret = decode_AuthorityKeyIdentifier(e->extnValue.data, 342 e->extnValue.length, 343 &ai, &size); 344 if (ret) { 345 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 346 "Decoding AuthorityKeyIdentifier failed: %d", ret); 347 return 1; 348 } 349 if (size != e->extnValue.length) { 350 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 351 "Decoding SKI ahve extra bits on the end"); 352 return 1; 353 } 354 355 if (ai.keyIdentifier) { 356 char *id; 357 hex_encode(ai.keyIdentifier->data, ai.keyIdentifier->length, &id); 358 if (id) { 359 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 360 "\tauthority key id: %s\n", id); 361 free(id); 362 } 363 } 364 365 return 0; 366 } 367 368 369 static int 370 check_pkinit_san(hx509_validate_ctx ctx, heim_any *a) 371 { 372 KRB5PrincipalName kn; 373 unsigned i; 374 size_t size; 375 int ret; 376 377 ret = decode_KRB5PrincipalName(a->data, a->length, &kn, &size); 378 if (ret) { 379 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 380 "Decoding kerberos name in SAN failed: %d", ret); 381 return 1; 382 } 383 384 if (size != a->length) { 385 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 386 "Decoding kerberos name have extra bits on the end"); 387 return 1; 388 } 389 390 /* print kerberos principal, add code to quote / within components */ 391 for (i = 0; i < kn.principalName.name_string.len; i++) { 392 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", 393 kn.principalName.name_string.val[i]); 394 if (i + 1 < kn.principalName.name_string.len) 395 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "/"); 396 } 397 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "@"); 398 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", kn.realm); 399 400 free_KRB5PrincipalName(&kn); 401 return 0; 402 } 403 404 static int 405 check_utf8_string_san(hx509_validate_ctx ctx, heim_any *a) 406 { 407 PKIXXmppAddr jid; 408 size_t size; 409 int ret; 410 411 ret = decode_PKIXXmppAddr(a->data, a->length, &jid, &size); 412 if (ret) { 413 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 414 "Decoding JID in SAN failed: %d", ret); 415 return 1; 416 } 417 418 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", jid); 419 free_PKIXXmppAddr(&jid); 420 421 return 0; 422 } 423 424 static int 425 check_altnull(hx509_validate_ctx ctx, heim_any *a) 426 { 427 return 0; 428 } 429 430 static int 431 check_CRLDistributionPoints(hx509_validate_ctx ctx, 432 struct cert_status *status, 433 enum critical_flag cf, 434 const Extension *e) 435 { 436 CRLDistributionPoints dp; 437 size_t size; 438 int ret, i; 439 440 check_Null(ctx, status, cf, e); 441 442 ret = decode_CRLDistributionPoints(e->extnValue.data, 443 e->extnValue.length, 444 &dp, &size); 445 if (ret) { 446 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 447 "Decoding CRL Distribution Points failed: %d\n", ret); 448 return 1; 449 } 450 451 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "CRL Distribution Points:\n"); 452 for (i = 0 ; i < dp.len; i++) { 453 if (dp.val[i].distributionPoint) { 454 DistributionPointName dpname; 455 heim_any *data = dp.val[i].distributionPoint; 456 int j; 457 458 ret = decode_DistributionPointName(data->data, data->length, 459 &dpname, NULL); 460 if (ret) { 461 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 462 "Failed to parse CRL Distribution Point Name: %d\n", ret); 463 continue; 464 } 465 466 switch (dpname.element) { 467 case choice_DistributionPointName_fullName: 468 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "Fullname:\n"); 469 470 for (j = 0 ; j < dpname.u.fullName.len; j++) { 471 char *s; 472 GeneralName *name = &dpname.u.fullName.val[j]; 473 474 ret = hx509_general_name_unparse(name, &s); 475 if (ret == 0 && s != NULL) { 476 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " %s\n", s); 477 free(s); 478 } 479 } 480 break; 481 case choice_DistributionPointName_nameRelativeToCRLIssuer: 482 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 483 "Unknown nameRelativeToCRLIssuer"); 484 break; 485 default: 486 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 487 "Unknown DistributionPointName"); 488 break; 489 } 490 free_DistributionPointName(&dpname); 491 } 492 } 493 free_CRLDistributionPoints(&dp); 494 495 status->haveCRLDP = 1; 496 497 return 0; 498 } 499 500 501 struct { 502 const char *name; 503 const heim_oid *(*oid)(void); 504 int (*func)(hx509_validate_ctx, heim_any *); 505 } check_altname[] = { 506 { "pk-init", oid_id_pkinit_san, check_pkinit_san }, 507 { "jabber", oid_id_pkix_on_xmppAddr, check_utf8_string_san }, 508 { "dns-srv", oid_id_pkix_on_dnsSRV, check_altnull }, 509 { "card-id", oid_id_uspkicommon_card_id, check_altnull }, 510 { "Microsoft NT-PRINCIPAL-NAME", oid_id_pkinit_ms_san, check_utf8_string_san } 511 }; 512 513 static int 514 check_altName(hx509_validate_ctx ctx, 515 struct cert_status *status, 516 const char *name, 517 enum critical_flag cf, 518 const Extension *e) 519 { 520 GeneralNames gn; 521 size_t size; 522 int ret, i; 523 524 check_Null(ctx, status, cf, e); 525 526 if (e->extnValue.length == 0) { 527 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 528 "%sAltName empty, not allowed", name); 529 return 1; 530 } 531 ret = decode_GeneralNames(e->extnValue.data, e->extnValue.length, 532 &gn, &size); 533 if (ret) { 534 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 535 "\tret = %d while decoding %s GeneralNames\n", 536 ret, name); 537 return 1; 538 } 539 if (gn.len == 0) { 540 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 541 "%sAltName generalName empty, not allowed\n", name); 542 return 1; 543 } 544 545 for (i = 0; i < gn.len; i++) { 546 switch (gn.val[i].element) { 547 case choice_GeneralName_otherName: { 548 unsigned j; 549 550 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 551 "%sAltName otherName ", name); 552 553 for (j = 0; j < sizeof(check_altname)/sizeof(check_altname[0]); j++) { 554 if (der_heim_oid_cmp((*check_altname[j].oid)(), 555 &gn.val[i].u.otherName.type_id) != 0) 556 continue; 557 558 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s: ", 559 check_altname[j].name); 560 (*check_altname[j].func)(ctx, &gn.val[i].u.otherName.value); 561 break; 562 } 563 if (j == sizeof(check_altname)/sizeof(check_altname[0])) { 564 hx509_oid_print(&gn.val[i].u.otherName.type_id, 565 validate_vprint, ctx); 566 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " unknown"); 567 } 568 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\n"); 569 break; 570 } 571 default: { 572 char *s; 573 ret = hx509_general_name_unparse(&gn.val[i], &s); 574 if (ret) { 575 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 576 "ret = %d unparsing GeneralName\n", ret); 577 return 1; 578 } 579 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s\n", s); 580 free(s); 581 break; 582 } 583 } 584 } 585 586 free_GeneralNames(&gn); 587 588 return 0; 589 } 590 591 static int 592 check_subjectAltName(hx509_validate_ctx ctx, 593 struct cert_status *status, 594 enum critical_flag cf, 595 const Extension *e) 596 { 597 status->haveSAN = 1; 598 return check_altName(ctx, status, "subject", cf, e); 599 } 600 601 static int 602 check_issuerAltName(hx509_validate_ctx ctx, 603 struct cert_status *status, 604 enum critical_flag cf, 605 const Extension *e) 606 { 607 status->haveIAN = 1; 608 return check_altName(ctx, status, "issuer", cf, e); 609 } 610 611 612 static int 613 check_basicConstraints(hx509_validate_ctx ctx, 614 struct cert_status *status, 615 enum critical_flag cf, 616 const Extension *e) 617 { 618 BasicConstraints b; 619 size_t size; 620 int ret; 621 622 check_Null(ctx, status, cf, e); 623 624 ret = decode_BasicConstraints(e->extnValue.data, e->extnValue.length, 625 &b, &size); 626 if (ret) { 627 printf("\tret = %d while decoding BasicConstraints\n", ret); 628 return 0; 629 } 630 if (size != e->extnValue.length) 631 printf("\tlength of der data isn't same as extension\n"); 632 633 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 634 "\tis %sa CA\n", b.cA && *b.cA ? "" : "NOT "); 635 if (b.pathLenConstraint) 636 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 637 "\tpathLenConstraint: %d\n", *b.pathLenConstraint); 638 639 if (b.cA) { 640 if (*b.cA) { 641 if (!e->critical) 642 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 643 "Is a CA and not BasicConstraints CRITICAL\n"); 644 status->isca = 1; 645 } 646 else 647 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 648 "cA is FALSE, not allowed to be\n"); 649 } 650 free_BasicConstraints(&b); 651 652 return 0; 653 } 654 655 static int 656 check_proxyCertInfo(hx509_validate_ctx ctx, 657 struct cert_status *status, 658 enum critical_flag cf, 659 const Extension *e) 660 { 661 check_Null(ctx, status, cf, e); 662 status->isproxy = 1; 663 return 0; 664 } 665 666 static int 667 check_authorityInfoAccess(hx509_validate_ctx ctx, 668 struct cert_status *status, 669 enum critical_flag cf, 670 const Extension *e) 671 { 672 AuthorityInfoAccessSyntax aia; 673 size_t size; 674 int ret, i; 675 676 check_Null(ctx, status, cf, e); 677 678 ret = decode_AuthorityInfoAccessSyntax(e->extnValue.data, 679 e->extnValue.length, 680 &aia, &size); 681 if (ret) { 682 printf("\tret = %d while decoding AuthorityInfoAccessSyntax\n", ret); 683 return 0; 684 } 685 686 for (i = 0; i < aia.len; i++) { 687 char *str; 688 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 689 "\ttype: "); 690 hx509_oid_print(&aia.val[i].accessMethod, validate_vprint, ctx); 691 hx509_general_name_unparse(&aia.val[i].accessLocation, &str); 692 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 693 "\n\tdirname: %s\n", str); 694 free(str); 695 } 696 free_AuthorityInfoAccessSyntax(&aia); 697 698 return 0; 699 } 700 701 /* 702 * 703 */ 704 705 struct { 706 const char *name; 707 const heim_oid *(*oid)(void); 708 int (*func)(hx509_validate_ctx ctx, 709 struct cert_status *status, 710 enum critical_flag cf, 711 const Extension *); 712 enum critical_flag cf; 713 } check_extension[] = { 714 #define ext(name, checkname) #name, &oid_id_x509_ce_##name, check_##checkname 715 { ext(subjectDirectoryAttributes, Null), M_N_C }, 716 { ext(subjectKeyIdentifier, subjectKeyIdentifier), M_N_C }, 717 { ext(keyUsage, Null), S_C }, 718 { ext(subjectAltName, subjectAltName), M_N_C }, 719 { ext(issuerAltName, issuerAltName), S_N_C }, 720 { ext(basicConstraints, basicConstraints), D_C }, 721 { ext(cRLNumber, Null), M_N_C }, 722 { ext(cRLReason, Null), M_N_C }, 723 { ext(holdInstructionCode, Null), M_N_C }, 724 { ext(invalidityDate, Null), M_N_C }, 725 { ext(deltaCRLIndicator, Null), M_C }, 726 { ext(issuingDistributionPoint, Null), M_C }, 727 { ext(certificateIssuer, Null), M_C }, 728 { ext(nameConstraints, Null), M_C }, 729 { ext(cRLDistributionPoints, CRLDistributionPoints), S_N_C }, 730 { ext(certificatePolicies, Null) }, 731 { ext(policyMappings, Null), M_N_C }, 732 { ext(authorityKeyIdentifier, authorityKeyIdentifier), M_N_C }, 733 { ext(policyConstraints, Null), D_C }, 734 { ext(extKeyUsage, Null), D_C }, 735 { ext(freshestCRL, Null), M_N_C }, 736 { ext(inhibitAnyPolicy, Null), M_C }, 737 #undef ext 738 #define ext(name, checkname) #name, &oid_id_pkix_pe_##name, check_##checkname 739 { ext(proxyCertInfo, proxyCertInfo), M_C }, 740 { ext(authorityInfoAccess, authorityInfoAccess), M_C }, 741 #undef ext 742 { "US Fed PKI - PIV Interim", oid_id_uspkicommon_piv_interim, 743 check_Null, D_C }, 744 { "Netscape cert comment", oid_id_netscape_cert_comment, 745 check_Null, D_C }, 746 { NULL } 747 }; 748 749 /** 750 * Allocate a hx509 validation/printing context. 751 * 752 * @param context A hx509 context. 753 * @param ctx a new allocated hx509 validation context, free with 754 * hx509_validate_ctx_free(). 755 756 * @return An hx509 error code, see hx509_get_error_string(). 757 * 758 * @ingroup hx509_print 759 */ 760 761 int 762 hx509_validate_ctx_init(hx509_context context, hx509_validate_ctx *ctx) 763 { 764 *ctx = malloc(sizeof(**ctx)); 765 if (*ctx == NULL) 766 return ENOMEM; 767 memset(*ctx, 0, sizeof(**ctx)); 768 return 0; 769 } 770 771 /** 772 * Set the printing functions for the validation context. 773 * 774 * @param ctx a hx509 valication context. 775 * @param func the printing function to usea. 776 * @param c the context variable to the printing function. 777 * 778 * @return An hx509 error code, see hx509_get_error_string(). 779 * 780 * @ingroup hx509_print 781 */ 782 783 void 784 hx509_validate_ctx_set_print(hx509_validate_ctx ctx, 785 hx509_vprint_func func, 786 void *c) 787 { 788 ctx->vprint_func = func; 789 ctx->ctx = c; 790 } 791 792 /** 793 * Add flags to control the behaivor of the hx509_validate_cert() 794 * function. 795 * 796 * @param ctx A hx509 validation context. 797 * @param flags flags to add to the validation context. 798 * 799 * @return An hx509 error code, see hx509_get_error_string(). 800 * 801 * @ingroup hx509_print 802 */ 803 804 void 805 hx509_validate_ctx_add_flags(hx509_validate_ctx ctx, int flags) 806 { 807 ctx->flags |= flags; 808 } 809 810 /** 811 * Free an hx509 validate context. 812 * 813 * @param ctx the hx509 validate context to free. 814 * 815 * @ingroup hx509_print 816 */ 817 818 void 819 hx509_validate_ctx_free(hx509_validate_ctx ctx) 820 { 821 free(ctx); 822 } 823 824 /** 825 * Validate/Print the status of the certificate. 826 * 827 * @param context A hx509 context. 828 * @param ctx A hx509 validation context. 829 * @param cert the cerificate to validate/print. 830 831 * @return An hx509 error code, see hx509_get_error_string(). 832 * 833 * @ingroup hx509_print 834 */ 835 836 int 837 hx509_validate_cert(hx509_context context, 838 hx509_validate_ctx ctx, 839 hx509_cert cert) 840 { 841 Certificate *c = _hx509_get_cert(cert); 842 TBSCertificate *t = &c->tbsCertificate; 843 hx509_name issuer, subject; 844 char *str; 845 struct cert_status status; 846 int ret; 847 848 memset(&status, 0, sizeof(status)); 849 850 if (_hx509_cert_get_version(c) != 3) 851 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 852 "Not version 3 certificate\n"); 853 854 if ((t->version == NULL || *t->version < 2) && t->extensions) 855 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 856 "Not version 3 certificate with extensions\n"); 857 858 if (_hx509_cert_get_version(c) >= 3 && t->extensions == NULL) 859 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 860 "Version 3 certificate without extensions\n"); 861 862 ret = hx509_cert_get_subject(cert, &subject); 863 if (ret) abort(); 864 hx509_name_to_string(subject, &str); 865 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 866 "subject name: %s\n", str); 867 free(str); 868 869 ret = hx509_cert_get_issuer(cert, &issuer); 870 if (ret) abort(); 871 hx509_name_to_string(issuer, &str); 872 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 873 "issuer name: %s\n", str); 874 free(str); 875 876 if (hx509_name_cmp(subject, issuer) == 0) { 877 status.selfsigned = 1; 878 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 879 "\tis a self-signed certificate\n"); 880 } 881 882 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 883 "Validity:\n"); 884 885 Time2string(&t->validity.notBefore, &str); 886 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tnotBefore %s\n", str); 887 free(str); 888 Time2string(&t->validity.notAfter, &str); 889 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tnotAfter %s\n", str); 890 free(str); 891 892 if (t->extensions) { 893 int i, j; 894 895 if (t->extensions->len == 0) { 896 validate_print(ctx, 897 HX509_VALIDATE_F_VALIDATE|HX509_VALIDATE_F_VERBOSE, 898 "The empty extensions list is not " 899 "allowed by PKIX\n"); 900 } 901 902 for (i = 0; i < t->extensions->len; i++) { 903 904 for (j = 0; check_extension[j].name; j++) 905 if (der_heim_oid_cmp((*check_extension[j].oid)(), 906 &t->extensions->val[i].extnID) == 0) 907 break; 908 if (check_extension[j].name == NULL) { 909 int flags = HX509_VALIDATE_F_VERBOSE; 910 if (t->extensions->val[i].critical) 911 flags |= HX509_VALIDATE_F_VALIDATE; 912 validate_print(ctx, flags, "don't know what "); 913 if (t->extensions->val[i].critical) 914 validate_print(ctx, flags, "and is CRITICAL "); 915 if (ctx->flags & flags) 916 hx509_oid_print(&t->extensions->val[i].extnID, 917 validate_vprint, ctx); 918 validate_print(ctx, flags, " is\n"); 919 continue; 920 } 921 validate_print(ctx, 922 HX509_VALIDATE_F_VALIDATE|HX509_VALIDATE_F_VERBOSE, 923 "checking extention: %s\n", 924 check_extension[j].name); 925 (*check_extension[j].func)(ctx, 926 &status, 927 check_extension[j].cf, 928 &t->extensions->val[i]); 929 } 930 } else 931 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "no extentions\n"); 932 933 if (status.isca) { 934 if (!status.haveSKI) 935 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 936 "CA certificate have no SubjectKeyIdentifier\n"); 937 938 } else { 939 if (!status.haveAKI) 940 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 941 "Is not CA and doesn't have " 942 "AuthorityKeyIdentifier\n"); 943 } 944 945 946 if (!status.haveSKI) 947 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 948 "Doesn't have SubjectKeyIdentifier\n"); 949 950 if (status.isproxy && status.isca) 951 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 952 "Proxy and CA at the same time!\n"); 953 954 if (status.isproxy) { 955 if (status.haveSAN) 956 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 957 "Proxy and have SAN\n"); 958 if (status.haveIAN) 959 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 960 "Proxy and have IAN\n"); 961 } 962 963 if (hx509_name_is_null_p(subject) && !status.haveSAN) 964 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 965 "NULL subject DN and doesn't have a SAN\n"); 966 967 if (!status.selfsigned && !status.haveCRLDP) 968 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 969 "Not a CA nor PROXY and doesn't have" 970 "CRL Dist Point\n"); 971 972 if (status.selfsigned) { 973 ret = _hx509_verify_signature_bitstring(context, 974 c, 975 &c->signatureAlgorithm, 976 &c->tbsCertificate._save, 977 &c->signatureValue); 978 if (ret == 0) 979 validate_print(ctx, HX509_VALIDATE_F_VERBOSE, 980 "Self-signed certificate was self-signed\n"); 981 else 982 validate_print(ctx, HX509_VALIDATE_F_VALIDATE, 983 "Self-signed certificate NOT really self-signed!\n"); 984 } 985 986 hx509_name_free(&subject); 987 hx509_name_free(&issuer); 988 989 return 0; 990 } 991