aboutsummaryrefslogtreecommitdiff
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
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.
-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;