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