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.
This commit is contained in:
Ben Langfeld 2015-04-08 22:21:09 -03:00
parent d9814709e2
commit 917d48f30b
16 changed files with 305 additions and 260 deletions

View File

@ -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">>};

View File

@ -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]),

View File

@ -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.

View File

@ -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) ->

View File

@ -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,

View File

@ -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}

View File

@ -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()) ->

View File

@ -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),

View File

@ -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;

View File

@ -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, AuthzId, 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, 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) ->

View File

@ -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) ->

View File

@ -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.

View File

@ -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.

View File

@ -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, <<"">>))

View File

@ -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

View File

@ -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;