24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-02 21:17:12 +02:00

Apply SASLprep before storing/converting passwords

Fixes #996 and #1295
This commit is contained in:
Evgeniy Khramtsov 2017-02-12 10:06:30 +03:00
parent 67c9de6461
commit fd885d0818
3 changed files with 84 additions and 32 deletions

View File

@ -143,9 +143,12 @@ check_password(User, AuthzId, Server, Password, Digest,
set_password(User, Server, Password) -> set_password(User, Server, Password) ->
LUser = jid:nodeprep(User), LUser = jid:nodeprep(User),
LServer = jid:nameprep(Server), LServer = jid:nameprep(Server),
LPassword = jid:resourceprep(Password),
US = {LUser, LServer}, US = {LUser, LServer},
if (LUser == error) or (LServer == error) -> if (LUser == error) or (LServer == error) ->
{error, invalid_jid}; {error, invalid_jid};
LPassword == error ->
{error, invalid_password};
true -> true ->
F = fun () -> F = fun () ->
Password2 = case is_scrammed() and is_binary(Password) Password2 = case is_scrammed() and is_binary(Password)
@ -167,9 +170,12 @@ try_register(User, Server, PasswordList) ->
iolist_to_binary(PasswordList); iolist_to_binary(PasswordList);
true -> PasswordList true -> PasswordList
end, end,
LPassword = jid:resourceprep(Password),
US = {LUser, LServer}, US = {LUser, LServer},
if (LUser == error) or (LServer == error) -> if (LUser == error) or (LServer == error) ->
{error, invalid_jid}; {error, invalid_jid};
LPassword == error ->
{error, invalid_password};
true -> true ->
F = fun () -> F = fun () ->
case mnesia:read({passwd, US}) of case mnesia:read({passwd, US}) of
@ -441,9 +447,21 @@ scram_passwords() ->
?INFO_MSG("Converting the stored passwords into " ?INFO_MSG("Converting the stored passwords into "
"SCRAM bits", "SCRAM bits",
[]), []),
Fun = fun (#passwd{password = Password} = P) -> Fun = fun (#passwd{us = {U, S}, password = Password} = P)
when is_binary(Password) ->
case jid:resourceprep(Password) of
error ->
?ERROR_MSG(
"SASLprep failed for "
"password of user ~s@~s",
[U, S]),
P;
_ ->
Scram = password_to_scram(Password), Scram = password_to_scram(Password),
P#passwd{password = Scram} P#passwd{password = Scram}
end;
(P) ->
P
end, end,
Fields = record_info(fields, passwd), Fields = record_info(fields, passwd),
mnesia:transform_table(passwd, Fun, Fields). mnesia:transform_table(passwd, Fun, Fields).
@ -465,13 +483,18 @@ password_to_scram(Password, IterationCount) ->
iterationcount = IterationCount}. iterationcount = IterationCount}.
is_password_scram_valid(Password, Scram) -> is_password_scram_valid(Password, Scram) ->
case jid:resourceprep(Password) of
error ->
false;
_ ->
IterationCount = Scram#scram.iterationcount, IterationCount = Scram#scram.iterationcount,
Salt = jlib:decode_base64(Scram#scram.salt), Salt = jlib:decode_base64(Scram#scram.salt),
SaltedPassword = scram:salted_password(Password, Salt, SaltedPassword = scram:salted_password(Password, Salt,
IterationCount), IterationCount),
StoredKey = StoredKey =
scram:stored_key(scram:client_key(SaltedPassword)), scram:stored_key(scram:client_key(SaltedPassword)),
jlib:decode_base64(Scram#scram.storedkey) == StoredKey. jlib:decode_base64(Scram#scram.storedkey) == StoredKey
end.
export(_Server) -> export(_Server) ->
[{passwd, [{passwd,

View File

@ -120,9 +120,12 @@ check_password(User, AuthzId, Server, Password, Digest,
set_password(User, Server, Password) -> set_password(User, Server, Password) ->
LUser = jid:nodeprep(User), LUser = jid:nodeprep(User),
LServer = jid:nameprep(Server), LServer = jid:nameprep(Server),
LPassword = jid:resourceprep(Password),
US = {LUser, LServer}, US = {LUser, LServer},
if (LUser == error) or (LServer == error) -> if (LUser == error) or (LServer == error) ->
{error, invalid_jid}; {error, invalid_jid};
LPassword == error ->
{error, invalid_password};
true -> true ->
Password2 = case is_scrammed() and is_binary(Password) Password2 = case is_scrammed() and is_binary(Password)
of of
@ -141,9 +144,12 @@ try_register(User, Server, PasswordList) ->
iolist_to_binary(PasswordList); iolist_to_binary(PasswordList);
true -> PasswordList true -> PasswordList
end, end,
LPassword = jid:resourceprep(Password),
US = {LUser, LServer}, US = {LUser, LServer},
if (LUser == error) or (LServer == error) -> if (LUser == error) or (LServer == error) ->
{error, invalid_jid}; {error, invalid_jid};
LPassword == error ->
{error, invalid_password};
true -> true ->
case ejabberd_riak:get(passwd, passwd_schema(), US) of case ejabberd_riak:get(passwd, passwd_schema(), US) of
{error, notfound} -> {error, notfound} ->
@ -284,13 +290,18 @@ password_to_scram(Password, IterationCount) ->
iterationcount = IterationCount}. iterationcount = IterationCount}.
is_password_scram_valid(Password, Scram) -> is_password_scram_valid(Password, Scram) ->
case jid:resourceprep(Password) of
error ->
false;
_ ->
IterationCount = Scram#scram.iterationcount, IterationCount = Scram#scram.iterationcount,
Salt = jlib:decode_base64(Scram#scram.salt), Salt = jlib:decode_base64(Scram#scram.salt),
SaltedPassword = scram:salted_password(Password, Salt, SaltedPassword = scram:salted_password(Password, Salt,
IterationCount), IterationCount),
StoredKey = StoredKey =
scram:stored_key(scram:client_key(SaltedPassword)), scram:stored_key(scram:client_key(SaltedPassword)),
jlib:decode_base64(Scram#scram.storedkey) == StoredKey. jlib:decode_base64(Scram#scram.storedkey) == StoredKey
end.
export(_Server) -> export(_Server) ->
[{passwd, [{passwd,

View File

@ -159,10 +159,13 @@ check_password(User, AuthzId, Server, Password, Digest,
set_password(User, Server, Password) -> set_password(User, Server, Password) ->
LServer = jid:nameprep(Server), LServer = jid:nameprep(Server),
LUser = jid:nodeprep(User), LUser = jid:nodeprep(User),
LPassword = jid:resourceprep(Password),
if (LUser == error) or (LServer == error) -> if (LUser == error) or (LServer == error) ->
{error, invalid_jid}; {error, invalid_jid};
(LUser == <<>>) or (LServer == <<>>) -> (LUser == <<>>) or (LServer == <<>>) ->
{error, invalid_jid}; {error, invalid_jid};
LPassword == error ->
{error, invalid_password};
true -> true ->
case is_scrammed() of case is_scrammed() of
true -> true ->
@ -193,10 +196,13 @@ set_password(User, Server, Password) ->
try_register(User, Server, Password) -> try_register(User, Server, Password) ->
LServer = jid:nameprep(Server), LServer = jid:nameprep(Server),
LUser = jid:nodeprep(User), LUser = jid:nodeprep(User),
LPassword = jid:resourceprep(Password),
if (LUser == error) or (LServer == error) -> if (LUser == error) or (LServer == error) ->
{error, invalid_jid}; {error, invalid_jid};
(LUser == <<>>) or (LServer == <<>>) -> (LUser == <<>>) or (LServer == <<>>) ->
{error, invalid_jid}; {error, invalid_jid};
LPassword == error ->
{error, invalid_password};
true -> true ->
case is_scrammed() of case is_scrammed() of
true -> true ->
@ -427,13 +433,18 @@ is_password_scram_valid_stored(Password, Scram, _, _) ->
is_password_scram_valid(Password, Scram). is_password_scram_valid(Password, Scram).
is_password_scram_valid(Password, Scram) -> is_password_scram_valid(Password, Scram) ->
case jid:resourceprep(Password) of
error ->
false;
_ ->
IterationCount = Scram#scram.iterationcount, IterationCount = Scram#scram.iterationcount,
Salt = jlib:decode_base64(Scram#scram.salt), Salt = jlib:decode_base64(Scram#scram.salt),
SaltedPassword = scram:salted_password(Password, Salt, SaltedPassword = scram:salted_password(Password, Salt,
IterationCount), IterationCount),
StoredKey = StoredKey =
scram:stored_key(scram:client_key(SaltedPassword)), scram:stored_key(scram:client_key(SaltedPassword)),
jlib:decode_base64(Scram#scram.storedkey) == StoredKey. jlib:decode_base64(Scram#scram.storedkey) == StoredKey
end.
-define(BATCH_SIZE, 1000). -define(BATCH_SIZE, 1000).
@ -466,14 +477,21 @@ convert_to_scram(Server) ->
{selected, Rs} -> {selected, Rs} ->
lists:foreach( lists:foreach(
fun({LUser, Password}) -> fun({LUser, Password}) ->
case jid:resourceprep(Password) of
error ->
?ERROR_MSG(
"SASLprep failed for "
"password of user ~s@~s",
[LUser, LServer]);
_ ->
Scram = password_to_scram(Password), Scram = password_to_scram(Password),
set_password_scram_t( set_password_scram_t(
LUser, LUser,
Scram#scram.storedkey, Scram#scram.storedkey,
Scram#scram.serverkey, Scram#scram.serverkey,
Scram#scram.salt, Scram#scram.salt,
Scram#scram.iterationcount Scram#scram.iterationcount)
) end
end, Rs), end, Rs),
continue; continue;
Err -> {bad_reply, Err} Err -> {bad_reply, Err}