Line data Source code
1 : /* pcy_cache.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 : * 2004.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * licensing@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : * This product includes cryptographic software written by Eric Young
55 : * (eay@cryptsoft.com). This product includes software written by Tim
56 : * Hudson (tjh@cryptsoft.com).
57 : *
58 : */
59 :
60 : #include "cryptlib.h"
61 : #include <openssl/x509.h>
62 : #include <openssl/x509v3.h>
63 :
64 : #include "pcy_int.h"
65 :
66 : static int policy_data_cmp(const X509_POLICY_DATA *const *a,
67 : const X509_POLICY_DATA *const *b);
68 : static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
69 :
70 : /*
71 : * Set cache entry according to CertificatePolicies extension. Note: this
72 : * destroys the passed CERTIFICATEPOLICIES structure.
73 : */
74 :
75 0 : static int policy_cache_create(X509 *x,
76 : CERTIFICATEPOLICIES *policies, int crit)
77 : {
78 : int i;
79 : int ret = 0;
80 0 : X509_POLICY_CACHE *cache = x->policy_cache;
81 : X509_POLICY_DATA *data = NULL;
82 : POLICYINFO *policy;
83 0 : if (sk_POLICYINFO_num(policies) == 0)
84 : goto bad_policy;
85 0 : cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
86 0 : if (!cache->data)
87 : goto bad_policy;
88 0 : for (i = 0; i < sk_POLICYINFO_num(policies); i++) {
89 0 : policy = sk_POLICYINFO_value(policies, i);
90 0 : data = policy_data_new(policy, NULL, crit);
91 0 : if (!data)
92 : goto bad_policy;
93 : /*
94 : * Duplicate policy OIDs are illegal: reject if matches found.
95 : */
96 0 : if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
97 0 : if (cache->anyPolicy) {
98 : ret = -1;
99 : goto bad_policy;
100 : }
101 0 : cache->anyPolicy = data;
102 0 : } else if (sk_X509_POLICY_DATA_find(cache->data, data) != -1) {
103 : ret = -1;
104 : goto bad_policy;
105 0 : } else if (!sk_X509_POLICY_DATA_push(cache->data, data))
106 : goto bad_policy;
107 : data = NULL;
108 : }
109 : ret = 1;
110 : bad_policy:
111 0 : if (ret == -1)
112 0 : x->ex_flags |= EXFLAG_INVALID_POLICY;
113 0 : if (data)
114 0 : policy_data_free(data);
115 0 : sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
116 0 : if (ret <= 0) {
117 0 : sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
118 0 : cache->data = NULL;
119 : }
120 0 : return ret;
121 : }
122 :
123 0 : static int policy_cache_new(X509 *x)
124 : {
125 : X509_POLICY_CACHE *cache;
126 : ASN1_INTEGER *ext_any = NULL;
127 : POLICY_CONSTRAINTS *ext_pcons = NULL;
128 : CERTIFICATEPOLICIES *ext_cpols = NULL;
129 : POLICY_MAPPINGS *ext_pmaps = NULL;
130 : int i;
131 0 : cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE));
132 0 : if (!cache)
133 : return 0;
134 0 : cache->anyPolicy = NULL;
135 0 : cache->data = NULL;
136 0 : cache->any_skip = -1;
137 0 : cache->explicit_skip = -1;
138 0 : cache->map_skip = -1;
139 :
140 0 : x->policy_cache = cache;
141 :
142 : /*
143 : * Handle requireExplicitPolicy *first*. Need to process this even if we
144 : * don't have any policies.
145 : */
146 0 : ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
147 :
148 0 : if (!ext_pcons) {
149 0 : if (i != -1)
150 : goto bad_cache;
151 : } else {
152 0 : if (!ext_pcons->requireExplicitPolicy
153 0 : && !ext_pcons->inhibitPolicyMapping)
154 : goto bad_cache;
155 0 : if (!policy_cache_set_int(&cache->explicit_skip,
156 : ext_pcons->requireExplicitPolicy))
157 : goto bad_cache;
158 0 : if (!policy_cache_set_int(&cache->map_skip,
159 : ext_pcons->inhibitPolicyMapping))
160 : goto bad_cache;
161 : }
162 :
163 : /* Process CertificatePolicies */
164 :
165 0 : ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
166 : /*
167 : * If no CertificatePolicies extension or problem decoding then there is
168 : * no point continuing because the valid policies will be NULL.
169 : */
170 0 : if (!ext_cpols) {
171 : /* If not absent some problem with extension */
172 0 : if (i != -1)
173 : goto bad_cache;
174 : return 1;
175 : }
176 :
177 0 : i = policy_cache_create(x, ext_cpols, i);
178 :
179 : /* NB: ext_cpols freed by policy_cache_set_policies */
180 :
181 0 : if (i <= 0)
182 : return i;
183 :
184 0 : ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
185 :
186 0 : if (!ext_pmaps) {
187 : /* If not absent some problem with extension */
188 0 : if (i != -1)
189 : goto bad_cache;
190 : } else {
191 0 : i = policy_cache_set_mapping(x, ext_pmaps);
192 0 : if (i <= 0)
193 : goto bad_cache;
194 : }
195 :
196 0 : ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
197 :
198 0 : if (!ext_any) {
199 0 : if (i != -1)
200 : goto bad_cache;
201 0 : } else if (!policy_cache_set_int(&cache->any_skip, ext_any))
202 : goto bad_cache;
203 :
204 : if (0) {
205 : bad_cache:
206 0 : x->ex_flags |= EXFLAG_INVALID_POLICY;
207 : }
208 :
209 0 : if (ext_pcons)
210 0 : POLICY_CONSTRAINTS_free(ext_pcons);
211 :
212 0 : if (ext_any)
213 0 : ASN1_INTEGER_free(ext_any);
214 :
215 : return 1;
216 :
217 : }
218 :
219 1681 : void policy_cache_free(X509_POLICY_CACHE *cache)
220 : {
221 1681 : if (!cache)
222 1681 : return;
223 0 : if (cache->anyPolicy)
224 0 : policy_data_free(cache->anyPolicy);
225 0 : if (cache->data)
226 0 : sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
227 0 : OPENSSL_free(cache);
228 : }
229 :
230 0 : const X509_POLICY_CACHE *policy_cache_set(X509 *x)
231 : {
232 :
233 0 : if (x->policy_cache == NULL) {
234 0 : CRYPTO_w_lock(CRYPTO_LOCK_X509);
235 0 : policy_cache_new(x);
236 0 : CRYPTO_w_unlock(CRYPTO_LOCK_X509);
237 : }
238 :
239 0 : return x->policy_cache;
240 :
241 : }
242 :
243 0 : X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
244 : const ASN1_OBJECT *id)
245 : {
246 : int idx;
247 : X509_POLICY_DATA tmp;
248 0 : tmp.valid_policy = (ASN1_OBJECT *)id;
249 0 : idx = sk_X509_POLICY_DATA_find(cache->data, &tmp);
250 0 : if (idx == -1)
251 : return NULL;
252 0 : return sk_X509_POLICY_DATA_value(cache->data, idx);
253 : }
254 :
255 0 : static int policy_data_cmp(const X509_POLICY_DATA *const *a,
256 : const X509_POLICY_DATA *const *b)
257 : {
258 0 : return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
259 : }
260 :
261 : static int policy_cache_set_int(long *out, ASN1_INTEGER *value)
262 : {
263 0 : if (value == NULL)
264 : return 1;
265 0 : if (value->type == V_ASN1_NEG_INTEGER)
266 : return 0;
267 0 : *out = ASN1_INTEGER_get(value);
268 : return 1;
269 : }
|