Branch data Line data Source code
1 : : #include <openssl/x509.h>
2 : : #include <openssl/x509v3.h>
3 : : #include "../e_os.h"
4 : : #include <string.h>
5 : :
6 : : static const char *const names[] =
7 : : {
8 : : "a", "b", ".", "*", "@",
9 : : ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
10 : : "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
11 : : "*@example.com", "test@*.example.com", "example.com", "www.example.com",
12 : : "test.www.example.com", "*.example.com", "*.www.example.com",
13 : : "test.*.example.com", "www.*.com",
14 : : ".www.example.com", "*www.example.com",
15 : : "example.net", "xn--rger-koa.example.com",
16 : : "a.example.com", "b.example.com",
17 : : "postmaster@example.com", "Postmaster@example.com",
18 : : "postmaster@EXAMPLE.COM",
19 : : NULL
20 : : };
21 : :
22 : : static const char *const exceptions[] =
23 : : {
24 : : "set CN: host: [*.example.com] matches [a.example.com]",
25 : : "set CN: host: [*.example.com] matches [b.example.com]",
26 : : "set CN: host: [*.example.com] matches [www.example.com]",
27 : : "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
28 : : "set CN: host: [*.www.example.com] matches [test.www.example.com]",
29 : : "set CN: host: [*.www.example.com] matches [.www.example.com]",
30 : : "set CN: host: [*www.example.com] matches [www.example.com]",
31 : : "set CN: host: [test.www.example.com] matches [.www.example.com]",
32 : : "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
33 : : "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
34 : : "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
35 : : "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
36 : : "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
37 : : "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
38 : : "set dnsName: host: [*.example.com] matches [www.example.com]",
39 : : "set dnsName: host: [*.example.com] matches [a.example.com]",
40 : : "set dnsName: host: [*.example.com] matches [b.example.com]",
41 : : "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
42 : : "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
43 : : "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
44 : : "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
45 : : "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
46 : : "set dnsName: host: [*www.example.com] matches [www.example.com]",
47 : : "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
48 : : "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
49 : : "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
50 : : "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
51 : : "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
52 : : NULL
53 : : };
54 : :
55 : 70 : static int is_exception(const char *msg)
56 : : {
57 : : const char *const *p;
58 [ + - ]: 721 : for (p = exceptions; *p; ++p)
59 [ + + ]: 721 : if (strcmp(msg, *p) == 0)
60 : : return 1;
61 : : return 0;
62 : : }
63 : :
64 : 344 : static int set_cn(X509 *crt, ...)
65 : : {
66 : 344 : int ret = 0;
67 : 344 : X509_NAME *n = NULL;
68 : : va_list ap;
69 : 344 : va_start(ap, crt);
70 : 344 : n = X509_NAME_new();
71 [ + - ]: 344 : if (n == NULL)
72 : : goto out;
73 : : while (1) {
74 : : int nid;
75 : : const char *name;
76 [ + - ]: 946 : nid = va_arg(ap, int);
77 [ + + ]: 946 : if (nid == 0)
78 : : break;
79 [ + - ]: 602 : name = va_arg(ap, const char *);
80 [ + - ]: 602 : if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC,
81 : : (unsigned char *)name,
82 : : -1, -1, 1))
83 : : goto out;
84 : : }
85 [ + - ]: 344 : if (!X509_set_subject_name(crt, n))
86 : : goto out;
87 : 344 : ret = 1;
88 : : out:
89 : 344 : X509_NAME_free(n);
90 : 344 : va_end(ap);
91 : 344 : return ret;
92 : : }
93 : :
94 : : /*
95 : : int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
96 : : X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
97 : : int nid, int crit, ASN1_OCTET_STRING *data);
98 : : int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
99 : : */
100 : :
101 : 86 : static int set_altname(X509 *crt, ...)
102 : : {
103 : 86 : int ret = 0;
104 : 86 : GENERAL_NAMES *gens = NULL;
105 : 86 : GENERAL_NAME *gen = NULL;
106 : 86 : ASN1_IA5STRING *ia5 = NULL;
107 : : va_list ap;
108 : 86 : va_start(ap, crt);
109 : 86 : gens = sk_GENERAL_NAME_new_null();
110 [ + - ]: 86 : if (gens == NULL)
111 : : goto out;
112 : : while (1) {
113 : : int type;
114 : : const char *name;
115 [ + - ]: 172 : type = va_arg(ap, int);
116 [ + + ]: 172 : if (type == 0)
117 : : break;
118 [ + - ]: 86 : name = va_arg(ap, const char *);
119 : :
120 : 86 : gen = GENERAL_NAME_new();
121 [ + - ]: 86 : if (gen == NULL)
122 : : goto out;
123 : 86 : ia5 = ASN1_IA5STRING_new();
124 [ + - ]: 86 : if (ia5 == NULL)
125 : : goto out;
126 [ + - ]: 86 : if (!ASN1_STRING_set(ia5, name, -1))
127 : : goto out;
128 [ + - ]: 86 : switch (type)
129 : : {
130 : : case GEN_EMAIL:
131 : : case GEN_DNS:
132 : 86 : GENERAL_NAME_set0_value(gen, type, ia5);
133 : 86 : ia5 = NULL;
134 : : break;
135 : : default:
136 : 0 : abort();
137 : : }
138 : 86 : sk_GENERAL_NAME_push(gens, gen);
139 : 86 : gen = NULL;
140 : 86 : }
141 [ + - ]: 86 : if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
142 : : goto out;
143 : 86 : ret = 1;
144 : : out:
145 : 86 : ASN1_IA5STRING_free(ia5);
146 : 86 : GENERAL_NAME_free(gen);
147 : 86 : GENERAL_NAMES_free(gens);
148 : 86 : va_end(ap);
149 : 86 : return ret;
150 : : }
151 : :
152 : 43 : static int set_cn1(X509 *crt, const char *name)
153 : : {
154 : 43 : return set_cn(crt, NID_commonName, name, 0);
155 : : }
156 : :
157 : :
158 : 43 : static int set_cn_and_email(X509 *crt, const char *name)
159 : : {
160 : 43 : return set_cn(crt, NID_commonName, name,
161 : : NID_pkcs9_emailAddress, "dummy@example.com", 0);
162 : : }
163 : :
164 : 43 : static int set_cn2(X509 *crt, const char *name)
165 : : {
166 : 43 : return set_cn(crt, NID_commonName, "dummy value",
167 : : NID_commonName, name, 0);
168 : : }
169 : :
170 : 43 : static int set_cn3(X509 *crt, const char *name)
171 : : {
172 : 43 : return set_cn(crt, NID_commonName, name,
173 : : NID_commonName, "dummy value", 0);
174 : : }
175 : :
176 : 43 : static int set_email1(X509 *crt, const char *name)
177 : : {
178 : 43 : return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
179 : : }
180 : :
181 : 43 : static int set_email2(X509 *crt, const char *name)
182 : : {
183 : 43 : return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
184 : : NID_pkcs9_emailAddress, name, 0);
185 : : }
186 : :
187 : 43 : static int set_email3(X509 *crt, const char *name)
188 : : {
189 : 43 : return set_cn(crt, NID_pkcs9_emailAddress, name,
190 : : NID_pkcs9_emailAddress, "dummy@example.com", 0);
191 : : }
192 : :
193 : 43 : static int set_email_and_cn(X509 *crt, const char *name)
194 : : {
195 : 43 : return set_cn(crt, NID_pkcs9_emailAddress, name,
196 : : NID_commonName, "www.example.org", 0);
197 : : }
198 : :
199 : 43 : static int set_altname_dns(X509 *crt, const char *name)
200 : : {
201 : 43 : return set_altname(crt, GEN_DNS, name, 0);
202 : : }
203 : :
204 : 43 : static int set_altname_email(X509 *crt, const char *name)
205 : : {
206 : 43 : return set_altname(crt, GEN_EMAIL, name, 0);
207 : : }
208 : :
209 : : struct set_name_fn
210 : : {
211 : : int (*fn)(X509 *, const char *);
212 : : const char *name;
213 : : int host;
214 : : int email;
215 : : };
216 : :
217 : : static const struct set_name_fn name_fns[] =
218 : : {
219 : : {set_cn1, "set CN", 1, 0},
220 : : {set_cn2, "set CN", 1, 0},
221 : : {set_cn3, "set CN", 1, 0},
222 : : {set_cn_and_email, "set CN", 1, 0},
223 : : {set_email1, "set emailAddress", 0, 1},
224 : : {set_email2, "set emailAddress", 0, 1},
225 : : {set_email3, "set emailAddress", 0, 1},
226 : : {set_email_and_cn, "set emailAddress", 0, 1},
227 : : {set_altname_dns, "set dnsName", 1, 0},
228 : : {set_altname_email, "set rfc822Name", 0, 1},
229 : : {NULL, NULL, 0}
230 : : };
231 : :
232 : 430 : static X509 *make_cert()
233 : : {
234 : 430 : X509 *ret = NULL;
235 : 430 : X509 *crt = NULL;
236 : 430 : X509_NAME *issuer = NULL;
237 : 430 : crt = X509_new();
238 [ + - ]: 430 : if (crt == NULL)
239 : : goto out;
240 [ + - ]: 430 : if (!X509_set_version(crt, 3))
241 : : goto out;
242 : 430 : ret = crt;
243 : 430 : crt = NULL;
244 : : out:
245 : 430 : X509_NAME_free(issuer);
246 : 430 : return ret;
247 : : }
248 : :
249 : : static int errors;
250 : :
251 : 55470 : static void check_message(const struct set_name_fn *fn, const char *op,
252 : : const char *nameincert, int match, const char *name)
253 : : {
254 : : char msg[1024];
255 [ + + ]: 55470 : if (match < 0)
256 : 55470 : return;
257 [ + + ]: 70 : BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
258 : : fn->name, op, nameincert,
259 : : match ? "matches" : "does not match", name);
260 [ - + ]: 70 : if (is_exception(msg))
261 : : return;
262 : 0 : puts(msg);
263 : 0 : ++errors;
264 : : }
265 : :
266 : 430 : static void run_cert(X509 *crt, const char *nameincert,
267 : : const struct set_name_fn *fn)
268 : : {
269 : 430 : const char *const *pname = names;
270 [ + + ]: 18920 : while (*pname)
271 : : {
272 : 18490 : int samename = strcasecmp(nameincert, *pname) == 0;
273 : 18490 : size_t namelen = strlen(*pname);
274 : 18490 : char *name = malloc(namelen);
275 : : int match, ret;
276 : 18490 : memcpy(name, *pname, namelen);
277 : :
278 : 18490 : ret = X509_check_host(crt, name, namelen, 0, NULL);
279 : 18490 : match = -1;
280 [ - + ]: 18490 : if (ret < 0)
281 : : {
282 : 0 : fprintf(stderr, "internal error in X509_check_host");
283 : 0 : ++errors;
284 : : }
285 [ + + ]: 18490 : else if (fn->host)
286 : : {
287 [ + + ]: 9245 : if (ret == 1 && !samename)
288 : 40 : match = 1;
289 [ - + ]: 9245 : if (ret == 0 && samename)
290 : 0 : match = 0;
291 : : }
292 [ - + ]: 9245 : else if (ret == 1)
293 : 0 : match = 1;
294 : 18490 : check_message(fn, "host", nameincert, match, *pname);
295 : :
296 : 18490 : ret = X509_check_host(crt, name, namelen,
297 : : X509_CHECK_FLAG_NO_WILDCARDS, NULL);
298 : 18490 : match = -1;
299 [ - + ]: 18490 : if (ret < 0)
300 : : {
301 : 0 : fprintf(stderr, "internal error in X509_check_host");
302 : 0 : ++errors;
303 : : }
304 [ + + ]: 18490 : else if (fn->host)
305 : : {
306 [ + + ]: 9245 : if (ret == 1 && !samename)
307 : 10 : match = 1;
308 [ - + ]: 9245 : if (ret == 0 && samename)
309 : 0 : match = 0;
310 : : }
311 [ - + ]: 9245 : else if (ret == 1)
312 : 0 : match = 1;
313 : 18490 : check_message(fn, "host-no-wildcards",
314 : : nameincert, match, *pname);
315 : :
316 : 18490 : ret = X509_check_email(crt, name, namelen, 0);
317 : 18490 : match = -1;
318 [ + + ]: 18490 : if (fn->email)
319 : : {
320 [ - + ]: 9245 : if (ret && !samename)
321 : 0 : match = 1;
322 [ + + ][ + - ]: 9245 : if (!ret && samename && strchr(nameincert, '@') != NULL)
323 : 20 : match = 0;
324 : : }
325 [ - + ]: 9245 : else if (ret)
326 : 0 : match = 1;
327 : 18490 : check_message(fn, "email", nameincert, match, *pname);
328 : 18490 : ++pname;
329 : 18490 : free(name);
330 : : }
331 : 430 : }
332 : :
333 : : int
334 : 1 : main(void)
335 : : {
336 : 1 : const struct set_name_fn *pfn = name_fns;
337 [ + + ]: 11 : while (pfn->name) {
338 : : const char *const *pname = names;
339 [ + + ]: 440 : while (*pname)
340 : : {
341 : 430 : X509 *crt = make_cert();
342 [ - + ]: 430 : if (crt == NULL)
343 : : {
344 : 0 : fprintf(stderr, "make_cert failed\n");
345 : 0 : return 1;
346 : : }
347 [ - + ]: 430 : if (!pfn->fn(crt, *pname))
348 : : {
349 : 0 : fprintf(stderr, "X509 name setting failed\n");
350 : 0 : return 1;
351 : : }
352 : 430 : run_cert(crt, *pname, pfn);
353 : 430 : X509_free(crt);
354 : 430 : ++pname;
355 : : }
356 : 10 : ++pfn;
357 : : }
358 : 1 : return errors > 0 ? 1 : 0;
359 : : }
|