GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/x509v3/pcy_tree.c Lines: 0 281 0.0 %
Date: 2016-12-06 Branches: 0 225 0.0 %

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