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