| 238 | } |
| 239 | |
| 240 | static int verify_hostname(X509 *cert, const char *hostname) |
| 241 | { |
| 242 | #if (OPENSSL_VERSION_NUMBER >= 0x40000000L) |
| 243 | const X509_NAME *subj; |
| 244 | #else |
| 245 | X509_NAME *subj; |
| 246 | #endif |
| 247 | const X509_NAME_ENTRY *cname_entry; |
| 248 | const ASN1_STRING *cname; |
| 249 | int i, found; |
| 250 | STACK_OF(GENERAL_NAME) *subj_alt_names; |
| 251 | |
| 252 | /* try the DNS subjectAltNames */ |
| 253 | found = 0; |
| 254 | if ((subj_alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL))) { |
| 255 | int num_subj_alt_names = sk_GENERAL_NAME_num(subj_alt_names); |
| 256 | for (i = 0; !found && i < num_subj_alt_names; i++) { |
| 257 | int ntype; |
| 258 | GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i); |
| 259 | ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype); |
| 260 | |
| 261 | if (ntype == GEN_DNS && host_matches(hostname, subj_alt_str)) |
| 262 | found = 1; |
| 263 | } |
| 264 | sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free); |
| 265 | } |
| 266 | if (found) |
| 267 | return 0; |
| 268 | |
| 269 | /* try the common name */ |
| 270 | if (!(subj = X509_get_subject_name(cert))) |
| 271 | return error("cannot get certificate subject"); |
| 272 | if ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1)) < 0 || |
| 273 | (cname_entry = X509_NAME_get_entry(subj, i)) == NULL || |
| 274 | (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL) |
| 275 | return error("cannot get certificate common name"); |
| 276 | if (host_matches(hostname, cname)) |
| 277 | return 0; |
| 278 | return error("certificate owner '%s' does not match hostname '%s'", |
| 279 | ASN1_STRING_get0_data(cname), hostname); |
| 280 | } |
| 281 | |
| 282 | static int ssl_socket_connect(struct imap_socket *sock, |
| 283 | const struct imap_server_conf *cfg, |
no test coverage detected