verifytest.c revision 1.1
1/*	$OpenBSD: verifytest.c,v 1.1 2014/11/01 11:55:27 jsing Exp $	*/
2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <err.h>
19#include <stdio.h>
20#include <stdlib.h>
21
22#include <openssl/x509v3.h>
23
24extern int tls_check_hostname(X509 *cert, const char *host);
25
26struct verify_test {
27	const char common_name[128];
28	const char alt_name[128];
29	int alt_name_len;
30	int alt_name_type;
31	const char hostname[128];
32	int want;
33};
34
35struct verify_test verify_tests[] = {
36	{
37		.common_name = "www.openbsd.org",
38		.hostname = "www.openbsd.org",
39		.want = 0,
40	},
41	{
42		.common_name = "www.openbsd.org",
43		.hostname = "",
44		.want = -1,
45	},
46	{
47		.common_name = "*.openbsd.org",
48		.hostname = "www.openbsd.org",
49		.want = 0,
50	},
51	{
52		.common_name = "www.openbsdfoundation.org",
53		.hostname = "www.openbsd.org",
54		.want = -1,
55	},
56	{
57		.common_name = "w*.openbsd.org",
58		.hostname = "www.openbsd.org",
59		.want = -1,
60	},
61	{
62		.common_name = "www.*.org",
63		.hostname = "www.openbsd.org",
64		.want = -1,
65	},
66	{
67		.common_name = "www.openbsd.*",
68		.hostname = "www.openbsd.org",
69		.want = -1,
70	},
71	{
72		.common_name = "*",
73		.hostname = "www.openbsd.org",
74		.want = -1,
75	},
76	{
77		.common_name = "*.org",
78		.hostname = "www.openbsd.org",
79		.want = -1,
80	},
81	{
82		.common_name = "*.org",
83		.hostname = "openbsd.org",
84		.want = -1,
85	},
86	{
87		.common_name = "1.2.3.4",
88		.hostname = "1.2.3.4",
89		.want = 0,
90	},
91	{
92		.common_name = "*.2.3.4",
93		.hostname = "1.2.3.4",
94		.want = -1,
95	},
96	{
97		.common_name = "cafe::beef",
98		.hostname = "cafe::beef",
99		.want = 0,
100	},
101	{
102		.common_name = "www.openbsd.org",
103		.alt_name = "ftp.openbsd.org",
104		.alt_name_len = -1,
105		.alt_name_type = GEN_DNS,
106		.hostname = "ftp.openbsd.org",
107		.want = 0,
108	},
109	{
110		.common_name = "www.openbsdfoundation.org",
111		.alt_name = "*.openbsd.org",
112		.alt_name_len = -1,
113		.alt_name_type = GEN_DNS,
114		.hostname = "www.openbsd.org",
115		.want = 0,
116	},
117	{
118		.common_name = "www.openbsdfoundation.org",
119		.alt_name = "*.org",
120		.alt_name_len = -1,
121		.alt_name_type = GEN_DNS,
122		.hostname = "www.openbsd.org",
123		.want = -1,
124	},
125	{
126		.common_name = "www.openbsd.org",
127		.alt_name = "1.2.3.4",
128		.alt_name_len = -1,
129		.alt_name_type = GEN_DNS,
130		.hostname = "1.2.3.4",
131		.want = -1,
132	},
133	{
134		.common_name = "www.openbsd.org",
135		.alt_name = {0x1, 0x2, 0x3, 0x4},
136		.alt_name_len = 4,
137		.alt_name_type = GEN_IPADD,
138		.hostname = "1.2.3.4",
139		.want = 0,
140	},
141	{
142		.common_name = "www.openbsd.org",
143		.alt_name = {
144			0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xef,
146		},
147		.alt_name_len = 16,
148		.alt_name_type = GEN_IPADD,
149		.hostname = "cafe::beef",
150		.want = 0,
151	},
152};
153
154#define N_VERIFY_TESTS \
155    (sizeof(verify_tests) / sizeof(*verify_tests))
156
157static int
158do_verify_test(int test_no, struct verify_test *vt)
159{
160	STACK_OF(GENERAL_NAME) *alt_name_stack = NULL;
161	ASN1_STRING *alt_name_str;
162	GENERAL_NAME *alt_name;
163	X509_NAME *name;
164	X509 *cert;
165
166	/* Build certificate structure. */
167	if ((cert = X509_new()) == NULL)
168		errx(1, "failed to malloc X509");
169	if ((name = X509_NAME_new()) == NULL)
170		errx(1, "failed to malloc X509_NAME");
171	if (X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC,
172	    (unsigned char *)vt->common_name, -1, -1, 0) == 0)
173		errx(1, "failed to add name entry");
174	if (X509_set_subject_name(cert, name) == 0)
175		errx(1, "failed to set subject name");
176	X509_NAME_free(name);
177
178	if (vt->alt_name_type != 0) {
179		if ((alt_name_stack = sk_GENERAL_NAME_new_null()) == NULL)
180			errx(1, "failed to malloc sk_GENERAL_NAME");
181		if ((alt_name = GENERAL_NAME_new()) == NULL)
182			errx(1, "failed to malloc GENERAL_NAME");
183		alt_name->type = vt->alt_name_type;
184
185		if ((alt_name_str = ASN1_STRING_new()) == NULL)
186			errx(1, "failed to malloc alt name");
187		if (ASN1_STRING_set(alt_name_str, vt->alt_name,
188		    vt->alt_name_len) == 0)
189			errx(1, "failed to set alt name");
190
191		switch (alt_name->type) {
192		case GEN_DNS:
193			alt_name->d.dNSName = alt_name_str;
194			break;
195
196		case GEN_IPADD:
197			alt_name->d.iPAddress = alt_name_str;
198			break;
199
200		default:
201			errx(1, "unknown alt name type (%i)", alt_name->type);
202		}
203
204		if (sk_GENERAL_NAME_push(alt_name_stack, alt_name) == 0)
205			errx(1, "failed to push alt_name");
206		if (X509_add1_ext_i2d(cert, NID_subject_alt_name,
207		    alt_name_stack, 0, 0) == 0)
208			errx(1, "failed to set subject alt name");
209		sk_GENERAL_NAME_pop_free(alt_name_stack, GENERAL_NAME_free);
210	}
211
212	if (tls_check_hostname(cert, vt->hostname) != vt->want) {
213		fprintf(stderr, "FAIL: test %i failed with common name "
214		    "'%s', alt name '%s' and hostname '%s'\n", test_no,
215		    vt->common_name, vt->alt_name, vt->hostname);
216		return (1);
217	}
218
219	X509_free(cert);
220
221	return (0);
222}
223
224int
225main(int argc, char **argv)
226{
227	int failed = 0;
228	size_t i;
229
230	for (i = 0; i < N_VERIFY_TESTS; i++)
231		failed += do_verify_test(i, &verify_tests[i]);
232
233	return (failed);
234}
235