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 64static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b); 65static void trtable_free(X509_TRUST *p); 66 67static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); 68static int trust_1oid(X509_TRUST *trust, X509 *x, int flags); 69static int trust_compat(X509_TRUST *trust, X509 *x, int flags); 70 71static int obj_trust(int id, X509 *x, int flags); 72static 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 80static 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 99IMPLEMENT_STACK_OF(X509_TRUST) 100 101static STACK_OF(X509_TRUST) *trtable = NULL; 102 103static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b) 104{ 105 return (*a)->trust - (*b)->trust; 106} 107 108int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, 109 int) { 110 int (*oldtrust) (int, X509 *, int); 111 oldtrust = default_trust; 112 default_trust = trust; 113 return oldtrust; 114} 115 116int X509_check_trust(X509 *x, int id, int flags) 117{ 118 X509_TRUST *pt; 119 int idx; 120 if (id == -1) 121 return 1; 122 /* We get this as a default value */ 123 if (id == 0) { 124 int rv; 125 rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); 126 if (rv != X509_TRUST_UNTRUSTED) 127 return rv; 128 return trust_compat(NULL, x, 0); 129 } 130 idx = X509_TRUST_get_by_id(id); 131 if (idx == -1) 132 return default_trust(id, x, flags); 133 pt = X509_TRUST_get0(idx); 134 return pt->check_trust(pt, x, flags); 135} 136 137int X509_TRUST_get_count(void) 138{ 139 if (!trtable) 140 return X509_TRUST_COUNT; 141 return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; 142} 143 144X509_TRUST *X509_TRUST_get0(int idx) 145{ 146 if (idx < 0) 147 return NULL; 148 if (idx < (int)X509_TRUST_COUNT) 149 return trstandard + idx; 150 return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); 151} 152 153int X509_TRUST_get_by_id(int id) 154{ 155 X509_TRUST tmp; 156 int idx; 157 if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) 158 return id - X509_TRUST_MIN; 159 tmp.trust = id; 160 if (!trtable) 161 return -1; 162 idx = sk_X509_TRUST_find(trtable, &tmp); 163 if (idx == -1) 164 return -1; 165 return idx + X509_TRUST_COUNT; 166} 167 168int X509_TRUST_set(int *t, int trust) 169{ 170 if (X509_TRUST_get_by_id(trust) == -1) { 171 X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST); 172 return 0; 173 } 174 *t = trust; 175 return 1; 176} 177 178int 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 flags &= ~X509_TRUST_DYNAMIC; 187 /* This will always be set for application modified trust entries */ 188 flags |= X509_TRUST_DYNAMIC_NAME; 189 /* Get existing entry if any */ 190 idx = X509_TRUST_get_by_id(id); 191 /* Need a new entry */ 192 if (idx == -1) { 193 if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { 194 X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); 195 return 0; 196 } 197 trtmp->flags = X509_TRUST_DYNAMIC; 198 } else 199 trtmp = X509_TRUST_get0(idx); 200 201 /* OPENSSL_free existing name if dynamic */ 202 if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) 203 OPENSSL_free(trtmp->name); 204 /* dup supplied name */ 205 if (!(trtmp->name = BUF_strdup(name))) { 206 X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); 207 return 0; 208 } 209 /* Keep the dynamic flag of existing entry */ 210 trtmp->flags &= X509_TRUST_DYNAMIC; 211 /* Set all other flags */ 212 trtmp->flags |= flags; 213 214 trtmp->trust = id; 215 trtmp->check_trust = ck; 216 trtmp->arg1 = arg1; 217 trtmp->arg2 = arg2; 218 219 /* If its a new entry manage the dynamic table */ 220 if (idx == -1) { 221 if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { 222 X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); 223 return 0; 224 } 225 if (!sk_X509_TRUST_push(trtable, trtmp)) { 226 X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); 227 return 0; 228 } 229 } 230 return 1; 231} 232 233static void trtable_free(X509_TRUST *p) 234{ 235 if (!p) 236 return; 237 if (p->flags & X509_TRUST_DYNAMIC) { 238 if (p->flags & X509_TRUST_DYNAMIC_NAME) 239 OPENSSL_free(p->name); 240 OPENSSL_free(p); 241 } 242} 243 244void X509_TRUST_cleanup(void) 245{ 246 unsigned int i; 247 for (i = 0; i < X509_TRUST_COUNT; i++) 248 trtable_free(trstandard + i); 249 sk_X509_TRUST_pop_free(trtable, trtable_free); 250 trtable = NULL; 251} 252 253int X509_TRUST_get_flags(X509_TRUST *xp) 254{ 255 return xp->flags; 256} 257 258char *X509_TRUST_get0_name(X509_TRUST *xp) 259{ 260 return xp->name; 261} 262 263int X509_TRUST_get_trust(X509_TRUST *xp) 264{ 265 return xp->trust; 266} 267 268static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) 269{ 270 if (x->aux && (x->aux->trust || x->aux->reject)) 271 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 return trust_compat(trust, x, flags); 277} 278 279static int trust_1oid(X509_TRUST *trust, X509 *x, int flags) 280{ 281 if (x->aux) 282 return obj_trust(trust->arg1, x, flags); 283 return X509_TRUST_UNTRUSTED; 284} 285 286static int trust_compat(X509_TRUST *trust, X509 *x, int flags) 287{ 288 X509_check_purpose(x, -1, 0); 289 if (x->ex_flags & EXFLAG_SS) 290 return X509_TRUST_TRUSTED; 291 else 292 return X509_TRUST_UNTRUSTED; 293} 294 295static int obj_trust(int id, X509 *x, int flags) 296{ 297 ASN1_OBJECT *obj; 298 int i; 299 X509_CERT_AUX *ax; 300 ax = x->aux; 301 if (!ax) 302 return X509_TRUST_UNTRUSTED; 303 if (ax->reject) { 304 for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { 305 obj = sk_ASN1_OBJECT_value(ax->reject, i); 306 if (OBJ_obj2nid(obj) == id) 307 return X509_TRUST_REJECTED; 308 } 309 } 310 if (ax->trust) { 311 for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { 312 obj = sk_ASN1_OBJECT_value(ax->trust, i); 313 if (OBJ_obj2nid(obj) == id) 314 return X509_TRUST_TRUSTED; 315 } 316 } 317 return X509_TRUST_UNTRUSTED; 318} 319