Skip to content

Commit 25abc0c

Browse files
Merge pull request rabbitmq#1466 from rabbitmq/rabbitmq-server-story-153435857
Internal authN backend: make it impossible to successfully log in with a blank password (for 3.6.x)
2 parents 20945a9 + a85e840 commit 25abc0c

File tree

3 files changed

+84
-8
lines changed

3 files changed

+84
-8
lines changed

src/rabbit_auth_backend_internal.erl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ hashing_module_for_user(#internal_user{
9393
hashing_algorithm = ModOrUndefined}) ->
9494
rabbit_password:hashing_mod(ModOrUndefined).
9595

96+
-define(BLANK_PASSWORD_REJECTION_MESSAGE,
97+
"user '~s' attempted to log in with a blank password, which is prohibited by the internal authN backend. "
98+
"To use TLS/x509 certificate-based authentication, see the rabbitmq_auth_mechanism_ssl plugin and configure the client to use the EXTERNAL authentication mechanism. "
99+
"Alternatively change the password for the user to be non-blank.").
100+
96101
%% For cases when we do not have a set of credentials,
97102
%% namely when x509 (TLS) certificates are used. This should only be
98103
%% possible when the EXTERNAL authentication mechanism is used, see
@@ -103,6 +108,14 @@ user_login_authentication(Username, []) ->
103108
%% performs initial validation.
104109
user_login_authentication(Username, AuthProps) ->
105110
case lists:keyfind(password, 1, AuthProps) of
111+
%% Passwordless users are not supposed to be used with
112+
%% this backend (and PLAIN authentication mechanism in general).
113+
{password, <<"">>} ->
114+
{refused, ?BLANK_PASSWORD_REJECTION_MESSAGE,
115+
[Username]};
116+
{password, ""} ->
117+
{refused, ?BLANK_PASSWORD_REJECTION_MESSAGE,
118+
[Username]};
106119
{password, Cleartext} ->
107120
internal_check_user_login(
108121
Username,
@@ -111,6 +124,13 @@ user_login_authentication(Username, AuthProps) ->
111124
} = U) ->
112125
Hash =:= rabbit_password:salted_hash(
113126
hashing_module_for_user(U), Salt, Cleartext);
127+
%% rabbitmqctl clear_password will set password_hash to an empty
128+
%% binary.
129+
%%
130+
%% See the comment on passwordless users above.
131+
(#internal_user{
132+
password_hash = <<"">>}) ->
133+
false;
114134
(#internal_user{}) ->
115135
false
116136
end);

src/rabbit_auth_mechanism_plain.erl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@
2828
{requires, rabbit_registry},
2929
{enables, kernel_ready}]}).
3030

31-
%% SASL PLAIN, as used by the Qpid Java client and our clients. Also,
32-
%% apparently, by OpenAMQ.
33-
34-
%% TODO: reimplement this using the binary module? - that makes use of
35-
%% BIFs to do binary matching and will thus be much faster.
36-
3731
description() ->
3832
[{description, <<"SASL PLAIN authentication mechanism">>}].
3933

test/unit_inbroker_parallel_SUITE.erl

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
-include_lib("common_test/include/ct.hrl").
2020
-include_lib("kernel/include/file.hrl").
2121
-include_lib("amqp_client/include/amqp_client.hrl").
22+
-include_lib("eunit/include/eunit.hrl").
2223

2324
-compile(export_all).
2425

@@ -47,6 +48,10 @@ groups() ->
4748
password_hashing,
4849
change_password
4950
]},
51+
{auth_backend_internal, [parallel], [
52+
login_with_credentials_but_no_password,
53+
login_of_passwordless_user
54+
]},
5055
{policy_validation, [parallel, {repeat, 20}], [
5156
ha_policy_validation,
5257
policy_validation,
@@ -684,9 +689,12 @@ user_management1(_Config) ->
684689
%% user authentication
685690
ok = control_action(authenticate_user,
686691
["user_management-user", "user_management-newpassword"]),
687-
{refused, _User, _Format, _Params} =
692+
?assertMatch({refused, _User, _Format, _Params},
688693
control_action(authenticate_user,
689-
["user_management-user", "user_management-password"]),
694+
["user_management-user", "user_management-password"])),
695+
?assertMatch({refused, _User, _Format, _Params},
696+
control_action(authenticate_user,
697+
["user_management-user", ""])),
690698

691699
%% vhost creation
692700
ok = control_action(add_vhost,
@@ -748,6 +756,60 @@ user_management1(_Config) ->
748756

749757
passed.
750758

759+
760+
%% -------------------------------------------------------------------
761+
%% rabbit_auth_backend_internal
762+
%% -------------------------------------------------------------------
763+
764+
login_with_credentials_but_no_password(Config) ->
765+
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
766+
?MODULE, login_with_credentials_but_no_password1, [Config]).
767+
768+
login_with_credentials_but_no_password1(_Config) ->
769+
Username = "login_with_credentials_but_no_password-user",
770+
Password = "login_with_credentials_but_no_password-password",
771+
ok = control_action(add_user, [Username, Password]),
772+
773+
try
774+
rabbit_auth_backend_internal:user_login_authentication(Username,
775+
[{key, <<"value">>}]),
776+
?assert(false)
777+
catch exit:{unknown_auth_props, Username, [{key, <<"value">>}]} ->
778+
ok
779+
end,
780+
781+
ok = control_action(delete_user,
782+
[Username]),
783+
784+
passed.
785+
786+
%% passwordless users are not supposed to be used with
787+
%% this backend (and PLAIN authentication mechanism in general)
788+
login_of_passwordless_user(Config) ->
789+
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
790+
?MODULE, login_of_passwordless_user1, [Config]).
791+
792+
login_of_passwordless_user1(_Config) ->
793+
Username = "login_of_passwordless_user-user",
794+
Password = "",
795+
ok = control_action(add_user, [Username, Password]),
796+
797+
?assertMatch(
798+
{refused, _Message, [Username]},
799+
rabbit_auth_backend_internal:user_login_authentication(Username,
800+
[{password, <<"">>}])),
801+
802+
?assertMatch(
803+
{refused, _Format, [Username]},
804+
rabbit_auth_backend_internal:user_login_authentication(Username,
805+
[{password, ""}])),
806+
807+
ok = control_action(delete_user,
808+
[Username]),
809+
810+
passed.
811+
812+
751813
runtime_parameters(Config) ->
752814
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
753815
?MODULE, runtime_parameters1, [Config]).

0 commit comments

Comments
 (0)