1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2007-2021 VMware, Inc. or its affiliates. All rights reserved.
%%
-module(rabbit_ssl_options).
-export([fix/1]).
-define(BAD_SSL_PROTOCOL_VERSIONS, [
%% POODLE
sslv3
]).
-spec fix(rabbit_types:infos()) -> rabbit_types:infos().
fix(Config) ->
fix_verify_fun(fix_ssl_protocol_versions(Config)).
fix_verify_fun(SslOptsConfig) ->
%% Starting with ssl 4.0.1 in Erlang R14B, the verify_fun function
%% takes 3 arguments and returns a tuple.
case rabbit_misc:pget(verify_fun, SslOptsConfig) of
{Module, Function, InitialUserState} ->
Fun = make_verify_fun(Module, Function, InitialUserState),
rabbit_misc:pset(verify_fun, Fun, SslOptsConfig);
{Module, Function} when is_atom(Module) ->
Fun = make_verify_fun(Module, Function, none),
rabbit_misc:pset(verify_fun, Fun, SslOptsConfig);
{Verifyfun, _InitialUserState} when is_function(Verifyfun, 3) ->
SslOptsConfig;
undefined ->
SslOptsConfig
end.
make_verify_fun(Module, Function, InitialUserState) ->
try
%% Preload the module: it is required to use
%% erlang:function_exported/3.
Module:module_info()
catch
_:Exception ->
rabbit_log:error("TLS verify_fun: module ~s missing: ~p",
[Module, Exception]),
throw({error, {invalid_verify_fun, missing_module}})
end,
NewForm = erlang:function_exported(Module, Function, 3),
OldForm = erlang:function_exported(Module, Function, 1),
case {NewForm, OldForm} of
{true, _} ->
%% This verify_fun is supported by Erlang R14B+ (ssl
%% 4.0.1 and later).
Fun = fun(OtpCert, Event, UserState) ->
Module:Function(OtpCert, Event, UserState)
end,
{Fun, InitialUserState};
{_, true} ->
%% This verify_fun is supported by Erlang R14B+ for
%% undocumented backward compatibility.
%%
%% InitialUserState is ignored in this case.
fun(Args) ->
Module:Function(Args)
end;
_ ->
rabbit_log:error("TLS verify_fun: no ~s:~s/3 exported",
[Module, Function]),
throw({error, {invalid_verify_fun, function_not_exported}})
end.
fix_ssl_protocol_versions(Config) ->
case application:get_env(rabbit, ssl_allow_poodle_attack) of
{ok, true} ->
Config;
_ ->
Configured = case rabbit_misc:pget(versions, Config) of
undefined -> rabbit_misc:pget(available,
ssl:versions(),
[]);
Vs -> Vs
end,
rabbit_misc:pset(versions, Configured -- ?BAD_SSL_PROTOCOL_VERSIONS, Config)
end.
|