1 /* $OpenBSD: x509_crld.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 1999. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 #include <stdio.h> 60 #include <string.h> 61 62 #include <openssl/asn1.h> 63 #include <openssl/asn1t.h> 64 #include <openssl/conf.h> 65 #include <openssl/err.h> 66 #include <openssl/x509v3.h> 67 68 #include "x509_lcl.h" 69 70 static void *v2i_crld(const X509V3_EXT_METHOD *method, 71 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); 72 static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, 73 int indent); 74 75 const X509V3_EXT_METHOD v3_crld = { 76 .ext_nid = NID_crl_distribution_points, 77 .ext_flags = 0, 78 .it = &CRL_DIST_POINTS_it, 79 .ext_new = NULL, 80 .ext_free = NULL, 81 .d2i = NULL, 82 .i2d = NULL, 83 .i2s = NULL, 84 .s2i = NULL, 85 .i2v = NULL, 86 .v2i = v2i_crld, 87 .i2r = i2r_crldp, 88 .r2i = NULL, 89 .usr_data = NULL, 90 }; 91 92 const X509V3_EXT_METHOD v3_freshest_crl = { 93 .ext_nid = NID_freshest_crl, 94 .ext_flags = 0, 95 .it = &CRL_DIST_POINTS_it, 96 .ext_new = NULL, 97 .ext_free = NULL, 98 .d2i = NULL, 99 .i2d = NULL, 100 .i2s = NULL, 101 .s2i = NULL, 102 .i2v = NULL, 103 .v2i = v2i_crld, 104 .i2r = i2r_crldp, 105 .r2i = NULL, 106 .usr_data = NULL, 107 }; 108 109 static STACK_OF(GENERAL_NAME) * 110 gnames_from_sectname(X509V3_CTX *ctx, char *sect) 111 { 112 STACK_OF(CONF_VALUE) *gnsect; 113 STACK_OF(GENERAL_NAME) *gens; 114 115 if (*sect == '@') 116 gnsect = X509V3_get_section(ctx, sect + 1); 117 else 118 gnsect = X509V3_parse_list(sect); 119 if (!gnsect) { 120 X509V3error(X509V3_R_SECTION_NOT_FOUND); 121 return NULL; 122 } 123 gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect); 124 if (*sect == '@') 125 X509V3_section_free(ctx, gnsect); 126 else 127 sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free); 128 return gens; 129 } 130 131 static int 132 set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, CONF_VALUE *cnf) 133 { 134 STACK_OF(GENERAL_NAME) *fnm = NULL; 135 STACK_OF(X509_NAME_ENTRY) *rnm = NULL; 136 137 if (!strncmp(cnf->name, "fullname", 9)) { 138 fnm = gnames_from_sectname(ctx, cnf->value); 139 if (!fnm) 140 goto err; 141 } else if (!strcmp(cnf->name, "relativename")) { 142 int ret; 143 STACK_OF(CONF_VALUE) *dnsect; 144 X509_NAME *nm; 145 nm = X509_NAME_new(); 146 if (!nm) 147 return -1; 148 dnsect = X509V3_get_section(ctx, cnf->value); 149 if (!dnsect) { 150 X509V3error(X509V3_R_SECTION_NOT_FOUND); 151 X509_NAME_free(nm); 152 return -1; 153 } 154 ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC); 155 X509V3_section_free(ctx, dnsect); 156 rnm = nm->entries; 157 nm->entries = NULL; 158 X509_NAME_free(nm); 159 if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) 160 goto err; 161 /* Since its a name fragment can't have more than one 162 * RDNSequence 163 */ 164 if (sk_X509_NAME_ENTRY_value(rnm, 165 sk_X509_NAME_ENTRY_num(rnm) - 1)->set) { 166 X509V3error(X509V3_R_INVALID_MULTIPLE_RDNS); 167 goto err; 168 } 169 } else 170 return 0; 171 172 if (*pdp) { 173 X509V3error(X509V3_R_DISTPOINT_ALREADY_SET); 174 goto err; 175 } 176 177 *pdp = DIST_POINT_NAME_new(); 178 if (!*pdp) 179 goto err; 180 if (fnm) { 181 (*pdp)->type = 0; 182 (*pdp)->name.fullname = fnm; 183 } else { 184 (*pdp)->type = 1; 185 (*pdp)->name.relativename = rnm; 186 } 187 188 return 1; 189 190 err: 191 sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free); 192 sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free); 193 return -1; 194 } 195 196 static const BIT_STRING_BITNAME reason_flags[] = { 197 {0, "Unused", "unused"}, 198 {1, "Key Compromise", "keyCompromise"}, 199 {2, "CA Compromise", "CACompromise"}, 200 {3, "Affiliation Changed", "affiliationChanged"}, 201 {4, "Superseded", "superseded"}, 202 {5, "Cessation Of Operation", "cessationOfOperation"}, 203 {6, "Certificate Hold", "certificateHold"}, 204 {7, "Privilege Withdrawn", "privilegeWithdrawn"}, 205 {8, "AA Compromise", "AACompromise"}, 206 {-1, NULL, NULL} 207 }; 208 209 static int 210 set_reasons(ASN1_BIT_STRING **preas, char *value) 211 { 212 STACK_OF(CONF_VALUE) *rsk = NULL; 213 const BIT_STRING_BITNAME *pbn; 214 const char *bnam; 215 int i, ret = 0; 216 217 if (*preas != NULL) 218 return 0; 219 rsk = X509V3_parse_list(value); 220 if (rsk == NULL) 221 return 0; 222 for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) { 223 bnam = sk_CONF_VALUE_value(rsk, i)->name; 224 if (!*preas) { 225 *preas = ASN1_BIT_STRING_new(); 226 if (!*preas) 227 goto err; 228 } 229 for (pbn = reason_flags; pbn->lname; pbn++) { 230 if (!strcmp(pbn->sname, bnam)) { 231 if (!ASN1_BIT_STRING_set_bit(*preas, 232 pbn->bitnum, 1)) 233 goto err; 234 break; 235 } 236 } 237 if (!pbn->lname) 238 goto err; 239 } 240 ret = 1; 241 242 err: 243 sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free); 244 return ret; 245 } 246 247 static int 248 print_reasons(BIO *out, const char *rname, ASN1_BIT_STRING *rflags, int indent) 249 { 250 int first = 1; 251 const BIT_STRING_BITNAME *pbn; 252 253 BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, ""); 254 for (pbn = reason_flags; pbn->lname; pbn++) { 255 if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) { 256 if (first) 257 first = 0; 258 else 259 BIO_puts(out, ", "); 260 BIO_puts(out, pbn->lname); 261 } 262 } 263 if (first) 264 BIO_puts(out, "<EMPTY>\n"); 265 else 266 BIO_puts(out, "\n"); 267 return 1; 268 } 269 270 static DIST_POINT * 271 crldp_from_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 272 { 273 int i; 274 CONF_VALUE *cnf; 275 DIST_POINT *point = NULL; 276 277 point = DIST_POINT_new(); 278 if (!point) 279 goto err; 280 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 281 int ret; 282 cnf = sk_CONF_VALUE_value(nval, i); 283 ret = set_dist_point_name(&point->distpoint, ctx, cnf); 284 if (ret > 0) 285 continue; 286 if (ret < 0) 287 goto err; 288 if (!strcmp(cnf->name, "reasons")) { 289 if (!set_reasons(&point->reasons, cnf->value)) 290 goto err; 291 } 292 else if (!strcmp(cnf->name, "CRLissuer")) { 293 point->CRLissuer = 294 gnames_from_sectname(ctx, cnf->value); 295 if (!point->CRLissuer) 296 goto err; 297 } 298 } 299 300 return point; 301 302 err: 303 DIST_POINT_free(point); 304 return NULL; 305 } 306 307 static void * 308 v2i_crld(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 309 STACK_OF(CONF_VALUE) *nval) 310 { 311 STACK_OF(DIST_POINT) *crld = NULL; 312 GENERAL_NAMES *gens = NULL; 313 GENERAL_NAME *gen = NULL; 314 CONF_VALUE *cnf; 315 int i; 316 317 if (!(crld = sk_DIST_POINT_new_null())) 318 goto merr; 319 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 320 DIST_POINT *point; 321 cnf = sk_CONF_VALUE_value(nval, i); 322 if (!cnf->value) { 323 STACK_OF(CONF_VALUE) *dpsect; 324 dpsect = X509V3_get_section(ctx, cnf->name); 325 if (!dpsect) 326 goto err; 327 point = crldp_from_section(ctx, dpsect); 328 X509V3_section_free(ctx, dpsect); 329 if (!point) 330 goto err; 331 if (!sk_DIST_POINT_push(crld, point)) { 332 DIST_POINT_free(point); 333 goto merr; 334 } 335 } else { 336 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 337 goto err; 338 if (!(gens = GENERAL_NAMES_new())) 339 goto merr; 340 if (!sk_GENERAL_NAME_push(gens, gen)) 341 goto merr; 342 gen = NULL; 343 if (!(point = DIST_POINT_new())) 344 goto merr; 345 if (!sk_DIST_POINT_push(crld, point)) { 346 DIST_POINT_free(point); 347 goto merr; 348 } 349 if (!(point->distpoint = DIST_POINT_NAME_new())) 350 goto merr; 351 point->distpoint->name.fullname = gens; 352 point->distpoint->type = 0; 353 gens = NULL; 354 } 355 } 356 return crld; 357 358 merr: 359 X509V3error(ERR_R_MALLOC_FAILURE); 360 err: 361 GENERAL_NAME_free(gen); 362 GENERAL_NAMES_free(gens); 363 sk_DIST_POINT_pop_free(crld, DIST_POINT_free); 364 return NULL; 365 } 366 367 static int 368 dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) 369 { 370 DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval; 371 372 switch (operation) { 373 case ASN1_OP_NEW_POST: 374 dpn->dpname = NULL; 375 break; 376 377 case ASN1_OP_FREE_POST: 378 if (dpn->dpname) 379 X509_NAME_free(dpn->dpname); 380 break; 381 } 382 return 1; 383 } 384 385 386 static const ASN1_AUX DIST_POINT_NAME_aux = { 387 .app_data = NULL, 388 .flags = 0, 389 .ref_offset = 0, 390 .ref_lock = 0, 391 .asn1_cb = dpn_cb, 392 .enc_offset = 0, 393 }; 394 static const ASN1_TEMPLATE DIST_POINT_NAME_ch_tt[] = { 395 { 396 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF, 397 .tag = 0, 398 .offset = offsetof(DIST_POINT_NAME, name.fullname), 399 .field_name = "name.fullname", 400 .item = &GENERAL_NAME_it, 401 }, 402 { 403 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF, 404 .tag = 1, 405 .offset = offsetof(DIST_POINT_NAME, name.relativename), 406 .field_name = "name.relativename", 407 .item = &X509_NAME_ENTRY_it, 408 }, 409 }; 410 411 const ASN1_ITEM DIST_POINT_NAME_it = { 412 .itype = ASN1_ITYPE_CHOICE, 413 .utype = offsetof(DIST_POINT_NAME, type), 414 .templates = DIST_POINT_NAME_ch_tt, 415 .tcount = sizeof(DIST_POINT_NAME_ch_tt) / sizeof(ASN1_TEMPLATE), 416 .funcs = &DIST_POINT_NAME_aux, 417 .size = sizeof(DIST_POINT_NAME), 418 .sname = "DIST_POINT_NAME", 419 }; 420 421 422 423 DIST_POINT_NAME * 424 d2i_DIST_POINT_NAME(DIST_POINT_NAME **a, const unsigned char **in, long len) 425 { 426 return (DIST_POINT_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 427 &DIST_POINT_NAME_it); 428 } 429 430 int 431 i2d_DIST_POINT_NAME(DIST_POINT_NAME *a, unsigned char **out) 432 { 433 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_NAME_it); 434 } 435 436 DIST_POINT_NAME * 437 DIST_POINT_NAME_new(void) 438 { 439 return (DIST_POINT_NAME *)ASN1_item_new(&DIST_POINT_NAME_it); 440 } 441 442 void 443 DIST_POINT_NAME_free(DIST_POINT_NAME *a) 444 { 445 ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_NAME_it); 446 } 447 448 static const ASN1_TEMPLATE DIST_POINT_seq_tt[] = { 449 { 450 .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, 451 .tag = 0, 452 .offset = offsetof(DIST_POINT, distpoint), 453 .field_name = "distpoint", 454 .item = &DIST_POINT_NAME_it, 455 }, 456 { 457 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 458 .tag = 1, 459 .offset = offsetof(DIST_POINT, reasons), 460 .field_name = "reasons", 461 .item = &ASN1_BIT_STRING_it, 462 }, 463 { 464 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, 465 .tag = 2, 466 .offset = offsetof(DIST_POINT, CRLissuer), 467 .field_name = "CRLissuer", 468 .item = &GENERAL_NAME_it, 469 }, 470 }; 471 472 const ASN1_ITEM DIST_POINT_it = { 473 .itype = ASN1_ITYPE_SEQUENCE, 474 .utype = V_ASN1_SEQUENCE, 475 .templates = DIST_POINT_seq_tt, 476 .tcount = sizeof(DIST_POINT_seq_tt) / sizeof(ASN1_TEMPLATE), 477 .funcs = NULL, 478 .size = sizeof(DIST_POINT), 479 .sname = "DIST_POINT", 480 }; 481 482 483 DIST_POINT * 484 d2i_DIST_POINT(DIST_POINT **a, const unsigned char **in, long len) 485 { 486 return (DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 487 &DIST_POINT_it); 488 } 489 490 int 491 i2d_DIST_POINT(DIST_POINT *a, unsigned char **out) 492 { 493 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_it); 494 } 495 496 DIST_POINT * 497 DIST_POINT_new(void) 498 { 499 return (DIST_POINT *)ASN1_item_new(&DIST_POINT_it); 500 } 501 502 void 503 DIST_POINT_free(DIST_POINT *a) 504 { 505 ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_it); 506 } 507 508 static const ASN1_TEMPLATE CRL_DIST_POINTS_item_tt = { 509 .flags = ASN1_TFLG_SEQUENCE_OF, 510 .tag = 0, 511 .offset = 0, 512 .field_name = "CRLDistributionPoints", 513 .item = &DIST_POINT_it, 514 }; 515 516 const ASN1_ITEM CRL_DIST_POINTS_it = { 517 .itype = ASN1_ITYPE_PRIMITIVE, 518 .utype = -1, 519 .templates = &CRL_DIST_POINTS_item_tt, 520 .tcount = 0, 521 .funcs = NULL, 522 .size = 0, 523 .sname = "CRL_DIST_POINTS", 524 }; 525 526 527 CRL_DIST_POINTS * 528 d2i_CRL_DIST_POINTS(CRL_DIST_POINTS **a, const unsigned char **in, long len) 529 { 530 return (CRL_DIST_POINTS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 531 &CRL_DIST_POINTS_it); 532 } 533 534 int 535 i2d_CRL_DIST_POINTS(CRL_DIST_POINTS *a, unsigned char **out) 536 { 537 return ASN1_item_i2d((ASN1_VALUE *)a, out, &CRL_DIST_POINTS_it); 538 } 539 540 CRL_DIST_POINTS * 541 CRL_DIST_POINTS_new(void) 542 { 543 return (CRL_DIST_POINTS *)ASN1_item_new(&CRL_DIST_POINTS_it); 544 } 545 546 void 547 CRL_DIST_POINTS_free(CRL_DIST_POINTS *a) 548 { 549 ASN1_item_free((ASN1_VALUE *)a, &CRL_DIST_POINTS_it); 550 } 551 552 static const ASN1_TEMPLATE ISSUING_DIST_POINT_seq_tt[] = { 553 { 554 .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, 555 .tag = 0, 556 .offset = offsetof(ISSUING_DIST_POINT, distpoint), 557 .field_name = "distpoint", 558 .item = &DIST_POINT_NAME_it, 559 }, 560 { 561 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 562 .tag = 1, 563 .offset = offsetof(ISSUING_DIST_POINT, onlyuser), 564 .field_name = "onlyuser", 565 .item = &ASN1_FBOOLEAN_it, 566 }, 567 { 568 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 569 .tag = 2, 570 .offset = offsetof(ISSUING_DIST_POINT, onlyCA), 571 .field_name = "onlyCA", 572 .item = &ASN1_FBOOLEAN_it, 573 }, 574 { 575 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 576 .tag = 3, 577 .offset = offsetof(ISSUING_DIST_POINT, onlysomereasons), 578 .field_name = "onlysomereasons", 579 .item = &ASN1_BIT_STRING_it, 580 }, 581 { 582 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 583 .tag = 4, 584 .offset = offsetof(ISSUING_DIST_POINT, indirectCRL), 585 .field_name = "indirectCRL", 586 .item = &ASN1_FBOOLEAN_it, 587 }, 588 { 589 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 590 .tag = 5, 591 .offset = offsetof(ISSUING_DIST_POINT, onlyattr), 592 .field_name = "onlyattr", 593 .item = &ASN1_FBOOLEAN_it, 594 }, 595 }; 596 597 const ASN1_ITEM ISSUING_DIST_POINT_it = { 598 .itype = ASN1_ITYPE_SEQUENCE, 599 .utype = V_ASN1_SEQUENCE, 600 .templates = ISSUING_DIST_POINT_seq_tt, 601 .tcount = sizeof(ISSUING_DIST_POINT_seq_tt) / sizeof(ASN1_TEMPLATE), 602 .funcs = NULL, 603 .size = sizeof(ISSUING_DIST_POINT), 604 .sname = "ISSUING_DIST_POINT", 605 }; 606 607 608 ISSUING_DIST_POINT * 609 d2i_ISSUING_DIST_POINT(ISSUING_DIST_POINT **a, const unsigned char **in, long len) 610 { 611 return (ISSUING_DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 612 &ISSUING_DIST_POINT_it); 613 } 614 615 int 616 i2d_ISSUING_DIST_POINT(ISSUING_DIST_POINT *a, unsigned char **out) 617 { 618 return ASN1_item_i2d((ASN1_VALUE *)a, out, &ISSUING_DIST_POINT_it); 619 } 620 621 ISSUING_DIST_POINT * 622 ISSUING_DIST_POINT_new(void) 623 { 624 return (ISSUING_DIST_POINT *)ASN1_item_new(&ISSUING_DIST_POINT_it); 625 } 626 627 void 628 ISSUING_DIST_POINT_free(ISSUING_DIST_POINT *a) 629 { 630 ASN1_item_free((ASN1_VALUE *)a, &ISSUING_DIST_POINT_it); 631 } 632 633 static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, 634 int indent); 635 static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 636 STACK_OF(CONF_VALUE) *nval); 637 638 const X509V3_EXT_METHOD v3_idp = { 639 NID_issuing_distribution_point, X509V3_EXT_MULTILINE, 640 &ISSUING_DIST_POINT_it, 641 0, 0, 0, 0, 642 0, 0, 643 0, 644 v2i_idp, 645 i2r_idp, 0, 646 NULL 647 }; 648 649 static void * 650 v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 651 STACK_OF(CONF_VALUE) *nval) 652 { 653 ISSUING_DIST_POINT *idp = NULL; 654 CONF_VALUE *cnf; 655 char *name, *val; 656 int i, ret; 657 658 idp = ISSUING_DIST_POINT_new(); 659 if (!idp) 660 goto merr; 661 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 662 cnf = sk_CONF_VALUE_value(nval, i); 663 name = cnf->name; 664 val = cnf->value; 665 ret = set_dist_point_name(&idp->distpoint, ctx, cnf); 666 if (ret > 0) 667 continue; 668 if (ret < 0) 669 goto err; 670 if (!strcmp(name, "onlyuser")) { 671 if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) 672 goto err; 673 } 674 else if (!strcmp(name, "onlyCA")) { 675 if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) 676 goto err; 677 } 678 else if (!strcmp(name, "onlyAA")) { 679 if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) 680 goto err; 681 } 682 else if (!strcmp(name, "indirectCRL")) { 683 if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) 684 goto err; 685 } 686 else if (!strcmp(name, "onlysomereasons")) { 687 if (!set_reasons(&idp->onlysomereasons, val)) 688 goto err; 689 } else { 690 X509V3error(X509V3_R_INVALID_NAME); 691 X509V3_conf_err(cnf); 692 goto err; 693 } 694 } 695 return idp; 696 697 merr: 698 X509V3error(ERR_R_MALLOC_FAILURE); 699 err: 700 ISSUING_DIST_POINT_free(idp); 701 return NULL; 702 } 703 704 static int 705 print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) 706 { 707 int i; 708 709 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 710 BIO_printf(out, "%*s", indent + 2, ""); 711 GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); 712 BIO_puts(out, "\n"); 713 } 714 return 1; 715 } 716 717 static int 718 print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) 719 { 720 if (dpn->type == 0) { 721 BIO_printf(out, "%*sFull Name:\n", indent, ""); 722 print_gens(out, dpn->name.fullname, indent); 723 } else { 724 X509_NAME ntmp; 725 ntmp.entries = dpn->name.relativename; 726 BIO_printf(out, "%*sRelative Name:\n%*s", 727 indent, "", indent + 2, ""); 728 X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE); 729 BIO_puts(out, "\n"); 730 } 731 return 1; 732 } 733 734 static int 735 i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, int indent) 736 { 737 ISSUING_DIST_POINT *idp = pidp; 738 739 if (idp->distpoint) 740 print_distpoint(out, idp->distpoint, indent); 741 if (idp->onlyuser > 0) 742 BIO_printf(out, "%*sOnly User Certificates\n", indent, ""); 743 if (idp->onlyCA > 0) 744 BIO_printf(out, "%*sOnly CA Certificates\n", indent, ""); 745 if (idp->indirectCRL > 0) 746 BIO_printf(out, "%*sIndirect CRL\n", indent, ""); 747 if (idp->onlysomereasons) 748 print_reasons(out, "Only Some Reasons", 749 idp->onlysomereasons, indent); 750 if (idp->onlyattr > 0) 751 BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, ""); 752 if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) && 753 (idp->indirectCRL <= 0) && !idp->onlysomereasons && 754 (idp->onlyattr <= 0)) 755 BIO_printf(out, "%*s<EMPTY>\n", indent, ""); 756 757 return 1; 758 } 759 760 static int 761 i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, int indent) 762 { 763 STACK_OF(DIST_POINT) *crld = pcrldp; 764 DIST_POINT *point; 765 int i; 766 767 for (i = 0; i < sk_DIST_POINT_num(crld); i++) { 768 BIO_puts(out, "\n"); 769 point = sk_DIST_POINT_value(crld, i); 770 if (point->distpoint) 771 print_distpoint(out, point->distpoint, indent); 772 if (point->reasons) 773 print_reasons(out, "Reasons", point->reasons, 774 indent); 775 if (point->CRLissuer) { 776 BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); 777 print_gens(out, point->CRLissuer, indent); 778 } 779 } 780 return 1; 781 } 782 783 int 784 DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) 785 { 786 int i; 787 STACK_OF(X509_NAME_ENTRY) *frag; 788 X509_NAME_ENTRY *ne; 789 790 if (!dpn || (dpn->type != 1)) 791 return 1; 792 frag = dpn->name.relativename; 793 dpn->dpname = X509_NAME_dup(iname); 794 if (!dpn->dpname) 795 return 0; 796 for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) { 797 ne = sk_X509_NAME_ENTRY_value(frag, i); 798 if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) { 799 X509_NAME_free(dpn->dpname); 800 dpn->dpname = NULL; 801 return 0; 802 } 803 } 804 /* generate cached encoding of name */ 805 if (i2d_X509_NAME(dpn->dpname, NULL) < 0) { 806 X509_NAME_free(dpn->dpname); 807 dpn->dpname = NULL; 808 return 0; 809 } 810 return 1; 811 } 812