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