1c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* pcy_tree.c */
2c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * project 2004.
4c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
5c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* ====================================================================
6c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
7c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
8c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Redistribution and use in source and binary forms, with or without
9c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * modification, are permitted provided that the following conditions
10c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * are met:
11c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
12c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 1. Redistributions of source code must retain the above copyright
13c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer.
14c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
15c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
16c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer in
17c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    the documentation and/or other materials provided with the
18c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    distribution.
19c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
20c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 3. All advertising materials mentioning features or use of this
21c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    software must display the following acknowledgment:
22c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes software developed by the OpenSSL Project
23c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
25c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    endorse or promote products derived from this software without
27c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    prior written permission. For written permission, please contact
28c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    licensing@OpenSSL.org.
29c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
30c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 5. Products derived from this software may not be called "OpenSSL"
31c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    nor may "OpenSSL" appear in their names without prior written
32c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    permission of the OpenSSL Project.
33c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
34c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 6. Redistributions of any form whatsoever must retain the following
35c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    acknowledgment:
36c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes software developed by the OpenSSL Project
37c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
39c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE.
51c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ====================================================================
52c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
53c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This product includes cryptographic software written by Eric Young
54c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * (eay@cryptsoft.com).  This product includes software written by Tim
55c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Hudson (tjh@cryptsoft.com).
56c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
57c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
58c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
59c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include "cryptlib.h"
60c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/x509.h>
61c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/x509v3.h>
62c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
63c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include "pcy_int.h"
64c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
65480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* Enable this to print out the complete policy tree at various point during
66480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * evaluation.
67480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org */
68480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
69480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/*#define OPENSSL_POLICY_DEBUG*/
70480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
71480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#ifdef OPENSSL_POLICY_DEBUG
72480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
73480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
74480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				X509_POLICY_NODE *node, int indent)
75480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
76480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (	    (lev->flags & X509_V_FLAG_INHIBIT_MAP)
77480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		|| !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
78480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_puts(err, "  Not Mapped\n");
79480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
80480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
81480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		int i;
82480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
83480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ASN1_OBJECT *oid;
84480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_puts(err, "  Expected: ");
85480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++)
86480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
87480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			oid = sk_ASN1_OBJECT_value(pset, i);
88480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (i)
89480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				BIO_puts(err, ", ");
90480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			i2a_ASN1_OBJECT(err, oid);
91480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
92480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_puts(err, "\n");
93480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
94480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
95480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
96480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic void tree_print(char *str, X509_POLICY_TREE *tree,
97480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_POLICY_LEVEL *curr)
98480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
99480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	X509_POLICY_LEVEL *plev;
100480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	X509_POLICY_NODE *node;
101480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int i;
102480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO *err;
103480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	err = BIO_new_fp(stderr, BIO_NOCLOSE);
104480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!curr)
105480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		curr = tree->levels + tree->nlevel;
106480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
107480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		curr++;
108480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(err, "Level print after %s\n", str);
109480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
110480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	for (plev = tree->levels; plev != curr; plev++)
111480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
112480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_printf(err, "Level %ld, flags = %x\n",
113480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				plev - tree->levels, plev->flags);
114480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++)
115480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
116480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			node = sk_X509_POLICY_NODE_value(plev->nodes, i);
117480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_POLICY_NODE_print(err, node, 2);
118480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			expected_print(err, plev, node, 2);
119480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BIO_printf(err, "  Flags: %x\n", node->data->flags);
120480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
121480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (plev->anyPolicy)
122480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
123480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
124480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
125480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_free(err);
126480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
127480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
128480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#else
129480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
130480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#define tree_print(a,b,c) /* */
131480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
132480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
133480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
134c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Initialize policy tree. Return values:
135c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *  0 Some internal error occured.
136c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * -1 Inconsistent or invalid extensions in certificates.
137c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *  1 Tree initialized OK.
138c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *  2 Policy tree is empty.
139c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *  5 Tree OK and requireExplicitPolicy true.
140c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *  6 Tree empty and requireExplicitPolicy true.
141c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
142c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
143c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
144c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			unsigned int flags)
145c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
146c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_TREE *tree;
147c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_LEVEL *level;
148c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	const X509_POLICY_CACHE *cache;
149c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_DATA *data = NULL;
150c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509 *x;
151c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret = 1;
152c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i, n;
153c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int explicit_policy;
154c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int any_skip;
155c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int map_skip;
156c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	*ptree = NULL;
157c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	n = sk_X509_num(certs);
158c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
159480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if 0
160c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Disable policy mapping for now... */
161c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	flags |= X509_V_FLAG_INHIBIT_MAP;
162480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
163c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
164c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (flags & X509_V_FLAG_EXPLICIT_POLICY)
165c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		explicit_policy = 0;
166c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
167c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		explicit_policy = n + 1;
168c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
169c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (flags & X509_V_FLAG_INHIBIT_ANY)
170c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		any_skip = 0;
171c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
172c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		any_skip = n + 1;
173c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
174c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (flags & X509_V_FLAG_INHIBIT_MAP)
175c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		map_skip = 0;
176c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
177c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		map_skip = n + 1;
178c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
179c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Can't do anything with just a trust anchor */
180c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (n == 1)
181c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 1;
182c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* First setup policy cache in all certificates apart from the
183c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * trust anchor. Note any bad cache results on the way. Also can
184c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * calculate explicit_policy value at this point.
185c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 */
186c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = n - 2; i >= 0; i--)
187c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
188c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		x = sk_X509_value(certs, i);
189c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		X509_check_purpose(x, -1, -1);
190c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		cache = policy_cache_set(x);
191c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* If cache NULL something bad happened: return immediately */
192c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (cache == NULL)
193c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
194c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* If inconsistent extensions keep a note of it but continue */
195c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (x->ex_flags & EXFLAG_INVALID_POLICY)
196c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = -1;
197c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Otherwise if we have no data (hence no CertificatePolicies)
198c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * and haven't already set an inconsistent code note it.
199c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
200c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else if ((ret == 1) && !cache->data)
201c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = 2;
202c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (explicit_policy > 0)
203c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
204c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!(x->ex_flags & EXFLAG_SI))
205c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				explicit_policy--;
206c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((cache->explicit_skip != -1)
207c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				&& (cache->explicit_skip < explicit_policy))
208c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				explicit_policy = cache->explicit_skip;
209c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
210c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
211c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
212c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret != 1)
213c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
214c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ret == 2 && !explicit_policy)
215c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 6;
216c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return ret;
217c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
218c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
219c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
220c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* If we get this far initialize the tree */
221c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
222c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
223c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
224c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!tree)
225c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
226c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
227c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	tree->flags = 0;
228c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
229c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	tree->nlevel = 0;
230c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	tree->extra_data = NULL;
231c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	tree->auth_policies = NULL;
232c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	tree->user_policies = NULL;
233c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
234c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!tree->levels)
235c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
236c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		OPENSSL_free(tree);
237c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
238c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
239c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
240c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
241c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
242c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	tree->nlevel = n;
243c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
244c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	level = tree->levels;
245c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
246c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Root data: initialize to anyPolicy */
247c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
248c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
249c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
250c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!data || !level_add_node(level, data, NULL, tree))
251c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto bad_tree;
252c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
253c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = n - 2; i >= 0; i--)
254c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
255c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		level++;
256c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		x = sk_X509_value(certs, i);
257c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		cache = policy_cache_set(x);
258c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
259c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		level->cert = x;
260c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
261c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!cache->anyPolicy)
262c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				level->flags |= X509_V_FLAG_INHIBIT_ANY;
263c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
264c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Determine inhibit any and inhibit map flags */
265c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (any_skip == 0)
266c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
267c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/* Any matching allowed if certificate is self
268c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * issued and not the last in the chain.
269c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 */
270c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
271c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				level->flags |= X509_V_FLAG_INHIBIT_ANY;
272c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
273c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
274c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
275c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!(x->ex_flags & EXFLAG_SI))
276c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				any_skip--;
277c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((cache->any_skip >= 0)
278c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				&& (cache->any_skip < any_skip))
279c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				any_skip = cache->any_skip;
280c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
281c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
282c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (map_skip == 0)
283c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			level->flags |= X509_V_FLAG_INHIBIT_MAP;
284c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
285c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
286480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!(x->ex_flags & EXFLAG_SI))
287480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				map_skip--;
288c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((cache->map_skip >= 0)
289c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				&& (cache->map_skip < map_skip))
290c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				map_skip = cache->map_skip;
291c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
292c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
293c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
294c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
295c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	*ptree = tree;
296c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
297c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (explicit_policy)
298c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 1;
299c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
300c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 5;
301c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
302c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bad_tree:
303c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
304c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_policy_tree_free(tree);
305c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
306c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 0;
307c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
308c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
309c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
310480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
311480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				const X509_POLICY_DATA *data)
312480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
313480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	X509_POLICY_LEVEL *last = curr - 1;
314480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	X509_POLICY_NODE *node;
315480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int i, matched = 0;
316480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Iterate through all in nodes linking matches */
317480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
318480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
319480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		node = sk_X509_POLICY_NODE_value(last->nodes, i);
320480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (policy_node_match(last, node, data->valid_policy))
321480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
322480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!level_add_node(curr, data, node, NULL))
323480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
324480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			matched = 1;
325480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
326480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
327480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!matched && last->anyPolicy)
328480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
329480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!level_add_node(curr, data, last->anyPolicy, NULL))
330480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
331480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
332480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
333480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
334480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
335480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* This corresponds to RFC3280 6.1.3(d)(1):
336c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * link any data from CertificatePolicies onto matching parent
337c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * or anyPolicy if no match.
338c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
339c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
340c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int tree_link_nodes(X509_POLICY_LEVEL *curr,
341c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				const X509_POLICY_CACHE *cache)
342c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
343c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
344c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_DATA *data;
345480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
346c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
347c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
348c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data = sk_X509_POLICY_DATA_value(cache->data, i);
349c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* If a node is mapped any it doesn't have a corresponding
350c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * CertificatePolicies entry.
351c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * However such an identical node would be created
352c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * if anyPolicy matching is enabled because there would be
353c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * no match with the parent valid_policy_set. So we create
354c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * link because then it will have the mapping flags
355c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * right and we can prune it later.
356c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
357480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if 0
358c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
359c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			&& !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
360c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			continue;
361480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
362480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		/* Look for matching nodes in previous level */
363480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!tree_link_matching_nodes(curr, data))
364c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				return 0;
365c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
366c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
367c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
368c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
369480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* This corresponds to RFC3280 6.1.3(d)(2):
370c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Create new data for any unmatched policies in the parent and link
371c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * to anyPolicy.
372c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
373c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
374480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int tree_add_unmatched(X509_POLICY_LEVEL *curr,
375480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			const X509_POLICY_CACHE *cache,
376480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			const ASN1_OBJECT *id,
377480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_POLICY_NODE *node,
378480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_POLICY_TREE *tree)
379480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
380480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	X509_POLICY_DATA *data;
381480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (id == NULL)
382480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		id = node->data->valid_policy;
383480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Create a new node with qualifiers from anyPolicy and
384480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 * id from unmatched node.
385480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 */
386480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	data = policy_data_new(NULL, id, node_critical(node));
387480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
388480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (data == NULL)
389480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
390480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Curr may not have anyPolicy */
391480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	data->qualifier_set = cache->anyPolicy->qualifier_set;
392480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
393480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!level_add_node(curr, data, node, tree))
394480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
395480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		policy_data_free(data);
396480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
397480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
398480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
399480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
400480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
401480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
402480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int tree_link_unmatched(X509_POLICY_LEVEL *curr,
403480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			const X509_POLICY_CACHE *cache,
404480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_POLICY_NODE *node,
405480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_POLICY_TREE *tree)
406480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
407480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	const X509_POLICY_LEVEL *last = curr - 1;
408480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int i;
409480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
410480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (	    (last->flags & X509_V_FLAG_INHIBIT_MAP)
411480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		|| !(node->data->flags & POLICY_DATA_FLAG_MAPPED))
412480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
413480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		/* If no policy mapping: matched if one child present */
414480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (node->nchild)
415480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 1;
416480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!tree_add_unmatched(curr, cache, NULL, node, tree))
417480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
418480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		/* Add it */
419480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
420480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
421480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
422480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		/* If mapping: matched if one child per expected policy set */
423480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
424480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (node->nchild == sk_ASN1_OBJECT_num(expset))
425480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 1;
426480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		/* Locate unmatched nodes */
427480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++)
428480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
429480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
430480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (level_find_node(curr, node, oid))
431480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				continue;
432480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!tree_add_unmatched(curr, cache, oid, node, tree))
433480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
434480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
435480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
436480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
437480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
438480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
439480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
440480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
441480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
442c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int tree_link_any(X509_POLICY_LEVEL *curr,
443c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			const X509_POLICY_CACHE *cache,
444c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			X509_POLICY_TREE *tree)
445c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
446c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
447480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/*X509_POLICY_DATA *data;*/
448c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_NODE *node;
449480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	X509_POLICY_LEVEL *last = curr - 1;
450c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
451c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
452c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
453c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		node = sk_X509_POLICY_NODE_value(last->nodes, i);
454c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
455480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!tree_link_unmatched(curr, cache, node, tree))
456480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
457480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
458480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if 0
459480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
460c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Skip any node with any children: we only want unmathced
461c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * nodes.
462c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 *
463c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * Note: need something better for policy mapping
464c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * because each node may have multiple children
465c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
466c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (node->nchild)
467c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			continue;
468480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
469c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Create a new node with qualifiers from anyPolicy and
470c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * id from unmatched node.
471c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
472c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data = policy_data_new(NULL, node->data->valid_policy,
473c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						node_critical(node));
474c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
475c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (data == NULL)
476c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
477c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Curr may not have anyPolicy */
478c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data->qualifier_set = cache->anyPolicy->qualifier_set;
479c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
480c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!level_add_node(curr, data, node, tree))
481c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
482c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			policy_data_free(data);
483c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
484c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
485480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
486480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
487480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
488c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
489c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Finally add link to anyPolicy */
490c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (last->anyPolicy)
491c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
492c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!level_add_node(curr, cache->anyPolicy,
493c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						last->anyPolicy, NULL))
494c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
495c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
496c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
497c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
498c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
499c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Prune the tree: delete any child mapped child data on the current level
500c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * then proceed up the tree deleting any data with no children. If we ever
501c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * have no data on a level we can halt because the tree will be empty.
502c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
503c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
504c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
505c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
506480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	STACK_OF(X509_POLICY_NODE) *nodes;
507c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_NODE *node;
508c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
509480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	nodes = curr->nodes;
510480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (curr->flags & X509_V_FLAG_INHIBIT_MAP)
511c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
512480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
513c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
514480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			node = sk_X509_POLICY_NODE_value(nodes, i);
515480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			/* Delete any mapped data: see RFC3280 XXXX */
516480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
517480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
518480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				node->parent->nchild--;
519480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				OPENSSL_free(node);
520480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				(void)sk_X509_POLICY_NODE_delete(nodes,i);
521480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
522c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
523c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
524c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
525c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for(;;)	{
526c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		--curr;
527480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		nodes = curr->nodes;
528480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
529c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
530480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			node = sk_X509_POLICY_NODE_value(nodes, i);
531c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (node->nchild == 0)
532c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
533c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				node->parent->nchild--;
534c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				OPENSSL_free(node);
535480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				(void)sk_X509_POLICY_NODE_delete(nodes, i);
536c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
537c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
538c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (curr->anyPolicy && !curr->anyPolicy->nchild)
539c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
540c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (curr->anyPolicy->parent)
541c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				curr->anyPolicy->parent->nchild--;
542c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			OPENSSL_free(curr->anyPolicy);
543c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			curr->anyPolicy = NULL;
544c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
545c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (curr == tree->levels)
546c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
547c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/* If we zapped anyPolicy at top then tree is empty */
548c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!curr->anyPolicy)
549c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					return 2;
550c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 1;
551c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
552c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
553c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
554c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
555c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
556c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
557c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
558c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
559c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						 X509_POLICY_NODE *pcy)
560c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
561c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!*pnodes)
562c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
563c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		*pnodes = policy_node_cmp_new();
564c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!*pnodes)
565c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
566c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
567c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else if (sk_X509_POLICY_NODE_find(*pnodes, pcy) != -1)
568c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 1;
569c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
570c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
571c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
572c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
573c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
574c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
575c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
576c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
577c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Calculate the authority set based on policy tree.
578c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * The 'pnodes' parameter is used as a store for the set of policy nodes
579c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * used to calculate the user set. If the authority set is not anyPolicy
580c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * then pnodes will just point to the authority set. If however the authority
581c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * set is anyPolicy then the set of valid policies (other than anyPolicy)
582c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * is store in pnodes. The return value of '2' is used in this case to indicate
583c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * that pnodes should be freed.
584c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
585c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
586c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int tree_calculate_authority_set(X509_POLICY_TREE *tree,
587c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					STACK_OF(X509_POLICY_NODE) **pnodes)
588c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
589c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_LEVEL *curr;
590c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_NODE *node, *anyptr;
591c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(X509_POLICY_NODE) **addnodes;
592c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i, j;
593c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	curr = tree->levels + tree->nlevel - 1;
594c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
595c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* If last level contains anyPolicy set is anyPolicy */
596c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (curr->anyPolicy)
597c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
598c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
599c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
600c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		addnodes = pnodes;
601c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
602c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
603c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Add policies to authority set */
604c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		addnodes = &tree->auth_policies;
605c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
606c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	curr = tree->levels;
607c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = 1; i < tree->nlevel; i++)
608c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
609c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* If no anyPolicy node on this this level it can't
610c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * appear on lower levels so end search.
611c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
612c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!(anyptr = curr->anyPolicy))
613c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
614c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		curr++;
615c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++)
616c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
617c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			node = sk_X509_POLICY_NODE_value(curr->nodes, j);
618c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((node->parent == anyptr)
619c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				&& !tree_add_auth_node(addnodes, node))
620c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					return 0;
621c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
622c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
623c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
624c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (addnodes == pnodes)
625c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 2;
626c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
627c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	*pnodes = tree->auth_policies;
628c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
629c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
630c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
631c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
632c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int tree_calculate_user_set(X509_POLICY_TREE *tree,
633c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				STACK_OF(ASN1_OBJECT) *policy_oids,
634c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				STACK_OF(X509_POLICY_NODE) *auth_nodes)
635c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
636c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
637c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_NODE *node;
638c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_OBJECT *oid;
639c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
640c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_NODE *anyPolicy;
641c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_DATA *extra;
642c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
643c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Check if anyPolicy present in authority constrained policy set:
644c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * this will happen if it is a leaf node.
645c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 */
646c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
647c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
648c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 1;
649c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
650c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
651c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
652c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
653c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
654c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		oid = sk_ASN1_OBJECT_value(policy_oids, i);
655c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (OBJ_obj2nid(oid) == NID_any_policy)
656c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
657c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			tree->flags |= POLICY_FLAG_ANY_POLICY;
658c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 1;
659c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
660c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
661c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
662c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
663c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
664c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		oid = sk_ASN1_OBJECT_value(policy_oids, i);
665c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		node = tree_find_sk(auth_nodes, oid);
666c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!node)
667c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
668c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!anyPolicy)
669c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				continue;
670c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/* Create a new node with policy ID from user set
671c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * and qualifiers from anyPolicy.
672c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 */
673c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			extra = policy_data_new(NULL, oid,
674c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						node_critical(anyPolicy));
675c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!extra)
676c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				return 0;
677c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			extra->qualifier_set = anyPolicy->data->qualifier_set;
678c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
679c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						| POLICY_DATA_FLAG_EXTRA_NODE;
680c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			node = level_add_node(NULL, extra, anyPolicy->parent,
681c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						tree);
682c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
683c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!tree->user_policies)
684c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
685c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			tree->user_policies = sk_X509_POLICY_NODE_new_null();
686c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!tree->user_policies)
687c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				return 1;
688c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
689c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
690c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
691c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
692c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
693c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
694c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
695c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
696c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int tree_evaluate(X509_POLICY_TREE *tree)
697c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
698c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret, i;
699c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_LEVEL *curr = tree->levels + 1;
700c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	const X509_POLICY_CACHE *cache;
701c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
702c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for(i = 1; i < tree->nlevel; i++, curr++)
703c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
704c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		cache = policy_cache_set(curr->cert);
705c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!tree_link_nodes(curr, cache))
706c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
707c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
708c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
709c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			&& !tree_link_any(curr, cache, tree))
710c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
711480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	tree_print("before tree_prune()", tree, curr);
712c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret = tree_prune(tree, curr);
713c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ret != 1)
714c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return ret;
715c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
716c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
717c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
718c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
719c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
720c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
721c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic void exnode_free(X509_POLICY_NODE *node)
722c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
723c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
724c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		OPENSSL_free(node);
725c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
726c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
727c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
728c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgvoid X509_policy_tree_free(X509_POLICY_TREE *tree)
729c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
730c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_LEVEL *curr;
731c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
732c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
733c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!tree)
734c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return;
735c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
736c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	sk_X509_POLICY_NODE_free(tree->auth_policies);
737c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
738c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
739c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++)
740c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
741c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (curr->cert)
742c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			X509_free(curr->cert);
743c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (curr->nodes)
744c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sk_X509_POLICY_NODE_pop_free(curr->nodes,
745c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						policy_node_free);
746c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (curr->anyPolicy)
747c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			policy_node_free(curr->anyPolicy);
748c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
749c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
750c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (tree->extra_data)
751c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		sk_X509_POLICY_DATA_pop_free(tree->extra_data,
752c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						policy_data_free);
753c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
754c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	OPENSSL_free(tree->levels);
755c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	OPENSSL_free(tree);
756c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
757c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
758c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
759c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Application policy checking function.
760c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Return codes:
761c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *  0 	Internal Error.
762c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *  1   Successful.
763c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * -1   One or more certificates contain invalid or inconsistent extensions
764c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * -2	User constrained policy set empty and requireExplicit true.
765c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
766c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
767c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
768c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			STACK_OF(X509) *certs,
769c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			STACK_OF(ASN1_OBJECT) *policy_oids,
770c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			unsigned int flags)
771c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
772c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret;
773c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_POLICY_TREE *tree = NULL;
774c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
775c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	*ptree = NULL;
776c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
777c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	*pexplicit_policy = 0;
778c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret = tree_init(&tree, certs, flags);
779c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
780c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (ret)
781c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
782c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
783c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Tree empty requireExplicit False: OK */
784c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case 2:
785c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 1;
786c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
787c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Some internal error */
788480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case -1:
789480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return -1;
790480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
791480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		/* Some internal error */
792c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case 0:
793c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
794c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
795c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Tree empty requireExplicit True: Error */
796c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
797c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case 6:
798c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		*pexplicit_policy = 1;
799c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return -2;
800c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
801c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Tree OK requireExplicit True: OK and continue */
802c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case 5:
803c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		*pexplicit_policy = 1;
804c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
805c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
806c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Tree OK: continue */
807c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
808c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case 1:
809c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!tree)
810c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/*
811c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * tree_init() returns success and a null tree
812c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * if it's just looking at a trust anchor.
813c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * I'm not sure that returning success here is
814c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * correct, but I'm sure that reporting this
815c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * as an internal error which our caller
816c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 * interprets as a malloc failure is wrong.
817c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 */
818c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 1;
819c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
820c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
821c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
822c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!tree) goto error;
823c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret = tree_evaluate(tree);
824c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
825480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	tree_print("tree_evaluate()", tree, NULL);
826480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
827c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret <= 0)
828c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto error;
829c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
830c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Return value 2 means tree empty */
831c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret == 2)
832c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
833c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		X509_policy_tree_free(tree);
834c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (*pexplicit_policy)
835c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return -2;
836c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
837c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 1;
838c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
839c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
840c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Tree is not empty: continue */
841c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
842c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret = tree_calculate_authority_set(tree, &auth_nodes);
843c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
844c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!ret)
845c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto error;
846c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
847c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
848c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto error;
849c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
850c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret == 2)
851c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		sk_X509_POLICY_NODE_free(auth_nodes);
852c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
853c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (tree)
854c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		*ptree = tree;
855c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
856c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (*pexplicit_policy)
857c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
858c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		nodes = X509_policy_tree_get0_user_policies(tree);
859c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (sk_X509_POLICY_NODE_num(nodes) <= 0)
860c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return -2;
861c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
862c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
863c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
864c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
865c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	error:
866c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
867c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509_policy_tree_free(tree);
868c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
869c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 0;
870c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
871c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
872c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
873