195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * project 2004.
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* ====================================================================
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the above copyright
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    the documentation and/or other materials provided with the
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    distribution.
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    software must display the following acknowledgment:
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software developed by the OpenSSL Project
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    endorse or promote products derived from this software without
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    prior written permission. For written permission, please contact
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    licensing@OpenSSL.org.
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5. Products derived from this software may not be called "OpenSSL"
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    nor may "OpenSSL" appear in their names without prior written
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    permission of the OpenSSL Project.
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6. Redistributions of any form whatsoever must retain the following
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    acknowledgment:
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software developed by the OpenSSL Project
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ====================================================================
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This product includes cryptographic software written by Eric Young
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Hudson (tjh@cryptsoft.com).
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h>
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/obj.h>
6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/stack.h>
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/thread.h>
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/x509.h>
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/x509v3.h>
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "pcy_int.h"
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Enable this to print out the complete policy tree at various point during
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * evaluation.
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/*#define OPENSSL_POLICY_DEBUG*/
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#ifdef OPENSSL_POLICY_DEBUG
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				X509_POLICY_NODE *node, int indent)
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (	    (lev->flags & X509_V_FLAG_INHIBIT_MAP)
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		|| !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		BIO_puts(err, "  Not Mapped\n");
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		int i;
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ASN1_OBJECT *oid;
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		BIO_puts(err, "  Expected: ");
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++)
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			oid = sk_ASN1_OBJECT_value(pset, i);
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (i)
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				BIO_puts(err, ", ");
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			i2a_ASN1_OBJECT(err, oid);
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		BIO_puts(err, "\n");
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void tree_print(char *str, X509_POLICY_TREE *tree,
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_POLICY_LEVEL *curr)
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_LEVEL *plev;
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_NODE *node;
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i;
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	BIO *err;
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	err = BIO_new_fp(stderr, BIO_NOCLOSE);
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!curr)
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		curr = tree->levels + tree->nlevel;
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		curr++;
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	BIO_printf(err, "Level print after %s\n", str);
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (plev = tree->levels; plev != curr; plev++)
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		BIO_printf(err, "Level %ld, flags = %x\n",
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				plev - tree->levels, plev->flags);
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++)
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			node = sk_X509_POLICY_NODE_value(plev->nodes, i);
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_POLICY_NODE_print(err, node, 2);
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			expected_print(err, plev, node, 2);
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			BIO_printf(err, "  Flags: %x\n", node->data->flags);
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (plev->anyPolicy)
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	BIO_free(err);
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#else
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define tree_print(a,b,c) /* */
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Initialize policy tree. Return values:
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *  0 Some internal error occured.
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * -1 Inconsistent or invalid extensions in certificates.
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *  1 Tree initialized OK.
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *  2 Policy tree is empty.
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *  5 Tree OK and requireExplicitPolicy true.
14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *  6 Tree empty and requireExplicitPolicy true.
14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			unsigned int flags)
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_TREE *tree;
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_LEVEL *level;
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const X509_POLICY_CACHE *cache;
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_DATA *data = NULL;
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509 *x;
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret = 1;
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i, n;
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int explicit_policy;
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int any_skip;
15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int map_skip;
15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ptree = NULL;
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	n = sk_X509_num(certs);
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if 0
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Disable policy mapping for now... */
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	flags |= X509_V_FLAG_INHIBIT_MAP;
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (flags & X509_V_FLAG_EXPLICIT_POLICY)
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		explicit_policy = 0;
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		explicit_policy = n + 1;
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (flags & X509_V_FLAG_INHIBIT_ANY)
17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		any_skip = 0;
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		any_skip = n + 1;
17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (flags & X509_V_FLAG_INHIBIT_MAP)
17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		map_skip = 0;
17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		map_skip = n + 1;
18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Can't do anything with just a trust anchor */
18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (n == 1)
18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* First setup policy cache in all certificates apart from the
18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * trust anchor. Note any bad cache results on the way. Also can
18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * calculate explicit_policy value at this point.
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = n - 2; i >= 0; i--)
19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		x = sk_X509_value(certs, i);
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		X509_check_purpose(x, -1, -1);
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cache = policy_cache_set(x);
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If cache NULL something bad happened: return immediately */
19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (cache == NULL)
19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If inconsistent extensions keep a note of it but continue */
19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (x->ex_flags & EXFLAG_INVALID_POLICY)
19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ret = -1;
20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Otherwise if we have no data (hence no CertificatePolicies)
20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * and haven't already set an inconsistent code note it.
20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else if ((ret == 1) && !cache->data)
20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ret = 2;
20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (explicit_policy > 0)
20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!(x->ex_flags & EXFLAG_SI))
20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				explicit_policy--;
20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ((cache->explicit_skip != -1)
21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				&& (cache->explicit_skip < explicit_policy))
21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				explicit_policy = cache->explicit_skip;
21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (ret != 1)
21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (ret == 2 && !explicit_policy)
21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 6;
21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return ret;
22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If we get this far initialize the tree */
22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!tree)
22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree->flags = 0;
23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree->nlevel = 0;
23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree->extra_data = NULL;
23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree->auth_policies = NULL;
23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree->user_policies = NULL;
23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!tree->levels)
23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_free(tree);
24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree->nlevel = n;
24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	level = tree->levels;
24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Root data: initialize to anyPolicy */
25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!data || !level_add_node(level, data, NULL, tree))
25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto bad_tree;
25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = n - 2; i >= 0; i--)
25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		level++;
25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		x = sk_X509_value(certs, i);
26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cache = policy_cache_set(x);
261150c617cfce408faf1274a60e5db194595cb4473David Benjamin		level->cert = X509_up_ref(x);
26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!cache->anyPolicy)
26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				level->flags |= X509_V_FLAG_INHIBIT_ANY;
26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Determine inhibit any and inhibit map flags */
26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (any_skip == 0)
26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Any matching allowed if certificate is self
27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * issued and not the last in the chain.
27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				level->flags |= X509_V_FLAG_INHIBIT_ANY;
27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!(x->ex_flags & EXFLAG_SI))
27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				any_skip--;
27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ((cache->any_skip >= 0)
28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				&& (cache->any_skip < any_skip))
28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				any_skip = cache->any_skip;
28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (map_skip == 0)
28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			level->flags |= X509_V_FLAG_INHIBIT_MAP;
28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!(x->ex_flags & EXFLAG_SI))
28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				map_skip--;
29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ((cache->map_skip >= 0)
29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				&& (cache->map_skip < map_skip))
29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				map_skip = cache->map_skip;
29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ptree = tree;
29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (explicit_policy)
30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 5;
30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	bad_tree:
30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_policy_tree_free(tree);
30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 0;
30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const X509_POLICY_DATA *data)
31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_LEVEL *last = curr - 1;
31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_NODE *node;
31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int matched = 0;
31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t i;
31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Iterate through all in nodes linking matches */
32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		node = sk_X509_POLICY_NODE_value(last->nodes, i);
32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (policy_node_match(last, node, data->valid_policy))
32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!level_add_node(curr, data, node, NULL))
32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			matched = 1;
32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!matched && last->anyPolicy)
33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!level_add_node(curr, data, last->anyPolicy, NULL))
33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* This corresponds to RFC3280 6.1.3(d)(1):
33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * link any data from CertificatePolicies onto matching parent
34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * or anyPolicy if no match.
34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_link_nodes(X509_POLICY_LEVEL *curr,
34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const X509_POLICY_CACHE *cache)
34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t i;
34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_DATA *data;
34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		data = sk_X509_POLICY_DATA_value(cache->data, i);
35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If a node is mapped any it doesn't have a corresponding
35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * CertificatePolicies entry.
35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * However such an identical node would be created
35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * if anyPolicy matching is enabled because there would be
35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * no match with the parent valid_policy_set. So we create
35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * link because then it will have the mapping flags
35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * right and we can prune it later.
35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if 0
36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			&& !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			continue;
36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Look for matching nodes in previous level */
36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!tree_link_matching_nodes(curr, data))
36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* This corresponds to RFC3280 6.1.3(d)(2):
37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Create new data for any unmatched policies in the parent and link
37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * to anyPolicy.
37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_add_unmatched(X509_POLICY_LEVEL *curr,
37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const X509_POLICY_CACHE *cache,
37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const ASN1_OBJECT *id,
38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_POLICY_NODE *node,
38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_POLICY_TREE *tree)
38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_DATA *data;
38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (id == NULL)
38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		id = node->data->valid_policy;
38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Create a new node with qualifiers from anyPolicy and
38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * id from unmatched node.
38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	data = policy_data_new(NULL, id, node_critical(node));
39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (data == NULL)
39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Curr may not have anyPolicy */
39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	data->qualifier_set = cache->anyPolicy->qualifier_set;
39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!level_add_node(curr, data, node, tree))
39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		policy_data_free(data);
39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
40395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
40495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_link_unmatched(X509_POLICY_LEVEL *curr,
40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const X509_POLICY_CACHE *cache,
40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_POLICY_NODE *node,
40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_POLICY_TREE *tree)
40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const X509_POLICY_LEVEL *last = curr - 1;
41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t i;
41295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (	    (last->flags & X509_V_FLAG_INHIBIT_MAP)
41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		|| !(node->data->flags & POLICY_DATA_FLAG_MAPPED))
41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If no policy mapping: matched if one child present */
41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (node->nchild)
41895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 1;
41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!tree_add_unmatched(curr, cache, NULL, node, tree))
42095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
42195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Add it */
42295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
42395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
42495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
42595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If mapping: matched if one child per expected policy set */
42695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
42795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (node->nchild == sk_ASN1_OBJECT_num(expset))
42895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 1;
42995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Locate unmatched nodes */
43095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++)
43195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
43295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
43395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (level_find_node(curr, node, oid))
43495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				continue;
43595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!tree_add_unmatched(curr, cache, oid, node, tree))
43695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
43795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
43895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
44095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
44195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
44295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
44395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
44495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
44595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_link_any(X509_POLICY_LEVEL *curr,
44695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const X509_POLICY_CACHE *cache,
44795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_POLICY_TREE *tree)
44895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
44995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t i;
45095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/*X509_POLICY_DATA *data;*/
45195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_NODE *node;
45295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_LEVEL *last = curr - 1;
45395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
45495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
45595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
45695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		node = sk_X509_POLICY_NODE_value(last->nodes, i);
45795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
45895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!tree_link_unmatched(curr, cache, node, tree))
45995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
46095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
46195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if 0
46295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
46395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Skip any node with any children: we only want unmathced
46495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * nodes.
46595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 *
46695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * Note: need something better for policy mapping
46795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * because each node may have multiple children
46895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
46995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (node->nchild)
47095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			continue;
47195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
47295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Create a new node with qualifiers from anyPolicy and
47395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * id from unmatched node.
47495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
47595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		data = policy_data_new(NULL, node->data->valid_policy,
47695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						node_critical(node));
47795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
47895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (data == NULL)
47995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
48095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Curr may not have anyPolicy */
48195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		data->qualifier_set = cache->anyPolicy->qualifier_set;
48295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
48395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!level_add_node(curr, data, node, tree))
48495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
48595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			policy_data_free(data);
48695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
48795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
48895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
49095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
49195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
49295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Finally add link to anyPolicy */
49395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (last->anyPolicy)
49495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
49595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!level_add_node(curr, cache->anyPolicy,
49695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						last->anyPolicy, NULL))
49795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
49895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
49995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
50095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
50195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
50295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Prune the tree: delete any child mapped child data on the current level
50395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * then proceed up the tree deleting any data with no children. If we ever
50495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * have no data on a level we can halt because the tree will be empty.
50595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
50695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
50795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
50895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
50995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	STACK_OF(X509_POLICY_NODE) *nodes;
51095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_NODE *node;
51195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i;
51295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	nodes = curr->nodes;
51395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (curr->flags & X509_V_FLAG_INHIBIT_MAP)
51495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
51595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
51695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
51795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			node = sk_X509_POLICY_NODE_value(nodes, i);
51895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Delete any mapped data: see RFC3280 XXXX */
51995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
52095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
52195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				node->parent->nchild--;
52295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_free(node);
52395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				(void)sk_X509_POLICY_NODE_delete(nodes,i);
52495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
52595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
52695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
52795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for(;;)	{
52995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		--curr;
53095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		nodes = curr->nodes;
53195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
53295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
53395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			node = sk_X509_POLICY_NODE_value(nodes, i);
53495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (node->nchild == 0)
53595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
53695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				node->parent->nchild--;
53795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_free(node);
53895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				(void)sk_X509_POLICY_NODE_delete(nodes, i);
53995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
54095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
54195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (curr->anyPolicy && !curr->anyPolicy->nchild)
54295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
54395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (curr->anyPolicy->parent)
54495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				curr->anyPolicy->parent->nchild--;
54595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_free(curr->anyPolicy);
54695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			curr->anyPolicy = NULL;
54795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
54895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (curr == tree->levels)
54995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
55095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If we zapped anyPolicy at top then tree is empty */
55195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!curr->anyPolicy)
55295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					return 2;
55395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 1;
55495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
55595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
55695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
55795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
55895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
55995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
56095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
56295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						 X509_POLICY_NODE *pcy)
56395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
56495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!*pnodes)
56595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
56695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*pnodes = policy_node_cmp_new();
56795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*pnodes)
56895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
56995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
57095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
57195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
57295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
57395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
57495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
57595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
57695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
57795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
57895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
57995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Calculate the authority set based on policy tree.
58195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The 'pnodes' parameter is used as a store for the set of policy nodes
58295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * used to calculate the user set. If the authority set is not anyPolicy
58395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * then pnodes will just point to the authority set. If however the authority
58495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * set is anyPolicy then the set of valid policies (other than anyPolicy)
58595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * is store in pnodes. The return value of '2' is used in this case to indicate
58695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * that pnodes should be freed.
58795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
58895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_calculate_authority_set(X509_POLICY_TREE *tree,
59095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					STACK_OF(X509_POLICY_NODE) **pnodes)
59195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
59295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_LEVEL *curr;
59395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_NODE *node, *anyptr;
59495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	STACK_OF(X509_POLICY_NODE) **addnodes;
59595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i;
59695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t j;
59795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	curr = tree->levels + tree->nlevel - 1;
59895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
59995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If last level contains anyPolicy set is anyPolicy */
60095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (curr->anyPolicy)
60195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
60295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
60395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
60495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		addnodes = pnodes;
60595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
60695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
60795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Add policies to authority set */
60895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		addnodes = &tree->auth_policies;
60995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
61095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	curr = tree->levels;
61195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = 1; i < tree->nlevel; i++)
61295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
61395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If no anyPolicy node on this this level it can't
61495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * appear on lower levels so end search.
61595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
61695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!(anyptr = curr->anyPolicy))
61795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			break;
61895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		curr++;
61995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++)
62095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
62195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			node = sk_X509_POLICY_NODE_value(curr->nodes, j);
62295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ((node->parent == anyptr)
62395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				&& !tree_add_auth_node(addnodes, node))
62495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					return 0;
62595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
62695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
62795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
62895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (addnodes == pnodes)
62995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 2;
63095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
63195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*pnodes = tree->auth_policies;
63295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
63395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
63495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
63595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
63695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_calculate_user_set(X509_POLICY_TREE *tree,
63795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				STACK_OF(ASN1_OBJECT) *policy_oids,
63895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				STACK_OF(X509_POLICY_NODE) *auth_nodes)
63995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
64095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t i;
64195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_NODE *node;
64295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_OBJECT *oid;
64395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
64495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_NODE *anyPolicy;
64595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_DATA *extra;
64695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
64795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Check if anyPolicy present in authority constrained policy set:
64895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * this will happen if it is a leaf node.
64995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
65095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
65195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
65295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
65395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
65495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
65595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
65695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
65795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
65895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		oid = sk_ASN1_OBJECT_value(policy_oids, i);
65995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (OBJ_obj2nid(oid) == NID_any_policy)
66095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
66195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			tree->flags |= POLICY_FLAG_ANY_POLICY;
66295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 1;
66395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
66495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
66595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
66695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
66795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
66895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		oid = sk_ASN1_OBJECT_value(policy_oids, i);
66995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		node = tree_find_sk(auth_nodes, oid);
67095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!node)
67195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
67295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!anyPolicy)
67395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				continue;
67495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Create a new node with policy ID from user set
67595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * and qualifiers from anyPolicy.
67695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
67795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			extra = policy_data_new(NULL, oid,
67895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						node_critical(anyPolicy));
67995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!extra)
68095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
68195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			extra->qualifier_set = anyPolicy->data->qualifier_set;
68295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
68395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						| POLICY_DATA_FLAG_EXTRA_NODE;
68495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			node = level_add_node(NULL, extra, anyPolicy->parent,
68595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						tree);
68695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
68795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!tree->user_policies)
68895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
68995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			tree->user_policies = sk_X509_POLICY_NODE_new_null();
69095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!tree->user_policies)
69195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 1;
69295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
69395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
69495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
69595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
69695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
69795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
69895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
69995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
70095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int tree_evaluate(X509_POLICY_TREE *tree)
70195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
70295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret, i;
70395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_LEVEL *curr = tree->levels + 1;
70495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const X509_POLICY_CACHE *cache;
70595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
70695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for(i = 1; i < tree->nlevel; i++, curr++)
70795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
70895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cache = policy_cache_set(curr->cert);
70995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!tree_link_nodes(curr, cache))
71095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
71195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
71295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
71395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			&& !tree_link_any(curr, cache, tree))
71495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
71595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree_print("before tree_prune()", tree, curr);
71695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = tree_prune(tree, curr);
71795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (ret != 1)
71895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return ret;
71995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
72095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
72195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
72295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
72395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
72495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
72595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void exnode_free(X509_POLICY_NODE *node)
72695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
72795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
72895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_free(node);
72995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
73095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
73195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
73295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid X509_policy_tree_free(X509_POLICY_TREE *tree)
73395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
73495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_LEVEL *curr;
73595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i;
73695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
73795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!tree)
73895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return;
73995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
74095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	sk_X509_POLICY_NODE_free(tree->auth_policies);
74195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
74295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
74395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++)
74495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
74595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (curr->cert)
74695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			X509_free(curr->cert);
74795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (curr->nodes)
74895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			sk_X509_POLICY_NODE_pop_free(curr->nodes,
74995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						policy_node_free);
75095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (curr->anyPolicy)
75195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			policy_node_free(curr->anyPolicy);
75295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
75395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
75495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (tree->extra_data)
75595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		sk_X509_POLICY_DATA_pop_free(tree->extra_data,
75695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						policy_data_free);
75795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
75895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	OPENSSL_free(tree->levels);
75995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	OPENSSL_free(tree);
76095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
76195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
76295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
76395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Application policy checking function.
76495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Return codes:
76595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *  0 	Internal Error.
76695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *  1   Successful.
76795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * -1   One or more certificates contain invalid or inconsistent extensions
76895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * -2	User constrained policy set empty and requireExplicit true.
76995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
77095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
77195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
77295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			STACK_OF(X509) *certs,
77395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			STACK_OF(ASN1_OBJECT) *policy_oids,
77495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			unsigned int flags)
77595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
77695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret;
77795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_POLICY_TREE *tree = NULL;
77895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
77995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*ptree = NULL;
78095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
78195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*pexplicit_policy = 0;
78295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ret = tree_init(&tree, certs, flags);
78395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
78495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	switch (ret)
78595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
78695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
78795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Tree empty requireExplicit False: OK */
78895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case 2:
78995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
79095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
79195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Some internal error */
79295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case -1:
79395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return -1;
79495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
79595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Some internal error */
79695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case 0:
79795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
79895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
79995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Tree empty requireExplicit True: Error */
80095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
80195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case 6:
80295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*pexplicit_policy = 1;
80395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return -2;
80495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
80595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Tree OK requireExplicit True: OK and continue */
80695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case 5:
80795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*pexplicit_policy = 1;
80895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
80995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
81095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Tree OK: continue */
81195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
81295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case 1:
81395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!tree)
81495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/*
81595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * tree_init() returns success and a null tree
81695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * if it's just looking at a trust anchor.
81795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * I'm not sure that returning success here is
81895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * correct, but I'm sure that reporting this
81995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * as an internal error which our caller
82095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * interprets as a malloc failure is wrong.
82195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
82295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 1;
82395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
82495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
82595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
82695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!tree) goto error;
82795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ret = tree_evaluate(tree);
82895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
82995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	tree_print("tree_evaluate()", tree, NULL);
83095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
83195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (ret <= 0)
83295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto error;
83395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
83495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Return value 2 means tree empty */
83595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (ret == 2)
83695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
83795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		X509_policy_tree_free(tree);
83895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (*pexplicit_policy)
83995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -2;
84095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
84195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 1;
84295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
84395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
84495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Tree is not empty: continue */
84595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
84695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ret = tree_calculate_authority_set(tree, &auth_nodes);
84795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
84895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!ret)
84995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto error;
85095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
85195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
85295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto error;
85395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
85495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (ret == 2)
85595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		sk_X509_POLICY_NODE_free(auth_nodes);
85695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
85795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (tree)
85895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*ptree = tree;
85995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
86095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (*pexplicit_policy)
86195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
86295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		nodes = X509_policy_tree_get0_user_policies(tree);
86395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (sk_X509_POLICY_NODE_num(nodes) <= 0)
86495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -2;
86595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
86695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
86795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
86895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
86995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	error:
87095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
87195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	X509_policy_tree_free(tree);
87295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
87395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 0;
87495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
87595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
87695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
877