You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

424 lines
12 KiB

  1. /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  2. * project 1999. */
  3. /* ====================================================================
  4. * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. *
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. *
  18. * 3. All advertising materials mentioning features or use of this
  19. * software must display the following acknowledgment:
  20. * "This product includes software developed by the OpenSSL Project
  21. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  22. *
  23. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  24. * endorse or promote products derived from this software without
  25. * prior written permission. For written permission, please contact
  26. * licensing@OpenSSL.org.
  27. *
  28. * 5. Products derived from this software may not be called "OpenSSL"
  29. * nor may "OpenSSL" appear in their names without prior written
  30. * permission of the OpenSSL Project.
  31. *
  32. * 6. Redistributions of any form whatsoever must retain the following
  33. * acknowledgment:
  34. * "This product includes software developed by the OpenSSL Project
  35. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  36. *
  37. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  38. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  39. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  40. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  41. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  42. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  43. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  44. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  45. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  46. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  47. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  48. * OF THE POSSIBILITY OF SUCH DAMAGE.
  49. * ====================================================================
  50. *
  51. * This product includes cryptographic software written by Eric Young
  52. * (eay@cryptsoft.com). This product includes software written by Tim
  53. * Hudson (tjh@cryptsoft.com). */
  54. #include <string.h>
  55. #include <openssl/crypto.h>
  56. #include <openssl/mem.h>
  57. #include <openssl/x509.h>
  58. #include <openssl/x509v3.h>
  59. static const char *const names[] =
  60. {
  61. "a", "b", ".", "*", "@",
  62. ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
  63. "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
  64. "*@example.com", "test@*.example.com", "example.com", "www.example.com",
  65. "test.www.example.com", "*.example.com", "*.www.example.com",
  66. "test.*.example.com", "www.*.com",
  67. ".www.example.com", "*www.example.com",
  68. "example.net", "xn--rger-koa.example.com",
  69. "a.example.com", "b.example.com",
  70. "postmaster@example.com", "Postmaster@example.com",
  71. "postmaster@EXAMPLE.COM",
  72. NULL
  73. };
  74. static const char *const exceptions[] =
  75. {
  76. "set CN: host: [*.example.com] matches [a.example.com]",
  77. "set CN: host: [*.example.com] matches [b.example.com]",
  78. "set CN: host: [*.example.com] matches [www.example.com]",
  79. "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
  80. "set CN: host: [*.www.example.com] matches [test.www.example.com]",
  81. "set CN: host: [*.www.example.com] matches [.www.example.com]",
  82. "set CN: host: [*www.example.com] matches [www.example.com]",
  83. "set CN: host: [test.www.example.com] matches [.www.example.com]",
  84. "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
  85. "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
  86. "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
  87. "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
  88. "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
  89. "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
  90. "set dnsName: host: [*.example.com] matches [www.example.com]",
  91. "set dnsName: host: [*.example.com] matches [a.example.com]",
  92. "set dnsName: host: [*.example.com] matches [b.example.com]",
  93. "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
  94. "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
  95. "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
  96. "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
  97. "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
  98. "set dnsName: host: [*www.example.com] matches [www.example.com]",
  99. "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
  100. "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
  101. "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
  102. "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
  103. "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
  104. NULL
  105. };
  106. static int is_exception(const char *msg)
  107. {
  108. const char *const *p;
  109. for (p = exceptions; *p; ++p)
  110. if (strcmp(msg, *p) == 0)
  111. return 1;
  112. return 0;
  113. }
  114. static int set_cn(X509 *crt, ...)
  115. {
  116. int ret = 0;
  117. X509_NAME *n = NULL;
  118. va_list ap;
  119. va_start(ap, crt);
  120. n = X509_NAME_new();
  121. if (n == NULL)
  122. goto out;
  123. while (1) {
  124. int nid;
  125. const char *name;
  126. nid = va_arg(ap, int);
  127. if (nid == 0)
  128. break;
  129. name = va_arg(ap, const char *);
  130. if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC,
  131. (unsigned char *)name,
  132. -1, -1, 1))
  133. goto out;
  134. }
  135. if (!X509_set_subject_name(crt, n))
  136. goto out;
  137. ret = 1;
  138. out:
  139. X509_NAME_free(n);
  140. va_end(ap);
  141. return ret;
  142. }
  143. /*
  144. int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
  145. X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
  146. int nid, int crit, ASN1_OCTET_STRING *data);
  147. int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
  148. */
  149. static int set_altname(X509 *crt, ...)
  150. {
  151. int ret = 0;
  152. GENERAL_NAMES *gens = NULL;
  153. GENERAL_NAME *gen = NULL;
  154. ASN1_IA5STRING *ia5 = NULL;
  155. va_list ap;
  156. va_start(ap, crt);
  157. gens = sk_GENERAL_NAME_new_null();
  158. if (gens == NULL)
  159. goto out;
  160. while (1) {
  161. int type;
  162. const char *name;
  163. type = va_arg(ap, int);
  164. if (type == 0)
  165. break;
  166. name = va_arg(ap, const char *);
  167. gen = GENERAL_NAME_new();
  168. if (gen == NULL)
  169. goto out;
  170. ia5 = ASN1_IA5STRING_new();
  171. if (ia5 == NULL)
  172. goto out;
  173. if (!ASN1_STRING_set(ia5, name, -1))
  174. goto out;
  175. switch (type)
  176. {
  177. case GEN_EMAIL:
  178. case GEN_DNS:
  179. GENERAL_NAME_set0_value(gen, type, ia5);
  180. ia5 = NULL;
  181. break;
  182. default:
  183. abort();
  184. }
  185. sk_GENERAL_NAME_push(gens, gen);
  186. gen = NULL;
  187. }
  188. if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
  189. goto out;
  190. ret = 1;
  191. out:
  192. ASN1_IA5STRING_free(ia5);
  193. GENERAL_NAME_free(gen);
  194. GENERAL_NAMES_free(gens);
  195. va_end(ap);
  196. return ret;
  197. }
  198. static int set_cn1(X509 *crt, const char *name)
  199. {
  200. return set_cn(crt, NID_commonName, name, 0);
  201. }
  202. static int set_cn_and_email(X509 *crt, const char *name)
  203. {
  204. return set_cn(crt, NID_commonName, name,
  205. NID_pkcs9_emailAddress, "dummy@example.com", 0);
  206. }
  207. static int set_cn2(X509 *crt, const char *name)
  208. {
  209. return set_cn(crt, NID_commonName, "dummy value",
  210. NID_commonName, name, 0);
  211. }
  212. static int set_cn3(X509 *crt, const char *name)
  213. {
  214. return set_cn(crt, NID_commonName, name,
  215. NID_commonName, "dummy value", 0);
  216. }
  217. static int set_email1(X509 *crt, const char *name)
  218. {
  219. return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
  220. }
  221. static int set_email2(X509 *crt, const char *name)
  222. {
  223. return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
  224. NID_pkcs9_emailAddress, name, 0);
  225. }
  226. static int set_email3(X509 *crt, const char *name)
  227. {
  228. return set_cn(crt, NID_pkcs9_emailAddress, name,
  229. NID_pkcs9_emailAddress, "dummy@example.com", 0);
  230. }
  231. static int set_email_and_cn(X509 *crt, const char *name)
  232. {
  233. return set_cn(crt, NID_pkcs9_emailAddress, name,
  234. NID_commonName, "www.example.org", 0);
  235. }
  236. static int set_altname_dns(X509 *crt, const char *name)
  237. {
  238. return set_altname(crt, GEN_DNS, name, 0);
  239. }
  240. static int set_altname_email(X509 *crt, const char *name)
  241. {
  242. return set_altname(crt, GEN_EMAIL, name, 0);
  243. }
  244. struct set_name_fn
  245. {
  246. int (*fn)(X509 *, const char *);
  247. const char *name;
  248. int host;
  249. int email;
  250. };
  251. static const struct set_name_fn name_fns[] =
  252. {
  253. {set_cn1, "set CN", 1, 0},
  254. {set_cn2, "set CN", 1, 0},
  255. {set_cn3, "set CN", 1, 0},
  256. {set_cn_and_email, "set CN", 1, 0},
  257. {set_email1, "set emailAddress", 0, 1},
  258. {set_email2, "set emailAddress", 0, 1},
  259. {set_email3, "set emailAddress", 0, 1},
  260. {set_email_and_cn, "set emailAddress", 0, 1},
  261. {set_altname_dns, "set dnsName", 1, 0},
  262. {set_altname_email, "set rfc822Name", 0, 1},
  263. {NULL, NULL, 0}
  264. };
  265. static X509 *make_cert(void)
  266. {
  267. X509 *ret = NULL;
  268. X509 *crt = NULL;
  269. X509_NAME *issuer = NULL;
  270. crt = X509_new();
  271. if (crt == NULL)
  272. goto out;
  273. if (!X509_set_version(crt, 3))
  274. goto out;
  275. ret = crt;
  276. crt = NULL;
  277. out:
  278. X509_NAME_free(issuer);
  279. return ret;
  280. }
  281. static int errors;
  282. static void check_message(const struct set_name_fn *fn, const char *op,
  283. const char *nameincert, int match, const char *name)
  284. {
  285. char msg[1024];
  286. if (match < 0)
  287. return;
  288. BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
  289. fn->name, op, nameincert,
  290. match ? "matches" : "does not match", name);
  291. if (is_exception(msg))
  292. return;
  293. puts(msg);
  294. ++errors;
  295. }
  296. static void run_cert(X509 *crt, const char *nameincert,
  297. const struct set_name_fn *fn)
  298. {
  299. const char *const *pname = names;
  300. while (*pname)
  301. {
  302. int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
  303. size_t namelen = strlen(*pname);
  304. char *name = malloc(namelen);
  305. int match, ret;
  306. memcpy(name, *pname, namelen);
  307. ret = X509_check_host(crt, (const unsigned char *)name,
  308. namelen, 0);
  309. match = -1;
  310. if (ret < 0)
  311. {
  312. fprintf(stderr, "internal error in X509_check_host");
  313. ++errors;
  314. }
  315. else if (fn->host)
  316. {
  317. if (ret == 1 && !samename)
  318. match = 1;
  319. if (ret == 0 && samename)
  320. match = 0;
  321. }
  322. else if (ret == 1)
  323. match = 1;
  324. check_message(fn, "host", nameincert, match, *pname);
  325. ret = X509_check_host(crt, (const unsigned char *)name,
  326. namelen, X509_CHECK_FLAG_NO_WILDCARDS);
  327. match = -1;
  328. if (ret < 0)
  329. {
  330. fprintf(stderr, "internal error in X509_check_host");
  331. ++errors;
  332. }
  333. else if (fn->host)
  334. {
  335. if (ret == 1 && !samename)
  336. match = 1;
  337. if (ret == 0 && samename)
  338. match = 0;
  339. }
  340. else if (ret == 1)
  341. match = 1;
  342. check_message(fn, "host-no-wildcards",
  343. nameincert, match, *pname);
  344. ret = X509_check_email(crt, (const unsigned char *)name,
  345. namelen, 0);
  346. match = -1;
  347. if (fn->email)
  348. {
  349. if (ret && !samename)
  350. match = 1;
  351. if (!ret && samename && strchr(nameincert, '@') != NULL)
  352. match = 0;
  353. }
  354. else if (ret)
  355. match = 1;
  356. check_message(fn, "email", nameincert, match, *pname);
  357. ++pname;
  358. free(name);
  359. }
  360. }
  361. int
  362. main(void)
  363. {
  364. CRYPTO_library_init();
  365. const struct set_name_fn *pfn = name_fns;
  366. while (pfn->name) {
  367. const char *const *pname = names;
  368. while (*pname)
  369. {
  370. X509 *crt = make_cert();
  371. if (crt == NULL)
  372. {
  373. fprintf(stderr, "make_cert failed\n");
  374. return 1;
  375. }
  376. if (!pfn->fn(crt, *pname))
  377. {
  378. fprintf(stderr, "X509 name setting failed\n");
  379. return 1;
  380. }
  381. run_cert(crt, *pname, pfn);
  382. X509_free(crt);
  383. ++pname;
  384. }
  385. ++pfn;
  386. }
  387. if (errors == 0) {
  388. printf("PASS\n");
  389. }
  390. return errors > 0 ? 1 : 0;
  391. }