1 /* $OpenBSD: pcy_tree.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 2004. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 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 <openssl/x509.h> 60 #include <openssl/x509v3.h> 61 62 #include "pcy_int.h" 63 #include "x509_lcl.h" 64 65 /* Enable this to print out the complete policy tree at various point during 66 * evaluation. 67 */ 68 69 /*#define OPENSSL_POLICY_DEBUG*/ 70 71 #ifdef OPENSSL_POLICY_DEBUG 72 73 static void 74 expected_print(BIO *err, X509_POLICY_LEVEL *lev, X509_POLICY_NODE *node, 75 int indent) 76 { 77 if ((lev->flags & X509_V_FLAG_INHIBIT_MAP) || 78 !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK)) 79 BIO_puts(err, " Not Mapped\n"); 80 else { 81 int i; 82 STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set; 83 ASN1_OBJECT *oid; 84 BIO_puts(err, " Expected: "); 85 for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) { 86 oid = sk_ASN1_OBJECT_value(pset, i); 87 if (i) 88 BIO_puts(err, ", "); 89 i2a_ASN1_OBJECT(err, oid); 90 } 91 BIO_puts(err, "\n"); 92 } 93 } 94 95 static void 96 tree_print(char *str, X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) 97 { 98 X509_POLICY_LEVEL *plev; 99 X509_POLICY_NODE *node; 100 int i; 101 BIO *err; 102 103 if ((err = BIO_new_fp(stderr, BIO_NOCLOSE)) == NULL) 104 return; 105 106 if (!curr) 107 curr = tree->levels + tree->nlevel; 108 else 109 curr++; 110 BIO_printf(err, "Level print after %s\n", str); 111 BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels); 112 for (plev = tree->levels; plev != curr; plev++) { 113 BIO_printf(err, "Level %ld, flags = %x\n", 114 plev - tree->levels, plev->flags); 115 for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) { 116 node = sk_X509_POLICY_NODE_value(plev->nodes, i); 117 X509_POLICY_NODE_print(err, node, 2); 118 expected_print(err, plev, node, 2); 119 BIO_printf(err, " Flags: %x\n", node->data->flags); 120 } 121 if (plev->anyPolicy) 122 X509_POLICY_NODE_print(err, plev->anyPolicy, 2); 123 } 124 125 BIO_free(err); 126 } 127 #else 128 129 #define tree_print(a,b,c) /* */ 130 131 #endif 132 133 /* Initialize policy tree. Return values: 134 * 0 Some internal error occured. 135 * -1 Inconsistent or invalid extensions in certificates. 136 * 1 Tree initialized OK. 137 * 2 Policy tree is empty. 138 * 5 Tree OK and requireExplicitPolicy true. 139 * 6 Tree empty and requireExplicitPolicy true. 140 */ 141 142 static int 143 tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, unsigned int flags) 144 { 145 X509_POLICY_TREE *tree; 146 X509_POLICY_LEVEL *level; 147 const X509_POLICY_CACHE *cache; 148 X509_POLICY_DATA *data = NULL; 149 X509 *x; 150 int ret = 1; 151 int i, n; 152 int explicit_policy; 153 int any_skip; 154 int map_skip; 155 156 *ptree = NULL; 157 n = sk_X509_num(certs); 158 159 if (flags & X509_V_FLAG_EXPLICIT_POLICY) 160 explicit_policy = 0; 161 else 162 explicit_policy = n + 1; 163 164 if (flags & X509_V_FLAG_INHIBIT_ANY) 165 any_skip = 0; 166 else 167 any_skip = n + 1; 168 169 if (flags & X509_V_FLAG_INHIBIT_MAP) 170 map_skip = 0; 171 else 172 map_skip = n + 1; 173 174 /* Can't do anything with just a trust anchor */ 175 if (n == 1) 176 return 1; 177 /* First setup policy cache in all certificates apart from the 178 * trust anchor. Note any bad cache results on the way. Also can 179 * calculate explicit_policy value at this point. 180 */ 181 for (i = n - 2; i >= 0; i--) { 182 x = sk_X509_value(certs, i); 183 X509_check_purpose(x, -1, -1); 184 cache = policy_cache_set(x); 185 /* If cache NULL something bad happened: return immediately */ 186 if (cache == NULL) 187 return 0; 188 /* If inconsistent extensions keep a note of it but continue */ 189 if (x->ex_flags & EXFLAG_INVALID_POLICY) 190 ret = -1; 191 /* Otherwise if we have no data (hence no CertificatePolicies) 192 * and haven't already set an inconsistent code note it. 193 */ 194 else if ((ret == 1) && !cache->data) 195 ret = 2; 196 if (explicit_policy > 0) { 197 if (!(x->ex_flags & EXFLAG_SI)) 198 explicit_policy--; 199 if ((cache->explicit_skip != -1) && 200 (cache->explicit_skip < explicit_policy)) 201 explicit_policy = cache->explicit_skip; 202 } 203 } 204 205 if (ret != 1) { 206 if (ret == 2 && !explicit_policy) 207 return 6; 208 return ret; 209 } 210 211 212 /* If we get this far initialize the tree */ 213 214 tree = malloc(sizeof(X509_POLICY_TREE)); 215 216 if (!tree) 217 return 0; 218 219 tree->flags = 0; 220 tree->levels = calloc(n, sizeof(X509_POLICY_LEVEL)); 221 tree->nlevel = 0; 222 tree->extra_data = NULL; 223 tree->auth_policies = NULL; 224 tree->user_policies = NULL; 225 226 if (!tree->levels) { 227 free(tree); 228 return 0; 229 } 230 231 tree->nlevel = n; 232 233 level = tree->levels; 234 235 /* Root data: initialize to anyPolicy */ 236 237 data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0); 238 239 if (!data || !level_add_node(level, data, NULL, tree, NULL)) 240 goto bad_tree; 241 242 for (i = n - 2; i >= 0; i--) { 243 level++; 244 x = sk_X509_value(certs, i); 245 cache = policy_cache_set(x); 246 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); 247 level->cert = x; 248 249 if (!cache->anyPolicy) 250 level->flags |= X509_V_FLAG_INHIBIT_ANY; 251 252 /* Determine inhibit any and inhibit map flags */ 253 if (any_skip == 0) { 254 /* Any matching allowed if certificate is self 255 * issued and not the last in the chain. 256 */ 257 if (!(x->ex_flags & EXFLAG_SI) || (i == 0)) 258 level->flags |= X509_V_FLAG_INHIBIT_ANY; 259 } else { 260 if (!(x->ex_flags & EXFLAG_SI)) 261 any_skip--; 262 if ((cache->any_skip >= 0) && 263 (cache->any_skip < any_skip)) 264 any_skip = cache->any_skip; 265 } 266 267 if (map_skip == 0) 268 level->flags |= X509_V_FLAG_INHIBIT_MAP; 269 else { 270 if (!(x->ex_flags & EXFLAG_SI)) 271 map_skip--; 272 if ((cache->map_skip >= 0) && 273 (cache->map_skip < map_skip)) 274 map_skip = cache->map_skip; 275 } 276 277 } 278 279 *ptree = tree; 280 281 if (explicit_policy) 282 return 1; 283 else 284 return 5; 285 286 bad_tree: 287 X509_policy_tree_free(tree); 288 289 return 0; 290 } 291 292 static int 293 tree_link_matching_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_DATA *data) 294 { 295 X509_POLICY_LEVEL *last = curr - 1; 296 X509_POLICY_NODE *node; 297 int i, matched = 0; 298 299 /* Iterate through all in nodes linking matches */ 300 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { 301 node = sk_X509_POLICY_NODE_value(last->nodes, i); 302 if (policy_node_match(last, node, data->valid_policy)) { 303 if (!level_add_node(curr, data, node, NULL, NULL)) 304 return 0; 305 matched = 1; 306 } 307 } 308 if (!matched && last->anyPolicy) { 309 if (!level_add_node(curr, data, last->anyPolicy, NULL, NULL)) 310 return 0; 311 } 312 return 1; 313 } 314 315 /* This corresponds to RFC3280 6.1.3(d)(1): 316 * link any data from CertificatePolicies onto matching parent 317 * or anyPolicy if no match. 318 */ 319 320 static int 321 tree_link_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache) 322 { 323 int i; 324 X509_POLICY_DATA *data; 325 326 for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) { 327 data = sk_X509_POLICY_DATA_value(cache->data, i); 328 /* Look for matching nodes in previous level */ 329 if (!tree_link_matching_nodes(curr, data)) 330 return 0; 331 } 332 return 1; 333 } 334 335 /* This corresponds to RFC3280 6.1.3(d)(2): 336 * Create new data for any unmatched policies in the parent and link 337 * to anyPolicy. 338 */ 339 340 static int 341 tree_add_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache, 342 const ASN1_OBJECT *id, X509_POLICY_NODE *node, X509_POLICY_TREE *tree) 343 { 344 X509_POLICY_DATA *data; 345 346 if (id == NULL) 347 id = node->data->valid_policy; 348 /* Create a new node with qualifiers from anyPolicy and 349 * id from unmatched node. 350 */ 351 data = policy_data_new(NULL, id, node_critical(node)); 352 353 if (data == NULL) 354 return 0; 355 /* Curr may not have anyPolicy */ 356 data->qualifier_set = cache->anyPolicy->qualifier_set; 357 data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; 358 if (!level_add_node(curr, data, node, tree, NULL)) { 359 policy_data_free(data); 360 return 0; 361 } 362 363 return 1; 364 } 365 366 static int 367 tree_link_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache, 368 X509_POLICY_NODE *node, X509_POLICY_TREE *tree) 369 { 370 const X509_POLICY_LEVEL *last = curr - 1; 371 int i; 372 373 if ((last->flags & X509_V_FLAG_INHIBIT_MAP) || 374 !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) { 375 /* If no policy mapping: matched if one child present */ 376 if (node->nchild) 377 return 1; 378 if (!tree_add_unmatched(curr, cache, NULL, node, tree)) 379 return 0; 380 /* Add it */ 381 } else { 382 /* If mapping: matched if one child per expected policy set */ 383 STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set; 384 if (node->nchild == sk_ASN1_OBJECT_num(expset)) 385 return 1; 386 /* Locate unmatched nodes */ 387 for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) { 388 ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i); 389 if (level_find_node(curr, node, oid)) 390 continue; 391 if (!tree_add_unmatched(curr, cache, oid, node, tree)) 392 return 0; 393 } 394 } 395 396 return 1; 397 } 398 399 static int 400 tree_link_any(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache, 401 X509_POLICY_TREE *tree) 402 { 403 int i; 404 X509_POLICY_NODE *node; 405 X509_POLICY_LEVEL *last = curr - 1; 406 407 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { 408 node = sk_X509_POLICY_NODE_value(last->nodes, i); 409 410 if (!tree_link_unmatched(curr, cache, node, tree)) 411 return 0; 412 } 413 /* Finally add link to anyPolicy */ 414 if (last->anyPolicy) { 415 if (!level_add_node(curr, cache->anyPolicy, 416 last->anyPolicy, NULL, NULL)) 417 return 0; 418 } 419 return 1; 420 } 421 422 /* Prune the tree: delete any child mapped child data on the current level 423 * then proceed up the tree deleting any data with no children. If we ever 424 * have no data on a level we can halt because the tree will be empty. 425 */ 426 427 static int 428 tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) 429 { 430 STACK_OF(X509_POLICY_NODE) *nodes; 431 X509_POLICY_NODE *node; 432 int i; 433 434 nodes = curr->nodes; 435 if (curr->flags & X509_V_FLAG_INHIBIT_MAP) { 436 for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { 437 node = sk_X509_POLICY_NODE_value(nodes, i); 438 /* Delete any mapped data: see RFC3280 XXXX */ 439 if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) { 440 node->parent->nchild--; 441 free(node); 442 (void)sk_X509_POLICY_NODE_delete(nodes, i); 443 } 444 } 445 } 446 447 for (;;) { 448 --curr; 449 nodes = curr->nodes; 450 for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { 451 node = sk_X509_POLICY_NODE_value(nodes, i); 452 if (node->nchild == 0) { 453 node->parent->nchild--; 454 free(node); 455 (void)sk_X509_POLICY_NODE_delete(nodes, i); 456 } 457 } 458 if (curr->anyPolicy && !curr->anyPolicy->nchild) { 459 if (curr->anyPolicy->parent) 460 curr->anyPolicy->parent->nchild--; 461 free(curr->anyPolicy); 462 curr->anyPolicy = NULL; 463 } 464 if (curr == tree->levels) { 465 /* If we zapped anyPolicy at top then tree is empty */ 466 if (!curr->anyPolicy) 467 return 2; 468 return 1; 469 } 470 } 471 472 return 1; 473 } 474 475 static int 476 tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, X509_POLICY_NODE *pcy) 477 { 478 if (!*pnodes) { 479 *pnodes = policy_node_cmp_new(); 480 if (!*pnodes) 481 return 0; 482 } else if (sk_X509_POLICY_NODE_find(*pnodes, pcy) != -1) 483 return 1; 484 485 if (!sk_X509_POLICY_NODE_push(*pnodes, pcy)) 486 return 0; 487 488 return 1; 489 } 490 491 /* Calculate the authority set based on policy tree. 492 * The 'pnodes' parameter is used as a store for the set of policy nodes 493 * used to calculate the user set. If the authority set is not anyPolicy 494 * then pnodes will just point to the authority set. If however the authority 495 * set is anyPolicy then the set of valid policies (other than anyPolicy) 496 * is store in pnodes. The return value of '2' is used in this case to indicate 497 * that pnodes should be freed. 498 */ 499 500 static int 501 tree_calculate_authority_set(X509_POLICY_TREE *tree, 502 STACK_OF(X509_POLICY_NODE) **pnodes) 503 { 504 X509_POLICY_LEVEL *curr; 505 X509_POLICY_NODE *node, *anyptr; 506 STACK_OF(X509_POLICY_NODE) **addnodes; 507 int i, j; 508 509 curr = tree->levels + tree->nlevel - 1; 510 511 /* If last level contains anyPolicy set is anyPolicy */ 512 if (curr->anyPolicy) { 513 if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) 514 return 0; 515 addnodes = pnodes; 516 } else 517 /* Add policies to authority set */ 518 addnodes = &tree->auth_policies; 519 520 curr = tree->levels; 521 for (i = 1; i < tree->nlevel; i++) { 522 /* If no anyPolicy node on this this level it can't 523 * appear on lower levels so end search. 524 */ 525 if (!(anyptr = curr->anyPolicy)) 526 break; 527 curr++; 528 for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) { 529 node = sk_X509_POLICY_NODE_value(curr->nodes, j); 530 if ((node->parent == anyptr) && 531 !tree_add_auth_node(addnodes, node)) 532 return 0; 533 } 534 } 535 536 if (addnodes == pnodes) 537 return 2; 538 539 *pnodes = tree->auth_policies; 540 541 return 1; 542 } 543 544 static int 545 tree_calculate_user_set(X509_POLICY_TREE *tree, 546 STACK_OF(ASN1_OBJECT) *policy_oids, STACK_OF(X509_POLICY_NODE) *auth_nodes) 547 { 548 int i; 549 X509_POLICY_NODE *node; 550 ASN1_OBJECT *oid; 551 X509_POLICY_NODE *anyPolicy; 552 X509_POLICY_DATA *extra; 553 554 /* Check if anyPolicy present in authority constrained policy set: 555 * this will happen if it is a leaf node. 556 */ 557 558 if (sk_ASN1_OBJECT_num(policy_oids) <= 0) 559 return 1; 560 561 anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy; 562 563 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { 564 oid = sk_ASN1_OBJECT_value(policy_oids, i); 565 if (OBJ_obj2nid(oid) == NID_any_policy) { 566 tree->flags |= POLICY_FLAG_ANY_POLICY; 567 return 1; 568 } 569 } 570 571 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { 572 oid = sk_ASN1_OBJECT_value(policy_oids, i); 573 node = tree_find_sk(auth_nodes, oid); 574 if (!node) { 575 if (!anyPolicy) 576 continue; 577 /* Create a new node with policy ID from user set 578 * and qualifiers from anyPolicy. 579 */ 580 extra = policy_data_new(NULL, oid, 581 node_critical(anyPolicy)); 582 if (!extra) 583 return 0; 584 extra->qualifier_set = anyPolicy->data->qualifier_set; 585 extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS | 586 POLICY_DATA_FLAG_EXTRA_NODE; 587 (void) level_add_node(NULL, extra, anyPolicy->parent, 588 tree, &node); 589 } 590 if (!tree->user_policies) { 591 tree->user_policies = sk_X509_POLICY_NODE_new_null(); 592 if (!tree->user_policies) 593 return 1; 594 } 595 if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) 596 return 0; 597 } 598 return 1; 599 } 600 601 static int 602 tree_evaluate(X509_POLICY_TREE *tree) 603 { 604 int ret, i; 605 X509_POLICY_LEVEL *curr = tree->levels + 1; 606 const X509_POLICY_CACHE *cache; 607 608 for (i = 1; i < tree->nlevel; i++, curr++) { 609 cache = policy_cache_set(curr->cert); 610 if (!tree_link_nodes(curr, cache)) 611 return 0; 612 613 if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) && 614 !tree_link_any(curr, cache, tree)) 615 return 0; 616 tree_print("before tree_prune()", tree, curr); 617 ret = tree_prune(tree, curr); 618 if (ret != 1) 619 return ret; 620 } 621 622 return 1; 623 } 624 625 static void 626 exnode_free(X509_POLICY_NODE *node) 627 { 628 if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE)) 629 free(node); 630 } 631 632 void 633 X509_policy_tree_free(X509_POLICY_TREE *tree) 634 { 635 X509_POLICY_LEVEL *curr; 636 int i; 637 638 if (!tree) 639 return; 640 641 sk_X509_POLICY_NODE_free(tree->auth_policies); 642 sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free); 643 644 for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) { 645 X509_free(curr->cert); 646 if (curr->nodes) 647 sk_X509_POLICY_NODE_pop_free(curr->nodes, 648 policy_node_free); 649 if (curr->anyPolicy) 650 policy_node_free(curr->anyPolicy); 651 } 652 653 if (tree->extra_data) 654 sk_X509_POLICY_DATA_pop_free(tree->extra_data, 655 policy_data_free); 656 657 free(tree->levels); 658 free(tree); 659 } 660 661 /* Application policy checking function. 662 * Return codes: 663 * 0 Internal Error. 664 * 1 Successful. 665 * -1 One or more certificates contain invalid or inconsistent extensions 666 * -2 User constrained policy set empty and requireExplicit true. 667 */ 668 669 int 670 X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, 671 STACK_OF(X509) *certs, STACK_OF(ASN1_OBJECT) *policy_oids, 672 unsigned int flags) 673 { 674 int ret, ret2; 675 X509_POLICY_TREE *tree = NULL; 676 STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL; 677 678 *ptree = NULL; 679 *pexplicit_policy = 0; 680 ret = tree_init(&tree, certs, flags); 681 682 switch (ret) { 683 684 /* Tree empty requireExplicit False: OK */ 685 case 2: 686 return 1; 687 688 /* Some internal error */ 689 case -1: 690 return -1; 691 692 /* Some internal error */ 693 case 0: 694 return 0; 695 696 /* Tree empty requireExplicit True: Error */ 697 698 case 6: 699 *pexplicit_policy = 1; 700 return -2; 701 702 /* Tree OK requireExplicit True: OK and continue */ 703 case 5: 704 *pexplicit_policy = 1; 705 break; 706 707 /* Tree OK: continue */ 708 709 case 1: 710 if (!tree) 711 /* 712 * tree_init() returns success and a null tree 713 * if it's just looking at a trust anchor. 714 * I'm not sure that returning success here is 715 * correct, but I'm sure that reporting this 716 * as an internal error which our caller 717 * interprets as a malloc failure is wrong. 718 */ 719 return 1; 720 break; 721 } 722 723 if (!tree) 724 goto error; 725 ret = tree_evaluate(tree); 726 727 tree_print("tree_evaluate()", tree, NULL); 728 729 if (ret <= 0) 730 goto error; 731 732 /* Return value 2 means tree empty */ 733 if (ret == 2) { 734 X509_policy_tree_free(tree); 735 if (*pexplicit_policy) 736 return -2; 737 else 738 return 1; 739 } 740 741 /* Tree is not empty: continue */ 742 743 ret = tree_calculate_authority_set(tree, &auth_nodes); 744 if (ret == 0) 745 goto error; 746 747 ret2 = tree_calculate_user_set(tree, policy_oids, auth_nodes); 748 749 /* Return value 2 means auth_nodes needs to be freed */ 750 if (ret == 2) 751 sk_X509_POLICY_NODE_free(auth_nodes); 752 753 if (ret2 == 0) 754 goto error; 755 756 if (tree) 757 *ptree = tree; 758 759 if (*pexplicit_policy) { 760 nodes = X509_policy_tree_get0_user_policies(tree); 761 if (sk_X509_POLICY_NODE_num(nodes) <= 0) 762 return -2; 763 } 764 765 return 1; 766 767 error: 768 X509_policy_tree_free(tree); 769 770 return 0; 771 } 772