Skip to content

Commit

Permalink
Add tests for SNI and peer name checks
Browse files Browse the repository at this point in the history
- connect to DNS names with trailing dot
- connect to DNS names with double trailing dot
- rustls, always give `peer->hostname` and let it
  figure out SNI itself
  • Loading branch information
icing committed Apr 22, 2024
1 parent e9a3ae2 commit 8d8b99d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 7 deletions.
9 changes: 2 additions & 7 deletions lib/vtls/rustls.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,13 +479,8 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,

backend->config = rustls_client_config_builder_build(config_builder);
DEBUGASSERT(rconn == NULL);
{
/* rustls claims to manage ip address hostnames as well here. So,
* if we have an SNI, we use it, otherwise we pass the hostname */
char *server = connssl->peer.sni?
connssl->peer.sni : connssl->peer.hostname;
result = rustls_client_connection_new(backend->config, server, &rconn);
}
result = rustls_client_connection_new(backend->config,
connssl->peer.hostname, &rconn);
if(result != RUSTLS_RESULT_OK) {
rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
failf(data, "rustls_client_connection_new: %.*s", (int)errorlen, errorbuf);
Expand Down
40 changes: 40 additions & 0 deletions tests/http/test_17_ssl_use.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,44 @@ def test_17_02_sslinfo_reconnect(self, env: Env, httpd, nghttpx, tls_max, repeat
else:
assert djson['SSL_SESSION_RESUMED'] == exp_resumed, f'{i}: {djson}'

# use host name with trailing dot, verify handshake
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
def test_17_03_trailing_dot(self, env: Env, httpd, nghttpx, repeat, proto):
if env.curl_uses_lib('gnutls'):
pytest.skip("gnutls does not match hostnames with trailing dot")
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
curl = CurlClient(env=env)
domain = f'{env.domain1}.'
url = f'https://{env.authority_for(domain, proto)}/curltest/sslinfo'
r = curl.http_get(url=url, alpn_proto=proto)
assert r.exit_code == 0, f'{r}'
assert r.json, f'{r}'
if proto != 'h3': # we proxy h3
# the SNI the server received is without trailing dot
assert r.json['SSL_TLS_SNI'] == env.domain1, f'{r.json}'

# use host name with double trailing dot, verify handshake
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
def test_17_04_double_dot(self, env: Env, httpd, nghttpx, repeat, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
if proto == 'h3' and env.curl_uses_lib('wolfssl'):
pytest.skip("wolfSSL HTTP/3 peer verification does not properly check")
curl = CurlClient(env=env)
domain = f'{env.domain1}..'
url = f'https://{env.authority_for(domain, proto)}/curltest/sslinfo'
r = curl.http_get(url=url, alpn_proto=proto, extra_args=[
'-H', f'Host: {env.domain1}',
])
if r.exit_code == 0:
assert r.json, f'{r.stdout}'
# the SNI the server received is without trailing dot
if proto != 'h3': # we proxy h3
assert r.json['SSL_TLS_SNI'] == env.domain1, f'{r.json}'
assert False, f'should not have succeeded: {r.json}'
# 7 - rustls rejects a servername with .. during setup
# 35 - libressl rejects setting an SNI name with trailing dot
# 60 - peer name matching failed against certificate
assert r.exit_code in [7, 35, 60], f'{r}'

1 change: 1 addition & 0 deletions tests/http/testenv/mod_curltest/mod_curltest.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ static int curltest_sslinfo_handler(request_rec *r)
brigade_env_var(r, bb, "SSL_SESSION_RESUMED");
brigade_env_var(r, bb, "SSL_SRP_USER");
brigade_env_var(r, bb, "SSL_SRP_USERINFO");
brigade_env_var(r, bb, "SSL_TLS_SNI");
apr_brigade_puts(bb, NULL, NULL, "}\n");

/* flush response */
Expand Down

0 comments on commit 8d8b99d

Please sign in to comment.