1/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2 * project 2004.
3 */
4/* ====================================================================
5 * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in
16 *    the documentation and/or other materials provided with the
17 *    distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 *    software must display the following acknowledgment:
21 *    "This product includes software developed by the OpenSSL Project
22 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 *    endorse or promote products derived from this software without
26 *    prior written permission. For written permission, please contact
27 *    licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 *    nor may "OpenSSL" appear in their names without prior written
31 *    permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 *    acknowledgment:
35 *    "This product includes software developed by the OpenSSL Project
36 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com).  This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
55 *
56 */
57
58#include <openssl/mem.h>
59#include <openssl/obj.h>
60#include <openssl/stack.h>
61#include <openssl/thread.h>
62#include <openssl/x509.h>
63#include <openssl/x509v3.h>
64
65#include "pcy_int.h"
66
67
68/* Enable this to print out the complete policy tree at various point during
69 * evaluation.
70 */
71
72/*#define OPENSSL_POLICY_DEBUG*/
73
74#ifdef OPENSSL_POLICY_DEBUG
75
76static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
77				X509_POLICY_NODE *node, int indent)
78	{
79	if (	    (lev->flags & X509_V_FLAG_INHIBIT_MAP)
80		|| !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
81		BIO_puts(err, "  Not Mapped\n");
82	else
83		{
84		int i;
85		STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
86		ASN1_OBJECT *oid;
87		BIO_puts(err, "  Expected: ");
88		for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++)
89			{
90			oid = sk_ASN1_OBJECT_value(pset, i);
91			if (i)
92				BIO_puts(err, ", ");
93			i2a_ASN1_OBJECT(err, oid);
94			}
95		BIO_puts(err, "\n");
96		}
97	}
98
99static void tree_print(char *str, X509_POLICY_TREE *tree,
100			X509_POLICY_LEVEL *curr)
101	{
102	X509_POLICY_LEVEL *plev;
103	X509_POLICY_NODE *node;
104	int i;
105	BIO *err;
106	err = BIO_new_fp(stderr, BIO_NOCLOSE);
107	if (!curr)
108		curr = tree->levels + tree->nlevel;
109	else
110		curr++;
111	BIO_printf(err, "Level print after %s\n", str);
112	BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
113	for (plev = tree->levels; plev != curr; plev++)
114		{
115		BIO_printf(err, "Level %ld, flags = %x\n",
116				plev - tree->levels, plev->flags);
117		for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++)
118			{
119			node = sk_X509_POLICY_NODE_value(plev->nodes, i);
120			X509_POLICY_NODE_print(err, node, 2);
121			expected_print(err, plev, node, 2);
122			BIO_printf(err, "  Flags: %x\n", node->data->flags);
123			}
124		if (plev->anyPolicy)
125			X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
126		}
127
128	BIO_free(err);
129
130	}
131#else
132
133#define tree_print(a,b,c) /* */
134
135#endif
136
137/* Initialize policy tree. Return values:
138 *  0 Some internal error occured.
139 * -1 Inconsistent or invalid extensions in certificates.
140 *  1 Tree initialized OK.
141 *  2 Policy tree is empty.
142 *  5 Tree OK and requireExplicitPolicy true.
143 *  6 Tree empty and requireExplicitPolicy true.
144 */
145
146static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
147			unsigned int flags)
148	{
149	X509_POLICY_TREE *tree;
150	X509_POLICY_LEVEL *level;
151	const X509_POLICY_CACHE *cache;
152	X509_POLICY_DATA *data = NULL;
153	X509 *x;
154	int ret = 1;
155	int i, n;
156	int explicit_policy;
157	int any_skip;
158	int map_skip;
159	*ptree = NULL;
160	n = sk_X509_num(certs);
161
162#if 0
163	/* Disable policy mapping for now... */
164	flags |= X509_V_FLAG_INHIBIT_MAP;
165#endif
166
167	if (flags & X509_V_FLAG_EXPLICIT_POLICY)
168		explicit_policy = 0;
169	else
170		explicit_policy = n + 1;
171
172	if (flags & X509_V_FLAG_INHIBIT_ANY)
173		any_skip = 0;
174	else
175		any_skip = n + 1;
176
177	if (flags & X509_V_FLAG_INHIBIT_MAP)
178		map_skip = 0;
179	else
180		map_skip = n + 1;
181
182	/* Can't do anything with just a trust anchor */
183	if (n == 1)
184		return 1;
185	/* First setup policy cache in all certificates apart from the
186	 * trust anchor. Note any bad cache results on the way. Also can
187	 * calculate explicit_policy value at this point.
188	 */
189	for (i = n - 2; i >= 0; i--)
190		{
191		x = sk_X509_value(certs, i);
192		X509_check_purpose(x, -1, -1);
193		cache = policy_cache_set(x);
194		/* If cache NULL something bad happened: return immediately */
195		if (cache == NULL)
196			return 0;
197		/* If inconsistent extensions keep a note of it but continue */
198		if (x->ex_flags & EXFLAG_INVALID_POLICY)
199			ret = -1;
200		/* Otherwise if we have no data (hence no CertificatePolicies)
201		 * and haven't already set an inconsistent code note it.
202		 */
203		else if ((ret == 1) && !cache->data)
204			ret = 2;
205		if (explicit_policy > 0)
206			{
207			if (!(x->ex_flags & EXFLAG_SI))
208				explicit_policy--;
209			if ((cache->explicit_skip != -1)
210				&& (cache->explicit_skip < explicit_policy))
211				explicit_policy = cache->explicit_skip;
212			}
213		}
214
215	if (ret != 1)
216		{
217		if (ret == 2 && !explicit_policy)
218			return 6;
219		return ret;
220		}
221
222
223	/* If we get this far initialize the tree */
224
225	tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
226
227	if (!tree)
228		return 0;
229
230	tree->flags = 0;
231	tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
232	tree->nlevel = 0;
233	tree->extra_data = NULL;
234	tree->auth_policies = NULL;
235	tree->user_policies = NULL;
236
237	if (!tree->levels)
238		{
239		OPENSSL_free(tree);
240		return 0;
241		}
242
243	memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
244
245	tree->nlevel = n;
246
247	level = tree->levels;
248
249	/* Root data: initialize to anyPolicy */
250
251	data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
252
253	if (!data || !level_add_node(level, data, NULL, tree))
254		goto bad_tree;
255
256	for (i = n - 2; i >= 0; i--)
257		{
258		level++;
259		x = sk_X509_value(certs, i);
260		cache = policy_cache_set(x);
261		level->cert = X509_up_ref(x);
262
263		if (!cache->anyPolicy)
264				level->flags |= X509_V_FLAG_INHIBIT_ANY;
265
266		/* Determine inhibit any and inhibit map flags */
267		if (any_skip == 0)
268			{
269			/* Any matching allowed if certificate is self
270			 * issued and not the last in the chain.
271			 */
272			if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
273				level->flags |= X509_V_FLAG_INHIBIT_ANY;
274			}
275		else
276			{
277			if (!(x->ex_flags & EXFLAG_SI))
278				any_skip--;
279			if ((cache->any_skip >= 0)
280				&& (cache->any_skip < any_skip))
281				any_skip = cache->any_skip;
282			}
283
284		if (map_skip == 0)
285			level->flags |= X509_V_FLAG_INHIBIT_MAP;
286		else
287			{
288			if (!(x->ex_flags & EXFLAG_SI))
289				map_skip--;
290			if ((cache->map_skip >= 0)
291				&& (cache->map_skip < map_skip))
292				map_skip = cache->map_skip;
293			}
294
295		}
296
297	*ptree = tree;
298
299	if (explicit_policy)
300		return 1;
301	else
302		return 5;
303
304	bad_tree:
305
306	X509_policy_tree_free(tree);
307
308	return 0;
309
310	}
311
312static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
313				const X509_POLICY_DATA *data)
314	{
315	X509_POLICY_LEVEL *last = curr - 1;
316	X509_POLICY_NODE *node;
317	int matched = 0;
318	size_t i;
319	/* Iterate through all in nodes linking matches */
320	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
321		{
322		node = sk_X509_POLICY_NODE_value(last->nodes, i);
323		if (policy_node_match(last, node, data->valid_policy))
324			{
325			if (!level_add_node(curr, data, node, NULL))
326				return 0;
327			matched = 1;
328			}
329		}
330	if (!matched && last->anyPolicy)
331		{
332		if (!level_add_node(curr, data, last->anyPolicy, NULL))
333			return 0;
334		}
335	return 1;
336	}
337
338/* This corresponds to RFC3280 6.1.3(d)(1):
339 * link any data from CertificatePolicies onto matching parent
340 * or anyPolicy if no match.
341 */
342
343static int tree_link_nodes(X509_POLICY_LEVEL *curr,
344				const X509_POLICY_CACHE *cache)
345	{
346	size_t i;
347	X509_POLICY_DATA *data;
348
349	for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
350		{
351		data = sk_X509_POLICY_DATA_value(cache->data, i);
352		/* If a node is mapped any it doesn't have a corresponding
353		 * CertificatePolicies entry.
354		 * However such an identical node would be created
355		 * if anyPolicy matching is enabled because there would be
356		 * no match with the parent valid_policy_set. So we create
357		 * link because then it will have the mapping flags
358		 * right and we can prune it later.
359		 */
360#if 0
361		if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
362			&& !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
363			continue;
364#endif
365		/* Look for matching nodes in previous level */
366		if (!tree_link_matching_nodes(curr, data))
367				return 0;
368		}
369	return 1;
370	}
371
372/* This corresponds to RFC3280 6.1.3(d)(2):
373 * Create new data for any unmatched policies in the parent and link
374 * to anyPolicy.
375 */
376
377static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
378			const X509_POLICY_CACHE *cache,
379			const ASN1_OBJECT *id,
380			X509_POLICY_NODE *node,
381			X509_POLICY_TREE *tree)
382	{
383	X509_POLICY_DATA *data;
384	if (id == NULL)
385		id = node->data->valid_policy;
386	/* Create a new node with qualifiers from anyPolicy and
387	 * id from unmatched node.
388	 */
389	data = policy_data_new(NULL, id, node_critical(node));
390
391	if (data == NULL)
392		return 0;
393	/* Curr may not have anyPolicy */
394	data->qualifier_set = cache->anyPolicy->qualifier_set;
395	data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
396	if (!level_add_node(curr, data, node, tree))
397		{
398		policy_data_free(data);
399		return 0;
400		}
401
402	return 1;
403	}
404
405static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
406			const X509_POLICY_CACHE *cache,
407			X509_POLICY_NODE *node,
408			X509_POLICY_TREE *tree)
409	{
410	const X509_POLICY_LEVEL *last = curr - 1;
411	size_t i;
412
413	if (	    (last->flags & X509_V_FLAG_INHIBIT_MAP)
414		|| !(node->data->flags & POLICY_DATA_FLAG_MAPPED))
415		{
416		/* If no policy mapping: matched if one child present */
417		if (node->nchild)
418			return 1;
419		if (!tree_add_unmatched(curr, cache, NULL, node, tree))
420			return 0;
421		/* Add it */
422		}
423	else
424		{
425		/* If mapping: matched if one child per expected policy set */
426		STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
427		if (node->nchild == sk_ASN1_OBJECT_num(expset))
428			return 1;
429		/* Locate unmatched nodes */
430		for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++)
431			{
432			ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
433			if (level_find_node(curr, node, oid))
434				continue;
435			if (!tree_add_unmatched(curr, cache, oid, node, tree))
436				return 0;
437			}
438
439		}
440
441	return 1;
442
443	}
444
445static int tree_link_any(X509_POLICY_LEVEL *curr,
446			const X509_POLICY_CACHE *cache,
447			X509_POLICY_TREE *tree)
448	{
449	size_t i;
450	/*X509_POLICY_DATA *data;*/
451	X509_POLICY_NODE *node;
452	X509_POLICY_LEVEL *last = curr - 1;
453
454	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
455		{
456		node = sk_X509_POLICY_NODE_value(last->nodes, i);
457
458		if (!tree_link_unmatched(curr, cache, node, tree))
459			return 0;
460
461#if 0
462
463		/* Skip any node with any children: we only want unmathced
464		 * nodes.
465		 *
466		 * Note: need something better for policy mapping
467		 * because each node may have multiple children
468		 */
469		if (node->nchild)
470			continue;
471
472		/* Create a new node with qualifiers from anyPolicy and
473		 * id from unmatched node.
474		 */
475		data = policy_data_new(NULL, node->data->valid_policy,
476						node_critical(node));
477
478		if (data == NULL)
479			return 0;
480		/* Curr may not have anyPolicy */
481		data->qualifier_set = cache->anyPolicy->qualifier_set;
482		data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
483		if (!level_add_node(curr, data, node, tree))
484			{
485			policy_data_free(data);
486			return 0;
487			}
488
489#endif
490
491		}
492	/* Finally add link to anyPolicy */
493	if (last->anyPolicy)
494		{
495		if (!level_add_node(curr, cache->anyPolicy,
496						last->anyPolicy, NULL))
497			return 0;
498		}
499	return 1;
500	}
501
502/* Prune the tree: delete any child mapped child data on the current level
503 * then proceed up the tree deleting any data with no children. If we ever
504 * have no data on a level we can halt because the tree will be empty.
505 */
506
507static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
508	{
509	STACK_OF(X509_POLICY_NODE) *nodes;
510	X509_POLICY_NODE *node;
511	int i;
512	nodes = curr->nodes;
513	if (curr->flags & X509_V_FLAG_INHIBIT_MAP)
514		{
515		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
516			{
517			node = sk_X509_POLICY_NODE_value(nodes, i);
518			/* Delete any mapped data: see RFC3280 XXXX */
519			if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
520				{
521				node->parent->nchild--;
522				OPENSSL_free(node);
523				(void)sk_X509_POLICY_NODE_delete(nodes,i);
524				}
525			}
526		}
527
528	for(;;)	{
529		--curr;
530		nodes = curr->nodes;
531		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
532			{
533			node = sk_X509_POLICY_NODE_value(nodes, i);
534			if (node->nchild == 0)
535				{
536				node->parent->nchild--;
537				OPENSSL_free(node);
538				(void)sk_X509_POLICY_NODE_delete(nodes, i);
539				}
540			}
541		if (curr->anyPolicy && !curr->anyPolicy->nchild)
542			{
543			if (curr->anyPolicy->parent)
544				curr->anyPolicy->parent->nchild--;
545			OPENSSL_free(curr->anyPolicy);
546			curr->anyPolicy = NULL;
547			}
548		if (curr == tree->levels)
549			{
550			/* If we zapped anyPolicy at top then tree is empty */
551			if (!curr->anyPolicy)
552					return 2;
553			return 1;
554			}
555		}
556
557	return 1;
558
559	}
560
561static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
562						 X509_POLICY_NODE *pcy)
563	{
564	if (!*pnodes)
565		{
566		*pnodes = policy_node_cmp_new();
567		if (!*pnodes)
568			return 0;
569		}
570	else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
571		return 1;
572
573	if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
574		return 0;
575
576	return 1;
577
578	}
579
580/* Calculate the authority set based on policy tree.
581 * The 'pnodes' parameter is used as a store for the set of policy nodes
582 * used to calculate the user set. If the authority set is not anyPolicy
583 * then pnodes will just point to the authority set. If however the authority
584 * set is anyPolicy then the set of valid policies (other than anyPolicy)
585 * is store in pnodes. The return value of '2' is used in this case to indicate
586 * that pnodes should be freed.
587 */
588
589static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
590					STACK_OF(X509_POLICY_NODE) **pnodes)
591	{
592	X509_POLICY_LEVEL *curr;
593	X509_POLICY_NODE *node, *anyptr;
594	STACK_OF(X509_POLICY_NODE) **addnodes;
595	int i;
596	size_t j;
597	curr = tree->levels + tree->nlevel - 1;
598
599	/* If last level contains anyPolicy set is anyPolicy */
600	if (curr->anyPolicy)
601		{
602		if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
603			return 0;
604		addnodes = pnodes;
605		}
606	else
607		/* Add policies to authority set */
608		addnodes = &tree->auth_policies;
609
610	curr = tree->levels;
611	for (i = 1; i < tree->nlevel; i++)
612		{
613		/* If no anyPolicy node on this this level it can't
614		 * appear on lower levels so end search.
615		 */
616		if (!(anyptr = curr->anyPolicy))
617			break;
618		curr++;
619		for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++)
620			{
621			node = sk_X509_POLICY_NODE_value(curr->nodes, j);
622			if ((node->parent == anyptr)
623				&& !tree_add_auth_node(addnodes, node))
624					return 0;
625			}
626		}
627
628	if (addnodes == pnodes)
629		return 2;
630
631	*pnodes = tree->auth_policies;
632
633	return 1;
634	}
635
636static int tree_calculate_user_set(X509_POLICY_TREE *tree,
637				STACK_OF(ASN1_OBJECT) *policy_oids,
638				STACK_OF(X509_POLICY_NODE) *auth_nodes)
639	{
640	size_t i;
641	X509_POLICY_NODE *node;
642	ASN1_OBJECT *oid;
643
644	X509_POLICY_NODE *anyPolicy;
645	X509_POLICY_DATA *extra;
646
647	/* Check if anyPolicy present in authority constrained policy set:
648	 * this will happen if it is a leaf node.
649	 */
650
651	if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
652		return 1;
653
654	anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
655
656	for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
657		{
658		oid = sk_ASN1_OBJECT_value(policy_oids, i);
659		if (OBJ_obj2nid(oid) == NID_any_policy)
660			{
661			tree->flags |= POLICY_FLAG_ANY_POLICY;
662			return 1;
663			}
664		}
665
666	for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
667		{
668		oid = sk_ASN1_OBJECT_value(policy_oids, i);
669		node = tree_find_sk(auth_nodes, oid);
670		if (!node)
671			{
672			if (!anyPolicy)
673				continue;
674			/* Create a new node with policy ID from user set
675			 * and qualifiers from anyPolicy.
676			 */
677			extra = policy_data_new(NULL, oid,
678						node_critical(anyPolicy));
679			if (!extra)
680				return 0;
681			extra->qualifier_set = anyPolicy->data->qualifier_set;
682			extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
683						| POLICY_DATA_FLAG_EXTRA_NODE;
684			node = level_add_node(NULL, extra, anyPolicy->parent,
685						tree);
686			}
687		if (!tree->user_policies)
688			{
689			tree->user_policies = sk_X509_POLICY_NODE_new_null();
690			if (!tree->user_policies)
691				return 1;
692			}
693		if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
694			return 0;
695		}
696	return 1;
697
698	}
699
700static int tree_evaluate(X509_POLICY_TREE *tree)
701	{
702	int ret, i;
703	X509_POLICY_LEVEL *curr = tree->levels + 1;
704	const X509_POLICY_CACHE *cache;
705
706	for(i = 1; i < tree->nlevel; i++, curr++)
707		{
708		cache = policy_cache_set(curr->cert);
709		if (!tree_link_nodes(curr, cache))
710			return 0;
711
712		if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
713			&& !tree_link_any(curr, cache, tree))
714			return 0;
715	tree_print("before tree_prune()", tree, curr);
716		ret = tree_prune(tree, curr);
717		if (ret != 1)
718			return ret;
719		}
720
721	return 1;
722
723	}
724
725static void exnode_free(X509_POLICY_NODE *node)
726	{
727	if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
728		OPENSSL_free(node);
729	}
730
731
732void X509_policy_tree_free(X509_POLICY_TREE *tree)
733	{
734	X509_POLICY_LEVEL *curr;
735	int i;
736
737	if (!tree)
738		return;
739
740	sk_X509_POLICY_NODE_free(tree->auth_policies);
741	sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
742
743	for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++)
744		{
745		if (curr->cert)
746			X509_free(curr->cert);
747		if (curr->nodes)
748			sk_X509_POLICY_NODE_pop_free(curr->nodes,
749						policy_node_free);
750		if (curr->anyPolicy)
751			policy_node_free(curr->anyPolicy);
752		}
753
754	if (tree->extra_data)
755		sk_X509_POLICY_DATA_pop_free(tree->extra_data,
756						policy_data_free);
757
758	OPENSSL_free(tree->levels);
759	OPENSSL_free(tree);
760
761	}
762
763/* Application policy checking function.
764 * Return codes:
765 *  0 	Internal Error.
766 *  1   Successful.
767 * -1   One or more certificates contain invalid or inconsistent extensions
768 * -2	User constrained policy set empty and requireExplicit true.
769 */
770
771int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
772			STACK_OF(X509) *certs,
773			STACK_OF(ASN1_OBJECT) *policy_oids,
774			unsigned int flags)
775	{
776	int ret;
777	X509_POLICY_TREE *tree = NULL;
778	STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
779	*ptree = NULL;
780
781	*pexplicit_policy = 0;
782	ret = tree_init(&tree, certs, flags);
783
784	switch (ret)
785		{
786
787		/* Tree empty requireExplicit False: OK */
788		case 2:
789		return 1;
790
791		/* Some internal error */
792		case -1:
793		return -1;
794
795		/* Some internal error */
796		case 0:
797		return 0;
798
799		/* Tree empty requireExplicit True: Error */
800
801		case 6:
802		*pexplicit_policy = 1;
803		return -2;
804
805		/* Tree OK requireExplicit True: OK and continue */
806		case 5:
807		*pexplicit_policy = 1;
808		break;
809
810		/* Tree OK: continue */
811
812		case 1:
813		if (!tree)
814			/*
815			 * tree_init() returns success and a null tree
816			 * if it's just looking at a trust anchor.
817			 * I'm not sure that returning success here is
818			 * correct, but I'm sure that reporting this
819			 * as an internal error which our caller
820			 * interprets as a malloc failure is wrong.
821			 */
822			return 1;
823		break;
824		}
825
826	if (!tree) goto error;
827	ret = tree_evaluate(tree);
828
829	tree_print("tree_evaluate()", tree, NULL);
830
831	if (ret <= 0)
832		goto error;
833
834	/* Return value 2 means tree empty */
835	if (ret == 2)
836		{
837		X509_policy_tree_free(tree);
838		if (*pexplicit_policy)
839			return -2;
840		else
841			return 1;
842		}
843
844	/* Tree is not empty: continue */
845
846	ret = tree_calculate_authority_set(tree, &auth_nodes);
847
848	if (!ret)
849		goto error;
850
851	if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
852		goto error;
853
854	if (ret == 2)
855		sk_X509_POLICY_NODE_free(auth_nodes);
856
857	if (tree)
858		*ptree = tree;
859
860	if (*pexplicit_policy)
861		{
862		nodes = X509_policy_tree_get0_user_policies(tree);
863		if (sk_X509_POLICY_NODE_num(nodes) <= 0)
864			return -2;
865		}
866
867	return 1;
868
869	error:
870
871	X509_policy_tree_free(tree);
872
873	return 0;
874
875	}
876
877