LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/x509v3 - pcy_tree.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 0 241 0.0 %
Date: 2015-10-10 Functions: 0 14 0.0 %

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

Generated by: LCOV version 1.10