1/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2 * project 2004. */
3/* ====================================================================
4 * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in
15 *    the documentation and/or other materials provided with the
16 *    distribution.
17 *
18 * 3. All advertising materials mentioning features or use of this
19 *    software must display the following acknowledgment:
20 *    "This product includes software developed by the OpenSSL Project
21 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
22 *
23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
24 *    endorse or promote products derived from this software without
25 *    prior written permission. For written permission, please contact
26 *    licensing@OpenSSL.org.
27 *
28 * 5. Products derived from this software may not be called "OpenSSL"
29 *    nor may "OpenSSL" appear in their names without prior written
30 *    permission of the OpenSSL Project.
31 *
32 * 6. Redistributions of any form whatsoever must retain the following
33 *    acknowledgment:
34 *    "This product includes software developed by the OpenSSL Project
35 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48 * OF THE POSSIBILITY OF SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This product includes cryptographic software written by Eric Young
52 * (eay@cryptsoft.com).  This product includes software written by Tim
53 * Hudson (tjh@cryptsoft.com). */
54
55#include <string.h>
56
57#include <openssl/buf.h>
58#include <openssl/lhash.h>
59#include <openssl/mem.h>
60#include <openssl/obj.h>
61#include <openssl/stack.h>
62#include <openssl/x509.h>
63#include <openssl/x509v3.h>
64
65#include "vpm_int.h"
66
67
68/* X509_VERIFY_PARAM functions */
69
70#define SET_HOST 0
71#define ADD_HOST 1
72
73static char *str_copy(char *s) { return OPENSSL_strdup(s); }
74static void str_free(char *s) { OPENSSL_free(s); }
75
76#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
77
78static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
79				    const char *name, size_t namelen)
80	{
81	char *copy;
82
83	/*
84	 * Refuse names with embedded NUL bytes.
85	 * XXX: Do we need to push an error onto the error stack?
86	 */
87	if (name && memchr(name, '\0', namelen))
88		 return 0;
89
90	if (mode == SET_HOST && id->hosts)
91		{
92		string_stack_free(id->hosts);
93		id->hosts = NULL;
94		}
95	if (name == NULL || namelen == 0)
96		return 1;
97
98	copy = BUF_strndup(name, namelen);
99	if (copy == NULL)
100		return 0;
101
102	if (id->hosts == NULL &&
103	    (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL)
104		{
105		OPENSSL_free(copy);
106		return 0;
107		}
108
109	if (!sk_OPENSSL_STRING_push(id->hosts, copy))
110		{
111		OPENSSL_free(copy);
112		if (sk_OPENSSL_STRING_num(id->hosts) == 0)
113			{
114			sk_OPENSSL_STRING_free(id->hosts);
115			id->hosts = NULL;
116			}
117		return 0;
118		}
119
120	return 1;
121	}
122
123static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
124	{
125	X509_VERIFY_PARAM_ID *paramid;
126	if (!param)
127		return;
128	param->name = NULL;
129	param->purpose = 0;
130	param->trust = 0;
131	/*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
132	param->inh_flags = 0;
133	param->flags = 0;
134	param->depth = -1;
135	if (param->policies)
136		{
137		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
138		param->policies = NULL;
139		}
140	paramid = param->id;
141	if (paramid->hosts)
142		{
143		string_stack_free(paramid->hosts);
144		paramid->hosts = NULL;
145		}
146	if (paramid->peername)
147		{
148		OPENSSL_free(paramid->peername);
149		paramid->peername = NULL;
150		}
151	if (paramid->email)
152		{
153		OPENSSL_free(paramid->email);
154		paramid->email = NULL;
155		paramid->emaillen = 0;
156		}
157	if (paramid->ip)
158		{
159		OPENSSL_free(paramid->ip);
160		paramid->ip = NULL;
161		paramid->iplen = 0;
162		}
163
164	}
165
166X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
167	{
168	X509_VERIFY_PARAM *param;
169	X509_VERIFY_PARAM_ID *paramid;
170	param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
171	if (!param)
172		return NULL;
173	paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID));
174	if (!paramid)
175		{
176		OPENSSL_free(param);
177		return NULL;
178		}
179	memset(param, 0, sizeof(X509_VERIFY_PARAM));
180	memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
181	param->id = paramid;
182	x509_verify_param_zero(param);
183	return param;
184	}
185
186void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
187	{
188	if (param == NULL)
189		return;
190	x509_verify_param_zero(param);
191	OPENSSL_free(param->id);
192	OPENSSL_free(param);
193	}
194
195/* This function determines how parameters are "inherited" from one structure
196 * to another. There are several different ways this can happen.
197 *
198 * 1. If a child structure needs to have its values initialized from a parent
199 *    they are simply copied across. For example SSL_CTX copied to SSL.
200 * 2. If the structure should take on values only if they are currently unset.
201 *    For example the values in an SSL structure will take appropriate value
202 *    for SSL servers or clients but only if the application has not set new
203 *    ones.
204 *
205 * The "inh_flags" field determines how this function behaves.
206 *
207 * Normally any values which are set in the default are not copied from the
208 * destination and verify flags are ORed together.
209 *
210 * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
211 * to the destination. Effectively the values in "to" become default values
212 * which will be used only if nothing new is set in "from".
213 *
214 * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
215 * they are set or not. Flags is still Ored though.
216 *
217 * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
218 * of ORed.
219 *
220 * If X509_VP_FLAG_LOCKED is set then no values are copied.
221 *
222 * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
223 * after the next call.
224 */
225
226/* Macro to test if a field should be copied from src to dest */
227
228#define test_x509_verify_param_copy(field, def) \
229	(to_overwrite || \
230		((src->field != def) && (to_default || (dest->field == def))))
231
232/* As above but for ID fields */
233
234#define test_x509_verify_param_copy_id(idf, def) \
235	test_x509_verify_param_copy(id->idf, def)
236
237/* Macro to test and copy a field if necessary */
238
239#define x509_verify_param_copy(field, def) \
240	if (test_x509_verify_param_copy(field, def)) \
241		dest->field = src->field
242
243
244int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
245						const X509_VERIFY_PARAM *src)
246	{
247	unsigned long inh_flags;
248	int to_default, to_overwrite;
249	X509_VERIFY_PARAM_ID *id;
250	if (!src)
251		return 1;
252	id = src->id;
253	inh_flags = dest->inh_flags | src->inh_flags;
254
255	if (inh_flags & X509_VP_FLAG_ONCE)
256		dest->inh_flags = 0;
257
258	if (inh_flags & X509_VP_FLAG_LOCKED)
259		return 1;
260
261	if (inh_flags & X509_VP_FLAG_DEFAULT)
262		to_default = 1;
263	else
264		to_default = 0;
265
266	if (inh_flags & X509_VP_FLAG_OVERWRITE)
267		to_overwrite = 1;
268	else
269		to_overwrite = 0;
270
271	x509_verify_param_copy(purpose, 0);
272	x509_verify_param_copy(trust, 0);
273	x509_verify_param_copy(depth, -1);
274
275	/* If overwrite or check time not set, copy across */
276
277	if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME))
278		{
279		dest->check_time = src->check_time;
280		dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
281		/* Don't need to copy flag: that is done below */
282		}
283
284	if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
285		dest->flags = 0;
286
287	dest->flags |= src->flags;
288
289	if (test_x509_verify_param_copy(policies, NULL))
290		{
291		if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
292			return 0;
293		}
294
295	/* Copy the host flags if and only if we're copying the host list */
296	if (test_x509_verify_param_copy_id(hosts, NULL))
297		{
298		if (dest->id->hosts)
299			{
300			string_stack_free(dest->id->hosts);
301			dest->id->hosts = NULL;
302			}
303		if (id->hosts)
304			{
305			dest->id->hosts =
306			    sk_OPENSSL_STRING_deep_copy(id->hosts,
307							str_copy, str_free);
308			if (dest->id->hosts == NULL)
309				return 0;
310			dest->id->hostflags = id->hostflags;
311			}
312		}
313
314	if (test_x509_verify_param_copy_id(email, NULL))
315		{
316		if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
317			return 0;
318		}
319
320	if (test_x509_verify_param_copy_id(ip, NULL))
321		{
322		if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
323			return 0;
324		}
325
326	return 1;
327	}
328
329int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
330						const X509_VERIFY_PARAM *from)
331	{
332	unsigned long save_flags = to->inh_flags;
333	int ret;
334	to->inh_flags |= X509_VP_FLAG_DEFAULT;
335	ret = X509_VERIFY_PARAM_inherit(to, from);
336	to->inh_flags = save_flags;
337	return ret;
338	}
339
340static int int_x509_param_set1(char **pdest, size_t *pdestlen,
341				const char *src, size_t srclen)
342	{
343	void *tmp;
344	if (src)
345		{
346		if (srclen == 0)
347			{
348			tmp = BUF_strdup(src);
349			srclen = strlen(src);
350			}
351		else
352			tmp = BUF_memdup(src, srclen);
353		if (!tmp)
354			return 0;
355		}
356	else
357		{
358		tmp = NULL;
359		srclen = 0;
360		}
361	if (*pdest)
362		OPENSSL_free(*pdest);
363	*pdest = tmp;
364	if (pdestlen)
365		*pdestlen = srclen;
366	return 1;
367	}
368
369int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
370	{
371	if (param->name)
372		OPENSSL_free(param->name);
373	param->name = BUF_strdup(name);
374	if (param->name)
375		return 1;
376	return 0;
377	}
378
379int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
380	{
381	param->flags |= flags;
382	if (flags & X509_V_FLAG_POLICY_MASK)
383		param->flags |= X509_V_FLAG_POLICY_CHECK;
384	return 1;
385	}
386
387int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
388	{
389	param->flags &= ~flags;
390	return 1;
391	}
392
393unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
394	{
395	return param->flags;
396	}
397
398int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
399	{
400	return X509_PURPOSE_set(&param->purpose, purpose);
401	}
402
403int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
404	{
405	return X509_TRUST_set(&param->trust, trust);
406	}
407
408void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
409	{
410	param->depth = depth;
411	}
412
413void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
414	{
415	param->check_time = t;
416	param->flags |= X509_V_FLAG_USE_CHECK_TIME;
417	}
418
419int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
420	{
421	if (!param->policies)
422		{
423		param->policies = sk_ASN1_OBJECT_new_null();
424		if (!param->policies)
425			return 0;
426		}
427	if (!sk_ASN1_OBJECT_push(param->policies, policy))
428		return 0;
429	return 1;
430	}
431
432int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
433					STACK_OF(ASN1_OBJECT) *policies)
434	{
435	size_t i;
436	ASN1_OBJECT *oid, *doid;
437	if (!param)
438		return 0;
439	if (param->policies)
440		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
441
442	if (!policies)
443		{
444		param->policies = NULL;
445		return 1;
446		}
447
448	param->policies = sk_ASN1_OBJECT_new_null();
449	if (!param->policies)
450		return 0;
451
452	for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++)
453		{
454		oid = sk_ASN1_OBJECT_value(policies, i);
455		doid = OBJ_dup(oid);
456		if (!doid)
457			return 0;
458		if (!sk_ASN1_OBJECT_push(param->policies, doid))
459			{
460			ASN1_OBJECT_free(doid);
461			return 0;
462			}
463		}
464	param->flags |= X509_V_FLAG_POLICY_CHECK;
465	return 1;
466	}
467
468int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
469				const char *name, size_t namelen)
470	{
471	return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
472	}
473
474int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
475				const char *name, size_t namelen)
476	{
477	return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
478	}
479
480void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
481					unsigned int flags)
482	{
483	param->id->hostflags = flags;
484	}
485
486char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
487	{
488	return param->id->peername;
489	}
490
491int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
492				const char *email, size_t emaillen)
493	{
494	return int_x509_param_set1(&param->id->email, &param->id->emaillen,
495					email, emaillen);
496	}
497
498int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
499					const unsigned char *ip, size_t iplen)
500	{
501	if (iplen != 0 && iplen != 4 && iplen != 16)
502		return 0;
503	return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen,
504				   (char *)ip, iplen);
505	}
506
507int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
508	{
509	unsigned char ipout[16];
510	size_t iplen;
511
512	iplen = (size_t) a2i_ipadd(ipout, ipasc);
513	if (iplen == 0)
514		return 0;
515	return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
516	}
517
518int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
519	{
520	return param->depth;
521	}
522
523const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
524	{
525	return param->name;
526	}
527
528static const X509_VERIFY_PARAM_ID _empty_id = {NULL, 0U, NULL, NULL, 0, NULL, 0};
529
530#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
531
532/* Default verify parameters: these are used for various
533 * applications and can be overridden by the user specified table.
534 * NB: the 'name' field *must* be in alphabetical order because it
535 * will be searched using OBJ_search.
536 */
537
538static const X509_VERIFY_PARAM default_table[] = {
539	{
540	(char *) "default",	/* X509 default parameters */
541	0,		/* Check time */
542	0,		/* internal flags */
543	0,		/* flags */
544	0,		/* purpose */
545	0,		/* trust */
546	100,		/* depth */
547	NULL,		/* policies */
548	vpm_empty_id
549	},
550	{
551	(char *) "pkcs7",			/* S/MIME sign parameters */
552	0,				/* Check time */
553	0,				/* internal flags */
554	0,				/* flags */
555	X509_PURPOSE_SMIME_SIGN,	/* purpose */
556	X509_TRUST_EMAIL,		/* trust */
557	-1,				/* depth */
558	NULL,				/* policies */
559	vpm_empty_id
560	},
561	{
562	(char *) "smime_sign",			/* S/MIME sign parameters */
563	0,				/* Check time */
564	0,				/* internal flags */
565	0,				/* flags */
566	X509_PURPOSE_SMIME_SIGN,	/* purpose */
567	X509_TRUST_EMAIL,		/* trust */
568	-1,				/* depth */
569	NULL,				/* policies */
570	vpm_empty_id
571	},
572	{
573	(char *) "ssl_client",			/* SSL/TLS client parameters */
574	0,				/* Check time */
575	0,				/* internal flags */
576	0,				/* flags */
577	X509_PURPOSE_SSL_CLIENT,	/* purpose */
578	X509_TRUST_SSL_CLIENT,		/* trust */
579	-1,				/* depth */
580	NULL,				/* policies */
581	vpm_empty_id
582	},
583	{
584	(char *) "ssl_server",			/* SSL/TLS server parameters */
585	0,				/* Check time */
586	0,				/* internal flags */
587	0,				/* flags */
588	X509_PURPOSE_SSL_SERVER,	/* purpose */
589	X509_TRUST_SSL_SERVER,		/* trust */
590	-1,				/* depth */
591	NULL,				/* policies */
592	vpm_empty_id
593	}};
594
595static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
596
597static int param_cmp(const X509_VERIFY_PARAM **a,
598			const X509_VERIFY_PARAM **b)
599	{
600	return strcmp((*a)->name, (*b)->name);
601	}
602
603int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
604	{
605	X509_VERIFY_PARAM *ptmp;
606	if (!param_table)
607		{
608		param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
609		if (!param_table)
610			return 0;
611		}
612	else
613		{
614		size_t idx;
615
616		if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param))
617			{
618			ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
619			X509_VERIFY_PARAM_free(ptmp);
620			(void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
621			}
622		}
623	if (!sk_X509_VERIFY_PARAM_push(param_table, param))
624		return 0;
625	return 1;
626	}
627
628int X509_VERIFY_PARAM_get_count(void)
629	{
630	int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
631	if (param_table)
632		num += sk_X509_VERIFY_PARAM_num(param_table);
633	return num;
634	}
635
636const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
637	{
638	int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
639	if (id < num)
640		return default_table + id;
641	return sk_X509_VERIFY_PARAM_value(param_table, id - num);
642	}
643
644const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
645	{
646	X509_VERIFY_PARAM pm;
647	unsigned i, limit;
648
649	pm.name = (char *)name;
650	if (param_table)
651		{
652		size_t idx;
653		if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm))
654			return sk_X509_VERIFY_PARAM_value(param_table, idx);
655		}
656
657	limit = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
658	for (i = 0; i < limit; i++) {
659		if (strcmp(default_table[i].name, name) == 0) {
660			return &default_table[i];
661		}
662	}
663	return NULL;
664	}
665
666void X509_VERIFY_PARAM_table_cleanup(void)
667	{
668	if (param_table)
669		sk_X509_VERIFY_PARAM_pop_free(param_table,
670						X509_VERIFY_PARAM_free);
671	param_table = NULL;
672	}
673