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