Home | History | Annotate | Download | only in x509v3
      1 /* Written by Dr Stephen N Henson (steve (at) 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     54  * Hudson (tjh (at) cryptsoft.com). */
     55 
     56 #include <openssl/mem.h>
     57 #include <openssl/obj.h>
     58 #include <openssl/thread.h>
     59 #include <openssl/x509.h>
     60 #include <openssl/x509v3.h>
     61 
     62 #include "pcy_int.h"
     63 #include "../internal.h"
     64 
     65 
     66 static int policy_data_cmp(const X509_POLICY_DATA **a,
     67 				const X509_POLICY_DATA **b);
     68 static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
     69 
     70 /* Set cache entry according to CertificatePolicies extension.
     71  * Note: this destroys the passed CERTIFICATEPOLICIES structure.
     72  */
     73 
     74 static int policy_cache_create(X509 *x,
     75 			CERTIFICATEPOLICIES *policies, int crit)
     76 	{
     77 	size_t i;
     78 	int ret = 0;
     79 	X509_POLICY_CACHE *cache = x->policy_cache;
     80 	X509_POLICY_DATA *data = NULL;
     81 	POLICYINFO *policy;
     82 	if (sk_POLICYINFO_num(policies) == 0)
     83 		goto bad_policy;
     84 	cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
     85 	if (!cache->data)
     86 		goto bad_policy;
     87 	for (i = 0; i < sk_POLICYINFO_num(policies); i++)
     88 		{
     89 		policy = sk_POLICYINFO_value(policies, i);
     90 		data = policy_data_new(policy, NULL, crit);
     91 		if (!data)
     92 			goto bad_policy;
     93 		/* Duplicate policy OIDs are illegal: reject if matches
     94 		 * found.
     95 		 */
     96 		if (OBJ_obj2nid(data->valid_policy) == NID_any_policy)
     97 			{
     98 			if (cache->anyPolicy)
     99 				{
    100 				ret = -1;
    101 				goto bad_policy;
    102 				}
    103 			cache->anyPolicy = data;
    104 			}
    105 		else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data))
    106 			{
    107 			ret = -1;
    108 			goto bad_policy;
    109 			}
    110 		else if (!sk_X509_POLICY_DATA_push(cache->data, data))
    111 			goto bad_policy;
    112 		data = NULL;
    113 		}
    114 	ret = 1;
    115 	bad_policy:
    116 	if (ret == -1)
    117 		x->ex_flags |= EXFLAG_INVALID_POLICY;
    118 	if (data)
    119 		policy_data_free(data);
    120 	sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
    121 	if (ret <= 0)
    122 		{
    123 		sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
    124 		cache->data = NULL;
    125 		}
    126 	return ret;
    127 	}
    128 
    129 
    130 static int policy_cache_new(X509 *x)
    131 	{
    132 	X509_POLICY_CACHE *cache;
    133 	ASN1_INTEGER *ext_any = NULL;
    134 	POLICY_CONSTRAINTS *ext_pcons = NULL;
    135 	CERTIFICATEPOLICIES *ext_cpols = NULL;
    136 	POLICY_MAPPINGS *ext_pmaps = NULL;
    137 	int i;
    138 	cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE));
    139 	if (!cache)
    140 		return 0;
    141 	cache->anyPolicy = NULL;
    142 	cache->data = NULL;
    143 	cache->any_skip = -1;
    144 	cache->explicit_skip = -1;
    145 	cache->map_skip = -1;
    146 
    147 	x->policy_cache = cache;
    148 
    149 	/* Handle requireExplicitPolicy *first*. Need to process this
    150 	 * even if we don't have any policies.
    151 	 */
    152 	ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
    153 
    154 	if (!ext_pcons)
    155 		{
    156 		if (i != -1)
    157 			goto bad_cache;
    158 		}
    159 	else
    160 		{
    161 		if (!ext_pcons->requireExplicitPolicy
    162 			&& !ext_pcons->inhibitPolicyMapping)
    163 			goto bad_cache;
    164 		if (!policy_cache_set_int(&cache->explicit_skip,
    165 			ext_pcons->requireExplicitPolicy))
    166 			goto bad_cache;
    167 		if (!policy_cache_set_int(&cache->map_skip,
    168 			ext_pcons->inhibitPolicyMapping))
    169 			goto bad_cache;
    170 		}
    171 
    172 	/* Process CertificatePolicies */
    173 
    174 	ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
    175 	/* If no CertificatePolicies extension or problem decoding then
    176 	 * there is no point continuing because the valid policies will be
    177 	 * NULL.
    178 	 */
    179 	if (!ext_cpols)
    180 		{
    181 		/* If not absent some problem with extension */
    182 		if (i != -1)
    183 			goto bad_cache;
    184 		return 1;
    185 		}
    186 
    187 	i = policy_cache_create(x, ext_cpols, i);
    188 
    189 	/* NB: ext_cpols freed by policy_cache_set_policies */
    190 
    191 	if (i <= 0)
    192 		return i;
    193 
    194 	ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
    195 
    196 	if (!ext_pmaps)
    197 		{
    198 		/* If not absent some problem with extension */
    199 		if (i != -1)
    200 			goto bad_cache;
    201 		}
    202 	else
    203 		{
    204 		i = policy_cache_set_mapping(x, ext_pmaps);
    205 		if (i <= 0)
    206 			goto bad_cache;
    207 		}
    208 
    209 	ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
    210 
    211 	if (!ext_any)
    212 		{
    213 		if (i != -1)
    214 			goto bad_cache;
    215 		}
    216 	else if (!policy_cache_set_int(&cache->any_skip, ext_any))
    217 			goto bad_cache;
    218 
    219 	if (0)
    220 		{
    221 		bad_cache:
    222 		x->ex_flags |= EXFLAG_INVALID_POLICY;
    223 		}
    224 
    225 	if(ext_pcons)
    226 		POLICY_CONSTRAINTS_free(ext_pcons);
    227 
    228 	if (ext_any)
    229 		ASN1_INTEGER_free(ext_any);
    230 
    231 	return 1;
    232 
    233 
    234 }
    235 
    236 void policy_cache_free(X509_POLICY_CACHE *cache)
    237 	{
    238 	if (!cache)
    239 		return;
    240 	if (cache->anyPolicy)
    241 		policy_data_free(cache->anyPolicy);
    242 	if (cache->data)
    243 		sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
    244 	OPENSSL_free(cache);
    245 	}
    246 
    247 /* g_x509_policy_cache_lock is used to protect against concurrent calls to
    248  * |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t|
    249  * in the |X509| structure, but |CRYPTO_once_t| isn't public. */
    250 static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock =
    251     CRYPTO_STATIC_MUTEX_INIT;
    252 
    253 const X509_POLICY_CACHE *policy_cache_set(X509 *x)
    254 	{
    255 	X509_POLICY_CACHE *cache;
    256 
    257 	CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock);
    258 	cache = x->policy_cache;
    259 	CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
    260 
    261 	if (cache != NULL)
    262 		return cache;
    263 
    264 	CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock);
    265 	if (x->policy_cache == NULL)
    266 		policy_cache_new(x);
    267 	cache = x->policy_cache;
    268 	CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
    269 
    270 	return cache;
    271 	}
    272 
    273 X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
    274 						const ASN1_OBJECT *id)
    275 	{
    276 	size_t idx;
    277 	X509_POLICY_DATA tmp;
    278 
    279 	tmp.valid_policy = (ASN1_OBJECT *)id;
    280 	if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp))
    281 		return NULL;
    282 	return sk_X509_POLICY_DATA_value(cache->data, idx);
    283 	}
    284 
    285 static int policy_data_cmp(const X509_POLICY_DATA **a,
    286 				const X509_POLICY_DATA **b)
    287 	{
    288 	return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
    289 	}
    290 
    291 static int policy_cache_set_int(long *out, ASN1_INTEGER *value)
    292 	{
    293 	if (value == NULL)
    294 		return 1;
    295 	if (value->type == V_ASN1_NEG_INTEGER)
    296 		return 0;
    297 	*out = ASN1_INTEGER_get(value);
    298 	return 1;
    299 	}
    300