159191Skris/* x509_trs.c */ 2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 359191Skris * project 1999. 459191Skris */ 559191Skris/* ==================================================================== 659191Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 759191Skris * 859191Skris * Redistribution and use in source and binary forms, with or without 959191Skris * modification, are permitted provided that the following conditions 1059191Skris * are met: 1159191Skris * 1259191Skris * 1. Redistributions of source code must retain the above copyright 1359191Skris * notice, this list of conditions and the following disclaimer. 1459191Skris * 1559191Skris * 2. Redistributions in binary form must reproduce the above copyright 1659191Skris * notice, this list of conditions and the following disclaimer in 1759191Skris * the documentation and/or other materials provided with the 1859191Skris * distribution. 1959191Skris * 2059191Skris * 3. All advertising materials mentioning features or use of this 2159191Skris * software must display the following acknowledgment: 2259191Skris * "This product includes software developed by the OpenSSL Project 2359191Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2459191Skris * 2559191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2659191Skris * endorse or promote products derived from this software without 2759191Skris * prior written permission. For written permission, please contact 2859191Skris * licensing@OpenSSL.org. 2959191Skris * 3059191Skris * 5. Products derived from this software may not be called "OpenSSL" 3159191Skris * nor may "OpenSSL" appear in their names without prior written 3259191Skris * permission of the OpenSSL Project. 3359191Skris * 3459191Skris * 6. Redistributions of any form whatsoever must retain the following 3559191Skris * acknowledgment: 3659191Skris * "This product includes software developed by the OpenSSL Project 3759191Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3859191Skris * 3959191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4059191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4159191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4259191Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4359191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4459191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4559191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4659191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4759191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4859191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4959191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5059191Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5159191Skris * ==================================================================== 5259191Skris * 5359191Skris * This product includes cryptographic software written by Eric Young 5459191Skris * (eay@cryptsoft.com). This product includes software written by Tim 5559191Skris * Hudson (tjh@cryptsoft.com). 5659191Skris * 5759191Skris */ 5859191Skris 5959191Skris#include <stdio.h> 6059191Skris#include "cryptlib.h" 6159191Skris#include <openssl/x509v3.h> 6259191Skris 6359191Skris 6468651Skrisstatic int tr_cmp(const X509_TRUST * const *a, 6568651Skris const X509_TRUST * const *b); 6659191Skrisstatic void trtable_free(X509_TRUST *p); 6759191Skris 6859191Skrisstatic int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); 69109998Smarkmstatic int trust_1oid(X509_TRUST *trust, X509 *x, int flags); 7059191Skrisstatic int trust_compat(X509_TRUST *trust, X509 *x, int flags); 7159191Skris 7259191Skrisstatic int obj_trust(int id, X509 *x, int flags); 7359191Skrisstatic int (*default_trust)(int id, X509 *x, int flags) = obj_trust; 7459191Skris 7559191Skris/* WARNING: the following table should be kept in order of trust 7659191Skris * and without any gaps so we can just subtract the minimum trust 7759191Skris * value to get an index into the table 7859191Skris */ 7959191Skris 8059191Skrisstatic X509_TRUST trstandard[] = { 8159191Skris{X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL}, 8259191Skris{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, NULL}, 8389837Skris{X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth, NULL}, 8459191Skris{X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, NULL}, 85120631Snectar{X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign, NULL}, 86109998Smarkm{X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, NULL}, 87238405Sjkim{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP, NULL}, 88238405Sjkim{X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL} 8959191Skris}; 9059191Skris 9159191Skris#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST)) 9259191Skris 9359191SkrisIMPLEMENT_STACK_OF(X509_TRUST) 9459191Skris 9559191Skrisstatic STACK_OF(X509_TRUST) *trtable = NULL; 9659191Skris 9768651Skrisstatic int tr_cmp(const X509_TRUST * const *a, 9868651Skris const X509_TRUST * const *b) 9959191Skris{ 10059191Skris return (*a)->trust - (*b)->trust; 10159191Skris} 10259191Skris 10359191Skrisint (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int) 10459191Skris{ 105109998Smarkm int (*oldtrust)(int , X509 *, int); 106109998Smarkm oldtrust = default_trust; 107109998Smarkm default_trust = trust; 108109998Smarkm return oldtrust; 10959191Skris} 11059191Skris 11159191Skris 11259191Skrisint X509_check_trust(X509 *x, int id, int flags) 11359191Skris{ 11459191Skris X509_TRUST *pt; 11559191Skris int idx; 11659191Skris if(id == -1) return 1; 11759191Skris idx = X509_TRUST_get_by_id(id); 11859191Skris if(idx == -1) return default_trust(id, x, flags); 11959191Skris pt = X509_TRUST_get0(idx); 12059191Skris return pt->check_trust(pt, x, flags); 12159191Skris} 12259191Skris 12359191Skrisint X509_TRUST_get_count(void) 12459191Skris{ 12559191Skris if(!trtable) return X509_TRUST_COUNT; 12659191Skris return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; 12759191Skris} 12859191Skris 12959191SkrisX509_TRUST * X509_TRUST_get0(int idx) 13059191Skris{ 13159191Skris if(idx < 0) return NULL; 132160814Ssimon if(idx < (int)X509_TRUST_COUNT) return trstandard + idx; 13359191Skris return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); 13459191Skris} 13559191Skris 13659191Skrisint X509_TRUST_get_by_id(int id) 13759191Skris{ 13859191Skris X509_TRUST tmp; 13959191Skris int idx; 14059191Skris if((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) 14159191Skris return id - X509_TRUST_MIN; 14259191Skris tmp.trust = id; 14359191Skris if(!trtable) return -1; 14459191Skris idx = sk_X509_TRUST_find(trtable, &tmp); 14559191Skris if(idx == -1) return -1; 14659191Skris return idx + X509_TRUST_COUNT; 14759191Skris} 14859191Skris 149109998Smarkmint X509_TRUST_set(int *t, int trust) 150109998Smarkm{ 151109998Smarkm if(X509_TRUST_get_by_id(trust) == -1) { 152109998Smarkm X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST); 153109998Smarkm return 0; 154109998Smarkm } 155109998Smarkm *t = trust; 156109998Smarkm return 1; 157109998Smarkm} 158109998Smarkm 15959191Skrisint X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), 16059191Skris char *name, int arg1, void *arg2) 16159191Skris{ 16259191Skris int idx; 16359191Skris X509_TRUST *trtmp; 16459191Skris /* This is set according to what we change: application can't set it */ 16559191Skris flags &= ~X509_TRUST_DYNAMIC; 16659191Skris /* This will always be set for application modified trust entries */ 16759191Skris flags |= X509_TRUST_DYNAMIC_NAME; 16859191Skris /* Get existing entry if any */ 16959191Skris idx = X509_TRUST_get_by_id(id); 17059191Skris /* Need a new entry */ 17159191Skris if(idx == -1) { 17268651Skris if(!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { 17359191Skris X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); 17459191Skris return 0; 17559191Skris } 17659191Skris trtmp->flags = X509_TRUST_DYNAMIC; 17759191Skris } else trtmp = X509_TRUST_get0(idx); 17859191Skris 17968651Skris /* OPENSSL_free existing name if dynamic */ 18068651Skris if(trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name); 18159191Skris /* dup supplied name */ 18259191Skris if(!(trtmp->name = BUF_strdup(name))) { 18359191Skris X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); 18459191Skris return 0; 18559191Skris } 18659191Skris /* Keep the dynamic flag of existing entry */ 18759191Skris trtmp->flags &= X509_TRUST_DYNAMIC; 18859191Skris /* Set all other flags */ 18959191Skris trtmp->flags |= flags; 19059191Skris 19159191Skris trtmp->trust = id; 19259191Skris trtmp->check_trust = ck; 19359191Skris trtmp->arg1 = arg1; 19459191Skris trtmp->arg2 = arg2; 19559191Skris 19659191Skris /* If its a new entry manage the dynamic table */ 19759191Skris if(idx == -1) { 19859191Skris if(!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { 19959191Skris X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); 20059191Skris return 0; 20159191Skris } 20259191Skris if (!sk_X509_TRUST_push(trtable, trtmp)) { 20359191Skris X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); 20459191Skris return 0; 20559191Skris } 20659191Skris } 20759191Skris return 1; 20859191Skris} 20959191Skris 21059191Skrisstatic void trtable_free(X509_TRUST *p) 21159191Skris { 21259191Skris if(!p) return; 21359191Skris if (p->flags & X509_TRUST_DYNAMIC) 21459191Skris { 21559191Skris if (p->flags & X509_TRUST_DYNAMIC_NAME) 21668651Skris OPENSSL_free(p->name); 21768651Skris OPENSSL_free(p); 21859191Skris } 21959191Skris } 22059191Skris 22159191Skrisvoid X509_TRUST_cleanup(void) 22259191Skris{ 223160814Ssimon unsigned int i; 22459191Skris for(i = 0; i < X509_TRUST_COUNT; i++) trtable_free(trstandard + i); 22559191Skris sk_X509_TRUST_pop_free(trtable, trtable_free); 22659191Skris trtable = NULL; 22759191Skris} 22859191Skris 22959191Skrisint X509_TRUST_get_flags(X509_TRUST *xp) 23059191Skris{ 23159191Skris return xp->flags; 23259191Skris} 23359191Skris 23459191Skrischar *X509_TRUST_get0_name(X509_TRUST *xp) 23559191Skris{ 23659191Skris return xp->name; 23759191Skris} 23859191Skris 23959191Skrisint X509_TRUST_get_trust(X509_TRUST *xp) 24059191Skris{ 24159191Skris return xp->trust; 24259191Skris} 24359191Skris 24459191Skrisstatic int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) 24559191Skris{ 24679998Skris if(x->aux && (x->aux->trust || x->aux->reject)) 24779998Skris return obj_trust(trust->arg1, x, flags); 24859191Skris /* we don't have any trust settings: for compatibility 24959191Skris * we return trusted if it is self signed 25059191Skris */ 25159191Skris return trust_compat(trust, x, flags); 25259191Skris} 25359191Skris 254109998Smarkmstatic int trust_1oid(X509_TRUST *trust, X509 *x, int flags) 255109998Smarkm{ 256109998Smarkm if(x->aux) return obj_trust(trust->arg1, x, flags); 257109998Smarkm return X509_TRUST_UNTRUSTED; 258109998Smarkm} 259109998Smarkm 26059191Skrisstatic int trust_compat(X509_TRUST *trust, X509 *x, int flags) 26159191Skris{ 26259191Skris X509_check_purpose(x, -1, 0); 26359191Skris if(x->ex_flags & EXFLAG_SS) return X509_TRUST_TRUSTED; 26459191Skris else return X509_TRUST_UNTRUSTED; 26559191Skris} 26659191Skris 26759191Skrisstatic int obj_trust(int id, X509 *x, int flags) 26859191Skris{ 26959191Skris ASN1_OBJECT *obj; 27059191Skris int i; 27159191Skris X509_CERT_AUX *ax; 27259191Skris ax = x->aux; 27359191Skris if(!ax) return X509_TRUST_UNTRUSTED; 27459191Skris if(ax->reject) { 27559191Skris for(i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { 27659191Skris obj = sk_ASN1_OBJECT_value(ax->reject, i); 27759191Skris if(OBJ_obj2nid(obj) == id) return X509_TRUST_REJECTED; 27859191Skris } 27959191Skris } 28059191Skris if(ax->trust) { 28159191Skris for(i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { 28259191Skris obj = sk_ASN1_OBJECT_value(ax->trust, i); 28359191Skris if(OBJ_obj2nid(obj) == id) return X509_TRUST_TRUSTED; 28459191Skris } 28559191Skris } 28659191Skris return X509_TRUST_UNTRUSTED; 28759191Skris} 28859191Skris 289