aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephen Röttger <stephen.roettger@zero-entropy.de>2013-04-17 12:34:53 +0200
committerBadlop <badlop@process-one.net>2013-04-23 13:55:36 +0200
commit9fa415e557fcb1befadaaee7c2258db622f7c02b (patch)
tree2c07f9e3e446c13d214b4d6182bb5492c5ea1c72 /src
parentFix bug when getting room config (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/cyrsasl_scram.erl79
1 files changed, 43 insertions, 36 deletions
diff --git a/src/cyrsasl_scram.erl b/src/cyrsasl_scram.erl
index 33d18cd1a..ee68bed1e 100644
--- a/src/cyrsasl_scram.erl
+++ b/src/cyrsasl_scram.erl
@@ -32,6 +32,8 @@
-include("ejabberd.hrl").
+-include("jlib.hrl").
+
-behaviour(cyrsasl).
-record(state,
@@ -60,8 +62,11 @@ mech_new(_Host, GetPassword, _CheckPassword,
{ok, #state{step = 2, get_password = GetPassword}}.
mech_step(#state{step = 2} = State, ClientIn) ->
- case str:tokens(ClientIn, <<",">>) of
- [CBind, UserNameAttribute, ClientNonceAttribute]
+ case re:split(ClientIn, <<",">>, [{return, binary}]) of
+ [_CBind, _AuthorizationIdentity, _UserNameAttribute, _ClientNonceAttribute, ExtensionAttribute | _]
+ when ExtensionAttribute /= [] ->
+ {error, <<"protocol-error-extension-not-supported">>};
+ [CBind, _AuthorizationIdentity, UserNameAttribute, ClientNonceAttribute | _]
when (CBind == <<"y">>) or (CBind == <<"n">>) ->
case parse_attribute(UserNameAttribute) of
{error, Reason} -> {error, Reason};
@@ -123,42 +128,44 @@ mech_step(#state{step = 4} = State, ClientIn) ->
[GS2ChannelBindingAttribute, NonceAttribute,
ClientProofAttribute] ->
case parse_attribute(GS2ChannelBindingAttribute) of
- {$c, CVal} when (CVal == <<"biws">>) or (CVal == <<"eSws">>) ->
- %% biws is base64 for n,, => channelbinding not supported
- %% eSws is base64 for y,, => channelbinding supported by client only
- Nonce = <<(State#state.client_nonce)/binary,
- (State#state.server_nonce)/binary>>,
- case parse_attribute(NonceAttribute) of
- {$r, CompareNonce} when CompareNonce == Nonce ->
- case parse_attribute(ClientProofAttribute) of
- {$p, ClientProofB64} ->
- ClientProof = jlib:decode_base64(ClientProofB64),
- AuthMessage =
- iolist_to_binary(
- [State#state.auth_message,
- ",",
- str:substr(ClientIn, 1,
- str:str(ClientIn, <<",p=">>)
- - 1)]),
- ClientSignature =
- scram:client_signature(State#state.stored_key,
- AuthMessage),
- ClientKey = scram:client_key(ClientProof,
- ClientSignature),
- CompareStoredKey = scram:stored_key(ClientKey),
- if CompareStoredKey == State#state.stored_key ->
- ServerSignature =
- scram:server_signature(State#state.server_key,
- AuthMessage),
- {ok, [{username, State#state.username}],
- <<"v=",
- (jlib:encode_base64(ServerSignature))/binary>>};
- true -> {error, <<"bad-auth">>}
+ {$c, CVal} ->
+ ChannelBindingSupport = binary:at(jlib:decode_base64(CVal), 0),
+ if (ChannelBindingSupport == $n)
+ or (ChannelBindingSupport == $y) ->
+ Nonce = <<(State#state.client_nonce)/binary,
+ (State#state.server_nonce)/binary>>,
+ case parse_attribute(NonceAttribute) of
+ {$r, CompareNonce} when CompareNonce == Nonce ->
+ case parse_attribute(ClientProofAttribute) of
+ {$p, ClientProofB64} ->
+ ClientProof = jlib:decode_base64(ClientProofB64),
+ AuthMessage = iolist_to_binary(
+ [State#state.auth_message,
+ ",",
+ str:substr(ClientIn, 1,
+ str:str(ClientIn, <<",p=">>)
+ - 1)]),
+ ClientSignature =
+ scram:client_signature(State#state.stored_key,
+ AuthMessage),
+ ClientKey = scram:client_key(ClientProof,
+ ClientSignature),
+ CompareStoredKey = scram:stored_key(ClientKey),
+ if CompareStoredKey == State#state.stored_key ->
+ ServerSignature =
+ scram:server_signature(State#state.server_key,
+ AuthMessage),
+ {ok, [{username, State#state.username}],
+ <<"v=",
+ (jlib:encode_base64(ServerSignature))/binary>>};
+ true -> {error, <<"bad-auth">>}
+ end;
+ _Else -> {error, <<"bad-protocol">>}
end;
+ {$r, _} -> {error, <<"bad-nonce">>};
_Else -> {error, <<"bad-protocol">>}
- end;
- {$r, _} -> {error, <<"bad-nonce">>};
- _Else -> {error, <<"bad-protocol">>}
+ end;
+ true -> {error, <<"bad-channel-binding">>}
end;
_Else -> {error, <<"bad-protocol">>}
end;