Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proxy peer verification, use correct type #12931

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lib/urldata.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,17 @@ typedef enum {
/* SSL backend-specific data; declared differently by each SSL backend */
struct ssl_backend_data;

typedef enum {
CURL_SSL_PEER_DNS,
CURL_SSL_PEER_IPV4,
CURL_SSL_PEER_IPV6
} ssl_peer_type;

struct ssl_peer {
char *hostname; /* hostname for verification */
char *dispname; /* display version of hostname */
char *sni; /* SNI version of hostname or NULL if not usable */
BIT(is_ip_address); /* if hostname is an IPv4|6 address */
ssl_peer_type type; /* type of the peer information */
};

struct ssl_primary_config {
Expand Down
2 changes: 1 addition & 1 deletion lib/vtls/bearssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}

if(connssl->peer.is_ip_address) {
if(connssl->peer.type != CURL_SSL_PEER_DNS) {
if(verifyhost) {
failf(data, "BearSSL: "
"host verification of IP address is not supported");
Expand Down
42 changes: 26 additions & 16 deletions lib/vtls/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2134,7 +2134,7 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
struct ssl_peer *peer, X509 *server_cert)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
int target; /* target type, GEN_DNS or GEN_IPADD */
size_t addrlen = 0;
STACK_OF(GENERAL_NAME) *altnames;
#ifdef ENABLE_IPV6
Expand All @@ -2149,19 +2149,28 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,

(void)conn;
hostlen = strlen(peer->hostname);
if(peer->is_ip_address) {
switch(peer->type) {
case CURL_SSL_PEER_IPV4:
if(!Curl_inet_pton(AF_INET, peer->hostname, &addr))
return CURLE_PEER_FAILED_VERIFICATION;
target = GEN_IPADD;
addrlen = sizeof(struct in_addr);
break;
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip &&
Curl_inet_pton(AF_INET6, peer->hostname, &addr)) {
target = GEN_IPADD;
addrlen = sizeof(struct in6_addr);
}
else
case CURL_SSL_PEER_IPV6:
if(!Curl_inet_pton(AF_INET6, peer->hostname, &addr))
return CURLE_PEER_FAILED_VERIFICATION;
target = GEN_IPADD;
addrlen = sizeof(struct in6_addr);
break;
#endif
if(Curl_inet_pton(AF_INET, peer->hostname, &addr)) {
target = GEN_IPADD;
addrlen = sizeof(struct in_addr);
}
case CURL_SSL_PEER_DNS:
target = GEN_DNS;
break;
default:
DEBUGASSERT(0);
failf(data, "unexpected ssl peer type: %d", peer->type);
return CURLE_PEER_FAILED_VERIFICATION;
}

/* get a "list" of alternative names */
Expand Down Expand Up @@ -2242,11 +2251,12 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
/* an alternative name matched */
;
else if(dNSName || iPAddress) {
infof(data, " subjectAltName does not match %s %s",
peer->is_ip_address? "ip address" : "host name", peer->dispname);
const char *tname = (peer->type == CURL_SSL_PEER_DNS)? "host name" :
(peer->type == CURL_SSL_PEER_IPV4)?
"ipv4 address" : "ipv6 address";
infof(data, " subjectAltName does not match %s %s", tname, peer->dispname);
failf(data, "SSL: no alternative certificate subject name matches "
"target %s '%s'",
peer->is_ip_address? "ip address" : "host name", peer->dispname);
"target %s '%s'", tname, peer->dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
Expand Down
2 changes: 1 addition & 1 deletion lib/vtls/schannel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}

/* Warn if SNI is disabled due to use of an IP address */
if(connssl->peer.is_ip_address) {
if(connssl->peer.type != CURL_SSL_PEER_DNS) {
infof(data, "schannel: using IP address, SNI is not supported by OS.");
}

Expand Down
2 changes: 1 addition & 1 deletion lib/vtls/sectransp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2008,7 +2008,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
}

if(connssl->peer.is_ip_address) {
if(connssl->peer.type != CURL_SSL_PEER_DNS) {
infof(data, "WARNING: using IP address, SNI is being disabled by "
"the OS.");
}
Expand Down
28 changes: 19 additions & 9 deletions lib/vtls/vtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1516,7 +1516,7 @@ void Curl_ssl_peer_cleanup(struct ssl_peer *peer)
free(peer->sni);
free(peer->hostname);
peer->hostname = peer->sni = peer->dispname = NULL;
peer->is_ip_address = FALSE;
peer->type = CURL_SSL_PEER_DNS;
}

static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
Expand All @@ -1530,18 +1530,23 @@ static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
cf->connected = FALSE;
}

static int is_ip_address(const char *hostname)
static ssl_peer_type get_peer_type(const char *hostname)
{
if(hostname && hostname[0]) {
#ifdef ENABLE_IPV6
struct in6_addr addr;
struct in6_addr addr;
#else
struct in_addr addr;
struct in_addr addr;
#endif
return (hostname && hostname[0] && (Curl_inet_pton(AF_INET, hostname, &addr)
if(Curl_inet_pton(AF_INET, hostname, &addr))
return CURL_SSL_PEER_IPV4;
#ifdef ENABLE_IPV6
|| Curl_inet_pton(AF_INET6, hostname, &addr)
else if(Curl_inet_pton(AF_INET6, hostname, &addr)) {
return CURL_SSL_PEER_IPV6;
}
#endif
));
}
return CURL_SSL_PEER_DNS;
}

CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf)
Expand Down Expand Up @@ -1569,6 +1574,11 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf)
eport = cf->conn->remote_port;
}

/* There is some inherited weirdness here. We should never get
* a hostname that is the empty string (I believe). We check
* for it, but it should not be necessary. Let's catch those
* conditions, if they exist, in debug builds. */
DEBUGASSERT(!ehostname || ehostname[0]);
/* change if ehostname changed */
if(ehostname && (!peer->hostname
|| strcmp(ehostname, peer->hostname))) {
Expand All @@ -1589,8 +1599,8 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf)
}

peer->sni = NULL;
peer->is_ip_address = is_ip_address(peer->hostname)? TRUE : FALSE;
if(peer->hostname[0] && !peer->is_ip_address) {
peer->type = get_peer_type(peer->hostname);
if(peer->type == CURL_SSL_PEER_DNS && peer->hostname[0]) {
/* not an IP address, normalize according to RCC 6066 ch. 3,
* max len of SNI is 2^16-1, no trailing dot */
size_t len = strlen(peer->hostname);
Expand Down
Loading