Skip to content

Commit 8929be6

Browse files
committed
Support for get_password returning multiple passwords
1 parent be24923 commit 8929be6

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

src/xmpp_sasl_digest.erl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
-export([parse/1]).
2626

2727
-type get_password_fun() :: fun((binary()) -> {false, any()} |
28-
{binary(), atom()}).
28+
{binary(), atom()} |
29+
{[any()], atom()}).
2930
-type check_password_fun() :: fun((binary(), binary(), binary(), binary(),
3031
fun((binary()) -> binary())) ->
3132
{boolean(), any()} |
@@ -85,7 +86,14 @@ mech_step(#state{step = 3, nonce = Nonce} = State,
8586
AuthzId = proplists:get_value(<<"authzid">>, KeyVals, <<>>),
8687
case (State#state.get_password)(UserName) of
8788
{false, _} -> {error, not_authorized, UserName};
88-
{Passwd, AuthModule} ->
89+
{Passwds, AuthModule} ->
90+
Passwd = case Passwds of
91+
Bin when is_binary(Bin) -> Bin;
92+
List -> lists:foldl(
93+
fun(Bin, false) when is_binary(Bin) -> Bin;
94+
(_, Acc) -> Acc
95+
end, false, List)
96+
end,
8997
case (State#state.check_password)(UserName, UserName, <<"">>,
9098
proplists:get_value(<<"response">>, KeyVals, <<>>),
9199
fun (PW) ->

src/xmpp_sasl_scram.erl

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
-include("scram.hrl").
2828

2929
-type password() :: binary() | #scram{}.
30-
-type get_password_fun() :: fun((binary()) -> {false | {false, atom(), binary()} | password(), module()}).
30+
-type get_password_fun() :: fun((binary()) -> {false | {false, atom(), binary()} | password() | [password()], module()}).
3131

3232
-record(state,
3333
{step = 2 :: 2 | 4,
@@ -124,10 +124,21 @@ mech_step(#state{step = 2, algo = Algo, ssdp = Ssdp} = State, ClientIn) ->
124124
case parse_attribute(ClientNonceAttribute) of
125125
{$r, ClientNonce} ->
126126
{Pass, AuthModule} = (State#state.get_password)(UserName),
127-
LPass = if is_binary(Pass) -> jid:resourceprep(Pass);
128-
true -> Pass
127+
Pass2 = case Pass of
128+
Bin when is_binary(Bin) -> Bin;
129+
List when is_list(List) ->
130+
lists:foldl(
131+
fun(#scram{hash = Hash} = S, _) when Algo == Hash ->
132+
S;
133+
(Bin2, false) when is_binary(Bin2) -> Bin2;
134+
(_, Acc) -> Acc
135+
end, false, List);
136+
Other -> Other
129137
end,
130-
case Pass of
138+
LPass = if is_binary(Pass2) -> jid:resourceprep(Pass2);
139+
true -> Pass2
140+
end,
141+
case Pass2 of
131142
{false, Condition, Text} ->
132143
{error, {Condition, Text}, UserName};
133144
false ->
@@ -138,7 +149,7 @@ mech_step(#state{step = 2, algo = Algo, ssdp = Ssdp} = State, ClientIn) ->
138149
{error, saslprep_failed, UserName};
139150
_ ->
140151
{StoredKey, ServerKey, Salt, IterationCount} =
141-
case Pass of
152+
case Pass2 of
142153
#scram{storedkey = STK, serverkey = SEK, salt = Slt,
143154
iterationcount = IC} ->
144155
{base64:decode(STK),
@@ -148,7 +159,7 @@ mech_step(#state{step = 2, algo = Algo, ssdp = Ssdp} = State, ClientIn) ->
148159
TempSalt =
149160
p1_rand:bytes(?SALT_LENGTH),
150161
SaltedPassword =
151-
scram:salted_password(Algo, Pass,
162+
scram:salted_password(Algo, Pass2,
152163
TempSalt,
153164
?SCRAM_DEFAULT_ITERATION_COUNT),
154165
{scram:stored_key(Algo, scram:client_key(Algo, SaltedPassword)),

0 commit comments

Comments
 (0)