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