1 /* $OpenBSD: x509_cpols.c,v 1.1 2020/06/04 15:19:31 jsing 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 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 const 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 102 static 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 110 const 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 121 CERTIFICATEPOLICIES * 122 d2i_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 } 127 128 int 129 i2d_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES *a, unsigned char **out) 130 { 131 return ASN1_item_i2d((ASN1_VALUE *)a, out, &CERTIFICATEPOLICIES_it); 132 } 133 134 CERTIFICATEPOLICIES * 135 CERTIFICATEPOLICIES_new(void) 136 { 137 return (CERTIFICATEPOLICIES *)ASN1_item_new(&CERTIFICATEPOLICIES_it); 138 } 139 140 void 141 CERTIFICATEPOLICIES_free(CERTIFICATEPOLICIES *a) 142 { 143 ASN1_item_free((ASN1_VALUE *)a, &CERTIFICATEPOLICIES_it); 144 } 145 146 static const ASN1_TEMPLATE POLICYINFO_seq_tt[] = { 147 { 148 .flags = 0, 149 .tag = 0, 150 .offset = offsetof(POLICYINFO, policyid), 151 .field_name = "policyid", 152 .item = &ASN1_OBJECT_it, 153 }, 154 { 155 .flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, 156 .tag = 0, 157 .offset = offsetof(POLICYINFO, qualifiers), 158 .field_name = "qualifiers", 159 .item = &POLICYQUALINFO_it, 160 }, 161 }; 162 163 const ASN1_ITEM POLICYINFO_it = { 164 .itype = ASN1_ITYPE_SEQUENCE, 165 .utype = V_ASN1_SEQUENCE, 166 .templates = POLICYINFO_seq_tt, 167 .tcount = sizeof(POLICYINFO_seq_tt) / sizeof(ASN1_TEMPLATE), 168 .funcs = NULL, 169 .size = sizeof(POLICYINFO), 170 .sname = "POLICYINFO", 171 }; 172 173 174 POLICYINFO * 175 d2i_POLICYINFO(POLICYINFO **a, const unsigned char **in, long len) 176 { 177 return (POLICYINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 178 &POLICYINFO_it); 179 } 180 181 int 182 i2d_POLICYINFO(POLICYINFO *a, unsigned char **out) 183 { 184 return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYINFO_it); 185 } 186 187 POLICYINFO * 188 POLICYINFO_new(void) 189 { 190 return (POLICYINFO *)ASN1_item_new(&POLICYINFO_it); 191 } 192 193 void 194 POLICYINFO_free(POLICYINFO *a) 195 { 196 ASN1_item_free((ASN1_VALUE *)a, &POLICYINFO_it); 197 } 198 199 static const ASN1_TEMPLATE policydefault_tt = { 200 .flags = 0, 201 .tag = 0, 202 .offset = offsetof(POLICYQUALINFO, d.other), 203 .field_name = "d.other", 204 .item = &ASN1_ANY_it, 205 }; 206 207 static const ASN1_ADB_TABLE POLICYQUALINFO_adbtbl[] = { 208 { 209 .value = NID_id_qt_cps, 210 .tt = { 211 .flags = 0, 212 .tag = 0, 213 .offset = offsetof(POLICYQUALINFO, d.cpsuri), 214 .field_name = "d.cpsuri", 215 .item = &ASN1_IA5STRING_it, 216 }, 217 218 }, 219 { 220 .value = NID_id_qt_unotice, 221 .tt = { 222 .flags = 0, 223 .tag = 0, 224 .offset = offsetof(POLICYQUALINFO, d.usernotice), 225 .field_name = "d.usernotice", 226 .item = &USERNOTICE_it, 227 }, 228 229 }, 230 }; 231 232 static const ASN1_ADB POLICYQUALINFO_adb = { 233 .flags = 0, 234 .offset = offsetof(POLICYQUALINFO, pqualid), 235 .app_items = 0, 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->data); 701 break; 702 703 case NID_id_qt_unotice: 704 BIO_printf(out, "%*sUser Notice:\n", indent, ""); 705 print_notice(out, qualinfo->d.usernotice, indent + 2); 706 break; 707 708 default: 709 BIO_printf(out, "%*sUnknown Qualifier: ", 710 indent + 2, ""); 711 712 i2a_ASN1_OBJECT(out, qualinfo->pqualid); 713 BIO_puts(out, "\n"); 714 break; 715 } 716 } 717 } 718 719 static void 720 print_notice(BIO *out, USERNOTICE *notice, int indent) 721 { 722 int i; 723 724 if (notice->noticeref) { 725 NOTICEREF *ref; 726 ref = notice->noticeref; 727 BIO_printf(out, "%*sOrganization: %s\n", indent, "", 728 ref->organization->data); 729 BIO_printf(out, "%*sNumber%s: ", indent, "", 730 sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); 731 for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { 732 ASN1_INTEGER *num; 733 char *tmp; 734 num = sk_ASN1_INTEGER_value(ref->noticenos, i); 735 if (i) 736 BIO_puts(out, ", "); 737 tmp = i2s_ASN1_INTEGER(NULL, num); 738 BIO_puts(out, tmp); 739 free(tmp); 740 } 741 BIO_puts(out, "\n"); 742 } 743 if (notice->exptext) 744 BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", 745 notice->exptext->data); 746 } 747 748 void 749 X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) 750 { 751 const X509_POLICY_DATA *dat = node->data; 752 753 BIO_printf(out, "%*sPolicy: ", indent, ""); 754 755 i2a_ASN1_OBJECT(out, dat->valid_policy); 756 BIO_puts(out, "\n"); 757 BIO_printf(out, "%*s%s\n", indent + 2, "", 758 node_data_critical(dat) ? "Critical" : "Non Critical"); 759 if (dat->qualifier_set) 760 print_qualifiers(out, dat->qualifier_set, indent + 2); 761 else 762 BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); 763 } 764