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(&param->purpose, purpose);
23738494Sobrien	}
23838494Sobrien
23938494Sobrienint X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
24038494Sobrien	{
24138494Sobrien	return X509_TRUST_set(&param->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