/* 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 {
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");
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
(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 */
/* 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 {
}
/* 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.");
}
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.");
}
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)
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)
}
/* change if ehostname changed */
+ DEBUGASSERT(!ehostname || ehostname[0]);
if(ehostname && (!peer->hostname
|| strcmp(ehostname, peer->hostname))) {
Curl_ssl_peer_cleanup(peer);
}
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);