#elif defined(USE_WOLFSSL)
(void)data;
if(conn_config->verifyhost) {
- char *snihost = peer->sni ? peer->sni : peer->hostname;
WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl);
- if(wolfSSL_X509_check_host(cert, snihost, strlen(snihost), 0, NULL)
- == WOLFSSL_FAILURE) {
+ if(!cert)
+ result = CURLE_OUT_OF_MEMORY;
+ else if(peer->sni &&
+ (wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, NULL)
+ == WOLFSSL_FAILURE))
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ else if(!peer->sni &&
+ (wolfSSL_X509_check_ip_asc(cert, peer->hostname, 0)
+ == WOLFSSL_FAILURE))
result = CURLE_PEER_FAILED_VERIFICATION;
- }
wolfSSL_X509_free(cert);
}
if(!result)
}
#endif
- /* Enable RFC2818 checks */
- if(conn_config->verifyhost) {
- char *snihost = connssl->peer.sni ?
- connssl->peer.sni : connssl->peer.hostname;
- if(wolfSSL_check_domain_name(wssl->ssl, snihost) !=
+ /* Enable RFC2818 checks on domain names. This cannot check
+ * IP addresses which we need to do extra after the handshake. */
+ if(conn_config->verifyhost && connssl->peer.sni) {
+ if(wolfSSL_check_domain_name(wssl->ssl, connssl->peer.sni) !=
WOLFSSL_SUCCESS) {
return CURLE_SSL_CONNECT_ERROR;
}
detail = wolfSSL_get_error(wssl->ssl, ret);
CURL_TRC_CF(data, cf, "wolfSSL_connect() -> %d, detail=%d", ret, detail);
+ /* On a successful handshake with an IP address, do an extra check
+ * on the peer certificate */
+ if(ret == WOLFSSL_SUCCESS &&
+ conn_config->verifyhost &&
+ !connssl->peer.sni) {
+ /* we have an IP address as host name. */
+ WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(wssl->ssl);
+ if(!cert) {
+ failf(data, "unable to get peer certificate");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ ret = wolfSSL_X509_check_ip_asc(cert, connssl->peer.hostname, 0);
+ CURL_TRC_CF(data, cf, "check peer certificate for IP match on %s -> %d",
+ connssl->peer.hostname, ret);
+ if(ret != WOLFSSL_SUCCESS)
+ detail = DOMAIN_NAME_MISMATCH;
+ wolfSSL_X509_free(cert);
+ }
+
if(ret == WOLFSSL_SUCCESS) {
return CURLE_OK;
}
pytest.skip("h3 not supported")
if proto != 'h3' and sys.platform.startswith('darwin') and env.ci_run:
pytest.skip('failing on macOS CI runners')
+ if proto == 'h3' and sys.platform.startswith('darwin') and env.curl_uses_lib('wolfssl'):
+ pytest.skip('h3 wolfssl early data failing on macOS')
if proto == 'h3' and sys.platform.startswith('darwin') and env.curl_uses_lib('gnutls'):
pytest.skip('h3 gnutls early data failing on macOS')
count = 2
pytest.skip("h3 not supported")
if proto != 'h3' and sys.platform.startswith('darwin') and env.ci_run:
pytest.skip('failing on macOS CI runners')
+ if proto == 'h3' and sys.platform.startswith('darwin') and env.curl_uses_lib('wolfssl'):
+ pytest.skip('h3 wolfssl early data failing on macOS')
if proto == 'h3' and sys.platform.startswith('darwin') and env.curl_uses_lib('gnutls'):
pytest.skip('h3 gnutls early data failing on macOS')
count = 2
r = curl.http_get(url=url, alpn_proto=proto)
assert r.exit_code == 60, f'{r}'
+ # use IP address that is in cert as DNS name (not really legal)
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_17_05_very_bad_ip_addr(self, env: Env, proto,
+ httpd, configures_httpd,
+ nghttpx, configures_nghttpx):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if env.curl_uses_lib('mbedtls'):
+ pytest.skip("mbedtls falsely verifies a DNS: altname as IP address")
+ if env.curl_uses_lib('wolfssl'):
+ pytest.skip("wolfSSL falsely verifies a DNS: altname as IP address")
+ httpd.set_domain1_cred_name('domain1-very-bad')
+ httpd.reload_if_config_changed()
+ if proto == 'h3':
+ nghttpx.set_cred_name('domain1-very-bad')
+ nghttpx.reload_if_config_changed()
+ curl = CurlClient(env=env)
+ url = f'https://127.0.0.1:{env.port_for(proto)}/curltest/sslinfo'
+ r = curl.http_get(url=url, alpn_proto=proto)
+ assert r.exit_code == 60, f'{r}'
+
# use localhost for connect
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
def test_17_06_localhost(self, env: Env, proto, httpd, nghttpx):
def _add_leaf_usages(csr: Any, domains: List[str], issuer: Credentials) -> Any:
names = []
for name in domains:
- try:
- names.append(x509.IPAddress(ipaddress.ip_address(name)))
- # TODO: specify specific exceptions here
- except: # noqa: E722
- names.append(x509.DNSName(name))
+ m = re.match(r'dns:(.+)', name)
+ if m:
+ names.append(x509.DNSName(m.group(1)))
+ else:
+ try:
+ names.append(x509.IPAddress(ipaddress.ip_address(name)))
+ # TODO: specify specific exceptions here
+ except: # noqa: E722
+ names.append(x509.DNSName(name))
return csr.add_extension(
x509.BasicConstraints(ca=False, path_length=None),
self.cert_specs = [
CertificateSpec(domains=[self.domain1, self.domain1brotli, 'localhost', '127.0.0.1'], key_type='rsa2048'),
CertificateSpec(name='domain1-no-ip', domains=[self.domain1, self.domain1brotli], key_type='rsa2048'),
+ CertificateSpec(name='domain1-very-bad', domains=[self.domain1, 'dns:127.0.0.1'], key_type='rsa2048'),
CertificateSpec(domains=[self.domain2], key_type='rsa2048'),
CertificateSpec(domains=[self.ftp_domain], key_type='rsa2048'),
CertificateSpec(domains=[self.proxy_domain, '127.0.0.1'], key_type='rsa2048'),