xref: /openbsd/lib/libcrypto/x509/x509_vpm.c (revision e51d4db3)
1*e51d4db3Stb /* $OpenBSD: x509_vpm.c,v 1.38 2023/05/24 08:46:01 tb Exp $ */
282a8dcafSdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
35650a0e1Sdjm  * project 2004.
45650a0e1Sdjm  */
55650a0e1Sdjm /* ====================================================================
65650a0e1Sdjm  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
75650a0e1Sdjm  *
85650a0e1Sdjm  * Redistribution and use in source and binary forms, with or without
95650a0e1Sdjm  * modification, are permitted provided that the following conditions
105650a0e1Sdjm  * are met:
115650a0e1Sdjm  *
125650a0e1Sdjm  * 1. Redistributions of source code must retain the above copyright
135650a0e1Sdjm  *    notice, this list of conditions and the following disclaimer.
145650a0e1Sdjm  *
155650a0e1Sdjm  * 2. Redistributions in binary form must reproduce the above copyright
165650a0e1Sdjm  *    notice, this list of conditions and the following disclaimer in
175650a0e1Sdjm  *    the documentation and/or other materials provided with the
185650a0e1Sdjm  *    distribution.
195650a0e1Sdjm  *
205650a0e1Sdjm  * 3. All advertising materials mentioning features or use of this
215650a0e1Sdjm  *    software must display the following acknowledgment:
225650a0e1Sdjm  *    "This product includes software developed by the OpenSSL Project
235650a0e1Sdjm  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
245650a0e1Sdjm  *
255650a0e1Sdjm  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
265650a0e1Sdjm  *    endorse or promote products derived from this software without
275650a0e1Sdjm  *    prior written permission. For written permission, please contact
285650a0e1Sdjm  *    licensing@OpenSSL.org.
295650a0e1Sdjm  *
305650a0e1Sdjm  * 5. Products derived from this software may not be called "OpenSSL"
315650a0e1Sdjm  *    nor may "OpenSSL" appear in their names without prior written
325650a0e1Sdjm  *    permission of the OpenSSL Project.
335650a0e1Sdjm  *
345650a0e1Sdjm  * 6. Redistributions of any form whatsoever must retain the following
355650a0e1Sdjm  *    acknowledgment:
365650a0e1Sdjm  *    "This product includes software developed by the OpenSSL Project
375650a0e1Sdjm  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
385650a0e1Sdjm  *
395650a0e1Sdjm  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
405650a0e1Sdjm  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
415650a0e1Sdjm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
425650a0e1Sdjm  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
435650a0e1Sdjm  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
445650a0e1Sdjm  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
455650a0e1Sdjm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
465650a0e1Sdjm  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
475650a0e1Sdjm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
485650a0e1Sdjm  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
495650a0e1Sdjm  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
505650a0e1Sdjm  * OF THE POSSIBILITY OF SUCH DAMAGE.
515650a0e1Sdjm  * ====================================================================
525650a0e1Sdjm  *
535650a0e1Sdjm  * This product includes cryptographic software written by Eric Young
545650a0e1Sdjm  * (eay@cryptsoft.com).  This product includes software written by Tim
555650a0e1Sdjm  * Hudson (tjh@cryptsoft.com).
565650a0e1Sdjm  *
575650a0e1Sdjm  */
585650a0e1Sdjm 
595650a0e1Sdjm #include <stdio.h>
60a8913c44Sjsing #include <string.h>
615650a0e1Sdjm 
62b6ab114eSjsing #include <openssl/buffer.h>
635650a0e1Sdjm #include <openssl/crypto.h>
645650a0e1Sdjm #include <openssl/lhash.h>
65deda88cbSbeck #include <openssl/stack.h>
665650a0e1Sdjm #include <openssl/x509.h>
675650a0e1Sdjm #include <openssl/x509v3.h>
685650a0e1Sdjm 
69c9675a23Stb #include "x509_local.h"
70deda88cbSbeck 
715650a0e1Sdjm /* X509_VERIFY_PARAM functions */
725650a0e1Sdjm 
7347398500Sjsing int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
7447398500Sjsing     size_t emaillen);
7547398500Sjsing int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
7647398500Sjsing     size_t iplen);
7747398500Sjsing 
78deda88cbSbeck #define SET_HOST 0
79deda88cbSbeck #define ADD_HOST 1
80deda88cbSbeck 
81deda88cbSbeck static void
82deda88cbSbeck str_free(char *s)
83deda88cbSbeck {
84deda88cbSbeck     free(s);
85deda88cbSbeck }
86deda88cbSbeck 
87deda88cbSbeck /*
88deda88cbSbeck  * Post 1.0.1 sk function "deep_copy".  For the moment we simply make
89deda88cbSbeck  * these take void * and use them directly without a glorious blob of
90deda88cbSbeck  * obfuscating macros of dubious value in front of them. All this in
91deda88cbSbeck  * preparation for a rototilling of safestack.h (likely inspired by
92deda88cbSbeck  * this).
93deda88cbSbeck  */
94deda88cbSbeck static void *
95deda88cbSbeck sk_deep_copy(void *sk_void, void *copy_func_void, void *free_func_void)
96deda88cbSbeck {
97deda88cbSbeck 	_STACK *sk = sk_void;
98deda88cbSbeck 	void *(*copy_func)(void *) = copy_func_void;
9909cc2fe7Sbcook 	void (*free_func)(void *) = free_func_void;
100deda88cbSbeck 	_STACK *ret = sk_dup(sk);
10141b79ad3Sderaadt 	size_t i;
102deda88cbSbeck 
103deda88cbSbeck 	if (ret == NULL)
104deda88cbSbeck 		return NULL;
105deda88cbSbeck 
106deda88cbSbeck 	for (i = 0; i < ret->num; i++) {
107deda88cbSbeck 		if (ret->data[i] == NULL)
108deda88cbSbeck 			continue;
109deda88cbSbeck 		ret->data[i] = copy_func(ret->data[i]);
110deda88cbSbeck 		if (ret->data[i] == NULL) {
111deda88cbSbeck 			size_t j;
112deda88cbSbeck 			for (j = 0; j < i; j++) {
113deda88cbSbeck 				if (ret->data[j] != NULL)
114deda88cbSbeck 					free_func(ret->data[j]);
115deda88cbSbeck 			}
116deda88cbSbeck 			sk_free(ret);
117deda88cbSbeck 			return NULL;
118deda88cbSbeck 		}
119deda88cbSbeck 	}
120deda88cbSbeck 
121deda88cbSbeck 	return ret;
122deda88cbSbeck }
123deda88cbSbeck 
124deda88cbSbeck static int
1252a5239c0Sbeck x509_param_set_hosts_internal(X509_VERIFY_PARAM_ID *id, int mode,
126deda88cbSbeck     const char *name, size_t namelen)
127deda88cbSbeck {
128deda88cbSbeck 	char *copy;
129deda88cbSbeck 
130e9803435Sbeck 	if (name != NULL && namelen == 0)
131e9803435Sbeck 		namelen = strlen(name);
132deda88cbSbeck 	/*
133deda88cbSbeck 	 * Refuse names with embedded NUL bytes.
134deda88cbSbeck 	 */
135deda88cbSbeck 	if (name && memchr(name, '\0', namelen))
136deda88cbSbeck 		return 0;
137deda88cbSbeck 
138deda88cbSbeck 	if (mode == SET_HOST && id->hosts) {
139c4aa7822Stb 		sk_OPENSSL_STRING_pop_free(id->hosts, str_free);
140deda88cbSbeck 		id->hosts = NULL;
141deda88cbSbeck 	}
142deda88cbSbeck 	if (name == NULL || namelen == 0)
143deda88cbSbeck 		return 1;
144deda88cbSbeck 	copy = strndup(name, namelen);
145deda88cbSbeck 	if (copy == NULL)
146deda88cbSbeck 		return 0;
147deda88cbSbeck 
148deda88cbSbeck 	if (id->hosts == NULL &&
149deda88cbSbeck 	    (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
150deda88cbSbeck 		free(copy);
151deda88cbSbeck 		return 0;
152deda88cbSbeck 	}
153deda88cbSbeck 
154deda88cbSbeck 	if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
155deda88cbSbeck 		free(copy);
156deda88cbSbeck 		if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
157deda88cbSbeck 			sk_OPENSSL_STRING_free(id->hosts);
158deda88cbSbeck 			id->hosts = NULL;
159deda88cbSbeck 		}
160deda88cbSbeck 		return 0;
161deda88cbSbeck 	}
162deda88cbSbeck 
163deda88cbSbeck 	return 1;
164deda88cbSbeck }
165deda88cbSbeck 
16615238b08Sjsing static void
16715238b08Sjsing x509_verify_param_zero(X509_VERIFY_PARAM *param)
1685650a0e1Sdjm {
169deda88cbSbeck 	X509_VERIFY_PARAM_ID *paramid;
1705650a0e1Sdjm 	if (!param)
1715650a0e1Sdjm 		return;
1724c6be9d1Stb 	free(param->name);
1735650a0e1Sdjm 	param->name = NULL;
1745650a0e1Sdjm 	param->purpose = 0;
1755650a0e1Sdjm 	param->trust = 0;
176f1535dc8Sdjm 	/*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
177e2ee43e0Sdjm 	param->inh_flags = 0;
178d4b1ba33Stb 	param->flags = 0;
1795650a0e1Sdjm 	param->depth = -1;
1807609e5c6Stedu 	if (param->policies) {
1815650a0e1Sdjm 		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
1825650a0e1Sdjm 		param->policies = NULL;
1835650a0e1Sdjm 	}
184deda88cbSbeck 	paramid = param->id;
185deda88cbSbeck 	if (paramid->hosts) {
186c4aa7822Stb 		sk_OPENSSL_STRING_pop_free(paramid->hosts, str_free);
187deda88cbSbeck 		paramid->hosts = NULL;
188deda88cbSbeck 	}
189deda88cbSbeck 	free(paramid->peername);
190deda88cbSbeck 	paramid->peername = NULL;
191deda88cbSbeck 	free(paramid->email);
192deda88cbSbeck 	paramid->email = NULL;
193deda88cbSbeck 	paramid->emaillen = 0;
194deda88cbSbeck 	free(paramid->ip);
195deda88cbSbeck 	paramid->ip = NULL;
196deda88cbSbeck 	paramid->iplen = 0;
1972a5239c0Sbeck 	paramid->poisoned = 0;
1985650a0e1Sdjm }
1995650a0e1Sdjm 
20015238b08Sjsing X509_VERIFY_PARAM *
20115238b08Sjsing X509_VERIFY_PARAM_new(void)
2025650a0e1Sdjm {
2035650a0e1Sdjm 	X509_VERIFY_PARAM *param;
204deda88cbSbeck 	X509_VERIFY_PARAM_ID *paramid;
20566415b63Stedu 	param = calloc(1, sizeof(X509_VERIFY_PARAM));
206deda88cbSbeck 	if (param == NULL)
207deda88cbSbeck 		return NULL;
208deda88cbSbeck 	paramid = calloc(1, sizeof(X509_VERIFY_PARAM_ID));
209deda88cbSbeck 	if (paramid == NULL) {
210deda88cbSbeck 		free(param);
211deda88cbSbeck 		return NULL;
212deda88cbSbeck 	}
213deda88cbSbeck 	param->id = paramid;
2145650a0e1Sdjm 	x509_verify_param_zero(param);
2155650a0e1Sdjm 	return param;
2165650a0e1Sdjm }
217cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_new);
2185650a0e1Sdjm 
21915238b08Sjsing void
22015238b08Sjsing X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
2215650a0e1Sdjm {
222deda88cbSbeck 	if (param == NULL)
223deda88cbSbeck 		return;
2245650a0e1Sdjm 	x509_verify_param_zero(param);
225deda88cbSbeck 	free(param->id);
2266f3a6cb1Sbeck 	free(param);
2275650a0e1Sdjm }
228cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_free);
2295650a0e1Sdjm 
23040007492Stb /*
23140007492Stb  * This function determines how parameters are "inherited" from one structure
2325650a0e1Sdjm  * to another. There are several different ways this can happen.
2335650a0e1Sdjm  *
2345650a0e1Sdjm  * 1. If a child structure needs to have its values initialized from a parent
2355650a0e1Sdjm  *    they are simply copied across. For example SSL_CTX copied to SSL.
2365650a0e1Sdjm  * 2. If the structure should take on values only if they are currently unset.
2375650a0e1Sdjm  *    For example the values in an SSL structure will take appropriate value
2385650a0e1Sdjm  *    for SSL servers or clients but only if the application has not set new
2395650a0e1Sdjm  *    ones.
2405650a0e1Sdjm  *
2415650a0e1Sdjm  * The "inh_flags" field determines how this function behaves.
2425650a0e1Sdjm  *
2435650a0e1Sdjm  * Normally any values which are set in the default are not copied from the
2445650a0e1Sdjm  * destination and verify flags are ORed together.
2455650a0e1Sdjm  *
2465650a0e1Sdjm  * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
2475650a0e1Sdjm  * to the destination. Effectively the values in "to" become default values
2485650a0e1Sdjm  * which will be used only if nothing new is set in "from".
2495650a0e1Sdjm  *
2505650a0e1Sdjm  * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
2515650a0e1Sdjm  * they are set or not. Flags is still Ored though.
2525650a0e1Sdjm  *
2535650a0e1Sdjm  * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
2545650a0e1Sdjm  * of ORed.
2555650a0e1Sdjm  *
2565650a0e1Sdjm  * If X509_VP_FLAG_LOCKED is set then no values are copied.
2575650a0e1Sdjm  *
2585650a0e1Sdjm  * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
2595650a0e1Sdjm  * after the next call.
2605650a0e1Sdjm  */
2615650a0e1Sdjm 
2625650a0e1Sdjm /* Macro to test if a field should be copied from src to dest */
2635650a0e1Sdjm 
2645650a0e1Sdjm #define test_x509_verify_param_copy(field, def) \
2655650a0e1Sdjm 	(to_overwrite || \
2665650a0e1Sdjm 		((src->field != def) && (to_default || (dest->field == def))))
2675650a0e1Sdjm 
268deda88cbSbeck /* As above but for ID fields */
269deda88cbSbeck 
270deda88cbSbeck #define test_x509_verify_param_copy_id(idf, def) \
271deda88cbSbeck 	test_x509_verify_param_copy(id->idf, def)
272deda88cbSbeck 
2735650a0e1Sdjm /* Macro to test and copy a field if necessary */
2745650a0e1Sdjm 
2755650a0e1Sdjm #define x509_verify_param_copy(field, def) \
2765650a0e1Sdjm 	if (test_x509_verify_param_copy(field, def)) \
2775650a0e1Sdjm 		dest->field = src->field
2785650a0e1Sdjm 
27915238b08Sjsing int
28015238b08Sjsing X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, const X509_VERIFY_PARAM *src)
2815650a0e1Sdjm {
2825650a0e1Sdjm 	unsigned long inh_flags;
2835650a0e1Sdjm 	int to_default, to_overwrite;
284deda88cbSbeck 	X509_VERIFY_PARAM_ID *id;
28515238b08Sjsing 
2865650a0e1Sdjm 	if (!src)
2875650a0e1Sdjm 		return 1;
288deda88cbSbeck 	id = src->id;
2895650a0e1Sdjm 	inh_flags = dest->inh_flags | src->inh_flags;
2905650a0e1Sdjm 
2915650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_ONCE)
2925650a0e1Sdjm 		dest->inh_flags = 0;
2935650a0e1Sdjm 
2945650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_LOCKED)
2955650a0e1Sdjm 		return 1;
2965650a0e1Sdjm 
2975650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_DEFAULT)
2985650a0e1Sdjm 		to_default = 1;
2995650a0e1Sdjm 	else
3005650a0e1Sdjm 		to_default = 0;
3015650a0e1Sdjm 
3025650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_OVERWRITE)
3035650a0e1Sdjm 		to_overwrite = 1;
3045650a0e1Sdjm 	else
3055650a0e1Sdjm 		to_overwrite = 0;
3065650a0e1Sdjm 
3075650a0e1Sdjm 	x509_verify_param_copy(purpose, 0);
3085650a0e1Sdjm 	x509_verify_param_copy(trust, 0);
3095650a0e1Sdjm 	x509_verify_param_copy(depth, -1);
3105650a0e1Sdjm 
3115650a0e1Sdjm 	/* If overwrite or check time not set, copy across */
3125650a0e1Sdjm 
3137609e5c6Stedu 	if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
3145650a0e1Sdjm 		dest->check_time = src->check_time;
3155650a0e1Sdjm 		dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
3165650a0e1Sdjm 		/* Don't need to copy flag: that is done below */
3175650a0e1Sdjm 	}
3185650a0e1Sdjm 
3195650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
3205650a0e1Sdjm 		dest->flags = 0;
3215650a0e1Sdjm 
3225650a0e1Sdjm 	dest->flags |= src->flags;
3235650a0e1Sdjm 
3247609e5c6Stedu 	if (test_x509_verify_param_copy(policies, NULL)) {
3255650a0e1Sdjm 		if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
3265650a0e1Sdjm 			return 0;
3275650a0e1Sdjm 	}
3285650a0e1Sdjm 
329deda88cbSbeck 	/* Copy the host flags if and only if we're copying the host list */
330deda88cbSbeck 	if (test_x509_verify_param_copy_id(hosts, NULL)) {
331deda88cbSbeck 		if (dest->id->hosts) {
332c4aa7822Stb 			sk_OPENSSL_STRING_pop_free(dest->id->hosts, str_free);
333deda88cbSbeck 			dest->id->hosts = NULL;
334deda88cbSbeck 		}
335deda88cbSbeck 		if (id->hosts) {
336deda88cbSbeck 			dest->id->hosts =
337deda88cbSbeck 			    sk_deep_copy(id->hosts, strdup, str_free);
338deda88cbSbeck 			if (dest->id->hosts == NULL)
339deda88cbSbeck 				return 0;
340deda88cbSbeck 			dest->id->hostflags = id->hostflags;
341deda88cbSbeck 		}
342deda88cbSbeck 	}
343deda88cbSbeck 
344deda88cbSbeck 	if (test_x509_verify_param_copy_id(email, NULL)) {
345deda88cbSbeck 		if (!X509_VERIFY_PARAM_set1_email(dest, id->email,
346deda88cbSbeck 		    id->emaillen))
347deda88cbSbeck 			return 0;
348deda88cbSbeck 	}
349deda88cbSbeck 
350deda88cbSbeck 	if (test_x509_verify_param_copy_id(ip, NULL)) {
351deda88cbSbeck 		if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
352deda88cbSbeck 			return 0;
353deda88cbSbeck 	}
354deda88cbSbeck 
3555650a0e1Sdjm 	return 1;
3565650a0e1Sdjm }
357cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_inherit);
3585650a0e1Sdjm 
35915238b08Sjsing int
36015238b08Sjsing X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from)
3615650a0e1Sdjm {
362f1535dc8Sdjm 	unsigned long save_flags = to->inh_flags;
363f1535dc8Sdjm 	int ret;
36415238b08Sjsing 
3655650a0e1Sdjm 	to->inh_flags |= X509_VP_FLAG_DEFAULT;
366f1535dc8Sdjm 	ret = X509_VERIFY_PARAM_inherit(to, from);
367f1535dc8Sdjm 	to->inh_flags = save_flags;
368f1535dc8Sdjm 	return ret;
3695650a0e1Sdjm }
370cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1);
3715650a0e1Sdjm 
372deda88cbSbeck static int
3732a5239c0Sbeck x509_param_set1_internal(char **pdest, size_t *pdestlen,  const char *src,
3742a5239c0Sbeck     size_t srclen, int nonul)
375deda88cbSbeck {
376deda88cbSbeck 	char *tmp;
3772a5239c0Sbeck 
3782a5239c0Sbeck 	if (src == NULL)
3792a5239c0Sbeck 		return 0;
3802a5239c0Sbeck 
381deda88cbSbeck 	if (srclen == 0) {
3822a5239c0Sbeck 		srclen = strlen(src);
3832a5239c0Sbeck 		if (srclen == 0)
3842a5239c0Sbeck 			return 0;
385deda88cbSbeck 		if ((tmp = strdup(src)) == NULL)
386deda88cbSbeck 			return 0;
387deda88cbSbeck 	} else {
3882a5239c0Sbeck 		if (nonul && memchr(src, '\0', srclen))
3892a5239c0Sbeck 			return 0;
390deda88cbSbeck 		if ((tmp = malloc(srclen)) == NULL)
391deda88cbSbeck 			return 0;
392deda88cbSbeck 		memcpy(tmp, src, srclen);
393deda88cbSbeck 	}
3942a5239c0Sbeck 
395deda88cbSbeck 	if (*pdest)
396deda88cbSbeck 		free(*pdest);
397deda88cbSbeck 	*pdest = tmp;
398deda88cbSbeck 	if (pdestlen)
399deda88cbSbeck 		*pdestlen = srclen;
400deda88cbSbeck 	return 1;
401deda88cbSbeck }
402deda88cbSbeck 
40315238b08Sjsing int
40415238b08Sjsing X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
4055650a0e1Sdjm {
4066f3a6cb1Sbeck 	free(param->name);
407cfa3bb9dSmiod 	param->name = NULL;
40869442892Sbeck 	if (name == NULL)
40969442892Sbeck 		return 1;
41069442892Sbeck 	param->name = strdup(name);
4115650a0e1Sdjm 	if (param->name)
4125650a0e1Sdjm 		return 1;
4135650a0e1Sdjm 	return 0;
4145650a0e1Sdjm }
415cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_name);
4165650a0e1Sdjm 
41715238b08Sjsing int
41815238b08Sjsing X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
4195650a0e1Sdjm {
4205650a0e1Sdjm 	param->flags |= flags;
4215650a0e1Sdjm 	return 1;
4225650a0e1Sdjm }
423cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_flags);
4245650a0e1Sdjm 
42515238b08Sjsing int
42615238b08Sjsing X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
4275650a0e1Sdjm {
4285650a0e1Sdjm 	param->flags &= ~flags;
4295650a0e1Sdjm 	return 1;
4305650a0e1Sdjm }
431cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_clear_flags);
4325650a0e1Sdjm 
43315238b08Sjsing unsigned long
43415238b08Sjsing X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
4355650a0e1Sdjm {
4365650a0e1Sdjm 	return param->flags;
4375650a0e1Sdjm }
438cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_flags);
4395650a0e1Sdjm 
44015238b08Sjsing int
44115238b08Sjsing X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
4425650a0e1Sdjm {
4435650a0e1Sdjm 	return X509_PURPOSE_set(&param->purpose, purpose);
4445650a0e1Sdjm }
445cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_purpose);
4465650a0e1Sdjm 
44715238b08Sjsing int
44815238b08Sjsing X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
4495650a0e1Sdjm {
4505650a0e1Sdjm 	return X509_TRUST_set(&param->trust, trust);
4515650a0e1Sdjm }
452cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_trust);
4535650a0e1Sdjm 
45415238b08Sjsing void
45515238b08Sjsing X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
4565650a0e1Sdjm {
4575650a0e1Sdjm 	param->depth = depth;
4585650a0e1Sdjm }
459cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_depth);
4605650a0e1Sdjm 
46115238b08Sjsing void
462e84fde04Stb X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level)
463e84fde04Stb {
464e84fde04Stb 	param->security_level = auth_level;
465e84fde04Stb }
466cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_auth_level);
467e84fde04Stb 
4686f34a740Stb time_t
4696f34a740Stb X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param)
4706f34a740Stb {
4716f34a740Stb 	return param->check_time;
4726f34a740Stb }
473cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_time);
4746f34a740Stb 
475e84fde04Stb void
47615238b08Sjsing X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
4775650a0e1Sdjm {
4785650a0e1Sdjm 	param->check_time = t;
4795650a0e1Sdjm 	param->flags |= X509_V_FLAG_USE_CHECK_TIME;
4805650a0e1Sdjm }
481cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_time);
4825650a0e1Sdjm 
48315238b08Sjsing int
48415238b08Sjsing X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
4855650a0e1Sdjm {
4867609e5c6Stedu 	if (!param->policies) {
4875650a0e1Sdjm 		param->policies = sk_ASN1_OBJECT_new_null();
4885650a0e1Sdjm 		if (!param->policies)
4895650a0e1Sdjm 			return 0;
4905650a0e1Sdjm 	}
4915650a0e1Sdjm 	if (!sk_ASN1_OBJECT_push(param->policies, policy))
4925650a0e1Sdjm 		return 0;
4935650a0e1Sdjm 	return 1;
4945650a0e1Sdjm }
495cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_add0_policy);
4965650a0e1Sdjm 
49715238b08Sjsing int
49815238b08Sjsing X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
4995650a0e1Sdjm     STACK_OF(ASN1_OBJECT) *policies)
5005650a0e1Sdjm {
5015650a0e1Sdjm 	int i;
5025650a0e1Sdjm 	ASN1_OBJECT *oid, *doid;
50315238b08Sjsing 
5045650a0e1Sdjm 	if (!param)
5055650a0e1Sdjm 		return 0;
5065650a0e1Sdjm 	if (param->policies)
5075650a0e1Sdjm 		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
5085650a0e1Sdjm 
5097609e5c6Stedu 	if (!policies) {
5105650a0e1Sdjm 		param->policies = NULL;
5115650a0e1Sdjm 		return 1;
5125650a0e1Sdjm 	}
5135650a0e1Sdjm 
5145650a0e1Sdjm 	param->policies = sk_ASN1_OBJECT_new_null();
5155650a0e1Sdjm 	if (!param->policies)
5165650a0e1Sdjm 		return 0;
5175650a0e1Sdjm 
5187609e5c6Stedu 	for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
5195650a0e1Sdjm 		oid = sk_ASN1_OBJECT_value(policies, i);
5205650a0e1Sdjm 		doid = OBJ_dup(oid);
5215650a0e1Sdjm 		if (!doid)
5225650a0e1Sdjm 			return 0;
5237609e5c6Stedu 		if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
5245650a0e1Sdjm 			ASN1_OBJECT_free(doid);
5255650a0e1Sdjm 			return 0;
5265650a0e1Sdjm 		}
5275650a0e1Sdjm 	}
5285650a0e1Sdjm 	return 1;
5295650a0e1Sdjm }
530cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_policies);
5315650a0e1Sdjm 
53215238b08Sjsing int
533deda88cbSbeck X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
534deda88cbSbeck     const char *name, size_t namelen)
535deda88cbSbeck {
5362a5239c0Sbeck 	if (x509_param_set_hosts_internal(param->id, SET_HOST, name, namelen))
5372a5239c0Sbeck 		return 1;
5382a5239c0Sbeck 	param->id->poisoned = 1;
5392a5239c0Sbeck 	return 0;
540deda88cbSbeck }
541cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_host);
542deda88cbSbeck 
543deda88cbSbeck int
544deda88cbSbeck X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
545deda88cbSbeck     const char *name, size_t namelen)
546deda88cbSbeck {
5472a5239c0Sbeck 	if (x509_param_set_hosts_internal(param->id, ADD_HOST, name, namelen))
5482a5239c0Sbeck 		return 1;
5492a5239c0Sbeck 	param->id->poisoned = 1;
5502a5239c0Sbeck 	return 0;
551deda88cbSbeck }
552cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_add1_host);
553deda88cbSbeck 
554*e51d4db3Stb /* Public API in OpenSSL - nothing seems to use this. */
555*e51d4db3Stb unsigned int
556*e51d4db3Stb X509_VERIFY_PARAM_get_hostflags(X509_VERIFY_PARAM *param)
557*e51d4db3Stb {
558*e51d4db3Stb 	return param->id->hostflags;
559*e51d4db3Stb }
560*e51d4db3Stb 
561deda88cbSbeck void
562deda88cbSbeck X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags)
563deda88cbSbeck {
564deda88cbSbeck 	param->id->hostflags = flags;
565deda88cbSbeck }
566cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_hostflags);
567deda88cbSbeck 
568deda88cbSbeck char *
569deda88cbSbeck X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
570deda88cbSbeck {
571deda88cbSbeck 	return param->id->peername;
572deda88cbSbeck }
573cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0_peername);
574deda88cbSbeck 
575deda88cbSbeck int
576deda88cbSbeck X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,  const char *email,
577deda88cbSbeck     size_t emaillen)
578deda88cbSbeck {
5792a5239c0Sbeck 	if (x509_param_set1_internal(&param->id->email, &param->id->emaillen,
5802a5239c0Sbeck 	    email, emaillen, 1))
5812a5239c0Sbeck 		return 1;
5822a5239c0Sbeck 	param->id->poisoned = 1;
5832a5239c0Sbeck 	return 0;
584deda88cbSbeck }
585cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_email);
586deda88cbSbeck 
587deda88cbSbeck int
588deda88cbSbeck X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
589deda88cbSbeck     size_t iplen)
590deda88cbSbeck {
5912a5239c0Sbeck 	if (iplen != 4 && iplen != 16)
5922a5239c0Sbeck 		goto err;
5932a5239c0Sbeck 	if (x509_param_set1_internal((char **)&param->id->ip, &param->id->iplen,
5942a5239c0Sbeck 		(char *)ip, iplen, 0))
5952a5239c0Sbeck 		return 1;
5962a5239c0Sbeck  err:
5972a5239c0Sbeck 	param->id->poisoned = 1;
598deda88cbSbeck 	return 0;
599deda88cbSbeck }
600cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_ip);
601deda88cbSbeck 
602deda88cbSbeck int
603deda88cbSbeck X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
604deda88cbSbeck {
605deda88cbSbeck 	unsigned char ipout[16];
606deda88cbSbeck 	size_t iplen;
607deda88cbSbeck 
608deda88cbSbeck 	iplen = (size_t)a2i_ipadd(ipout, ipasc);
609deda88cbSbeck 	return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
610deda88cbSbeck }
611cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_ip_asc);
612deda88cbSbeck 
613deda88cbSbeck int
61415238b08Sjsing X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
6155650a0e1Sdjm {
6165650a0e1Sdjm 	return param->depth;
6175650a0e1Sdjm }
618cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_depth);
6195650a0e1Sdjm 
620deda88cbSbeck const char *
621deda88cbSbeck X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
622deda88cbSbeck {
623deda88cbSbeck 	return param->name;
624deda88cbSbeck }
625cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0_name);
626deda88cbSbeck 
627deda88cbSbeck static const X509_VERIFY_PARAM_ID _empty_id = { NULL };
628deda88cbSbeck 
629deda88cbSbeck #define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
630deda88cbSbeck 
631deda88cbSbeck /*
632deda88cbSbeck  * Default verify parameters: these are used for various applications and can
633deda88cbSbeck  * be overridden by the user specified table.
6345650a0e1Sdjm  */
6355650a0e1Sdjm 
6365650a0e1Sdjm static const X509_VERIFY_PARAM default_table[] = {
6375650a0e1Sdjm 	{
638deda88cbSbeck 		.name = "default",
639a37b3debSjsing 		.flags = X509_V_FLAG_TRUSTED_FIRST,
640deda88cbSbeck 		.depth = 100,
641f69362f8Sbeck 		.trust = 0,  /* XXX This is not the default trust value */
642deda88cbSbeck 		.id = vpm_empty_id
6435650a0e1Sdjm 	},
6445650a0e1Sdjm 	{
645deda88cbSbeck 		.name = "pkcs7",
646deda88cbSbeck 		.purpose = X509_PURPOSE_SMIME_SIGN,
647deda88cbSbeck 		.trust = X509_TRUST_EMAIL,
648deda88cbSbeck 		.depth = -1,
649deda88cbSbeck 		.id = vpm_empty_id
650e2ee43e0Sdjm 	},
651e2ee43e0Sdjm 	{
652deda88cbSbeck 		.name = "smime_sign",
653deda88cbSbeck 		.purpose = X509_PURPOSE_SMIME_SIGN,
654deda88cbSbeck 		.trust = X509_TRUST_EMAIL,
655deda88cbSbeck 		.depth =  -1,
656deda88cbSbeck 		.id = vpm_empty_id
6575650a0e1Sdjm 	},
6585650a0e1Sdjm 	{
659deda88cbSbeck 		.name = "ssl_client",
660deda88cbSbeck 		.purpose = X509_PURPOSE_SSL_CLIENT,
661deda88cbSbeck 		.trust = X509_TRUST_SSL_CLIENT,
662deda88cbSbeck 		.depth = -1,
663deda88cbSbeck 		.id = vpm_empty_id
6645650a0e1Sdjm 	},
6655650a0e1Sdjm 	{
666deda88cbSbeck 		.name = "ssl_server",
667deda88cbSbeck 		.purpose = X509_PURPOSE_SSL_SERVER,
668deda88cbSbeck 		.trust = X509_TRUST_SSL_SERVER,
669deda88cbSbeck 		.depth = -1,
670deda88cbSbeck 		.id = vpm_empty_id
6717609e5c6Stedu 	}
6727609e5c6Stedu };
6735650a0e1Sdjm 
6745650a0e1Sdjm static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
6755650a0e1Sdjm 
67615238b08Sjsing static int
67715238b08Sjsing param_cmp(const X509_VERIFY_PARAM * const *a,
6785650a0e1Sdjm     const X509_VERIFY_PARAM * const *b)
6795650a0e1Sdjm {
6805650a0e1Sdjm 	return strcmp((*a)->name, (*b)->name);
6815650a0e1Sdjm }
6825650a0e1Sdjm 
68315238b08Sjsing int
68415238b08Sjsing X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
6855650a0e1Sdjm {
6865650a0e1Sdjm 	X509_VERIFY_PARAM *ptmp;
6877609e5c6Stedu 	if (!param_table) {
6885650a0e1Sdjm 		param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
6895650a0e1Sdjm 		if (!param_table)
6905650a0e1Sdjm 			return 0;
6917609e5c6Stedu 	} else {
692deda88cbSbeck 		size_t idx;
693deda88cbSbeck 
694deda88cbSbeck 		if ((idx = sk_X509_VERIFY_PARAM_find(param_table, param))
695deda88cbSbeck 		    != -1) {
696deda88cbSbeck 			ptmp = sk_X509_VERIFY_PARAM_value(param_table,
697deda88cbSbeck 			    idx);
6985650a0e1Sdjm 			X509_VERIFY_PARAM_free(ptmp);
699deda88cbSbeck 			(void)sk_X509_VERIFY_PARAM_delete(param_table,
700deda88cbSbeck 			    idx);
7015650a0e1Sdjm 		}
7025650a0e1Sdjm 	}
7035650a0e1Sdjm 	if (!sk_X509_VERIFY_PARAM_push(param_table, param))
7045650a0e1Sdjm 		return 0;
7055650a0e1Sdjm 	return 1;
7065650a0e1Sdjm }
707cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_add0_table);
7085650a0e1Sdjm 
709deda88cbSbeck int
710deda88cbSbeck X509_VERIFY_PARAM_get_count(void)
7115650a0e1Sdjm {
712deda88cbSbeck 	int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
713deda88cbSbeck 	if (param_table)
714deda88cbSbeck 		num += sk_X509_VERIFY_PARAM_num(param_table);
715deda88cbSbeck 	return num;
716deda88cbSbeck }
717cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_count);
718deda88cbSbeck 
71940007492Stb const X509_VERIFY_PARAM *
72040007492Stb X509_VERIFY_PARAM_get0(int id)
721deda88cbSbeck {
722deda88cbSbeck 	int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
723deda88cbSbeck 	if (id < num)
724deda88cbSbeck 		return default_table + id;
725deda88cbSbeck 	return sk_X509_VERIFY_PARAM_value(param_table, id - num);
726deda88cbSbeck }
727cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0);
728deda88cbSbeck 
72940007492Stb const X509_VERIFY_PARAM *
73040007492Stb X509_VERIFY_PARAM_lookup(const char *name)
731deda88cbSbeck {
7325650a0e1Sdjm 	X509_VERIFY_PARAM pm;
733deda88cbSbeck 	unsigned int i, limit;
734f1535dc8Sdjm 
7355650a0e1Sdjm 	pm.name = (char *)name;
7367609e5c6Stedu 	if (param_table) {
737deda88cbSbeck 		size_t idx;
738deda88cbSbeck 		if ((idx = sk_X509_VERIFY_PARAM_find(param_table, &pm)) != -1)
7395650a0e1Sdjm 			return sk_X509_VERIFY_PARAM_value(param_table, idx);
7405650a0e1Sdjm 	}
741deda88cbSbeck 
742deda88cbSbeck 	limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
743deda88cbSbeck 	for (i = 0; i < limit; i++) {
744deda88cbSbeck 		if (strcmp(default_table[i].name, name) == 0) {
745deda88cbSbeck 			return &default_table[i];
746deda88cbSbeck 		}
747deda88cbSbeck 	}
748deda88cbSbeck 	return NULL;
7495650a0e1Sdjm }
750cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_lookup);
7515650a0e1Sdjm 
75215238b08Sjsing void
75315238b08Sjsing X509_VERIFY_PARAM_table_cleanup(void)
7545650a0e1Sdjm {
7555650a0e1Sdjm 	if (param_table)
7565650a0e1Sdjm 		sk_X509_VERIFY_PARAM_pop_free(param_table,
7575650a0e1Sdjm 		    X509_VERIFY_PARAM_free);
7585650a0e1Sdjm 	param_table = NULL;
7595650a0e1Sdjm }
760cedac418Stb LCRYPTO_ALIAS(X509_VERIFY_PARAM_table_cleanup);
761