SCRAM optional parameter parsing bugfix
The server gave an authentication error, if optional parameters were present in the GS2 Header. Specifically, the "a=" parameter, that can be used by admins to login as a different user.
This commit is contained in:
parent
c0afb1f282
commit
9fa415e557
|
@ -32,6 +32,8 @@
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
|
|
||||||
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-behaviour(cyrsasl).
|
-behaviour(cyrsasl).
|
||||||
|
|
||||||
-record(state,
|
-record(state,
|
||||||
|
@ -60,8 +62,11 @@ mech_new(_Host, GetPassword, _CheckPassword,
|
||||||
{ok, #state{step = 2, get_password = GetPassword}}.
|
{ok, #state{step = 2, get_password = GetPassword}}.
|
||||||
|
|
||||||
mech_step(#state{step = 2} = State, ClientIn) ->
|
mech_step(#state{step = 2} = State, ClientIn) ->
|
||||||
case str:tokens(ClientIn, <<",">>) of
|
case re:split(ClientIn, <<",">>, [{return, binary}]) of
|
||||||
[CBind, UserNameAttribute, ClientNonceAttribute]
|
[_CBind, _AuthorizationIdentity, _UserNameAttribute, _ClientNonceAttribute, ExtensionAttribute | _]
|
||||||
|
when ExtensionAttribute /= [] ->
|
||||||
|
{error, <<"protocol-error-extension-not-supported">>};
|
||||||
|
[CBind, _AuthorizationIdentity, UserNameAttribute, ClientNonceAttribute | _]
|
||||||
when (CBind == <<"y">>) or (CBind == <<"n">>) ->
|
when (CBind == <<"y">>) or (CBind == <<"n">>) ->
|
||||||
case parse_attribute(UserNameAttribute) of
|
case parse_attribute(UserNameAttribute) of
|
||||||
{error, Reason} -> {error, Reason};
|
{error, Reason} -> {error, Reason};
|
||||||
|
@ -123,42 +128,44 @@ mech_step(#state{step = 4} = State, ClientIn) ->
|
||||||
[GS2ChannelBindingAttribute, NonceAttribute,
|
[GS2ChannelBindingAttribute, NonceAttribute,
|
||||||
ClientProofAttribute] ->
|
ClientProofAttribute] ->
|
||||||
case parse_attribute(GS2ChannelBindingAttribute) of
|
case parse_attribute(GS2ChannelBindingAttribute) of
|
||||||
{$c, CVal} when (CVal == <<"biws">>) or (CVal == <<"eSws">>) ->
|
{$c, CVal} ->
|
||||||
%% biws is base64 for n,, => channelbinding not supported
|
ChannelBindingSupport = binary:at(jlib:decode_base64(CVal), 0),
|
||||||
%% eSws is base64 for y,, => channelbinding supported by client only
|
if (ChannelBindingSupport == $n)
|
||||||
Nonce = <<(State#state.client_nonce)/binary,
|
or (ChannelBindingSupport == $y) ->
|
||||||
(State#state.server_nonce)/binary>>,
|
Nonce = <<(State#state.client_nonce)/binary,
|
||||||
case parse_attribute(NonceAttribute) of
|
(State#state.server_nonce)/binary>>,
|
||||||
{$r, CompareNonce} when CompareNonce == Nonce ->
|
case parse_attribute(NonceAttribute) of
|
||||||
case parse_attribute(ClientProofAttribute) of
|
{$r, CompareNonce} when CompareNonce == Nonce ->
|
||||||
{$p, ClientProofB64} ->
|
case parse_attribute(ClientProofAttribute) of
|
||||||
ClientProof = jlib:decode_base64(ClientProofB64),
|
{$p, ClientProofB64} ->
|
||||||
AuthMessage =
|
ClientProof = jlib:decode_base64(ClientProofB64),
|
||||||
iolist_to_binary(
|
AuthMessage = iolist_to_binary(
|
||||||
[State#state.auth_message,
|
[State#state.auth_message,
|
||||||
",",
|
",",
|
||||||
str:substr(ClientIn, 1,
|
str:substr(ClientIn, 1,
|
||||||
str:str(ClientIn, <<",p=">>)
|
str:str(ClientIn, <<",p=">>)
|
||||||
- 1)]),
|
- 1)]),
|
||||||
ClientSignature =
|
ClientSignature =
|
||||||
scram:client_signature(State#state.stored_key,
|
scram:client_signature(State#state.stored_key,
|
||||||
AuthMessage),
|
AuthMessage),
|
||||||
ClientKey = scram:client_key(ClientProof,
|
ClientKey = scram:client_key(ClientProof,
|
||||||
ClientSignature),
|
ClientSignature),
|
||||||
CompareStoredKey = scram:stored_key(ClientKey),
|
CompareStoredKey = scram:stored_key(ClientKey),
|
||||||
if CompareStoredKey == State#state.stored_key ->
|
if CompareStoredKey == State#state.stored_key ->
|
||||||
ServerSignature =
|
ServerSignature =
|
||||||
scram:server_signature(State#state.server_key,
|
scram:server_signature(State#state.server_key,
|
||||||
AuthMessage),
|
AuthMessage),
|
||||||
{ok, [{username, State#state.username}],
|
{ok, [{username, State#state.username}],
|
||||||
<<"v=",
|
<<"v=",
|
||||||
(jlib:encode_base64(ServerSignature))/binary>>};
|
(jlib:encode_base64(ServerSignature))/binary>>};
|
||||||
true -> {error, <<"bad-auth">>}
|
true -> {error, <<"bad-auth">>}
|
||||||
|
end;
|
||||||
|
_Else -> {error, <<"bad-protocol">>}
|
||||||
end;
|
end;
|
||||||
|
{$r, _} -> {error, <<"bad-nonce">>};
|
||||||
_Else -> {error, <<"bad-protocol">>}
|
_Else -> {error, <<"bad-protocol">>}
|
||||||
end;
|
end;
|
||||||
{$r, _} -> {error, <<"bad-nonce">>};
|
true -> {error, <<"bad-channel-binding">>}
|
||||||
_Else -> {error, <<"bad-protocol">>}
|
|
||||||
end;
|
end;
|
||||||
_Else -> {error, <<"bad-protocol">>}
|
_Else -> {error, <<"bad-protocol">>}
|
||||||
end;
|
end;
|
||||||
|
|
Loading…
Reference in New Issue