Packages
amqp_client
3.8.21
4.2.1
4.2.0
retired
4.1.6
4.1.5
retired
4.1.5-rc.2
retired
4.1.5-rc.1
retired
4.1.5-1
4.0.3
4.0.3-rc.1
3.13.0-rc.2
3.13.0-rc.1
3.12.14
3.12.13
3.12.12
3.12.11
3.12.10
3.12.9
3.12.8
3.12.7
3.12.6
3.12.5
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.12.0-rc.4
3.11.28
3.11.27
3.11.26
3.11.25
3.11.24
3.11.23
3.11.22
3.11.21
3.11.20
3.11.19
3.11.18
3.11.17
3.11.13
3.11.12
3.11.11
3.11.10
3.11.9
3.11.8
3.11.7
3.11.6
3.11.5
3.11.4
3.11.3
3.11.2
3.11.1
3.11.0
3.11.0-rc.2
3.11.0-rc.1
3.11.0-1
3.10.20
3.10.19
3.10.18
3.10.17
3.10.16
3.10.15
3.10.14
3.10.13
3.10.12
3.10.11
3.10.10
3.10.9
3.10.8
3.10.7
3.10.6
3.10.5
3.10.4
3.10.3
3.10.2
3.10.1
3.10.0
3.10.0-rc.6
3.10.0-rc.5
3.9.29
3.9.28
3.9.27
3.9.26
3.9.25
3.9.24
3.9.23
3.9.22
3.9.21
3.9.20
3.9.19
3.9.18
3.9.17
3.9.16
3.9.15
3.9.11
3.9.8
3.9.5
3.9.4
3.9.1
3.8.35
3.8.34
3.8.33
3.8.32
3.8.31
3.8.30
3.8.25
3.8.21
3.8.19
3.8.14
3.8.11
3.8.10
3.8.10-rc.1
3.8.9
3.8.7
3.8.6
3.8.6-rc.2
3.8.6-rc.1
3.8.5
3.8.5-rc.2
3.8.5-rc.1
3.8.4
3.8.4-rc.3
3.8.4-rc.1
3.8.3
3.8.3-rc.2
3.8.3-rc.1
3.8.2
3.8.2-rc.1
3.8.1
3.8.1-rc.1
3.8.0
3.8.0-rc.3
3.8.0-rc.2
3.8.0-rc.1
3.7.28
3.7.27
3.7.27-rc.2
3.7.27-rc.1
3.7.26
3.7.25
3.7.25-rc.1
3.7.24
3.7.24-rc.2
3.7.24-rc.1
3.7.23
3.7.23-rc.1
3.7.22
3.7.22-rc.2
3.7.22-rc.1
3.7.21
3.7.20
3.7.20-rc.2
3.7.20-rc.1
3.7.19
3.7.18
3.7.18-rc.1
3.7.17
3.7.17-rc.3
3.7.17-rc.2
3.7.15
3.7.14
3.7.14-rc.2
3.7.14-rc.1
3.7.13
3.7.13-rc.2
3.7.13-rc.1
3.7.12
3.7.12-rc.2
3.7.12-rc.1
3.7.11
3.7.11-rc.2
3.7.11-rc.1
3.7.10-rc.4
3.7.10-rc.3
3.7.10-rc.2
3.7.10-rc.1
3.7.9
3.7.9-rc.3
3.7.9-rc.2
3.7.8
3.7.8-rc.4
3.7.8-rc.3
3.7.8-rc.2
3.7.8-rc.1
3.7.7
3.7.7-rc.2
3.7.7-rc.1
3.7.6
3.7.6-rc.2
3.7.6-rc.1
3.7.5
3.7.5-rc.1
3.7.4
3.7.4-rc.4
3.7.4-rc.3
3.7.4-rc.2
3.7.4-rc.1
3.7.3
3.7.3-rc.2
3.7.3-rc.1
3.7.2
3.7.1
3.7.0-rc.2
3.6.16
3.6.16-rc.1
3.6.15
3.6.15-rc.1
3.6.14
3.6.13
3.6.12
3.6.11
3.6.10
3.6.9
3.6.8
3.6.7
3.6.7-pre.1
3.5.6
3.5.0
3.4.0
3.3.5
3.0.2
0.0.0-rc.1
RabbitMQ AMQP Client
Current section
Files
Jump to
Current section
Files
src/amqp_ssl.erl
-module(amqp_ssl).
-include("amqp_client_internal.hrl").
-include_lib("public_key/include/public_key.hrl").
-export([maybe_enhance_ssl_options/1,
add_verify_fun_to_opts/2,
verify_fun/3]).
maybe_enhance_ssl_options(Params = #amqp_params_network{ssl_options = none}) ->
Params;
maybe_enhance_ssl_options(Params = #amqp_params_network{host = Host, ssl_options = Opts0}) ->
Opts1 = maybe_add_sni(Host, Opts0),
Opts2 = maybe_add_verify(Opts1),
Params#amqp_params_network{ssl_options = Opts2};
maybe_enhance_ssl_options(Params) ->
Params.
% https://github.com/erlang/otp/blob/master/lib/inets/src/http_client/httpc_handler.erl
maybe_add_sni(Host, Options) ->
maybe_add_sni_0(lists:keyfind(server_name_indication, 1, Options), Host, Options).
maybe_add_sni_0(false, Host, Options) ->
% NB: this is the case where the user did not specify
% server_name_indication at all. If Host is a DNS host name,
% we will specify server_name_indication via code
maybe_add_sni_1(inet_parse:domain(Host), Host, Options);
maybe_add_sni_0({server_name_indication, disable}, _Host, Options) ->
% NB: this is the case where the user explicitly disabled
% server_name_indication
Options;
maybe_add_sni_0({server_name_indication, SniHost}, _Host, Options) ->
% NB: this is the case where the user explicitly specified
% an SNI host name. We may need to add verify_fun for OTP 19
maybe_add_verify_fun(lists:keymember(verify_fun, 1, Options), SniHost, Options).
maybe_add_sni_1(false, _Host, Options) ->
% NB: host is not a DNS host name, so nothing to add
Options;
maybe_add_sni_1(true, Host, Options) ->
Opts1 = [{server_name_indication, Host} | Options],
maybe_add_verify_fun(lists:keymember(verify_fun, 1, Opts1), Host, Opts1).
maybe_add_verify_fun(true, _Host, Options) ->
% NB: verify_fun already present, don't add twice
Options;
maybe_add_verify_fun(false, Host, Options) ->
add_verify_fun_to_opts(lists:keyfind(verify, 1, Options), Host, Options).
maybe_add_verify(Options) ->
case lists:keymember(verify, 1, Options) of
true ->
% NB: user has explicitly set 'verify'
Options;
_ ->
?LOG_WARN("Connection (~p): Certificate chain verification is not enabled for this TLS connection. "
"Please see https://rabbitmq.com/ssl.html for more information.~n", [self()]),
Options
end.
add_verify_fun_to_opts(Host, Options) ->
add_verify_fun_to_opts(false, Host, Options).
add_verify_fun_to_opts({verify, verify_none}, _Host, Options) ->
% NB: this is the case where the user explicitly disabled
% certificate chain verification so there's not much sense
% in adding verify_fun
Options;
add_verify_fun_to_opts(_, _Host, Options) ->
% NB: this is the case where the user either did not
% set the verify option or set it to verify_peer
Options.
-type hostname() :: nonempty_string() | binary().
-spec verify_fun(Cert :: #'OTPCertificate'{},
Event :: {bad_cert, Reason :: atom() | {revoked, atom()}} |
{extension, #'Extension'{}}, InitialUserState :: term()) ->
{valid, UserState :: term()} | {valid_peer, UserState :: hostname()} |
{fail, Reason :: term()} | {unknown, UserState :: term()}.
verify_fun(_, {bad_cert, _} = Reason, _) ->
{fail, Reason};
verify_fun(_, {extension, _}, UserState) ->
{unknown, UserState};
verify_fun(_, valid, UserState) ->
{valid, UserState};
% NOTE:
% The user state is the hostname to verify as configured in
% amqp_ssl:make_verify_fun
verify_fun(Cert, valid_peer, Hostname) when Hostname =/= disable ->
verify_hostname(Cert, Hostname);
verify_fun(_, valid_peer, UserState) ->
{valid, UserState}.
% https://github.com/erlang/otp/blob/master/lib/ssl/src/ssl_certificate.erl
verify_hostname(Cert, Hostname) ->
case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}]) of
true ->
{valid, Hostname};
false ->
{fail, {bad_cert, hostname_check_failed}}
end.