/*
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
 * 2004.
 */
/* ====================================================================
 * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    licensing@OpenSSL.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */

#include <string.h>

#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/stack.h>
#include <openssl/thread.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>

#include "../internal.h"
#include "../x509/internal.h"
#include "internal.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 occurred.
// -1 Inconsistent or invalid extensions in certificates.
//  1 Tree initialized OK.
//  2 Policy tree is empty.
//  5 Tree OK and requireExplicitPolicy true.
//  6 Tree empty and requireExplicitPolicy true.

static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
                     unsigned int flags) {
  X509_POLICY_TREE *tree;
  X509_POLICY_LEVEL *level;
  const X509_POLICY_CACHE *cache;
  X509_POLICY_DATA *data = NULL;
  X509 *x;
  int ret = 1;
  int i, n;
  int explicit_policy;
  int any_skip;
  int map_skip;
  *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;
  } else {
    explicit_policy = n + 1;
  }

  if (flags & X509_V_FLAG_INHIBIT_ANY) {
    any_skip = 0;
  } else {
    any_skip = n + 1;
  }

  if (flags & X509_V_FLAG_INHIBIT_MAP) {
    map_skip = 0;
  } else {
    map_skip = n + 1;
  }

  // Can't do anything with just a trust anchor
  if (n == 1) {
    return 1;
  }
  // First setup policy cache in all certificates apart from the trust
  // anchor. Note any bad cache results on the way. Also can calculate
  // explicit_policy value at this point.
  for (i = n - 2; i >= 0; i--) {
    x = sk_X509_value(certs, i);
    X509_check_purpose(x, -1, -1);
    cache = policy_cache_set(x);
    // If cache NULL something bad happened: return immediately
    if (cache == NULL) {
      return 0;
    }
    // If inconsistent extensions keep a note of it but continue
    if (x->ex_flags & EXFLAG_INVALID_POLICY) {
      ret = -1;
    }
    // Otherwise if we have no data (hence no CertificatePolicies) and
    // haven't already set an inconsistent code note it.
    else if ((ret == 1) && !cache->data) {
      ret = 2;
    }
    if (explicit_policy > 0) {
      if (!(x->ex_flags & EXFLAG_SI)) {
        explicit_policy--;
      }
      if ((cache->explicit_skip != -1) &&
          (cache->explicit_skip < explicit_policy)) {
        explicit_policy = cache->explicit_skip;
      }
    }
  }

  if (ret != 1) {
    if (ret == 2 && !explicit_policy) {
      return 6;
    }
    return ret;
  }

  // If we get this far initialize the tree

  tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));

  if (!tree) {
    return 0;
  }

  tree->flags = 0;
  tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
  tree->nlevel = 0;
  tree->extra_data = NULL;
  tree->auth_policies = NULL;
  tree->user_policies = NULL;

  if (!tree->levels) {
    OPENSSL_free(tree);
    return 0;
  }

  OPENSSL_memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));

  tree->nlevel = n;

  level = tree->levels;

  // Root data: initialize to anyPolicy

  data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);

  if (!data || !level_add_node(level, data, NULL, tree)) {
    goto bad_tree;
  }

  for (i = n - 2; i >= 0; i--) {
    level++;
    x = sk_X509_value(certs, i);
    cache = policy_cache_set(x);
    X509_up_ref(x);
    level->cert = x;

    if (!cache->anyPolicy) {
      level->flags |= X509_V_FLAG_INHIBIT_ANY;
    }

    // Determine inhibit any and inhibit map flags
    if (any_skip == 0) {
      // Any matching allowed if certificate is self issued and not the
      // last in the chain.
      if (!(x->ex_flags & EXFLAG_SI) || (i == 0)) {
        level->flags |= X509_V_FLAG_INHIBIT_ANY;
      }
    } else {
      if (!(x->ex_flags & EXFLAG_SI)) {
        any_skip--;
      }
      if ((cache->any_skip >= 0) && (cache->any_skip < any_skip)) {
        any_skip = cache->any_skip;
      }
    }

    if (map_skip == 0) {
      level->flags |= X509_V_FLAG_INHIBIT_MAP;
    } else {
      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;

  if (explicit_policy) {
    return 1;
  } else {
    return 5;
  }

bad_tree:

  X509_policy_tree_free(tree);

  return 0;
}

static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
                                    X509_POLICY_DATA *data) {
  X509_POLICY_LEVEL *last = curr - 1;
  X509_POLICY_NODE *node;
  int matched = 0;
  size_t i;
  // 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 RFC 3280 6.1.3(d)(1): link any data from
// CertificatePolicies onto matching parent or anyPolicy if no match.

static int tree_link_nodes(X509_POLICY_LEVEL *curr,
                           const X509_POLICY_CACHE *cache) {
  size_t i;
  X509_POLICY_DATA *data;

  for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
    data = sk_X509_POLICY_DATA_value(cache->data, i);
    // If a node is mapped any it doesn't have a corresponding
    // CertificatePolicies entry. However such an identical node would
    // be created if anyPolicy matching is enabled because there would be
    // no match with the parent valid_policy_set. So we create 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;
#endif
    // Look for matching nodes in previous level
    if (!tree_link_matching_nodes(curr, data)) {
      return 0;
    }
  }
  return 1;
}

// This corresponds to RFC 3280 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;
  size_t 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 ((size_t)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) {
  size_t i;
  // X509_POLICY_DATA *data;
  X509_POLICY_NODE *node;
  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.
        // Note: need something better for policy mapping because each node
        // may have multiple children
        if (node->nchild)
            continue;

        // Create a new node with qualifiers from anyPolicy and id from
        // unmatched node.
        data = policy_data_new(NULL, node->data->valid_policy,
                               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;
        }
#endif
  }
  // Finally add link to anyPolicy
  if (last->anyPolicy) {
    if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL)) {
      return 0;
    }
  }
  return 1;
}

// Prune the tree: delete any child mapped child data on the current level
// then proceed up the tree deleting any data with no children. If we ever
// have no data on a level we can halt because the tree will be empty.

static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) {
  STACK_OF(X509_POLICY_NODE) *nodes;
  X509_POLICY_NODE *node;
  int i;
  nodes = curr->nodes;
  if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
    for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
      node = sk_X509_POLICY_NODE_value(nodes, i);
      // Delete any mapped data: see RFC 3280 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;
    nodes = curr->nodes;
    for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; 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(nodes, i);
      }
    }
    if (curr->anyPolicy && !curr->anyPolicy->nchild) {
      if (curr->anyPolicy->parent) {
        curr->anyPolicy->parent->nchild--;
      }
      OPENSSL_free(curr->anyPolicy);
      curr->anyPolicy = NULL;
    }
    if (curr == tree->levels) {
      // If we zapped anyPolicy at top then tree is empty
      if (!curr->anyPolicy) {
        return 2;
      }
      return 1;
    }
  }
}

static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
                              X509_POLICY_NODE *pcy) {
  if (!*pnodes) {
    *pnodes = policy_node_cmp_new();
    if (!*pnodes) {
      return 0;
    }
  } else {
    sk_X509_POLICY_NODE_sort(*pnodes);
    if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy)) {
      return 1;
    }
  }
  if (!sk_X509_POLICY_NODE_push(*pnodes, pcy)) {
    return 0;
  }

  return 1;
}

// Calculate the authority set based on policy tree. The 'pnodes' parameter
// is used as a store for the set of policy nodes used to calculate the user
// set. If the authority set is not anyPolicy then pnodes will just point to
// the authority set. If however the authority set is anyPolicy then the set
// of valid policies (other than anyPolicy) is store in pnodes. The return
// value of '2' is used in this case to indicate that pnodes should be freed.

static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
                                        STACK_OF(X509_POLICY_NODE) **pnodes) {
  X509_POLICY_LEVEL *curr;
  X509_POLICY_NODE *node, *anyptr;
  STACK_OF(X509_POLICY_NODE) **addnodes;
  int i;
  size_t j;
  curr = tree->levels + tree->nlevel - 1;

  // If last level contains anyPolicy set is anyPolicy
  if (curr->anyPolicy) {
    if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) {
      return 0;
    }
    addnodes = pnodes;
  } else {
    // Add policies to authority set
    addnodes = &tree->auth_policies;
  }

  curr = tree->levels;
  for (i = 1; i < tree->nlevel; i++) {
    // If no anyPolicy node on this this level it can't appear on lower
    // levels so end search.
    if (!(anyptr = curr->anyPolicy)) {
      break;
    }
    curr++;
    for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
      node = sk_X509_POLICY_NODE_value(curr->nodes, j);
      if ((node->parent == anyptr) && !tree_add_auth_node(addnodes, node)) {
        return 0;
      }
    }
  }

  if (addnodes == pnodes) {
    return 2;
  }

  *pnodes = tree->auth_policies;

  return 1;
}

static int tree_calculate_user_set(X509_POLICY_TREE *tree,
                                   STACK_OF(ASN1_OBJECT) *policy_oids,
                                   STACK_OF(X509_POLICY_NODE) *auth_nodes) {
  size_t i;
  X509_POLICY_NODE *node;
  ASN1_OBJECT *oid;

  X509_POLICY_NODE *anyPolicy;
  X509_POLICY_DATA *extra;

  // Check if anyPolicy present in authority constrained policy set: this
  // will happen if it is a leaf node.

  if (sk_ASN1_OBJECT_num(policy_oids) <= 0) {
    return 1;
  }

  anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;

  for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
    oid = sk_ASN1_OBJECT_value(policy_oids, i);
    if (OBJ_obj2nid(oid) == NID_any_policy) {
      tree->flags |= POLICY_FLAG_ANY_POLICY;
      return 1;
    }
  }

  for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
    oid = sk_ASN1_OBJECT_value(policy_oids, i);
    node = tree_find_sk(auth_nodes, oid);
    if (!node) {
      if (!anyPolicy) {
        continue;
      }
      // Create a new node with policy ID from user set and qualifiers
      // from anyPolicy.
      extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
      if (!extra) {
        return 0;
      }
      extra->qualifier_set = anyPolicy->data->qualifier_set;
      extra->flags =
          POLICY_DATA_FLAG_SHARED_QUALIFIERS | POLICY_DATA_FLAG_EXTRA_NODE;
      node = level_add_node(NULL, extra, anyPolicy->parent, tree);
    }
    if (!tree->user_policies) {
      tree->user_policies = sk_X509_POLICY_NODE_new_null();
      if (!tree->user_policies) {
        return 1;
      }
    }
    if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) {
      return 0;
    }
  }
  return 1;
}

static int tree_evaluate(X509_POLICY_TREE *tree) {
  int ret, i;
  X509_POLICY_LEVEL *curr = tree->levels + 1;
  const X509_POLICY_CACHE *cache;

  for (i = 1; i < tree->nlevel; i++, curr++) {
    cache = policy_cache_set(curr->cert);
    if (!tree_link_nodes(curr, cache)) {
      return 0;
    }

    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;
    }
  }

  return 1;
}

static void exnode_free(X509_POLICY_NODE *node) {
  if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE)) {
    OPENSSL_free(node);
  }
}

void X509_policy_tree_free(X509_POLICY_TREE *tree) {
  X509_POLICY_LEVEL *curr;
  int i;

  if (!tree) {
    return;
  }

  sk_X509_POLICY_NODE_free(tree->auth_policies);
  sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);

  for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
    if (curr->cert) {
      X509_free(curr->cert);
    }
    if (curr->nodes) {
      sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free);
    }
    if (curr->anyPolicy) {
      policy_node_free(curr->anyPolicy);
    }
  }

  if (tree->extra_data) {
    sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
  }

  OPENSSL_free(tree->levels);
  OPENSSL_free(tree);
}

//-
// Application policy checking function.
// Return codes:
//  0   Internal Error.
//  1   Successful.
// -1   One or more certificates contain invalid or inconsistent extensions
// -2   User constrained policy set empty and requireExplicit true.

int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
                      STACK_OF(X509) *certs, STACK_OF(ASN1_OBJECT) *policy_oids,
                      unsigned int flags) {
  int ret;
  int calc_ret;
  X509_POLICY_TREE *tree = NULL;
  STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
  *ptree = NULL;

  *pexplicit_policy = 0;
  ret = tree_init(&tree, certs, flags);

  switch (ret) {
      // Tree empty requireExplicit False: OK
    case 2:
      return 1;

      // Some internal error
    case -1:
      return -1;

      // Some internal error
    case 0:
      return 0;

      // Tree empty requireExplicit True: Error

    case 6:
      *pexplicit_policy = 1;
      return -2;

      // Tree OK requireExplicit True: OK and continue
    case 5:
      *pexplicit_policy = 1;
      break;

      // Tree OK: continue

    case 1:
      if (!tree) {
        // tree_init() returns success and a null tree
        // if it's just looking at a trust anchor.
        // I'm not sure that returning success here is
        // correct, but I'm sure that reporting this
        // as an internal error which our caller
        // interprets as a malloc failure is wrong.
        return 1;
      }
      break;
  }

  if (!tree) {
    goto error;
  }
  ret = tree_evaluate(tree);

  tree_print("tree_evaluate()", tree, NULL);

  if (ret <= 0) {
    goto error;
  }

  // Return value 2 means tree empty
  if (ret == 2) {
    X509_policy_tree_free(tree);
    if (*pexplicit_policy) {
      return -2;
    } else {
      return 1;
    }
  }

  // Tree is not empty: continue

  calc_ret = tree_calculate_authority_set(tree, &auth_nodes);

  if (!calc_ret) {
    goto error;
  }

  ret = tree_calculate_user_set(tree, policy_oids, auth_nodes);

  if (calc_ret == 2) {
    sk_X509_POLICY_NODE_free(auth_nodes);
  }

  if (!ret) {
    goto error;
  }


  if (tree) {
    *ptree = tree;
  }

  if (*pexplicit_policy) {
    nodes = X509_policy_tree_get0_user_policies(tree);
    if (sk_X509_POLICY_NODE_num(nodes) <= 0) {
      return -2;
    }
  }

  return 1;

error:

  X509_policy_tree_free(tree);

  return 0;
}
