LCOV - code coverage report
Current view: top level - x509v3 - pcy_tree.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 0 248 0.0 %
Date: 2014-08-02 Functions: 0 14 0.0 %
Branches: 0 229 0.0 %

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

Generated by: LCOV version 1.9