Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/processone/ejabberd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephen Röttger <stephen.roettger@zero-entropy.de>2013-04-17 14:34:53 +0400
committerBadlop <badlop@process-one.net>2013-04-23 15:55:36 +0400
commit9fa415e557fcb1befadaaee7c2258db622f7c02b (patch)
tree2c07f9e3e446c13d214b4d6182bb5492c5ea1c72 /src
parentc0afb1f28214177fb8124dde441f1abad63438f7 (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;