• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include "internal/cryptlib.h"
11 #include <openssl/x509.h>
12 #include <openssl/x509v3.h>
13 
14 #include "pcy_local.h"
15 
16 /*
17  * If the maximum number of nodes in the policy tree isn't defined, set it to
18  * a generous default of 1000 nodes.
19  *
20  * Defining this to be zero means unlimited policy tree growth which opens the
21  * door on CVE-2023-0464.
22  */
23 
24 #ifndef OPENSSL_POLICY_TREE_NODES_MAX
25 # define OPENSSL_POLICY_TREE_NODES_MAX 1000
26 #endif
27 
28 /*
29  * Enable this to print out the complete policy tree at various point during
30  * evaluation.
31  */
32 
33 /*
34  * #define OPENSSL_POLICY_DEBUG
35  */
36 
37 #ifdef OPENSSL_POLICY_DEBUG
38 
expected_print(BIO * err,X509_POLICY_LEVEL * lev,X509_POLICY_NODE * node,int indent)39 static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
40                            X509_POLICY_NODE *node, int indent)
41 {
42     if ((lev->flags & X509_V_FLAG_INHIBIT_MAP)
43         || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
44         BIO_puts(err, "  Not Mapped\n");
45     else {
46         int i;
47         STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
48         ASN1_OBJECT *oid;
49         BIO_puts(err, "  Expected: ");
50         for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) {
51             oid = sk_ASN1_OBJECT_value(pset, i);
52             if (i)
53                 BIO_puts(err, ", ");
54             i2a_ASN1_OBJECT(err, oid);
55         }
56         BIO_puts(err, "\n");
57     }
58 }
59 
tree_print(char * str,X509_POLICY_TREE * tree,X509_POLICY_LEVEL * curr)60 static void tree_print(char *str, X509_POLICY_TREE *tree,
61                        X509_POLICY_LEVEL *curr)
62 {
63     BIO *err = BIO_new_fp(stderr, BIO_NOCLOSE);
64     X509_POLICY_LEVEL *plev;
65 
66     if (err == NULL)
67         return;
68     if (!curr)
69         curr = tree->levels + tree->nlevel;
70     else
71         curr++;
72 
73     BIO_printf(err, "Level print after %s\n", str);
74     BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
75     for (plev = tree->levels; plev != curr; plev++) {
76         int i;
77 
78         BIO_printf(err, "Level %ld, flags = %x\n",
79                    (long)(plev - tree->levels), plev->flags);
80         for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
81             X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(plev->nodes, i);
82 
83             X509_POLICY_NODE_print(err, node, 2);
84             expected_print(err, plev, node, 2);
85             BIO_printf(err, "  Flags: %x\n", node->data->flags);
86         }
87         if (plev->anyPolicy)
88             X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
89     }
90     BIO_free(err);
91 }
92 #endif
93 
94 /*-
95  * Return value: <= 0 on error, or positive bit mask:
96  *
97  * X509_PCY_TREE_VALID: valid tree
98  * X509_PCY_TREE_EMPTY: empty tree (including bare TA case)
99  * X509_PCY_TREE_EXPLICIT: explicit policy required
100  */
tree_init(X509_POLICY_TREE ** ptree,STACK_OF (X509)* certs,unsigned int flags)101 static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
102                      unsigned int flags)
103 {
104     X509_POLICY_TREE *tree;
105     X509_POLICY_LEVEL *level;
106     const X509_POLICY_CACHE *cache;
107     X509_POLICY_DATA *data = NULL;
108     int ret = X509_PCY_TREE_VALID;
109     int n = sk_X509_num(certs) - 1; /* RFC5280 paths omit the TA */
110     int explicit_policy = (flags & X509_V_FLAG_EXPLICIT_POLICY) ? 0 : n+1;
111     int any_skip = (flags & X509_V_FLAG_INHIBIT_ANY) ? 0 : n+1;
112     int map_skip = (flags & X509_V_FLAG_INHIBIT_MAP) ? 0 : n+1;
113     int i;
114 
115     *ptree = NULL;
116 
117     /* Can't do anything with just a trust anchor */
118     if (n == 0)
119         return X509_PCY_TREE_EMPTY;
120 
121     /*
122      * First setup the policy cache in all n non-TA certificates, this will be
123      * used in X509_verify_cert() which will invoke the verify callback for all
124      * certificates with invalid policy extensions.
125      */
126     for (i = n - 1; i >= 0; i--) {
127         X509 *x = sk_X509_value(certs, i);
128 
129         /* Call for side-effect of computing hash and caching extensions */
130         X509_check_purpose(x, -1, 0);
131 
132         /* If cache is NULL, likely ENOMEM: return immediately */
133         if (policy_cache_set(x) == NULL)
134             return X509_PCY_TREE_INTERNAL;
135     }
136 
137     /*
138      * At this point check for invalid policies and required explicit policy.
139      * Note that the explicit_policy counter is a count-down to zero, with the
140      * requirement kicking in if and once it does that.  The counter is
141      * decremented for every non-self-issued certificate in the path, but may
142      * be further reduced by policy constraints in a non-leaf certificate.
143      *
144      * The ultimate policy set is the intersection of all the policies along
145      * the path, if we hit a certificate with an empty policy set, and explicit
146      * policy is required we're done.
147      */
148     for (i = n - 1;
149          i >= 0 && (explicit_policy > 0 || (ret & X509_PCY_TREE_EMPTY) == 0);
150          i--) {
151         X509 *x = sk_X509_value(certs, i);
152         uint32_t ex_flags = X509_get_extension_flags(x);
153 
154         /* All the policies are already cached, we can return early */
155         if (ex_flags & EXFLAG_INVALID_POLICY)
156             return X509_PCY_TREE_INVALID;
157 
158         /* Access the cache which we now know exists */
159         cache = policy_cache_set(x);
160 
161         if ((ret & X509_PCY_TREE_VALID) && cache->data == NULL)
162             ret = X509_PCY_TREE_EMPTY;
163         if (explicit_policy > 0) {
164             if (!(ex_flags & EXFLAG_SI))
165                 explicit_policy--;
166             if ((cache->explicit_skip >= 0)
167                 && (cache->explicit_skip < explicit_policy))
168                 explicit_policy = cache->explicit_skip;
169         }
170     }
171 
172     if (explicit_policy == 0)
173         ret |= X509_PCY_TREE_EXPLICIT;
174     if ((ret & X509_PCY_TREE_VALID) == 0)
175         return ret;
176 
177     /* If we get this far initialize the tree */
178     if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) {
179         X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
180         return X509_PCY_TREE_INTERNAL;
181     }
182 
183     /* Limit the growth of the tree to mitigate CVE-2023-0464 */
184     tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX;
185 
186     /*
187      * http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
188      *
189      * The top level is implicitly for the trust anchor with valid expected
190      * policies of anyPolicy.  (RFC 5280 has the TA at depth 0 and the leaf at
191      * depth n, we have the leaf at depth 0 and the TA at depth n).
192      */
193     if ((tree->levels = OPENSSL_zalloc(sizeof(*tree->levels)*(n+1))) == NULL) {
194         OPENSSL_free(tree);
195         X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
196         return X509_PCY_TREE_INTERNAL;
197     }
198     tree->nlevel = n+1;
199     level = tree->levels;
200     if ((data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0)) == NULL)
201         goto bad_tree;
202     if (level_add_node(level, data, NULL, tree, 1) == NULL) {
203         policy_data_free(data);
204         goto bad_tree;
205     }
206 
207     /*
208      * In this pass initialize all the tree levels and whether anyPolicy and
209      * policy mapping are inhibited at each level.
210      */
211     for (i = n - 1; i >= 0; i--) {
212         X509 *x = sk_X509_value(certs, i);
213         uint32_t ex_flags = X509_get_extension_flags(x);
214 
215         /* Access the cache which we now know exists */
216         cache = policy_cache_set(x);
217 
218         X509_up_ref(x);
219         (++level)->cert = x;
220 
221         if (!cache->anyPolicy)
222             level->flags |= X509_V_FLAG_INHIBIT_ANY;
223 
224         /* Determine inhibit any and inhibit map flags */
225         if (any_skip == 0) {
226             /*
227              * Any matching allowed only if certificate is self issued and not
228              * the last in the chain.
229              */
230             if (!(ex_flags & EXFLAG_SI) || (i == 0))
231                 level->flags |= X509_V_FLAG_INHIBIT_ANY;
232         } else {
233             if (!(ex_flags & EXFLAG_SI))
234                 any_skip--;
235             if ((cache->any_skip >= 0) && (cache->any_skip < any_skip))
236                 any_skip = cache->any_skip;
237         }
238 
239         if (map_skip == 0)
240             level->flags |= X509_V_FLAG_INHIBIT_MAP;
241         else {
242             if (!(ex_flags & EXFLAG_SI))
243                 map_skip--;
244             if ((cache->map_skip >= 0) && (cache->map_skip < map_skip))
245                 map_skip = cache->map_skip;
246         }
247     }
248 
249     *ptree = tree;
250     return ret;
251 
252  bad_tree:
253     X509_policy_tree_free(tree);
254     return X509_PCY_TREE_INTERNAL;
255 }
256 
257 /*
258  * Return value: 1 on success, 0 otherwise
259  */
tree_link_matching_nodes(X509_POLICY_LEVEL * curr,X509_POLICY_DATA * data,X509_POLICY_TREE * tree)260 static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
261                                     X509_POLICY_DATA *data,
262                                     X509_POLICY_TREE *tree)
263 {
264     X509_POLICY_LEVEL *last = curr - 1;
265     int i, matched = 0;
266 
267     /* Iterate through all in nodes linking matches */
268     for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
269         X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i);
270 
271         if (policy_node_match(last, node, data->valid_policy)) {
272             if (level_add_node(curr, data, node, tree, 0) == NULL)
273                 return 0;
274             matched = 1;
275         }
276     }
277     if (!matched && last->anyPolicy) {
278         if (level_add_node(curr, data, last->anyPolicy, tree, 0) == NULL)
279             return 0;
280     }
281     return 1;
282 }
283 
284 /*
285  * This corresponds to RFC3280 6.1.3(d)(1): link any data from
286  * CertificatePolicies onto matching parent or anyPolicy if no match.
287  *
288  * Return value: 1 on success, 0 otherwise.
289  */
tree_link_nodes(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,X509_POLICY_TREE * tree)290 static int tree_link_nodes(X509_POLICY_LEVEL *curr,
291                            const X509_POLICY_CACHE *cache,
292                            X509_POLICY_TREE *tree)
293 {
294     int i;
295 
296     for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
297         X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i);
298 
299         /* Look for matching nodes in previous level */
300         if (!tree_link_matching_nodes(curr, data, tree))
301             return 0;
302     }
303     return 1;
304 }
305 
306 /*
307  * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched
308  * policies in the parent and link to anyPolicy.
309  *
310  * Return value: 1 on success, 0 otherwise.
311  */
tree_add_unmatched(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,const ASN1_OBJECT * id,X509_POLICY_NODE * node,X509_POLICY_TREE * tree)312 static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
313                               const X509_POLICY_CACHE *cache,
314                               const ASN1_OBJECT *id,
315                               X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
316 {
317     X509_POLICY_DATA *data;
318 
319     if (id == NULL)
320         id = node->data->valid_policy;
321     /*
322      * Create a new node with qualifiers from anyPolicy and id from unmatched
323      * node.
324      */
325     if ((data = policy_data_new(NULL, id, node_critical(node))) == NULL)
326         return 0;
327 
328     /* Curr may not have anyPolicy */
329     data->qualifier_set = cache->anyPolicy->qualifier_set;
330     data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
331     if (level_add_node(curr, data, node, tree, 1) == NULL) {
332         policy_data_free(data);
333         return 0;
334     }
335     return 1;
336 }
337 
338 /*
339  * Return value: 1 on success, 0 otherwise.
340  */
tree_link_unmatched(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,X509_POLICY_NODE * node,X509_POLICY_TREE * tree)341 static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
342                                const X509_POLICY_CACHE *cache,
343                                X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
344 {
345     const X509_POLICY_LEVEL *last = curr - 1;
346     int i;
347 
348     if ((last->flags & X509_V_FLAG_INHIBIT_MAP)
349         || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
350         /* If no policy mapping: matched if one child present */
351         if (node->nchild)
352             return 1;
353         if (!tree_add_unmatched(curr, cache, NULL, node, tree))
354             return 0;
355         /* Add it */
356     } else {
357         /* If mapping: matched if one child per expected policy set */
358         STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
359         if (node->nchild == sk_ASN1_OBJECT_num(expset))
360             return 1;
361         /* Locate unmatched nodes */
362         for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
363             ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
364             if (level_find_node(curr, node, oid))
365                 continue;
366             if (!tree_add_unmatched(curr, cache, oid, node, tree))
367                 return 0;
368         }
369 
370     }
371     return 1;
372 }
373 
374 /*
375  * Return value: 1 on success, 0 otherwise
376  */
tree_link_any(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,X509_POLICY_TREE * tree)377 static int tree_link_any(X509_POLICY_LEVEL *curr,
378                          const X509_POLICY_CACHE *cache,
379                          X509_POLICY_TREE *tree)
380 {
381     int i;
382     X509_POLICY_NODE *node;
383     X509_POLICY_LEVEL *last = curr - 1;
384 
385     for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
386         node = sk_X509_POLICY_NODE_value(last->nodes, i);
387 
388         if (!tree_link_unmatched(curr, cache, node, tree))
389             return 0;
390     }
391     /* Finally add link to anyPolicy */
392     if (last->anyPolicy &&
393         level_add_node(curr, cache->anyPolicy, last->anyPolicy, tree, 0) == NULL)
394         return 0;
395     return 1;
396 }
397 
398 /*-
399  * Prune the tree: delete any child mapped child data on the current level then
400  * proceed up the tree deleting any data with no children. If we ever have no
401  * data on a level we can halt because the tree will be empty.
402  *
403  * Return value: <= 0 error, otherwise one of:
404  *
405  * X509_PCY_TREE_VALID: valid tree
406  * X509_PCY_TREE_EMPTY: empty tree
407  */
tree_prune(X509_POLICY_TREE * tree,X509_POLICY_LEVEL * curr)408 static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
409 {
410     STACK_OF(X509_POLICY_NODE) *nodes;
411     X509_POLICY_NODE *node;
412     int i;
413     nodes = curr->nodes;
414     if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
415         for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
416             node = sk_X509_POLICY_NODE_value(nodes, i);
417             /* Delete any mapped data: see RFC3280 XXXX */
418             if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
419                 node->parent->nchild--;
420                 OPENSSL_free(node);
421                 (void)sk_X509_POLICY_NODE_delete(nodes, i);
422             }
423         }
424     }
425 
426     for (;;) {
427         --curr;
428         nodes = curr->nodes;
429         for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
430             node = sk_X509_POLICY_NODE_value(nodes, i);
431             if (node->nchild == 0) {
432                 node->parent->nchild--;
433                 OPENSSL_free(node);
434                 (void)sk_X509_POLICY_NODE_delete(nodes, i);
435             }
436         }
437         if (curr->anyPolicy && !curr->anyPolicy->nchild) {
438             if (curr->anyPolicy->parent)
439                 curr->anyPolicy->parent->nchild--;
440             OPENSSL_free(curr->anyPolicy);
441             curr->anyPolicy = NULL;
442         }
443         if (curr == tree->levels) {
444             /* If we zapped anyPolicy at top then tree is empty */
445             if (!curr->anyPolicy)
446                 return X509_PCY_TREE_EMPTY;
447             break;
448         }
449     }
450     return X509_PCY_TREE_VALID;
451 }
452 
453 /*
454  * Return value: 1 on success, 0 otherwise.
455  */
tree_add_auth_node(STACK_OF (X509_POLICY_NODE)** pnodes,X509_POLICY_NODE * pcy)456 static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
457                               X509_POLICY_NODE *pcy)
458 {
459     if (*pnodes == NULL &&
460         (*pnodes = policy_node_cmp_new()) == NULL)
461         return 0;
462     if (sk_X509_POLICY_NODE_find(*pnodes, pcy) >= 0)
463         return 1;
464     return sk_X509_POLICY_NODE_push(*pnodes, pcy) != 0;
465 }
466 
467 #define TREE_CALC_FAILURE 0
468 #define TREE_CALC_OK_NOFREE 1
469 #define TREE_CALC_OK_DOFREE 2
470 
471 /*-
472  * Calculate the authority set based on policy tree. The 'pnodes' parameter is
473  * used as a store for the set of policy nodes used to calculate the user set.
474  * If the authority set is not anyPolicy then pnodes will just point to the
475  * authority set. If however the authority set is anyPolicy then the set of
476  * valid policies (other than anyPolicy) is store in pnodes.
477  *
478  * Return value:
479  *  TREE_CALC_FAILURE on failure,
480  *  TREE_CALC_OK_NOFREE on success and pnodes need not be freed,
481  *  TREE_CALC_OK_DOFREE on success and pnodes needs to be freed
482  */
tree_calculate_authority_set(X509_POLICY_TREE * tree,STACK_OF (X509_POLICY_NODE)** pnodes)483 static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
484                                         STACK_OF(X509_POLICY_NODE) **pnodes)
485 {
486     X509_POLICY_LEVEL *curr;
487     X509_POLICY_NODE *node, *anyptr;
488     STACK_OF(X509_POLICY_NODE) **addnodes;
489     int i, j;
490     curr = tree->levels + tree->nlevel - 1;
491 
492     /* If last level contains anyPolicy set is anyPolicy */
493     if (curr->anyPolicy) {
494         if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
495             return TREE_CALC_FAILURE;
496         addnodes = pnodes;
497     } else
498         /* Add policies to authority set */
499         addnodes = &tree->auth_policies;
500 
501     curr = tree->levels;
502     for (i = 1; i < tree->nlevel; i++) {
503         /*
504          * If no anyPolicy node on this this level it can't appear on lower
505          * levels so end search.
506          */
507         if ((anyptr = curr->anyPolicy) == NULL)
508             break;
509         curr++;
510         for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
511             node = sk_X509_POLICY_NODE_value(curr->nodes, j);
512             if ((node->parent == anyptr)
513                 && !tree_add_auth_node(addnodes, node)) {
514                 if (addnodes == pnodes) {
515                     sk_X509_POLICY_NODE_free(*pnodes);
516                     *pnodes = NULL;
517                 }
518                 return TREE_CALC_FAILURE;
519             }
520         }
521     }
522     if (addnodes == pnodes)
523         return TREE_CALC_OK_DOFREE;
524 
525     *pnodes = tree->auth_policies;
526     return TREE_CALC_OK_NOFREE;
527 }
528 
529 /*
530  * Return value: 1 on success, 0 otherwise.
531  */
tree_calculate_user_set(X509_POLICY_TREE * tree,STACK_OF (ASN1_OBJECT)* policy_oids,STACK_OF (X509_POLICY_NODE)* auth_nodes)532 static int tree_calculate_user_set(X509_POLICY_TREE *tree,
533                                    STACK_OF(ASN1_OBJECT) *policy_oids,
534                                    STACK_OF(X509_POLICY_NODE) *auth_nodes)
535 {
536     int i;
537     X509_POLICY_NODE *node;
538     ASN1_OBJECT *oid;
539     X509_POLICY_NODE *anyPolicy;
540     X509_POLICY_DATA *extra;
541 
542     /*
543      * Check if anyPolicy present in authority constrained policy set: this
544      * will happen if it is a leaf node.
545      */
546     if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
547         return 1;
548 
549     anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
550 
551     for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
552         oid = sk_ASN1_OBJECT_value(policy_oids, i);
553         if (OBJ_obj2nid(oid) == NID_any_policy) {
554             tree->flags |= POLICY_FLAG_ANY_POLICY;
555             return 1;
556         }
557     }
558 
559     for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
560         oid = sk_ASN1_OBJECT_value(policy_oids, i);
561         node = tree_find_sk(auth_nodes, oid);
562         if (!node) {
563             if (!anyPolicy)
564                 continue;
565             /*
566              * Create a new node with policy ID from user set and qualifiers
567              * from anyPolicy.
568              */
569             extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
570             if (extra == NULL)
571                 return 0;
572             extra->qualifier_set = anyPolicy->data->qualifier_set;
573             extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
574                 | POLICY_DATA_FLAG_EXTRA_NODE;
575             node = level_add_node(NULL, extra, anyPolicy->parent, tree, 1);
576         }
577         if (!tree->user_policies) {
578             tree->user_policies = sk_X509_POLICY_NODE_new_null();
579             if (!tree->user_policies)
580                 return 1;
581         }
582         if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
583             return 0;
584     }
585     return 1;
586 }
587 
588 /*-
589  * Return value: <= 0 error, otherwise one of:
590  *  X509_PCY_TREE_VALID: valid tree
591  *  X509_PCY_TREE_EMPTY: empty tree
592  * (see tree_prune()).
593  */
tree_evaluate(X509_POLICY_TREE * tree)594 static int tree_evaluate(X509_POLICY_TREE *tree)
595 {
596     int ret, i;
597     X509_POLICY_LEVEL *curr = tree->levels + 1;
598     const X509_POLICY_CACHE *cache;
599 
600     for (i = 1; i < tree->nlevel; i++, curr++) {
601         cache = policy_cache_set(curr->cert);
602         if (!tree_link_nodes(curr, cache, tree))
603             return X509_PCY_TREE_INTERNAL;
604 
605         if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
606             && !tree_link_any(curr, cache, tree))
607             return X509_PCY_TREE_INTERNAL;
608 #ifdef OPENSSL_POLICY_DEBUG
609         tree_print("before tree_prune()", tree, curr);
610 #endif
611         ret = tree_prune(tree, curr);
612         if (ret != X509_PCY_TREE_VALID)
613             return ret;
614     }
615     return X509_PCY_TREE_VALID;
616 }
617 
exnode_free(X509_POLICY_NODE * node)618 static void exnode_free(X509_POLICY_NODE *node)
619 {
620     if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
621         OPENSSL_free(node);
622 }
623 
X509_policy_tree_free(X509_POLICY_TREE * tree)624 void X509_policy_tree_free(X509_POLICY_TREE *tree)
625 {
626     X509_POLICY_LEVEL *curr;
627     int i;
628 
629     if (!tree)
630         return;
631 
632     sk_X509_POLICY_NODE_free(tree->auth_policies);
633     sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
634 
635     for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
636         X509_free(curr->cert);
637         sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free);
638         policy_node_free(curr->anyPolicy);
639     }
640 
641     sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
642     OPENSSL_free(tree->levels);
643     OPENSSL_free(tree);
644 
645 }
646 
647 /*-
648  * Application policy checking function.
649  * Return codes:
650  *  X509_PCY_TREE_FAILURE:  Failure to satisfy explicit policy
651  *  X509_PCY_TREE_INVALID:  Inconsistent or invalid extensions
652  *  X509_PCY_TREE_INTERNAL: Internal error, most likely malloc
653  *  X509_PCY_TREE_VALID:    Success (null tree if empty or bare TA)
654  */
X509_policy_check(X509_POLICY_TREE ** ptree,int * pexplicit_policy,STACK_OF (X509)* certs,STACK_OF (ASN1_OBJECT)* policy_oids,unsigned int flags)655 int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
656                       STACK_OF(X509) *certs,
657                       STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
658 {
659     int init_ret;
660     int ret;
661     int calc_ret;
662     X509_POLICY_TREE *tree = NULL;
663     STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
664 
665     *ptree = NULL;
666     *pexplicit_policy = 0;
667     init_ret = tree_init(&tree, certs, flags);
668 
669     if (init_ret <= 0)
670         return init_ret;
671 
672     if ((init_ret & X509_PCY_TREE_EXPLICIT) == 0) {
673         if (init_ret & X509_PCY_TREE_EMPTY) {
674             X509_policy_tree_free(tree);
675             return X509_PCY_TREE_VALID;
676         }
677     } else {
678         *pexplicit_policy = 1;
679         /* Tree empty and requireExplicit True: Error */
680         if (init_ret & X509_PCY_TREE_EMPTY)
681             return X509_PCY_TREE_FAILURE;
682     }
683 
684     ret = tree_evaluate(tree);
685 #ifdef OPENSSL_POLICY_DEBUG
686     tree_print("tree_evaluate()", tree, NULL);
687 #endif
688     if (ret <= 0)
689         goto error;
690 
691     if (ret == X509_PCY_TREE_EMPTY) {
692         X509_policy_tree_free(tree);
693         if (init_ret & X509_PCY_TREE_EXPLICIT)
694             return X509_PCY_TREE_FAILURE;
695         return X509_PCY_TREE_VALID;
696     }
697 
698     /* Tree is not empty: continue */
699 
700     if ((calc_ret = tree_calculate_authority_set(tree, &auth_nodes)) == 0)
701         goto error;
702     ret = tree_calculate_user_set(tree, policy_oids, auth_nodes);
703     if (calc_ret == TREE_CALC_OK_DOFREE)
704         sk_X509_POLICY_NODE_free(auth_nodes);
705     if (!ret)
706         goto error;
707 
708     *ptree = tree;
709 
710     if (init_ret & X509_PCY_TREE_EXPLICIT) {
711         nodes = X509_policy_tree_get0_user_policies(tree);
712         if (sk_X509_POLICY_NODE_num(nodes) <= 0)
713             return X509_PCY_TREE_FAILURE;
714     }
715     return X509_PCY_TREE_VALID;
716 
717  error:
718     X509_policy_tree_free(tree);
719     return X509_PCY_TREE_INTERNAL;
720 }
721