x509_vpm.c revision 160815
138494Sobrien/* x509_vpm.c */ 2174313Sobrien/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 338494Sobrien * project 2004. 438494Sobrien */ 538494Sobrien/* ==================================================================== 638494Sobrien * Copyright (c) 2004 The OpenSSL Project. All rights reserved. 738494Sobrien * 838494Sobrien * Redistribution and use in source and binary forms, with or without 938494Sobrien * modification, are permitted provided that the following conditions 1038494Sobrien * are met: 1138494Sobrien * 1238494Sobrien * 1. Redistributions of source code must retain the above copyright 1338494Sobrien * notice, this list of conditions and the following disclaimer. 1438494Sobrien * 1538494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1638494Sobrien * notice, this list of conditions and the following disclaimer in 1738494Sobrien * the documentation and/or other materials provided with the 1838494Sobrien * distribution. 1938494Sobrien * 2042633Sobrien * 3. All advertising materials mentioning features or use of this 2138494Sobrien * software must display the following acknowledgment: 2238494Sobrien * "This product includes software developed by the OpenSSL Project 2338494Sobrien * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2438494Sobrien * 2538494Sobrien * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2638494Sobrien * endorse or promote products derived from this software without 2738494Sobrien * prior written permission. For written permission, please contact 2838494Sobrien * licensing@OpenSSL.org. 2938494Sobrien * 3038494Sobrien * 5. Products derived from this software may not be called "OpenSSL" 3138494Sobrien * nor may "OpenSSL" appear in their names without prior written 3238494Sobrien * permission of the OpenSSL Project. 3338494Sobrien * 3438494Sobrien * 6. Redistributions of any form whatsoever must retain the following 3538494Sobrien * acknowledgment: 3638494Sobrien * "This product includes software developed by the OpenSSL Project 3738494Sobrien * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3838494Sobrien * 3938494Sobrien * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40174313Sobrien * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4138494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4238494Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4338494Sobrien * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4438494Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4538494Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4638494Sobrien * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4738494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4838494Sobrien * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4938494Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5038494Sobrien * OF THE POSSIBILITY OF SUCH DAMAGE. 5138494Sobrien * ==================================================================== 5238494Sobrien * 5338494Sobrien * This product includes cryptographic software written by Eric Young 5438494Sobrien * (eay@cryptsoft.com). This product includes software written by Tim 5538494Sobrien * Hudson (tjh@cryptsoft.com). 5638494Sobrien * 5738494Sobrien */ 5838494Sobrien 5938494Sobrien#include <stdio.h> 6038494Sobrien 6138494Sobrien#include "cryptlib.h" 6238494Sobrien#include <openssl/crypto.h> 6338494Sobrien#include <openssl/lhash.h> 6438494Sobrien#include <openssl/buffer.h> 6538494Sobrien#include <openssl/x509.h> 6638500Sobrien#include <openssl/x509v3.h> 6738494Sobrien 6838494Sobrien/* X509_VERIFY_PARAM functions */ 6938494Sobrien 7038494Sobrienstatic void x509_verify_param_zero(X509_VERIFY_PARAM *param) 7138494Sobrien { 7238494Sobrien if (!param) 7338494Sobrien return; 7438494Sobrien param->name = NULL; 7538494Sobrien param->purpose = 0; 7638494Sobrien param->trust = 0; 7738494Sobrien param->inh_flags = X509_VP_FLAG_DEFAULT; 7838494Sobrien param->flags = 0; 7938494Sobrien param->depth = -1; 8038494Sobrien if (param->policies) 8138494Sobrien { 8238494Sobrien sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); 8338494Sobrien param->policies = NULL; 8438494Sobrien } 8538494Sobrien } 8638494Sobrien 8738494SobrienX509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) 8838494Sobrien { 8938494Sobrien X509_VERIFY_PARAM *param; 9038494Sobrien param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM)); 9138494Sobrien memset(param, 0, sizeof(X509_VERIFY_PARAM)); 9238494Sobrien x509_verify_param_zero(param); 9338494Sobrien return param; 9438494Sobrien } 9538494Sobrien 9638494Sobrienvoid X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) 9738494Sobrien { 9838494Sobrien x509_verify_param_zero(param); 9938494Sobrien OPENSSL_free(param); 10038494Sobrien } 10138494Sobrien 10238494Sobrien/* This function determines how parameters are "inherited" from one structure 10338494Sobrien * to another. There are several different ways this can happen. 10438494Sobrien * 10538494Sobrien * 1. If a child structure needs to have its values initialized from a parent 10638494Sobrien * they are simply copied across. For example SSL_CTX copied to SSL. 10738494Sobrien * 2. If the structure should take on values only if they are currently unset. 10838494Sobrien * For example the values in an SSL structure will take appropriate value 10938494Sobrien * for SSL servers or clients but only if the application has not set new 11038494Sobrien * ones. 11138494Sobrien * 11238494Sobrien * The "inh_flags" field determines how this function behaves. 11338494Sobrien * 11438494Sobrien * Normally any values which are set in the default are not copied from the 11538494Sobrien * destination and verify flags are ORed together. 11638494Sobrien * 11738494Sobrien * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied 118174313Sobrien * to the destination. Effectively the values in "to" become default values 11938494Sobrien * which will be used only if nothing new is set in "from". 12038494Sobrien * 12138494Sobrien * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether 12238494Sobrien * they are set or not. Flags is still Ored though. 12338494Sobrien * 12438494Sobrien * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead 12538494Sobrien * of ORed. 12638494Sobrien * 12738494Sobrien * If X509_VP_FLAG_LOCKED is set then no values are copied. 12838494Sobrien * 12938494Sobrien * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed 13038494Sobrien * after the next call. 13138494Sobrien */ 13238494Sobrien 13338494Sobrien/* Macro to test if a field should be copied from src to dest */ 13438494Sobrien 13538494Sobrien#define test_x509_verify_param_copy(field, def) \ 13638494Sobrien (to_overwrite || \ 13738494Sobrien ((src->field != def) && (to_default || (dest->field == def)))) 13838494Sobrien 13938494Sobrien/* Macro to test and copy a field if necessary */ 14038494Sobrien 14138494Sobrien#define x509_verify_param_copy(field, def) \ 14238494Sobrien if (test_x509_verify_param_copy(field, def)) \ 14338494Sobrien dest->field = src->field 14438494Sobrien 14538494Sobrien 14638494Sobrienint X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, 14738494Sobrien const X509_VERIFY_PARAM *src) 14838494Sobrien { 14938494Sobrien unsigned long inh_flags; 15038494Sobrien int to_default, to_overwrite; 15138494Sobrien if (!src) 15238494Sobrien return 1; 15338494Sobrien inh_flags = dest->inh_flags | src->inh_flags; 15438494Sobrien 15538494Sobrien if (inh_flags & X509_VP_FLAG_ONCE) 15638494Sobrien dest->inh_flags = 0; 15738494Sobrien 15838494Sobrien if (inh_flags & X509_VP_FLAG_LOCKED) 15938494Sobrien return 1; 16038494Sobrien 16138494Sobrien if (inh_flags & X509_VP_FLAG_DEFAULT) 162174313Sobrien to_default = 1; 16338494Sobrien else 16438494Sobrien to_default = 0; 16538494Sobrien 16638494Sobrien if (inh_flags & X509_VP_FLAG_OVERWRITE) 16738494Sobrien to_overwrite = 1; 16838494Sobrien else 16938494Sobrien to_overwrite = 0; 17038494Sobrien 17138494Sobrien x509_verify_param_copy(purpose, 0); 17238494Sobrien x509_verify_param_copy(trust, 0); 17338494Sobrien x509_verify_param_copy(depth, -1); 17438494Sobrien 17538494Sobrien /* If overwrite or check time not set, copy across */ 17638494Sobrien 17738494Sobrien if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) 17838494Sobrien { 17938494Sobrien dest->check_time = src->check_time; 18038494Sobrien dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME; 18138494Sobrien /* Don't need to copy flag: that is done below */ 18238494Sobrien } 18338494Sobrien 18438494Sobrien if (inh_flags & X509_VP_FLAG_RESET_FLAGS) 18538494Sobrien dest->flags = 0; 18638494Sobrien 18738494Sobrien dest->flags |= src->flags; 18838494Sobrien 18938494Sobrien if (test_x509_verify_param_copy(policies, NULL)) 19038494Sobrien { 19138494Sobrien if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) 19238494Sobrien return 0; 19338494Sobrien } 19438494Sobrien 19538494Sobrien return 1; 19638494Sobrien } 19738494Sobrien 19838494Sobrienint X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, 19938494Sobrien const X509_VERIFY_PARAM *from) 20038494Sobrien { 20138494Sobrien to->inh_flags |= X509_VP_FLAG_DEFAULT; 20238494Sobrien return X509_VERIFY_PARAM_inherit(to, from); 20338494Sobrien } 20438494Sobrien 20538494Sobrienint X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) 20638494Sobrien { 20738494Sobrien if (param->name) 20838494Sobrien OPENSSL_free(param->name); 20938494Sobrien param->name = BUF_strdup(name); 21038494Sobrien if (param->name) 21138494Sobrien return 1; 21238494Sobrien return 0; 21338494Sobrien } 21438494Sobrien 21538494Sobrienint X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) 21638494Sobrien { 21738494Sobrien param->flags |= flags; 21838494Sobrien if (flags & X509_V_FLAG_POLICY_MASK) 21938494Sobrien param->flags |= X509_V_FLAG_POLICY_CHECK; 22038494Sobrien return 1; 22138494Sobrien } 22238494Sobrien 22338494Sobrienint X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags) 22438494Sobrien { 22538494Sobrien param->flags &= ~flags; 22638494Sobrien return 1; 22738494Sobrien } 22838494Sobrien 22938494Sobrienunsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) 23038494Sobrien { 23138494Sobrien return param->flags; 23238494Sobrien } 23338494Sobrien 23438494Sobrienint X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) 23538494Sobrien { 23638494Sobrien return X509_PURPOSE_set(¶m->purpose, purpose); 23738494Sobrien } 23838494Sobrien 23938494Sobrienint X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) 24038494Sobrien { 24138494Sobrien return X509_TRUST_set(¶m->trust, trust); 24238494Sobrien } 24338494Sobrien 24438494Sobrienvoid X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) 24538494Sobrien { 24638494Sobrien param->depth = depth; 24738494Sobrien } 24838494Sobrien 24938494Sobrienvoid X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) 25038494Sobrien { 25138494Sobrien param->check_time = t; 25238494Sobrien param->flags |= X509_V_FLAG_USE_CHECK_TIME; 25338494Sobrien } 25438494Sobrien 25538494Sobrienint X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy) 25638494Sobrien { 25738494Sobrien if (!param->policies) 25838494Sobrien { 25938494Sobrien param->policies = sk_ASN1_OBJECT_new_null(); 26038494Sobrien if (!param->policies) 26138494Sobrien return 0; 26238494Sobrien } 26338494Sobrien if (!sk_ASN1_OBJECT_push(param->policies, policy)) 26438494Sobrien return 0; 26538494Sobrien return 1; 26638494Sobrien } 26738494Sobrien 26838494Sobrienint X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, 26938494Sobrien STACK_OF(ASN1_OBJECT) *policies) 27038494Sobrien { 27138494Sobrien int i; 27238494Sobrien ASN1_OBJECT *oid, *doid; 27338494Sobrien if (!param) 27438494Sobrien return 0; 27538494Sobrien if (param->policies) 27638494Sobrien sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); 27738494Sobrien 27838494Sobrien if (!policies) 27938494Sobrien { 28038500Sobrien param->policies = NULL; 28138494Sobrien return 1; 28238494Sobrien } 28338494Sobrien 28438494Sobrien param->policies = sk_ASN1_OBJECT_new_null(); 28538494Sobrien if (!param->policies) 28638494Sobrien return 0; 28738494Sobrien 28838494Sobrien for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) 28938494Sobrien { 29038494Sobrien oid = sk_ASN1_OBJECT_value(policies, i); 29138494Sobrien doid = OBJ_dup(oid); 29238494Sobrien if (!doid) 29338494Sobrien return 0; 29438494Sobrien if (!sk_ASN1_OBJECT_push(param->policies, doid)) 29538494Sobrien { 29638494Sobrien ASN1_OBJECT_free(doid); 29738494Sobrien return 0; 29838494Sobrien } 29938494Sobrien } 30038494Sobrien param->flags |= X509_V_FLAG_POLICY_CHECK; 30138494Sobrien return 1; 30238494Sobrien } 30338494Sobrien 30438494Sobrienint X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) 30538494Sobrien { 30638494Sobrien return param->depth; 30738494Sobrien } 30838494Sobrien 30938494Sobrien/* Default verify parameters: these are used for various 31038494Sobrien * applications and can be overridden by the user specified table. 31138494Sobrien * NB: the 'name' field *must* be in alphabetical order because it 31238494Sobrien * will be searched using OBJ_search. 31338494Sobrien */ 31438494Sobrien 31538494Sobrienstatic const X509_VERIFY_PARAM default_table[] = { 31638494Sobrien { 31738494Sobrien "default", /* X509 default parameters */ 31838494Sobrien 0, /* Check time */ 31938494Sobrien 0, /* internal flags */ 32038494Sobrien 0, /* flags */ 32138494Sobrien 0, /* purpose */ 32238494Sobrien 0, /* trust */ 32338494Sobrien 9, /* depth */ 324174313Sobrien NULL /* policies */ 32538494Sobrien }, 32638494Sobrien { 32738494Sobrien "pkcs7", /* SSL/TLS client parameters */ 32838494Sobrien 0, /* Check time */ 32938494Sobrien 0, /* internal flags */ 33038494Sobrien 0, /* flags */ 33138494Sobrien X509_PURPOSE_SMIME_SIGN, /* purpose */ 33238494Sobrien X509_TRUST_EMAIL, /* trust */ 33338494Sobrien -1, /* depth */ 33438494Sobrien NULL /* policies */ 33538494Sobrien }, 33638494Sobrien { 33738494Sobrien "ssl_client", /* SSL/TLS client parameters */ 33838494Sobrien 0, /* Check time */ 33938494Sobrien 0, /* internal flags */ 34038494Sobrien 0, /* flags */ 34138494Sobrien X509_PURPOSE_SSL_CLIENT, /* purpose */ 34238494Sobrien X509_TRUST_SSL_CLIENT, /* trust */ 34338494Sobrien -1, /* depth */ 34438494Sobrien NULL /* policies */ 34541145Sobrien }, 34638494Sobrien { 34738494Sobrien "ssl_server", /* SSL/TLS server parameters */ 34838494Sobrien 0, /* Check time */ 34938494Sobrien 0, /* internal flags */ 35038494Sobrien 0, /* flags */ 35138494Sobrien X509_PURPOSE_SSL_SERVER, /* purpose */ 35238494Sobrien X509_TRUST_SSL_SERVER, /* trust */ 35338494Sobrien -1, /* depth */ 35438494Sobrien NULL /* policies */ 35538494Sobrien }}; 35638494Sobrien 35738494Sobrienstatic STACK_OF(X509_VERIFY_PARAM) *param_table = NULL; 35838494Sobrien 35938494Sobrienstatic int table_cmp(const void *pa, const void *pb) 36038494Sobrien { 36138494Sobrien const X509_VERIFY_PARAM *a = pa, *b = pb; 36238494Sobrien return strcmp(a->name, b->name); 36338494Sobrien } 364174313Sobrien 36538494Sobrienstatic int param_cmp(const X509_VERIFY_PARAM * const *a, 36638494Sobrien const X509_VERIFY_PARAM * const *b) 36738494Sobrien { 36838494Sobrien return strcmp((*a)->name, (*b)->name); 36938494Sobrien } 37038494Sobrien 37138494Sobrienint X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) 37238494Sobrien { 37338494Sobrien int idx; 37438494Sobrien X509_VERIFY_PARAM *ptmp; 37538494Sobrien if (!param_table) 37638494Sobrien { 37738494Sobrien param_table = sk_X509_VERIFY_PARAM_new(param_cmp); 37838494Sobrien if (!param_table) 37938494Sobrien return 0; 38038494Sobrien } 38138494Sobrien else 38238494Sobrien { 38338494Sobrien idx = sk_X509_VERIFY_PARAM_find(param_table, param); 38438494Sobrien if (idx != -1) 38538494Sobrien { 38638494Sobrien ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx); 38738494Sobrien X509_VERIFY_PARAM_free(ptmp); 38838494Sobrien sk_X509_VERIFY_PARAM_delete(param_table, idx); 38938494Sobrien } 39038494Sobrien } 39138494Sobrien if (!sk_X509_VERIFY_PARAM_push(param_table, param)) 39238494Sobrien return 0; 39338494Sobrien return 1; 39438494Sobrien } 39538494Sobrien 39638494Sobrienconst X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) 39738494Sobrien { 39838494Sobrien int idx; 39938494Sobrien X509_VERIFY_PARAM pm; 40038494Sobrien pm.name = (char *)name; 40138494Sobrien if (param_table) 40238494Sobrien { 40338494Sobrien idx = sk_X509_VERIFY_PARAM_find(param_table, &pm); 40438494Sobrien if (idx != -1) 40538494Sobrien return sk_X509_VERIFY_PARAM_value(param_table, idx); 40638494Sobrien } 40738494Sobrien return (const X509_VERIFY_PARAM *) OBJ_bsearch((char *)&pm, 40838494Sobrien (char *)&default_table, 40938494Sobrien sizeof(default_table)/sizeof(X509_VERIFY_PARAM), 41038494Sobrien sizeof(X509_VERIFY_PARAM), 41138494Sobrien table_cmp); 41238494Sobrien } 41338494Sobrien 41438494Sobrienvoid X509_VERIFY_PARAM_table_cleanup(void) 41538494Sobrien { 41638494Sobrien if (param_table) 41738494Sobrien sk_X509_VERIFY_PARAM_pop_free(param_table, 41838494Sobrien X509_VERIFY_PARAM_free); 41938494Sobrien param_table = NULL; 42038494Sobrien } 42138494Sobrien