Remove old versions of OpenSSL.
[dragonfly.git] / crypto / openssl-0.9 / crypto / x509v3 / pcy_tree.c
blobb1ce77b9afc7ad9d5ebb11177ae2a6a8d7625768
1 /* pcy_tree.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3 * project 2004.
4 */
5 /* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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/)"
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.
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.
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/)"
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 * ====================================================================
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).
59 #include "cryptlib.h"
60 #include <openssl/x509.h>
61 #include <openssl/x509v3.h>
63 #include "pcy_int.h"
65 /* Initialize policy tree. Return values:
66 * 0 Some internal error occured.
67 * -1 Inconsistent or invalid extensions in certificates.
68 * 1 Tree initialized OK.
69 * 2 Policy tree is empty.
70 * 5 Tree OK and requireExplicitPolicy true.
71 * 6 Tree empty and requireExplicitPolicy true.
74 static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
75 unsigned int flags)
77 X509_POLICY_TREE *tree;
78 X509_POLICY_LEVEL *level;
79 const X509_POLICY_CACHE *cache;
80 X509_POLICY_DATA *data = NULL;
81 X509 *x;
82 int ret = 1;
83 int i, n;
84 int explicit_policy;
85 int any_skip;
86 int map_skip;
87 *ptree = NULL;
88 n = sk_X509_num(certs);
90 /* Disable policy mapping for now... */
91 flags |= X509_V_FLAG_INHIBIT_MAP;
93 if (flags & X509_V_FLAG_EXPLICIT_POLICY)
94 explicit_policy = 0;
95 else
96 explicit_policy = n + 1;
98 if (flags & X509_V_FLAG_INHIBIT_ANY)
99 any_skip = 0;
100 else
101 any_skip = n + 1;
103 if (flags & X509_V_FLAG_INHIBIT_MAP)
104 map_skip = 0;
105 else
106 map_skip = n + 1;
108 /* Can't do anything with just a trust anchor */
109 if (n == 1)
110 return 1;
111 /* First setup policy cache in all certificates apart from the
112 * trust anchor. Note any bad cache results on the way. Also can
113 * calculate explicit_policy value at this point.
115 for (i = n - 2; i >= 0; i--)
117 x = sk_X509_value(certs, i);
118 X509_check_purpose(x, -1, -1);
119 cache = policy_cache_set(x);
120 /* If cache NULL something bad happened: return immediately */
121 if (cache == NULL)
122 return 0;
123 /* If inconsistent extensions keep a note of it but continue */
124 if (x->ex_flags & EXFLAG_INVALID_POLICY)
125 ret = -1;
126 /* Otherwise if we have no data (hence no CertificatePolicies)
127 * and haven't already set an inconsistent code note it.
129 else if ((ret == 1) && !cache->data)
130 ret = 2;
131 if (explicit_policy > 0)
133 if (!(x->ex_flags & EXFLAG_SI))
134 explicit_policy--;
135 if ((cache->explicit_skip != -1)
136 && (cache->explicit_skip < explicit_policy))
137 explicit_policy = cache->explicit_skip;
141 if (ret != 1)
143 if (ret == 2 && !explicit_policy)
144 return 6;
145 return ret;
149 /* If we get this far initialize the tree */
151 tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
153 if (!tree)
154 return 0;
156 tree->flags = 0;
157 tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
158 tree->nlevel = 0;
159 tree->extra_data = NULL;
160 tree->auth_policies = NULL;
161 tree->user_policies = NULL;
163 if (!tree)
165 OPENSSL_free(tree);
166 return 0;
169 memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
171 tree->nlevel = n;
173 level = tree->levels;
175 /* Root data: initialize to anyPolicy */
177 data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
179 if (!data || !level_add_node(level, data, NULL, tree))
180 goto bad_tree;
182 for (i = n - 2; i >= 0; i--)
184 level++;
185 x = sk_X509_value(certs, i);
186 cache = policy_cache_set(x);
188 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
189 level->cert = x;
191 if (!cache->anyPolicy)
192 level->flags |= X509_V_FLAG_INHIBIT_ANY;
194 /* Determine inhibit any and inhibit map flags */
195 if (any_skip == 0)
197 /* Any matching allowed if certificate is self
198 * issued and not the last in the chain.
200 if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
201 level->flags |= X509_V_FLAG_INHIBIT_ANY;
203 else
205 if (!(x->ex_flags & EXFLAG_SI))
206 any_skip--;
207 if ((cache->any_skip >= 0)
208 && (cache->any_skip < any_skip))
209 any_skip = cache->any_skip;
212 if (map_skip == 0)
213 level->flags |= X509_V_FLAG_INHIBIT_MAP;
214 else
216 map_skip--;
217 if ((cache->map_skip >= 0)
218 && (cache->map_skip < map_skip))
219 map_skip = cache->map_skip;
225 *ptree = tree;
227 if (explicit_policy)
228 return 1;
229 else
230 return 5;
232 bad_tree:
234 X509_policy_tree_free(tree);
236 return 0;
240 /* This corresponds to RFC3280 XXXX XXXXX:
241 * link any data from CertificatePolicies onto matching parent
242 * or anyPolicy if no match.
245 static int tree_link_nodes(X509_POLICY_LEVEL *curr,
246 const X509_POLICY_CACHE *cache)
248 int i;
249 X509_POLICY_LEVEL *last;
250 X509_POLICY_DATA *data;
251 X509_POLICY_NODE *parent;
252 last = curr - 1;
253 for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
255 data = sk_X509_POLICY_DATA_value(cache->data, i);
256 /* If a node is mapped any it doesn't have a corresponding
257 * CertificatePolicies entry.
258 * However such an identical node would be created
259 * if anyPolicy matching is enabled because there would be
260 * no match with the parent valid_policy_set. So we create
261 * link because then it will have the mapping flags
262 * right and we can prune it later.
264 if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
265 && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
266 continue;
267 /* Look for matching node in parent */
268 parent = level_find_node(last, data->valid_policy);
269 /* If no match link to anyPolicy */
270 if (!parent)
271 parent = last->anyPolicy;
272 if (parent && !level_add_node(curr, data, parent, NULL))
273 return 0;
275 return 1;
278 /* This corresponds to RFC3280 XXXX XXXXX:
279 * Create new data for any unmatched policies in the parent and link
280 * to anyPolicy.
283 static int tree_link_any(X509_POLICY_LEVEL *curr,
284 const X509_POLICY_CACHE *cache,
285 X509_POLICY_TREE *tree)
287 int i;
288 X509_POLICY_DATA *data;
289 X509_POLICY_NODE *node;
290 X509_POLICY_LEVEL *last;
292 last = curr - 1;
294 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
296 node = sk_X509_POLICY_NODE_value(last->nodes, i);
298 /* Skip any node with any children: we only want unmathced
299 * nodes.
301 * Note: need something better for policy mapping
302 * because each node may have multiple children
304 if (node->nchild)
305 continue;
306 /* Create a new node with qualifiers from anyPolicy and
307 * id from unmatched node.
309 data = policy_data_new(NULL, node->data->valid_policy,
310 node_critical(node));
312 if (data == NULL)
313 return 0;
314 /* Curr may not have anyPolicy */
315 data->qualifier_set = cache->anyPolicy->qualifier_set;
316 data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
317 if (!level_add_node(curr, data, node, tree))
319 policy_data_free(data);
320 return 0;
323 /* Finally add link to anyPolicy */
324 if (last->anyPolicy)
326 if (!level_add_node(curr, cache->anyPolicy,
327 last->anyPolicy, NULL))
328 return 0;
330 return 1;
333 /* Prune the tree: delete any child mapped child data on the current level
334 * then proceed up the tree deleting any data with no children. If we ever
335 * have no data on a level we can halt because the tree will be empty.
338 static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
340 X509_POLICY_NODE *node;
341 int i;
342 for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--)
344 node = sk_X509_POLICY_NODE_value(curr->nodes, i);
345 /* Delete any mapped data: see RFC3280 XXXX */
346 if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
348 node->parent->nchild--;
349 OPENSSL_free(node);
350 (void)sk_X509_POLICY_NODE_delete(curr->nodes, i);
354 for(;;) {
355 --curr;
356 for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--)
358 node = sk_X509_POLICY_NODE_value(curr->nodes, i);
359 if (node->nchild == 0)
361 node->parent->nchild--;
362 OPENSSL_free(node);
363 (void)sk_X509_POLICY_NODE_delete(curr->nodes, i);
366 if (curr->anyPolicy && !curr->anyPolicy->nchild)
368 if (curr->anyPolicy->parent)
369 curr->anyPolicy->parent->nchild--;
370 OPENSSL_free(curr->anyPolicy);
371 curr->anyPolicy = NULL;
373 if (curr == tree->levels)
375 /* If we zapped anyPolicy at top then tree is empty */
376 if (!curr->anyPolicy)
377 return 2;
378 return 1;
382 return 1;
386 static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
387 X509_POLICY_NODE *pcy)
389 if (!*pnodes)
391 *pnodes = policy_node_cmp_new();
392 if (!*pnodes)
393 return 0;
395 else if (sk_X509_POLICY_NODE_find(*pnodes, pcy) != -1)
396 return 1;
398 if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
399 return 0;
401 return 1;
405 /* Calculate the authority set based on policy tree.
406 * The 'pnodes' parameter is used as a store for the set of policy nodes
407 * used to calculate the user set. If the authority set is not anyPolicy
408 * then pnodes will just point to the authority set. If however the authority
409 * set is anyPolicy then the set of valid policies (other than anyPolicy)
410 * is store in pnodes. The return value of '2' is used in this case to indicate
411 * that pnodes should be freed.
414 static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
415 STACK_OF(X509_POLICY_NODE) **pnodes)
417 X509_POLICY_LEVEL *curr;
418 X509_POLICY_NODE *node, *anyptr;
419 STACK_OF(X509_POLICY_NODE) **addnodes;
420 int i, j;
421 curr = tree->levels + tree->nlevel - 1;
423 /* If last level contains anyPolicy set is anyPolicy */
424 if (curr->anyPolicy)
426 if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
427 return 0;
428 addnodes = pnodes;
430 else
431 /* Add policies to authority set */
432 addnodes = &tree->auth_policies;
434 curr = tree->levels;
435 for (i = 1; i < tree->nlevel; i++)
437 /* If no anyPolicy node on this this level it can't
438 * appear on lower levels so end search.
440 if (!(anyptr = curr->anyPolicy))
441 break;
442 curr++;
443 for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++)
445 node = sk_X509_POLICY_NODE_value(curr->nodes, j);
446 if ((node->parent == anyptr)
447 && !tree_add_auth_node(addnodes, node))
448 return 0;
452 if (addnodes == pnodes)
453 return 2;
455 *pnodes = tree->auth_policies;
457 return 1;
460 static int tree_calculate_user_set(X509_POLICY_TREE *tree,
461 STACK_OF(ASN1_OBJECT) *policy_oids,
462 STACK_OF(X509_POLICY_NODE) *auth_nodes)
464 int i;
465 X509_POLICY_NODE *node;
466 ASN1_OBJECT *oid;
468 X509_POLICY_NODE *anyPolicy;
469 X509_POLICY_DATA *extra;
471 /* Check if anyPolicy present in authority constrained policy set:
472 * this will happen if it is a leaf node.
475 if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
476 return 1;
478 anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
480 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
482 oid = sk_ASN1_OBJECT_value(policy_oids, i);
483 if (OBJ_obj2nid(oid) == NID_any_policy)
485 tree->flags |= POLICY_FLAG_ANY_POLICY;
486 return 1;
490 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
492 oid = sk_ASN1_OBJECT_value(policy_oids, i);
493 node = tree_find_sk(auth_nodes, oid);
494 if (!node)
496 if (!anyPolicy)
497 continue;
498 /* Create a new node with policy ID from user set
499 * and qualifiers from anyPolicy.
501 extra = policy_data_new(NULL, oid,
502 node_critical(anyPolicy));
503 if (!extra)
504 return 0;
505 extra->qualifier_set = anyPolicy->data->qualifier_set;
506 extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
507 | POLICY_DATA_FLAG_EXTRA_NODE;
508 node = level_add_node(NULL, extra, anyPolicy->parent,
509 tree);
511 if (!tree->user_policies)
513 tree->user_policies = sk_X509_POLICY_NODE_new_null();
514 if (!tree->user_policies)
515 return 1;
517 if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
518 return 0;
520 return 1;
524 static int tree_evaluate(X509_POLICY_TREE *tree)
526 int ret, i;
527 X509_POLICY_LEVEL *curr = tree->levels + 1;
528 const X509_POLICY_CACHE *cache;
530 for(i = 1; i < tree->nlevel; i++, curr++)
532 cache = policy_cache_set(curr->cert);
533 if (!tree_link_nodes(curr, cache))
534 return 0;
536 if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
537 && !tree_link_any(curr, cache, tree))
538 return 0;
539 ret = tree_prune(tree, curr);
540 if (ret != 1)
541 return ret;
544 return 1;
548 static void exnode_free(X509_POLICY_NODE *node)
550 if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
551 OPENSSL_free(node);
555 void X509_policy_tree_free(X509_POLICY_TREE *tree)
557 X509_POLICY_LEVEL *curr;
558 int i;
560 if (!tree)
561 return;
563 sk_X509_POLICY_NODE_free(tree->auth_policies);
564 sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
566 for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++)
568 if (curr->cert)
569 X509_free(curr->cert);
570 if (curr->nodes)
571 sk_X509_POLICY_NODE_pop_free(curr->nodes,
572 policy_node_free);
573 if (curr->anyPolicy)
574 policy_node_free(curr->anyPolicy);
577 if (tree->extra_data)
578 sk_X509_POLICY_DATA_pop_free(tree->extra_data,
579 policy_data_free);
581 OPENSSL_free(tree->levels);
582 OPENSSL_free(tree);
586 /* Application policy checking function.
587 * Return codes:
588 * 0 Internal Error.
589 * 1 Successful.
590 * -1 One or more certificates contain invalid or inconsistent extensions
591 * -2 User constrained policy set empty and requireExplicit true.
594 int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
595 STACK_OF(X509) *certs,
596 STACK_OF(ASN1_OBJECT) *policy_oids,
597 unsigned int flags)
599 int ret;
600 X509_POLICY_TREE *tree = NULL;
601 STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
602 *ptree = NULL;
604 *pexplicit_policy = 0;
605 ret = tree_init(&tree, certs, flags);
608 switch (ret)
611 /* Tree empty requireExplicit False: OK */
612 case 2:
613 return 1;
615 /* Some internal error */
616 case 0:
617 return 0;
619 /* Tree empty requireExplicit True: Error */
621 case 6:
622 *pexplicit_policy = 1;
623 return -2;
625 /* Tree OK requireExplicit True: OK and continue */
626 case 5:
627 *pexplicit_policy = 1;
628 break;
630 /* Tree OK: continue */
632 case 1:
633 if (!tree)
635 * tree_init() returns success and a null tree
636 * if it's just looking at a trust anchor.
637 * I'm not sure that returning success here is
638 * correct, but I'm sure that reporting this
639 * as an internal error which our caller
640 * interprets as a malloc failure is wrong.
642 return 1;
643 break;
646 if (!tree) goto error;
647 ret = tree_evaluate(tree);
649 if (ret <= 0)
650 goto error;
652 /* Return value 2 means tree empty */
653 if (ret == 2)
655 X509_policy_tree_free(tree);
656 if (*pexplicit_policy)
657 return -2;
658 else
659 return 1;
662 /* Tree is not empty: continue */
664 ret = tree_calculate_authority_set(tree, &auth_nodes);
666 if (!ret)
667 goto error;
669 if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
670 goto error;
672 if (ret == 2)
673 sk_X509_POLICY_NODE_free(auth_nodes);
675 if (tree)
676 *ptree = tree;
678 if (*pexplicit_policy)
680 nodes = X509_policy_tree_get0_user_policies(tree);
681 if (sk_X509_POLICY_NODE_num(nodes) <= 0)
682 return -2;
685 return 1;
687 error:
689 X509_policy_tree_free(tree);
691 return 0;