mirror of
https://github.com/moparisthebest/curl
synced 2024-11-14 21:45:13 -05:00
openssl: fix cert check with non-DNS name fields present
Regression introduced in 5f5b62635
(released in 7.48.0)
Reported-by: Fabian Ruff
Fixes #875
This commit is contained in:
parent
b1839f6ed8
commit
d4643d6e79
@ -1082,6 +1082,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
#endif
|
#endif
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
bool dNSName = FALSE; /* if a dNSName field exists in the cert */
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
if(conn->bits.ipv6_ip &&
|
if(conn->bits.ipv6_ip &&
|
||||||
@ -1102,16 +1103,23 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
if(altnames) {
|
if(altnames) {
|
||||||
int numalts;
|
int numalts;
|
||||||
int i;
|
int i;
|
||||||
|
bool dnsmatched = FALSE;
|
||||||
|
bool ipmatched = FALSE;
|
||||||
|
|
||||||
/* get amount of alternatives, RFC2459 claims there MUST be at least
|
/* get amount of alternatives, RFC2459 claims there MUST be at least
|
||||||
one, but we don't depend on it... */
|
one, but we don't depend on it... */
|
||||||
numalts = sk_GENERAL_NAME_num(altnames);
|
numalts = sk_GENERAL_NAME_num(altnames);
|
||||||
|
|
||||||
/* loop through all alternatives while none has matched */
|
/* loop through all alternatives - until a dnsmatch */
|
||||||
for(i=0; (i<numalts) && !matched; i++) {
|
for(i=0; (i < numalts) && !dnsmatched; i++) {
|
||||||
/* get a handle to alternative name number i */
|
/* get a handle to alternative name number i */
|
||||||
const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
|
const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
|
||||||
|
|
||||||
|
/* If a subjectAltName extension of type dNSName is present, that MUST
|
||||||
|
be used as the identity. / RFC2818 section 3.1 */
|
||||||
|
if(check->type == GEN_DNS)
|
||||||
|
dNSName = TRUE;
|
||||||
|
|
||||||
/* only check alternatives of the same type the target is */
|
/* only check alternatives of the same type the target is */
|
||||||
if(check->type == target) {
|
if(check->type == target) {
|
||||||
/* get data and length */
|
/* get data and length */
|
||||||
@ -1134,7 +1142,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
/* if this isn't true, there was an embedded zero in the name
|
/* if this isn't true, there was an embedded zero in the name
|
||||||
string and we cannot match it. */
|
string and we cannot match it. */
|
||||||
Curl_cert_hostcheck(altptr, conn->host.name)) {
|
Curl_cert_hostcheck(altptr, conn->host.name)) {
|
||||||
matched = TRUE;
|
dnsmatched = TRUE;
|
||||||
infof(data,
|
infof(data,
|
||||||
" subjectAltName: host \"%s\" matched cert's \"%s\"\n",
|
" subjectAltName: host \"%s\" matched cert's \"%s\"\n",
|
||||||
conn->host.dispname, altptr);
|
conn->host.dispname, altptr);
|
||||||
@ -1145,7 +1153,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
/* compare alternative IP address if the data chunk is the same size
|
/* compare alternative IP address if the data chunk is the same size
|
||||||
our server IP address is */
|
our server IP address is */
|
||||||
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) {
|
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) {
|
||||||
matched = TRUE;
|
ipmatched = TRUE;
|
||||||
infof(data,
|
infof(data,
|
||||||
" subjectAltName: host \"%s\" matched cert's IP address!\n",
|
" subjectAltName: host \"%s\" matched cert's IP address!\n",
|
||||||
conn->host.dispname);
|
conn->host.dispname);
|
||||||
@ -1155,14 +1163,19 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
GENERAL_NAMES_free(altnames);
|
GENERAL_NAMES_free(altnames);
|
||||||
|
|
||||||
|
if(dnsmatched || (!dNSName && ipmatched)) {
|
||||||
|
/* count as a match if the dnsname matched or if there was no dnsname
|
||||||
|
fields at all AND there was an IP field match */
|
||||||
|
matched = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(matched)
|
if(matched)
|
||||||
/* an alternative name matched */
|
/* an alternative name matched */
|
||||||
;
|
;
|
||||||
else if(altnames) {
|
else if(dNSName) {
|
||||||
/* an alternative name field existed, but didn't match and then we MUST
|
/* an dNSName field existed, but didn't match and then we MUST fail */
|
||||||
fail */
|
|
||||||
infof(data, " subjectAltName does not match %s\n", conn->host.dispname);
|
infof(data, " subjectAltName does not match %s\n", conn->host.dispname);
|
||||||
failf(data, "SSL: no alternative certificate subject name matches "
|
failf(data, "SSL: no alternative certificate subject name matches "
|
||||||
"target host name '%s'", conn->host.dispname);
|
"target host name '%s'", conn->host.dispname);
|
||||||
|
Loading…
Reference in New Issue
Block a user