pcy_cache.c revision 194206
133965Sjdp/* pcy_cache.c */ 260510Sobrien/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 333965Sjdp * project 2004. 433965Sjdp */ 533965Sjdp/* ==================================================================== 633965Sjdp * Copyright (c) 2004 The OpenSSL Project. All rights reserved. 733965Sjdp * 833965Sjdp * Redistribution and use in source and binary forms, with or without 933965Sjdp * modification, are permitted provided that the following conditions 1033965Sjdp * are met: 1133965Sjdp * 1233965Sjdp * 1. Redistributions of source code must retain the above copyright 1333965Sjdp * notice, this list of conditions and the following disclaimer. 1433965Sjdp * 1533965Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1633965Sjdp * notice, this list of conditions and the following disclaimer in 1733965Sjdp * the documentation and/or other materials provided with the 1833965Sjdp * distribution. 1933965Sjdp * 2033965Sjdp * 3. All advertising materials mentioning features or use of this 2157406Sjdp * software must display the following acknowledgment: 2257406Sjdp * "This product includes software developed by the OpenSSL Project 2333965Sjdp * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2433965Sjdp * 2533965Sjdp * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2633965Sjdp * endorse or promote products derived from this software without 2733965Sjdp * prior written permission. For written permission, please contact 2833965Sjdp * licensing@OpenSSL.org. 2933965Sjdp * 3033965Sjdp * 5. Products derived from this software may not be called "OpenSSL" 3133965Sjdp * nor may "OpenSSL" appear in their names without prior written 3233965Sjdp * permission of the OpenSSL Project. 3333965Sjdp * 3433965Sjdp * 6. Redistributions of any form whatsoever must retain the following 3533965Sjdp * acknowledgment: 3633965Sjdp * "This product includes software developed by the OpenSSL Project 3733965Sjdp * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3833965Sjdp * 3933965Sjdp * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4033965Sjdp * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4133965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4233965Sjdp * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4333965Sjdp * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4433965Sjdp * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4533965Sjdp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4633965Sjdp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4733965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4833965Sjdp * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4933965Sjdp * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5033965Sjdp * OF THE POSSIBILITY OF SUCH DAMAGE. 5133965Sjdp * ==================================================================== 5233965Sjdp * 5333965Sjdp * This product includes cryptographic software written by Eric Young 5433965Sjdp * (eay@cryptsoft.com). This product includes software written by Tim 5533965Sjdp * Hudson (tjh@cryptsoft.com). 5633965Sjdp * 5733965Sjdp */ 5833965Sjdp 5933965Sjdp#include "cryptlib.h" 6033965Sjdp#include <openssl/x509.h> 6133965Sjdp#include <openssl/x509v3.h> 6233965Sjdp 6333965Sjdp#include "pcy_int.h" 6433965Sjdp 6533965Sjdpstatic int policy_data_cmp(const X509_POLICY_DATA * const *a, 6633965Sjdp const X509_POLICY_DATA * const *b); 6733965Sjdpstatic int policy_cache_set_int(long *out, ASN1_INTEGER *value); 6833965Sjdp 6933965Sjdp/* Set cache entry according to CertificatePolicies extension. 7033965Sjdp * Note: this destroys the passed CERTIFICATEPOLICIES structure. 7133965Sjdp */ 7233965Sjdp 7333965Sjdpstatic int policy_cache_create(X509 *x, 7433965Sjdp CERTIFICATEPOLICIES *policies, int crit) 7533965Sjdp { 7633965Sjdp int i; 7733965Sjdp int ret = 0; 7833965Sjdp X509_POLICY_CACHE *cache = x->policy_cache; 7933965Sjdp X509_POLICY_DATA *data = NULL; 8033965Sjdp POLICYINFO *policy; 8133965Sjdp if (sk_POLICYINFO_num(policies) == 0) 8233965Sjdp goto bad_policy; 8333965Sjdp cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp); 8433965Sjdp if (!cache->data) 8533965Sjdp goto bad_policy; 8633965Sjdp for (i = 0; i < sk_POLICYINFO_num(policies); i++) 8733965Sjdp { 8833965Sjdp policy = sk_POLICYINFO_value(policies, i); 8933965Sjdp data = policy_data_new(policy, NULL, crit); 9033965Sjdp if (!data) 9133965Sjdp goto bad_policy; 9233965Sjdp /* Duplicate policy OIDs are illegal: reject if matches 9333965Sjdp * found. 9433965Sjdp */ 9533965Sjdp if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) 9633965Sjdp { 9733965Sjdp if (cache->anyPolicy) 9833965Sjdp { 9933965Sjdp ret = -1; 10033965Sjdp goto bad_policy; 10133965Sjdp } 10233965Sjdp cache->anyPolicy = data; 10333965Sjdp } 10460510Sobrien else if (sk_X509_POLICY_DATA_find(cache->data, data) != -1) 10560510Sobrien { 10633965Sjdp ret = -1; 10733965Sjdp goto bad_policy; 10833965Sjdp } 10933965Sjdp else if (!sk_X509_POLICY_DATA_push(cache->data, data)) 11060510Sobrien goto bad_policy; 11160510Sobrien data = NULL; 11260510Sobrien } 11333965Sjdp ret = 1; 11433965Sjdp bad_policy: 11533965Sjdp if (ret == -1) 11633965Sjdp x->ex_flags |= EXFLAG_INVALID_POLICY; 11733965Sjdp if (data) 11833965Sjdp policy_data_free(data); 11933965Sjdp sk_POLICYINFO_pop_free(policies, POLICYINFO_free); 12033965Sjdp if (ret <= 0) 12133965Sjdp { 12233965Sjdp sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); 12333965Sjdp cache->data = NULL; 12433965Sjdp } 12533965Sjdp return ret; 12633965Sjdp } 12733965Sjdp 12833965Sjdp 12933965Sjdpstatic int policy_cache_new(X509 *x) 13048850Sdfr { 13148850Sdfr X509_POLICY_CACHE *cache; 13260510Sobrien ASN1_INTEGER *ext_any = NULL; 13360510Sobrien POLICY_CONSTRAINTS *ext_pcons = NULL; 13433965Sjdp CERTIFICATEPOLICIES *ext_cpols = NULL; 13533965Sjdp POLICY_MAPPINGS *ext_pmaps = NULL; 13633965Sjdp int i; 13733965Sjdp cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE)); 13833965Sjdp if (!cache) 13933965Sjdp return 0; 14033965Sjdp cache->anyPolicy = NULL; 14133965Sjdp cache->data = NULL; 14233965Sjdp cache->maps = NULL; 14333965Sjdp cache->any_skip = -1; 14433965Sjdp cache->explicit_skip = -1; 14533965Sjdp cache->map_skip = -1; 14633965Sjdp 14733965Sjdp x->policy_cache = cache; 14833965Sjdp 14933965Sjdp /* Handle requireExplicitPolicy *first*. Need to process this 15033965Sjdp * even if we don't have any policies. 15133965Sjdp */ 15233965Sjdp ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL); 15333965Sjdp 15433965Sjdp if (!ext_pcons) 15533965Sjdp { 15633965Sjdp if (i != -1) 15733965Sjdp goto bad_cache; 15833965Sjdp } 15933965Sjdp else 16033965Sjdp { 16133965Sjdp if (!ext_pcons->requireExplicitPolicy 16233965Sjdp && !ext_pcons->inhibitPolicyMapping) 16333965Sjdp goto bad_cache; 16433965Sjdp if (!policy_cache_set_int(&cache->explicit_skip, 16533965Sjdp ext_pcons->requireExplicitPolicy)) 16633965Sjdp goto bad_cache; 16733965Sjdp if (!policy_cache_set_int(&cache->map_skip, 16833965Sjdp ext_pcons->inhibitPolicyMapping)) 16933965Sjdp goto bad_cache; 17060510Sobrien } 17160510Sobrien 17233965Sjdp /* Process CertificatePolicies */ 17333965Sjdp 17433965Sjdp ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL); 17533965Sjdp /* If no CertificatePolicies extension or problem decoding then 17633965Sjdp * there is no point continuing because the valid policies will be 17733965Sjdp * NULL. 17833965Sjdp */ 17933965Sjdp if (!ext_cpols) 18033965Sjdp { 18133965Sjdp /* If not absent some problem with extension */ 18233965Sjdp if (i != -1) 18333965Sjdp goto bad_cache; 18433965Sjdp return 1; 18533965Sjdp } 18633965Sjdp 18733965Sjdp i = policy_cache_create(x, ext_cpols, i); 18833965Sjdp 18933965Sjdp /* NB: ext_cpols freed by policy_cache_set_policies */ 19033965Sjdp 19133965Sjdp if (i <= 0) 19233965Sjdp return i; 19333965Sjdp 19433965Sjdp ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL); 19533965Sjdp 19633965Sjdp if (!ext_pmaps) 19733965Sjdp { 19833965Sjdp /* If not absent some problem with extension */ 19933965Sjdp if (i != -1) 20033965Sjdp goto bad_cache; 20133965Sjdp } 20233965Sjdp else 20333965Sjdp { 20433965Sjdp i = policy_cache_set_mapping(x, ext_pmaps); 20533965Sjdp if (i <= 0) 20633965Sjdp goto bad_cache; 20733965Sjdp } 20833965Sjdp 20933965Sjdp ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL); 21033965Sjdp 21133965Sjdp if (!ext_any) 21233965Sjdp { 21333965Sjdp if (i != -1) 21433965Sjdp goto bad_cache; 21533965Sjdp } 21633965Sjdp else if (!policy_cache_set_int(&cache->any_skip, ext_any)) 21733965Sjdp goto bad_cache; 21833965Sjdp 21933965Sjdp if (0) 22033965Sjdp { 22133965Sjdp bad_cache: 22233965Sjdp x->ex_flags |= EXFLAG_INVALID_POLICY; 22333965Sjdp } 22433965Sjdp 22533965Sjdp if(ext_pcons) 22633965Sjdp POLICY_CONSTRAINTS_free(ext_pcons); 22733965Sjdp 22833965Sjdp if (ext_any) 22933965Sjdp ASN1_INTEGER_free(ext_any); 23060510Sobrien 23160510Sobrien return 1; 23260510Sobrien 23360510Sobrien 23460510Sobrien} 23560510Sobrien 23660510Sobrienvoid policy_cache_free(X509_POLICY_CACHE *cache) 23733965Sjdp { 23833965Sjdp if (!cache) 23933965Sjdp return; 24033965Sjdp if (cache->anyPolicy) 24133965Sjdp policy_data_free(cache->anyPolicy); 24233965Sjdp if (cache->data) 24333965Sjdp sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); 24433965Sjdp OPENSSL_free(cache); 24533965Sjdp } 24633965Sjdp 24733965Sjdpconst X509_POLICY_CACHE *policy_cache_set(X509 *x) 24833965Sjdp { 24933965Sjdp 25033965Sjdp if (x->policy_cache == NULL) 25133965Sjdp { 25233965Sjdp CRYPTO_w_lock(CRYPTO_LOCK_X509); 25333965Sjdp policy_cache_new(x); 25433965Sjdp CRYPTO_w_unlock(CRYPTO_LOCK_X509); 25533965Sjdp } 25633965Sjdp 25733965Sjdp return x->policy_cache; 25833965Sjdp 25933965Sjdp } 26033965Sjdp 26133965SjdpX509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, 26233965Sjdp const ASN1_OBJECT *id) 26333965Sjdp { 26433965Sjdp int idx; 26533965Sjdp X509_POLICY_DATA tmp; 26633965Sjdp tmp.valid_policy = (ASN1_OBJECT *)id; 26733965Sjdp idx = sk_X509_POLICY_DATA_find(cache->data, &tmp); 26833965Sjdp if (idx == -1) 26933965Sjdp return NULL; 27033965Sjdp return sk_X509_POLICY_DATA_value(cache->data, idx); 27133965Sjdp } 27233965Sjdp 27333965Sjdpstatic int policy_data_cmp(const X509_POLICY_DATA * const *a, 27433965Sjdp const X509_POLICY_DATA * const *b) 27533965Sjdp { 27633965Sjdp return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy); 27733965Sjdp } 27833965Sjdp 27933965Sjdpstatic int policy_cache_set_int(long *out, ASN1_INTEGER *value) 28033965Sjdp { 28133965Sjdp if (value == NULL) 28233965Sjdp return 1; 28333965Sjdp if (value->type == V_ASN1_NEG_INTEGER) 28433965Sjdp return 0; 28533965Sjdp *out = ASN1_INTEGER_get(value); 28633965Sjdp return 1; 28733965Sjdp } 28833965Sjdp