Skip to content

Commit 2e7e2bc

Browse files
authored
Fix CVE-2014-0139: Prevent wildcard certificates from matching IP addresses (#26)
1 parent 017765e commit 2e7e2bc

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

https.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "config.h"
99

10+
#include <arpa/inet.h>
1011
#include <sys/types.h>
1112
#include <sys/socket.h>
1213
#include <sys/time.h>
@@ -106,27 +107,47 @@ _SSL_check_server_cert(SSL *ssl, const char *hostname)
106107
{
107108
X509 *cert;
108109
X509_NAME *subject;
109-
const GENERAL_NAME *altname;
110110
STACK_OF(GENERAL_NAME) *altnames;
111111
ASN1_STRING *tmp;
112112
int i, n, match = -1;
113-
const char *p;
113+
struct in6_addr addr;
114+
int hostnametype = GEN_DNS;
115+
size_t addrsize = 0;
114116

115117
if (SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE ||
116118
(cert = SSL_get_peer_certificate(ssl)) == NULL) {
117119
return (1);
118120
}
121+
122+
/* Check if hostname is an IP address */
123+
if (inet_pton(AF_INET6, hostname, &addr) == 1) {
124+
hostnametype = GEN_IPADD;
125+
addrsize = sizeof(struct in6_addr);
126+
} else if (inet_pton(AF_INET, hostname, &addr) == 1) {
127+
hostnametype = GEN_IPADD;
128+
addrsize = sizeof(struct in_addr);
129+
}
130+
119131
/* Check subjectAltName */
120132
if ((altnames = X509_get_ext_d2i(cert, NID_subject_alt_name,
121133
NULL, NULL)) != NULL) {
122134
n = sk_GENERAL_NAME_num(altnames);
123135

124136
for (i = 0; i < n && match != 1; i++) {
125-
altname = sk_GENERAL_NAME_value(altnames, i);
126-
p = (char *)ASN1_STRING_get0_data(altname->d.ia5);
127-
if (altname->type == GEN_DNS) {
128-
match = (ASN1_STRING_length(altname->d.ia5) ==
129-
strlen(p) && match_pattern(hostname, p));
137+
const GENERAL_NAME *altname = sk_GENERAL_NAME_value(altnames, i);
138+
if (hostnametype == altname->type) {
139+
char *altptr = (char *)ASN1_STRING_get0_data(altname->d.ia5);
140+
size_t altsize = (size_t)ASN1_STRING_length(altname->d.ia5);
141+
142+
if (altname->type == GEN_DNS) {
143+
match = (altsize == strlen(altptr) && match_pattern(hostname, altptr));
144+
} else if (altname->type == GEN_IPADD) {
145+
if ((altsize == addrsize) && !memcmp(altptr, &addr, altsize)) {
146+
match = 1;
147+
} else {
148+
match = 0;
149+
}
150+
}
130151
}
131152
}
132153
GENERAL_NAMES_free(altnames);
@@ -142,9 +163,15 @@ _SSL_check_server_cert(SSL *ssl, const char *hostname)
142163
if ((tmp = X509_NAME_ENTRY_get_data(
143164
X509_NAME_get_entry(subject, i))) != NULL &&
144165
ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
145-
p = (char *)ASN1_STRING_get0_data(tmp);
146-
match = (ASN1_STRING_length(tmp) ==
147-
strlen(p) && match_pattern(hostname, p));
166+
const char *pattern = (char *)ASN1_STRING_get0_data(tmp);
167+
size_t patternsize = (size_t)ASN1_STRING_length(tmp);
168+
if (patternsize == strlen(pattern)) {
169+
if (!strchr(pattern, '*')) {
170+
match = strcasecmp(hostname, pattern) == 0;
171+
} else if (hostnametype == GEN_DNS) {
172+
match = match_pattern(hostname, pattern);
173+
}
174+
}
148175
}
149176
}
150177
}

0 commit comments

Comments
 (0)