1 #include <openssl/x509.h>
2 #include <openssl/x509v3.h>
6 static const char *const names
[] = {
7 "a", "b", ".", "*", "@",
8 ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
9 "-example.com", "example-.com",
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 "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com",
17 "*.good--example.com", "www.good--example.com",
18 "*.xn--bar.com", "xn--foo.xn--bar.com",
19 "a.example.com", "b.example.com",
20 "postmaster@example.com", "Postmaster@example.com",
21 "postmaster@EXAMPLE.COM",
25 static const char *const exceptions
[] = {
26 "set CN: host: [*.example.com] matches [a.example.com]",
27 "set CN: host: [*.example.com] matches [b.example.com]",
28 "set CN: host: [*.example.com] matches [www.example.com]",
29 "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
30 "set CN: host: [*.www.example.com] matches [test.www.example.com]",
31 "set CN: host: [*.www.example.com] matches [.www.example.com]",
32 "set CN: host: [*www.example.com] matches [www.example.com]",
33 "set CN: host: [test.www.example.com] matches [.www.example.com]",
34 "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
35 "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
36 "set CN: host: [*.good--example.com] matches [www.good--example.com]",
37 "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
38 "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
39 "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
40 "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
41 "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
42 "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
43 "set dnsName: host: [*.example.com] matches [www.example.com]",
44 "set dnsName: host: [*.example.com] matches [a.example.com]",
45 "set dnsName: host: [*.example.com] matches [b.example.com]",
46 "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
47 "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
48 "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
49 "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
50 "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
51 "set dnsName: host: [*www.example.com] matches [www.example.com]",
52 "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
53 "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
54 "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
55 "set dnsName: host: [*.good--example.com] matches [www.good--example.com]",
56 "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
57 "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
58 "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
59 "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
63 static int is_exception(const char *msg
)
66 for (p
= exceptions
; *p
; ++p
)
67 if (strcmp(msg
, *p
) == 0)
72 static int set_cn(X509
*crt
, ...)
84 nid
= va_arg(ap
, int);
87 name
= va_arg(ap
, const char *);
88 if (!X509_NAME_add_entry_by_NID(n
, nid
, MBSTRING_ASC
,
89 (unsigned char *)name
, -1, -1, 1))
92 if (!X509_set_subject_name(crt
, n
))
102 int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
103 X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
104 int nid, int crit, ASN1_OCTET_STRING *data);
105 int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
108 static int set_altname(X509
*crt
, ...)
111 GENERAL_NAMES
*gens
= NULL
;
112 GENERAL_NAME
*gen
= NULL
;
113 ASN1_IA5STRING
*ia5
= NULL
;
116 gens
= sk_GENERAL_NAME_new_null();
122 type
= va_arg(ap
, int);
125 name
= va_arg(ap
, const char *);
127 gen
= GENERAL_NAME_new();
130 ia5
= ASN1_IA5STRING_new();
133 if (!ASN1_STRING_set(ia5
, name
, -1))
138 GENERAL_NAME_set0_value(gen
, type
, ia5
);
144 sk_GENERAL_NAME_push(gens
, gen
);
147 if (!X509_add1_ext_i2d(crt
, NID_subject_alt_name
, gens
, 0, 0))
151 ASN1_IA5STRING_free(ia5
);
152 GENERAL_NAME_free(gen
);
153 GENERAL_NAMES_free(gens
);
158 static int set_cn1(X509
*crt
, const char *name
)
160 return set_cn(crt
, NID_commonName
, name
, 0);
163 static int set_cn_and_email(X509
*crt
, const char *name
)
165 return set_cn(crt
, NID_commonName
, name
,
166 NID_pkcs9_emailAddress
, "dummy@example.com", 0);
169 static int set_cn2(X509
*crt
, const char *name
)
171 return set_cn(crt
, NID_commonName
, "dummy value",
172 NID_commonName
, name
, 0);
175 static int set_cn3(X509
*crt
, const char *name
)
177 return set_cn(crt
, NID_commonName
, name
,
178 NID_commonName
, "dummy value", 0);
181 static int set_email1(X509
*crt
, const char *name
)
183 return set_cn(crt
, NID_pkcs9_emailAddress
, name
, 0);
186 static int set_email2(X509
*crt
, const char *name
)
188 return set_cn(crt
, NID_pkcs9_emailAddress
, "dummy@example.com",
189 NID_pkcs9_emailAddress
, name
, 0);
192 static int set_email3(X509
*crt
, const char *name
)
194 return set_cn(crt
, NID_pkcs9_emailAddress
, name
,
195 NID_pkcs9_emailAddress
, "dummy@example.com", 0);
198 static int set_email_and_cn(X509
*crt
, const char *name
)
200 return set_cn(crt
, NID_pkcs9_emailAddress
, name
,
201 NID_commonName
, "www.example.org", 0);
204 static int set_altname_dns(X509
*crt
, const char *name
)
206 return set_altname(crt
, GEN_DNS
, name
, 0);
209 static int set_altname_email(X509
*crt
, const char *name
)
211 return set_altname(crt
, GEN_EMAIL
, name
, 0);
215 int (*fn
) (X509
*, const char *);
221 static const struct set_name_fn name_fns
[] = {
222 {set_cn1
, "set CN", 1, 0},
223 {set_cn2
, "set CN", 1, 0},
224 {set_cn3
, "set CN", 1, 0},
225 {set_cn_and_email
, "set CN", 1, 0},
226 {set_email1
, "set emailAddress", 0, 1},
227 {set_email2
, "set emailAddress", 0, 1},
228 {set_email3
, "set emailAddress", 0, 1},
229 {set_email_and_cn
, "set emailAddress", 0, 1},
230 {set_altname_dns
, "set dnsName", 1, 0},
231 {set_altname_email
, "set rfc822Name", 0, 1},
235 static X509
*make_cert()
239 X509_NAME
*issuer
= NULL
;
243 if (!X509_set_version(crt
, 3))
248 X509_NAME_free(issuer
);
254 static void check_message(const struct set_name_fn
*fn
, const char *op
,
255 const char *nameincert
, int match
, const char *name
)
260 BIO_snprintf(msg
, sizeof(msg
), "%s: %s: [%s] %s [%s]",
261 fn
->name
, op
, nameincert
,
262 match
? "matches" : "does not match", name
);
263 if (is_exception(msg
))
269 static void run_cert(X509
*crt
, const char *nameincert
,
270 const struct set_name_fn
*fn
)
272 const char *const *pname
= names
;
274 int samename
= strcasecmp(nameincert
, *pname
) == 0;
275 size_t namelen
= strlen(*pname
);
276 char *name
= malloc(namelen
);
278 memcpy(name
, *pname
, namelen
);
280 ret
= X509_check_host(crt
, name
, namelen
, 0, NULL
);
283 fprintf(stderr
, "internal error in X509_check_host");
285 } else if (fn
->host
) {
286 if (ret
== 1 && !samename
)
288 if (ret
== 0 && samename
)
292 check_message(fn
, "host", nameincert
, match
, *pname
);
294 ret
= X509_check_host(crt
, name
, namelen
,
295 X509_CHECK_FLAG_NO_WILDCARDS
, NULL
);
298 fprintf(stderr
, "internal error in X509_check_host");
300 } else if (fn
->host
) {
301 if (ret
== 1 && !samename
)
303 if (ret
== 0 && samename
)
307 check_message(fn
, "host-no-wildcards", nameincert
, match
, *pname
);
309 ret
= X509_check_email(crt
, name
, namelen
, 0);
312 if (ret
&& !samename
)
314 if (!ret
&& samename
&& strchr(nameincert
, '@') != NULL
)
318 check_message(fn
, "email", nameincert
, match
, *pname
);
326 const struct set_name_fn
*pfn
= name_fns
;
328 const char *const *pname
= names
;
330 X509
*crt
= make_cert();
332 fprintf(stderr
, "make_cert failed\n");
335 if (!pfn
->fn(crt
, *pname
)) {
336 fprintf(stderr
, "X509 name setting failed\n");
339 run_cert(crt
, *pname
, pfn
);
345 return errors
> 0 ? 1 : 0;