• 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 if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
547         return 1;
548 
549     if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
550         return 0;
551 
552     return 1;
553 
554 }
555 
556 /*
557  * Calculate the authority set based on policy tree. The 'pnodes' parameter
558  * is used as a store for the set of policy nodes used to calculate the user
559  * set. If the authority set is not anyPolicy then pnodes will just point to
560  * the authority set. If however the authority set is anyPolicy then the set
561  * of valid policies (other than anyPolicy) is store in pnodes. The return
562  * value of '2' is used in this case to indicate that pnodes should be freed.
563  */
564 
tree_calculate_authority_set(X509_POLICY_TREE * tree,STACK_OF (X509_POLICY_NODE)** pnodes)565 static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
566                                         STACK_OF(X509_POLICY_NODE) **pnodes)
567 {
568     X509_POLICY_LEVEL *curr;
569     X509_POLICY_NODE *node, *anyptr;
570     STACK_OF(X509_POLICY_NODE) **addnodes;
571     int i;
572     size_t j;
573     curr = tree->levels + tree->nlevel - 1;
574 
575     /* If last level contains anyPolicy set is anyPolicy */
576     if (curr->anyPolicy) {
577         if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
578             return 0;
579         addnodes = pnodes;
580     } else
581         /* Add policies to authority set */
582         addnodes = &tree->auth_policies;
583 
584     curr = tree->levels;
585     for (i = 1; i < tree->nlevel; i++) {
586         /*
587          * If no anyPolicy node on this this level it can't appear on lower
588          * levels so end search.
589          */
590         if (!(anyptr = curr->anyPolicy))
591             break;
592         curr++;
593         for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
594             node = sk_X509_POLICY_NODE_value(curr->nodes, j);
595             if ((node->parent == anyptr)
596                 && !tree_add_auth_node(addnodes, node))
597                 return 0;
598         }
599     }
600 
601     if (addnodes == pnodes)
602         return 2;
603 
604     *pnodes = tree->auth_policies;
605 
606     return 1;
607 }
608 
tree_calculate_user_set(X509_POLICY_TREE * tree,STACK_OF (ASN1_OBJECT)* policy_oids,STACK_OF (X509_POLICY_NODE)* auth_nodes)609 static int tree_calculate_user_set(X509_POLICY_TREE *tree,
610                                    STACK_OF(ASN1_OBJECT) *policy_oids,
611                                    STACK_OF(X509_POLICY_NODE) *auth_nodes)
612 {
613     size_t i;
614     X509_POLICY_NODE *node;
615     ASN1_OBJECT *oid;
616 
617     X509_POLICY_NODE *anyPolicy;
618     X509_POLICY_DATA *extra;
619 
620     /*
621      * Check if anyPolicy present in authority constrained policy set: this
622      * will happen if it is a leaf node.
623      */
624 
625     if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
626         return 1;
627 
628     anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
629 
630     for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
631         oid = sk_ASN1_OBJECT_value(policy_oids, i);
632         if (OBJ_obj2nid(oid) == NID_any_policy) {
633             tree->flags |= POLICY_FLAG_ANY_POLICY;
634             return 1;
635         }
636     }
637 
638     for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
639         oid = sk_ASN1_OBJECT_value(policy_oids, i);
640         node = tree_find_sk(auth_nodes, oid);
641         if (!node) {
642             if (!anyPolicy)
643                 continue;
644             /*
645              * Create a new node with policy ID from user set and qualifiers
646              * from anyPolicy.
647              */
648             extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
649             if (!extra)
650                 return 0;
651             extra->qualifier_set = anyPolicy->data->qualifier_set;
652             extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
653                 | POLICY_DATA_FLAG_EXTRA_NODE;
654             node = level_add_node(NULL, extra, anyPolicy->parent, tree);
655         }
656         if (!tree->user_policies) {
657             tree->user_policies = sk_X509_POLICY_NODE_new_null();
658             if (!tree->user_policies)
659                 return 1;
660         }
661         if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
662             return 0;
663     }
664     return 1;
665 
666 }
667 
tree_evaluate(X509_POLICY_TREE * tree)668 static int tree_evaluate(X509_POLICY_TREE *tree)
669 {
670     int ret, i;
671     X509_POLICY_LEVEL *curr = tree->levels + 1;
672     const X509_POLICY_CACHE *cache;
673 
674     for (i = 1; i < tree->nlevel; i++, curr++) {
675         cache = policy_cache_set(curr->cert);
676         if (!tree_link_nodes(curr, cache))
677             return 0;
678 
679         if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
680             && !tree_link_any(curr, cache, tree))
681             return 0;
682         tree_print("before tree_prune()", tree, curr);
683         ret = tree_prune(tree, curr);
684         if (ret != 1)
685             return ret;
686     }
687 
688     return 1;
689 
690 }
691 
exnode_free(X509_POLICY_NODE * node)692 static void exnode_free(X509_POLICY_NODE *node)
693 {
694     if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
695         OPENSSL_free(node);
696 }
697 
X509_policy_tree_free(X509_POLICY_TREE * tree)698 void X509_policy_tree_free(X509_POLICY_TREE *tree)
699 {
700     X509_POLICY_LEVEL *curr;
701     int i;
702 
703     if (!tree)
704         return;
705 
706     sk_X509_POLICY_NODE_free(tree->auth_policies);
707     sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
708 
709     for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
710         if (curr->cert)
711             X509_free(curr->cert);
712         if (curr->nodes)
713             sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free);
714         if (curr->anyPolicy)
715             policy_node_free(curr->anyPolicy);
716     }
717 
718     if (tree->extra_data)
719         sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
720 
721     OPENSSL_free(tree->levels);
722     OPENSSL_free(tree);
723 
724 }
725 
726 /*-
727  * Application policy checking function.
728  * Return codes:
729  *  0   Internal Error.
730  *  1   Successful.
731  * -1   One or more certificates contain invalid or inconsistent extensions
732  * -2   User constrained policy set empty and requireExplicit true.
733  */
734 
X509_policy_check(X509_POLICY_TREE ** ptree,int * pexplicit_policy,STACK_OF (X509)* certs,STACK_OF (ASN1_OBJECT)* policy_oids,unsigned int flags)735 int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
736                       STACK_OF(X509) *certs,
737                       STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
738 {
739     int ret;
740     int calc_ret;
741     X509_POLICY_TREE *tree = NULL;
742     STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
743     *ptree = NULL;
744 
745     *pexplicit_policy = 0;
746     ret = tree_init(&tree, certs, flags);
747 
748     switch (ret) {
749 
750         /* Tree empty requireExplicit False: OK */
751     case 2:
752         return 1;
753 
754         /* Some internal error */
755     case -1:
756         return -1;
757 
758         /* Some internal error */
759     case 0:
760         return 0;
761 
762         /* Tree empty requireExplicit True: Error */
763 
764     case 6:
765         *pexplicit_policy = 1;
766         return -2;
767 
768         /* Tree OK requireExplicit True: OK and continue */
769     case 5:
770         *pexplicit_policy = 1;
771         break;
772 
773         /* Tree OK: continue */
774 
775     case 1:
776         if (!tree)
777             /*
778              * tree_init() returns success and a null tree
779              * if it's just looking at a trust anchor.
780              * I'm not sure that returning success here is
781              * correct, but I'm sure that reporting this
782              * as an internal error which our caller
783              * interprets as a malloc failure is wrong.
784              */
785             return 1;
786         break;
787     }
788 
789     if (!tree)
790         goto error;
791     ret = tree_evaluate(tree);
792 
793     tree_print("tree_evaluate()", tree, NULL);
794 
795     if (ret <= 0)
796         goto error;
797 
798     /* Return value 2 means tree empty */
799     if (ret == 2) {
800         X509_policy_tree_free(tree);
801         if (*pexplicit_policy)
802             return -2;
803         else
804             return 1;
805     }
806 
807     /* Tree is not empty: continue */
808 
809     calc_ret = tree_calculate_authority_set(tree, &auth_nodes);
810 
811     if (!calc_ret)
812         goto error;
813 
814     ret = tree_calculate_user_set(tree, policy_oids, auth_nodes);
815 
816     if (calc_ret == 2)
817         sk_X509_POLICY_NODE_free(auth_nodes);
818 
819     if (!ret)
820         goto error;
821 
822 
823     if (tree)
824         *ptree = tree;
825 
826     if (*pexplicit_policy) {
827         nodes = X509_policy_tree_get0_user_policies(tree);
828         if (sk_X509_POLICY_NODE_num(nodes) <= 0)
829             return -2;
830     }
831 
832     return 1;
833 
834  error:
835 
836     X509_policy_tree_free(tree);
837 
838     return 0;
839 
840 }
841