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