Update to work with ejabberd 15.06

This commit is contained in:
Badlop 2015-06-26 17:52:51 +02:00
parent db91c97614
commit 6d655af0c4
2 changed files with 52 additions and 31 deletions

View File

@ -10,6 +10,8 @@
-behaviour(ejabberd_gen_auth).
-behaviour(ejabberd_config).
%% External exports
-export([start/1,
set_password/3,
@ -23,30 +25,34 @@
get_vh_registered_users_number/2,
get_password/2,
get_password_s/2,
does_user_exist/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0,
store_type/1,
login/2,
get_password/3,
opt_type/1,
stop/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
opt_type(auth_opts) -> fun (V) -> V end;
opt_type(_) -> [auth_opts].
-spec start(binary()) -> ok.
start(Host) ->
AuthOpts = ejabberd_config:get_local_option(auth_opts, Host),
AuthOpts = ejabberd_config:get_option({auth_opts, Host}, fun(V) -> V end),
{_, AuthHost} = lists:keyfind(host, 1, AuthOpts),
PoolSize = proplists:get_value(connection_pool_size, AuthOpts, 10),
Opts = proplists:get_value(connection_opts, AuthOpts, []),
ChildMods = [fusco],
ChildMFA = {fusco, start_link, [AuthHost, Opts]},
ChildMFA = {fusco, start_link, [binary_to_list(AuthHost), Opts]},
{ok, _} = supervisor:start_child(ejabberd_sup,
{{ejabberd_auth_http_sup, Host},
@ -61,14 +67,14 @@ plain_password_required() ->
-spec store_type(binary()) -> plain | scram.
store_type(Server) ->
case scram:enabled(Server) of
case scram2:enabled(Server) of
false -> plain;
true -> scram
end.
-spec check_password(ejabberd:luser(), ejabberd:lserver(), binary()) -> boolean().
check_password(LUser, LServer, Password) ->
case scram:enabled(LServer) of
case scram2:enabled(LServer) of
false ->
case make_req(get, <<"check_password">>, LUser, LServer, Password) of
{ok, <<"true">>} -> true;
@ -84,24 +90,39 @@ check_password(LUser, LServer, Password, Digest, DigestGen) ->
{error, _} ->
false;
{ok, GotPasswd} ->
case scram:enabled(LServer) of
case scram2:enabled(LServer) of
true ->
case scram:deserialize(GotPasswd) of
case scram2:deserialize(GotPasswd) of
{ok, #scram{} = Scram} ->
scram:check_digest(Scram, Digest, DigestGen, Password);
scram2:check_digest(Scram, Digest, DigestGen, Password);
_ ->
false
end;
false ->
ejabberd_auth:check_digest(Digest, DigestGen, Password, GotPasswd)
check_digest(Digest, DigestGen, Password, GotPasswd)
end
end.
-spec check_digest(binary(), fun(), binary(), binary()) -> boolean().
check_digest(Digest, DigestGen, Password, Passwd) ->
DigRes = if
Digest /= <<>> ->
Digest == DigestGen(Passwd);
true ->
false
end,
if DigRes ->
true;
true ->
(Passwd == Password) and (Password /= <<>>)
end.
-spec set_password(ejabberd:luser(), ejabberd:lserver(), binary()) -> ok | {error, term()}.
set_password(LUser, LServer, Password) ->
PasswordFinal = case scram:enabled(LServer) of
true -> scram:serialize(scram:password_to_scram(
Password, scram:iterations(LServer)));
PasswordFinal = case scram2:enabled(LServer) of
true -> scram2:serialize(scram2:password_to_scram(
Password, scram2:iterations(LServer)));
false -> Password
end,
case make_req(post, <<"set_password">>, LUser, LServer, PasswordFinal) of
@ -111,9 +132,9 @@ set_password(LUser, LServer, Password) ->
-spec try_register(ejabberd:luser(), ejabberd:lserver(), binary()) -> {atomic, ok | exists} | {error, term()}.
try_register(LUser, LServer, Password) ->
PasswordFinal = case scram:enabled(LServer) of
true -> scram:serialize(scram:password_to_scram(
Password, scram:iterations(LServer)));
PasswordFinal = case scram2:enabled(LServer) of
true -> scram2:serialize(scram2:password_to_scram(
Password, scram2:iterations(LServer)));
false -> Password
end,
case make_req(post, <<"register">>, LUser, LServer, PasswordFinal) of
@ -149,11 +170,11 @@ get_password(LUser, LServer) ->
{error, _} ->
false;
{ok, Password} ->
case scram:enabled(LServer) of
case scram2:enabled(LServer) of
true ->
case scram:deserialize(Password) of
case scram2:deserialize(Password) of
{ok, #scram{} = Scram} ->
scram:scram_to_tuple(Scram);
scram2:scram_to_tuple(Scram);
_ ->
false
end;
@ -169,8 +190,8 @@ get_password_s(User, Server) ->
_ -> <<>>
end.
-spec does_user_exist(ejabberd:luser(), ejabberd:lserver()) -> boolean().
does_user_exist(LUser, LServer) ->
-spec is_user_exists(ejabberd:luser(), ejabberd:lserver()) -> boolean().
is_user_exists(LUser, LServer) ->
case make_req(get, <<"user_exists">>, LUser, LServer, <<"">>) of
{ok, <<"true">>} -> true;
_ -> false
@ -182,7 +203,7 @@ remove_user(LUser, LServer) ->
-spec remove_user(ejabberd:luser(), ejabberd:lserver(), binary()) -> ok | not_exists | not_allowed | bad_request.
remove_user(LUser, LServer, Password) ->
case scram:enabled(LServer) of
case scram2:enabled(LServer) of
false ->
remove_user_req(LUser, LServer, Password, <<"remove_user_validate">>);
true ->
@ -215,13 +236,13 @@ remove_user_req(LUser, LServer, Password, Method) ->
make_req(_, _, LUser, LServer, _) when LUser == error orelse LServer == error ->
{error, {prep_failed, LUser, LServer}};
make_req(Method, Path, LUser, LServer, Password) ->
AuthOpts = ejabberd_config:get_local_option(auth_opts, LServer),
AuthOpts = ejabberd_config:get_option({auth_opts, LServer}, fun(V) -> V end),
BasicAuth = case lists:keyfind(basic_auth, 1, AuthOpts) of
{_, BasicAuth0} -> BasicAuth0;
_ -> ""
end,
PathPrefix = case lists:keyfind(path_prefix, 1, AuthOpts) of
{_, Prefix} -> ejabberd_binary:string_to_binary(Prefix);
{_, Prefix} -> Prefix;
false -> <<"/">>
end,
BasicAuth64 = base64:encode(BasicAuth),
@ -268,9 +289,9 @@ existing_pool_name(Host) ->
verify_scram_password(LUser, LServer, Password) ->
case make_req(get, <<"get_password">>, LUser, LServer, <<"">>) of
{ok, RawPassword} ->
case scram:deserialize(RawPassword) of
case scram2:deserialize(RawPassword) of
{ok, #scram{} = ScramRecord} ->
{ok, scram:check_password(Password, ScramRecord)};
{ok, scram2:check_password(Password, ScramRecord)};
_ ->
{error, bad_request}
end;

View File

@ -24,11 +24,12 @@
%%%
%%%----------------------------------------------------------------------
-module(scram).
-module(scram2).
-author('stephen.roettger@googlemail.com').
-include("ejabberd.hrl").
-include("logger.hrl").
%% External exports
%% ejabberd doesn't implement SASLPREP, so we use the similar RESOURCEPREP instead
@ -56,7 +57,6 @@
-export([scram_to_tuple/1]).
-define(SALT_LENGTH, 16).
-define(SCRAM_DEFAULT_ITERATION_COUNT, 4096).
-define(SCRAM_SERIAL_PREFIX, "==SCRAM==,").
-spec salted_password(binary(), binary(), non_neg_integer()) -> binary().
@ -106,7 +106,7 @@ hi_round(Password, UPrev, IterationCount) ->
enabled(Host) ->
case ejabberd_config:get_local_option(auth_opts, Host) of
case ejabberd_config:get_option({auth_opts, Host}, fun(V) -> V end) of
undefined ->
false;
AuthOpts ->
@ -116,7 +116,7 @@ enabled(Host) ->
iterations() -> ?SCRAM_DEFAULT_ITERATION_COUNT.
iterations(Host) ->
case ejabberd_config:get_local_option(auth_opts, Host) of
case ejabberd_config:get_option({auth_opts, Host}, fun(V) -> V end) of
undefined ->
iterations();
AuthOpts ->
@ -134,7 +134,7 @@ password_to_scram(#scram{} = Password, _) ->
password_to_scram(Password, IterationCount) ->
Salt = crypto:rand_bytes(?SALT_LENGTH),
SaltedPassword = salted_password(Password, Salt, IterationCount),
StoredKey = stored_key(scram:client_key(SaltedPassword)),
StoredKey = stored_key(scram2:client_key(SaltedPassword)),
ServerKey = server_key(SaltedPassword),
#scram{storedkey = base64:encode(StoredKey),
serverkey = base64:encode(ServerKey),