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