• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string.h>
59 
60 #include <openssl/mem.h>
61 #include <openssl/obj.h>
62 #include <openssl/stack.h>
63 #include <openssl/thread.h>
64 #include <openssl/x509.h>
65 #include <openssl/x509v3.h>
66 
67 #include "pcy_int.h"
68 
69 
70 /* Enable this to print out the complete policy tree at various point during
71  * evaluation.
72  */
73 
74 /*#define OPENSSL_POLICY_DEBUG*/
75 
76 #ifdef OPENSSL_POLICY_DEBUG
77 
expected_print(BIO * err,X509_POLICY_LEVEL * lev,X509_POLICY_NODE * node,int indent)78 static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
79 				X509_POLICY_NODE *node, int indent)
80 	{
81 	if (	    (lev->flags & X509_V_FLAG_INHIBIT_MAP)
82 		|| !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
83 		BIO_puts(err, "  Not Mapped\n");
84 	else
85 		{
86 		int i;
87 		STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
88 		ASN1_OBJECT *oid;
89 		BIO_puts(err, "  Expected: ");
90 		for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++)
91 			{
92 			oid = sk_ASN1_OBJECT_value(pset, i);
93 			if (i)
94 				BIO_puts(err, ", ");
95 			i2a_ASN1_OBJECT(err, oid);
96 			}
97 		BIO_puts(err, "\n");
98 		}
99 	}
100 
tree_print(char * str,X509_POLICY_TREE * tree,X509_POLICY_LEVEL * curr)101 static void tree_print(char *str, X509_POLICY_TREE *tree,
102 			X509_POLICY_LEVEL *curr)
103 	{
104 	X509_POLICY_LEVEL *plev;
105 	X509_POLICY_NODE *node;
106 	int i;
107 	BIO *err;
108 	err = BIO_new_fp(stderr, BIO_NOCLOSE);
109 	if (!curr)
110 		curr = tree->levels + tree->nlevel;
111 	else
112 		curr++;
113 	BIO_printf(err, "Level print after %s\n", str);
114 	BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
115 	for (plev = tree->levels; plev != curr; plev++)
116 		{
117 		BIO_printf(err, "Level %ld, flags = %x\n",
118 				plev - tree->levels, plev->flags);
119 		for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++)
120 			{
121 			node = sk_X509_POLICY_NODE_value(plev->nodes, i);
122 			X509_POLICY_NODE_print(err, node, 2);
123 			expected_print(err, plev, node, 2);
124 			BIO_printf(err, "  Flags: %x\n", node->data->flags);
125 			}
126 		if (plev->anyPolicy)
127 			X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
128 		}
129 
130 	BIO_free(err);
131 
132 	}
133 #else
134 
135 #define tree_print(a,b,c) /* */
136 
137 #endif
138 
139 /* Initialize policy tree. Return values:
140  *  0 Some internal error occured.
141  * -1 Inconsistent or invalid extensions in certificates.
142  *  1 Tree initialized OK.
143  *  2 Policy tree is empty.
144  *  5 Tree OK and requireExplicitPolicy true.
145  *  6 Tree empty and requireExplicitPolicy true.
146  */
147 
tree_init(X509_POLICY_TREE ** ptree,STACK_OF (X509)* certs,unsigned int flags)148 static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
149 			unsigned int flags)
150 	{
151 	X509_POLICY_TREE *tree;
152 	X509_POLICY_LEVEL *level;
153 	const X509_POLICY_CACHE *cache;
154 	X509_POLICY_DATA *data = NULL;
155 	X509 *x;
156 	int ret = 1;
157 	int i, n;
158 	int explicit_policy;
159 	int any_skip;
160 	int map_skip;
161 	*ptree = NULL;
162 	n = sk_X509_num(certs);
163 
164 #if 0
165 	/* Disable policy mapping for now... */
166 	flags |= X509_V_FLAG_INHIBIT_MAP;
167 #endif
168 
169 	if (flags & X509_V_FLAG_EXPLICIT_POLICY)
170 		explicit_policy = 0;
171 	else
172 		explicit_policy = n + 1;
173 
174 	if (flags & X509_V_FLAG_INHIBIT_ANY)
175 		any_skip = 0;
176 	else
177 		any_skip = n + 1;
178 
179 	if (flags & X509_V_FLAG_INHIBIT_MAP)
180 		map_skip = 0;
181 	else
182 		map_skip = n + 1;
183 
184 	/* Can't do anything with just a trust anchor */
185 	if (n == 1)
186 		return 1;
187 	/* First setup policy cache in all certificates apart from the
188 	 * trust anchor. Note any bad cache results on the way. Also can
189 	 * calculate explicit_policy value at this point.
190 	 */
191 	for (i = n - 2; i >= 0; i--)
192 		{
193 		x = sk_X509_value(certs, i);
194 		X509_check_purpose(x, -1, -1);
195 		cache = policy_cache_set(x);
196 		/* If cache NULL something bad happened: return immediately */
197 		if (cache == NULL)
198 			return 0;
199 		/* If inconsistent extensions keep a note of it but continue */
200 		if (x->ex_flags & EXFLAG_INVALID_POLICY)
201 			ret = -1;
202 		/* Otherwise if we have no data (hence no CertificatePolicies)
203 		 * and haven't already set an inconsistent code note it.
204 		 */
205 		else if ((ret == 1) && !cache->data)
206 			ret = 2;
207 		if (explicit_policy > 0)
208 			{
209 			if (!(x->ex_flags & EXFLAG_SI))
210 				explicit_policy--;
211 			if ((cache->explicit_skip != -1)
212 				&& (cache->explicit_skip < explicit_policy))
213 				explicit_policy = cache->explicit_skip;
214 			}
215 		}
216 
217 	if (ret != 1)
218 		{
219 		if (ret == 2 && !explicit_policy)
220 			return 6;
221 		return ret;
222 		}
223 
224 
225 	/* If we get this far initialize the tree */
226 
227 	tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
228 
229 	if (!tree)
230 		return 0;
231 
232 	tree->flags = 0;
233 	tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
234 	tree->nlevel = 0;
235 	tree->extra_data = NULL;
236 	tree->auth_policies = NULL;
237 	tree->user_policies = NULL;
238 
239 	if (!tree->levels)
240 		{
241 		OPENSSL_free(tree);
242 		return 0;
243 		}
244 
245 	memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
246 
247 	tree->nlevel = n;
248 
249 	level = tree->levels;
250 
251 	/* Root data: initialize to anyPolicy */
252 
253 	data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
254 
255 	if (!data || !level_add_node(level, data, NULL, tree))
256 		goto bad_tree;
257 
258 	for (i = n - 2; i >= 0; i--)
259 		{
260 		level++;
261 		x = sk_X509_value(certs, i);
262 		cache = policy_cache_set(x);
263 		level->cert = X509_up_ref(x);
264 
265 		if (!cache->anyPolicy)
266 				level->flags |= X509_V_FLAG_INHIBIT_ANY;
267 
268 		/* Determine inhibit any and inhibit map flags */
269 		if (any_skip == 0)
270 			{
271 			/* Any matching allowed if certificate is self
272 			 * issued and not the last in the chain.
273 			 */
274 			if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
275 				level->flags |= X509_V_FLAG_INHIBIT_ANY;
276 			}
277 		else
278 			{
279 			if (!(x->ex_flags & EXFLAG_SI))
280 				any_skip--;
281 			if ((cache->any_skip >= 0)
282 				&& (cache->any_skip < any_skip))
283 				any_skip = cache->any_skip;
284 			}
285 
286 		if (map_skip == 0)
287 			level->flags |= X509_V_FLAG_INHIBIT_MAP;
288 		else
289 			{
290 			if (!(x->ex_flags & EXFLAG_SI))
291 				map_skip--;
292 			if ((cache->map_skip >= 0)
293 				&& (cache->map_skip < map_skip))
294 				map_skip = cache->map_skip;
295 			}
296 
297 		}
298 
299 	*ptree = tree;
300 
301 	if (explicit_policy)
302 		return 1;
303 	else
304 		return 5;
305 
306 	bad_tree:
307 
308 	X509_policy_tree_free(tree);
309 
310 	return 0;
311 
312 	}
313 
tree_link_matching_nodes(X509_POLICY_LEVEL * curr,const X509_POLICY_DATA * data)314 static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
315 				const X509_POLICY_DATA *data)
316 	{
317 	X509_POLICY_LEVEL *last = curr - 1;
318 	X509_POLICY_NODE *node;
319 	int matched = 0;
320 	size_t i;
321 	/* Iterate through all in nodes linking matches */
322 	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
323 		{
324 		node = sk_X509_POLICY_NODE_value(last->nodes, i);
325 		if (policy_node_match(last, node, data->valid_policy))
326 			{
327 			if (!level_add_node(curr, data, node, NULL))
328 				return 0;
329 			matched = 1;
330 			}
331 		}
332 	if (!matched && last->anyPolicy)
333 		{
334 		if (!level_add_node(curr, data, last->anyPolicy, NULL))
335 			return 0;
336 		}
337 	return 1;
338 	}
339 
340 /* This corresponds to RFC3280 6.1.3(d)(1):
341  * link any data from CertificatePolicies onto matching parent
342  * or anyPolicy if no match.
343  */
344 
tree_link_nodes(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache)345 static int tree_link_nodes(X509_POLICY_LEVEL *curr,
346 				const X509_POLICY_CACHE *cache)
347 	{
348 	size_t i;
349 	X509_POLICY_DATA *data;
350 
351 	for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
352 		{
353 		data = sk_X509_POLICY_DATA_value(cache->data, i);
354 		/* If a node is mapped any it doesn't have a corresponding
355 		 * CertificatePolicies entry.
356 		 * However such an identical node would be created
357 		 * if anyPolicy matching is enabled because there would be
358 		 * no match with the parent valid_policy_set. So we create
359 		 * link because then it will have the mapping flags
360 		 * right and we can prune it later.
361 		 */
362 #if 0
363 		if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
364 			&& !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
365 			continue;
366 #endif
367 		/* Look for matching nodes in previous level */
368 		if (!tree_link_matching_nodes(curr, data))
369 				return 0;
370 		}
371 	return 1;
372 	}
373 
374 /* This corresponds to RFC3280 6.1.3(d)(2):
375  * Create new data for any unmatched policies in the parent and link
376  * to anyPolicy.
377  */
378 
tree_add_unmatched(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,const ASN1_OBJECT * id,X509_POLICY_NODE * node,X509_POLICY_TREE * tree)379 static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
380 			const X509_POLICY_CACHE *cache,
381 			const ASN1_OBJECT *id,
382 			X509_POLICY_NODE *node,
383 			X509_POLICY_TREE *tree)
384 	{
385 	X509_POLICY_DATA *data;
386 	if (id == NULL)
387 		id = node->data->valid_policy;
388 	/* Create a new node with qualifiers from anyPolicy and
389 	 * id from unmatched node.
390 	 */
391 	data = policy_data_new(NULL, id, node_critical(node));
392 
393 	if (data == NULL)
394 		return 0;
395 	/* Curr may not have anyPolicy */
396 	data->qualifier_set = cache->anyPolicy->qualifier_set;
397 	data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
398 	if (!level_add_node(curr, data, node, tree))
399 		{
400 		policy_data_free(data);
401 		return 0;
402 		}
403 
404 	return 1;
405 	}
406 
tree_link_unmatched(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,X509_POLICY_NODE * node,X509_POLICY_TREE * tree)407 static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
408 			const X509_POLICY_CACHE *cache,
409 			X509_POLICY_NODE *node,
410 			X509_POLICY_TREE *tree)
411 	{
412 	const X509_POLICY_LEVEL *last = curr - 1;
413 	size_t i;
414 
415 	if (	    (last->flags & X509_V_FLAG_INHIBIT_MAP)
416 		|| !(node->data->flags & POLICY_DATA_FLAG_MAPPED))
417 		{
418 		/* If no policy mapping: matched if one child present */
419 		if (node->nchild)
420 			return 1;
421 		if (!tree_add_unmatched(curr, cache, NULL, node, tree))
422 			return 0;
423 		/* Add it */
424 		}
425 	else
426 		{
427 		/* If mapping: matched if one child per expected policy set */
428 		STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
429 		if (node->nchild == sk_ASN1_OBJECT_num(expset))
430 			return 1;
431 		/* Locate unmatched nodes */
432 		for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++)
433 			{
434 			ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
435 			if (level_find_node(curr, node, oid))
436 				continue;
437 			if (!tree_add_unmatched(curr, cache, oid, node, tree))
438 				return 0;
439 			}
440 
441 		}
442 
443 	return 1;
444 
445 	}
446 
tree_link_any(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,X509_POLICY_TREE * tree)447 static int tree_link_any(X509_POLICY_LEVEL *curr,
448 			const X509_POLICY_CACHE *cache,
449 			X509_POLICY_TREE *tree)
450 	{
451 	size_t i;
452 	/*X509_POLICY_DATA *data;*/
453 	X509_POLICY_NODE *node;
454 	X509_POLICY_LEVEL *last = curr - 1;
455 
456 	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
457 		{
458 		node = sk_X509_POLICY_NODE_value(last->nodes, i);
459 
460 		if (!tree_link_unmatched(curr, cache, node, tree))
461 			return 0;
462 
463 #if 0
464 
465 		/* Skip any node with any children: we only want unmathced
466 		 * nodes.
467 		 *
468 		 * Note: need something better for policy mapping
469 		 * because each node may have multiple children
470 		 */
471 		if (node->nchild)
472 			continue;
473 
474 		/* Create a new node with qualifiers from anyPolicy and
475 		 * id from unmatched node.
476 		 */
477 		data = policy_data_new(NULL, node->data->valid_policy,
478 						node_critical(node));
479 
480 		if (data == NULL)
481 			return 0;
482 		/* Curr may not have anyPolicy */
483 		data->qualifier_set = cache->anyPolicy->qualifier_set;
484 		data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
485 		if (!level_add_node(curr, data, node, tree))
486 			{
487 			policy_data_free(data);
488 			return 0;
489 			}
490 
491 #endif
492 
493 		}
494 	/* Finally add link to anyPolicy */
495 	if (last->anyPolicy)
496 		{
497 		if (!level_add_node(curr, cache->anyPolicy,
498 						last->anyPolicy, NULL))
499 			return 0;
500 		}
501 	return 1;
502 	}
503 
504 /* Prune the tree: delete any child mapped child data on the current level
505  * then proceed up the tree deleting any data with no children. If we ever
506  * have no data on a level we can halt because the tree will be empty.
507  */
508 
tree_prune(X509_POLICY_TREE * tree,X509_POLICY_LEVEL * curr)509 static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
510 	{
511 	STACK_OF(X509_POLICY_NODE) *nodes;
512 	X509_POLICY_NODE *node;
513 	int i;
514 	nodes = curr->nodes;
515 	if (curr->flags & X509_V_FLAG_INHIBIT_MAP)
516 		{
517 		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
518 			{
519 			node = sk_X509_POLICY_NODE_value(nodes, i);
520 			/* Delete any mapped data: see RFC3280 XXXX */
521 			if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
522 				{
523 				node->parent->nchild--;
524 				OPENSSL_free(node);
525 				(void)sk_X509_POLICY_NODE_delete(nodes,i);
526 				}
527 			}
528 		}
529 
530 	for(;;)	{
531 		--curr;
532 		nodes = curr->nodes;
533 		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
534 			{
535 			node = sk_X509_POLICY_NODE_value(nodes, i);
536 			if (node->nchild == 0)
537 				{
538 				node->parent->nchild--;
539 				OPENSSL_free(node);
540 				(void)sk_X509_POLICY_NODE_delete(nodes, i);
541 				}
542 			}
543 		if (curr->anyPolicy && !curr->anyPolicy->nchild)
544 			{
545 			if (curr->anyPolicy->parent)
546 				curr->anyPolicy->parent->nchild--;
547 			OPENSSL_free(curr->anyPolicy);
548 			curr->anyPolicy = NULL;
549 			}
550 		if (curr == tree->levels)
551 			{
552 			/* If we zapped anyPolicy at top then tree is empty */
553 			if (!curr->anyPolicy)
554 					return 2;
555 			return 1;
556 			}
557 		}
558 
559 	}
560 
tree_add_auth_node(STACK_OF (X509_POLICY_NODE)** pnodes,X509_POLICY_NODE * pcy)561 static 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 
tree_calculate_authority_set(X509_POLICY_TREE * tree,STACK_OF (X509_POLICY_NODE)** pnodes)589 static 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 
tree_calculate_user_set(X509_POLICY_TREE * tree,STACK_OF (ASN1_OBJECT)* policy_oids,STACK_OF (X509_POLICY_NODE)* auth_nodes)636 static 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 
tree_evaluate(X509_POLICY_TREE * tree)700 static 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 
exnode_free(X509_POLICY_NODE * node)725 static 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 
X509_policy_tree_free(X509_POLICY_TREE * tree)732 void 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 
X509_policy_check(X509_POLICY_TREE ** ptree,int * pexplicit_policy,STACK_OF (X509)* certs,STACK_OF (ASN1_OBJECT)* policy_oids,unsigned int flags)771 int 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