1 /* $OpenBSD: verifytest.c,v 1.5 2015/09/11 13:10:42 beck Exp $ */ 2 /* 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <err.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 22 #include <openssl/x509v3.h> 23 #include <tls.h> 24 25 extern int tls_check_name(struct tls *ctx, X509 *cert, const char *name); 26 27 struct verify_test { 28 const char common_name[128]; 29 const char alt_name[128]; 30 int alt_name_len; 31 int alt_name_type; 32 const char name[128]; 33 int want; 34 }; 35 36 struct verify_test verify_tests[] = { 37 { 38 .common_name = "www.openbsd.org", 39 .name = "www.openbsd.org", 40 .want = 0, 41 }, 42 { 43 .common_name = "www.openbsd.org", 44 .name = "", 45 .want = -1, 46 }, 47 { 48 .common_name = "*.openbsd.org", 49 .name = "www.openbsd.org", 50 .want = 0, 51 }, 52 { 53 .common_name = "www.openbsdfoundation.org", 54 .name = "www.openbsd.org", 55 .want = -1, 56 }, 57 { 58 .common_name = "w*.openbsd.org", 59 .name = "www.openbsd.org", 60 .want = -1, 61 }, 62 { 63 .common_name = "www.*.org", 64 .name = "www.openbsd.org", 65 .want = -1, 66 }, 67 { 68 .common_name = "www.openbsd.*", 69 .name = "www.openbsd.org", 70 .want = -1, 71 }, 72 { 73 .common_name = "*", 74 .name = "www.openbsd.org", 75 .want = -1, 76 }, 77 { 78 .common_name = "*.org", 79 .name = "www.openbsd.org", 80 .want = -1, 81 }, 82 { 83 .common_name = "*.org", 84 .name = "openbsd.org", 85 .want = -1, 86 }, 87 { 88 .common_name = "1.2.3.4", 89 .name = "1.2.3.4", 90 .want = 0, 91 }, 92 { 93 .common_name = "*.2.3.4", 94 .name = "1.2.3.4", 95 .want = -1, 96 }, 97 { 98 .common_name = "cafe::beef", 99 .name = "cafe::beef", 100 .want = 0, 101 }, 102 { 103 .common_name = "www.openbsd.org", 104 .alt_name = "ftp.openbsd.org", 105 .alt_name_len = -1, 106 .alt_name_type = GEN_DNS, 107 .name = "ftp.openbsd.org", 108 .want = 0, 109 }, 110 { 111 .common_name = "www.openbsdfoundation.org", 112 .alt_name = "*.openbsd.org", 113 .alt_name_len = -1, 114 .alt_name_type = GEN_DNS, 115 .name = "www.openbsd.org", 116 .want = 0, 117 }, 118 { 119 .common_name = "www.openbsdfoundation.org", 120 .alt_name = "*.org", 121 .alt_name_len = -1, 122 .alt_name_type = GEN_DNS, 123 .name = "www.openbsd.org", 124 .want = -1, 125 }, 126 { 127 .common_name = "www.openbsd.org", 128 .alt_name = "1.2.3.4", 129 .alt_name_len = -1, 130 .alt_name_type = GEN_DNS, 131 .name = "1.2.3.4", 132 .want = -1, 133 }, 134 { 135 .common_name = "www.openbsd.org", 136 .alt_name = {0x1, 0x2, 0x3, 0x4}, 137 .alt_name_len = 4, 138 .alt_name_type = GEN_IPADD, 139 .name = "1.2.3.4", 140 .want = 0, 141 }, 142 { 143 .common_name = "www.openbsd.org", 144 .alt_name = { 145 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xef, 147 }, 148 .alt_name_len = 16, 149 .alt_name_type = GEN_IPADD, 150 .name = "cafe::beef", 151 .want = 0, 152 }, 153 { 154 .common_name = "*.openbsd.org", 155 .name = ".openbsd.org", 156 .want = -1, 157 }, 158 }; 159 160 #define N_VERIFY_TESTS \ 161 (sizeof(verify_tests) / sizeof(*verify_tests)) 162 163 static int 164 do_verify_test(int test_no, struct verify_test *vt) 165 { 166 STACK_OF(GENERAL_NAME) *alt_name_stack = NULL; 167 ASN1_STRING *alt_name_str; 168 GENERAL_NAME *alt_name; 169 X509_NAME *name; 170 X509 *cert; 171 struct tls *tls; 172 173 /* Build certificate structure. */ 174 if ((cert = X509_new()) == NULL) 175 errx(1, "failed to malloc X509"); 176 if ((name = X509_NAME_new()) == NULL) 177 errx(1, "failed to malloc X509_NAME"); 178 if (X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC, 179 (unsigned char *)vt->common_name, -1, -1, 0) == 0) 180 errx(1, "failed to add name entry"); 181 if (X509_set_subject_name(cert, name) == 0) 182 errx(1, "failed to set subject name"); 183 X509_NAME_free(name); 184 if ((tls = tls_client()) == NULL) 185 errx(1, "failed to malloc tls_client"); 186 187 if (vt->alt_name_type != 0) { 188 if ((alt_name_stack = sk_GENERAL_NAME_new_null()) == NULL) 189 errx(1, "failed to malloc sk_GENERAL_NAME"); 190 if ((alt_name = GENERAL_NAME_new()) == NULL) 191 errx(1, "failed to malloc GENERAL_NAME"); 192 alt_name->type = vt->alt_name_type; 193 194 if ((alt_name_str = ASN1_STRING_new()) == NULL) 195 errx(1, "failed to malloc alt name"); 196 if (ASN1_STRING_set(alt_name_str, vt->alt_name, 197 vt->alt_name_len) == 0) 198 errx(1, "failed to set alt name"); 199 200 switch (alt_name->type) { 201 case GEN_DNS: 202 alt_name->d.dNSName = alt_name_str; 203 break; 204 205 case GEN_IPADD: 206 alt_name->d.iPAddress = alt_name_str; 207 break; 208 209 default: 210 errx(1, "unknown alt name type (%i)", alt_name->type); 211 } 212 213 if (sk_GENERAL_NAME_push(alt_name_stack, alt_name) == 0) 214 errx(1, "failed to push alt_name"); 215 if (X509_add1_ext_i2d(cert, NID_subject_alt_name, 216 alt_name_stack, 0, 0) == 0) 217 errx(1, "failed to set subject alt name"); 218 sk_GENERAL_NAME_pop_free(alt_name_stack, GENERAL_NAME_free); 219 } 220 221 if (tls_check_name(tls, cert, vt->name) != vt->want) { 222 fprintf(stderr, "FAIL: test %i failed with common name " 223 "'%s', alt name '%s' and name '%s'\n", test_no, 224 vt->common_name, vt->alt_name, vt->name); 225 return (1); 226 } 227 228 X509_free(cert); 229 230 return (0); 231 } 232 233 int 234 main(int argc, char **argv) 235 { 236 int failed = 0; 237 size_t i; 238 239 for (i = 0; i < N_VERIFY_TESTS; i++) 240 failed += do_verify_test(i, &verify_tests[i]); 241 242 return (failed); 243 } 244