1/* $OpenBSD: x509_cpols.c,v 1.11 2023/04/26 20:54:21 tb Exp $ */ 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 1999. 4 */ 5/* ==================================================================== 6 * Copyright (c) 1999-2004 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/* Certificate policies extension support: this one is a bit complex... */ 71 72static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, 73 BIO *out, int indent); 74static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, 75 X509V3_CTX *ctx, char *value); 76static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, 77 int indent); 78static void print_notice(BIO *out, USERNOTICE *notice, int indent); 79static POLICYINFO *policy_section(X509V3_CTX *ctx, 80 STACK_OF(CONF_VALUE) *polstrs, int ia5org); 81static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, 82 STACK_OF(CONF_VALUE) *unot, int ia5org); 83static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos); 84 85const X509V3_EXT_METHOD v3_cpols = { 86 .ext_nid = NID_certificate_policies, 87 .ext_flags = 0, 88 .it = &CERTIFICATEPOLICIES_it, 89 .ext_new = NULL, 90 .ext_free = NULL, 91 .d2i = NULL, 92 .i2d = NULL, 93 .i2s = NULL, 94 .s2i = NULL, 95 .i2v = NULL, 96 .v2i = NULL, 97 .i2r = (X509V3_EXT_I2R)i2r_certpol, 98 .r2i = (X509V3_EXT_R2I)r2i_certpol, 99 .usr_data = NULL, 100}; 101 102static const ASN1_TEMPLATE CERTIFICATEPOLICIES_item_tt = { 103 .flags = ASN1_TFLG_SEQUENCE_OF, 104 .tag = 0, 105 .offset = 0, 106 .field_name = "CERTIFICATEPOLICIES", 107 .item = &POLICYINFO_it, 108}; 109 110const ASN1_ITEM CERTIFICATEPOLICIES_it = { 111 .itype = ASN1_ITYPE_PRIMITIVE, 112 .utype = -1, 113 .templates = &CERTIFICATEPOLICIES_item_tt, 114 .tcount = 0, 115 .funcs = NULL, 116 .size = 0, 117 .sname = "CERTIFICATEPOLICIES", 118}; 119 120 121CERTIFICATEPOLICIES * 122d2i_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES **a, const unsigned char **in, long len) 123{ 124 return (CERTIFICATEPOLICIES *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 125 &CERTIFICATEPOLICIES_it); 126} 127LCRYPTO_ALIAS(d2i_CERTIFICATEPOLICIES); 128 129int 130i2d_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES *a, unsigned char **out) 131{ 132 return ASN1_item_i2d((ASN1_VALUE *)a, out, &CERTIFICATEPOLICIES_it); 133} 134LCRYPTO_ALIAS(i2d_CERTIFICATEPOLICIES); 135 136CERTIFICATEPOLICIES * 137CERTIFICATEPOLICIES_new(void) 138{ 139 return (CERTIFICATEPOLICIES *)ASN1_item_new(&CERTIFICATEPOLICIES_it); 140} 141LCRYPTO_ALIAS(CERTIFICATEPOLICIES_new); 142 143void 144CERTIFICATEPOLICIES_free(CERTIFICATEPOLICIES *a) 145{ 146 ASN1_item_free((ASN1_VALUE *)a, &CERTIFICATEPOLICIES_it); 147} 148LCRYPTO_ALIAS(CERTIFICATEPOLICIES_free); 149 150static const ASN1_TEMPLATE POLICYINFO_seq_tt[] = { 151 { 152 .flags = 0, 153 .tag = 0, 154 .offset = offsetof(POLICYINFO, policyid), 155 .field_name = "policyid", 156 .item = &ASN1_OBJECT_it, 157 }, 158 { 159 .flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, 160 .tag = 0, 161 .offset = offsetof(POLICYINFO, qualifiers), 162 .field_name = "qualifiers", 163 .item = &POLICYQUALINFO_it, 164 }, 165}; 166 167const ASN1_ITEM POLICYINFO_it = { 168 .itype = ASN1_ITYPE_SEQUENCE, 169 .utype = V_ASN1_SEQUENCE, 170 .templates = POLICYINFO_seq_tt, 171 .tcount = sizeof(POLICYINFO_seq_tt) / sizeof(ASN1_TEMPLATE), 172 .funcs = NULL, 173 .size = sizeof(POLICYINFO), 174 .sname = "POLICYINFO", 175}; 176 177 178POLICYINFO * 179d2i_POLICYINFO(POLICYINFO **a, const unsigned char **in, long len) 180{ 181 return (POLICYINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 182 &POLICYINFO_it); 183} 184LCRYPTO_ALIAS(d2i_POLICYINFO); 185 186int 187i2d_POLICYINFO(POLICYINFO *a, unsigned char **out) 188{ 189 return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYINFO_it); 190} 191LCRYPTO_ALIAS(i2d_POLICYINFO); 192 193POLICYINFO * 194POLICYINFO_new(void) 195{ 196 return (POLICYINFO *)ASN1_item_new(&POLICYINFO_it); 197} 198LCRYPTO_ALIAS(POLICYINFO_new); 199 200void 201POLICYINFO_free(POLICYINFO *a) 202{ 203 ASN1_item_free((ASN1_VALUE *)a, &POLICYINFO_it); 204} 205LCRYPTO_ALIAS(POLICYINFO_free); 206 207static const ASN1_TEMPLATE policydefault_tt = { 208 .flags = 0, 209 .tag = 0, 210 .offset = offsetof(POLICYQUALINFO, d.other), 211 .field_name = "d.other", 212 .item = &ASN1_ANY_it, 213}; 214 215static const ASN1_ADB_TABLE POLICYQUALINFO_adbtbl[] = { 216 { 217 .value = NID_id_qt_cps, 218 .tt = { 219 .flags = 0, 220 .tag = 0, 221 .offset = offsetof(POLICYQUALINFO, d.cpsuri), 222 .field_name = "d.cpsuri", 223 .item = &ASN1_IA5STRING_it, 224 }, 225 }, 226 { 227 .value = NID_id_qt_unotice, 228 .tt = { 229 .flags = 0, 230 .tag = 0, 231 .offset = offsetof(POLICYQUALINFO, d.usernotice), 232 .field_name = "d.usernotice", 233 .item = &USERNOTICE_it, 234 }, 235 }, 236}; 237 238static const ASN1_ADB POLICYQUALINFO_adb = { 239 .flags = 0, 240 .offset = offsetof(POLICYQUALINFO, pqualid), 241 .tbl = POLICYQUALINFO_adbtbl, 242 .tblcount = sizeof(POLICYQUALINFO_adbtbl) / sizeof(ASN1_ADB_TABLE), 243 .default_tt = &policydefault_tt, 244 .null_tt = NULL, 245}; 246 247static const ASN1_TEMPLATE POLICYQUALINFO_seq_tt[] = { 248 { 249 .flags = 0, 250 .tag = 0, 251 .offset = offsetof(POLICYQUALINFO, pqualid), 252 .field_name = "pqualid", 253 .item = &ASN1_OBJECT_it, 254 }, 255 { 256 .flags = ASN1_TFLG_ADB_OID, 257 .tag = -1, 258 .offset = 0, 259 .field_name = "POLICYQUALINFO", 260 .item = (const ASN1_ITEM *)&POLICYQUALINFO_adb, 261 }, 262}; 263 264const ASN1_ITEM POLICYQUALINFO_it = { 265 .itype = ASN1_ITYPE_SEQUENCE, 266 .utype = V_ASN1_SEQUENCE, 267 .templates = POLICYQUALINFO_seq_tt, 268 .tcount = sizeof(POLICYQUALINFO_seq_tt) / sizeof(ASN1_TEMPLATE), 269 .funcs = NULL, 270 .size = sizeof(POLICYQUALINFO), 271 .sname = "POLICYQUALINFO", 272}; 273 274 275POLICYQUALINFO * 276d2i_POLICYQUALINFO(POLICYQUALINFO **a, const unsigned char **in, long len) 277{ 278 return (POLICYQUALINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 279 &POLICYQUALINFO_it); 280} 281LCRYPTO_ALIAS(d2i_POLICYQUALINFO); 282 283int 284i2d_POLICYQUALINFO(POLICYQUALINFO *a, unsigned char **out) 285{ 286 return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYQUALINFO_it); 287} 288LCRYPTO_ALIAS(i2d_POLICYQUALINFO); 289 290POLICYQUALINFO * 291POLICYQUALINFO_new(void) 292{ 293 return (POLICYQUALINFO *)ASN1_item_new(&POLICYQUALINFO_it); 294} 295LCRYPTO_ALIAS(POLICYQUALINFO_new); 296 297void 298POLICYQUALINFO_free(POLICYQUALINFO *a) 299{ 300 ASN1_item_free((ASN1_VALUE *)a, &POLICYQUALINFO_it); 301} 302LCRYPTO_ALIAS(POLICYQUALINFO_free); 303 304static const ASN1_TEMPLATE USERNOTICE_seq_tt[] = { 305 { 306 .flags = ASN1_TFLG_OPTIONAL, 307 .tag = 0, 308 .offset = offsetof(USERNOTICE, noticeref), 309 .field_name = "noticeref", 310 .item = &NOTICEREF_it, 311 }, 312 { 313 .flags = ASN1_TFLG_OPTIONAL, 314 .tag = 0, 315 .offset = offsetof(USERNOTICE, exptext), 316 .field_name = "exptext", 317 .item = &DISPLAYTEXT_it, 318 }, 319}; 320 321const ASN1_ITEM USERNOTICE_it = { 322 .itype = ASN1_ITYPE_SEQUENCE, 323 .utype = V_ASN1_SEQUENCE, 324 .templates = USERNOTICE_seq_tt, 325 .tcount = sizeof(USERNOTICE_seq_tt) / sizeof(ASN1_TEMPLATE), 326 .funcs = NULL, 327 .size = sizeof(USERNOTICE), 328 .sname = "USERNOTICE", 329}; 330 331 332USERNOTICE * 333d2i_USERNOTICE(USERNOTICE **a, const unsigned char **in, long len) 334{ 335 return (USERNOTICE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 336 &USERNOTICE_it); 337} 338LCRYPTO_ALIAS(d2i_USERNOTICE); 339 340int 341i2d_USERNOTICE(USERNOTICE *a, unsigned char **out) 342{ 343 return ASN1_item_i2d((ASN1_VALUE *)a, out, &USERNOTICE_it); 344} 345LCRYPTO_ALIAS(i2d_USERNOTICE); 346 347USERNOTICE * 348USERNOTICE_new(void) 349{ 350 return (USERNOTICE *)ASN1_item_new(&USERNOTICE_it); 351} 352LCRYPTO_ALIAS(USERNOTICE_new); 353 354void 355USERNOTICE_free(USERNOTICE *a) 356{ 357 ASN1_item_free((ASN1_VALUE *)a, &USERNOTICE_it); 358} 359LCRYPTO_ALIAS(USERNOTICE_free); 360 361static const ASN1_TEMPLATE NOTICEREF_seq_tt[] = { 362 { 363 .flags = 0, 364 .tag = 0, 365 .offset = offsetof(NOTICEREF, organization), 366 .field_name = "organization", 367 .item = &DISPLAYTEXT_it, 368 }, 369 { 370 .flags = ASN1_TFLG_SEQUENCE_OF, 371 .tag = 0, 372 .offset = offsetof(NOTICEREF, noticenos), 373 .field_name = "noticenos", 374 .item = &ASN1_INTEGER_it, 375 }, 376}; 377 378const ASN1_ITEM NOTICEREF_it = { 379 .itype = ASN1_ITYPE_SEQUENCE, 380 .utype = V_ASN1_SEQUENCE, 381 .templates = NOTICEREF_seq_tt, 382 .tcount = sizeof(NOTICEREF_seq_tt) / sizeof(ASN1_TEMPLATE), 383 .funcs = NULL, 384 .size = sizeof(NOTICEREF), 385 .sname = "NOTICEREF", 386}; 387 388 389NOTICEREF * 390d2i_NOTICEREF(NOTICEREF **a, const unsigned char **in, long len) 391{ 392 return (NOTICEREF *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 393 &NOTICEREF_it); 394} 395LCRYPTO_ALIAS(d2i_NOTICEREF); 396 397int 398i2d_NOTICEREF(NOTICEREF *a, unsigned char **out) 399{ 400 return ASN1_item_i2d((ASN1_VALUE *)a, out, &NOTICEREF_it); 401} 402LCRYPTO_ALIAS(i2d_NOTICEREF); 403 404NOTICEREF * 405NOTICEREF_new(void) 406{ 407 return (NOTICEREF *)ASN1_item_new(&NOTICEREF_it); 408} 409LCRYPTO_ALIAS(NOTICEREF_new); 410 411void 412NOTICEREF_free(NOTICEREF *a) 413{ 414 ASN1_item_free((ASN1_VALUE *)a, &NOTICEREF_it); 415} 416LCRYPTO_ALIAS(NOTICEREF_free); 417 418static STACK_OF(POLICYINFO) * 419r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value) 420{ 421 STACK_OF(POLICYINFO) *pols = NULL; 422 char *pstr; 423 POLICYINFO *pol; 424 ASN1_OBJECT *pobj; 425 STACK_OF(CONF_VALUE) *vals; 426 CONF_VALUE *cnf; 427 int i, ia5org; 428 429 pols = sk_POLICYINFO_new_null(); 430 if (pols == NULL) { 431 X509V3error(ERR_R_MALLOC_FAILURE); 432 return NULL; 433 } 434 vals = X509V3_parse_list(value); 435 if (vals == NULL) { 436 X509V3error(ERR_R_X509V3_LIB); 437 goto err; 438 } 439 ia5org = 0; 440 for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { 441 cnf = sk_CONF_VALUE_value(vals, i); 442 if (cnf->value || !cnf->name) { 443 X509V3error(X509V3_R_INVALID_POLICY_IDENTIFIER); 444 X509V3_conf_err(cnf); 445 goto err; 446 } 447 pstr = cnf->name; 448 if (!strcmp(pstr, "ia5org")) { 449 ia5org = 1; 450 continue; 451 } else if (*pstr == '@') { 452 STACK_OF(CONF_VALUE) *polsect; 453 polsect = X509V3_get_section(ctx, pstr + 1); 454 if (!polsect) { 455 X509V3error(X509V3_R_INVALID_SECTION); 456 X509V3_conf_err(cnf); 457 goto err; 458 } 459 pol = policy_section(ctx, polsect, ia5org); 460 X509V3_section_free(ctx, polsect); 461 if (!pol) 462 goto err; 463 } else { 464 if (!(pobj = OBJ_txt2obj(cnf->name, 0))) { 465 X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER); 466 X509V3_conf_err(cnf); 467 goto err; 468 } 469 pol = POLICYINFO_new(); 470 pol->policyid = pobj; 471 } 472 if (!sk_POLICYINFO_push(pols, pol)){ 473 POLICYINFO_free(pol); 474 X509V3error(ERR_R_MALLOC_FAILURE); 475 goto err; 476 } 477 } 478 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 479 return pols; 480 481err: 482 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 483 sk_POLICYINFO_pop_free(pols, POLICYINFO_free); 484 return NULL; 485} 486 487static POLICYINFO * 488policy_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *polstrs, int ia5org) 489{ 490 int i; 491 CONF_VALUE *cnf; 492 POLICYINFO *pol; 493 POLICYQUALINFO *nqual = NULL; 494 495 if ((pol = POLICYINFO_new()) == NULL) 496 goto merr; 497 for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { 498 cnf = sk_CONF_VALUE_value(polstrs, i); 499 if (strcmp(cnf->name, "policyIdentifier") == 0) { 500 ASN1_OBJECT *pobj; 501 502 if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) { 503 X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER); 504 X509V3_conf_err(cnf); 505 goto err; 506 } 507 pol->policyid = pobj; 508 } else if (name_cmp(cnf->name, "CPS") == 0) { 509 if ((nqual = POLICYQUALINFO_new()) == NULL) 510 goto merr; 511 nqual->pqualid = OBJ_nid2obj(NID_id_qt_cps); 512 nqual->d.cpsuri = ASN1_IA5STRING_new(); 513 if (nqual->d.cpsuri == NULL) 514 goto merr; 515 if (ASN1_STRING_set(nqual->d.cpsuri, cnf->value, 516 strlen(cnf->value)) == 0) 517 goto merr; 518 519 if (pol->qualifiers == NULL) { 520 pol->qualifiers = sk_POLICYQUALINFO_new_null(); 521 if (pol->qualifiers == NULL) 522 goto merr; 523 } 524 if (sk_POLICYQUALINFO_push(pol->qualifiers, nqual) == 0) 525 goto merr; 526 nqual = NULL; 527 } else if (name_cmp(cnf->name, "userNotice") == 0) { 528 STACK_OF(CONF_VALUE) *unot; 529 POLICYQUALINFO *qual; 530 531 if (*cnf->value != '@') { 532 X509V3error(X509V3_R_EXPECTED_A_SECTION_NAME); 533 X509V3_conf_err(cnf); 534 goto err; 535 } 536 unot = X509V3_get_section(ctx, cnf->value + 1); 537 if (unot == NULL) { 538 X509V3error(X509V3_R_INVALID_SECTION); 539 X509V3_conf_err(cnf); 540 goto err; 541 } 542 qual = notice_section(ctx, unot, ia5org); 543 X509V3_section_free(ctx, unot); 544 if (qual == NULL) 545 goto err; 546 547 if (pol->qualifiers == NULL) { 548 pol->qualifiers = sk_POLICYQUALINFO_new_null(); 549 if (pol->qualifiers == NULL) 550 goto merr; 551 } 552 if (sk_POLICYQUALINFO_push(pol->qualifiers, qual) == 0) 553 goto merr; 554 } else { 555 X509V3error(X509V3_R_INVALID_OPTION); 556 X509V3_conf_err(cnf); 557 goto err; 558 } 559 } 560 if (pol->policyid == NULL) { 561 X509V3error(X509V3_R_NO_POLICY_IDENTIFIER); 562 goto err; 563 } 564 565 return pol; 566 567merr: 568 X509V3error(ERR_R_MALLOC_FAILURE); 569 570err: 571 POLICYQUALINFO_free(nqual); 572 POLICYINFO_free(pol); 573 return NULL; 574} 575 576static POLICYQUALINFO * 577notice_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *unot, int ia5org) 578{ 579 int i, ret; 580 CONF_VALUE *cnf; 581 USERNOTICE *not; 582 POLICYQUALINFO *qual; 583 584 if (!(qual = POLICYQUALINFO_new())) 585 goto merr; 586 qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice); 587 if (!(not = USERNOTICE_new())) 588 goto merr; 589 qual->d.usernotice = not; 590 for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { 591 cnf = sk_CONF_VALUE_value(unot, i); 592 if (!strcmp(cnf->name, "explicitText")) { 593 if (not->exptext == NULL) { 594 not->exptext = ASN1_UTF8STRING_new(); 595 if (not->exptext == NULL) 596 goto merr; 597 } 598 if (!ASN1_STRING_set(not->exptext, cnf->value, 599 strlen(cnf->value))) 600 goto merr; 601 } else if (!strcmp(cnf->name, "organization")) { 602 NOTICEREF *nref; 603 if (!not->noticeref) { 604 if (!(nref = NOTICEREF_new())) 605 goto merr; 606 not->noticeref = nref; 607 } else 608 nref = not->noticeref; 609 if (ia5org) 610 nref->organization->type = V_ASN1_IA5STRING; 611 else 612 nref->organization->type = V_ASN1_VISIBLESTRING; 613 if (!ASN1_STRING_set(nref->organization, cnf->value, 614 strlen(cnf->value))) 615 goto merr; 616 } else if (!strcmp(cnf->name, "noticeNumbers")) { 617 NOTICEREF *nref; 618 STACK_OF(CONF_VALUE) *nos; 619 if (!not->noticeref) { 620 if (!(nref = NOTICEREF_new())) 621 goto merr; 622 not->noticeref = nref; 623 } else 624 nref = not->noticeref; 625 nos = X509V3_parse_list(cnf->value); 626 if (!nos || !sk_CONF_VALUE_num(nos)) { 627 X509V3error(X509V3_R_INVALID_NUMBERS); 628 X509V3_conf_err(cnf); 629 if (nos != NULL) 630 sk_CONF_VALUE_pop_free(nos, 631 X509V3_conf_free); 632 goto err; 633 } 634 ret = nref_nos(nref->noticenos, nos); 635 sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); 636 if (!ret) 637 goto err; 638 } else { 639 X509V3error(X509V3_R_INVALID_OPTION); 640 X509V3_conf_err(cnf); 641 goto err; 642 } 643 } 644 645 if (not->noticeref && 646 (!not->noticeref->noticenos || !not->noticeref->organization)) { 647 X509V3error(X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); 648 goto err; 649 } 650 651 return qual; 652 653merr: 654 X509V3error(ERR_R_MALLOC_FAILURE); 655 656err: 657 POLICYQUALINFO_free(qual); 658 return NULL; 659} 660 661static int 662nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) 663{ 664 CONF_VALUE *cnf; 665 ASN1_INTEGER *aint; 666 int i; 667 668 for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { 669 cnf = sk_CONF_VALUE_value(nos, i); 670 if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { 671 X509V3error(X509V3_R_INVALID_NUMBER); 672 goto err; 673 } 674 if (!sk_ASN1_INTEGER_push(nnums, aint)) 675 goto merr; 676 } 677 return 1; 678 679merr: 680 X509V3error(ERR_R_MALLOC_FAILURE); 681 682err: 683 sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free); 684 return 0; 685} 686 687static int 688i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, BIO *out, 689 int indent) 690{ 691 int i; 692 POLICYINFO *pinfo; 693 694 /* First print out the policy OIDs */ 695 for (i = 0; i < sk_POLICYINFO_num(pol); i++) { 696 pinfo = sk_POLICYINFO_value(pol, i); 697 BIO_printf(out, "%*sPolicy: ", indent, ""); 698 i2a_ASN1_OBJECT(out, pinfo->policyid); 699 BIO_puts(out, "\n"); 700 if (pinfo->qualifiers) 701 print_qualifiers(out, pinfo->qualifiers, indent + 2); 702 } 703 return 1; 704} 705 706static void 707print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent) 708{ 709 POLICYQUALINFO *qualinfo; 710 int i; 711 712 for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { 713 qualinfo = sk_POLICYQUALINFO_value(quals, i); 714 switch (OBJ_obj2nid(qualinfo->pqualid)) { 715 case NID_id_qt_cps: 716 BIO_printf(out, "%*sCPS: %.*s\n", indent, "", 717 qualinfo->d.cpsuri->length, 718 qualinfo->d.cpsuri->data); 719 break; 720 721 case NID_id_qt_unotice: 722 BIO_printf(out, "%*sUser Notice:\n", indent, ""); 723 print_notice(out, qualinfo->d.usernotice, indent + 2); 724 break; 725 726 default: 727 BIO_printf(out, "%*sUnknown Qualifier: ", 728 indent + 2, ""); 729 730 i2a_ASN1_OBJECT(out, qualinfo->pqualid); 731 BIO_puts(out, "\n"); 732 break; 733 } 734 } 735} 736 737static void 738print_notice(BIO *out, USERNOTICE *notice, int indent) 739{ 740 int i; 741 742 if (notice->noticeref) { 743 NOTICEREF *ref; 744 ref = notice->noticeref; 745 BIO_printf(out, "%*sOrganization: %.*s\n", indent, "", 746 ref->organization->length, ref->organization->data); 747 BIO_printf(out, "%*sNumber%s: ", indent, "", 748 sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); 749 for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { 750 ASN1_INTEGER *num; 751 char *tmp; 752 num = sk_ASN1_INTEGER_value(ref->noticenos, i); 753 if (i) 754 BIO_puts(out, ", "); 755 tmp = i2s_ASN1_INTEGER(NULL, num); 756 BIO_puts(out, tmp); 757 free(tmp); 758 } 759 BIO_puts(out, "\n"); 760 } 761 if (notice->exptext) 762 BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "", 763 notice->exptext->length, notice->exptext->data); 764} 765