Line data Source code
1 : /* x509_trs.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 : * 1999.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 1999 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 <stdio.h>
61 : #include "cryptlib.h"
62 : #include <openssl/x509v3.h>
63 :
64 : static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b);
65 : static void trtable_free(X509_TRUST *p);
66 :
67 : static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
68 : static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
69 : static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
70 :
71 : static int obj_trust(int id, X509 *x, int flags);
72 : static int (*default_trust) (int id, X509 *x, int flags) = obj_trust;
73 :
74 : /*
75 : * WARNING: the following table should be kept in order of trust and without
76 : * any gaps so we can just subtract the minimum trust value to get an index
77 : * into the table
78 : */
79 :
80 : static X509_TRUST trstandard[] = {
81 : {X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL},
82 : {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth,
83 : NULL},
84 : {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth,
85 : NULL},
86 : {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect,
87 : NULL},
88 : {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign,
89 : NULL},
90 : {X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign,
91 : NULL},
92 : {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP,
93 : NULL},
94 : {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL}
95 : };
96 :
97 : #define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST))
98 :
99 : IMPLEMENT_STACK_OF(X509_TRUST)
100 :
101 : static STACK_OF(X509_TRUST) *trtable = NULL;
102 :
103 0 : static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b)
104 : {
105 0 : return (*a)->trust - (*b)->trust;
106 : }
107 :
108 0 : int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
109 : int) {
110 : int (*oldtrust) (int, X509 *, int);
111 0 : oldtrust = default_trust;
112 0 : default_trust = trust;
113 0 : return oldtrust;
114 : }
115 :
116 370 : int X509_check_trust(X509 *x, int id, int flags)
117 : {
118 : X509_TRUST *pt;
119 : int idx;
120 370 : if (id == -1)
121 : return 1;
122 : /* We get this as a default value */
123 370 : if (id == 0) {
124 : int rv;
125 0 : rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
126 0 : if (rv != X509_TRUST_UNTRUSTED)
127 : return rv;
128 0 : return trust_compat(NULL, x, 0);
129 : }
130 370 : idx = X509_TRUST_get_by_id(id);
131 370 : if (idx == -1)
132 0 : return default_trust(id, x, flags);
133 370 : pt = X509_TRUST_get0(idx);
134 370 : return pt->check_trust(pt, x, flags);
135 : }
136 :
137 0 : int X509_TRUST_get_count(void)
138 : {
139 0 : if (!trtable)
140 : return X509_TRUST_COUNT;
141 0 : return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
142 : }
143 :
144 370 : X509_TRUST *X509_TRUST_get0(int idx)
145 : {
146 370 : if (idx < 0)
147 : return NULL;
148 370 : if (idx < (int)X509_TRUST_COUNT)
149 370 : return trstandard + idx;
150 0 : return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
151 : }
152 :
153 370 : int X509_TRUST_get_by_id(int id)
154 : {
155 : X509_TRUST tmp;
156 : int idx;
157 370 : if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
158 370 : return id - X509_TRUST_MIN;
159 0 : tmp.trust = id;
160 0 : if (!trtable)
161 : return -1;
162 0 : idx = sk_X509_TRUST_find(trtable, &tmp);
163 0 : if (idx == -1)
164 : return -1;
165 0 : return idx + X509_TRUST_COUNT;
166 : }
167 :
168 0 : int X509_TRUST_set(int *t, int trust)
169 : {
170 0 : if (X509_TRUST_get_by_id(trust) == -1) {
171 0 : X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST);
172 0 : return 0;
173 : }
174 0 : *t = trust;
175 0 : return 1;
176 : }
177 :
178 0 : int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
179 : char *name, int arg1, void *arg2)
180 : {
181 : int idx;
182 : X509_TRUST *trtmp;
183 : /*
184 : * This is set according to what we change: application can't set it
185 : */
186 0 : flags &= ~X509_TRUST_DYNAMIC;
187 : /* This will always be set for application modified trust entries */
188 0 : flags |= X509_TRUST_DYNAMIC_NAME;
189 : /* Get existing entry if any */
190 0 : idx = X509_TRUST_get_by_id(id);
191 : /* Need a new entry */
192 0 : if (idx == -1) {
193 0 : if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) {
194 0 : X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
195 0 : return 0;
196 : }
197 0 : trtmp->flags = X509_TRUST_DYNAMIC;
198 : } else
199 0 : trtmp = X509_TRUST_get0(idx);
200 :
201 : /* OPENSSL_free existing name if dynamic */
202 0 : if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
203 0 : OPENSSL_free(trtmp->name);
204 : /* dup supplied name */
205 0 : if (!(trtmp->name = BUF_strdup(name))) {
206 0 : X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
207 0 : return 0;
208 : }
209 : /* Keep the dynamic flag of existing entry */
210 0 : trtmp->flags &= X509_TRUST_DYNAMIC;
211 : /* Set all other flags */
212 0 : trtmp->flags |= flags;
213 :
214 0 : trtmp->trust = id;
215 0 : trtmp->check_trust = ck;
216 0 : trtmp->arg1 = arg1;
217 0 : trtmp->arg2 = arg2;
218 :
219 : /* If its a new entry manage the dynamic table */
220 0 : if (idx == -1) {
221 0 : if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
222 0 : X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
223 0 : return 0;
224 : }
225 0 : if (!sk_X509_TRUST_push(trtable, trtmp)) {
226 0 : X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
227 0 : return 0;
228 : }
229 : }
230 : return 1;
231 : }
232 :
233 0 : static void trtable_free(X509_TRUST *p)
234 : {
235 0 : if (!p)
236 0 : return;
237 0 : if (p->flags & X509_TRUST_DYNAMIC) {
238 0 : if (p->flags & X509_TRUST_DYNAMIC_NAME)
239 0 : OPENSSL_free(p->name);
240 0 : OPENSSL_free(p);
241 : }
242 : }
243 :
244 0 : void X509_TRUST_cleanup(void)
245 : {
246 : unsigned int i;
247 0 : for (i = 0; i < X509_TRUST_COUNT; i++)
248 0 : trtable_free(trstandard + i);
249 0 : sk_X509_TRUST_pop_free(trtable, trtable_free);
250 0 : trtable = NULL;
251 0 : }
252 :
253 0 : int X509_TRUST_get_flags(X509_TRUST *xp)
254 : {
255 0 : return xp->flags;
256 : }
257 :
258 0 : char *X509_TRUST_get0_name(X509_TRUST *xp)
259 : {
260 0 : return xp->name;
261 : }
262 :
263 0 : int X509_TRUST_get_trust(X509_TRUST *xp)
264 : {
265 0 : return xp->trust;
266 : }
267 :
268 370 : static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
269 : {
270 370 : if (x->aux && (x->aux->trust || x->aux->reject))
271 0 : return obj_trust(trust->arg1, x, flags);
272 : /*
273 : * we don't have any trust settings: for compatibility we return trusted
274 : * if it is self signed
275 : */
276 370 : return trust_compat(trust, x, flags);
277 : }
278 :
279 0 : static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
280 : {
281 0 : if (x->aux)
282 0 : return obj_trust(trust->arg1, x, flags);
283 : return X509_TRUST_UNTRUSTED;
284 : }
285 :
286 0 : static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
287 : {
288 370 : X509_check_purpose(x, -1, 0);
289 370 : if (x->ex_flags & EXFLAG_SS)
290 : return X509_TRUST_TRUSTED;
291 : else
292 0 : return X509_TRUST_UNTRUSTED;
293 : }
294 :
295 0 : static int obj_trust(int id, X509 *x, int flags)
296 : {
297 : ASN1_OBJECT *obj;
298 : int i;
299 : X509_CERT_AUX *ax;
300 0 : ax = x->aux;
301 0 : if (!ax)
302 : return X509_TRUST_UNTRUSTED;
303 0 : if (ax->reject) {
304 0 : for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
305 0 : obj = sk_ASN1_OBJECT_value(ax->reject, i);
306 0 : if (OBJ_obj2nid(obj) == id)
307 : return X509_TRUST_REJECTED;
308 : }
309 : }
310 0 : if (ax->trust) {
311 0 : for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
312 0 : obj = sk_ASN1_OBJECT_value(ax->trust, i);
313 0 : if (OBJ_obj2nid(obj) == id)
314 : return X509_TRUST_TRUSTED;
315 : }
316 : }
317 : return X509_TRUST_UNTRUSTED;
318 : }
|