📄 pcy_tree.c
字号:
/* pcy_tree.c *//* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL * project 2004. *//* ==================================================================== * Copyright (c) 2004 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * licensing@OpenSSL.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */#include "cryptlib.h"#include <openssl/x509.h>#include <openssl/x509v3.h>#include "pcy_int.h"/* Initialize policy tree. Return values: * 0 Some internal error occured. * -1 Inconsistent or invalid extensions in certificates. * 1 Tree initialized OK. * 2 Policy tree is empty. * 5 Tree OK and requireExplicitPolicy true. * 6 Tree empty and requireExplicitPolicy true. */static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, unsigned int flags) { X509_POLICY_TREE *tree; X509_POLICY_LEVEL *level; const X509_POLICY_CACHE *cache; X509_POLICY_DATA *data = NULL; X509 *x; int ret = 1; int i, n; int explicit_policy; int any_skip; int map_skip; *ptree = NULL; n = sk_X509_num(certs); /* Disable policy mapping for now... */ flags |= X509_V_FLAG_INHIBIT_MAP; if (flags & X509_V_FLAG_EXPLICIT_POLICY) explicit_policy = 0; else explicit_policy = n + 1; if (flags & X509_V_FLAG_INHIBIT_ANY) any_skip = 0; else any_skip = n + 1; if (flags & X509_V_FLAG_INHIBIT_MAP) map_skip = 0; else map_skip = n + 1; /* Can't do anything with just a trust anchor */ if (n == 1) return 1; /* First setup policy cache in all certificates apart from the * trust anchor. Note any bad cache results on the way. Also can * calculate explicit_policy value at this point. */ for (i = n - 2; i >= 0; i--) { x = sk_X509_value(certs, i); X509_check_purpose(x, -1, -1); cache = policy_cache_set(x); /* If cache NULL something bad happened: return immediately */ if (cache == NULL) return 0; /* If inconsistent extensions keep a note of it but continue */ if (x->ex_flags & EXFLAG_INVALID_POLICY) ret = -1; /* Otherwise if we have no data (hence no CertificatePolicies) * and haven't already set an inconsistent code note it. */ else if ((ret == 1) && !cache->data) ret = 2; if (explicit_policy > 0) { explicit_policy--; if (!(x->ex_flags & EXFLAG_SS) && (cache->explicit_skip != -1) && (cache->explicit_skip < explicit_policy)) explicit_policy = cache->explicit_skip; } } if (ret != 1) { if (ret == 2 && !explicit_policy) return 6; return ret; } /* If we get this far initialize the tree */ tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE)); if (!tree) return 0; tree->flags = 0; tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n); tree->nlevel = 0; tree->extra_data = NULL; tree->auth_policies = NULL; tree->user_policies = NULL; if (!tree) { OPENSSL_free(tree); return 0; } memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL)); tree->nlevel = n; level = tree->levels; /* Root data: initialize to anyPolicy */ data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0); if (!data || !level_add_node(level, data, NULL, tree)) goto bad_tree; for (i = n - 2; i >= 0; i--) { level++; x = sk_X509_value(certs, i); cache = policy_cache_set(x); CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); level->cert = x; if (!cache->anyPolicy) level->flags |= X509_V_FLAG_INHIBIT_ANY; /* Determine inhibit any and inhibit map flags */ if (any_skip == 0) { /* Any matching allowed if certificate is self * issued and not the last in the chain. */ if (!(x->ex_flags & EXFLAG_SS) || (i == 0)) level->flags |= X509_V_FLAG_INHIBIT_ANY; } else { any_skip--; if ((cache->any_skip > 0) && (cache->any_skip < any_skip)) any_skip = cache->any_skip; } if (map_skip == 0) level->flags |= X509_V_FLAG_INHIBIT_MAP; else { map_skip--; if ((cache->map_skip > 0) && (cache->map_skip < map_skip)) map_skip = cache->map_skip; } } *ptree = tree; if (explicit_policy) return 1; else return 5; bad_tree: X509_policy_tree_free(tree); return 0; }/* This corresponds to RFC3280 XXXX XXXXX: * link any data from CertificatePolicies onto matching parent * or anyPolicy if no match. */static int tree_link_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache) { int i; X509_POLICY_LEVEL *last; X509_POLICY_DATA *data; X509_POLICY_NODE *parent; last = curr - 1; for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) { data = sk_X509_POLICY_DATA_value(cache->data, i); /* If a node is mapped any it doesn't have a corresponding * CertificatePolicies entry. * However such an identical node would be created * if anyPolicy matching is enabled because there would be * no match with the parent valid_policy_set. So we create * link because then it will have the mapping flags * right and we can prune it later. */ if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) && !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) continue; /* Look for matching node in parent */ parent = level_find_node(last, data->valid_policy); /* If no match link to anyPolicy */ if (!parent) parent = last->anyPolicy; if (parent && !level_add_node(curr, data, parent, NULL)) return 0; } return 1; }/* This corresponds to RFC3280 XXXX XXXXX: * Create new data for any unmatched policies in the parent and link * to anyPolicy. */static int tree_link_any(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache, X509_POLICY_TREE *tree) { int i; X509_POLICY_DATA *data; X509_POLICY_NODE *node; X509_POLICY_LEVEL *last; last = curr - 1; for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { node = sk_X509_POLICY_NODE_value(last->nodes, i); /* Skip any node with any children: we only want unmathced * nodes. * * Note: need something better for policy mapping * because each node may have multiple children */ if (node->nchild) continue; /* Create a new node with qualifiers from anyPolicy and * id from unmatched node. */ data = policy_data_new(NULL, node->data->valid_policy, node_critical(node)); if (data == NULL) return 0; data->qualifier_set = curr->anyPolicy->data->qualifier_set; data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; if (!level_add_node(curr, data, node, tree)) { policy_data_free(data); return 0; } } /* Finally add link to anyPolicy */ if (last->anyPolicy) { if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL)) return 0; } return 1; }/* Prune the tree: delete any child mapped child data on the current level * then proceed up the tree deleting any data with no children. If we ever * have no data on a level we can halt because the tree will be empty. */static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) { X509_POLICY_NODE *node; int i; for (i = sk_X509_POLICY_NODE_num(curr->nodes) - 1; i >= 0; i--) { node = sk_X509_POLICY_NODE_value(curr->nodes, i); /* Delete any mapped data: see RFC3280 XXXX */ if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) { node->parent->nchild--; OPENSSL_free(node);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -