Line
Link Here
|
|
The server gave an authentication error, if optional parameters |
|
The server gave an authentication error, if optional parameters |
1 |
were present in the GS2 Header. Specifically, the "a=" parameter, |
1 |
were present in the GS2 Header. Specifically, the "a=" parameter, |
2 |
that can be used by admins to login as a different user. |
2 |
that can be used by admins to login as a different user. |
3 |
. |
3 |
. |
4 |
This patch is a backport of changes introduced by the commit |
4 |
This patch is a backport of changes introduced by the commit |
5 |
9e9b0eae802ee0508db6780426954efd048e7976 in the upstream Git repository |
5 |
9e9b0eae802ee0508db6780426954efd048e7976 in the upstream Git repository |
6 |
to the ejabberd code base as of version 2.1.10. |
6 |
to the ejabberd code base as of version 2.1.10. |
7 |
-- |
7 |
++ b/src/cyrsasl_scram.erl |
8 |
-- a/src/cyrsasl_scram.erl |
|
|
Lines 34-39
Link Here
|
34 |
|
34 |
|
35 |
-include("ejabberd.hrl"). |
35 |
-include("ejabberd.hrl"). |
36 |
|
36 |
|
|
|
37 |
-include("jlib.hrl"). |
38 |
|
37 |
-behaviour(cyrsasl). |
39 |
-behaviour(cyrsasl). |
38 |
|
40 |
|
39 |
-record(state, {step, stored_key, server_key, username, get_password, check_password, |
41 |
-record(state, {step, stored_key, server_key, username, get_password, check_password, |
Lines 52-59
Link Here
|
52 |
{ok, #state{step = 2, get_password = GetPassword}}. |
54 |
{ok, #state{step = 2, get_password = GetPassword}}. |
53 |
|
55 |
|
54 |
mech_step(#state{step = 2} = State, ClientIn) -> |
56 |
mech_step(#state{step = 2} = State, ClientIn) -> |
55 |
case string:tokens(ClientIn, ",") of |
57 |
case re:split(ClientIn, ",", [{return, list}]) of |
56 |
[CBind, UserNameAttribute, ClientNonceAttribute] when (CBind == "y") or (CBind == "n") -> |
58 |
[_CBind, _AuthorizationIdentity, _UserNameAttribute, _ClientNonceAttribute, ExtensionAttribute | _] |
|
|
59 |
when ExtensionAttribute /= [] -> |
60 |
{error, <<"protocol-error-extension-not-supported">>}; |
61 |
[CBind, _AuthorizationIdentity, UserNameAttribute, ClientNonceAttribute | _] |
62 |
when (CBind == "y") or (CBind == "n") -> |
57 |
case parse_attribute(UserNameAttribute) of |
63 |
case parse_attribute(UserNameAttribute) of |
58 |
{error, Reason} -> |
64 |
{error, Reason} -> |
59 |
{error, Reason}; |
65 |
{error, Reason}; |
Lines 100-131
Link Here
|
100 |
case string:tokens(ClientIn, ",") of |
106 |
case string:tokens(ClientIn, ",") of |
101 |
[GS2ChannelBindingAttribute, NonceAttribute, ClientProofAttribute] -> |
107 |
[GS2ChannelBindingAttribute, NonceAttribute, ClientProofAttribute] -> |
102 |
case parse_attribute(GS2ChannelBindingAttribute) of |
108 |
case parse_attribute(GS2ChannelBindingAttribute) of |
103 |
{$c, CVal} when (CVal == "biws") or (CVal == "eSws") -> |
109 |
{$c, CVal} -> |
104 |
%% biws is base64 for n,, => channelbinding not supported |
110 |
ChannelBindingSupport = string:left(jlib:decode_base64(CVal), 1), |
105 |
%% eSws is base64 for y,, => channelbinding supported by client only |
111 |
if (ChannelBindingSupport == "n") |
106 |
Nonce = State#state.client_nonce ++ State#state.server_nonce, |
112 |
or (ChannelBindingSupport == "y") -> |
107 |
case parse_attribute(NonceAttribute) of |
113 |
Nonce = State#state.client_nonce ++ State#state.server_nonce, |
108 |
{$r, CompareNonce} when CompareNonce == Nonce -> |
114 |
case parse_attribute(NonceAttribute) of |
109 |
case parse_attribute(ClientProofAttribute) of |
115 |
{$r, CompareNonce} when CompareNonce == Nonce -> |
110 |
{$p, ClientProofB64} -> |
116 |
case parse_attribute(ClientProofAttribute) of |
111 |
ClientProof = base64:decode(ClientProofB64), |
117 |
{$p, ClientProofB64} -> |
112 |
AuthMessage = State#state.auth_message ++ "," ++ string:substr(ClientIn, 1, string:str(ClientIn, ",p=")-1), |
118 |
ClientProof = base64:decode(ClientProofB64), |
113 |
ClientSignature = scram:client_signature(State#state.stored_key, AuthMessage), |
119 |
AuthMessage = State#state.auth_message ++ "," ++ string:substr(ClientIn, 1, string:str(ClientIn, ",p=")-1), |
114 |
ClientKey = scram:client_key(ClientProof, ClientSignature), |
120 |
ClientSignature = scram:client_signature(State#state.stored_key, AuthMessage), |
115 |
CompareStoredKey = scram:stored_key(ClientKey), |
121 |
ClientKey = scram:client_key(ClientProof, ClientSignature), |
116 |
if CompareStoredKey == State#state.stored_key -> |
122 |
CompareStoredKey = scram:stored_key(ClientKey), |
117 |
ServerSignature = scram:server_signature(State#state.server_key, AuthMessage), |
123 |
if CompareStoredKey == State#state.stored_key -> |
118 |
{ok, [{username, State#state.username}], "v=" ++ base64:encode_to_string(ServerSignature)}; |
124 |
ServerSignature = scram:server_signature(State#state.server_key, AuthMessage), |
119 |
true -> |
125 |
{ok, [{username, State#state.username}], "v=" ++ base64:encode_to_string(ServerSignature)}; |
120 |
{error, "bad-auth"} |
126 |
true -> |
|
|
127 |
{error, "bad-auth"} |
128 |
end; |
129 |
_Else -> |
130 |
{error, "bad-protocol"} |
121 |
end; |
131 |
end; |
|
|
132 |
{$r, _} -> |
133 |
{error, "bad-nonce"}; |
122 |
_Else -> |
134 |
_Else -> |
123 |
{error, "bad-protocol"} |
135 |
{error, "bad-protocol"} |
124 |
end; |
136 |
end; |
125 |
{$r, _} -> |
137 |
true -> |
126 |
{error, "bad-nonce"}; |
138 |
{error, "bad-channel-binding"} |
127 |
_Else -> |
|
|
128 |
{error, "bad-protocol"} |
129 |
end; |
139 |
end; |
130 |
_Else -> |
140 |
_Else -> |
131 |
{error, "bad-protocol"} |
141 |
{error, "bad-protocol"} |