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