summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509/pcy_tree.c
diff options
context:
space:
mode:
authortb <>2023-04-28 16:21:57 +0000
committertb <>2023-04-28 16:21:57 +0000
commit0f7876e466fed4dad77a738f0bdb63846092d5ef (patch)
treeab7bf11dbba9e8b630f9ced2d33ff8be0eb6049a /src/lib/libcrypto/x509/pcy_tree.c
parent1059b2a4a3d9eb72ad6073bbadee2edc0fd7f990 (diff)
downloadopenbsd-0f7876e466fed4dad77a738f0bdb63846092d5ef.tar.gz
openbsd-0f7876e466fed4dad77a738f0bdb63846092d5ef.tar.bz2
openbsd-0f7876e466fed4dad77a738f0bdb63846092d5ef.zip
Take the old policy code behind the barn
It can go play in the fields with all the other exponential time policy "code". discussed with jsing ok & commit message beck
Diffstat (limited to 'src/lib/libcrypto/x509/pcy_tree.c')
-rw-r--r--src/lib/libcrypto/x509/pcy_tree.c705
1 files changed, 0 insertions, 705 deletions
diff --git a/src/lib/libcrypto/x509/pcy_tree.c b/src/lib/libcrypto/x509/pcy_tree.c
deleted file mode 100644
index 4f253e3cd1..0000000000
--- a/src/lib/libcrypto/x509/pcy_tree.c
+++ /dev/null
@@ -1,705 +0,0 @@
1/* $OpenBSD: pcy_tree.c,v 1.8 2023/04/26 20:43:32 tb 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#ifndef LIBRESSL_HAS_POLICY_DAG
63
64#include "pcy_int.h"
65#include "x509_local.h"
66
67/* Initialize policy tree. Return values:
68 * 0 Some internal error occurred.
69 * -1 Inconsistent or invalid extensions in certificates.
70 * 1 Tree initialized OK.
71 * 2 Policy tree is empty.
72 * 5 Tree OK and requireExplicitPolicy true.
73 * 6 Tree empty and requireExplicitPolicy true.
74 */
75
76static int
77tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, unsigned int flags)
78{
79 X509_POLICY_TREE *tree;
80 X509_POLICY_LEVEL *level;
81 const X509_POLICY_CACHE *cache;
82 X509_POLICY_DATA *data = NULL;
83 X509 *x;
84 int ret = 1;
85 int i, n;
86 int explicit_policy;
87 int any_skip;
88 int map_skip;
89
90 *ptree = NULL;
91 n = sk_X509_num(certs);
92
93 if (flags & X509_V_FLAG_EXPLICIT_POLICY)
94 explicit_policy = 0;
95 else
96 explicit_policy = n + 1;
97
98 if (flags & X509_V_FLAG_INHIBIT_ANY)
99 any_skip = 0;
100 else
101 any_skip = n + 1;
102
103 if (flags & X509_V_FLAG_INHIBIT_MAP)
104 map_skip = 0;
105 else
106 map_skip = n + 1;
107
108 /* Can't do anything with just a trust anchor */
109 if (n == 1)
110 return 1;
111 /* First setup policy cache in all certificates apart from the
112 * trust anchor. Note any bad cache results on the way. Also can
113 * calculate explicit_policy value at this point.
114 */
115 for (i = n - 2; i >= 0; i--) {
116 x = sk_X509_value(certs, i);
117 X509_check_purpose(x, -1, -1);
118 cache = policy_cache_set(x);
119 /* If cache NULL something bad happened: return immediately */
120 if (cache == NULL)
121 return 0;
122 /* If inconsistent extensions keep a note of it but continue */
123 if (x->ex_flags & EXFLAG_INVALID_POLICY)
124 ret = -1;
125 /* Otherwise if we have no data (hence no CertificatePolicies)
126 * and haven't already set an inconsistent code note it.
127 */
128 else if ((ret == 1) && !cache->data)
129 ret = 2;
130 if (explicit_policy > 0) {
131 if (!(x->ex_flags & EXFLAG_SI))
132 explicit_policy--;
133 if ((cache->explicit_skip != -1) &&
134 (cache->explicit_skip < explicit_policy))
135 explicit_policy = cache->explicit_skip;
136 }
137 }
138
139 if (ret != 1) {
140 if (ret == 2 && !explicit_policy)
141 return 6;
142 return ret;
143 }
144
145
146 /* If we get this far initialize the tree */
147
148 tree = malloc(sizeof(X509_POLICY_TREE));
149
150 if (!tree)
151 return 0;
152
153 tree->flags = 0;
154 tree->levels = calloc(n, sizeof(X509_POLICY_LEVEL));
155 tree->nlevel = 0;
156 tree->extra_data = NULL;
157 tree->auth_policies = NULL;
158 tree->user_policies = NULL;
159
160 if (!tree->levels) {
161 free(tree);
162 return 0;
163 }
164
165 tree->nlevel = n;
166
167 level = tree->levels;
168
169 /* Root data: initialize to anyPolicy */
170
171 data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
172
173 if (!data || !level_add_node(level, data, NULL, tree, NULL))
174 goto bad_tree;
175
176 for (i = n - 2; i >= 0; i--) {
177 level++;
178 x = sk_X509_value(certs, i);
179 cache = policy_cache_set(x);
180 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
181 level->cert = x;
182
183 if (!cache->anyPolicy)
184 level->flags |= X509_V_FLAG_INHIBIT_ANY;
185
186 /* Determine inhibit any and inhibit map flags */
187 if (any_skip == 0) {
188 /* Any matching allowed if certificate is self
189 * issued and not the last in the chain.
190 */
191 if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
192 level->flags |= X509_V_FLAG_INHIBIT_ANY;
193 } else {
194 if (!(x->ex_flags & EXFLAG_SI))
195 any_skip--;
196 if ((cache->any_skip >= 0) &&
197 (cache->any_skip < any_skip))
198 any_skip = cache->any_skip;
199 }
200
201 if (map_skip == 0)
202 level->flags |= X509_V_FLAG_INHIBIT_MAP;
203 else {
204 if (!(x->ex_flags & EXFLAG_SI))
205 map_skip--;
206 if ((cache->map_skip >= 0) &&
207 (cache->map_skip < map_skip))
208 map_skip = cache->map_skip;
209 }
210
211 }
212
213 *ptree = tree;
214
215 if (explicit_policy)
216 return 1;
217 else
218 return 5;
219
220bad_tree:
221 X509_policy_tree_free(tree);
222
223 return 0;
224}
225
226static int
227tree_link_matching_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_DATA *data)
228{
229 X509_POLICY_LEVEL *last = curr - 1;
230 X509_POLICY_NODE *node;
231 int i, matched = 0;
232
233 /* Iterate through all in nodes linking matches */
234 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
235 node = sk_X509_POLICY_NODE_value(last->nodes, i);
236 if (policy_node_match(last, node, data->valid_policy)) {
237 if (!level_add_node(curr, data, node, NULL, NULL))
238 return 0;
239 matched = 1;
240 }
241 }
242 if (!matched && last->anyPolicy) {
243 if (!level_add_node(curr, data, last->anyPolicy, NULL, NULL))
244 return 0;
245 }
246 return 1;
247}
248
249/* This corresponds to RFC3280 6.1.3(d)(1):
250 * link any data from CertificatePolicies onto matching parent
251 * or anyPolicy if no match.
252 */
253
254static int
255tree_link_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache)
256{
257 int i;
258 X509_POLICY_DATA *data;
259
260 for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
261 data = sk_X509_POLICY_DATA_value(cache->data, i);
262 /* Look for matching nodes in previous level */
263 if (!tree_link_matching_nodes(curr, data))
264 return 0;
265 }
266 return 1;
267}
268
269/* This corresponds to RFC3280 6.1.3(d)(2):
270 * Create new data for any unmatched policies in the parent and link
271 * to anyPolicy.
272 */
273
274static int
275tree_add_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
276 const ASN1_OBJECT *id, X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
277{
278 X509_POLICY_DATA *data;
279
280 if (id == NULL)
281 id = node->data->valid_policy;
282 /* Create a new node with qualifiers from anyPolicy and
283 * id from unmatched node.
284 */
285 data = policy_data_new(NULL, id, node_critical(node));
286
287 if (data == NULL)
288 return 0;
289 /* Curr may not have anyPolicy */
290 data->qualifier_set = cache->anyPolicy->qualifier_set;
291 data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
292 if (!level_add_node(curr, data, node, tree, NULL)) {
293 policy_data_free(data);
294 return 0;
295 }
296
297 return 1;
298}
299
300static int
301tree_link_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
302 X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
303{
304 const X509_POLICY_LEVEL *last = curr - 1;
305 int i;
306
307 if ((last->flags & X509_V_FLAG_INHIBIT_MAP) ||
308 !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
309 /* If no policy mapping: matched if one child present */
310 if (node->nchild)
311 return 1;
312 if (!tree_add_unmatched(curr, cache, NULL, node, tree))
313 return 0;
314 /* Add it */
315 } else {
316 /* If mapping: matched if one child per expected policy set */
317 STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
318 if (node->nchild == sk_ASN1_OBJECT_num(expset))
319 return 1;
320 /* Locate unmatched nodes */
321 for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
322 ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
323 if (level_find_node(curr, node, oid))
324 continue;
325 if (!tree_add_unmatched(curr, cache, oid, node, tree))
326 return 0;
327 }
328 }
329
330 return 1;
331}
332
333static int
334tree_link_any(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
335 X509_POLICY_TREE *tree)
336{
337 int i;
338 X509_POLICY_NODE *node;
339 X509_POLICY_LEVEL *last = curr - 1;
340
341 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
342 node = sk_X509_POLICY_NODE_value(last->nodes, i);
343
344 if (!tree_link_unmatched(curr, cache, node, tree))
345 return 0;
346 }
347 /* Finally add link to anyPolicy */
348 if (last->anyPolicy) {
349 if (!level_add_node(curr, cache->anyPolicy,
350 last->anyPolicy, NULL, NULL))
351 return 0;
352 }
353 return 1;
354}
355
356/* Prune the tree: delete any child mapped child data on the current level
357 * then proceed up the tree deleting any data with no children. If we ever
358 * have no data on a level we can halt because the tree will be empty.
359 */
360
361static int
362tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
363{
364 STACK_OF(X509_POLICY_NODE) *nodes;
365 X509_POLICY_NODE *node;
366 int i;
367
368 nodes = curr->nodes;
369 if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
370 for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
371 node = sk_X509_POLICY_NODE_value(nodes, i);
372 /* Delete any mapped data: see RFC3280 XXXX */
373 if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
374 node->parent->nchild--;
375 free(node);
376 (void)sk_X509_POLICY_NODE_delete(nodes, i);
377 }
378 }
379 }
380
381 for (;;) {
382 --curr;
383 nodes = curr->nodes;
384 for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
385 node = sk_X509_POLICY_NODE_value(nodes, i);
386 if (node->nchild == 0) {
387 node->parent->nchild--;
388 free(node);
389 (void)sk_X509_POLICY_NODE_delete(nodes, i);
390 }
391 }
392 if (curr->anyPolicy && !curr->anyPolicy->nchild) {
393 if (curr->anyPolicy->parent)
394 curr->anyPolicy->parent->nchild--;
395 free(curr->anyPolicy);
396 curr->anyPolicy = NULL;
397 }
398 if (curr == tree->levels) {
399 /* If we zapped anyPolicy at top then tree is empty */
400 if (!curr->anyPolicy)
401 return 2;
402 return 1;
403 }
404 }
405
406 return 1;
407}
408
409static int
410tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, X509_POLICY_NODE *pcy)
411{
412 if (!*pnodes) {
413 *pnodes = policy_node_cmp_new();
414 if (!*pnodes)
415 return 0;
416 } else if (sk_X509_POLICY_NODE_find(*pnodes, pcy) != -1)
417 return 1;
418
419 if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
420 return 0;
421
422 return 1;
423}
424
425/* Calculate the authority set based on policy tree.
426 * The 'pnodes' parameter is used as a store for the set of policy nodes
427 * used to calculate the user set. If the authority set is not anyPolicy
428 * then pnodes will just point to the authority set. If however the authority
429 * set is anyPolicy then the set of valid policies (other than anyPolicy)
430 * is store in pnodes. The return value of '2' is used in this case to indicate
431 * that pnodes should be freed.
432 */
433
434static int
435tree_calculate_authority_set(X509_POLICY_TREE *tree,
436 STACK_OF(X509_POLICY_NODE) **pnodes)
437{
438 X509_POLICY_LEVEL *curr;
439 X509_POLICY_NODE *node, *anyptr;
440 STACK_OF(X509_POLICY_NODE) **addnodes;
441 int i, j;
442
443 curr = tree->levels + tree->nlevel - 1;
444
445 /* If last level contains anyPolicy set is anyPolicy */
446 if (curr->anyPolicy) {
447 if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
448 return 0;
449 addnodes = pnodes;
450 } else
451 /* Add policies to authority set */
452 addnodes = &tree->auth_policies;
453
454 curr = tree->levels;
455 for (i = 1; i < tree->nlevel; i++) {
456 /* If no anyPolicy node on this this level it can't
457 * appear on lower levels so end search.
458 */
459 if (!(anyptr = curr->anyPolicy))
460 break;
461 curr++;
462 for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
463 node = sk_X509_POLICY_NODE_value(curr->nodes, j);
464 if ((node->parent == anyptr) &&
465 !tree_add_auth_node(addnodes, node))
466 return 0;
467 }
468 }
469
470 if (addnodes == pnodes)
471 return 2;
472
473 *pnodes = tree->auth_policies;
474
475 return 1;
476}
477
478static int
479tree_calculate_user_set(X509_POLICY_TREE *tree,
480 STACK_OF(ASN1_OBJECT) *policy_oids, STACK_OF(X509_POLICY_NODE) *auth_nodes)
481{
482 int i;
483 X509_POLICY_NODE *node;
484 ASN1_OBJECT *oid;
485 X509_POLICY_NODE *anyPolicy;
486 X509_POLICY_DATA *extra;
487
488 /* Check if anyPolicy present in authority constrained policy set:
489 * this will happen if it is a leaf node.
490 */
491
492 if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
493 return 1;
494
495 anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
496
497 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
498 oid = sk_ASN1_OBJECT_value(policy_oids, i);
499 if (OBJ_obj2nid(oid) == NID_any_policy) {
500 tree->flags |= POLICY_FLAG_ANY_POLICY;
501 return 1;
502 }
503 }
504
505 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
506 oid = sk_ASN1_OBJECT_value(policy_oids, i);
507 node = tree_find_sk(auth_nodes, oid);
508 if (!node) {
509 if (!anyPolicy)
510 continue;
511 /* Create a new node with policy ID from user set
512 * and qualifiers from anyPolicy.
513 */
514 extra = policy_data_new(NULL, oid,
515 node_critical(anyPolicy));
516 if (!extra)
517 return 0;
518 extra->qualifier_set = anyPolicy->data->qualifier_set;
519 extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS |
520 POLICY_DATA_FLAG_EXTRA_NODE;
521 (void) level_add_node(NULL, extra, anyPolicy->parent,
522 tree, &node);
523 }
524 if (!tree->user_policies) {
525 tree->user_policies = sk_X509_POLICY_NODE_new_null();
526 if (!tree->user_policies)
527 return 1;
528 }
529 if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
530 return 0;
531 }
532 return 1;
533}
534
535static int
536tree_evaluate(X509_POLICY_TREE *tree)
537{
538 int ret, i;
539 X509_POLICY_LEVEL *curr = tree->levels + 1;
540 const X509_POLICY_CACHE *cache;
541
542 for (i = 1; i < tree->nlevel; i++, curr++) {
543 cache = policy_cache_set(curr->cert);
544 if (!tree_link_nodes(curr, cache))
545 return 0;
546
547 if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) &&
548 !tree_link_any(curr, cache, tree))
549 return 0;
550 ret = tree_prune(tree, curr);
551 if (ret != 1)
552 return ret;
553 }
554
555 return 1;
556}
557
558static void
559exnode_free(X509_POLICY_NODE *node)
560{
561 if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
562 free(node);
563}
564
565void
566X509_policy_tree_free(X509_POLICY_TREE *tree)
567{
568 X509_POLICY_LEVEL *curr;
569 int i;
570
571 if (!tree)
572 return;
573
574 sk_X509_POLICY_NODE_free(tree->auth_policies);
575 sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
576
577 for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
578 X509_free(curr->cert);
579 if (curr->nodes)
580 sk_X509_POLICY_NODE_pop_free(curr->nodes,
581 policy_node_free);
582 if (curr->anyPolicy)
583 policy_node_free(curr->anyPolicy);
584 }
585
586 if (tree->extra_data)
587 sk_X509_POLICY_DATA_pop_free(tree->extra_data,
588 policy_data_free);
589
590 free(tree->levels);
591 free(tree);
592}
593LCRYPTO_ALIAS(X509_policy_tree_free);
594
595/* Application policy checking function.
596 * Return codes:
597 * 0 Internal Error.
598 * 1 Successful.
599 * -1 One or more certificates contain invalid or inconsistent extensions
600 * -2 User constrained policy set empty and requireExplicit true.
601 */
602
603int
604X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
605 STACK_OF(X509) *certs, STACK_OF(ASN1_OBJECT) *policy_oids,
606 unsigned int flags)
607{
608 int ret, ret2;
609 X509_POLICY_TREE *tree = NULL;
610 STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
611
612 *ptree = NULL;
613 *pexplicit_policy = 0;
614 ret = tree_init(&tree, certs, flags);
615
616 switch (ret) {
617
618 /* Tree empty requireExplicit False: OK */
619 case 2:
620 return 1;
621
622 /* Some internal error */
623 case -1:
624 return -1;
625
626 /* Some internal error */
627 case 0:
628 return 0;
629
630 /* Tree empty requireExplicit True: Error */
631
632 case 6:
633 *pexplicit_policy = 1;
634 return -2;
635
636 /* Tree OK requireExplicit True: OK and continue */
637 case 5:
638 *pexplicit_policy = 1;
639 break;
640
641 /* Tree OK: continue */
642
643 case 1:
644 if (!tree)
645 /*
646 * tree_init() returns success and a null tree
647 * if it's just looking at a trust anchor.
648 * I'm not sure that returning success here is
649 * correct, but I'm sure that reporting this
650 * as an internal error which our caller
651 * interprets as a malloc failure is wrong.
652 */
653 return 1;
654 break;
655 }
656
657 if (!tree)
658 goto error;
659 ret = tree_evaluate(tree);
660 if (ret <= 0)
661 goto error;
662
663 /* Return value 2 means tree empty */
664 if (ret == 2) {
665 X509_policy_tree_free(tree);
666 if (*pexplicit_policy)
667 return -2;
668 else
669 return 1;
670 }
671
672 /* Tree is not empty: continue */
673
674 ret = tree_calculate_authority_set(tree, &auth_nodes);
675 if (ret == 0)
676 goto error;
677
678 ret2 = tree_calculate_user_set(tree, policy_oids, auth_nodes);
679
680 /* Return value 2 means auth_nodes needs to be freed */
681 if (ret == 2)
682 sk_X509_POLICY_NODE_free(auth_nodes);
683
684 if (ret2 == 0)
685 goto error;
686
687 if (tree)
688 *ptree = tree;
689
690 if (*pexplicit_policy) {
691 nodes = X509_policy_tree_get0_user_policies(tree);
692 if (sk_X509_POLICY_NODE_num(nodes) <= 0)
693 return -2;
694 }
695
696 return 1;
697
698error:
699 X509_policy_tree_free(tree);
700
701 return 0;
702}
703LCRYPTO_ALIAS(X509_policy_check);
704
705#endif /* LIBRESSL_HAS_POLICY_DAG */