Support for policy mappings extension.
authorDr. Stephen Henson <steve@openssl.org>
Tue, 12 Aug 2008 10:32:56 +0000 (10:32 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 12 Aug 2008 10:32:56 +0000 (10:32 +0000)
Delete X509_POLICY_REF code.

Fix handling of invalid policy extensions to return the correct error.

Add command line option to inhibit policy mappings.

CHANGES
apps/apps.c
crypto/x509/x509_vfy.c
crypto/x509v3/pcy_cache.c
crypto/x509v3/pcy_data.c
crypto/x509v3/pcy_int.h
crypto/x509v3/pcy_map.c
crypto/x509v3/pcy_node.c
crypto/x509v3/pcy_tree.c
crypto/x509v3/v3_cpols.c
crypto/x509v3/v3_purp.c

diff --git a/CHANGES b/CHANGES
index 0d83a86..cede856 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 0.9.8i and 0.9.9  [xx XXX xxxx]
 
+  *) Add support for policy mappings extension.
+
+     This work was sponsored by Google.
+     [Steve Henson]
+
   *) Fixes to pathlength constraint, self issued certificate handling,
      policy processing to align with RFC3280 and PKITS tests.
 
index 43eae05..1ef1b14 100644 (file)
@@ -2235,6 +2235,8 @@ int args_verify(char ***pargs, int *pargc,
                flags |= X509_V_FLAG_EXPLICIT_POLICY;
        else if (!strcmp(arg, "-inhibit_any"))
                flags |= X509_V_FLAG_INHIBIT_ANY;
+       else if (!strcmp(arg, "-inhibit_map"))
+               flags |= X509_V_FLAG_INHIBIT_MAP;
        else if (!strcmp(arg, "-x509_strict"))
                flags |= X509_V_FLAG_X509_STRICT;
        else if (!strcmp(arg, "-policy_print"))
index fe47dcb..05dcd8b 100644 (file)
@@ -1122,7 +1122,8 @@ static int check_policy(X509_STORE_CTX *ctx)
                                continue;
                        ctx->current_cert = x;
                        ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
-                       ret = ctx->verify_cb(0, ctx);
+                       if(!ctx->verify_cb(0, ctx))
+                               return 0;
                        }
                return 1;
                }
index c18beb8..78645c4 100644 (file)
@@ -139,7 +139,6 @@ static int policy_cache_new(X509 *x)
                return 0;
        cache->anyPolicy = NULL;
        cache->data = NULL;
-       cache->maps = NULL;
        cache->any_skip = -1;
        cache->explicit_skip = -1;
        cache->map_skip = -1;
index 4711b1e..3d59f4d 100644 (file)
@@ -82,17 +82,21 @@ void policy_data_free(X509_POLICY_DATA *data)
  * another source.
  */
 
-X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, ASN1_OBJECT *id, int crit)
+X509_POLICY_DATA *policy_data_new(POLICYINFO *policy,
+                                       const ASN1_OBJECT *cid, int crit)
        {
        X509_POLICY_DATA *ret;
-       if (!policy && !id)
+       ASN1_OBJECT *id;
+       if (!policy && !cid)
                return NULL;
-       if (id)
+       if (cid)
                {
-               id = OBJ_dup(id);
+               id = OBJ_dup(cid);
                if (!id)
                        return NULL;
                }
+       else
+               id = NULL;
        ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA));
        if (!ret)
                return NULL;
index 5d54549..e947f27 100644 (file)
 
 
 typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
-typedef struct X509_POLICY_REF_st X509_POLICY_REF;
 
 DECLARE_STACK_OF(X509_POLICY_DATA)
-DECLARE_STACK_OF(X509_POLICY_REF)
 
 /* Internal structures */
 
@@ -110,16 +108,6 @@ struct X509_POLICY_DATA_st
 
 #define POLICY_DATA_FLAG_CRITICAL              0x10
 
-/* This structure is an entry from a table of mapped policies which
- * cross reference the policy it refers to.
- */
-
-struct X509_POLICY_REF_st
-       {
-       ASN1_OBJECT *subjectDomainPolicy;
-       const X509_POLICY_DATA *data;
-       };
-
 /* This structure is cached with a certificate */
 
 struct X509_POLICY_CACHE_st {
@@ -127,8 +115,6 @@ struct X509_POLICY_CACHE_st {
        X509_POLICY_DATA *anyPolicy;
        /* other policy data */
        STACK_OF(X509_POLICY_DATA) *data;
-       /* If policyMappings extension present a table of mapped policies */
-       STACK_OF(X509_POLICY_REF) *maps;
        /* If InhibitAnyPolicy present this is its value or -1 if absent. */
        long any_skip;
        /* If policyConstraints and requireExplicitPolicy present this is its
@@ -193,7 +179,7 @@ struct X509_POLICY_TREE_st
 
 /* Internal functions */
 
-X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, ASN1_OBJECT *id,
+X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
                                                                int crit);
 void policy_data_free(X509_POLICY_DATA *data);
 
@@ -209,15 +195,18 @@ void policy_cache_init(void);
 void policy_cache_free(X509_POLICY_CACHE *cache);
 
 X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
+                                       const X509_POLICY_NODE *parent, 
                                        const ASN1_OBJECT *id);
 
 X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
                                                const ASN1_OBJECT *id);
 
 X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
-                       X509_POLICY_DATA *data,
+                       const X509_POLICY_DATA *data,
                        X509_POLICY_NODE *parent,
                        X509_POLICY_TREE *tree);
 void policy_node_free(X509_POLICY_NODE *node);
+int policy_node_match(const X509_POLICY_LEVEL *lvl,
+                     const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
 
 const X509_POLICY_CACHE *policy_cache_set(X509 *x);
index 35221e8..11dbe0a 100644 (file)
 
 #include "pcy_int.h"
 
-static int ref_cmp(const X509_POLICY_REF * const *a,
-                       const X509_POLICY_REF * const *b)
-       {
-       return OBJ_cmp((*a)->subjectDomainPolicy, (*b)->subjectDomainPolicy);
-       }
-
-static void policy_map_free(X509_POLICY_REF *map)
-       {
-       if (map->subjectDomainPolicy)
-               ASN1_OBJECT_free(map->subjectDomainPolicy);
-       OPENSSL_free(map);
-       }
-
-static X509_POLICY_REF *policy_map_find(X509_POLICY_CACHE *cache, ASN1_OBJECT *id)
-       {
-       X509_POLICY_REF tmp;
-       int idx;
-       tmp.subjectDomainPolicy = id;
-
-       idx = sk_X509_POLICY_REF_find(cache->maps, &tmp);
-       if (idx == -1)
-               return NULL;
-       return sk_X509_POLICY_REF_value(cache->maps, idx);
-       }
-
 /* Set policy mapping entries in cache.
  * Note: this modifies the passed POLICY_MAPPINGS structure
  */
@@ -94,7 +69,6 @@ static X509_POLICY_REF *policy_map_find(X509_POLICY_CACHE *cache, ASN1_OBJECT *i
 int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
        {
        POLICY_MAPPING *map;
-       X509_POLICY_REF *ref = NULL;
        X509_POLICY_DATA *data;
        X509_POLICY_CACHE *cache = x->policy_cache;
        int i;
@@ -104,7 +78,6 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
                ret = -1;
                goto bad_mapping;
                }
-       cache->maps = sk_X509_POLICY_REF_new(ref_cmp);
        for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++)
                {
                map = sk_POLICY_MAPPING_value(maps, i);
@@ -116,13 +89,6 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
                        goto bad_mapping;
                        }
 
-               /* If we've already mapped from this OID bad mapping */
-               if (policy_map_find(cache, map->subjectDomainPolicy) != NULL)
-                       {
-                       ret = -1;
-                       goto bad_mapping;
-                       }
-
                /* Attempt to find matching policy data */
                data = policy_cache_find_data(cache, map->issuerDomainPolicy);
                /* If we don't have anyPolicy can't map */
@@ -138,7 +104,7 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
                        if (!data)
                                goto bad_mapping;
                        data->qualifier_set = cache->anyPolicy->qualifier_set;
-                       map->issuerDomainPolicy = NULL;
+                       /*map->issuerDomainPolicy = NULL;*/
                        data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
                        data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
                        if (!sk_X509_POLICY_DATA_push(cache->data, data))
@@ -149,23 +115,10 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
                        }
                else
                        data->flags |= POLICY_DATA_FLAG_MAPPED;
-
                if (!sk_ASN1_OBJECT_push(data->expected_policy_set, 
                                                map->subjectDomainPolicy))
                        goto bad_mapping;
-               
-               ref = OPENSSL_malloc(sizeof(X509_POLICY_REF));
-               if (!ref)
-                       goto bad_mapping;
-
-               ref->subjectDomainPolicy = map->subjectDomainPolicy;
                map->subjectDomainPolicy = NULL;
-               ref->data = data;
-
-               if (!sk_X509_POLICY_REF_push(cache->maps, ref))
-                       goto bad_mapping;
-
-               ref = NULL;
 
                }
 
@@ -173,13 +126,6 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
        bad_mapping:
        if (ret == -1)
                x->ex_flags |= EXFLAG_INVALID_POLICY;
-       if (ref)
-               policy_map_free(ref);
-       if (ret <= 0)
-               {
-               sk_X509_POLICY_REF_pop_free(cache->maps, policy_map_free);
-               cache->maps = NULL;
-               }
        sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
        return ret;
 
index dcc1554..8e19986 100644 (file)
@@ -92,13 +92,25 @@ X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
        }
 
 X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
+                                       const X509_POLICY_NODE *parent, 
                                        const ASN1_OBJECT *id)
        {
-       return tree_find_sk(level->nodes, id);
+       X509_POLICY_NODE *node;
+       int i;
+       for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++)
+               {
+               node = sk_X509_POLICY_NODE_value(level->nodes, i);
+               if (node->parent == parent)
+                       {
+                       if (!OBJ_cmp(node->data->valid_policy, id))
+                               return node;
+                       }
+               }
+       return NULL;
        }
 
 X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
-                       X509_POLICY_DATA *data,
+                       const X509_POLICY_DATA *data,
                        X509_POLICY_NODE *parent,
                        X509_POLICY_TREE *tree)
        {
@@ -155,4 +167,31 @@ void policy_node_free(X509_POLICY_NODE *node)
        OPENSSL_free(node);
        }
 
+/* See if a policy node matches a policy OID. If mapping enabled look through
+ * expected policy set otherwise just valid policy.
+ */
+
+int policy_node_match(const X509_POLICY_LEVEL *lvl,
+                     const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
+       {
+       int i;
+       ASN1_OBJECT *policy_oid;
+       const X509_POLICY_DATA *x = node->data;
+
+       if (        (lvl->flags & X509_V_FLAG_INHIBIT_MAP)
+               || !(x->flags & POLICY_DATA_FLAG_MAP_MASK))
+               {
+               if (!OBJ_cmp(x->valid_policy, oid))
+                       return 1;
+               return 0;
+               }
+
+       for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++)
+               {
+               policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
+               if (!OBJ_cmp(policy_oid, oid))
+                       return 1;
+               }
+       return 0;
 
+       }
index b1ce77b..e48d6ea 100644 (file)
 
 #include "pcy_int.h"
 
+/* Enable this to print out the complete policy tree at various point during
+ * evaluation.
+ */
+
+/*#define OPENSSL_POLICY_DEBUG*/
+
+#ifdef OPENSSL_POLICY_DEBUG
+
+static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
+                               X509_POLICY_NODE *node, int indent)
+       {
+       if (        (lev->flags & X509_V_FLAG_INHIBIT_MAP)
+               || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
+               BIO_puts(err, "  Not Mapped\n");
+       else
+               {
+               int i;
+               STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
+               ASN1_OBJECT *oid;
+               BIO_puts(err, "  Expected: ");
+               for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++)
+                       {
+                       oid = sk_ASN1_OBJECT_value(pset, i);
+                       if (i)
+                               BIO_puts(err, ", ");
+                       i2a_ASN1_OBJECT(err, oid);
+                       }
+               BIO_puts(err, "\n");
+               }
+       }
+
+static void tree_print(char *str, X509_POLICY_TREE *tree,
+                       X509_POLICY_LEVEL *curr)
+       {
+       X509_POLICY_LEVEL *plev;
+       X509_POLICY_NODE *node;
+       int i;
+       BIO *err;
+       err = BIO_new_fp(stderr, BIO_NOCLOSE);
+       if (!curr)
+               curr = tree->levels + tree->nlevel;
+       else
+               curr++;
+       BIO_printf(err, "Level print after %s\n", str);
+       BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
+       for (plev = tree->levels; plev != curr; plev++)
+               {
+               BIO_printf(err, "Level %ld, flags = %x\n",
+                               plev - tree->levels, plev->flags);
+               for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++)
+                       {
+                       node = sk_X509_POLICY_NODE_value(plev->nodes, i);
+                       X509_POLICY_NODE_print(err, node, 2);
+                       expected_print(err, plev, node, 2);
+                       BIO_printf(err, "  Flags: %x\n", node->data->flags);
+                       }
+               if (plev->anyPolicy)
+                       X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
+               }
+
+       BIO_free(err);
+
+       }
+#else
+
+#define tree_print(a,b,c) /* */
+
+#endif
+
 /* Initialize policy tree. Return values:
  *  0 Some internal error occured.
  * -1 Inconsistent or invalid extensions in certificates.
@@ -87,8 +156,10 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
        *ptree = NULL;
        n = sk_X509_num(certs);
 
+#if 0
        /* Disable policy mapping for now... */
        flags |= X509_V_FLAG_INHIBIT_MAP;
+#endif
 
        if (flags & X509_V_FLAG_EXPLICIT_POLICY)
                explicit_policy = 0;
@@ -184,7 +255,6 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
                level++;
                x = sk_X509_value(certs, i);
                cache = policy_cache_set(x);
-
                CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
                level->cert = x;
 
@@ -213,13 +283,13 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
                        level->flags |= X509_V_FLAG_INHIBIT_MAP;
                else
                        {
-                       map_skip--;
+                       if (!(x->ex_flags & EXFLAG_SI))
+                               map_skip--;
                        if ((cache->map_skip >= 0)
                                && (cache->map_skip < map_skip))
                                map_skip = cache->map_skip;
                        }
 
-
                }
 
        *ptree = tree;
@@ -237,7 +307,32 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
 
        }
 
-/* This corresponds to RFC3280 XXXX XXXXX:
+static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
+                               const X509_POLICY_DATA *data)
+       {
+       X509_POLICY_LEVEL *last = curr - 1;
+       X509_POLICY_NODE *node;
+       int i, matched = 0;
+       /* Iterate through all in nodes linking matches */
+       for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
+               {
+               node = sk_X509_POLICY_NODE_value(last->nodes, i);
+               if (policy_node_match(last, node, data->valid_policy))
+                       {
+                       if (!level_add_node(curr, data, node, NULL))
+                               return 0;
+                       matched = 1;
+                       }
+               }
+       if (!matched && last->anyPolicy)
+               {
+               if (!level_add_node(curr, data, last->anyPolicy, NULL))
+                       return 0;
+               }
+       return 1;
+       }
+
+/* This corresponds to RFC3280 6.1.3(d)(1):
  * link any data from CertificatePolicies onto matching parent
  * or anyPolicy if no match.
  */
@@ -248,7 +343,6 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr,
        int i;
        X509_POLICY_LEVEL *last;
        X509_POLICY_DATA *data;
-       X509_POLICY_NODE *parent;
        last = curr - 1;
        for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
                {
@@ -261,40 +355,109 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr,
                 * link because then it will have the mapping flags
                 * right and we can prune it later.
                 */
+#if 0
                if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
                        && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
                        continue;
-               /* Look for matching node in parent */
-               parent = level_find_node(last, data->valid_policy);
-               /* If no match link to anyPolicy */
-               if (!parent)
-                       parent = last->anyPolicy;
-               if (parent && !level_add_node(curr, data, parent, NULL))
+#endif
+               /* Look for matching nodes in previous level */
+               if (!tree_link_matching_nodes(curr, data))
                                return 0;
                }
        return 1;
        }
 
-/* This corresponds to RFC3280 XXXX XXXXX:
+/* This corresponds to RFC3280 6.1.3(d)(2):
  * Create new data for any unmatched policies in the parent and link
  * to anyPolicy.
  */
 
+static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
+                       const X509_POLICY_CACHE *cache,
+                       const ASN1_OBJECT *id,
+                       X509_POLICY_NODE *node,
+                       X509_POLICY_TREE *tree)
+       {
+       X509_POLICY_DATA *data;
+       if (id == NULL)
+               id = node->data->valid_policy;
+       /* Create a new node with qualifiers from anyPolicy and
+        * id from unmatched node.
+        */
+       data = policy_data_new(NULL, id, node_critical(node));
+
+       if (data == NULL)
+               return 0;
+       /* Curr may not have anyPolicy */
+       data->qualifier_set = cache->anyPolicy->qualifier_set;
+       data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+       if (!level_add_node(curr, data, node, tree))
+               {
+               policy_data_free(data);
+               return 0;
+               }
+
+       return 1;
+       }
+
+static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
+                       const X509_POLICY_CACHE *cache,
+                       X509_POLICY_NODE *node,
+                       X509_POLICY_TREE *tree)
+       {
+       const X509_POLICY_LEVEL *last = curr - 1;
+       int i;
+
+       if (        (last->flags & X509_V_FLAG_INHIBIT_MAP)
+               || !(node->data->flags & POLICY_DATA_FLAG_MAPPED))
+               {
+               /* If no policy mapping: matched if one child present */
+               if (node->nchild)
+                       return 1;
+               if (!tree_add_unmatched(curr, cache, NULL, node, tree))
+                       return 0;
+               /* Add it */
+               }
+       else
+               {
+               /* If mapping: matched if one child per expected policy set */
+               STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
+               if (node->nchild == sk_ASN1_OBJECT_num(expset))
+                       return 1;
+               /* Locate unmatched nodes */
+               for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++)
+                       {
+                       ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
+                       if (level_find_node(curr, node, oid))
+                               continue;
+                       if (!tree_add_unmatched(curr, cache, oid, node, tree))
+                               return 0;
+                       }
+
+               }
+
+       return 1;
+
+       }
+
 static int tree_link_any(X509_POLICY_LEVEL *curr,
                        const X509_POLICY_CACHE *cache,
                        X509_POLICY_TREE *tree)
        {
        int i;
-       X509_POLICY_DATA *data;
+       /*X509_POLICY_DATA *data;*/
        X509_POLICY_NODE *node;
-       X509_POLICY_LEVEL *last;
-
-       last = curr - 1;
+       X509_POLICY_LEVEL *last = curr - 1;
 
        for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
                {
                node = sk_X509_POLICY_NODE_value(last->nodes, i);
 
+               if (!tree_link_unmatched(curr, cache, node, tree))
+                       return 0;
+
+#if 0
+
                /* Skip any node with any children: we only want unmathced
                 * nodes.
                 *
@@ -303,6 +466,7 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
                 */
                if (node->nchild)
                        continue;
+
                /* Create a new node with qualifiers from anyPolicy and
                 * id from unmatched node.
                 */
@@ -319,6 +483,9 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
                        policy_data_free(data);
                        return 0;
                        }
+
+#endif
+
                }
        /* Finally add link to anyPolicy */
        if (last->anyPolicy)
@@ -337,30 +504,36 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
 
 static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
        {
+       STACK_OF(X509_POLICY_NODE) *nodes;
        X509_POLICY_NODE *node;
        int i;
-       for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--)
+       nodes = curr->nodes;
+       if (curr->flags & X509_V_FLAG_INHIBIT_MAP)
                {
-               node = sk_X509_POLICY_NODE_value(curr->nodes, i);
-               /* Delete any mapped data: see RFC3280 XXXX */
-               if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
+               for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
                        {
-                       node->parent->nchild--;
-                       OPENSSL_free(node);
-                       (void)sk_X509_POLICY_NODE_delete(curr->nodes, i);
+                       node = sk_X509_POLICY_NODE_value(nodes, i);
+                       /* Delete any mapped data: see RFC3280 XXXX */
+                       if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
+                               {
+                               node->parent->nchild--;
+                               OPENSSL_free(node);
+                               (void)sk_X509_POLICY_NODE_delete(nodes,i);
+                               }
                        }
                }
 
        for(;;) {
                --curr;
-               for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--)
+               nodes = curr->nodes;
+               for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
                        {
-                       node = sk_X509_POLICY_NODE_value(curr->nodes, i);
+                       node = sk_X509_POLICY_NODE_value(nodes, i);
                        if (node->nchild == 0)
                                {
                                node->parent->nchild--;
                                OPENSSL_free(node);
-                               (void)sk_X509_POLICY_NODE_delete(curr->nodes, i);
+                               (void)sk_X509_POLICY_NODE_delete(nodes, i);
                                }
                        }
                if (curr->anyPolicy && !curr->anyPolicy->nchild)
@@ -536,6 +709,7 @@ static int tree_evaluate(X509_POLICY_TREE *tree)
                if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
                        && !tree_link_any(curr, cache, tree))
                        return 0;
+       tree_print("before tree_prune()", tree, curr);
                ret = tree_prune(tree, curr);
                if (ret != 1)
                        return ret;
@@ -604,7 +778,6 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
        *pexplicit_policy = 0;
        ret = tree_init(&tree, certs, flags);
 
-
        switch (ret)
                {
 
@@ -612,6 +785,10 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
                case 2:
                return 1;
 
+               /* Some internal error */
+               case -1:
+               return -1;
+
                /* Some internal error */
                case 0:
                return 0;
@@ -646,6 +823,8 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
        if (!tree) goto error;
        ret = tree_evaluate(tree);
 
+       tree_print("tree_evaluate()", tree, NULL);
+
        if (ret <= 0)
                goto error;
 
index a40f490..441ccea 100644 (file)
@@ -446,4 +446,4 @@ void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
        else
                BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
        }
-       
+
index 7bb6658..bdf7222 100644 (file)
@@ -296,6 +296,7 @@ int X509_supported_extension(X509_EXTENSION *ex)
                NID_policy_constraints, /* 401 */
                NID_proxyCertInfo,      /* 663 */
                NID_name_constraints,   /* 666 */
+               NID_policy_mappings,    /* 747 */
                NID_inhibit_any_policy  /* 748 */
        };