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