Skip to content

Commit

Permalink
ssl: Handle ip-address as string correctly
Browse files Browse the repository at this point in the history
If the host was specified as string ip-address, server_name_indication
didn't work.

Convert "ip-address" to IP if needed, as was done
for upgraded sockets previously.

Also while at it cleanup handling when hostname is undefined.

Fixes erlang#7968
  • Loading branch information
dgud committed Jan 9, 2024
1 parent 7fc0898 commit 12fcb41
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 33 deletions.
34 changes: 10 additions & 24 deletions lib/ssl/src/ssl_certificate.erl
Original file line number Diff line number Diff line change
Expand Up @@ -553,33 +553,19 @@ other_issuer(#cert{otp=OtpCert}=Cert, CertDbHandle, CertDbRef) ->
end
end.

verify_hostname({fallback, Hostname}, Customize, Cert, UserState) when is_list(Hostname) ->
case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}], Customize) of
true ->
{valid, UserState};
false ->
case public_key:pkix_verify_hostname(Cert, [{ip, Hostname}], Customize) of
true ->
{valid, UserState};
false ->
{fail, {bad_cert, hostname_check_failed}}
end
end;

verify_hostname({fallback, Hostname}, Customize, Cert, UserState) ->
verify_hostname(Hostname, Customize, Cert, UserState) when is_tuple(Hostname) ->
case public_key:pkix_verify_hostname(Cert, [{ip, Hostname}], Customize) of
true ->
{valid, UserState};
false ->
{fail, {bad_cert, hostname_check_failed}}
true -> {valid, UserState};
false -> {fail, {bad_cert, hostname_check_failed}}
end;

verify_hostname(Hostname, Customize, Cert, UserState) ->
case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}], Customize) of
true ->
{valid, UserState};
false ->
{fail, {bad_cert, hostname_check_failed}}
HostId = case inet:parse_strict_address(Hostname) of
{ok, IP} -> {ip, IP};
_ -> {dns_id, Hostname}
end,
case public_key:pkix_verify_hostname(Cert, [HostId], Customize) of
true -> {valid, UserState};
false -> {fail, {bad_cert, hostname_check_failed}}
end.

verify_cert_extensions(Cert, #{cert_ext := CertExts} = UserState) ->
Expand Down
12 changes: 7 additions & 5 deletions lib/ssl/src/ssl_handshake.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3553,11 +3553,13 @@ sign_type(ecdsa) ->
server_name(_, _, server) ->
undefined; %% Not interesting to check your own name.
server_name(SSLOpts, Host, client) ->
case maps:get(server_name_indication, SSLOpts, undefined) of
undefined ->
{fallback, Host}; %% Fallback to Host argument to connect
SNI ->
SNI %% If Server Name Indication is available
SNI = case maps:get(server_name_indication, SSLOpts, undefined) of
undefined -> Host; %% Fallback to Host argument to connect
UserSNI -> UserSNI %% If Server Name Indication is available
end,
case is_atom(SNI) of
true -> atom_to_list(SNI);
false -> SNI
end.

client_ecc_extensions(SupportedECCs) ->
Expand Down
14 changes: 10 additions & 4 deletions lib/ssl/test/ssl_sni_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ dns_name(Config) ->
ip_fallback(Config) ->
Hostname = net_adm:localhost(),
{ok, #hostent{h_addr_list = [IP |_]}} = inet:gethostbyname(net_adm:localhost()),
IPStr = tuple_to_list(IP),
IPList = tuple_to_list(IP),
IPStr = lists:flatten(integer_to_list(hd(IPList)) ++ [io_lib:format(".~w", [I]) || I <- tl(IPList)]),
#{server_config := ServerOpts0,
client_config := ClientOpts0} =
public_key:pkix_test_data(#{server_chain =>
Expand All @@ -235,7 +236,7 @@ ip_fallback(Config) ->
peer => [{extensions, [#'Extension'{extnID =
?'id-ce-subjectAltName',
extnValue = [{dNSName, Hostname},
{iPAddress, IPStr}],
{iPAddress, IPList}],
critical = false}]},
{key, ssl_test_lib:hardcode_rsa_key(3)}]},
client_chain =>
Expand All @@ -246,11 +247,15 @@ ip_fallback(Config) ->
ServerConf = ssl_test_lib:sig_algs(rsa, Version) ++ ServerOpts0,
ClientConf = ssl_test_lib:sig_algs(rsa, Version) ++ ClientOpts0,
successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], Hostname, Config),
successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IP, Config).
successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IP, Config),
successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IPStr, Config),
successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], list_to_atom(Hostname), Config).

no_ip_fallback(Config) ->
Hostname = net_adm:localhost(),
{ok, #hostent{h_addr_list = [IP |_]}} = inet:gethostbyname(net_adm:localhost()),
IPList = tuple_to_list(IP),
IPStr = lists:flatten(integer_to_list(hd(IPList)) ++ [io_lib:format(".~w", [I]) || I <- tl(IPList)]),
#{server_config := ServerOpts0,
client_config := ClientOpts0} =
public_key:pkix_test_data(#{server_chain =>
Expand All @@ -270,7 +275,8 @@ no_ip_fallback(Config) ->
ServerConf = ssl_test_lib:sig_algs(rsa, Version) ++ ServerOpts0,
ClientConf = ssl_test_lib:sig_algs(rsa, Version) ++ ClientOpts0,
successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], Hostname, Config),
unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IP, Config).
unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IP, Config),
unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IPStr, Config).

dns_name_reuse(Config) ->
SNIHostname = "OTP.test.server",
Expand Down

0 comments on commit 12fcb41

Please sign in to comment.