• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3  * 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 <string.h>
60 
61 #include <openssl/mem.h>
62 #include <openssl/obj.h>
63 #include <openssl/stack.h>
64 #include <openssl/thread.h>
65 #include <openssl/x509.h>
66 #include <openssl/x509v3.h>
67 
68 #include "pcy_int.h"
69 #include "../internal.h"
70 
71 /*
72  * Enable this to print out the complete policy tree at various point during
73  * evaluation.
74  */
75 
76 /*
77  * #define OPENSSL_POLICY_DEBUG
78  */
79 
80 #ifdef OPENSSL_POLICY_DEBUG
81 
expected_print(BIO * err,X509_POLICY_LEVEL * lev,X509_POLICY_NODE * node,int indent)82 static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
83                            X509_POLICY_NODE *node, int indent)
84 {
85     if ((lev->flags & X509_V_FLAG_INHIBIT_MAP)
86         || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
87         BIO_puts(err, "  Not Mapped\n");
88     else {
89         int i;
90         STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
91         ASN1_OBJECT *oid;
92         BIO_puts(err, "  Expected: ");
93         for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) {
94             oid = sk_ASN1_OBJECT_value(pset, i);
95             if (i)
96                 BIO_puts(err, ", ");
97             i2a_ASN1_OBJECT(err, oid);
98         }
99         BIO_puts(err, "\n");
100     }
101 }
102 
tree_print(char * str,X509_POLICY_TREE * tree,X509_POLICY_LEVEL * curr)103 static void tree_print(char *str, X509_POLICY_TREE *tree,
104                        X509_POLICY_LEVEL *curr)
105 {
106     X509_POLICY_LEVEL *plev;
107     X509_POLICY_NODE *node;
108     int i;
109     BIO *err;
110     err = BIO_new_fp(stderr, BIO_NOCLOSE);
111     if (!curr)
112         curr = tree->levels + tree->nlevel;
113     else
114         curr++;
115     BIO_printf(err, "Level print after %s\n", str);
116     BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
117     for (plev = tree->levels; plev != curr; plev++) {
118         BIO_printf(err, "Level %ld, flags = %x\n",
119                    plev - tree->levels, plev->flags);
120         for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
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 /*-
140  * Initialize policy tree. Return values:
141  *  0 Some internal error occurred.
142  * -1 Inconsistent or invalid extensions in certificates.
143  *  1 Tree initialized OK.
144  *  2 Policy tree is empty.
145  *  5 Tree OK and requireExplicitPolicy true.
146  *  6 Tree empty and requireExplicitPolicy true.
147  */
148 
tree_init(X509_POLICY_TREE ** ptree,STACK_OF (X509)* certs,unsigned int flags)149 static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
150                      unsigned int flags)
151 {
152     X509_POLICY_TREE *tree;
153     X509_POLICY_LEVEL *level;
154     const X509_POLICY_CACHE *cache;
155     X509_POLICY_DATA *data = NULL;
156     X509 *x;
157     int ret = 1;
158     int i, n;
159     int explicit_policy;
160     int any_skip;
161     int map_skip;
162     *ptree = NULL;
163     n = sk_X509_num(certs);
164 
165 #if 0
166     /* Disable policy mapping for now... */
167     flags |= X509_V_FLAG_INHIBIT_MAP;
168 #endif
169 
170     if (flags & X509_V_FLAG_EXPLICIT_POLICY)
171         explicit_policy = 0;
172     else
173         explicit_policy = n + 1;
174 
175     if (flags & X509_V_FLAG_INHIBIT_ANY)
176         any_skip = 0;
177     else
178         any_skip = n + 1;
179 
180     if (flags & X509_V_FLAG_INHIBIT_MAP)
181         map_skip = 0;
182     else
183         map_skip = n + 1;
184 
185     /* Can't do anything with just a trust anchor */
186     if (n == 1)
187         return 1;
188     /*
189      * First setup policy cache in all certificates apart from the trust
190      * anchor. Note any bad cache results on the way. Also can calculate
191      * explicit_policy value at this point.
192      */
193     for (i = n - 2; i >= 0; i--) {
194         x = sk_X509_value(certs, i);
195         X509_check_purpose(x, -1, -1);
196         cache = policy_cache_set(x);
197         /* If cache NULL something bad happened: return immediately */
198         if (cache == NULL)
199             return 0;
200         /*
201          * If inconsistent extensions keep a note of it but continue
202          */
203         if (x->ex_flags & EXFLAG_INVALID_POLICY)
204             ret = -1;
205         /*
206          * Otherwise if we have no data (hence no CertificatePolicies) and
207          * haven't already set an inconsistent code note it.
208          */
209         else if ((ret == 1) && !cache->data)
210             ret = 2;
211         if (explicit_policy > 0) {
212             if (!(x->ex_flags & EXFLAG_SI))
213                 explicit_policy--;
214             if ((cache->explicit_skip != -1)
215                 && (cache->explicit_skip < explicit_policy))
216                 explicit_policy = cache->explicit_skip;
217         }
218     }
219 
220     if (ret != 1) {
221         if (ret == 2 && !explicit_policy)
222             return 6;
223         return ret;
224     }
225 
226     /* If we get this far initialize the tree */
227 
228     tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
229 
230     if (!tree)
231         return 0;
232 
233     tree->flags = 0;
234     tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
235     tree->nlevel = 0;
236     tree->extra_data = NULL;
237     tree->auth_policies = NULL;
238     tree->user_policies = NULL;
239 
240     if (!tree->levels) {
241         OPENSSL_free(tree);
242         return 0;
243     }
244 
245     OPENSSL_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         level++;
260         x = sk_X509_value(certs, i);
261         cache = policy_cache_set(x);
262         X509_up_ref(x);
263         level->cert = 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 issued and not the
272              * last in the chain.
273              */
274             if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
275                 level->flags |= X509_V_FLAG_INHIBIT_ANY;
276         } else {
277             if (!(x->ex_flags & EXFLAG_SI))
278                 any_skip--;
279             if ((cache->any_skip >= 0)
280                 && (cache->any_skip < any_skip))
281                 any_skip = cache->any_skip;
282         }
283 
284         if (map_skip == 0)
285             level->flags |= X509_V_FLAG_INHIBIT_MAP;
286         else {
287             if (!(x->ex_flags & EXFLAG_SI))
288                 map_skip--;
289             if ((cache->map_skip >= 0)
290                 && (cache->map_skip < map_skip))
291                 map_skip = cache->map_skip;
292         }
293 
294     }
295 
296     *ptree = tree;
297 
298     if (explicit_policy)
299         return 1;
300     else
301         return 5;
302 
303  bad_tree:
304 
305     X509_policy_tree_free(tree);
306 
307     return 0;
308 
309 }
310 
tree_link_matching_nodes(X509_POLICY_LEVEL * curr,X509_POLICY_DATA * data)311 static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
312                                     X509_POLICY_DATA *data)
313 {
314     X509_POLICY_LEVEL *last = curr - 1;
315     X509_POLICY_NODE *node;
316     int matched = 0;
317     size_t i;
318     /* Iterate through all in nodes linking matches */
319     for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
320         node = sk_X509_POLICY_NODE_value(last->nodes, i);
321         if (policy_node_match(last, node, data->valid_policy)) {
322             if (!level_add_node(curr, data, node, NULL))
323                 return 0;
324             matched = 1;
325         }
326     }
327     if (!matched && last->anyPolicy) {
328         if (!level_add_node(curr, data, last->anyPolicy, NULL))
329             return 0;
330     }
331     return 1;
332 }
333 
334 /*
335  * This corresponds to RFC3280 6.1.3(d)(1): link any data from
336  * CertificatePolicies onto matching parent or anyPolicy if no match.
337  */
338 
tree_link_nodes(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache)339 static int tree_link_nodes(X509_POLICY_LEVEL *curr,
340                            const X509_POLICY_CACHE *cache)
341 {
342     size_t i;
343     X509_POLICY_DATA *data;
344 
345     for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
346         data = sk_X509_POLICY_DATA_value(cache->data, i);
347         /*
348          * If a node is mapped any it doesn't have a corresponding
349          * CertificatePolicies entry. However such an identical node would
350          * be created if anyPolicy matching is enabled because there would be
351          * no match with the parent valid_policy_set. So we create link
352          * because then it will have the mapping flags right and we can prune
353          * it later.
354          */
355 #if 0
356         if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
357             && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
358             continue;
359 #endif
360         /* Look for matching nodes in previous level */
361         if (!tree_link_matching_nodes(curr, data))
362             return 0;
363     }
364     return 1;
365 }
366 
367 /*
368  * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched
369  * policies in the parent and link to anyPolicy.
370  */
371 
tree_add_unmatched(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,const ASN1_OBJECT * id,X509_POLICY_NODE * node,X509_POLICY_TREE * tree)372 static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
373                               const X509_POLICY_CACHE *cache,
374                               const ASN1_OBJECT *id,
375                               X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
376 {
377     X509_POLICY_DATA *data;
378     if (id == NULL)
379         id = node->data->valid_policy;
380     /*
381      * Create a new node with qualifiers from anyPolicy and id from unmatched
382      * node.
383      */
384     data = policy_data_new(NULL, id, node_critical(node));
385 
386     if (data == NULL)
387         return 0;
388     /* Curr may not have anyPolicy */
389     data->qualifier_set = cache->anyPolicy->qualifier_set;
390     data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
391     if (!level_add_node(curr, data, node, tree)) {
392         policy_data_free(data);
393         return 0;
394     }
395 
396     return 1;
397 }
398 
tree_link_unmatched(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,X509_POLICY_NODE * node,X509_POLICY_TREE * tree)399 static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
400                                const X509_POLICY_CACHE *cache,
401                                X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
402 {
403     const X509_POLICY_LEVEL *last = curr - 1;
404     size_t i;
405 
406     if ((last->flags & X509_V_FLAG_INHIBIT_MAP)
407         || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
408         /* If no policy mapping: matched if one child present */
409         if (node->nchild)
410             return 1;
411         if (!tree_add_unmatched(curr, cache, NULL, node, tree))
412             return 0;
413         /* Add it */
414     } else {
415         /* If mapping: matched if one child per expected policy set */
416         STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
417         if ((size_t)node->nchild == sk_ASN1_OBJECT_num(expset))
418             return 1;
419         /* Locate unmatched nodes */
420         for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
421             ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
422             if (level_find_node(curr, node, oid))
423                 continue;
424             if (!tree_add_unmatched(curr, cache, oid, node, tree))
425                 return 0;
426         }
427 
428     }
429 
430     return 1;
431 
432 }
433 
tree_link_any(X509_POLICY_LEVEL * curr,const X509_POLICY_CACHE * cache,X509_POLICY_TREE * tree)434 static int tree_link_any(X509_POLICY_LEVEL *curr,
435                          const X509_POLICY_CACHE *cache,
436                          X509_POLICY_TREE *tree)
437 {
438     size_t i;
439     /*
440      * X509_POLICY_DATA *data;
441      */
442     X509_POLICY_NODE *node;
443     X509_POLICY_LEVEL *last = curr - 1;
444 
445     for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
446         node = sk_X509_POLICY_NODE_value(last->nodes, i);
447 
448         if (!tree_link_unmatched(curr, cache, node, tree))
449             return 0;
450 
451 #if 0
452 
453         /*
454          * Skip any node with any children: we only want unmathced nodes.
455          * Note: need something better for policy mapping because each node
456          * may have multiple children
457          */
458         if (node->nchild)
459             continue;
460 
461         /*
462          * Create a new node with qualifiers from anyPolicy and id from
463          * unmatched node.
464          */
465         data = policy_data_new(NULL, node->data->valid_policy,
466                                node_critical(node));
467 
468         if (data == NULL)
469             return 0;
470         /* Curr may not have anyPolicy */
471         data->qualifier_set = cache->anyPolicy->qualifier_set;
472         data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
473         if (!level_add_node(curr, data, node, tree)) {
474             policy_data_free(data);
475             return 0;
476         }
477 #endif
478 
479     }
480     /* Finally add link to anyPolicy */
481     if (last->anyPolicy) {
482         if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL))
483             return 0;
484     }
485     return 1;
486 }
487 
488 /*
489  * Prune the tree: delete any child mapped child data on the current level
490  * then proceed up the tree deleting any data with no children. If we ever
491  * have no data on a level we can halt because the tree will be empty.
492  */
493 
tree_prune(X509_POLICY_TREE * tree,X509_POLICY_LEVEL * curr)494 static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
495 {
496     STACK_OF(X509_POLICY_NODE) *nodes;
497     X509_POLICY_NODE *node;
498     int i;
499     nodes = curr->nodes;
500     if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
501         for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
502             node = sk_X509_POLICY_NODE_value(nodes, i);
503             /* Delete any mapped data: see RFC3280 XXXX */
504             if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
505                 node->parent->nchild--;
506                 OPENSSL_free(node);
507                 (void)sk_X509_POLICY_NODE_delete(nodes, i);
508             }
509         }
510     }
511 
512     for (;;) {
513         --curr;
514         nodes = curr->nodes;
515         for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
516             node = sk_X509_POLICY_NODE_value(nodes, i);
517             if (node->nchild == 0) {
518                 node->parent->nchild--;
519                 OPENSSL_free(node);
520                 (void)sk_X509_POLICY_NODE_delete(nodes, i);
521             }
522         }
523         if (curr->anyPolicy && !curr->anyPolicy->nchild) {
524             if (curr->anyPolicy->parent)
525                 curr->anyPolicy->parent->nchild--;
526             OPENSSL_free(curr->anyPolicy);
527             curr->anyPolicy = NULL;
528         }
529         if (curr == tree->levels) {
530             /* If we zapped anyPolicy at top then tree is empty */
531             if (!curr->anyPolicy)
532                 return 2;
533             return 1;
534         }
535     }
536 
537 }
538 
tree_add_auth_node(STACK_OF (X509_POLICY_NODE)** pnodes,X509_POLICY_NODE * pcy)539 static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
540                               X509_POLICY_NODE *pcy)
541 {
542     if (!*pnodes) {
543         *pnodes = policy_node_cmp_new();
544         if (!*pnodes)
545             return 0;
546     } else {
547       sk_X509_POLICY_NODE_sort(*pnodes);
548       if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
549         return 1;
550     }
551     if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
552         return 0;
553 
554     return 1;
555 
556 }
557 
558 /*
559  * Calculate the authority set based on policy tree. The 'pnodes' parameter
560  * is used as a store for the set of policy nodes used to calculate the user
561  * set. If the authority set is not anyPolicy then pnodes will just point to
562  * the authority set. If however the authority set is anyPolicy then the set
563  * of valid policies (other than anyPolicy) is store in pnodes. The return
564  * value of '2' is used in this case to indicate that pnodes should be freed.
565  */
566 
tree_calculate_authority_set(X509_POLICY_TREE * tree,STACK_OF (X509_POLICY_NODE)** pnodes)567 static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
568                                         STACK_OF(X509_POLICY_NODE) **pnodes)
569 {
570     X509_POLICY_LEVEL *curr;
571     X509_POLICY_NODE *node, *anyptr;
572     STACK_OF(X509_POLICY_NODE) **addnodes;
573     int i;
574     size_t j;
575     curr = tree->levels + tree->nlevel - 1;
576 
577     /* If last level contains anyPolicy set is anyPolicy */
578     if (curr->anyPolicy) {
579         if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
580             return 0;
581         addnodes = pnodes;
582     } else
583         /* Add policies to authority set */
584         addnodes = &tree->auth_policies;
585 
586     curr = tree->levels;
587     for (i = 1; i < tree->nlevel; i++) {
588         /*
589          * If no anyPolicy node on this this level it can't appear on lower
590          * levels so end search.
591          */
592         if (!(anyptr = curr->anyPolicy))
593             break;
594         curr++;
595         for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
596             node = sk_X509_POLICY_NODE_value(curr->nodes, j);
597             if ((node->parent == anyptr)
598                 && !tree_add_auth_node(addnodes, node))
599                 return 0;
600         }
601     }
602 
603     if (addnodes == pnodes)
604         return 2;
605 
606     *pnodes = tree->auth_policies;
607 
608     return 1;
609 }
610 
tree_calculate_user_set(X509_POLICY_TREE * tree,STACK_OF (ASN1_OBJECT)* policy_oids,STACK_OF (X509_POLICY_NODE)* auth_nodes)611 static int tree_calculate_user_set(X509_POLICY_TREE *tree,
612                                    STACK_OF(ASN1_OBJECT) *policy_oids,
613                                    STACK_OF(X509_POLICY_NODE) *auth_nodes)
614 {
615     size_t i;
616     X509_POLICY_NODE *node;
617     ASN1_OBJECT *oid;
618 
619     X509_POLICY_NODE *anyPolicy;
620     X509_POLICY_DATA *extra;
621 
622     /*
623      * Check if anyPolicy present in authority constrained policy set: this
624      * will happen if it is a leaf node.
625      */
626 
627     if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
628         return 1;
629 
630     anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
631 
632     for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
633         oid = sk_ASN1_OBJECT_value(policy_oids, i);
634         if (OBJ_obj2nid(oid) == NID_any_policy) {
635             tree->flags |= POLICY_FLAG_ANY_POLICY;
636             return 1;
637         }
638     }
639 
640     for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
641         oid = sk_ASN1_OBJECT_value(policy_oids, i);
642         node = tree_find_sk(auth_nodes, oid);
643         if (!node) {
644             if (!anyPolicy)
645                 continue;
646             /*
647              * Create a new node with policy ID from user set and qualifiers
648              * from anyPolicy.
649              */
650             extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
651             if (!extra)
652                 return 0;
653             extra->qualifier_set = anyPolicy->data->qualifier_set;
654             extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
655                 | POLICY_DATA_FLAG_EXTRA_NODE;
656             node = level_add_node(NULL, extra, anyPolicy->parent, tree);
657         }
658         if (!tree->user_policies) {
659             tree->user_policies = sk_X509_POLICY_NODE_new_null();
660             if (!tree->user_policies)
661                 return 1;
662         }
663         if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
664             return 0;
665     }
666     return 1;
667 
668 }
669 
tree_evaluate(X509_POLICY_TREE * tree)670 static int tree_evaluate(X509_POLICY_TREE *tree)
671 {
672     int ret, i;
673     X509_POLICY_LEVEL *curr = tree->levels + 1;
674     const X509_POLICY_CACHE *cache;
675 
676     for (i = 1; i < tree->nlevel; i++, curr++) {
677         cache = policy_cache_set(curr->cert);
678         if (!tree_link_nodes(curr, cache))
679             return 0;
680 
681         if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
682             && !tree_link_any(curr, cache, tree))
683             return 0;
684         tree_print("before tree_prune()", tree, curr);
685         ret = tree_prune(tree, curr);
686         if (ret != 1)
687             return ret;
688     }
689 
690     return 1;
691 
692 }
693 
exnode_free(X509_POLICY_NODE * node)694 static void exnode_free(X509_POLICY_NODE *node)
695 {
696     if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
697         OPENSSL_free(node);
698 }
699 
X509_policy_tree_free(X509_POLICY_TREE * tree)700 void X509_policy_tree_free(X509_POLICY_TREE *tree)
701 {
702     X509_POLICY_LEVEL *curr;
703     int i;
704 
705     if (!tree)
706         return;
707 
708     sk_X509_POLICY_NODE_free(tree->auth_policies);
709     sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
710 
711     for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
712         if (curr->cert)
713             X509_free(curr->cert);
714         if (curr->nodes)
715             sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free);
716         if (curr->anyPolicy)
717             policy_node_free(curr->anyPolicy);
718     }
719 
720     if (tree->extra_data)
721         sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
722 
723     OPENSSL_free(tree->levels);
724     OPENSSL_free(tree);
725 
726 }
727 
728 /*-
729  * Application policy checking function.
730  * Return codes:
731  *  0   Internal Error.
732  *  1   Successful.
733  * -1   One or more certificates contain invalid or inconsistent extensions
734  * -2   User constrained policy set empty and requireExplicit true.
735  */
736 
X509_policy_check(X509_POLICY_TREE ** ptree,int * pexplicit_policy,STACK_OF (X509)* certs,STACK_OF (ASN1_OBJECT)* policy_oids,unsigned int flags)737 int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
738                       STACK_OF(X509) *certs,
739                       STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
740 {
741     int ret;
742     int calc_ret;
743     X509_POLICY_TREE *tree = NULL;
744     STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
745     *ptree = NULL;
746 
747     *pexplicit_policy = 0;
748     ret = tree_init(&tree, certs, flags);
749 
750     switch (ret) {
751 
752         /* Tree empty requireExplicit False: OK */
753     case 2:
754         return 1;
755 
756         /* Some internal error */
757     case -1:
758         return -1;
759 
760         /* Some internal error */
761     case 0:
762         return 0;
763 
764         /* Tree empty requireExplicit True: Error */
765 
766     case 6:
767         *pexplicit_policy = 1;
768         return -2;
769 
770         /* Tree OK requireExplicit True: OK and continue */
771     case 5:
772         *pexplicit_policy = 1;
773         break;
774 
775         /* Tree OK: continue */
776 
777     case 1:
778         if (!tree)
779             /*
780              * tree_init() returns success and a null tree
781              * if it's just looking at a trust anchor.
782              * I'm not sure that returning success here is
783              * correct, but I'm sure that reporting this
784              * as an internal error which our caller
785              * interprets as a malloc failure is wrong.
786              */
787             return 1;
788         break;
789     }
790 
791     if (!tree)
792         goto error;
793     ret = tree_evaluate(tree);
794 
795     tree_print("tree_evaluate()", tree, NULL);
796 
797     if (ret <= 0)
798         goto error;
799 
800     /* Return value 2 means tree empty */
801     if (ret == 2) {
802         X509_policy_tree_free(tree);
803         if (*pexplicit_policy)
804             return -2;
805         else
806             return 1;
807     }
808 
809     /* Tree is not empty: continue */
810 
811     calc_ret = tree_calculate_authority_set(tree, &auth_nodes);
812 
813     if (!calc_ret)
814         goto error;
815 
816     ret = tree_calculate_user_set(tree, policy_oids, auth_nodes);
817 
818     if (calc_ret == 2)
819         sk_X509_POLICY_NODE_free(auth_nodes);
820 
821     if (!ret)
822         goto error;
823 
824 
825     if (tree)
826         *ptree = tree;
827 
828     if (*pexplicit_policy) {
829         nodes = X509_policy_tree_get0_user_policies(tree);
830         if (sk_X509_POLICY_NODE_num(nodes) <= 0)
831             return -2;
832     }
833 
834     return 1;
835 
836  error:
837 
838     X509_policy_tree_free(tree);
839 
840     return 0;
841 
842 }
843