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