summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Langfeld <ben@langfeld.me>2015-04-08 22:21:09 -0300
committerBen Langfeld <ben@langfeld.me>2015-05-06 14:12:15 -0300
commit917d48f30bca65f984c4e1305eefe7266097ff65 (patch)
tree390c7a48debfc9ee47f3c78c4fc079c003a463b6
parentRemove commented code (diff)
Use SASL PLAIN authzid as client identity if auth module permits it
This allows the authentication modules to perform SASL proxy authentication. It puts the onus on them to authorize the authcid to masquerade as the authzid. Doesn't currently implement such functionality in existing auth modules, since they cannot currently codify a relationship between the two identities. Does not permit the authzid to use a domain differently from the one of the connection. Note: digest might not work, but I have no interest in it, being deprecated.
-rw-r--r--src/cyrsasl.erl2
-rw-r--r--src/cyrsasl_digest.erl10
-rw-r--r--src/cyrsasl_plain.erl15
-rw-r--r--src/ejabberd_auth.erl42
-rw-r--r--src/ejabberd_auth_anonymous.erl10
-rw-r--r--src/ejabberd_auth_external.erl54
-rw-r--r--src/ejabberd_auth_internal.erl84
-rw-r--r--src/ejabberd_auth_ldap.erl26
-rw-r--r--src/ejabberd_auth_odbc.erl174
-rw-r--r--src/ejabberd_auth_pam.erl36
-rw-r--r--src/ejabberd_auth_riak.erl78
-rw-r--r--src/ejabberd_c2s.erl28
-rw-r--r--src/ejabberd_commands.erl2
-rw-r--r--src/ejabberd_web_admin.erl2
-rw-r--r--src/mod_proxy65_stream.erl2
-rw-r--r--src/mod_register_web.erl2
16 files changed, 306 insertions, 261 deletions
diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl
index 764473ba..09b1a1a6 100644
--- a/src/cyrsasl.erl
+++ b/src/cyrsasl.erl
@@ -128,7 +128,7 @@ register_mechanism(Mechanism, Module, PasswordType) ->
%% end.
check_credentials(_State, Props) ->
- User = proplists:get_value(username, Props, <<>>),
+ User = proplists:get_value(authzid, Props, <<>>),
case jlib:nodeprep(User) of
error -> {error, <<"not-authorized">>};
<<"">> -> {error, <<"not-authorized">>};
diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl
index be9867ba..12e5555a 100644
--- a/src/cyrsasl_digest.erl
+++ b/src/cyrsasl_digest.erl
@@ -47,7 +47,7 @@
username = <<"">> :: binary(),
authzid = <<"">> :: binary(),
get_password = fun(_) -> {false, <<>>} end :: get_password_fun(),
- check_password = fun(_, _, _, _) -> false end :: check_password_fun(),
+ check_password = fun(_, _, _, _, _) -> false end :: check_password_fun(),
auth_module :: atom(),
host = <<"">> :: binary(),
hostfqdn = <<"">> :: binary()}).
@@ -95,7 +95,7 @@ mech_step(#state{step = 3, nonce = Nonce} = State,
case (State#state.get_password)(UserName) of
{false, _} -> {error, <<"not-authorized">>, UserName};
{Passwd, AuthModule} ->
- case (State#state.check_password)(UserName, <<"">>,
+ case (State#state.check_password)(UserName, UserName, <<"">>,
proplists:get_value(<<"response">>, KeyVals, <<>>),
fun (PW) ->
response(KeyVals,
@@ -123,7 +123,11 @@ mech_step(#state{step = 5, auth_module = AuthModule,
username = UserName, authzid = AuthzId},
<<"">>) ->
{ok,
- [{username, UserName}, {authzid, AuthzId},
+ [{username, UserName}, {authzid, case AuthzId of
+ <<"">> -> UserName;
+ _ -> AuthzId
+ end
+ },
{auth_module, AuthModule}]};
mech_step(A, B) ->
?DEBUG("SASL DIGEST: A ~p B ~p", [A, B]),
diff --git a/src/cyrsasl_plain.erl b/src/cyrsasl_plain.erl
index d2fb373e..ceceacca 100644
--- a/src/cyrsasl_plain.erl
+++ b/src/cyrsasl_plain.erl
@@ -45,7 +45,7 @@ mech_new(_Host, _GetPassword, CheckPassword, _CheckPasswordDigest) ->
mech_step(State, ClientIn) ->
case prepare(ClientIn) of
[AuthzId, User, Password] ->
- case (State#state.check_password)(User, Password) of
+ case (State#state.check_password)(User, AuthzId, Password) of
{true, AuthModule} ->
{ok,
[{username, User}, {authzid, AuthzId},
@@ -60,12 +60,17 @@ prepare(ClientIn) ->
[<<"">>, UserMaybeDomain, Password] ->
case parse_domain(UserMaybeDomain) of
%% <NUL>login@domain<NUL>pwd
- [User, _Domain] -> [UserMaybeDomain, User, Password];
+ [User, _Domain] -> [User, User, Password];
%% <NUL>login<NUL>pwd
- [User] -> [<<"">>, User, Password]
+ [User] -> [User, User, Password]
end;
- %% login@domain<NUL>login<NUL>pwd
- [AuthzId, User, Password] -> [AuthzId, User, Password];
+ [AuthzId, User, Password] ->
+ case parse_domain(AuthzId) of
+ %% login@domain<NUL>login<NUL>pwd
+ [AuthzUser, _Domain] -> [AuthzUser, User, Password];
+ %% login<NUL>login<NUL>pwd
+ [AuthzUser] -> [AuthzUser, User, Password]
+ end;
_ -> error
end.
diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl
index 991cb664..bf47af85 100644
--- a/src/ejabberd_auth.erl
+++ b/src/ejabberd_auth.erl
@@ -30,9 +30,9 @@
-author('alexey@process-one.net').
%% External exports
--export([start/0, set_password/3, check_password/3,
- check_password/5, check_password_with_authmodule/3,
- check_password_with_authmodule/5, try_register/3,
+-export([start/0, set_password/3, check_password/4,
+ check_password/6, check_password_with_authmodule/4,
+ check_password_with_authmodule/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2, export/1, import/1,
get_vh_registered_users_number/1, import/3,
@@ -61,8 +61,8 @@
-callback remove_user(binary(), binary()) -> any().
-callback remove_user(binary(), binary(), binary()) -> any().
-callback is_user_exists(binary(), binary()) -> boolean() | {error, atom()}.
--callback check_password(binary(), binary(), binary()) -> boolean().
--callback check_password(binary(), binary(), binary(), binary(),
+-callback check_password(binary(), binary(), binary(), binary()) -> boolean().
+-callback check_password(binary(), binary(), binary(), binary(), binary(),
fun((binary()) -> binary())) -> boolean().
-callback try_register(binary(), binary(), binary()) -> {atomic, atom()} |
{error, atom()}.
@@ -100,10 +100,10 @@ store_type(Server) ->
end,
plain, auth_modules(Server)).
--spec check_password(binary(), binary(), binary()) -> boolean().
+-spec check_password(binary(), binary(), binary(), binary()) -> boolean().
-check_password(User, Server, Password) ->
- case check_password_with_authmodule(User, Server,
+check_password(User, AuthzId, Server, Password) ->
+ case check_password_with_authmodule(User, AuthzId, Server,
Password)
of
{true, _AuthModule} -> true;
@@ -111,15 +111,15 @@ check_password(User, Server, Password) ->
end.
%% @doc Check if the user and password can login in server.
-%% @spec (User::string(), Server::string(), Password::string(),
+%% @spec (User::string(), AuthzId::string(), Server::string(), Password::string(),
%% Digest::string(), DigestGen::function()) ->
%% true | false
--spec check_password(binary(), binary(), binary(), binary(),
+-spec check_password(binary(), binary(), binary(), binary(), binary(),
fun((binary()) -> binary())) -> boolean().
-
-check_password(User, Server, Password, Digest,
+
+check_password(User, AuthzId, Server, Password, Digest,
DigestGen) ->
- case check_password_with_authmodule(User, Server,
+ case check_password_with_authmodule(User, AuthzId, Server,
Password, Digest, DigestGen)
of
{true, _AuthModule} -> true;
@@ -130,28 +130,28 @@ check_password(User, Server, Password, Digest,
%% The user can login if at least an authentication method accepts the user
%% and the password.
%% The first authentication method that accepts the credentials is returned.
-%% @spec (User::string(), Server::string(), Password::string()) ->
+%% @spec (User::string(), AuthzId::string(), Server::string(), Password::string()) ->
%% {true, AuthModule} | false
%% where
%% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external
%% | ejabberd_auth_internal | ejabberd_auth_ldap
-%% | ejabberd_auth_odbc | ejabberd_auth_pam
--spec check_password_with_authmodule(binary(), binary(), binary()) -> false |
+%% | ejabberd_auth_odbc | ejabberd_auth_pam | ejabberd_auth_riak
+-spec check_password_with_authmodule(binary(), binary(), binary(), binary()) -> false |
{true, atom()}.
-check_password_with_authmodule(User, Server,
+check_password_with_authmodule(User, AuthzId, Server,
Password) ->
check_password_loop(auth_modules(Server),
- [User, Server, Password]).
+ [User, AuthzId, Server, Password]).
--spec check_password_with_authmodule(binary(), binary(), binary(), binary(),
+-spec check_password_with_authmodule(binary(), binary(), binary(), binary(), binary(),
fun((binary()) -> binary())) -> false |
{true, atom()}.
-check_password_with_authmodule(User, Server, Password,
+check_password_with_authmodule(User, AuthzId, Server, Password,
Digest, DigestGen) ->
check_password_loop(auth_modules(Server),
- [User, Server, Password, Digest, DigestGen]).
+ [User, AuthzId, Server, Password, Digest, DigestGen]).
check_password_loop([], _Args) -> false;
check_password_loop([AuthModule | AuthModules], Args) ->
diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl
index cb320dea..05f790db 100644
--- a/src/ejabberd_auth_anonymous.erl
+++ b/src/ejabberd_auth_anonymous.erl
@@ -38,8 +38,8 @@
%% Function used by ejabberd_auth:
--export([login/2, set_password/3, check_password/3,
- check_password/5, try_register/3,
+-export([login/2, set_password/3, check_password/4,
+ check_password/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2, get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password_s/2,
@@ -174,11 +174,11 @@ purge_hook(true, LUser, LServer) ->
%% When anonymous login is enabled, check the password for permenant users
%% before allowing access
-check_password(User, Server, Password) ->
- check_password(User, Server, Password, undefined,
+check_password(User, AuthzId, Server, Password) ->
+ check_password(User, AuthzId, Server, Password, undefined,
undefined).
-check_password(User, Server, _Password, _Digest,
+check_password(User, _AuthzId, Server, _Password, _Digest,
_DigestGen) ->
case
ejabberd_auth:is_user_exists_in_other_modules(?MODULE,
diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl
index 0aa825f7..44c931cb 100644
--- a/src/ejabberd_auth_external.erl
+++ b/src/ejabberd_auth_external.erl
@@ -30,8 +30,8 @@
-behaviour(ejabberd_auth).
%% External exports
--export([start/1, set_password/3, check_password/3,
- check_password/5, try_register/3,
+-export([start/1, set_password/3, check_password/4,
+ check_password/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
@@ -75,16 +75,20 @@ plain_password_required() -> true.
store_type() -> external.
-check_password(User, Server, Password) ->
- case get_cache_option(Server) of
- false -> check_password_extauth(User, Server, Password);
- {true, CacheTime} ->
- check_password_cache(User, Server, Password, CacheTime)
+check_password(User, AuthzId, Server, Password) ->
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ case get_cache_option(Server) of
+ false -> check_password_extauth(User, AuthzId, Server, Password);
+ {true, CacheTime} ->
+ check_password_cache(User, AuthzId, Server, Password, CacheTime)
+ end
end.
-check_password(User, Server, Password, _Digest,
+check_password(User, AuthzId, Server, Password, _Digest,
_DigestGen) ->
- check_password(User, Server, Password).
+ check_password(User, AuthzId, Server, Password).
set_password(User, Server, Password) ->
case extauth:set_password(User, Server, Password) of
@@ -177,8 +181,8 @@ get_cache_option(Host) ->
CacheTime -> {true, CacheTime}
end.
-%% @spec (User, Server, Password) -> true | false
-check_password_extauth(User, Server, Password) ->
+%% @spec (User, AuthzId, Server, Password) -> true | false
+check_password_extauth(User, _AuthzId, Server, Password) ->
extauth:check_password(User, Server, Password) andalso
Password /= <<"">>.
@@ -186,35 +190,35 @@ check_password_extauth(User, Server, Password) ->
try_register_extauth(User, Server, Password) ->
extauth:try_register(User, Server, Password).
-check_password_cache(User, Server, Password, 0) ->
- check_password_external_cache(User, Server, Password);
-check_password_cache(User, Server, Password,
+check_password_cache(User, AuthzId, Server, Password, 0) ->
+ check_password_external_cache(User, AuthzId, Server, Password);
+check_password_cache(User, AuthzId, Server, Password,
CacheTime) ->
case get_last_access(User, Server) of
online ->
- check_password_internal(User, Server, Password);
+ check_password_internal(User, AuthzId, Server, Password);
never ->
- check_password_external_cache(User, Server, Password);
+ check_password_external_cache(User, AuthzId, Server, Password);
mod_last_required ->
?ERROR_MSG("extauth is used, extauth_cache is enabled "
"but mod_last is not enabled in that "
"host",
[]),
- check_password_external_cache(User, Server, Password);
+ check_password_external_cache(User, AuthzId, Server, Password);
TimeStamp ->
case is_fresh_enough(TimeStamp, CacheTime) of
%% If no need to refresh, check password against Mnesia
true ->
- case check_password_internal(User, Server, Password) of
+ case check_password_internal(User, AuthzId, Server, Password) of
%% If password valid in Mnesia, accept it
true -> true;
%% Else (password nonvalid in Mnesia), check in extauth and cache result
false ->
- check_password_external_cache(User, Server, Password)
+ check_password_external_cache(User, AuthzId, Server, Password)
end;
%% Else (need to refresh), check in extauth and cache result
false ->
- check_password_external_cache(User, Server, Password)
+ check_password_external_cache(User, AuthzId, Server, Password)
end
end.
@@ -240,8 +244,8 @@ get_password_cache(User, Server, CacheTime) ->
end.
%% Check the password using extauth; if success then cache it
-check_password_external_cache(User, Server, Password) ->
- case check_password_extauth(User, Server, Password) of
+check_password_external_cache(User, AuthzId, Server, Password) ->
+ case check_password_extauth(User, AuthzId, Server, Password) of
true ->
set_password_internal(User, Server, Password), true;
false -> false
@@ -255,9 +259,9 @@ try_register_external_cache(User, Server, Password) ->
_ -> {error, not_allowed}
end.
-%% @spec (User, Server, Password) -> true | false
-check_password_internal(User, Server, Password) ->
- ejabberd_auth_internal:check_password(User, Server,
+%% @spec (User, AuthzId, Server, Password) -> true | false
+check_password_internal(User, AuthzId, Server, Password) ->
+ ejabberd_auth_internal:check_password(User, AuthzId, Server,
Password).
%% @spec (User, Server, Password) -> ok | {error, invalid_jid}
diff --git a/src/ejabberd_auth_internal.erl b/src/ejabberd_auth_internal.erl
index fc128ac5..bb4ceab5 100644
--- a/src/ejabberd_auth_internal.erl
+++ b/src/ejabberd_auth_internal.erl
@@ -30,8 +30,8 @@
-behaviour(ejabberd_auth).
%% External exports
--export([start/1, set_password/3, check_password/3,
- check_password/5, try_register/3,
+-export([start/1, set_password/3, check_password/4,
+ check_password/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
@@ -85,45 +85,53 @@ store_type() ->
true -> scram %% allows: PLAIN SCRAM
end.
-check_password(User, Server, Password) ->
- LUser = jlib:nodeprep(User),
- LServer = jlib:nameprep(Server),
- US = {LUser, LServer},
- case catch mnesia:dirty_read({passwd, US}) of
- [#passwd{password = Password}]
- when is_binary(Password) ->
- Password /= <<"">>;
- [#passwd{password = Scram}]
- when is_record(Scram, scram) ->
- is_password_scram_valid(Password, Scram);
- _ -> false
+check_password(User, AuthzId, Server, Password) ->
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
+ US = {LUser, LServer},
+ case catch mnesia:dirty_read({passwd, US}) of
+ [#passwd{password = Password}]
+ when is_binary(Password) ->
+ Password /= <<"">>;
+ [#passwd{password = Scram}]
+ when is_record(Scram, scram) ->
+ is_password_scram_valid(Password, Scram);
+ _ -> false
+ end
end.
-check_password(User, Server, Password, Digest,
+check_password(User, AuthzId, Server, Password, Digest,
DigestGen) ->
- LUser = jlib:nodeprep(User),
- LServer = jlib:nameprep(Server),
- US = {LUser, LServer},
- case catch mnesia:dirty_read({passwd, US}) of
- [#passwd{password = Passwd}] when is_binary(Passwd) ->
- DigRes = if Digest /= <<"">> ->
- Digest == DigestGen(Passwd);
- true -> false
- end,
- if DigRes -> true;
- true -> (Passwd == Password) and (Password /= <<"">>)
- end;
- [#passwd{password = Scram}]
- when is_record(Scram, scram) ->
- Passwd = jlib:decode_base64(Scram#scram.storedkey),
- DigRes = if Digest /= <<"">> ->
- Digest == DigestGen(Passwd);
- true -> false
- end,
- if DigRes -> true;
- true -> (Passwd == Password) and (Password /= <<"">>)
- end;
- _ -> false
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
+ US = {LUser, LServer},
+ case catch mnesia:dirty_read({passwd, US}) of
+ [#passwd{password = Passwd}] when is_binary(Passwd) ->
+ DigRes = if Digest /= <<"">> ->
+ Digest == DigestGen(Passwd);
+ true -> false
+ end,
+ if DigRes -> true;
+ true -> (Passwd == Password) and (Password /= <<"">>)
+ end;
+ [#passwd{password = Scram}]
+ when is_record(Scram, scram) ->
+ Passwd = jlib:decode_base64(Scram#scram.storedkey),
+ DigRes = if Digest /= <<"">> ->
+ Digest == DigestGen(Passwd);
+ true -> false
+ end,
+ if DigRes -> true;
+ true -> (Passwd == Password) and (Password /= <<"">>)
+ end;
+ _ -> false
+ end
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl
index 3055d104..45964d66 100644
--- a/src/ejabberd_auth_ldap.erl
+++ b/src/ejabberd_auth_ldap.erl
@@ -36,7 +36,7 @@
%% External exports
-export([start/1, stop/1, start_link/1, set_password/3,
- check_password/3, check_password/5, try_register/3,
+ check_password/4, check_password/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
@@ -115,19 +115,23 @@ plain_password_required() -> true.
store_type() -> external.
-check_password(User, Server, Password) ->
- if Password == <<"">> -> false;
- true ->
- case catch check_password_ldap(User, Server, Password)
- of
- {'EXIT', _} -> false;
- Result -> Result
- end
+check_password(User, AuthzId, Server, Password) ->
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ if Password == <<"">> -> false;
+ true ->
+ case catch check_password_ldap(User, Server, Password)
+ of
+ {'EXIT', _} -> false;
+ Result -> Result
+ end
+ end
end.
-check_password(User, Server, Password, _Digest,
+check_password(User, AuthzId, Server, Password, _Digest,
_DigestGen) ->
- check_password(User, Server, Password).
+ check_password(User, AuthzId, Server, Password).
set_password(User, Server, Password) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl
index 881b86cc..b3bcd369 100644
--- a/src/ejabberd_auth_odbc.erl
+++ b/src/ejabberd_auth_odbc.erl
@@ -30,8 +30,8 @@
-behaviour(ejabberd_auth).
%% External exports
--export([start/1, set_password/3, check_password/3,
- check_password/5, try_register/3,
+-export([start/1, set_password/3, check_password/4,
+ check_password/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
@@ -63,89 +63,97 @@ store_type() ->
true -> scram %% allows: PLAIN SCRAM
end.
-%% @spec (User, Server, Password) -> true | false | {error, Error}
-check_password(User, Server, Password) ->
- LServer = jlib:nameprep(Server),
- LUser = jlib:nodeprep(User),
- if (LUser == error) or (LServer == error) ->
- false;
- (LUser == <<>>) or (LServer == <<>>) ->
- false;
- true ->
- Username = ejabberd_odbc:escape(LUser),
- case is_scrammed() of
- true ->
- try odbc_queries:get_password_scram(LServer, Username) of
- {selected, [<<"password">>, <<"serverkey">>,
- <<"salt">>, <<"iterationcount">>],
- [[StoredKey, ServerKey, Salt, IterationCount]]} ->
- Scram =
- #scram{storedkey = StoredKey,
- serverkey = ServerKey,
- salt = Salt,
- iterationcount = jlib:binary_to_integer(
- IterationCount)},
- is_password_scram_valid(Password, Scram);
- {selected, [<<"password">>, <<"serverkey">>,
- <<"salt">>, <<"iterationcount">>], []} ->
- false; %% Account does not exist
- {error, _Error} ->
- false %% Typical error is that table doesn't exist
- catch
- _:_ ->
- false %% Typical error is database not accessible
- end;
- false ->
- try odbc_queries:get_password(LServer, Username) of
- {selected, [<<"password">>], [[Password]]} ->
- Password /= <<"">>;
- {selected, [<<"password">>], [[_Password2]]} ->
- false; %% Password is not correct
- {selected, [<<"password">>], []} ->
- false; %% Account does not exist
- {error, _Error} ->
- false %% Typical error is that table doesn't exist
- catch
- _:_ ->
- false %% Typical error is database not accessible
- end
- end
+%% @spec (User, AuthzId, Server, Password) -> true | false | {error, Error}
+check_password(User, AuthzId, Server, Password) ->
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ LServer = jlib:nameprep(Server),
+ LUser = jlib:nodeprep(User),
+ if (LUser == error) or (LServer == error) ->
+ false;
+ (LUser == <<>>) or (LServer == <<>>) ->
+ false;
+ true ->
+ Username = ejabberd_odbc:escape(LUser),
+ case is_scrammed() of
+ true ->
+ try odbc_queries:get_password_scram(LServer, Username) of
+ {selected, [<<"password">>, <<"serverkey">>,
+ <<"salt">>, <<"iterationcount">>],
+ [[StoredKey, ServerKey, Salt, IterationCount]]} ->
+ Scram =
+ #scram{storedkey = StoredKey,
+ serverkey = ServerKey,
+ salt = Salt,
+ iterationcount = jlib:binary_to_integer(
+ IterationCount)},
+ is_password_scram_valid(Password, Scram);
+ {selected, [<<"password">>, <<"serverkey">>,
+ <<"salt">>, <<"iterationcount">>], []} ->
+ false; %% Account does not exist
+ {error, _Error} ->
+ false %% Typical error is that table doesn't exist
+ catch
+ _:_ ->
+ false %% Typical error is database not accessible
+ end;
+ false ->
+ try odbc_queries:get_password(LServer, Username) of
+ {selected, [<<"password">>], [[Password]]} ->
+ Password /= <<"">>;
+ {selected, [<<"password">>], [[_Password2]]} ->
+ false; %% Password is not correct
+ {selected, [<<"password">>], []} ->
+ false; %% Account does not exist
+ {error, _Error} ->
+ false %% Typical error is that table doesn't exist
+ catch
+ _:_ ->
+ false %% Typical error is database not accessible
+ end
+ end
+ end
end.
-%% @spec (User, Server, Password, Digest, DigestGen) -> true | false | {error, Error}
-check_password(User, Server, Password, Digest,
+%% @spec (User, AuthzId, Server, Password, Digest, DigestGen) -> true | false | {error, Error}
+check_password(User, AuthzId, Server, Password, Digest,
DigestGen) ->
- LServer = jlib:nameprep(Server),
- LUser = jlib:nodeprep(User),
- if (LUser == error) or (LServer == error) ->
- false;
- (LUser == <<>>) or (LServer == <<>>) ->
- false;
- true ->
- case is_scrammed() of
- false ->
- Username = ejabberd_odbc:escape(LUser),
- try odbc_queries:get_password(LServer, Username) of
- %% Account exists, check if password is valid
- {selected, [<<"password">>], [[Passwd]]} ->
- DigRes = if Digest /= <<"">> ->
- Digest == DigestGen(Passwd);
- true -> false
- end,
- if DigRes -> true;
- true -> (Passwd == Password) and (Password /= <<"">>)
- end;
- {selected, [<<"password">>], []} ->
- false; %% Account does not exist
- {error, _Error} ->
- false %% Typical error is that table doesn't exist
- catch
- _:_ ->
- false %% Typical error is database not accessible
- end;
- true ->
- false
- end
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ LServer = jlib:nameprep(Server),
+ LUser = jlib:nodeprep(User),
+ if (LUser == error) or (LServer == error) ->
+ false;
+ (LUser == <<>>) or (LServer == <<>>) ->
+ false;
+ true ->
+ case is_scrammed() of
+ false ->
+ Username = ejabberd_odbc:escape(LUser),
+ try odbc_queries:get_password(LServer, Username) of
+ %% Account exists, check if password is valid
+ {selected, [<<"password">>], [[Passwd]]} ->
+ DigRes = if Digest /= <<"">> ->
+ Digest == DigestGen(Passwd);
+ true -> false
+ end,
+ if DigRes -> true;
+ true -> (Passwd == Password) and (Password /= <<"">>)
+ end;
+ {selected, [<<"password">>], []} ->
+ false; %% Account does not exist
+ {error, _Error} ->
+ false %% Typical error is that table doesn't exist
+ catch
+ _:_ ->
+ false %% Typical error is database not accessible
+ end;
+ true ->
+ false
+ end
+ end
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
@@ -352,7 +360,7 @@ remove_user(User, Server, Password) ->
true ->
case is_scrammed() of
true ->
- case check_password(User, Server, Password) of
+ case check_password(User, <<"">>, Server, Password) of
true ->
remove_user(User, Server),
ok;
diff --git a/src/ejabberd_auth_pam.erl b/src/ejabberd_auth_pam.erl
index f3fdf628..da893eb4 100644
--- a/src/ejabberd_auth_pam.erl
+++ b/src/ejabberd_auth_pam.erl
@@ -32,8 +32,8 @@
%%====================================================================
%% API
%%====================================================================
--export([start/1, set_password/3, check_password/3,
- check_password/5, try_register/3,
+-export([start/1, set_password/3, check_password/4,
+ check_password/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2, get_vh_registered_users_number/1,
get_vh_registered_users_number/2,
@@ -47,21 +47,25 @@ start(_Host) ->
set_password(_User, _Server, _Password) ->
{error, not_allowed}.
-check_password(User, Server, Password, _Digest,
+check_password(User, AuthzId, Server, Password, _Digest,
_DigestGen) ->
- check_password(User, Server, Password).
-
-check_password(User, Host, Password) ->
- Service = get_pam_service(Host),
- UserInfo = case get_pam_userinfotype(Host) of
- username -> User;
- jid -> <<User/binary, "@", Host/binary>>
- end,
- case catch epam:authenticate(Service, UserInfo,
- Password)
- of
- true -> true;
- _ -> false
+ check_password(User, AuthzId, Server, Password).
+
+check_password(User, AuthzId, Host, Password) ->
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ Service = get_pam_service(Host),
+ UserInfo = case get_pam_userinfotype(Host) of
+ username -> User;
+ jid -> <<User/binary, "@", Host/binary>>
+ end,
+ case catch epam:authenticate(Service, UserInfo,
+ Password)
+ of
+ true -> true;
+ _ -> false
+ end
end.
try_register(_User, _Server, _Password) ->
diff --git a/src/ejabberd_auth_riak.erl b/src/ejabberd_auth_riak.erl
index 3f3484c1..8c926f4b 100644
--- a/src/ejabberd_auth_riak.erl
+++ b/src/ejabberd_auth_riak.erl
@@ -30,8 +30,8 @@
-behaviour(ejabberd_auth).
%% External exports
--export([start/1, set_password/3, check_password/3,
- check_password/5, try_register/3,
+-export([start/1, set_password/3, check_password/4,
+ check_password/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
@@ -66,42 +66,50 @@ store_type() ->
passwd_schema() ->
{record_info(fields, passwd), #passwd{}}.
-check_password(User, Server, Password) ->
- LUser = jlib:nodeprep(User),
- LServer = jlib:nameprep(Server),
- case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
- {ok, #passwd{password = Password}} when is_binary(Password) ->
- Password /= <<"">>;
- {ok, #passwd{password = Scram}} when is_record(Scram, scram) ->
- is_password_scram_valid(Password, Scram);
- _ ->
- false
+check_password(User, AuthzId, Server, Password) ->
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
+ case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
+ {ok, #passwd{password = Password}} when is_binary(Password) ->
+ Password /= <<"">>;
+ {ok, #passwd{password = Scram}} when is_record(Scram, scram) ->
+ is_password_scram_valid(Password, Scram);
+ _ ->
+ false
+ end
end.
-check_password(User, Server, Password, Digest,
+check_password(User, AuthzId, Server, Password, Digest,
DigestGen) ->
- LUser = jlib:nodeprep(User),
- LServer = jlib:nameprep(Server),
- case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
- {ok, #passwd{password = Passwd}} when is_binary(Passwd) ->
- DigRes = if Digest /= <<"">> ->
- Digest == DigestGen(Passwd);
- true -> false
- end,
- if DigRes -> true;
- true -> (Passwd == Password) and (Password /= <<"">>)
- end;
- {ok, #passwd{password = Scram}}
- when is_record(Scram, scram) ->
- Passwd = jlib:decode_base64(Scram#scram.storedkey),
- DigRes = if Digest /= <<"">> ->
- Digest == DigestGen(Passwd);
- true -> false
- end,
- if DigRes -> true;
- true -> (Passwd == Password) and (Password /= <<"">>)
- end;
- _ -> false
+ if AuthzId /= <<>> andalso AuthzId /= User ->
+ false;
+ true ->
+ LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
+ case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
+ {ok, #passwd{password = Passwd}} when is_binary(Passwd) ->
+ DigRes = if Digest /= <<"">> ->
+ Digest == DigestGen(Passwd);
+ true -> false
+ end,
+ if DigRes -> true;
+ true -> (Passwd == Password) and (Password /= <<"">>)
+ end;
+ {ok, #passwd{password = Scram}}
+ when is_record(Scram, scram) ->
+ Passwd = jlib:decode_base64(Scram#scram.storedkey),
+ DigRes = if Digest /= <<"">> ->
+ Digest == DigestGen(Passwd);
+ true -> false
+ end,
+ if DigRes -> true;
+ true -> (Passwd == Password) and (Password /= <<"">>)
+ end;
+ _ -> false
+ end
end.
set_password(User, Server, Password) ->
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index f2d16e87..22e17bee 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -397,13 +397,13 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
ejabberd_auth:get_password_with_authmodule(
U, Server)
end,
- fun(U, P) ->
+ fun(U, AuthzId, P) ->
ejabberd_auth:check_password_with_authmodule(
- U, Server, P)
+ U, AuthzId, Server, P)
end,
- fun(U, P, D, DG) ->
+ fun(U, AuthzId, P, D, DG) ->
ejabberd_auth:check_password_with_authmodule(
- U, Server, P, D, DG)
+ U, AuthzId, Server, P, D, DG)
end),
Mechs =
case TLSEnabled or not TLSRequired of
@@ -635,7 +635,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
DGen = fun (PW) ->
p1_sha:sha(<<(StateData#state.streamid)/binary, PW/binary>>)
end,
- case ejabberd_auth:check_password_with_authmodule(U,
+ case ejabberd_auth:check_password_with_authmodule(U, U,
StateData#state.server,
P, D, DGen)
of
@@ -753,9 +753,7 @@ wait_for_feature_request({xmlstreamelement, El},
of
{ok, Props} ->
(StateData#state.sockmod):reset_stream(StateData#state.socket),
- %U = xml:get_attr_s(username, Props),
- U = proplists:get_value(username, Props, <<>>),
- %AuthModule = xml:get_attr_s(auth_module, Props),
+ U = identity(Props),
AuthModule = proplists:get_value(auth_module, Props, undefined),
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p from ~s",
@@ -906,9 +904,7 @@ wait_for_sasl_response({xmlstreamelement, El},
{ok, Props} ->
catch
(StateData#state.sockmod):reset_stream(StateData#state.socket),
-% U = xml:get_attr_s(username, Props),
- U = proplists:get_value(username, Props, <<>>),
-% AuthModule = xml:get_attr_s(auth_module, Props),
+ U = identity(Props),
AuthModule = proplists:get_value(auth_module, Props, <<>>),
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p from ~s",
@@ -929,9 +925,7 @@ wait_for_sasl_response({xmlstreamelement, El},
user = U});
{ok, Props, ServerOut} ->
(StateData#state.sockmod):reset_stream(StateData#state.socket),
-% U = xml:get_attr_s(username, Props),
- U = proplists:get_value(username, Props, <<>>),
-% AuthModule = xml:get_attr_s(auth_module, Props),
+ U = identity(Props),
AuthModule = proplists:get_value(auth_module, Props, undefined),
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p from ~s",
@@ -3126,3 +3120,9 @@ pack_string(String, Pack) ->
transform_listen_option(Opt, Opts) ->
[Opt|Opts].
+
+identity(Props) ->
+ case proplists:get_value(authzid, Props, <<>>) of
+ <<>> -> proplists:get_value(username, Props, <<>>);
+ AuthzId -> AuthzId
+ end.
diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl
index a4f38e83..ca40d5dc 100644
--- a/src/ejabberd_commands.erl
+++ b/src/ejabberd_commands.erl
@@ -397,7 +397,7 @@ check_auth(noauth) ->
no_auth_provided;
check_auth({User, Server, Password}) ->
%% Check the account exists and password is valid
- case ejabberd_auth:check_password(User, Server, Password) of
+ case ejabberd_auth:check_password(User, <<"">>, Server, Password) of
true -> {ok, User, Server};
_ -> throw({error, invalid_account_data})
end.
diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl
index 29ecb734..7cf15210 100644
--- a/src/ejabberd_web_admin.erl
+++ b/src/ejabberd_web_admin.erl
@@ -263,7 +263,7 @@ get_auth_admin(Auth, HostHTTP, RPath, Method) ->
get_auth_account(HostOfRule, AccessRule, User, Server,
Pass) ->
- case ejabberd_auth:check_password(User, Server, Pass) of
+ case ejabberd_auth:check_password(User, <<"">>, Server, Pass) of
true ->
case is_acl_match(HostOfRule, AccessRule,
jlib:make_jid(User, Server, <<"">>))
diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl
index 663fbf72..db894de7 100644
--- a/src/mod_proxy65_stream.erl
+++ b/src/mod_proxy65_stream.erl
@@ -154,7 +154,7 @@ wait_for_auth(Packet,
#state{socket = Socket, host = Host} = StateData) ->
case mod_proxy65_lib:unpack_auth_request(Packet) of
{User, Pass} ->
- Result = ejabberd_auth:check_password(User, Host, Pass),
+ Result = ejabberd_auth:check_password(User, <<"">>, Host, Pass),
gen_tcp:send(Socket,
mod_proxy65_lib:make_auth_reply(Result)),
case Result of
diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl
index b9f799b4..b415d85e 100644
--- a/src/mod_register_web.erl
+++ b/src/mod_register_web.erl
@@ -437,7 +437,7 @@ check_account_exists(Username, Host) ->
end.
check_password(Username, Host, Password) ->
- case ejabberd_auth:check_password(Username, Host,
+ case ejabberd_auth:check_password(Username, <<"">>, Host,
Password)
of
true -> password_correct;