1/* $OpenBSD: x509_crld.c,v 1.5 2023/02/16 08:38:17 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 70static void *v2i_crld(const X509V3_EXT_METHOD *method, 71 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); 72static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, 73 int indent); 74 75const 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 92const 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 109static STACK_OF(GENERAL_NAME) * 110gnames_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 131static int 132set_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 190err: 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 196static 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 209static int 210set_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 242err: 243 sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free); 244 return ret; 245} 246 247static int 248print_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 270static DIST_POINT * 271crldp_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 302err: 303 DIST_POINT_free(point); 304 return NULL; 305} 306 307static void * 308v2i_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 358merr: 359 X509V3error(ERR_R_MALLOC_FAILURE); 360err: 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 367static int 368dpn_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 386static 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}; 394static 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 411const 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 423DIST_POINT_NAME * 424d2i_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} 429LCRYPTO_ALIAS(d2i_DIST_POINT_NAME); 430 431int 432i2d_DIST_POINT_NAME(DIST_POINT_NAME *a, unsigned char **out) 433{ 434 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_NAME_it); 435} 436LCRYPTO_ALIAS(i2d_DIST_POINT_NAME); 437 438DIST_POINT_NAME * 439DIST_POINT_NAME_new(void) 440{ 441 return (DIST_POINT_NAME *)ASN1_item_new(&DIST_POINT_NAME_it); 442} 443LCRYPTO_ALIAS(DIST_POINT_NAME_new); 444 445void 446DIST_POINT_NAME_free(DIST_POINT_NAME *a) 447{ 448 ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_NAME_it); 449} 450LCRYPTO_ALIAS(DIST_POINT_NAME_free); 451 452static const ASN1_TEMPLATE DIST_POINT_seq_tt[] = { 453 { 454 .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, 455 .tag = 0, 456 .offset = offsetof(DIST_POINT, distpoint), 457 .field_name = "distpoint", 458 .item = &DIST_POINT_NAME_it, 459 }, 460 { 461 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 462 .tag = 1, 463 .offset = offsetof(DIST_POINT, reasons), 464 .field_name = "reasons", 465 .item = &ASN1_BIT_STRING_it, 466 }, 467 { 468 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, 469 .tag = 2, 470 .offset = offsetof(DIST_POINT, CRLissuer), 471 .field_name = "CRLissuer", 472 .item = &GENERAL_NAME_it, 473 }, 474}; 475 476const ASN1_ITEM DIST_POINT_it = { 477 .itype = ASN1_ITYPE_SEQUENCE, 478 .utype = V_ASN1_SEQUENCE, 479 .templates = DIST_POINT_seq_tt, 480 .tcount = sizeof(DIST_POINT_seq_tt) / sizeof(ASN1_TEMPLATE), 481 .funcs = NULL, 482 .size = sizeof(DIST_POINT), 483 .sname = "DIST_POINT", 484}; 485 486 487DIST_POINT * 488d2i_DIST_POINT(DIST_POINT **a, const unsigned char **in, long len) 489{ 490 return (DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 491 &DIST_POINT_it); 492} 493LCRYPTO_ALIAS(d2i_DIST_POINT); 494 495int 496i2d_DIST_POINT(DIST_POINT *a, unsigned char **out) 497{ 498 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_it); 499} 500LCRYPTO_ALIAS(i2d_DIST_POINT); 501 502DIST_POINT * 503DIST_POINT_new(void) 504{ 505 return (DIST_POINT *)ASN1_item_new(&DIST_POINT_it); 506} 507LCRYPTO_ALIAS(DIST_POINT_new); 508 509void 510DIST_POINT_free(DIST_POINT *a) 511{ 512 ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_it); 513} 514LCRYPTO_ALIAS(DIST_POINT_free); 515 516static const ASN1_TEMPLATE CRL_DIST_POINTS_item_tt = { 517 .flags = ASN1_TFLG_SEQUENCE_OF, 518 .tag = 0, 519 .offset = 0, 520 .field_name = "CRLDistributionPoints", 521 .item = &DIST_POINT_it, 522}; 523 524const ASN1_ITEM CRL_DIST_POINTS_it = { 525 .itype = ASN1_ITYPE_PRIMITIVE, 526 .utype = -1, 527 .templates = &CRL_DIST_POINTS_item_tt, 528 .tcount = 0, 529 .funcs = NULL, 530 .size = 0, 531 .sname = "CRL_DIST_POINTS", 532}; 533 534 535CRL_DIST_POINTS * 536d2i_CRL_DIST_POINTS(CRL_DIST_POINTS **a, const unsigned char **in, long len) 537{ 538 return (CRL_DIST_POINTS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 539 &CRL_DIST_POINTS_it); 540} 541LCRYPTO_ALIAS(d2i_CRL_DIST_POINTS); 542 543int 544i2d_CRL_DIST_POINTS(CRL_DIST_POINTS *a, unsigned char **out) 545{ 546 return ASN1_item_i2d((ASN1_VALUE *)a, out, &CRL_DIST_POINTS_it); 547} 548LCRYPTO_ALIAS(i2d_CRL_DIST_POINTS); 549 550CRL_DIST_POINTS * 551CRL_DIST_POINTS_new(void) 552{ 553 return (CRL_DIST_POINTS *)ASN1_item_new(&CRL_DIST_POINTS_it); 554} 555LCRYPTO_ALIAS(CRL_DIST_POINTS_new); 556 557void 558CRL_DIST_POINTS_free(CRL_DIST_POINTS *a) 559{ 560 ASN1_item_free((ASN1_VALUE *)a, &CRL_DIST_POINTS_it); 561} 562LCRYPTO_ALIAS(CRL_DIST_POINTS_free); 563 564static const ASN1_TEMPLATE ISSUING_DIST_POINT_seq_tt[] = { 565 { 566 .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, 567 .tag = 0, 568 .offset = offsetof(ISSUING_DIST_POINT, distpoint), 569 .field_name = "distpoint", 570 .item = &DIST_POINT_NAME_it, 571 }, 572 { 573 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 574 .tag = 1, 575 .offset = offsetof(ISSUING_DIST_POINT, onlyuser), 576 .field_name = "onlyuser", 577 .item = &ASN1_FBOOLEAN_it, 578 }, 579 { 580 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 581 .tag = 2, 582 .offset = offsetof(ISSUING_DIST_POINT, onlyCA), 583 .field_name = "onlyCA", 584 .item = &ASN1_FBOOLEAN_it, 585 }, 586 { 587 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 588 .tag = 3, 589 .offset = offsetof(ISSUING_DIST_POINT, onlysomereasons), 590 .field_name = "onlysomereasons", 591 .item = &ASN1_BIT_STRING_it, 592 }, 593 { 594 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 595 .tag = 4, 596 .offset = offsetof(ISSUING_DIST_POINT, indirectCRL), 597 .field_name = "indirectCRL", 598 .item = &ASN1_FBOOLEAN_it, 599 }, 600 { 601 .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, 602 .tag = 5, 603 .offset = offsetof(ISSUING_DIST_POINT, onlyattr), 604 .field_name = "onlyattr", 605 .item = &ASN1_FBOOLEAN_it, 606 }, 607}; 608 609const ASN1_ITEM ISSUING_DIST_POINT_it = { 610 .itype = ASN1_ITYPE_SEQUENCE, 611 .utype = V_ASN1_SEQUENCE, 612 .templates = ISSUING_DIST_POINT_seq_tt, 613 .tcount = sizeof(ISSUING_DIST_POINT_seq_tt) / sizeof(ASN1_TEMPLATE), 614 .funcs = NULL, 615 .size = sizeof(ISSUING_DIST_POINT), 616 .sname = "ISSUING_DIST_POINT", 617}; 618 619 620ISSUING_DIST_POINT * 621d2i_ISSUING_DIST_POINT(ISSUING_DIST_POINT **a, const unsigned char **in, long len) 622{ 623 return (ISSUING_DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 624 &ISSUING_DIST_POINT_it); 625} 626LCRYPTO_ALIAS(d2i_ISSUING_DIST_POINT); 627 628int 629i2d_ISSUING_DIST_POINT(ISSUING_DIST_POINT *a, unsigned char **out) 630{ 631 return ASN1_item_i2d((ASN1_VALUE *)a, out, &ISSUING_DIST_POINT_it); 632} 633LCRYPTO_ALIAS(i2d_ISSUING_DIST_POINT); 634 635ISSUING_DIST_POINT * 636ISSUING_DIST_POINT_new(void) 637{ 638 return (ISSUING_DIST_POINT *)ASN1_item_new(&ISSUING_DIST_POINT_it); 639} 640LCRYPTO_ALIAS(ISSUING_DIST_POINT_new); 641 642void 643ISSUING_DIST_POINT_free(ISSUING_DIST_POINT *a) 644{ 645 ASN1_item_free((ASN1_VALUE *)a, &ISSUING_DIST_POINT_it); 646} 647LCRYPTO_ALIAS(ISSUING_DIST_POINT_free); 648 649static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, 650 int indent); 651static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 652 STACK_OF(CONF_VALUE) *nval); 653 654const X509V3_EXT_METHOD v3_idp = { 655 NID_issuing_distribution_point, X509V3_EXT_MULTILINE, 656 &ISSUING_DIST_POINT_it, 657 0, 0, 0, 0, 658 0, 0, 659 0, 660 v2i_idp, 661 i2r_idp, 0, 662 NULL 663}; 664 665static void * 666v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 667 STACK_OF(CONF_VALUE) *nval) 668{ 669 ISSUING_DIST_POINT *idp = NULL; 670 CONF_VALUE *cnf; 671 char *name, *val; 672 int i, ret; 673 674 idp = ISSUING_DIST_POINT_new(); 675 if (!idp) 676 goto merr; 677 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 678 cnf = sk_CONF_VALUE_value(nval, i); 679 name = cnf->name; 680 val = cnf->value; 681 ret = set_dist_point_name(&idp->distpoint, ctx, cnf); 682 if (ret > 0) 683 continue; 684 if (ret < 0) 685 goto err; 686 if (!strcmp(name, "onlyuser")) { 687 if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) 688 goto err; 689 } 690 else if (!strcmp(name, "onlyCA")) { 691 if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) 692 goto err; 693 } 694 else if (!strcmp(name, "onlyAA")) { 695 if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) 696 goto err; 697 } 698 else if (!strcmp(name, "indirectCRL")) { 699 if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) 700 goto err; 701 } 702 else if (!strcmp(name, "onlysomereasons")) { 703 if (!set_reasons(&idp->onlysomereasons, val)) 704 goto err; 705 } else { 706 X509V3error(X509V3_R_INVALID_NAME); 707 X509V3_conf_err(cnf); 708 goto err; 709 } 710 } 711 return idp; 712 713merr: 714 X509V3error(ERR_R_MALLOC_FAILURE); 715err: 716 ISSUING_DIST_POINT_free(idp); 717 return NULL; 718} 719 720static int 721print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) 722{ 723 int i; 724 725 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 726 BIO_printf(out, "%*s", indent + 2, ""); 727 GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); 728 BIO_puts(out, "\n"); 729 } 730 return 1; 731} 732 733static int 734print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) 735{ 736 if (dpn->type == 0) { 737 BIO_printf(out, "%*sFull Name:\n", indent, ""); 738 print_gens(out, dpn->name.fullname, indent); 739 } else { 740 X509_NAME ntmp; 741 ntmp.entries = dpn->name.relativename; 742 BIO_printf(out, "%*sRelative Name:\n%*s", 743 indent, "", indent + 2, ""); 744 X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE); 745 BIO_puts(out, "\n"); 746 } 747 return 1; 748} 749 750static int 751i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, int indent) 752{ 753 ISSUING_DIST_POINT *idp = pidp; 754 755 if (idp->distpoint) 756 print_distpoint(out, idp->distpoint, indent); 757 if (idp->onlyuser > 0) 758 BIO_printf(out, "%*sOnly User Certificates\n", indent, ""); 759 if (idp->onlyCA > 0) 760 BIO_printf(out, "%*sOnly CA Certificates\n", indent, ""); 761 if (idp->indirectCRL > 0) 762 BIO_printf(out, "%*sIndirect CRL\n", indent, ""); 763 if (idp->onlysomereasons) 764 print_reasons(out, "Only Some Reasons", 765 idp->onlysomereasons, indent); 766 if (idp->onlyattr > 0) 767 BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, ""); 768 if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) && 769 (idp->indirectCRL <= 0) && !idp->onlysomereasons && 770 (idp->onlyattr <= 0)) 771 BIO_printf(out, "%*s<EMPTY>\n", indent, ""); 772 773 return 1; 774} 775 776static int 777i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, int indent) 778{ 779 STACK_OF(DIST_POINT) *crld = pcrldp; 780 DIST_POINT *point; 781 int i; 782 783 for (i = 0; i < sk_DIST_POINT_num(crld); i++) { 784 BIO_puts(out, "\n"); 785 point = sk_DIST_POINT_value(crld, i); 786 if (point->distpoint) 787 print_distpoint(out, point->distpoint, indent); 788 if (point->reasons) 789 print_reasons(out, "Reasons", point->reasons, 790 indent); 791 if (point->CRLissuer) { 792 BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); 793 print_gens(out, point->CRLissuer, indent); 794 } 795 } 796 return 1; 797} 798 799int 800DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) 801{ 802 int i; 803 STACK_OF(X509_NAME_ENTRY) *frag; 804 X509_NAME_ENTRY *ne; 805 806 if (!dpn || (dpn->type != 1)) 807 return 1; 808 frag = dpn->name.relativename; 809 dpn->dpname = X509_NAME_dup(iname); 810 if (!dpn->dpname) 811 return 0; 812 for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) { 813 ne = sk_X509_NAME_ENTRY_value(frag, i); 814 if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) { 815 X509_NAME_free(dpn->dpname); 816 dpn->dpname = NULL; 817 return 0; 818 } 819 } 820 /* generate cached encoding of name */ 821 if (i2d_X509_NAME(dpn->dpname, NULL) < 0) { 822 X509_NAME_free(dpn->dpname); 823 dpn->dpname = NULL; 824 return 0; 825 } 826 return 1; 827} 828LCRYPTO_ALIAS(DIST_POINT_set_dpname); 829