xref: /openbsd/lib/libcrypto/x509/x509_vpm.c (revision f69362f8)
1*f69362f8Sbeck /* $OpenBSD: x509_vpm.c,v 1.14 2016/11/06 10:17:49 beck 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 
69deda88cbSbeck #include "vpm_int.h"
70deda88cbSbeck 
715650a0e1Sdjm /* X509_VERIFY_PARAM functions */
725650a0e1Sdjm 
73deda88cbSbeck #define SET_HOST 0
74deda88cbSbeck #define ADD_HOST 1
75deda88cbSbeck 
76deda88cbSbeck static void
77deda88cbSbeck str_free(char *s)
78deda88cbSbeck {
79deda88cbSbeck     free(s);
80deda88cbSbeck }
81deda88cbSbeck 
82deda88cbSbeck #define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
83deda88cbSbeck 
84deda88cbSbeck 
85deda88cbSbeck /*
86deda88cbSbeck  * Post 1.0.1 sk function "deep_copy".  For the moment we simply make
87deda88cbSbeck  * these take void * and use them directly without a glorious blob of
88deda88cbSbeck  * obfuscating macros of dubious value in front of them. All this in
89deda88cbSbeck  * preparation for a rototilling of safestack.h (likely inspired by
90deda88cbSbeck  * this).
91deda88cbSbeck  */
92deda88cbSbeck static void *
93deda88cbSbeck sk_deep_copy(void *sk_void, void *copy_func_void, void *free_func_void)
94deda88cbSbeck {
95deda88cbSbeck 	_STACK *sk = sk_void;
96deda88cbSbeck 	void *(*copy_func)(void *) = copy_func_void;
9709cc2fe7Sbcook 	void (*free_func)(void *) = free_func_void;
98deda88cbSbeck 	_STACK *ret = sk_dup(sk);
99deda88cbSbeck 
100deda88cbSbeck 	if (ret == NULL)
101deda88cbSbeck 		return NULL;
102deda88cbSbeck 
103deda88cbSbeck 	size_t i;
104deda88cbSbeck 	for (i = 0; i < ret->num; i++) {
105deda88cbSbeck 		if (ret->data[i] == NULL)
106deda88cbSbeck 			continue;
107deda88cbSbeck 		ret->data[i] = copy_func(ret->data[i]);
108deda88cbSbeck 		if (ret->data[i] == NULL) {
109deda88cbSbeck 			size_t j;
110deda88cbSbeck 			for (j = 0; j < i; j++) {
111deda88cbSbeck 				if (ret->data[j] != NULL)
112deda88cbSbeck 					free_func(ret->data[j]);
113deda88cbSbeck 			}
114deda88cbSbeck 			sk_free(ret);
115deda88cbSbeck 			return NULL;
116deda88cbSbeck 		}
117deda88cbSbeck 	}
118deda88cbSbeck 
119deda88cbSbeck 	return ret;
120deda88cbSbeck }
121deda88cbSbeck 
122deda88cbSbeck static int
123deda88cbSbeck int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
124deda88cbSbeck     const char *name, size_t namelen)
125deda88cbSbeck {
126deda88cbSbeck 	char *copy;
127deda88cbSbeck 
128deda88cbSbeck 	/*
129deda88cbSbeck 	 * Refuse names with embedded NUL bytes.
130deda88cbSbeck 	 * XXX: Do we need to push an error onto the error stack?
131deda88cbSbeck 	 */
132deda88cbSbeck 	if (name && memchr(name, '\0', namelen))
133deda88cbSbeck 		return 0;
134deda88cbSbeck 
135deda88cbSbeck 	if (mode == SET_HOST && id->hosts) {
136deda88cbSbeck 		string_stack_free(id->hosts);
137deda88cbSbeck 		id->hosts = NULL;
138deda88cbSbeck 	}
139deda88cbSbeck 	if (name == NULL || namelen == 0)
140deda88cbSbeck 		return 1;
141deda88cbSbeck 	copy = strndup(name, namelen);
142deda88cbSbeck 	if (copy == NULL)
143deda88cbSbeck 		return 0;
144deda88cbSbeck 
145deda88cbSbeck 	if (id->hosts == NULL &&
146deda88cbSbeck 	    (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
147deda88cbSbeck 		free(copy);
148deda88cbSbeck 		return 0;
149deda88cbSbeck 	}
150deda88cbSbeck 
151deda88cbSbeck 	if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
152deda88cbSbeck 		free(copy);
153deda88cbSbeck 		if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
154deda88cbSbeck 			sk_OPENSSL_STRING_free(id->hosts);
155deda88cbSbeck 			id->hosts = NULL;
156deda88cbSbeck 		}
157deda88cbSbeck 		return 0;
158deda88cbSbeck 	}
159deda88cbSbeck 
160deda88cbSbeck 	return 1;
161deda88cbSbeck }
162deda88cbSbeck 
16315238b08Sjsing static void
16415238b08Sjsing x509_verify_param_zero(X509_VERIFY_PARAM *param)
1655650a0e1Sdjm {
166deda88cbSbeck 	X509_VERIFY_PARAM_ID *paramid;
1675650a0e1Sdjm 	if (!param)
1685650a0e1Sdjm 		return;
1695650a0e1Sdjm 	param->name = NULL;
1705650a0e1Sdjm 	param->purpose = 0;
1715650a0e1Sdjm 	param->trust = 0;
172f1535dc8Sdjm 	/*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
173e2ee43e0Sdjm 	param->inh_flags = 0;
1745650a0e1Sdjm 	param->flags = 0;
1755650a0e1Sdjm 	param->depth = -1;
1767609e5c6Stedu 	if (param->policies) {
1775650a0e1Sdjm 		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
1785650a0e1Sdjm 		param->policies = NULL;
1795650a0e1Sdjm 	}
180deda88cbSbeck 	paramid = param->id;
181deda88cbSbeck 	if (paramid->hosts) {
182deda88cbSbeck 		string_stack_free(paramid->hosts);
183deda88cbSbeck 		paramid->hosts = NULL;
184deda88cbSbeck 	}
185deda88cbSbeck 	free(paramid->peername);
186deda88cbSbeck 	paramid->peername = NULL;
187deda88cbSbeck 	free(paramid->email);
188deda88cbSbeck 	paramid->email = NULL;
189deda88cbSbeck 	paramid->emaillen = 0;
190deda88cbSbeck 	free(paramid->ip);
191deda88cbSbeck 	paramid->ip = NULL;
192deda88cbSbeck 	paramid->iplen = 0;
1935650a0e1Sdjm }
1945650a0e1Sdjm 
19515238b08Sjsing X509_VERIFY_PARAM *
19615238b08Sjsing X509_VERIFY_PARAM_new(void)
1975650a0e1Sdjm {
1985650a0e1Sdjm 	X509_VERIFY_PARAM *param;
199deda88cbSbeck 	X509_VERIFY_PARAM_ID *paramid;
20066415b63Stedu 	param = calloc(1, sizeof(X509_VERIFY_PARAM));
201deda88cbSbeck 	if (param == NULL)
202deda88cbSbeck 		return NULL;
203deda88cbSbeck 	paramid = calloc (1, sizeof(X509_VERIFY_PARAM_ID));
204deda88cbSbeck 	if (paramid == NULL) {
205deda88cbSbeck 		free(param);
206deda88cbSbeck 		return NULL;
207deda88cbSbeck 	}
208deda88cbSbeck 	param->id = paramid;
2095650a0e1Sdjm 	x509_verify_param_zero(param);
2105650a0e1Sdjm 	return param;
2115650a0e1Sdjm }
2125650a0e1Sdjm 
21315238b08Sjsing void
21415238b08Sjsing X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
2155650a0e1Sdjm {
216deda88cbSbeck 	if (param == NULL)
217deda88cbSbeck 		return;
2185650a0e1Sdjm 	x509_verify_param_zero(param);
219deda88cbSbeck 	free(param->id);
2206f3a6cb1Sbeck 	free(param);
2215650a0e1Sdjm }
2225650a0e1Sdjm 
2235650a0e1Sdjm /* This function determines how parameters are "inherited" from one structure
2245650a0e1Sdjm  * to another. There are several different ways this can happen.
2255650a0e1Sdjm  *
2265650a0e1Sdjm  * 1. If a child structure needs to have its values initialized from a parent
2275650a0e1Sdjm  *    they are simply copied across. For example SSL_CTX copied to SSL.
2285650a0e1Sdjm  * 2. If the structure should take on values only if they are currently unset.
2295650a0e1Sdjm  *    For example the values in an SSL structure will take appropriate value
2305650a0e1Sdjm  *    for SSL servers or clients but only if the application has not set new
2315650a0e1Sdjm  *    ones.
2325650a0e1Sdjm  *
2335650a0e1Sdjm  * The "inh_flags" field determines how this function behaves.
2345650a0e1Sdjm  *
2355650a0e1Sdjm  * Normally any values which are set in the default are not copied from the
2365650a0e1Sdjm  * destination and verify flags are ORed together.
2375650a0e1Sdjm  *
2385650a0e1Sdjm  * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
2395650a0e1Sdjm  * to the destination. Effectively the values in "to" become default values
2405650a0e1Sdjm  * which will be used only if nothing new is set in "from".
2415650a0e1Sdjm  *
2425650a0e1Sdjm  * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
2435650a0e1Sdjm  * they are set or not. Flags is still Ored though.
2445650a0e1Sdjm  *
2455650a0e1Sdjm  * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
2465650a0e1Sdjm  * of ORed.
2475650a0e1Sdjm  *
2485650a0e1Sdjm  * If X509_VP_FLAG_LOCKED is set then no values are copied.
2495650a0e1Sdjm  *
2505650a0e1Sdjm  * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
2515650a0e1Sdjm  * after the next call.
2525650a0e1Sdjm  */
2535650a0e1Sdjm 
2545650a0e1Sdjm /* Macro to test if a field should be copied from src to dest */
2555650a0e1Sdjm 
2565650a0e1Sdjm #define test_x509_verify_param_copy(field, def) \
2575650a0e1Sdjm 	(to_overwrite || \
2585650a0e1Sdjm 		((src->field != def) && (to_default || (dest->field == def))))
2595650a0e1Sdjm 
260deda88cbSbeck /* As above but for ID fields */
261deda88cbSbeck 
262deda88cbSbeck #define test_x509_verify_param_copy_id(idf, def) \
263deda88cbSbeck 	test_x509_verify_param_copy(id->idf, def)
264deda88cbSbeck 
2655650a0e1Sdjm /* Macro to test and copy a field if necessary */
2665650a0e1Sdjm 
2675650a0e1Sdjm #define x509_verify_param_copy(field, def) \
2685650a0e1Sdjm 	if (test_x509_verify_param_copy(field, def)) \
2695650a0e1Sdjm 		dest->field = src->field
2705650a0e1Sdjm 
27115238b08Sjsing int
27215238b08Sjsing X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, const X509_VERIFY_PARAM *src)
2735650a0e1Sdjm {
2745650a0e1Sdjm 	unsigned long inh_flags;
2755650a0e1Sdjm 	int to_default, to_overwrite;
276deda88cbSbeck 	X509_VERIFY_PARAM_ID *id;
27715238b08Sjsing 
2785650a0e1Sdjm 	if (!src)
2795650a0e1Sdjm 		return 1;
280deda88cbSbeck 	id = src->id;
2815650a0e1Sdjm 	inh_flags = dest->inh_flags | src->inh_flags;
2825650a0e1Sdjm 
2835650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_ONCE)
2845650a0e1Sdjm 		dest->inh_flags = 0;
2855650a0e1Sdjm 
2865650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_LOCKED)
2875650a0e1Sdjm 		return 1;
2885650a0e1Sdjm 
2895650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_DEFAULT)
2905650a0e1Sdjm 		to_default = 1;
2915650a0e1Sdjm 	else
2925650a0e1Sdjm 		to_default = 0;
2935650a0e1Sdjm 
2945650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_OVERWRITE)
2955650a0e1Sdjm 		to_overwrite = 1;
2965650a0e1Sdjm 	else
2975650a0e1Sdjm 		to_overwrite = 0;
2985650a0e1Sdjm 
2995650a0e1Sdjm 	x509_verify_param_copy(purpose, 0);
3005650a0e1Sdjm 	x509_verify_param_copy(trust, 0);
3015650a0e1Sdjm 	x509_verify_param_copy(depth, -1);
3025650a0e1Sdjm 
3035650a0e1Sdjm 	/* If overwrite or check time not set, copy across */
3045650a0e1Sdjm 
3057609e5c6Stedu 	if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
3065650a0e1Sdjm 		dest->check_time = src->check_time;
3075650a0e1Sdjm 		dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
3085650a0e1Sdjm 		/* Don't need to copy flag: that is done below */
3095650a0e1Sdjm 	}
3105650a0e1Sdjm 
3115650a0e1Sdjm 	if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
3125650a0e1Sdjm 		dest->flags = 0;
3135650a0e1Sdjm 
3145650a0e1Sdjm 	dest->flags |= src->flags;
3155650a0e1Sdjm 
3167609e5c6Stedu 	if (test_x509_verify_param_copy(policies, NULL)) {
3175650a0e1Sdjm 		if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
3185650a0e1Sdjm 			return 0;
3195650a0e1Sdjm 	}
3205650a0e1Sdjm 
321deda88cbSbeck 	/* Copy the host flags if and only if we're copying the host list */
322deda88cbSbeck 	if (test_x509_verify_param_copy_id(hosts, NULL)) {
323deda88cbSbeck 		if (dest->id->hosts) {
324deda88cbSbeck 			string_stack_free(dest->id->hosts);
325deda88cbSbeck 			dest->id->hosts = NULL;
326deda88cbSbeck 		}
327deda88cbSbeck 		if (id->hosts) {
328deda88cbSbeck 			dest->id->hosts =
329deda88cbSbeck 			    sk_deep_copy(id->hosts, strdup, str_free);
330deda88cbSbeck 			if (dest->id->hosts == NULL)
331deda88cbSbeck 				return 0;
332deda88cbSbeck 			dest->id->hostflags = id->hostflags;
333deda88cbSbeck 		}
334deda88cbSbeck 	}
335deda88cbSbeck 
336deda88cbSbeck 	if (test_x509_verify_param_copy_id(email, NULL)) {
337deda88cbSbeck 		if (!X509_VERIFY_PARAM_set1_email(dest, id->email,
338deda88cbSbeck 		    id->emaillen))
339deda88cbSbeck 			return 0;
340deda88cbSbeck 	}
341deda88cbSbeck 
342deda88cbSbeck 	if (test_x509_verify_param_copy_id(ip, NULL)) {
343deda88cbSbeck 		if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
344deda88cbSbeck 			return 0;
345deda88cbSbeck 	}
346deda88cbSbeck 
3475650a0e1Sdjm 	return 1;
3485650a0e1Sdjm }
3495650a0e1Sdjm 
35015238b08Sjsing int
35115238b08Sjsing X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from)
3525650a0e1Sdjm {
353f1535dc8Sdjm 	unsigned long save_flags = to->inh_flags;
354f1535dc8Sdjm 	int ret;
35515238b08Sjsing 
3565650a0e1Sdjm 	to->inh_flags |= X509_VP_FLAG_DEFAULT;
357f1535dc8Sdjm 	ret = X509_VERIFY_PARAM_inherit(to, from);
358f1535dc8Sdjm 	to->inh_flags = save_flags;
359f1535dc8Sdjm 	return ret;
3605650a0e1Sdjm }
3615650a0e1Sdjm 
362deda88cbSbeck static int
363deda88cbSbeck int_x509_param_set1(char **pdest, size_t *pdestlen,  const char *src,
364deda88cbSbeck     size_t srclen)
365deda88cbSbeck {
366deda88cbSbeck 	char *tmp;
367deda88cbSbeck 	if (src) {
368deda88cbSbeck 		if (srclen == 0) {
369deda88cbSbeck 			if ((tmp = strdup(src)) == NULL)
370deda88cbSbeck 				return 0;
371deda88cbSbeck 			srclen = strlen(src);
372deda88cbSbeck 		} else {
373deda88cbSbeck 			if ((tmp = malloc(srclen)) == NULL)
374deda88cbSbeck 				return 0;
375deda88cbSbeck 			memcpy(tmp, src, srclen);
376deda88cbSbeck 		}
377deda88cbSbeck 	} else {
378deda88cbSbeck 		tmp = NULL;
379deda88cbSbeck 		srclen = 0;
380deda88cbSbeck 	}
381deda88cbSbeck 	if (*pdest)
382deda88cbSbeck 		free(*pdest);
383deda88cbSbeck 	*pdest = tmp;
384deda88cbSbeck 	if (pdestlen)
385deda88cbSbeck 		*pdestlen = srclen;
386deda88cbSbeck 	return 1;
387deda88cbSbeck }
388deda88cbSbeck 
38915238b08Sjsing int
39015238b08Sjsing X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
3915650a0e1Sdjm {
3926f3a6cb1Sbeck 	free(param->name);
393cfa3bb9dSmiod 	param->name = NULL;
39469442892Sbeck 	if (name == NULL)
39569442892Sbeck 		return 1;
39669442892Sbeck 	param->name = strdup(name);
3975650a0e1Sdjm 	if (param->name)
3985650a0e1Sdjm 		return 1;
3995650a0e1Sdjm 	return 0;
4005650a0e1Sdjm }
4015650a0e1Sdjm 
40215238b08Sjsing int
40315238b08Sjsing X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
4045650a0e1Sdjm {
4055650a0e1Sdjm 	param->flags |= flags;
4065650a0e1Sdjm 	if (flags & X509_V_FLAG_POLICY_MASK)
4075650a0e1Sdjm 		param->flags |= X509_V_FLAG_POLICY_CHECK;
4085650a0e1Sdjm 	return 1;
4095650a0e1Sdjm }
4105650a0e1Sdjm 
41115238b08Sjsing int
41215238b08Sjsing X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
4135650a0e1Sdjm {
4145650a0e1Sdjm 	param->flags &= ~flags;
4155650a0e1Sdjm 	return 1;
4165650a0e1Sdjm }
4175650a0e1Sdjm 
41815238b08Sjsing unsigned long
41915238b08Sjsing X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
4205650a0e1Sdjm {
4215650a0e1Sdjm 	return param->flags;
4225650a0e1Sdjm }
4235650a0e1Sdjm 
42415238b08Sjsing int
42515238b08Sjsing X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
4265650a0e1Sdjm {
4275650a0e1Sdjm 	return X509_PURPOSE_set(&param->purpose, purpose);
4285650a0e1Sdjm }
4295650a0e1Sdjm 
43015238b08Sjsing int
43115238b08Sjsing X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
4325650a0e1Sdjm {
4335650a0e1Sdjm 	return X509_TRUST_set(&param->trust, trust);
4345650a0e1Sdjm }
4355650a0e1Sdjm 
43615238b08Sjsing void
43715238b08Sjsing X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
4385650a0e1Sdjm {
4395650a0e1Sdjm 	param->depth = depth;
4405650a0e1Sdjm }
4415650a0e1Sdjm 
44215238b08Sjsing void
44315238b08Sjsing X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
4445650a0e1Sdjm {
4455650a0e1Sdjm 	param->check_time = t;
4465650a0e1Sdjm 	param->flags |= X509_V_FLAG_USE_CHECK_TIME;
4475650a0e1Sdjm }
4485650a0e1Sdjm 
44915238b08Sjsing int
45015238b08Sjsing X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
4515650a0e1Sdjm {
4527609e5c6Stedu 	if (!param->policies) {
4535650a0e1Sdjm 		param->policies = sk_ASN1_OBJECT_new_null();
4545650a0e1Sdjm 		if (!param->policies)
4555650a0e1Sdjm 			return 0;
4565650a0e1Sdjm 	}
4575650a0e1Sdjm 	if (!sk_ASN1_OBJECT_push(param->policies, policy))
4585650a0e1Sdjm 		return 0;
4595650a0e1Sdjm 	return 1;
4605650a0e1Sdjm }
4615650a0e1Sdjm 
46215238b08Sjsing int
46315238b08Sjsing X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
4645650a0e1Sdjm     STACK_OF(ASN1_OBJECT) *policies)
4655650a0e1Sdjm {
4665650a0e1Sdjm 	int i;
4675650a0e1Sdjm 	ASN1_OBJECT *oid, *doid;
46815238b08Sjsing 
4695650a0e1Sdjm 	if (!param)
4705650a0e1Sdjm 		return 0;
4715650a0e1Sdjm 	if (param->policies)
4725650a0e1Sdjm 		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
4735650a0e1Sdjm 
4747609e5c6Stedu 	if (!policies) {
4755650a0e1Sdjm 		param->policies = NULL;
4765650a0e1Sdjm 		return 1;
4775650a0e1Sdjm 	}
4785650a0e1Sdjm 
4795650a0e1Sdjm 	param->policies = sk_ASN1_OBJECT_new_null();
4805650a0e1Sdjm 	if (!param->policies)
4815650a0e1Sdjm 		return 0;
4825650a0e1Sdjm 
4837609e5c6Stedu 	for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
4845650a0e1Sdjm 		oid = sk_ASN1_OBJECT_value(policies, i);
4855650a0e1Sdjm 		doid = OBJ_dup(oid);
4865650a0e1Sdjm 		if (!doid)
4875650a0e1Sdjm 			return 0;
4887609e5c6Stedu 		if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
4895650a0e1Sdjm 			ASN1_OBJECT_free(doid);
4905650a0e1Sdjm 			return 0;
4915650a0e1Sdjm 		}
4925650a0e1Sdjm 	}
4935650a0e1Sdjm 	param->flags |= X509_V_FLAG_POLICY_CHECK;
4945650a0e1Sdjm 	return 1;
4955650a0e1Sdjm }
4965650a0e1Sdjm 
49715238b08Sjsing int
498deda88cbSbeck X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
499deda88cbSbeck     const char *name, size_t namelen)
500deda88cbSbeck {
501deda88cbSbeck 	return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
502deda88cbSbeck }
503deda88cbSbeck 
504deda88cbSbeck int
505deda88cbSbeck X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
506deda88cbSbeck     const char *name, size_t namelen)
507deda88cbSbeck {
508deda88cbSbeck 	return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
509deda88cbSbeck }
510deda88cbSbeck 
511deda88cbSbeck void
512deda88cbSbeck X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags)
513deda88cbSbeck {
514deda88cbSbeck 	param->id->hostflags = flags;
515deda88cbSbeck }
516deda88cbSbeck 
517deda88cbSbeck char *
518deda88cbSbeck X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
519deda88cbSbeck {
520deda88cbSbeck 	return param->id->peername;
521deda88cbSbeck }
522deda88cbSbeck 
523deda88cbSbeck int
524deda88cbSbeck X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,  const char *email,
525deda88cbSbeck     size_t emaillen)
526deda88cbSbeck {
527deda88cbSbeck 	return int_x509_param_set1(&param->id->email, &param->id->emaillen,
528deda88cbSbeck 	    email, emaillen);
529deda88cbSbeck }
530deda88cbSbeck 
531deda88cbSbeck int
532deda88cbSbeck X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
533deda88cbSbeck     size_t iplen)
534deda88cbSbeck {
535deda88cbSbeck 	if (iplen != 0 && iplen != 4 && iplen != 16)
536deda88cbSbeck 		return 0;
537deda88cbSbeck 	return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen,
538deda88cbSbeck 	    (char *)ip, iplen);
539deda88cbSbeck }
540deda88cbSbeck 
541deda88cbSbeck int
542deda88cbSbeck X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
543deda88cbSbeck {
544deda88cbSbeck 	unsigned char ipout[16];
545deda88cbSbeck 	size_t iplen;
546deda88cbSbeck 
547deda88cbSbeck 	iplen = (size_t)a2i_ipadd(ipout, ipasc);
548deda88cbSbeck 	if (iplen == 0)
549deda88cbSbeck 		return 0;
550deda88cbSbeck 	return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
551deda88cbSbeck }
552deda88cbSbeck 
553deda88cbSbeck int
55415238b08Sjsing X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
5555650a0e1Sdjm {
5565650a0e1Sdjm 	return param->depth;
5575650a0e1Sdjm }
5585650a0e1Sdjm 
559deda88cbSbeck const char *
560deda88cbSbeck X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
561deda88cbSbeck {
562deda88cbSbeck 	return param->name;
563deda88cbSbeck }
564deda88cbSbeck 
565deda88cbSbeck static const X509_VERIFY_PARAM_ID _empty_id = { NULL };
566deda88cbSbeck 
567deda88cbSbeck #define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
568deda88cbSbeck 
569deda88cbSbeck /*
570deda88cbSbeck  * Default verify parameters: these are used for various applications and can
571deda88cbSbeck  * be overridden by the user specified table.
5725650a0e1Sdjm  */
5735650a0e1Sdjm 
5745650a0e1Sdjm static const X509_VERIFY_PARAM default_table[] = {
5755650a0e1Sdjm 	{
576deda88cbSbeck 		.name = "default",
577deda88cbSbeck 		.depth = 100,
578*f69362f8Sbeck 		.trust = 0,  /* XXX This is not the default trust value */
579deda88cbSbeck 		.id = vpm_empty_id
5805650a0e1Sdjm 	},
5815650a0e1Sdjm 	{
582deda88cbSbeck 		.name = "pkcs7",
583deda88cbSbeck 		.purpose = X509_PURPOSE_SMIME_SIGN,
584deda88cbSbeck 		.trust = X509_TRUST_EMAIL,
585deda88cbSbeck 		.depth = -1,
586deda88cbSbeck 		.id = vpm_empty_id
587e2ee43e0Sdjm 	},
588e2ee43e0Sdjm 	{
589deda88cbSbeck 		.name = "smime_sign",
590deda88cbSbeck 		.purpose = X509_PURPOSE_SMIME_SIGN,
591deda88cbSbeck 		.trust = X509_TRUST_EMAIL,
592deda88cbSbeck 		.depth =  -1,
593deda88cbSbeck 		.id = vpm_empty_id
5945650a0e1Sdjm 	},
5955650a0e1Sdjm 	{
596deda88cbSbeck 		.name = "ssl_client",
597deda88cbSbeck 		.purpose = X509_PURPOSE_SSL_CLIENT,
598deda88cbSbeck 		.trust = X509_TRUST_SSL_CLIENT,
599deda88cbSbeck 		.depth = -1,
600deda88cbSbeck 		.id = vpm_empty_id
6015650a0e1Sdjm 	},
6025650a0e1Sdjm 	{
603deda88cbSbeck 		.name = "ssl_server",
604deda88cbSbeck 		.purpose = X509_PURPOSE_SSL_SERVER,
605deda88cbSbeck 		.trust = X509_TRUST_SSL_SERVER,
606deda88cbSbeck 		.depth = -1,
607deda88cbSbeck 		.id = vpm_empty_id
6087609e5c6Stedu 	}
6097609e5c6Stedu };
6105650a0e1Sdjm 
6115650a0e1Sdjm static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
6125650a0e1Sdjm 
61315238b08Sjsing static int
61415238b08Sjsing param_cmp(const X509_VERIFY_PARAM * const *a,
6155650a0e1Sdjm     const X509_VERIFY_PARAM * const *b)
6165650a0e1Sdjm {
6175650a0e1Sdjm 	return strcmp((*a)->name, (*b)->name);
6185650a0e1Sdjm }
6195650a0e1Sdjm 
62015238b08Sjsing int
62115238b08Sjsing X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
6225650a0e1Sdjm {
6235650a0e1Sdjm 	X509_VERIFY_PARAM *ptmp;
6247609e5c6Stedu 	if (!param_table) {
6255650a0e1Sdjm 		param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
6265650a0e1Sdjm 		if (!param_table)
6275650a0e1Sdjm 			return 0;
6287609e5c6Stedu 	} else {
629deda88cbSbeck 		size_t idx;
630deda88cbSbeck 
631deda88cbSbeck 		if ((idx = sk_X509_VERIFY_PARAM_find(param_table, param))
632deda88cbSbeck 		    != -1) {
633deda88cbSbeck 			ptmp = sk_X509_VERIFY_PARAM_value(param_table,
634deda88cbSbeck 			    idx);
6355650a0e1Sdjm 			X509_VERIFY_PARAM_free(ptmp);
636deda88cbSbeck 			(void)sk_X509_VERIFY_PARAM_delete(param_table,
637deda88cbSbeck 			    idx);
6385650a0e1Sdjm 		}
6395650a0e1Sdjm 	}
6405650a0e1Sdjm 	if (!sk_X509_VERIFY_PARAM_push(param_table, param))
6415650a0e1Sdjm 		return 0;
6425650a0e1Sdjm 	return 1;
6435650a0e1Sdjm }
6445650a0e1Sdjm 
645deda88cbSbeck int
646deda88cbSbeck X509_VERIFY_PARAM_get_count(void)
6475650a0e1Sdjm {
648deda88cbSbeck 	int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
649deda88cbSbeck 	if (param_table)
650deda88cbSbeck 		num += sk_X509_VERIFY_PARAM_num(param_table);
651deda88cbSbeck 	return num;
652deda88cbSbeck }
653deda88cbSbeck 
654deda88cbSbeck const
655deda88cbSbeck X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
656deda88cbSbeck {
657deda88cbSbeck 	int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
658deda88cbSbeck 	if (id < num)
659deda88cbSbeck 		return default_table + id;
660deda88cbSbeck 	return sk_X509_VERIFY_PARAM_value(param_table, id - num);
661deda88cbSbeck }
662deda88cbSbeck 
663deda88cbSbeck const
664deda88cbSbeck X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
665deda88cbSbeck {
6665650a0e1Sdjm 	X509_VERIFY_PARAM pm;
667deda88cbSbeck 	unsigned int i, limit;
668f1535dc8Sdjm 
6695650a0e1Sdjm 	pm.name = (char *)name;
6707609e5c6Stedu 	if (param_table) {
671deda88cbSbeck 		size_t idx;
672deda88cbSbeck 		if ((idx = sk_X509_VERIFY_PARAM_find(param_table, &pm)) != -1)
6735650a0e1Sdjm 			return sk_X509_VERIFY_PARAM_value(param_table, idx);
6745650a0e1Sdjm 	}
675deda88cbSbeck 
676deda88cbSbeck 	limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
677deda88cbSbeck 	for (i = 0; i < limit; i++) {
678deda88cbSbeck 		if (strcmp(default_table[i].name, name) == 0) {
679deda88cbSbeck 			return &default_table[i];
680deda88cbSbeck 		}
681deda88cbSbeck 	}
682deda88cbSbeck 	return NULL;
6835650a0e1Sdjm }
6845650a0e1Sdjm 
68515238b08Sjsing void
68615238b08Sjsing X509_VERIFY_PARAM_table_cleanup(void)
6875650a0e1Sdjm {
6885650a0e1Sdjm 	if (param_table)
6895650a0e1Sdjm 		sk_X509_VERIFY_PARAM_pop_free(param_table,
6905650a0e1Sdjm 		    X509_VERIFY_PARAM_free);
6915650a0e1Sdjm 	param_table = NULL;
6925650a0e1Sdjm }
693