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