1/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2 * project 2004. 3 */ 4/* ==================================================================== 5 * Copyright (c) 2004 The OpenSSL Project. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. All advertising materials mentioning features or use of this 20 * software must display the following acknowledgment: 21 * "This product includes software developed by the OpenSSL Project 22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23 * 24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25 * endorse or promote products derived from this software without 26 * prior written permission. For written permission, please contact 27 * licensing@OpenSSL.org. 28 * 29 * 5. Products derived from this software may not be called "OpenSSL" 30 * nor may "OpenSSL" appear in their names without prior written 31 * permission of the OpenSSL Project. 32 * 33 * 6. Redistributions of any form whatsoever must retain the following 34 * acknowledgment: 35 * "This product includes software developed by the OpenSSL Project 36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49 * OF THE POSSIBILITY OF SUCH DAMAGE. 50 * ==================================================================== 51 * 52 * This product includes cryptographic software written by Eric Young 53 * (eay@cryptsoft.com). This product includes software written by Tim 54 * Hudson (tjh@cryptsoft.com). 55 * 56 */ 57 58#include <openssl/mem.h> 59#include <openssl/obj.h> 60#include <openssl/stack.h> 61#include <openssl/thread.h> 62#include <openssl/x509.h> 63#include <openssl/x509v3.h> 64 65#include "pcy_int.h" 66 67 68/* Enable this to print out the complete policy tree at various point during 69 * evaluation. 70 */ 71 72/*#define OPENSSL_POLICY_DEBUG*/ 73 74#ifdef OPENSSL_POLICY_DEBUG 75 76static void expected_print(BIO *err, X509_POLICY_LEVEL *lev, 77 X509_POLICY_NODE *node, int indent) 78 { 79 if ( (lev->flags & X509_V_FLAG_INHIBIT_MAP) 80 || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK)) 81 BIO_puts(err, " Not Mapped\n"); 82 else 83 { 84 int i; 85 STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set; 86 ASN1_OBJECT *oid; 87 BIO_puts(err, " Expected: "); 88 for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) 89 { 90 oid = sk_ASN1_OBJECT_value(pset, i); 91 if (i) 92 BIO_puts(err, ", "); 93 i2a_ASN1_OBJECT(err, oid); 94 } 95 BIO_puts(err, "\n"); 96 } 97 } 98 99static void tree_print(char *str, X509_POLICY_TREE *tree, 100 X509_POLICY_LEVEL *curr) 101 { 102 X509_POLICY_LEVEL *plev; 103 X509_POLICY_NODE *node; 104 int i; 105 BIO *err; 106 err = BIO_new_fp(stderr, BIO_NOCLOSE); 107 if (!curr) 108 curr = tree->levels + tree->nlevel; 109 else 110 curr++; 111 BIO_printf(err, "Level print after %s\n", str); 112 BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels); 113 for (plev = tree->levels; plev != curr; plev++) 114 { 115 BIO_printf(err, "Level %ld, flags = %x\n", 116 plev - tree->levels, plev->flags); 117 for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) 118 { 119 node = sk_X509_POLICY_NODE_value(plev->nodes, i); 120 X509_POLICY_NODE_print(err, node, 2); 121 expected_print(err, plev, node, 2); 122 BIO_printf(err, " Flags: %x\n", node->data->flags); 123 } 124 if (plev->anyPolicy) 125 X509_POLICY_NODE_print(err, plev->anyPolicy, 2); 126 } 127 128 BIO_free(err); 129 130 } 131#else 132 133#define tree_print(a,b,c) /* */ 134 135#endif 136 137/* Initialize policy tree. Return values: 138 * 0 Some internal error occured. 139 * -1 Inconsistent or invalid extensions in certificates. 140 * 1 Tree initialized OK. 141 * 2 Policy tree is empty. 142 * 5 Tree OK and requireExplicitPolicy true. 143 * 6 Tree empty and requireExplicitPolicy true. 144 */ 145 146static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, 147 unsigned int flags) 148 { 149 X509_POLICY_TREE *tree; 150 X509_POLICY_LEVEL *level; 151 const X509_POLICY_CACHE *cache; 152 X509_POLICY_DATA *data = NULL; 153 X509 *x; 154 int ret = 1; 155 int i, n; 156 int explicit_policy; 157 int any_skip; 158 int map_skip; 159 *ptree = NULL; 160 n = sk_X509_num(certs); 161 162#if 0 163 /* Disable policy mapping for now... */ 164 flags |= X509_V_FLAG_INHIBIT_MAP; 165#endif 166 167 if (flags & X509_V_FLAG_EXPLICIT_POLICY) 168 explicit_policy = 0; 169 else 170 explicit_policy = n + 1; 171 172 if (flags & X509_V_FLAG_INHIBIT_ANY) 173 any_skip = 0; 174 else 175 any_skip = n + 1; 176 177 if (flags & X509_V_FLAG_INHIBIT_MAP) 178 map_skip = 0; 179 else 180 map_skip = n + 1; 181 182 /* Can't do anything with just a trust anchor */ 183 if (n == 1) 184 return 1; 185 /* First setup policy cache in all certificates apart from the 186 * trust anchor. Note any bad cache results on the way. Also can 187 * calculate explicit_policy value at this point. 188 */ 189 for (i = n - 2; i >= 0; i--) 190 { 191 x = sk_X509_value(certs, i); 192 X509_check_purpose(x, -1, -1); 193 cache = policy_cache_set(x); 194 /* If cache NULL something bad happened: return immediately */ 195 if (cache == NULL) 196 return 0; 197 /* If inconsistent extensions keep a note of it but continue */ 198 if (x->ex_flags & EXFLAG_INVALID_POLICY) 199 ret = -1; 200 /* Otherwise if we have no data (hence no CertificatePolicies) 201 * and haven't already set an inconsistent code note it. 202 */ 203 else if ((ret == 1) && !cache->data) 204 ret = 2; 205 if (explicit_policy > 0) 206 { 207 if (!(x->ex_flags & EXFLAG_SI)) 208 explicit_policy--; 209 if ((cache->explicit_skip != -1) 210 && (cache->explicit_skip < explicit_policy)) 211 explicit_policy = cache->explicit_skip; 212 } 213 } 214 215 if (ret != 1) 216 { 217 if (ret == 2 && !explicit_policy) 218 return 6; 219 return ret; 220 } 221 222 223 /* If we get this far initialize the tree */ 224 225 tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE)); 226 227 if (!tree) 228 return 0; 229 230 tree->flags = 0; 231 tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n); 232 tree->nlevel = 0; 233 tree->extra_data = NULL; 234 tree->auth_policies = NULL; 235 tree->user_policies = NULL; 236 237 if (!tree->levels) 238 { 239 OPENSSL_free(tree); 240 return 0; 241 } 242 243 memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL)); 244 245 tree->nlevel = n; 246 247 level = tree->levels; 248 249 /* Root data: initialize to anyPolicy */ 250 251 data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0); 252 253 if (!data || !level_add_node(level, data, NULL, tree)) 254 goto bad_tree; 255 256 for (i = n - 2; i >= 0; i--) 257 { 258 level++; 259 x = sk_X509_value(certs, i); 260 cache = policy_cache_set(x); 261 level->cert = X509_up_ref(x); 262 263 if (!cache->anyPolicy) 264 level->flags |= X509_V_FLAG_INHIBIT_ANY; 265 266 /* Determine inhibit any and inhibit map flags */ 267 if (any_skip == 0) 268 { 269 /* Any matching allowed if certificate is self 270 * issued and not the last in the chain. 271 */ 272 if (!(x->ex_flags & EXFLAG_SI) || (i == 0)) 273 level->flags |= X509_V_FLAG_INHIBIT_ANY; 274 } 275 else 276 { 277 if (!(x->ex_flags & EXFLAG_SI)) 278 any_skip--; 279 if ((cache->any_skip >= 0) 280 && (cache->any_skip < any_skip)) 281 any_skip = cache->any_skip; 282 } 283 284 if (map_skip == 0) 285 level->flags |= X509_V_FLAG_INHIBIT_MAP; 286 else 287 { 288 if (!(x->ex_flags & EXFLAG_SI)) 289 map_skip--; 290 if ((cache->map_skip >= 0) 291 && (cache->map_skip < map_skip)) 292 map_skip = cache->map_skip; 293 } 294 295 } 296 297 *ptree = tree; 298 299 if (explicit_policy) 300 return 1; 301 else 302 return 5; 303 304 bad_tree: 305 306 X509_policy_tree_free(tree); 307 308 return 0; 309 310 } 311 312static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, 313 const X509_POLICY_DATA *data) 314 { 315 X509_POLICY_LEVEL *last = curr - 1; 316 X509_POLICY_NODE *node; 317 int matched = 0; 318 size_t i; 319 /* Iterate through all in nodes linking matches */ 320 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) 321 { 322 node = sk_X509_POLICY_NODE_value(last->nodes, i); 323 if (policy_node_match(last, node, data->valid_policy)) 324 { 325 if (!level_add_node(curr, data, node, NULL)) 326 return 0; 327 matched = 1; 328 } 329 } 330 if (!matched && last->anyPolicy) 331 { 332 if (!level_add_node(curr, data, last->anyPolicy, NULL)) 333 return 0; 334 } 335 return 1; 336 } 337 338/* This corresponds to RFC3280 6.1.3(d)(1): 339 * link any data from CertificatePolicies onto matching parent 340 * or anyPolicy if no match. 341 */ 342 343static int tree_link_nodes(X509_POLICY_LEVEL *curr, 344 const X509_POLICY_CACHE *cache) 345 { 346 size_t i; 347 X509_POLICY_DATA *data; 348 349 for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) 350 { 351 data = sk_X509_POLICY_DATA_value(cache->data, i); 352 /* If a node is mapped any it doesn't have a corresponding 353 * CertificatePolicies entry. 354 * However such an identical node would be created 355 * if anyPolicy matching is enabled because there would be 356 * no match with the parent valid_policy_set. So we create 357 * link because then it will have the mapping flags 358 * right and we can prune it later. 359 */ 360#if 0 361 if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) 362 && !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) 363 continue; 364#endif 365 /* Look for matching nodes in previous level */ 366 if (!tree_link_matching_nodes(curr, data)) 367 return 0; 368 } 369 return 1; 370 } 371 372/* This corresponds to RFC3280 6.1.3(d)(2): 373 * Create new data for any unmatched policies in the parent and link 374 * to anyPolicy. 375 */ 376 377static int tree_add_unmatched(X509_POLICY_LEVEL *curr, 378 const X509_POLICY_CACHE *cache, 379 const ASN1_OBJECT *id, 380 X509_POLICY_NODE *node, 381 X509_POLICY_TREE *tree) 382 { 383 X509_POLICY_DATA *data; 384 if (id == NULL) 385 id = node->data->valid_policy; 386 /* Create a new node with qualifiers from anyPolicy and 387 * id from unmatched node. 388 */ 389 data = policy_data_new(NULL, id, node_critical(node)); 390 391 if (data == NULL) 392 return 0; 393 /* Curr may not have anyPolicy */ 394 data->qualifier_set = cache->anyPolicy->qualifier_set; 395 data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; 396 if (!level_add_node(curr, data, node, tree)) 397 { 398 policy_data_free(data); 399 return 0; 400 } 401 402 return 1; 403 } 404 405static int tree_link_unmatched(X509_POLICY_LEVEL *curr, 406 const X509_POLICY_CACHE *cache, 407 X509_POLICY_NODE *node, 408 X509_POLICY_TREE *tree) 409 { 410 const X509_POLICY_LEVEL *last = curr - 1; 411 size_t i; 412 413 if ( (last->flags & X509_V_FLAG_INHIBIT_MAP) 414 || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) 415 { 416 /* If no policy mapping: matched if one child present */ 417 if (node->nchild) 418 return 1; 419 if (!tree_add_unmatched(curr, cache, NULL, node, tree)) 420 return 0; 421 /* Add it */ 422 } 423 else 424 { 425 /* If mapping: matched if one child per expected policy set */ 426 STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set; 427 if (node->nchild == sk_ASN1_OBJECT_num(expset)) 428 return 1; 429 /* Locate unmatched nodes */ 430 for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) 431 { 432 ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i); 433 if (level_find_node(curr, node, oid)) 434 continue; 435 if (!tree_add_unmatched(curr, cache, oid, node, tree)) 436 return 0; 437 } 438 439 } 440 441 return 1; 442 443 } 444 445static int tree_link_any(X509_POLICY_LEVEL *curr, 446 const X509_POLICY_CACHE *cache, 447 X509_POLICY_TREE *tree) 448 { 449 size_t i; 450 /*X509_POLICY_DATA *data;*/ 451 X509_POLICY_NODE *node; 452 X509_POLICY_LEVEL *last = curr - 1; 453 454 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) 455 { 456 node = sk_X509_POLICY_NODE_value(last->nodes, i); 457 458 if (!tree_link_unmatched(curr, cache, node, tree)) 459 return 0; 460 461#if 0 462 463 /* Skip any node with any children: we only want unmathced 464 * nodes. 465 * 466 * Note: need something better for policy mapping 467 * because each node may have multiple children 468 */ 469 if (node->nchild) 470 continue; 471 472 /* Create a new node with qualifiers from anyPolicy and 473 * id from unmatched node. 474 */ 475 data = policy_data_new(NULL, node->data->valid_policy, 476 node_critical(node)); 477 478 if (data == NULL) 479 return 0; 480 /* Curr may not have anyPolicy */ 481 data->qualifier_set = cache->anyPolicy->qualifier_set; 482 data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; 483 if (!level_add_node(curr, data, node, tree)) 484 { 485 policy_data_free(data); 486 return 0; 487 } 488 489#endif 490 491 } 492 /* Finally add link to anyPolicy */ 493 if (last->anyPolicy) 494 { 495 if (!level_add_node(curr, cache->anyPolicy, 496 last->anyPolicy, NULL)) 497 return 0; 498 } 499 return 1; 500 } 501 502/* Prune the tree: delete any child mapped child data on the current level 503 * then proceed up the tree deleting any data with no children. If we ever 504 * have no data on a level we can halt because the tree will be empty. 505 */ 506 507static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) 508 { 509 STACK_OF(X509_POLICY_NODE) *nodes; 510 X509_POLICY_NODE *node; 511 int i; 512 nodes = curr->nodes; 513 if (curr->flags & X509_V_FLAG_INHIBIT_MAP) 514 { 515 for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) 516 { 517 node = sk_X509_POLICY_NODE_value(nodes, i); 518 /* Delete any mapped data: see RFC3280 XXXX */ 519 if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) 520 { 521 node->parent->nchild--; 522 OPENSSL_free(node); 523 (void)sk_X509_POLICY_NODE_delete(nodes,i); 524 } 525 } 526 } 527 528 for(;;) { 529 --curr; 530 nodes = curr->nodes; 531 for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) 532 { 533 node = sk_X509_POLICY_NODE_value(nodes, i); 534 if (node->nchild == 0) 535 { 536 node->parent->nchild--; 537 OPENSSL_free(node); 538 (void)sk_X509_POLICY_NODE_delete(nodes, i); 539 } 540 } 541 if (curr->anyPolicy && !curr->anyPolicy->nchild) 542 { 543 if (curr->anyPolicy->parent) 544 curr->anyPolicy->parent->nchild--; 545 OPENSSL_free(curr->anyPolicy); 546 curr->anyPolicy = NULL; 547 } 548 if (curr == tree->levels) 549 { 550 /* If we zapped anyPolicy at top then tree is empty */ 551 if (!curr->anyPolicy) 552 return 2; 553 return 1; 554 } 555 } 556 557 return 1; 558 559 } 560 561static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, 562 X509_POLICY_NODE *pcy) 563 { 564 if (!*pnodes) 565 { 566 *pnodes = policy_node_cmp_new(); 567 if (!*pnodes) 568 return 0; 569 } 570 else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy)) 571 return 1; 572 573 if (!sk_X509_POLICY_NODE_push(*pnodes, pcy)) 574 return 0; 575 576 return 1; 577 578 } 579 580/* Calculate the authority set based on policy tree. 581 * The 'pnodes' parameter is used as a store for the set of policy nodes 582 * used to calculate the user set. If the authority set is not anyPolicy 583 * then pnodes will just point to the authority set. If however the authority 584 * set is anyPolicy then the set of valid policies (other than anyPolicy) 585 * is store in pnodes. The return value of '2' is used in this case to indicate 586 * that pnodes should be freed. 587 */ 588 589static int tree_calculate_authority_set(X509_POLICY_TREE *tree, 590 STACK_OF(X509_POLICY_NODE) **pnodes) 591 { 592 X509_POLICY_LEVEL *curr; 593 X509_POLICY_NODE *node, *anyptr; 594 STACK_OF(X509_POLICY_NODE) **addnodes; 595 int i; 596 size_t j; 597 curr = tree->levels + tree->nlevel - 1; 598 599 /* If last level contains anyPolicy set is anyPolicy */ 600 if (curr->anyPolicy) 601 { 602 if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) 603 return 0; 604 addnodes = pnodes; 605 } 606 else 607 /* Add policies to authority set */ 608 addnodes = &tree->auth_policies; 609 610 curr = tree->levels; 611 for (i = 1; i < tree->nlevel; i++) 612 { 613 /* If no anyPolicy node on this this level it can't 614 * appear on lower levels so end search. 615 */ 616 if (!(anyptr = curr->anyPolicy)) 617 break; 618 curr++; 619 for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) 620 { 621 node = sk_X509_POLICY_NODE_value(curr->nodes, j); 622 if ((node->parent == anyptr) 623 && !tree_add_auth_node(addnodes, node)) 624 return 0; 625 } 626 } 627 628 if (addnodes == pnodes) 629 return 2; 630 631 *pnodes = tree->auth_policies; 632 633 return 1; 634 } 635 636static int tree_calculate_user_set(X509_POLICY_TREE *tree, 637 STACK_OF(ASN1_OBJECT) *policy_oids, 638 STACK_OF(X509_POLICY_NODE) *auth_nodes) 639 { 640 size_t i; 641 X509_POLICY_NODE *node; 642 ASN1_OBJECT *oid; 643 644 X509_POLICY_NODE *anyPolicy; 645 X509_POLICY_DATA *extra; 646 647 /* Check if anyPolicy present in authority constrained policy set: 648 * this will happen if it is a leaf node. 649 */ 650 651 if (sk_ASN1_OBJECT_num(policy_oids) <= 0) 652 return 1; 653 654 anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy; 655 656 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) 657 { 658 oid = sk_ASN1_OBJECT_value(policy_oids, i); 659 if (OBJ_obj2nid(oid) == NID_any_policy) 660 { 661 tree->flags |= POLICY_FLAG_ANY_POLICY; 662 return 1; 663 } 664 } 665 666 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) 667 { 668 oid = sk_ASN1_OBJECT_value(policy_oids, i); 669 node = tree_find_sk(auth_nodes, oid); 670 if (!node) 671 { 672 if (!anyPolicy) 673 continue; 674 /* Create a new node with policy ID from user set 675 * and qualifiers from anyPolicy. 676 */ 677 extra = policy_data_new(NULL, oid, 678 node_critical(anyPolicy)); 679 if (!extra) 680 return 0; 681 extra->qualifier_set = anyPolicy->data->qualifier_set; 682 extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS 683 | POLICY_DATA_FLAG_EXTRA_NODE; 684 node = level_add_node(NULL, extra, anyPolicy->parent, 685 tree); 686 } 687 if (!tree->user_policies) 688 { 689 tree->user_policies = sk_X509_POLICY_NODE_new_null(); 690 if (!tree->user_policies) 691 return 1; 692 } 693 if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) 694 return 0; 695 } 696 return 1; 697 698 } 699 700static int tree_evaluate(X509_POLICY_TREE *tree) 701 { 702 int ret, i; 703 X509_POLICY_LEVEL *curr = tree->levels + 1; 704 const X509_POLICY_CACHE *cache; 705 706 for(i = 1; i < tree->nlevel; i++, curr++) 707 { 708 cache = policy_cache_set(curr->cert); 709 if (!tree_link_nodes(curr, cache)) 710 return 0; 711 712 if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) 713 && !tree_link_any(curr, cache, tree)) 714 return 0; 715 tree_print("before tree_prune()", tree, curr); 716 ret = tree_prune(tree, curr); 717 if (ret != 1) 718 return ret; 719 } 720 721 return 1; 722 723 } 724 725static void exnode_free(X509_POLICY_NODE *node) 726 { 727 if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE)) 728 OPENSSL_free(node); 729 } 730 731 732void X509_policy_tree_free(X509_POLICY_TREE *tree) 733 { 734 X509_POLICY_LEVEL *curr; 735 int i; 736 737 if (!tree) 738 return; 739 740 sk_X509_POLICY_NODE_free(tree->auth_policies); 741 sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free); 742 743 for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) 744 { 745 if (curr->cert) 746 X509_free(curr->cert); 747 if (curr->nodes) 748 sk_X509_POLICY_NODE_pop_free(curr->nodes, 749 policy_node_free); 750 if (curr->anyPolicy) 751 policy_node_free(curr->anyPolicy); 752 } 753 754 if (tree->extra_data) 755 sk_X509_POLICY_DATA_pop_free(tree->extra_data, 756 policy_data_free); 757 758 OPENSSL_free(tree->levels); 759 OPENSSL_free(tree); 760 761 } 762 763/* Application policy checking function. 764 * Return codes: 765 * 0 Internal Error. 766 * 1 Successful. 767 * -1 One or more certificates contain invalid or inconsistent extensions 768 * -2 User constrained policy set empty and requireExplicit true. 769 */ 770 771int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, 772 STACK_OF(X509) *certs, 773 STACK_OF(ASN1_OBJECT) *policy_oids, 774 unsigned int flags) 775 { 776 int ret; 777 X509_POLICY_TREE *tree = NULL; 778 STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL; 779 *ptree = NULL; 780 781 *pexplicit_policy = 0; 782 ret = tree_init(&tree, certs, flags); 783 784 switch (ret) 785 { 786 787 /* Tree empty requireExplicit False: OK */ 788 case 2: 789 return 1; 790 791 /* Some internal error */ 792 case -1: 793 return -1; 794 795 /* Some internal error */ 796 case 0: 797 return 0; 798 799 /* Tree empty requireExplicit True: Error */ 800 801 case 6: 802 *pexplicit_policy = 1; 803 return -2; 804 805 /* Tree OK requireExplicit True: OK and continue */ 806 case 5: 807 *pexplicit_policy = 1; 808 break; 809 810 /* Tree OK: continue */ 811 812 case 1: 813 if (!tree) 814 /* 815 * tree_init() returns success and a null tree 816 * if it's just looking at a trust anchor. 817 * I'm not sure that returning success here is 818 * correct, but I'm sure that reporting this 819 * as an internal error which our caller 820 * interprets as a malloc failure is wrong. 821 */ 822 return 1; 823 break; 824 } 825 826 if (!tree) goto error; 827 ret = tree_evaluate(tree); 828 829 tree_print("tree_evaluate()", tree, NULL); 830 831 if (ret <= 0) 832 goto error; 833 834 /* Return value 2 means tree empty */ 835 if (ret == 2) 836 { 837 X509_policy_tree_free(tree); 838 if (*pexplicit_policy) 839 return -2; 840 else 841 return 1; 842 } 843 844 /* Tree is not empty: continue */ 845 846 ret = tree_calculate_authority_set(tree, &auth_nodes); 847 848 if (!ret) 849 goto error; 850 851 if (!tree_calculate_user_set(tree, policy_oids, auth_nodes)) 852 goto error; 853 854 if (ret == 2) 855 sk_X509_POLICY_NODE_free(auth_nodes); 856 857 if (tree) 858 *ptree = tree; 859 860 if (*pexplicit_policy) 861 { 862 nodes = X509_policy_tree_get0_user_policies(tree); 863 if (sk_X509_POLICY_NODE_num(nodes) <= 0) 864 return -2; 865 } 866 867 return 1; 868 869 error: 870 871 X509_policy_tree_free(tree); 872 873 return 0; 874 875 } 876 877