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