1 /* v3_crld.c */ 2 /* Written by Dr Stephen N Henson (steve (at) 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 (at) 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 (at) cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh (at) cryptsoft.com). */ 56 57 #include <stdio.h> 58 #include <string.h> 59 60 #include <openssl/asn1.h> 61 #include <openssl/asn1t.h> 62 #include <openssl/conf.h> 63 #include <openssl/err.h> 64 #include <openssl/mem.h> 65 #include <openssl/obj.h> 66 #include <openssl/x509v3.h> 67 68 69 static void *v2i_crld(const X509V3_EXT_METHOD *method, 70 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); 71 static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, 72 int indent); 73 74 const X509V3_EXT_METHOD v3_crld = 75 { 76 NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS), 77 0,0,0,0, 78 0,0, 79 0, 80 v2i_crld, 81 i2r_crldp,0, 82 NULL 83 }; 84 85 const X509V3_EXT_METHOD v3_freshest_crl = 86 { 87 NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS), 88 0,0,0,0, 89 0,0, 90 0, 91 v2i_crld, 92 i2r_crldp,0, 93 NULL 94 }; 95 96 static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, char *sect) 97 { 98 STACK_OF(CONF_VALUE) *gnsect; 99 STACK_OF(GENERAL_NAME) *gens; 100 if (*sect == '@') 101 gnsect = X509V3_get_section(ctx, sect + 1); 102 else 103 gnsect = X509V3_parse_list(sect); 104 if (!gnsect) 105 { 106 OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); 107 return NULL; 108 } 109 gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect); 110 if (*sect == '@') 111 X509V3_section_free(ctx, gnsect); 112 else 113 sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free); 114 return gens; 115 } 116 117 static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, 118 CONF_VALUE *cnf) 119 { 120 STACK_OF(GENERAL_NAME) *fnm = NULL; 121 STACK_OF(X509_NAME_ENTRY) *rnm = NULL; 122 if (!strncmp(cnf->name, "fullname", 9)) 123 { 124 fnm = gnames_from_sectname(ctx, cnf->value); 125 if (!fnm) 126 goto err; 127 } 128 else if (!strcmp(cnf->name, "relativename")) 129 { 130 int ret; 131 STACK_OF(CONF_VALUE) *dnsect; 132 X509_NAME *nm; 133 nm = X509_NAME_new(); 134 if (!nm) 135 return -1; 136 dnsect = X509V3_get_section(ctx, cnf->value); 137 if (!dnsect) 138 { 139 OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); 140 return -1; 141 } 142 ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC); 143 X509V3_section_free(ctx, dnsect); 144 rnm = nm->entries; 145 nm->entries = NULL; 146 X509_NAME_free(nm); 147 if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) 148 goto err; 149 /* Since its a name fragment can't have more than one 150 * RDNSequence 151 */ 152 if (sk_X509_NAME_ENTRY_value(rnm, 153 sk_X509_NAME_ENTRY_num(rnm) - 1)->set) 154 { 155 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS); 156 goto err; 157 } 158 } 159 else 160 return 0; 161 162 if (*pdp) 163 { 164 OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET); 165 goto err; 166 } 167 168 *pdp = DIST_POINT_NAME_new(); 169 if (!*pdp) 170 goto err; 171 if (fnm) 172 { 173 (*pdp)->type = 0; 174 (*pdp)->name.fullname = fnm; 175 } 176 else 177 { 178 (*pdp)->type = 1; 179 (*pdp)->name.relativename = rnm; 180 } 181 182 return 1; 183 184 err: 185 if (fnm) 186 sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free); 187 if (rnm) 188 sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free); 189 return -1; 190 } 191 192 static const BIT_STRING_BITNAME reason_flags[] = { 193 {0, "Unused", "unused"}, 194 {1, "Key Compromise", "keyCompromise"}, 195 {2, "CA Compromise", "CACompromise"}, 196 {3, "Affiliation Changed", "affiliationChanged"}, 197 {4, "Superseded", "superseded"}, 198 {5, "Cessation Of Operation", "cessationOfOperation"}, 199 {6, "Certificate Hold", "certificateHold"}, 200 {7, "Privilege Withdrawn", "privilegeWithdrawn"}, 201 {8, "AA Compromise", "AACompromise"}, 202 {-1, NULL, NULL} 203 }; 204 205 static int set_reasons(ASN1_BIT_STRING **preas, char *value) 206 { 207 STACK_OF(CONF_VALUE) *rsk = NULL; 208 const BIT_STRING_BITNAME *pbn; 209 const char *bnam; 210 size_t i; 211 int ret = 0; 212 rsk = X509V3_parse_list(value); 213 if (!rsk) 214 return 0; 215 if (*preas) 216 return 0; 217 for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) 218 { 219 bnam = sk_CONF_VALUE_value(rsk, i)->name; 220 if (!*preas) 221 { 222 *preas = ASN1_BIT_STRING_new(); 223 if (!*preas) 224 goto err; 225 } 226 for (pbn = reason_flags; pbn->lname; pbn++) 227 { 228 if (!strcmp(pbn->sname, bnam)) 229 { 230 if (!ASN1_BIT_STRING_set_bit(*preas, 231 pbn->bitnum, 1)) 232 goto err; 233 break; 234 } 235 } 236 if (!pbn->lname) 237 goto err; 238 } 239 ret = 1; 240 241 err: 242 sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free); 243 return ret; 244 } 245 246 static int print_reasons(BIO *out, const char *rname, 247 ASN1_BIT_STRING *rflags, int indent) 248 { 249 int first = 1; 250 const BIT_STRING_BITNAME *pbn; 251 BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, ""); 252 for (pbn = reason_flags; pbn->lname; pbn++) 253 { 254 if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) 255 { 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 *crldp_from_section(X509V3_CTX *ctx, 271 STACK_OF(CONF_VALUE) *nval) 272 { 273 size_t i; 274 CONF_VALUE *cnf; 275 DIST_POINT *point = NULL; 276 point = DIST_POINT_new(); 277 if (!point) 278 goto err; 279 for(i = 0; i < sk_CONF_VALUE_num(nval); i++) 280 { 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 { 290 if (!set_reasons(&point->reasons, cnf->value)) 291 goto err; 292 } 293 else if (!strcmp(cnf->name, "CRLissuer")) 294 { 295 point->CRLissuer = 296 gnames_from_sectname(ctx, cnf->value); 297 if (!point->CRLissuer) 298 goto err; 299 } 300 } 301 302 return point; 303 304 305 err: 306 if (point) 307 DIST_POINT_free(point); 308 return NULL; 309 } 310 311 static void *v2i_crld(const X509V3_EXT_METHOD *method, 312 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 313 { 314 STACK_OF(DIST_POINT) *crld = NULL; 315 GENERAL_NAMES *gens = NULL; 316 GENERAL_NAME *gen = NULL; 317 CONF_VALUE *cnf; 318 size_t i; 319 if(!(crld = sk_DIST_POINT_new_null())) goto merr; 320 for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { 321 DIST_POINT *point; 322 cnf = sk_CONF_VALUE_value(nval, i); 323 if (!cnf->value) 324 { 325 STACK_OF(CONF_VALUE) *dpsect; 326 dpsect = X509V3_get_section(ctx, cnf->name); 327 if (!dpsect) 328 goto err; 329 point = crldp_from_section(ctx, dpsect); 330 X509V3_section_free(ctx, dpsect); 331 if (!point) 332 goto err; 333 if(!sk_DIST_POINT_push(crld, point)) 334 { 335 DIST_POINT_free(point); 336 goto merr; 337 } 338 } 339 else 340 { 341 if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 342 goto err; 343 if(!(gens = GENERAL_NAMES_new())) 344 goto merr; 345 if(!sk_GENERAL_NAME_push(gens, gen)) 346 goto merr; 347 gen = NULL; 348 if(!(point = DIST_POINT_new())) 349 goto merr; 350 if(!sk_DIST_POINT_push(crld, point)) 351 { 352 DIST_POINT_free(point); 353 goto merr; 354 } 355 if(!(point->distpoint = DIST_POINT_NAME_new())) 356 goto merr; 357 point->distpoint->name.fullname = gens; 358 point->distpoint->type = 0; 359 gens = NULL; 360 } 361 } 362 return crld; 363 364 merr: 365 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 366 err: 367 GENERAL_NAME_free(gen); 368 GENERAL_NAMES_free(gens); 369 sk_DIST_POINT_pop_free(crld, DIST_POINT_free); 370 return NULL; 371 } 372 373 IMPLEMENT_ASN1_SET_OF(DIST_POINT) 374 375 static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, 376 void *exarg) 377 { 378 DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval; 379 380 switch(operation) 381 { 382 case ASN1_OP_NEW_POST: 383 dpn->dpname = NULL; 384 break; 385 386 case ASN1_OP_FREE_POST: 387 if (dpn->dpname) 388 X509_NAME_free(dpn->dpname); 389 break; 390 } 391 return 1; 392 } 393 394 395 ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = { 396 ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0), 397 ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1) 398 } ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type) 399 400 401 IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME) 402 403 ASN1_SEQUENCE(DIST_POINT) = { 404 ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0), 405 ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1), 406 ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2) 407 } ASN1_SEQUENCE_END(DIST_POINT) 408 409 IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT) 410 411 ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = 412 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT) 413 ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS) 414 415 IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS) 416 417 ASN1_SEQUENCE(ISSUING_DIST_POINT) = { 418 ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0), 419 ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1), 420 ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2), 421 ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3), 422 ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4), 423 ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5) 424 } ASN1_SEQUENCE_END(ISSUING_DIST_POINT) 425 426 IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT) 427 428 static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, 429 int indent); 430 static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 431 STACK_OF(CONF_VALUE) *nval); 432 433 const X509V3_EXT_METHOD v3_idp = 434 { 435 NID_issuing_distribution_point, X509V3_EXT_MULTILINE, 436 ASN1_ITEM_ref(ISSUING_DIST_POINT), 437 0,0,0,0, 438 0,0, 439 0, 440 v2i_idp, 441 i2r_idp,0, 442 NULL 443 }; 444 445 static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 446 STACK_OF(CONF_VALUE) *nval) 447 { 448 ISSUING_DIST_POINT *idp = NULL; 449 CONF_VALUE *cnf; 450 char *name, *val; 451 size_t i; 452 int ret; 453 idp = ISSUING_DIST_POINT_new(); 454 if (!idp) 455 goto merr; 456 for(i = 0; i < sk_CONF_VALUE_num(nval); i++) 457 { 458 cnf = sk_CONF_VALUE_value(nval, i); 459 name = cnf->name; 460 val = cnf->value; 461 ret = set_dist_point_name(&idp->distpoint, ctx, cnf); 462 if (ret > 0) 463 continue; 464 if (ret < 0) 465 goto err; 466 if (!strcmp(name, "onlyuser")) 467 { 468 if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) 469 goto err; 470 } 471 else if (!strcmp(name, "onlyCA")) 472 { 473 if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) 474 goto err; 475 } 476 else if (!strcmp(name, "onlyAA")) 477 { 478 if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) 479 goto err; 480 } 481 else if (!strcmp(name, "indirectCRL")) 482 { 483 if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) 484 goto err; 485 } 486 else if (!strcmp(name, "onlysomereasons")) 487 { 488 if (!set_reasons(&idp->onlysomereasons, val)) 489 goto err; 490 } 491 else 492 { 493 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); 494 X509V3_conf_err(cnf); 495 goto err; 496 } 497 } 498 return idp; 499 500 merr: 501 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 502 err: 503 ISSUING_DIST_POINT_free(idp); 504 return NULL; 505 } 506 507 static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) 508 { 509 size_t i; 510 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) 511 { 512 BIO_printf(out, "%*s", indent + 2, ""); 513 GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); 514 BIO_puts(out, "\n"); 515 } 516 return 1; 517 } 518 519 static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) 520 { 521 if (dpn->type == 0) 522 { 523 BIO_printf(out, "%*sFull Name:\n", indent, ""); 524 print_gens(out, dpn->name.fullname, indent); 525 } 526 else 527 { 528 X509_NAME ntmp; 529 ntmp.entries = dpn->name.relativename; 530 BIO_printf(out, "%*sRelative Name:\n%*s", 531 indent, "", indent + 2, ""); 532 X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE); 533 BIO_puts(out, "\n"); 534 } 535 return 1; 536 } 537 538 static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, 539 int indent) 540 { 541 ISSUING_DIST_POINT *idp = pidp; 542 if (idp->distpoint) 543 print_distpoint(out, idp->distpoint, indent); 544 if (idp->onlyuser > 0) 545 BIO_printf(out, "%*sOnly User Certificates\n", indent, ""); 546 if (idp->onlyCA > 0) 547 BIO_printf(out, "%*sOnly CA Certificates\n", indent, ""); 548 if (idp->indirectCRL > 0) 549 BIO_printf(out, "%*sIndirect CRL\n", indent, ""); 550 if (idp->onlysomereasons) 551 print_reasons(out, "Only Some Reasons", 552 idp->onlysomereasons, indent); 553 if (idp->onlyattr > 0) 554 BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, ""); 555 if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) 556 && (idp->indirectCRL <= 0) && !idp->onlysomereasons 557 && (idp->onlyattr <= 0)) 558 BIO_printf(out, "%*s<EMPTY>\n", indent, ""); 559 560 return 1; 561 } 562 563 static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, 564 int indent) 565 { 566 STACK_OF(DIST_POINT) *crld = pcrldp; 567 DIST_POINT *point; 568 size_t i; 569 for(i = 0; i < sk_DIST_POINT_num(crld); i++) 570 { 571 BIO_puts(out, "\n"); 572 point = sk_DIST_POINT_value(crld, i); 573 if(point->distpoint) 574 print_distpoint(out, point->distpoint, indent); 575 if(point->reasons) 576 print_reasons(out, "Reasons", point->reasons, 577 indent); 578 if(point->CRLissuer) 579 { 580 BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); 581 print_gens(out, point->CRLissuer, indent); 582 } 583 } 584 return 1; 585 } 586 587 int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) 588 { 589 size_t i; 590 STACK_OF(X509_NAME_ENTRY) *frag; 591 X509_NAME_ENTRY *ne; 592 if (!dpn || (dpn->type != 1)) 593 return 1; 594 frag = dpn->name.relativename; 595 dpn->dpname = X509_NAME_dup(iname); 596 if (!dpn->dpname) 597 return 0; 598 for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) 599 { 600 ne = sk_X509_NAME_ENTRY_value(frag, i); 601 if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) 602 { 603 X509_NAME_free(dpn->dpname); 604 dpn->dpname = NULL; 605 return 0; 606 } 607 } 608 /* generate cached encoding of name */ 609 if (i2d_X509_NAME(dpn->dpname, NULL) < 0) 610 { 611 X509_NAME_free(dpn->dpname); 612 dpn->dpname = NULL; 613 return 0; 614 } 615 return 1; 616 } 617