]> granicus.if.org Git - ejabberd/commitdiff
Use cache for authentication backends
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 11 May 2017 11:37:21 +0000 (14:37 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 11 May 2017 11:37:21 +0000 (14:37 +0300)
The commit introduces the following API incompatibilities:

In ejabberd_auth.erl:
* dirty_get_registered_users/0 is renamed to get_users/0
* get_vh_registered_users/1 is renamed to get_users/1
* get_vh_registered_users/2 is renamed to get_users/2
* get_vh_registered_users_number/1 is renamed to count_users/1
* get_vh_registered_users_number/2 is renamed to count_users/2

In ejabberd_auth callbacks
* plain_password_required/0 is replaced by plain_password_required/1
  where the argument is a virtual host
* store_type/0 is replaced by store_type/1 where the argument is
  a virtual host
* set_password/3 is now an optional callback
* remove_user/3 callback is no longer needed
* remove_user/2 now should return `ok | {error, atom()}`
* is_user_exists/2 now must only be implemented for backends
  with `external` store type
* check_password/6 is no longer needed
* check_password/4 now must only be implemented for backends
  with `external` store type
* try_register/3 is now an optional callback and should return
  `ok | {error, atom()}`
* dirty_get_registered_users/0 is no longer needed
* get_vh_registered_users/1 is no longer needed
* get_vh_registered_users/2 is renamed to get_users/2
* get_vh_registered_users_number/1 is no longer needed
* get_vh_registered_users_number/2 is renamed to count_users/2
* get_password_s/2 is no longer needed
* get_password/2 now must only be implemented for backends with
  `plain` or `scram` store type

Additionally, the commit introduces two new callbacks:
* use_cache/1 where the argument is a virtual host
* cache_nodes/1 where the argument is a virtual host

New options are also introduced: `auth_use_cache`, `auth_cache_missed`,
`auth_cache_life_time` and `auth_cache_size`.

23 files changed:
rebar.config
src/cyrsasl_scram.erl
src/ejabberd_admin.erl
src/ejabberd_auth.erl
src/ejabberd_auth_anonymous.erl
src/ejabberd_auth_external.erl
src/ejabberd_auth_ldap.erl
src/ejabberd_auth_mnesia.erl
src/ejabberd_auth_pam.erl
src/ejabberd_auth_riak.erl
src/ejabberd_auth_sql.erl
src/ejabberd_piefxis.erl
src/ejabberd_web_admin.erl
src/extauth.erl
src/mod_admin_extra.erl
src/mod_announce.erl
src/mod_configure.erl
src/mod_register.erl
src/mod_register_web.erl
src/mod_shared_roster.erl
src/mod_stats.erl
src/prosody2ejabberd.erl
test/suite.erl

index b553931e638e25d38dfa97d8f1788bf052c97b93..7def98c7951fc7b8809b77b863a8b718706c3a77 100644 (file)
@@ -20,7 +20,7 @@
 
 {deps, [{lager, ".*", {git, "https://github.com/basho/lager", {tag, "3.2.1"}}},
         {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", "470539a"}},
-        {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", "f31d039"}},
+        {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", "51eee22"}},
         {fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.11"}}},
         {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.8"}}},
         {fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.21"}}},
index 8cbc821c77e28169cf264e355c98db0224aa883b..b496be0a4a7a096ebf827b63105bf266154faac8 100644 (file)
@@ -111,7 +111,11 @@ mech_step(#state{step = 2} = State, ClientIn) ->
                                  {error, saslprep_failed, UserName};
                               true ->
                                  {StoredKey, ServerKey, Salt, IterationCount} =
-                                     if is_tuple(Pass) -> Pass;
+                                     if is_record(Pass, scram) ->
+                                             {misc:decode_base64(Pass#scram.storedkey),
+                                              misc:decode_base64(Pass#scram.serverkey),
+                                              misc:decode_base64(Pass#scram.salt),
+                                              Pass#scram.iterationcount};
                                         true ->
                                             TempSalt =
                                                 randoms:bytes(?SALT_LENGTH),
index a615b2fee6cc4124b5c53dee3fb54af137fed58b..c0429fb0c5a583d3bd9de00c6b580da32c654a64 100644 (file)
@@ -478,9 +478,9 @@ update_module(ModuleNameString) ->
 
 register(User, Host, Password) ->
     case ejabberd_auth:try_register(User, Host, Password) of
-       {atomic, ok} ->
+       ok ->
            {ok, io_lib:format("User ~s@~s successfully registered", [User, Host])};
-       {atomic, exists} ->
+       {error, exists} ->
            Msg = io_lib:format("User ~s@~s already registered", [User, Host]),
            {error, conflict, 10090, Msg};
        {error, Reason} ->
@@ -494,7 +494,7 @@ unregister(User, Host) ->
     {ok, ""}.
 
 registered_users(Host) ->
-    Users = ejabberd_auth:get_vh_registered_users(Host),
+    Users = ejabberd_auth:get_users(Host),
     SUsers = lists:sort(Users),
     lists:map(fun({U, _S}) -> U end, SUsers).
 
index 9751142a5a508751e7dacb3f5f39eb63d2fd01a5..23ed0eeae214f739a7f8a9720dbbad91d48e137c 100644 (file)
@@ -22,9 +22,6 @@
 %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 %%%
 %%%----------------------------------------------------------------------
-
-%% TODO: Use the functions in ejabberd auth to add and remove users.
-
 -module(ejabberd_auth).
 
 -behaviour(gen_server).
         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_info/0,
-        get_vh_registered_users_number/1, import/5, import_start/2,
-        get_vh_registered_users_number/2, get_password/2,
+        get_users/0, get_users/1, password_to_scram/1,
+        get_users/2, export/1, import_info/0,
+        count_users/1, import/5, import_start/2,
+        count_users/2, get_password/2,
         get_password_s/2, get_password_with_authmodule/2,
         is_user_exists/2, is_user_exists_in_other_modules/3,
         remove_user/2, remove_user/3, plain_password_required/1,
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
+-define(AUTH_CACHE, auth_cache).
+-define(SALT_LENGTH, 16).
+
 -record(state, {host_modules = #{} :: map()}).
 
--type scrammed_password() :: {binary(), binary(), binary(), non_neg_integer()}.
--type password() :: binary() | scrammed_password().
+-type password() :: binary() | #scram{}.
+-type digest_fun() :: fun((binary()) -> binary()).
 -export_type([password/0]).
 
 %%%----------------------------------------------------------------------
 
 -callback start(binary()) -> any().
 -callback stop(binary()) -> any().
--callback plain_password_required() -> boolean().
--callback store_type() -> plain | external | scram.
+-callback plain_password_required(binary()) -> boolean().
+-callback store_type(binary()) -> plain | external | scram.
 -callback set_password(binary(), binary(), binary()) -> ok | {error, atom()}.
--callback remove_user(binary(), binary()) -> any().
--callback remove_user(binary(), binary(), binary()) -> any().
+-callback remove_user(binary(), binary()) -> ok | {error, any()}.
 -callback is_user_exists(binary(), binary()) -> boolean() | {error, atom()}.
 -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()}.
--callback dirty_get_registered_users() -> [{binary(), binary()}].
--callback get_vh_registered_users(binary()) -> [{binary(), binary()}].
--callback get_vh_registered_users(binary(), opts()) -> [{binary(), binary()}].
--callback get_vh_registered_users_number(binary()) -> number().
--callback get_vh_registered_users_number(binary(), opts()) -> number().
--callback get_password(binary(), binary()) -> false | password().
--callback get_password_s(binary(), binary()) -> password().
+-callback try_register(binary(), binary(), password()) -> ok | {error, atom()}.
+-callback get_users(binary(), opts()) -> [{binary(), binary()}].
+-callback count_users(binary(), opts()) -> number().
+-callback get_password(binary(), binary()) -> {ok, password()} | error.
+-callback use_cache(binary()) -> boolean().
+-callback cache_nodes(binary()) -> boolean().
+
+-optional_callbacks([set_password/3,
+                    remove_user/2,
+                    is_user_exists/2,
+                    check_password/4,
+                    try_register/3,
+                    get_users/2,
+                    count_users/2,
+                    get_password/2,
+                    use_cache/1,
+                    cache_nodes/1]).
 
 -spec start_link() -> {ok, pid()} | {error, any()}.
 start_link() ->
@@ -99,9 +104,13 @@ init([]) ->
     HostModules = lists:foldl(
                    fun(Host, Acc) ->
                            Modules = auth_modules(Host),
-                           start(Host, Modules),
                            maps:put(Host, Modules, Acc)
                    end, #{}, ?MYHOSTS),
+    lists:foreach(
+      fun({Host, Modules}) ->
+             start(Host, Modules)
+      end, maps:to_list(HostModules)),
+    init_cache(HostModules),
     {ok, #state{host_modules = HostModules}}.
 
 handle_call(_Request, _From, State) ->
@@ -112,11 +121,13 @@ handle_cast({host_up, Host}, #state{host_modules = HostModules} = State) ->
     Modules = auth_modules(Host),
     start(Host, Modules),
     NewHostModules = maps:put(Host, Modules, HostModules),
+    init_cache(NewHostModules),
     {noreply, State#state{host_modules = NewHostModules}};
 handle_cast({host_down, Host}, #state{host_modules = HostModules} = State) ->
     Modules = maps:get(Host, HostModules, []),
     stop(Host, Modules),
     NewHostModules = maps:remove(Host, HostModules),
+    init_cache(NewHostModules),
     {noreply, State#state{host_modules = NewHostModules}};
 handle_cast(config_reloaded, #state{host_modules = HostModules} = State) ->
     NewHostModules = lists:foldl(
@@ -127,6 +138,7 @@ handle_cast(config_reloaded, #state{host_modules = HostModules} = State) ->
                               stop(Host, OldModules -- NewModules),
                               maps:put(Host, NewModules, Acc)
                       end, HostModules, ?MYHOSTS),
+    init_cache(NewHostModules),
     {noreply, State#state{host_modules = NewHostModules}};
 handle_cast(Msg, State) ->
     ?WARNING_MSG("unexpected cast: ~p", [Msg]),
@@ -162,306 +174,266 @@ host_down(Host) ->
 config_reloaded() ->
     gen_server:cast(?MODULE, config_reloaded).
 
+-spec plain_password_required(binary()) -> boolean().
 plain_password_required(Server) ->
-    lists:any(fun (M) -> M:plain_password_required() end,
+    lists:any(fun (M) -> M:plain_password_required(Server) end,
              auth_modules(Server)).
 
+-spec store_type(binary()) -> plain | scram | external.
 store_type(Server) ->
-%% @doc Check if the user and password can login in server.
-%% @spec (User::string(), Server::string(), Password::string()) ->
-%%     true | false
-    lists:foldl(fun (_, external) -> external;
-                   (M, scram) ->
-                       case M:store_type() of
-                         external -> external;
-                         _Else -> scram
-                       end;
-                   (M, plain) -> M:store_type()
-               end,
-               plain, auth_modules(Server)).
+    lists:foldl(
+      fun(_, external) -> external;
+        (M, scram) ->
+             case M:store_type(Server) of
+                 external -> external;
+                 _ -> scram
+             end;
+        (M, plain) ->
+             M:store_type(Server)
+      end, plain, auth_modules(Server)).
 
 -spec check_password(binary(), binary(), binary(), binary()) -> boolean().
-
 check_password(User, AuthzId, Server, Password) ->
-    case check_password_with_authmodule(User, AuthzId, Server,
-                                       Password)
-       of
-      {true, _AuthModule} -> true;
-      false -> false
-    end.
+    check_password(User, AuthzId, Server, Password, <<"">>, undefined).
 
-%% @doc Check if the user and password can login in server.
-%% @spec (User::string(), AuthzId::string(), Server::string(), Password::string(),
-%%        Digest::string(), DigestGen::function()) ->
-%%     true | false
 -spec check_password(binary(), binary(), binary(), binary(), binary(),
-                     fun((binary()) -> binary())) -> boolean().
-                                 
-check_password(User, AuthzId, Server, Password, Digest,
-              DigestGen) ->
-    case check_password_with_authmodule(User, AuthzId, Server,
-                                       Password, Digest, DigestGen)
-       of
-      {true, _AuthModule} -> true;
-      false -> false
+                     digest_fun() | undefined) -> boolean().
+check_password(User, AuthzId, Server, Password, Digest, DigestGen) ->
+    case check_password_with_authmodule(
+          User, AuthzId, Server, Password, Digest, DigestGen) of
+       {true, _AuthModule} -> true;
+       false -> false
     end.
 
-%% @doc Check if the user and password can login in server.
-%% 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(), AuthzId::string(), Server::string(), Password::string()) ->
-%%     {true, AuthModule} | false
-%% where
-%%   AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external
-%%                 | ejabberd_auth_mnesia | ejabberd_auth_ldap
-%%                 | ejabberd_auth_sql | ejabberd_auth_pam | ejabberd_auth_riak
--spec check_password_with_authmodule(binary(), binary(), binary(), binary()) -> false |
-                                                                      {true, atom()}.
-
-check_password_with_authmodule(User, AuthzId, Server,
-                              Password) ->
-    check_password_loop(auth_modules(Server),
-                       [User, AuthzId, Server, Password]).
-
--spec check_password_with_authmodule(binary(), binary(), binary(), binary(), binary(),
-                                     fun((binary()) -> binary())) -> false |
-                                                                     {true, atom()}.
-
-check_password_with_authmodule(User, AuthzId, Server, Password,
-                              Digest, DigestGen) ->
-    check_password_loop(auth_modules(Server),
-                       [User, AuthzId, Server, Password, Digest, DigestGen]).
-
-check_password_loop([], _Args) -> false;
-check_password_loop([AuthModule | AuthModules], Args) ->
-    case apply(AuthModule, check_password, Args) of
-      true -> {true, AuthModule};
-      false -> check_password_loop(AuthModules, Args)
+-spec check_password_with_authmodule(binary(), binary(),
+                                    binary(), binary()) -> false | {true, atom()}.
+check_password_with_authmodule(User, AuthzId, Server, Password) ->
+    check_password_with_authmodule(
+      User, AuthzId, Server, Password, <<"">>, undefined).
+
+-spec check_password_with_authmodule(
+       binary(), binary(), binary(), binary(), binary(),
+       digest_fun() | undefined) -> false | {true, atom()}.
+check_password_with_authmodule(User, AuthzId, Server, Password, Digest, DigestGen) ->
+    case validate_credentials(User, Server) of
+       {ok, LUser, LServer} ->
+           lists:foldl(
+             fun(Mod, false) ->
+                     case db_check_password(
+                            LUser, AuthzId, LServer, Password,
+                            Digest, DigestGen, Mod) of
+                         true -> {true, Mod};
+                         false -> false
+                     end;
+                (_, Acc) ->
+                     Acc
+             end, false, auth_modules(LServer));
+       _ ->
+           false
     end.
 
--spec set_password(binary(), binary(), binary()) -> ok |
-                                                    {error, atom()}.
-
-%% @spec (User::string(), Server::string(), Password::string()) ->
-%%       ok | {error, ErrorType}
-%% where ErrorType = empty_password | not_allowed | invalid_jid
-set_password(_User, _Server, <<"">>) ->
-    {error, empty_password};
+-spec set_password(binary(), binary(), password()) -> ok | {error, atom()}.
 set_password(User, Server, Password) ->
-%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, not_allowed}
-    lists:foldl(fun (M, {error, _}) ->
-                       M:set_password(User, Server, Password);
-                   (_M, Res) -> Res
-               end,
-               {error, not_allowed}, auth_modules(Server)).
-
--spec try_register(binary(), binary(), binary()) -> {atomic, atom()} |
-                                                    {error, atom()}.
-
-try_register(_User, _Server, <<"">>) ->
-    {error, not_allowed};
+    case validate_credentials(User, Server, Password) of
+       {ok, LUser, LServer} ->
+           lists:foldl(
+             fun(M, {error, _}) ->
+                     db_set_password(LUser, LServer, Password, M);
+                (_, ok) ->
+                     ok
+             end, {error, not_allowed}, auth_modules(LServer));
+       Err ->
+           Err
+    end.
+
+-spec try_register(binary(), binary(), password()) -> ok | {error, atom()}.
 try_register(User, Server, Password) ->
-    case is_user_exists(User, Server) of
-      true -> {atomic, exists};
-      false ->
-         LServer = jid:nameprep(Server),
-         case ejabberd_router:is_my_host(LServer) of
-           true ->
-               Res = lists:foldl(fun (_M, {atomic, ok} = Res) -> Res;
-                                     (M, _) ->
-                                         M:try_register(User, Server, Password)
-                                 end,
-                                 {error, not_allowed}, auth_modules(Server)),
-               case Res of
-                 {atomic, ok} ->
-                     ejabberd_hooks:run(register_user, Server,
-                                        [User, Server]),
-                     {atomic, ok};
-                 _ -> Res
-               end;
-           false -> {error, not_allowed}
-         end
+    case validate_credentials(User, Server, Password) of
+       {ok, LUser, LServer} ->
+           case is_user_exists(LUser, LServer) of
+               true ->
+                   {error, exists};
+               false ->
+                   case ejabberd_router:is_my_host(LServer) of
+                       true ->
+                           case lists:foldl(
+                                  fun(_, ok) ->
+                                          ok;
+                                     (Mod, _) ->
+                                          db_try_register(
+                                            User, Server, Password, Mod)
+                                  end, {error, not_allowed},
+                                  auth_modules(LServer)) of
+                               ok ->
+                                   ejabberd_hooks:run(
+                                     register_user, Server, [User, Server]);
+                               {error, _} = Err ->
+                                   Err
+                           end;
+                       false ->
+                           {error, not_allowed}
+                   end
+           end;
+       Err ->
+           Err
     end.
 
-%% Registered users list do not include anonymous users logged
--spec dirty_get_registered_users() -> [{binary(), binary()}].
-
-dirty_get_registered_users() ->
-    lists:flatmap(fun (M) -> M:dirty_get_registered_users()
-                 end,
-                 auth_modules()).
-
--spec get_vh_registered_users(binary()) -> [{binary(), binary()}].
-
-%% Registered users list do not include anonymous users logged
-get_vh_registered_users(Server) ->
-    lists:flatmap(fun (M) ->
-                         M:get_vh_registered_users(Server)
-                 end,
-                 auth_modules(Server)).
-
--spec get_vh_registered_users(binary(), opts()) -> [{binary(), binary()}].
-
-get_vh_registered_users(Server, Opts) ->
-    lists:flatmap(fun (M) ->
-                         case erlang:function_exported(M,
-                                                       get_vh_registered_users,
-                                                       2)
-                             of
-                           true -> M:get_vh_registered_users(Server, Opts);
-                           false -> M:get_vh_registered_users(Server)
-                         end
-                 end,
-                 auth_modules(Server)).
-
-get_vh_registered_users_number(Server) ->
-    lists:sum(lists:map(fun (M) ->
-                               case erlang:function_exported(M,
-                                                             get_vh_registered_users_number,
-                                                             1)
-                                   of
-                                 true ->
-                                     M:get_vh_registered_users_number(Server);
-                                 false ->
-                                     length(M:get_vh_registered_users(Server))
-                               end
-                       end,
-                       auth_modules(Server))).
-
--spec get_vh_registered_users_number(binary(), opts()) -> number().
-
-get_vh_registered_users_number(Server, Opts) ->
-%% @doc Get the password of the user.
-%% @spec (User::string(), Server::string()) -> Password::string()
-    lists:sum(lists:map(fun (M) ->
-                               case erlang:function_exported(M,
-                                                             get_vh_registered_users_number,
-                                                             2)
-                                   of
-                                 true ->
-                                     M:get_vh_registered_users_number(Server,
-                                                                      Opts);
-                                 false ->
-                                     length(M:get_vh_registered_users(Server))
-                               end
-                       end,
-                       auth_modules(Server))).
+-spec get_users() -> [{binary(), binary()}].
+get_users() ->
+    lists:flatmap(
+      fun({Host, Mod}) ->
+             db_get_users(Host, [], Mod)
+      end, auth_modules()).
+
+-spec get_users(binary()) -> [{binary(), binary()}].
+get_users(Server) ->
+    get_users(Server, []).
+
+-spec get_users(binary(), opts()) -> [{binary(), binary()}].
+get_users(Server, Opts) ->
+    case jid:nameprep(Server) of
+       error -> [];
+       LServer ->
+           lists:flatmap(
+             fun(M) -> db_get_users(LServer, Opts, M) end,
+             auth_modules(LServer))
+    end.
 
--spec get_password(binary(), binary()) -> false | password().
+-spec count_users(binary()) -> non_neg_integer().
+count_users(Server) ->
+    count_users(Server, []).
+
+-spec count_users(binary(), opts()) -> non_neg_integer().
+count_users(Server, Opts) ->
+    case jid:nameprep(Server) of
+       error -> 0;
+       LServer ->
+           lists:sum(
+             lists:map(
+               fun(M) -> db_count_users(LServer, Opts, M) end,
+               auth_modules(LServer)))
+    end.
 
+-spec get_password(binary(), binary()) -> false | password().
 get_password(User, Server) ->
-    lists:foldl(fun (M, false) ->
-                       M:get_password(User, Server);
-                   (_M, Password) -> Password
-               end,
-               false, auth_modules(Server)).
+    case validate_credentials(User, Server) of
+       {ok, LUser, LServer} ->
+           case lists:foldl(
+                  fun(M, error) -> db_get_password(LUser, LServer, M);
+                     (_M, Acc) -> Acc
+                  end, error, auth_modules(LServer)) of
+               {ok, Password} ->
+                   Password;
+               error ->
+                   false
+           end;
+       _ ->
+           false
+    end.
 
 -spec get_password_s(binary(), binary()) -> password().
-
 get_password_s(User, Server) ->
     case get_password(User, Server) of
       false -> <<"">>;
       Password -> Password
     end.
 
-%% @doc Get the password of the user and the auth module.
-%% @spec (User::string(), Server::string()) ->
-%%     {Password::string(), AuthModule::atom()} | {false, none}
 -spec get_password_with_authmodule(binary(), binary()) -> {false | password(), module()}.
-
 get_password_with_authmodule(User, Server) ->
-%% Returns true if the user exists in the DB or if an anonymous user is logged
-%% under the given name
-    lists:foldl(fun (M, {false, _}) ->
-                       {M:get_password(User, Server), M};
-                   (_M, {Password, AuthModule}) -> {Password, AuthModule}
-               end,
-               {false, none}, auth_modules(Server)).
+    case validate_credentials(User, Server) of
+       {ok, LUser, LServer} ->
+           case lists:foldl(
+                  fun(M, {error, _}) ->
+                          {db_get_password(LUser, LServer, M), M};
+                     (_M, Acc) ->
+                          Acc
+                  end, {error, undefined}, auth_modules(LServer)) of
+               {{ok, Password}, Module} ->
+                   {Password, Module};
+               {error, Module} ->
+                   {false, Module}
+           end;
+       _ ->
+           {false, undefined}
+    end.
 
 -spec is_user_exists(binary(), binary()) -> boolean().
-
 is_user_exists(_User, <<"">>) ->
     false;
-
 is_user_exists(User, Server) ->
-%% Check if the user exists in all authentications module except the module
-%% passed as parameter
-%% @spec (Module::atom(), User, Server) -> true | false | maybe
-    lists:any(fun (M) ->
-                     case M:is_user_exists(User, Server) of
-                       {error, Error} ->
-                           ?ERROR_MSG("The authentication module ~p returned "
-                                      "an error~nwhen checking user ~p in server "
-                                      "~p~nError message: ~p",
-                                      [M, User, Server, Error]),
-                           false;
-                       Else -> Else
+    case validate_credentials(User, Server) of
+       {ok, LUser, LServer} ->
+           lists:any(
+             fun(M) ->
+                     case db_is_user_exists(LUser, LServer, M) of
+                         {error, _} ->
+                             false;
+                         Else ->
+                             Else
                      end
-             end,
-             auth_modules(Server)).
+             end, auth_modules(LServer));
+       _ ->
+           false
+    end.
 
 -spec is_user_exists_in_other_modules(atom(), binary(), binary()) -> boolean() | maybe.
-
 is_user_exists_in_other_modules(Module, User, Server) ->
-    is_user_exists_in_other_modules_loop(auth_modules(Server)
-                                          -- [Module],
-                                        User, Server).
+    is_user_exists_in_other_modules_loop(
+      auth_modules(Server) -- [Module], User, Server).
 
-is_user_exists_in_other_modules_loop([], _User,
-                                    _Server) ->
+is_user_exists_in_other_modules_loop([], _User, _Server) ->
     false;
-is_user_exists_in_other_modules_loop([AuthModule
-                                     | AuthModules],
-                                    User, Server) ->
-    case AuthModule:is_user_exists(User, Server) of
-      true -> true;
-      false ->
-         is_user_exists_in_other_modules_loop(AuthModules, User,
-                                              Server);
-      {error, Error} ->
-         ?DEBUG("The authentication module ~p returned "
-                "an error~nwhen checking user ~p in server "
-                "~p~nError message: ~p",
-                [AuthModule, User, Server, Error]),
-         maybe
+is_user_exists_in_other_modules_loop([AuthModule | AuthModules], User, Server) ->
+    case db_is_user_exists(User, Server, AuthModule) of
+       true ->
+           true;
+       false ->
+           is_user_exists_in_other_modules_loop(AuthModules, User, Server);
+       {error, _} ->
+           maybe
     end.
 
 -spec remove_user(binary(), binary()) -> ok.
-
-%% @spec (User, Server) -> ok
-%% @doc Remove user.
-%% Note: it may return ok even if there was some problem removing the user.
 remove_user(User, Server) ->
-    lists:foreach(fun (M) -> M:remove_user(User, Server)
-                 end,
-                 auth_modules(Server)),
-    ejabberd_hooks:run(remove_user, jid:nameprep(Server),
-                      [User, Server]),
-    ok.
-
-%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error
-%% @doc Try to remove user if the provided password is correct.
-%% The removal is attempted in each auth method provided:
-%% when one returns 'ok' the loop stops;
-%% if no method returns 'ok' then it returns the error message indicated by the last method attempted.
--spec remove_user(binary(), binary(), binary()) -> any().
+    case validate_credentials(User, Server) of
+       {ok, LUser, LServer} ->
+           lists:foreach(
+             fun(Mod) -> db_remove_user(LUser, LServer, Mod) end,
+             auth_modules(LServer)),
+           ejabberd_hooks:run(remove_user, LServer, [LUser, LServer]);
+       _Err ->
+           ok
+    end.
 
+-spec remove_user(binary(), binary(), password()) -> ok | {error, atom()}.
 remove_user(User, Server, Password) ->
-    R = lists:foldl(fun (_M, ok = Res) -> Res;
-                       (M, _) -> M:remove_user(User, Server, Password)
-                   end,
-                   error, auth_modules(Server)),
-    case R of
-      ok ->
-         ejabberd_hooks:run(remove_user, jid:nameprep(Server),
-                            [User, Server]);
-      _ -> none
-    end,
-    R.
-
-%% @spec (IOList) -> non_negative_float()
+    case validate_credentials(User, Server, Password) of
+       {ok, LUser, LServer} ->
+           case lists:foldl(
+                  fun (_, ok) ->
+                          ok;
+                      (Mod, _) ->
+                          case db_check_password(
+                                 LUser, <<"">>, LServer, Password,
+                                 <<"">>, undefined, Mod) of
+                              true ->
+                                  db_remove_user(LUser, LServer, Mod);
+                              false ->
+                                  {error, not_allowed}
+                          end
+                  end, {error, not_allowed}, auth_modules(Server)) of
+               ok ->
+                   ejabberd_hooks:run(
+                     remove_user, LServer, [LUser, LServer]);
+               Err ->
+                   Err
+           end;
+       Err ->
+           Err
+    end.
+
 %% @doc Calculate informational entropy.
+-spec entropy(iodata()) -> float().
 entropy(B) ->
     case binary_to_list(B) of
       "" -> 0.0;
@@ -497,15 +469,266 @@ backend_type(Mod) ->
        _ -> Mod
     end.
 
+-spec password_format(binary() | global) -> plain | scram.
 password_format(LServer) ->
     ejabberd_config:get_option({auth_password_format, LServer}, plain).
 
+%%%----------------------------------------------------------------------
+%%% Backend calls
+%%%----------------------------------------------------------------------
+db_try_register(User, Server, Password, Mod) ->
+    case erlang:function_exported(Mod, try_register, 3) of
+       true ->
+           Password1 = case Mod:store_type(Server) of
+                           scram -> password_to_scram(Password);
+                           _ -> Password
+                       end,
+           case use_cache(Mod, Server) of
+               true ->
+                   case ets_cache:update(
+                          ?AUTH_CACHE, {User, Server}, {ok, Password},
+                          fun() -> Mod:try_register(User, Server, Password1) end,
+                          cache_nodes(Mod, Server)) of
+                       {ok, _} -> ok;
+                       {error, _} = Err -> Err
+                   end;
+               false ->
+                   Mod:try_register(User, Server, Password1)
+           end;
+       false ->
+           {error, not_allowed}
+    end.
+
+db_set_password(User, Server, Password, Mod) ->
+    case erlang:function_exported(Mod, set_password, 3) of
+       true ->
+           Password1 = case Mod:store_type(Server) of
+                           scram -> password_to_scram(Password);
+                           _ -> Password
+                       end,
+           case use_cache(Mod, Server) of
+               true ->
+                   case ets_cache:update(
+                          ?AUTH_CACHE, {User, Server}, {ok, Password},
+                          fun() -> Mod:set_password(User, Server, Password1) end,
+                          cache_nodes(Mod, Server)) of
+                       {ok, _} -> ok;
+                       {error, _} = Err -> Err
+                   end;
+               false ->
+                   Mod:set_password(User, Server, Password1)
+           end;
+       false ->
+           {error, not_allowed}
+    end.
+
+db_get_password(User, Server, Mod) ->
+    UseCache = use_cache(Mod, Server),
+    case erlang:function_exported(Mod, get_password, 2) of
+       false when UseCache ->
+           ets_cache:lookup(?AUTH_CACHE, {User, Server});
+       false ->
+           error;
+       true when UseCache ->
+           ets_cache:lookup(
+             ?AUTH_CACHE, {User, Server},
+             fun() -> Mod:get_password(User, Server) end);
+       true ->
+           Mod:get_password(User, Server)
+    end.
+
+db_is_user_exists(User, Server, Mod) ->
+    case db_get_password(User, Server, Mod) of
+       {ok, _} ->
+           true;
+       error ->
+           case Mod:store_type(Server) of
+               external ->
+                   Mod:is_user_exists(User, Server);
+               _ ->
+                   false
+           end
+    end.
+
+db_check_password(User, AuthzId, Server, ProvidedPassword,
+                 Digest, DigestFun, Mod) ->
+    case db_get_password(User, Server, Mod) of
+       {ok, ValidPassword} ->
+           match_passwords(ProvidedPassword, ValidPassword, Digest, DigestFun);
+       error ->
+           case {Mod:store_type(Server), use_cache(Mod, Server)} of
+               {external, true} ->
+                   case ets_cache:update(
+                          ?AUTH_CACHE, {User, Server}, {ok, ProvidedPassword},
+                          fun() ->
+                                  case Mod:check_password(
+                                         User, AuthzId, Server, ProvidedPassword) of
+                                      true ->
+                                          {ok, ProvidedPassword};
+                                      false ->
+                                          error
+                                  end
+                          end, cache_nodes(Mod, Server)) of
+                       {ok, _} ->
+                           true;
+                       error ->
+                           false
+                   end;
+               {external, false} ->
+                   Mod:check_password(User, AuthzId, Server, ProvidedPassword);
+               _ ->
+                   false
+           end
+    end.
+
+db_remove_user(User, Server, Mod) ->
+    case erlang:function_exported(Mod, remove_user, 2) of
+       true ->
+           case Mod:remove_user(User, Server) of
+               ok ->
+                   case use_cache(Mod, Server) of
+                       true ->
+                           ets_cache:delete(?AUTH_CACHE, {User, Server},
+                                            cache_nodes(Mod, Server));
+                       false ->
+                           ok
+                   end;
+               {error, _} = Err ->
+                   Err
+           end;
+       false ->
+           {error, not_allowed}
+    end.
+
+db_get_users(Server, Opts, Mod) ->
+    case erlang:function_exported(Mod, get_users, 2) of
+       true ->
+           Mod:get_users(Server, Opts);
+       false ->
+           case use_cache(Mod, Server) of
+               true ->
+                   ets_cache:fold(
+                     fun({User, S}, {ok, _}, Users) when S == Server ->
+                             [{User, Server}|Users];
+                        (_, _, Users) ->
+                             Users
+                     end, [], ?AUTH_CACHE);
+               false ->
+                   []
+           end
+    end.
+
+db_count_users(Server, Opts, Mod) ->
+    case erlang:function_exported(Mod, count_users, 2) of
+       true ->
+           Mod:count_users(Server, Opts);
+       false ->
+           case use_cache(Mod, Server) of
+               true ->
+                   ets_cache:fold(
+                     fun({_, S}, {ok, _}, Num) when S == Server ->
+                             Num + 1;
+                        (_, _, Num) ->
+                             Num
+                     end, 0, ?AUTH_CACHE);
+               false ->
+                   0
+           end
+    end.
+
+%%%----------------------------------------------------------------------
+%%% SCRAM stuff
+%%%----------------------------------------------------------------------
+is_password_scram_valid(Password, Scram) ->
+    case jid:resourceprep(Password) of
+       error ->
+           false;
+       _ ->
+           IterationCount = Scram#scram.iterationcount,
+           Salt = misc:decode_base64(Scram#scram.salt),
+           SaltedPassword = scram:salted_password(Password, Salt, IterationCount),
+           StoredKey = scram:stored_key(scram:client_key(SaltedPassword)),
+           misc:decode_base64(Scram#scram.storedkey) == StoredKey
+    end.
+
+password_to_scram(Password) ->
+    password_to_scram(Password, ?SCRAM_DEFAULT_ITERATION_COUNT).
+
+password_to_scram(#scram{} = Password, _IterationCount) ->
+    Password;
+password_to_scram(Password, IterationCount) ->
+    Salt = randoms:bytes(?SALT_LENGTH),
+    SaltedPassword = scram:salted_password(Password, Salt, IterationCount),
+    StoredKey = scram:stored_key(scram:client_key(SaltedPassword)),
+    ServerKey = scram:server_key(SaltedPassword),
+    #scram{storedkey = misc:encode_base64(StoredKey),
+          serverkey = misc:encode_base64(ServerKey),
+          salt = misc:encode_base64(Salt),
+          iterationcount = IterationCount}.
+
+%%%----------------------------------------------------------------------
+%%% Cache stuff
+%%%----------------------------------------------------------------------
+-spec init_cache(map()) -> ok.
+init_cache(HostModules) ->
+    case use_cache(HostModules) of
+       true ->
+           ets_cache:new(?AUTH_CACHE, cache_opts());
+       false ->
+           ets_cache:delete(?AUTH_CACHE)
+    end.
+
+-spec cache_opts() -> [proplists:property()].
+cache_opts() ->
+    MaxSize = ejabberd_config:get_option(
+               auth_cache_size,
+               ejabberd_config:cache_size(global)),
+    CacheMissed = ejabberd_config:get_option(
+                   auth_cache_missed,
+                   ejabberd_config:cache_missed(global)),
+    LifeTime = case ejabberd_config:get_option(
+                     auth_cache_life_time,
+                     ejabberd_config:cache_life_time(global)) of
+                  infinity -> infinity;
+                  I -> timer:seconds(I)
+              end,
+    [{max_size, MaxSize}, {cache_missed, CacheMissed}, {life_time, LifeTime}].
+
+-spec use_cache(map()) -> boolean().
+use_cache(HostModules) ->
+    lists:any(
+      fun({Host, Modules}) ->
+             lists:any(fun(Module) ->
+                               use_cache(Module, Host)
+                       end, Modules)
+      end, maps:to_list(HostModules)).
+
+-spec use_cache(module(), binary()) -> boolean().
+use_cache(Mod, LServer) ->
+    case erlang:function_exported(Mod, use_cache, 1) of
+       true -> Mod:use_cache(LServer);
+       false ->
+           ejabberd_config:get_option(
+             {auth_use_cache, LServer},
+             ejabberd_config:use_cache(LServer))
+    end.
+
+-spec cache_nodes(module(), binary()) -> [node()].
+cache_nodes(Mod, LServer) ->
+    case erlang:function_exported(Mod, cache_nodes, 1) of
+       true -> Mod:cache_nodes(LServer);
+       false -> ejabberd_cluster:get_nodes()
+    end.
+
 %%%----------------------------------------------------------------------
 %%% Internal functions
 %%%----------------------------------------------------------------------
--spec auth_modules() -> [module()].
+-spec auth_modules() -> [{binary(), module()}].
 auth_modules() ->
-    lists:usort(lists:flatmap(fun auth_modules/1, ?MYHOSTS)).
+    lists:flatmap(
+      fun(Host) ->
+             [{Host, Mod} || Mod <- auth_modules(Host)]
+      end, ?MYHOSTS).
 
 -spec auth_modules(binary()) -> [module()].
 auth_modules(Server) ->
@@ -516,6 +739,65 @@ auth_modules(Server) ->
                           (misc:atom_to_binary(M))/binary>>)
      || M <- Methods].
 
+-spec match_passwords(password(), password(),
+                     binary(), digest_fun() | undefined) -> boolean().
+match_passwords(Password, #scram{} = Scram, <<"">>, undefined) ->
+    is_password_scram_valid(Password, Scram);
+match_passwords(Password, #scram{} = Scram, Digest, DigestFun) ->
+    StoredKey = misc:decode_base64(Scram#scram.storedkey),
+    DigRes = if Digest /= <<"">> ->
+                    Digest == DigestFun(StoredKey);
+               true -> false
+            end,
+    if DigRes ->
+           true;
+       true ->
+           StoredKey == Password andalso Password /= <<"">>
+    end;
+match_passwords(ProvidedPassword, ValidPassword, <<"">>, undefined) ->
+    ProvidedPassword == ValidPassword andalso ProvidedPassword /= <<"">>;
+match_passwords(ProvidedPassword, ValidPassword, Digest, DigestFun) ->
+    DigRes = if Digest /= <<"">> ->
+                    Digest == DigestFun(ValidPassword);
+               true -> false
+            end,
+    if DigRes ->
+           true;
+       true ->
+           ValidPassword == ProvidedPassword andalso ProvidedPassword /= <<"">>
+    end.
+
+-spec validate_credentials(binary(), binary()) ->
+      {ok, binary(), binary()} | {error, invalid_jid}.
+validate_credentials(User, Server) ->
+    validate_credentials(User, Server, #scram{}).
+
+-spec validate_credentials(binary(), binary(), password()) ->
+      {ok, binary(), binary()} | {error, invalid_jid | invalid_password}.
+validate_credentials(_User, _Server, <<"">>) ->
+    {error, invalid_password};
+validate_credentials(User, Server, Password) ->
+    case jid:nodeprep(User) of
+       error ->
+           {error, invalid_jid};
+       LUser ->
+           case jid:nameprep(Server) of
+               error ->
+                   {error, invalid_jid};
+               LServer ->
+                   if is_record(Password, scram) ->
+                           {ok, LUser, LServer};
+                      true ->
+                           case jid:resourceprep(Password) of
+                               error ->
+                                   {error, invalid_password};
+                               _ ->
+                                   {ok, LUser, LServer}
+                           end
+                   end
+           end
+    end.
+
 export(Server) ->
     ejabberd_auth_mnesia:export(Server).
 
@@ -536,6 +818,10 @@ import(_LServer, {sql, _}, sql, <<"users">>, _) ->
 
 -spec opt_type(auth_method) -> fun((atom() | [atom()]) -> [atom()]);
              (auth_password_format) -> fun((plain | scram) -> plain | scram);
+             (auth_use_cache) -> fun((boolean()) -> boolean());
+             (auth_cache_missed) -> fun((boolean()) -> boolean());
+             (auth_cache_life_time) -> fun((timeout()) -> timeout());
+             (auth_cache_size) -> fun((timeout()) -> timeout());
              (atom()) -> [atom()].
 opt_type(auth_method) ->
     fun (V) when is_list(V) ->
@@ -546,4 +832,20 @@ opt_type(auth_password_format) ->
     fun (plain) -> plain;
        (scram) -> scram
     end;
-opt_type(_) -> [auth_method, auth_password_format].
+opt_type(auth_use_cache) ->
+    fun(B) when is_boolean(B) -> B end;
+opt_type(auth_cache_missed) ->
+    fun(B) when is_boolean(B) -> B end;
+opt_type(auth_cache_life_time) ->
+    fun(I) when is_integer(I), I>0 -> I;
+       (unlimited) -> infinity;
+       (infinity) -> infinity
+    end;
+opt_type(auth_cache_size) ->
+    fun(I) when is_integer(I), I>0 -> I;
+       (unlimited) -> infinity;
+       (infinity) -> infinity
+    end;
+opt_type(_) ->
+    [auth_method, auth_password_format, auth_use_cache,
+     auth_cache_missed, auth_cache_life_time, auth_cache_size].
index 5bb2daed74ae60c4f85505ebe5a95b7758898ad5..b3ae1f6dd4c007a63de9868114472acffa37f067 100644 (file)
         unregister_connection/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,
-        get_password/2, get_password/3, is_user_exists/2,
-        remove_user/2, remove_user/3, store_type/0,
-        plain_password_required/0, opt_type/1]).
+-export([login/2, check_password/4, is_user_exists/2,
+        get_users/2, count_users/2, store_type/1,
+        plain_password_required/1, opt_type/1]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
@@ -139,15 +133,7 @@ unregister_connection(_SID,
 %% ---------------------------------
 %% Specific anonymous auth functions
 %% ---------------------------------
-
-%% When anonymous login is enabled, check the password for permenant users
-%% before allowing access
-check_password(User, AuthzId, Server, Password) ->
-    check_password(User, AuthzId, Server, Password, undefined,
-                  undefined).
-
-check_password(User, _AuthzId, Server, _Password, _Digest,
-              _DigestGen) ->
+check_password(User, _AuthzId, Server, _Password) ->
     case
       ejabberd_auth:is_user_exists_in_other_modules(?MODULE,
                                                    User, Server)
@@ -173,68 +159,20 @@ login(User, Server) ->
          end
     end.
 
-%% When anonymous login is enabled, check that the user is permanent before
-%% changing its password
-set_password(User, Server, _Password) ->
-    case anonymous_user_exist(User, Server) of
-      true -> ok;
-      false -> {error, not_allowed}
-    end.
-
-%% When anonymous login is enabled, check if permanent users are allowed on
-%% the server:
-try_register(_User, _Server, _Password) ->
-    {error, not_allowed}.
-
-dirty_get_registered_users() -> [].
-
-get_vh_registered_users(Server) ->
-    [{U, S}
-     || {U, S, _R}
-           <- ejabberd_sm:get_vh_session_list(Server)].
-
-get_vh_registered_users(Server, _) ->
-    get_vh_registered_users(Server).
-
-get_vh_registered_users_number(Server) ->
-    length(get_vh_registered_users(Server)).
+get_users(Server, _) ->
+    [{U, S} || {U, S, _R} <- ejabberd_sm:get_vh_session_list(Server)].
 
-get_vh_registered_users_number(Server, _) ->
-    get_vh_registered_users_number(Server).
-
-%% Return password of permanent user or false for anonymous users
-get_password(User, Server) ->
-    get_password(User, Server, <<"">>).
-
-get_password(User, Server, DefaultValue) ->
-    case anonymous_user_exist(User, Server) or
-          login(User, Server)
-       of
-      %% We return the default value if the user is anonymous
-      true -> DefaultValue;
-      %% We return the permanent user password otherwise
-      false -> false
-    end.
-
-get_password_s(User, Server) ->
-    case get_password(User, Server) of
-        false ->
-            <<"">>;
-        Password ->
-            Password
-    end.
+count_users(Server, Opts) ->
+    length(get_users(Server, Opts)).
 
 is_user_exists(User, Server) ->
     anonymous_user_exist(User, Server).
 
-remove_user(_User, _Server) -> {error, not_allowed}.
-
-remove_user(_User, _Server, _Password) -> not_allowed.
-
-plain_password_required() -> false.
+plain_password_required(_) ->
+    false.
 
-store_type() ->
-       plain.
+store_type(_) ->
+    external.
 
 -spec opt_type(allow_multiple_connection) -> fun((boolean()) -> boolean());
              (anonymous_protocol) -> fun((sasl_anon | login_anon | both) ->
index 5bdd704a0e2bb606a3b1b799cb1aa12d32ff7009..5b2b26c1a618fb834b30c771b2152e6aee12a0d0 100644 (file)
 -behaviour(ejabberd_auth).
 
 -export([start/1, stop/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, get_password/2,
-        get_password_s/2, is_user_exists/2, remove_user/2,
-        remove_user/3, store_type/0, plain_password_required/0,
-        opt_type/1]).
+        try_register/3, is_user_exists/2, remove_user/2,
+        store_type/1, plain_password_required/1, opt_type/1]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
 %%%----------------------------------------------------------------------
 start(Host) ->
     Cmd = ejabberd_config:get_option({extauth_program, Host}, "extauth"),
-    extauth:start(Host, Cmd),
-    check_cache_last_options(Host),
-    ejabberd_auth_mnesia:start(Host).
+    extauth:start(Host, Cmd).
 
 stop(Host) ->
-    extauth:stop(Host),
-    ejabberd_auth_mnesia:stop(Host).
+    extauth:stop(Host).
 
-check_cache_last_options(Server) ->
-    case get_cache_option(Server) of
-      false -> no_cache;
-      {true, _CacheTime} ->
-         case get_mod_last_configured(Server) of
-           no_mod_last ->
-               ?ERROR_MSG("In host ~p extauth is used, extauth_cache "
-                          "is enabled but mod_last is not enabled.",
-                          [Server]),
-               no_cache;
-           _ -> cache
-         end
-    end.
-
-plain_password_required() -> true.
+plain_password_required(_) -> true.
 
-store_type() -> external.
+store_type(_) -> external.
 
 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
+           check_password_extauth(User, AuthzId, Server, Password)
     end.
 
-check_password(User, AuthzId, Server, Password, _Digest,
-              _DigestGen) ->
-    check_password(User, AuthzId, Server, Password).
-
 set_password(User, Server, Password) ->
     case extauth:set_password(User, Server, Password) of
-      true ->
-         set_password_mnesia(User, Server, Password), ok;
-      _ -> {error, unknown_problem}
+       true -> ok;
+       _ -> {error, db_failure}
     end.
 
 try_register(User, Server, Password) ->
-    case get_cache_option(Server) of
-      false -> try_register_extauth(User, Server, Password);
-      {true, _CacheTime} ->
-         try_register_external_cache(User, Server, Password)
-    end.
-
-dirty_get_registered_users() ->
-    ejabberd_auth_mnesia:dirty_get_registered_users().
-
-get_vh_registered_users(Server) ->
-    ejabberd_auth_mnesia:get_vh_registered_users(Server).
-
-get_vh_registered_users(Server, Data) ->
-    ejabberd_auth_mnesia:get_vh_registered_users(Server,
-                                                  Data).
-
-get_vh_registered_users_number(Server) ->
-    ejabberd_auth_mnesia:get_vh_registered_users_number(Server).
-
-get_vh_registered_users_number(Server, Data) ->
-    ejabberd_auth_mnesia:get_vh_registered_users_number(Server,
-                                                         Data).
-
-%% The password can only be returned if cache is enabled, cached info exists and is fresh enough.
-get_password(User, Server) ->
-    case get_cache_option(Server) of
-      false -> false;
-      {true, CacheTime} ->
-         get_password_cache(User, Server, CacheTime)
-    end.
-
-get_password_s(User, Server) ->
-    case get_password(User, Server) of
-      false -> <<"">>;
-      Other -> Other
-    end.
+    extauth:try_register(User, Server, Password).
 
-%% @spec (User, Server) -> true | false | {error, Error}
 is_user_exists(User, Server) ->
     try extauth:is_user_exists(User, Server) of
-      Res -> Res
+       Res -> Res
     catch
-      _:Error -> {error, Error}
+       _:Error ->
+           ?ERROR_MSG("external authentication program failure: ~p",
+                      [Error]),
+           {error, db_failure}
     end.
 
 remove_user(User, Server) ->
     case extauth:remove_user(User, Server) of
-      false -> false;
-      true ->
-         case get_cache_option(Server) of
-           false -> false;
-           {true, _CacheTime} ->
-               ejabberd_auth_mnesia:remove_user(User, Server)
-         end
+       false -> {error, not_allowed};
+       true -> ok
     end.
 
-remove_user(User, Server, Password) ->
-    case extauth:remove_user(User, Server, Password) of
-      false -> false;
-      true ->
-         case get_cache_option(Server) of
-           false -> false;
-           {true, _CacheTime} ->
-               ejabberd_auth_mnesia:remove_user(User, Server,
-                                                  Password)
-         end
-    end.
-
-%%%
-%%% Extauth cache management
-%%%
-
-%% @spec (Host::string()) -> false | {true, CacheTime::integer()}
-get_cache_option(Host) ->
-    case ejabberd_config:get_option({extauth_cache, Host}, false) of
-        false -> false;
-        CacheTime -> {true, CacheTime}
-    end.
-
-%% @spec (User, AuthzId, Server, Password) -> true | false
 check_password_extauth(User, _AuthzId, Server, Password) ->
     extauth:check_password(User, Server, Password) andalso
       Password /= <<"">>.
 
-%% @spec (User, Server, Password) -> true | false
-try_register_extauth(User, Server, Password) ->
-    extauth:try_register(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_mnesia(User, AuthzId, Server, Password);
-      never ->
-         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, AuthzId, Server, Password);
-      TimeStamp ->
-         case is_fresh_enough(TimeStamp, CacheTime) of
-           %% If no need to refresh, check password against Mnesia
-           true ->
-               case check_password_mnesia(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, AuthzId, Server, Password)
-               end;
-           %% Else (need to refresh), check in extauth and cache result
-           false ->
-               check_password_external_cache(User, AuthzId, Server, Password)
-         end
-    end.
-
-get_password_mnesia(User, Server) ->
-    ejabberd_auth_mnesia:get_password(User, Server).
-
--spec get_password_cache(User::binary(), Server::binary(), CacheTime::integer()) -> Password::string() | false.
-get_password_cache(User, Server, CacheTime) ->
-    case get_last_access(User, Server) of
-      online -> get_password_mnesia(User, Server);
-      never -> false;
-      mod_last_required ->
-         ?ERROR_MSG("extauth is used, extauth_cache is enabled "
-                    "but mod_last is not enabled in that "
-                    "host",
-                    []),
-         false;
-      TimeStamp ->
-         case is_fresh_enough(TimeStamp, CacheTime) of
-           true -> get_password_mnesia(User, Server);
-           false -> false
-         end
-    end.
-
-%% Check the password using extauth; if success then cache it
-check_password_external_cache(User, AuthzId, Server, Password) ->
-    case check_password_extauth(User, AuthzId, Server, Password) of
-      true ->
-         set_password_mnesia(User, Server, Password), true;
-      false -> false
-    end.
-
-%% Try to register using extauth; if success then cache it
-try_register_external_cache(User, Server, Password) ->
-    case try_register_extauth(User, Server, Password) of
-      {atomic, ok} = R ->
-         set_password_mnesia(User, Server, Password), R;
-      _ -> {error, not_allowed}
-    end.
-
-%% @spec (User, AuthzId, Server, Password) -> true | false
-check_password_mnesia(User, AuthzId, Server, Password) ->
-    ejabberd_auth_mnesia:check_password(User, AuthzId, Server,
-                                         Password).
-
-%% @spec (User, Server, Password) -> ok | {error, invalid_jid}
-set_password_mnesia(User, Server, Password) ->
-%% @spec (TimeLast, CacheTime) -> true | false
-%%       TimeLast = online | never | integer()
-%%       CacheTime = integer() | false
-    ejabberd_auth_mnesia:set_password(User, Server,
-                                       Password).
-
-is_fresh_enough(TimeStampLast, CacheTime) ->
-    Now = p1_time_compat:system_time(seconds),
-    TimeStampLast + CacheTime > Now.
-
-%% Code copied from mod_configure.erl
-%% Code copied from web/ejabberd_web_admin.erl
-%% TODO: Update time format to XEP-0202: Entity Time
--spec(get_last_access(User::binary(), Server::binary()) -> (online | never | mod_last_required | integer())).
-get_last_access(User, Server) ->
-    case ejabberd_sm:get_user_resources(User, Server) of
-      [] ->
-         case get_last_info(User, Server) of
-           mod_last_required -> mod_last_required;
-           not_found -> never;
-           {ok, Timestamp, _Status} -> Timestamp
-         end;
-      _ -> online
-    end.
-%% @spec (User, Server) -> {ok, Timestamp, Status} | not_found | mod_last_required
-
-get_last_info(User, Server) ->
-    case get_mod_last_enabled(Server) of
-      mod_last -> mod_last:get_last_info(User, Server);
-      no_mod_last -> mod_last_required
-    end.
-
-%% @spec (Server) -> mod_last | no_mod_last
-get_mod_last_enabled(Server) ->
-    case gen_mod:is_loaded(Server, mod_last) of
-      true -> mod_last;
-      false -> no_mod_last
-    end.
-
-get_mod_last_configured(Server) ->
-    case is_configured(Server, mod_last) of
-      true -> mod_last;
-      false -> no_mod_last
-    end.
-
-is_configured(Host, Module) ->
-    Os = ejabberd_config:get_option({modules, Host}, []),
-    lists:keymember(Module, 1, Os).
-
 -spec opt_type(extauth_cache) -> fun((false | non_neg_integer()) ->
                                      false | non_neg_integer());
              (extauth_program) -> fun((binary()) -> string());
              (atom()) -> [atom()].
 opt_type(extauth_cache) ->
+    ?WARNING_MSG("option 'extauth_cache' is deprecated and has no effect, "
+                "use authentication or global cache configuration "
+                "options: auth_use_cache, auth_cache_life_time, "
+                "use_cache, cache_life_time, and so on", []),
     fun (false) -> false;
        (I) when is_integer(I), I >= 0 -> I
     end;
index 8a4532e38b7bb8c7a6ee1d4d437d09b76f088ee8..15abebedcfb2ffe1252fcfe8a151f149c6d379be 100644 (file)
         handle_cast/2, terminate/2, code_change/3]).
 
 -export([start/1, stop/1, start_link/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, get_password/2,
-        get_password_s/2, is_user_exists/2, remove_user/2,
-        remove_user/3, store_type/0, plain_password_required/0,
+        check_password/4, is_user_exists/2,
+        get_users/2, count_users/2,
+        store_type/1, plain_password_required/1,
         opt_type/1]).
 
 -include("ejabberd.hrl").
@@ -112,9 +108,9 @@ init(Host) ->
                          State#state.password, State#state.tls_options),
     {ok, State}.
 
-plain_password_required() -> true.
+plain_password_required(_) -> true.
 
-store_type() -> external.
+store_type(_) -> external.
 
 check_password(User, AuthzId, Server, Password) ->
     if AuthzId /= <<>> andalso AuthzId /= User ->
@@ -129,60 +125,34 @@ check_password(User, AuthzId, Server, Password) ->
            end
     end.
 
-check_password(User, AuthzId, Server, Password, _Digest,
-              _DigestGen) ->
-    check_password(User, AuthzId, Server, Password).
-
 set_password(User, Server, Password) ->
     {ok, State} = eldap_utils:get_state(Server, ?MODULE),
     case find_user_dn(User, State) of
-      false -> {error, user_not_found};
+      false -> {error, notfound};
       DN ->
-         eldap_pool:modify_passwd(State#state.eldap_id, DN,
-                                  Password)
+           case eldap_pool:modify_passwd(State#state.eldap_id, DN,
+                                         Password) of
+               ok -> ok;
+               _Err -> {error, db_failure}
+           end
     end.
 
-%% @spec (User, Server, Password) -> {error, not_allowed}
-try_register(_User, _Server, _Password) ->
-    {error, not_allowed}.
-
-dirty_get_registered_users() ->
-    Servers = ejabberd_config:get_vh_by_auth_method(ldap),
-    lists:flatmap(fun (Server) ->
-                         get_vh_registered_users(Server)
-                 end,
-                 Servers).
-
-get_vh_registered_users(Server) ->
-    case catch get_vh_registered_users_ldap(Server) of
+get_users(Server, []) ->
+    case catch get_users_ldap(Server) of
       {'EXIT', _} -> [];
       Result -> Result
     end.
 
-get_vh_registered_users(Server, _) ->
-    get_vh_registered_users(Server).
-
-get_vh_registered_users_number(Server) ->
-    length(get_vh_registered_users(Server)).
-
-get_vh_registered_users_number(Server, _) ->
-    get_vh_registered_users_number(Server).
-
-get_password(_User, _Server) -> false.
-
-get_password_s(_User, _Server) -> <<"">>.
+count_users(Server, Opts) ->
+    length(get_users(Server, Opts)).
 
 %% @spec (User, Server) -> true | false | {error, Error}
 is_user_exists(User, Server) ->
     case catch is_user_exists_ldap(User, Server) of
-      {'EXIT', Error} -> {error, Error};
+      {'EXIT', _Error} -> {error, db_failure};
       Result -> Result
     end.
 
-remove_user(_User, _Server) -> {error, not_allowed}.
-
-remove_user(_User, _Server, _Password) -> not_allowed.
-
 %%%----------------------------------------------------------------------
 %%% Internal functions
 %%%----------------------------------------------------------------------
@@ -199,7 +169,7 @@ check_password_ldap(User, Server, Password) ->
          end
     end.
 
-get_vh_registered_users_ldap(Server) ->
+get_users_ldap(Server) ->
     {ok, State} = eldap_utils:get_state(Server, ?MODULE),
     UIDs = State#state.uids,
     Eldap_ID = State#state.eldap_id,
index 592b9c566bef9614ee93992cdedc56b5d8ebe29b..02c22f9d5d3ba8e816630800edf5fbd2f8a9ce15 100644 (file)
 
 -behaviour(ejabberd_auth).
 
--export([start/1, stop/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, init_db/0,
-        get_vh_registered_users_number/1,
-        get_vh_registered_users_number/2, get_password/2,
-        get_password_s/2, is_user_exists/2, remove_user/2,
-        remove_user/3, store_type/0, export/1, import/2,
-        plain_password_required/0]).
+-export([start/1, stop/1, set_password/3, try_register/3,
+        get_users/2, init_db/0,
+        count_users/2, get_password/2,
+        remove_user/2, store_type/1, export/1, import/2,
+        plain_password_required/1, use_cache/1]).
 -export([need_transform/1, transform/1]).
 
 -include("ejabberd.hrl").
@@ -52,8 +48,6 @@
 -record(reg_users_counter, {vhost = <<"">> :: binary(),
                             count = 0 :: integer() | '$1'}).
 
--define(SALT_LENGTH, 16).
-
 %%%----------------------------------------------------------------------
 %%% API
 %%%----------------------------------------------------------------------
@@ -67,14 +61,14 @@ stop(_Host) ->
 
 init_db() ->
     ejabberd_mnesia:create(?MODULE, passwd,
-                       [{disc_copies, [node()]},
+                       [{disc_only_copies, [node()]},
                         {attributes, record_info(fields, passwd)}]),
     ejabberd_mnesia:create(?MODULE, reg_users_counter,
                        [{ram_copies, [node()]},
                         {attributes, record_info(fields, reg_users_counter)}]).
 
 update_reg_users_counter_table(Server) ->
-    Set = get_vh_registered_users(Server),
+    Set = get_users(Server, []),
     Size = length(Set),
     LServer = jid:nameprep(Server),
     F = fun () ->
@@ -83,309 +77,153 @@ update_reg_users_counter_table(Server) ->
        end,
     mnesia:sync_dirty(F).
 
-plain_password_required() ->
-    is_scrammed().
-
-store_type() ->
-    ejabberd_auth:password_format(?MYNAME).
-
-check_password(User, AuthzId, Server, Password) ->
-    if AuthzId /= <<>> andalso AuthzId /= User ->
-           false;
-       true ->
-           LUser = jid:nodeprep(User),
-           LServer = jid: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
+use_cache(_) ->
+    case mnesia:table_info(passwd, storage_type) of
+       disc_only_copies -> true;
+       _ -> false
     end.
 
-check_password(User, AuthzId, Server, Password, Digest,
-              DigestGen) ->
-    if AuthzId /= <<>> andalso AuthzId /= User ->
-           false;
-       true ->
-           LUser = jid:nodeprep(User),
-           LServer = jid: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 = misc: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.
+plain_password_required(Server) ->
+    store_type(Server) == scram.
+
+store_type(Server) ->
+    ejabberd_auth:password_format(Server).
 
-%% @spec (User::string(), Server::string(), Password::string()) ->
-%%       ok | {error, invalid_jid}
 set_password(User, Server, Password) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    LPassword = jid:resourceprep(Password),
-    US = {LUser, LServer},
-    if (LUser == error) or (LServer == error) ->
-          {error, invalid_jid};
-       LPassword == error ->
-          {error, invalid_password};
-       true ->
-          F = fun () ->
-                      Password2 = case is_scrammed() and is_binary(Password)
-                                      of
-                                    true -> password_to_scram(Password);
-                                    false -> Password
-                                  end,
-                      mnesia:write(#passwd{us = US, password = Password2})
-              end,
-          {atomic, ok} = mnesia:transaction(F),
-          ok
+    US = {User, Server},
+    F = fun () ->
+               mnesia:write(#passwd{us = US, password = Password})
+       end,
+    case mnesia:transaction(F) of
+       {atomic, ok} ->
+           ok;
+       {aborted, Reason} ->
+           ?ERROR_MSG("Mnesia transaction failed: ~p", [Reason]),
+           {error, db_failure}
     end.
 
-%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} | {error, not_allowed} | {error, Reason}
-try_register(User, Server, PasswordList) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    Password = if is_list(PasswordList); is_binary(PasswordList) ->
-      iolist_to_binary(PasswordList);
-      true -> PasswordList
-    end,
-    LPassword = jid:resourceprep(Password),
-    US = {LUser, LServer},
-    if (LUser == error) or (LServer == error) ->
-          {error, invalid_jid};
-       (LPassword == error) and not is_record(Password, scram) ->
-          {error, invalid_password};
-       true ->
-          F = fun () ->
-                      case mnesia:read({passwd, US}) of
-                        [] ->
-                            Password2 = case is_scrammed() and
-                                               is_binary(Password)
-                                            of
-                                          true -> password_to_scram(Password);
-                                          false -> Password
-                                        end,
-                            mnesia:write(#passwd{us = US,
-                                                 password = Password2}),
-                            mnesia:dirty_update_counter(reg_users_counter,
-                                                        LServer, 1),
-                            ok;
-                        [_E] -> exists
-                      end
-              end,
-          mnesia:transaction(F)
+try_register(User, Server, Password) ->
+    US = {User, Server},
+    F = fun () ->
+               case mnesia:read({passwd, US}) of
+                   [] ->
+                       mnesia:write(#passwd{us = US, password = Password}),
+                       mnesia:dirty_update_counter(reg_users_counter, Server, 1),
+                       ok;
+                   [_] ->
+                       {error, exists}
+               end
+       end,
+    case mnesia:transaction(F) of
+       {atomic, Res} ->
+           Res;
+       {aborted, Reason} ->
+           ?ERROR_MSG("Mnesia transaction failed: ~p", [Reason]),
+           {error, db_failure}
     end.
 
-%% Get all registered users in Mnesia
-dirty_get_registered_users() ->
-    mnesia:dirty_all_keys(passwd).
-
-get_vh_registered_users(Server) ->
-    LServer = jid:nameprep(Server),
+get_users(Server, []) ->
     mnesia:dirty_select(passwd,
                        [{#passwd{us = '$1', _ = '_'},
-                         [{'==', {element, 2, '$1'}, LServer}], ['$1']}]).
-
-get_vh_registered_users(Server,
-                       [{from, Start}, {to, End}])
-    when is_integer(Start) and is_integer(End) ->
-    get_vh_registered_users(Server,
-                           [{limit, End - Start + 1}, {offset, Start}]);
-get_vh_registered_users(Server,
-                       [{limit, Limit}, {offset, Offset}])
-    when is_integer(Limit) and is_integer(Offset) ->
-    case get_vh_registered_users(Server) of
-      [] -> [];
-      Users ->
-         Set = lists:keysort(1, Users),
-         L = length(Set),
-         Start = if Offset < 1 -> 1;
-                    Offset > L -> L;
-                    true -> Offset
-                 end,
-         lists:sublist(Set, Start, Limit)
+                         [{'==', {element, 2, '$1'}, Server}], ['$1']}]);
+get_users(Server, [{from, Start}, {to, End}])
+  when is_integer(Start) and is_integer(End) ->
+    get_users(Server, [{limit, End - Start + 1}, {offset, Start}]);
+get_users(Server, [{limit, Limit}, {offset, Offset}])
+  when is_integer(Limit) and is_integer(Offset) ->
+    case get_users(Server, []) of
+       [] ->
+           [];
+       Users ->
+           Set = lists:keysort(1, Users),
+           L = length(Set),
+           Start = if Offset < 1 -> 1;
+                      Offset > L -> L;
+                      true -> Offset
+                   end,
+           lists:sublist(Set, Start, Limit)
     end;
-get_vh_registered_users(Server, [{prefix, Prefix}])
-    when is_binary(Prefix) ->
-    Set = [{U, S}
-          || {U, S} <- get_vh_registered_users(Server),
-             str:prefix(Prefix, U)],
+get_users(Server, [{prefix, Prefix}]) when is_binary(Prefix) ->
+    Set = [{U, S} || {U, S} <- get_users(Server, []), str:prefix(Prefix, U)],
     lists:keysort(1, Set);
-get_vh_registered_users(Server,
-                       [{prefix, Prefix}, {from, Start}, {to, End}])
-    when is_binary(Prefix) and is_integer(Start) and
-          is_integer(End) ->
-    get_vh_registered_users(Server,
-                           [{prefix, Prefix}, {limit, End - Start + 1},
-                            {offset, Start}]);
-get_vh_registered_users(Server,
-                       [{prefix, Prefix}, {limit, Limit}, {offset, Offset}])
-    when is_binary(Prefix) and is_integer(Limit) and
-          is_integer(Offset) ->
-    case [{U, S}
-         || {U, S} <- get_vh_registered_users(Server),
-            str:prefix(Prefix, U)]
-       of
-      [] -> [];
-      Users ->
-         Set = lists:keysort(1, Users),
-         L = length(Set),
-         Start = if Offset < 1 -> 1;
-                    Offset > L -> L;
-                    true -> Offset
-                 end,
-         lists:sublist(Set, Start, Limit)
+get_users(Server, [{prefix, Prefix}, {from, Start}, {to, End}])
+  when is_binary(Prefix) and is_integer(Start) and is_integer(End) ->
+    get_users(Server, [{prefix, Prefix}, {limit, End - Start + 1},
+                      {offset, Start}]);
+get_users(Server, [{prefix, Prefix}, {limit, Limit}, {offset, Offset}])
+  when is_binary(Prefix) and is_integer(Limit) and is_integer(Offset) ->
+    case [{U, S} || {U, S} <- get_users(Server, []), str:prefix(Prefix, U)] of
+       [] ->
+           [];
+       Users ->
+           Set = lists:keysort(1, Users),
+           L = length(Set),
+           Start = if Offset < 1 -> 1;
+                      Offset > L -> L;
+                      true -> Offset
+                   end,
+           lists:sublist(Set, Start, Limit)
     end;
-get_vh_registered_users(Server, _) ->
-    get_vh_registered_users(Server).
-
-get_vh_registered_users_number(Server) ->
-    LServer = jid:nameprep(Server),
-    Query = mnesia:dirty_select(reg_users_counter,
-                               [{#reg_users_counter{vhost = LServer,
-                                                    count = '$1'},
-                                 [], ['$1']}]),
-    case Query of
-      [Count] -> Count;
-      _ -> 0
-    end.
-
-get_vh_registered_users_number(Server,
-                              [{prefix, Prefix}])
-    when is_binary(Prefix) ->
-    Set = [{U, S}
-          || {U, S} <- get_vh_registered_users(Server),
-             str:prefix(Prefix, U)],
+get_users(Server, _) ->
+    get_users(Server, []).
+
+count_users(Server, []) ->
+    case mnesia:dirty_select(
+          reg_users_counter,
+          [{#reg_users_counter{vhost = Server, count = '$1'},
+            [], ['$1']}]) of
+       [Count] -> Count;
+       _ -> 0
+    end;
+count_users(Server, [{prefix, Prefix}]) when is_binary(Prefix) ->
+    Set = [{U, S} || {U, S} <- get_users(Server, []), str:prefix(Prefix, U)],
     length(Set);
-get_vh_registered_users_number(Server, _) ->
-    get_vh_registered_users_number(Server).
+count_users(Server, _) ->
+    count_users(Server, []).
 
 get_password(User, Server) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid: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) ->
-         {misc:decode_base64(Scram#scram.storedkey),
-          misc:decode_base64(Scram#scram.serverkey),
-          misc:decode_base64(Scram#scram.salt),
-          Scram#scram.iterationcount};
-      _ -> false
-    end.
-
-get_password_s(User, Server) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid: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) ->
-         <<"">>;
-      _ -> <<"">>
-    end.
-
-%% @spec (User, Server) -> true | false | {error, Error}
-is_user_exists(User, Server) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    US = {LUser, LServer},
-    case catch mnesia:dirty_read({passwd, US}) of
-      [] -> false;
-      [_] -> true;
-      Other -> {error, Other}
+    case mnesia:dirty_read(passwd, {User, Server}) of
+       [#passwd{password = Password}] ->
+           {ok, Password};
+       _ ->
+           error
     end.
 
-%% @spec (User, Server) -> ok
-%% @doc Remove user.
-%% Note: it returns ok even if there was some problem removing the user.
 remove_user(User, Server) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    US = {LUser, LServer},
+    US = {User, Server},
     F = fun () ->
                mnesia:delete({passwd, US}),
-               mnesia:dirty_update_counter(reg_users_counter, LServer,
-                                           -1)
-       end,
-    mnesia:transaction(F),
-    ok.
-
-%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request
-%% @doc Remove user if the provided password is correct.
-remove_user(User, Server, Password) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    US = {LUser, LServer},
-    F = fun () ->
-               case mnesia:read({passwd, US}) of
-                 [#passwd{password = Password}]
-                     when is_binary(Password) ->
-                     mnesia:delete({passwd, US}),
-                     mnesia:dirty_update_counter(reg_users_counter, LServer,
-                                                 -1),
-                     ok;
-                 [#passwd{password = Scram}]
-                     when is_record(Scram, scram) ->
-                     case is_password_scram_valid(Password, Scram) of
-                       true ->
-                           mnesia:delete({passwd, US}),
-                           mnesia:dirty_update_counter(reg_users_counter,
-                                                       LServer, -1),
-                           ok;
-                       false -> not_allowed
-                     end;
-                 _ -> not_exists
-               end
+               mnesia:dirty_update_counter(reg_users_counter, Server, -1),
+               ok
        end,
     case mnesia:transaction(F) of
-      {atomic, ok} -> ok;
-      {atomic, Res} -> Res;
-      _ -> bad_request
+       {atomic, ok} ->
+           ok;
+       {aborted, Reason} ->
+           ?ERROR_MSG("Mnesia transaction failed: ~p", [Reason]),
+           {error, db_failure}
     end.
 
 need_transform(#passwd{us = {U, S}, password = Pass}) ->
     if is_binary(Pass) ->
-           IsScrammed = is_scrammed(),
-           if IsScrammed ->
+           case store_type(S) of
+               scram ->
                    ?INFO_MSG("Passwords in Mnesia table 'passwd' "
-                             "will be SCRAM'ed", []);
-              true ->
-                   ok
-           end,
-           IsScrammed;
+                             "will be SCRAM'ed", []),
+                   true;
+               plain ->
+                   false
+           end;
        is_record(Pass, scram) ->
-           case is_scrammed() of
-               true ->
-                   next;
-               false ->
+           case store_type(S) of
+               scram ->
+                   false;
+               plain ->
                    ?WARNING_MSG("Some passwords were stored in the database "
                                 "as SCRAM, but 'auth_password_format' "
-                                "is not configured as 'scram'.", []),
+                                "is not configured as 'scram': some "
+                                "authentication mechanisms such as DIGEST-MD5 "
+                                "would *fail*", []),
                    false
            end;
        is_list(U) orelse is_list(S) orelse is_list(Pass) ->
@@ -410,61 +248,24 @@ transform(#passwd{us = {U, S}, password = Pass} = R)
     transform(R#passwd{us = NewUS, password = NewPass});
 transform(#passwd{us = {U, S}, password = Password} = P)
   when is_binary(Password) ->
-    case is_scrammed() of
-       true ->
+    case store_type(S) of
+       scram ->
            case jid:resourceprep(Password) of
                error ->
                    ?ERROR_MSG("SASLprep failed for password of user ~s@~s",
                               [U, S]),
                    P;
                _ ->
-                   Scram = password_to_scram(Password),
+                   Scram = ejabberd_auth:password_to_scram(Password),
                    P#passwd{password = Scram}
            end;
-       false ->
+       plain ->
            P
     end;
 transform(#passwd{password = Password} = P)
   when is_record(Password, scram) ->
     P.
 
-%%%
-%%% SCRAM
-%%%
-
-is_scrammed() ->
-    scram == store_type().
-
-password_to_scram(Password) ->
-    password_to_scram(Password,
-                     ?SCRAM_DEFAULT_ITERATION_COUNT).
-
-password_to_scram(Password, IterationCount) ->
-    Salt = randoms:bytes(?SALT_LENGTH),
-    SaltedPassword = scram:salted_password(Password, Salt,
-                                          IterationCount),
-    StoredKey =
-       scram:stored_key(scram:client_key(SaltedPassword)),
-    ServerKey = scram:server_key(SaltedPassword),
-    #scram{storedkey = misc:encode_base64(StoredKey),
-          serverkey = misc:encode_base64(ServerKey),
-          salt = misc:encode_base64(Salt),
-          iterationcount = IterationCount}.
-
-is_password_scram_valid(Password, Scram) ->
-    case jid:resourceprep(Password) of
-       error ->
-           false;
-       _ ->
-           IterationCount = Scram#scram.iterationcount,
-           Salt = misc:decode_base64(Scram#scram.salt),
-           SaltedPassword = scram:salted_password(Password, Salt,
-                                                  IterationCount),
-           StoredKey =
-               scram:stored_key(scram:client_key(SaltedPassword)),
-           misc:decode_base64(Scram#scram.storedkey) == StoredKey
-    end.
-
 export(_Server) ->
     [{passwd,
       fun(Host, #passwd{us = {LUser, LServer}, password = Password})
index 9d2fc819b7982db64c2333ef3955ca0b0f101fa2..f865f36f64734270abf3838781644c6b5f02877b 100644 (file)
 
 -behaviour(ejabberd_auth).
 
--export([start/1, stop/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, get_password/2,
-        get_password_s/2, is_user_exists/2, remove_user/2,
-        remove_user/3, store_type/0, plain_password_required/0,
+-export([start/1, stop/1, check_password/4,
+        is_user_exists/2, store_type/1, plain_password_required/1,
         opt_type/1]).
 
 start(_Host) ->
@@ -46,13 +40,6 @@ start(_Host) ->
 stop(_Host) ->
     ok.
 
-set_password(_User, _Server, _Password) ->
-    {error, not_allowed}.
-
-check_password(User, AuthzId, Server, Password, _Digest,
-              _DigestGen) ->
-    check_password(User, AuthzId, Server, Password).
-
 check_password(User, AuthzId, Host, Password) ->
     if AuthzId /= <<>> andalso AuthzId /= User ->
         false;
@@ -70,25 +57,6 @@ check_password(User, AuthzId, Host, Password) ->
         end
     end.
 
-try_register(_User, _Server, _Password) ->
-    {error, not_allowed}.
-
-dirty_get_registered_users() -> [].
-
-get_vh_registered_users(_Host) -> [].
-
-get_vh_registered_users(_Host, _) -> [].
-
-get_vh_registered_users_number(_Host) -> 0.
-
-get_vh_registered_users_number(_Host, _) -> 0.
-
-get_password(_User, _Server) -> false.
-
-get_password_s(_User, _Server) -> <<"">>.
-
-%% @spec (User, Server) -> true | false | {error, Error}
-%% TODO: Improve this function to return an error instead of 'false' when connection to PAM failed
 is_user_exists(User, Host) ->
     Service = get_pam_service(Host),
     UserInfo = case get_pam_userinfotype(Host) of
@@ -97,16 +65,13 @@ is_user_exists(User, Host) ->
               end,
     case catch epam:acct_mgmt(Service, UserInfo) of
       true -> true;
-      _ -> false
+      false -> false;
+      _Err -> {error, db_failure}
     end.
 
-remove_user(_User, _Server) -> {error, not_allowed}.
-
-remove_user(_User, _Server, _Password) -> not_allowed.
-
-plain_password_required() -> true.
+plain_password_required(_) -> true.
 
-store_type() -> external.
+store_type(_) -> external.
 
 %%====================================================================
 %% Internal functions
index 74f0f73caae27691575ccea183807e3330055b79..fccaba102931b957d97b8f9c0a9165de694c81fa 100644 (file)
 -behaviour(ejabberd_auth).
 
 %% External exports
--export([start/1, stop/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, get_password/2,
-        get_password_s/2, is_user_exists/2, remove_user/2,
-        remove_user/3, store_type/0, export/1, import/2,
-        plain_password_required/0]).
+-export([start/1, stop/1, set_password/3, try_register/3,
+        get_users/2, count_users/2,
+        get_password/2, remove_user/2, store_type/1, export/1, import/2,
+        plain_password_required/1]).
 -export([passwd_schema/0]).
 
 -include("ejabberd.hrl").
 -record(passwd, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$1',
                  password = <<"">> :: binary() | scram() | '_'}).
 
--define(SALT_LENGTH, 16).
-
 start(_Host) ->
     ok.
 
 stop(_Host) ->
     ok.
 
-plain_password_required() ->
-    case is_scrammed() of
-      false -> false;
-      true -> true
-    end.
+plain_password_required(Server) ->
+    store_type(Server) == scram.
 
-store_type() ->
-    case is_scrammed() of
-      false -> plain; %% allows: PLAIN DIGEST-MD5 SCRAM
-      true -> scram %% allows: PLAIN SCRAM
-    end.
+store_type(Server) ->
+    ejabberd_auth:password_format(Server).
 
 passwd_schema() ->
     {record_info(fields, passwd), #passwd{}}.
 
-check_password(User, AuthzId, Server, Password) ->
-    if AuthzId /= <<>> andalso AuthzId /= User ->
-        false;
-    true ->
-        LUser = jid:nodeprep(User),
-        LServer = jid: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, AuthzId, Server, Password, Digest,
-              DigestGen) ->
-    if AuthzId /= <<>> andalso AuthzId /= User ->
-        false;
-    true ->
-        LUser = jid:nodeprep(User),
-        LServer = jid: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 = misc: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) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    LPassword = jid:resourceprep(Password),
-    US = {LUser, LServer},
-    if (LUser == error) or (LServer == error) ->
-          {error, invalid_jid};
-       LPassword == error ->
-          {error, invalid_password};
-       true ->
-            Password2 = case is_scrammed() and is_binary(Password)
-                        of
-                            true -> password_to_scram(Password);
-                            false -> Password
-                        end,
-            ok = ejabberd_riak:put(#passwd{us = US, password = Password2},
-                                  passwd_schema(),
-                                   [{'2i', [{<<"host">>, LServer}]}])
-    end.
-
-try_register(User, Server, PasswordList) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    Password = if is_list(PasswordList); is_binary(PasswordList) ->
-      iolist_to_binary(PasswordList);
-      true -> PasswordList
-    end,
-    LPassword = jid:resourceprep(Password),
-    US = {LUser, LServer},
-    if (LUser == error) or (LServer == error) ->
-          {error, invalid_jid};
-       LPassword == error and not is_record(Password, scram) ->
-          {error, invalid_password};
-       true ->
-            case ejabberd_riak:get(passwd, passwd_schema(), US) of
-                {error, notfound} ->
-                    Password2 = case is_scrammed() and
-                                    is_binary(Password)
-                                of
-                                    true -> password_to_scram(Password);
-                                    false -> Password
-                                end,
-                    {atomic, ejabberd_riak:put(
-                               #passwd{us = US,
-                                       password = Password2},
-                              passwd_schema(),
-                               [{'2i', [{<<"host">>, LServer}]}])};
-                {ok, _} ->
-                    exists;
-                Err ->
-                    {atomic, Err}
-            end
+    ejabberd_riak:put(#passwd{us = {User, Server}, password = Password},
+                     passwd_schema(),
+                     [{'2i', [{<<"host">>, Server}]}]).
+
+try_register(User, Server, Password) ->
+    US = {User, Server},
+    case ejabberd_riak:get(passwd, passwd_schema(), US) of
+       {error, notfound} ->
+           ejabberd_riak:put(#passwd{us = US, password = Password},
+                             passwd_schema(),
+                             [{'2i', [{<<"host">>, Server}]}]);
+       {ok, _} ->
+           {error, exists};
+       {error, _} = Err ->
+           Err
     end.
 
-dirty_get_registered_users() ->
-    lists:flatmap(
-      fun(Server) ->
-              get_vh_registered_users(Server)
-      end, ejabberd_config:get_vh_by_auth_method(riak)).
-
-get_vh_registered_users(Server) ->
-    LServer = jid:nameprep(Server),
-    case ejabberd_riak:get_keys_by_index(passwd, <<"host">>, LServer) of
+get_users(Server, _) ->
+    case ejabberd_riak:get_keys_by_index(passwd, <<"host">>, Server) of
         {ok, Users} ->
             Users;
         _ ->
             []
     end.
 
-get_vh_registered_users(Server, _) ->
-    get_vh_registered_users(Server).
-
-get_vh_registered_users_number(Server) ->
-    LServer = jid:nameprep(Server),
-    case ejabberd_riak:count_by_index(passwd, <<"host">>, LServer) of
+count_users(Server, _) ->
+    case ejabberd_riak:count_by_index(passwd, <<"host">>, Server) of
         {ok, N} ->
             N;
         _ ->
             0
     end.
 
-get_vh_registered_users_number(Server, _) ->
-    get_vh_registered_users_number(Server).
-
 get_password(User, Server) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid: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) ->
-         {misc:decode_base64(Scram#scram.storedkey),
-          misc:decode_base64(Scram#scram.serverkey),
-          misc:decode_base64(Scram#scram.salt),
-          Scram#scram.iterationcount};
-      _ -> false
-    end.
-
-get_password_s(User, Server) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid: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) ->
-         <<"">>;
-      _ -> <<"">>
-    end.
-
-is_user_exists(User, Server) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
-      {error, notfound} -> false;
-      {ok, _} -> true;
-      Err -> Err
+    case ejabberd_riak:get(passwd, passwd_schema(), {User, Server}) of
+       {ok, Password} ->
+           {ok, Password};
+       {error, _} ->
+           error
     end.
 
 remove_user(User, Server) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    ejabberd_riak:delete(passwd, {LUser, LServer}),
-    ok.
-
-remove_user(User, Server, Password) ->
-    LUser = jid:nodeprep(User),
-    LServer = jid:nameprep(Server),
-    case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
-        {ok, #passwd{password = Password}}
-          when is_binary(Password) ->
-            ejabberd_riak:delete(passwd, {LUser, LServer}),
-            ok;
-        {ok, #passwd{password = Scram}}
-          when is_record(Scram, scram) ->
-            case is_password_scram_valid(Password, Scram) of
-                true ->
-                    ejabberd_riak:delete(passwd, {LUser, LServer}),
-                    ok;
-                false -> not_allowed
-            end;
-        _ -> not_exists
-    end.
-
-%%%
-%%% SCRAM
-%%%
-
-is_scrammed() ->
-    scram == ejabberd_auth:password_format(?MYNAME).
-
-password_to_scram(Password) ->
-    password_to_scram(Password,
-                     ?SCRAM_DEFAULT_ITERATION_COUNT).
-
-password_to_scram(Password, IterationCount) ->
-    Salt = randoms:bytes(?SALT_LENGTH),
-    SaltedPassword = scram:salted_password(Password, Salt,
-                                          IterationCount),
-    StoredKey =
-       scram:stored_key(scram:client_key(SaltedPassword)),
-    ServerKey = scram:server_key(SaltedPassword),
-    #scram{storedkey = misc:encode_base64(StoredKey),
-          serverkey = misc:encode_base64(ServerKey),
-          salt = misc:encode_base64(Salt),
-          iterationcount = IterationCount}.
-
-is_password_scram_valid(Password, Scram) ->
-    case jid:resourceprep(Password) of
-       error ->
-           false;
-       _ ->
-           IterationCount = Scram#scram.iterationcount,
-           Salt = misc:decode_base64(Scram#scram.salt),
-           SaltedPassword = scram:salted_password(Password, Salt,
-                                                  IterationCount),
-           StoredKey =
-               scram:stored_key(scram:client_key(SaltedPassword)),
-           misc:decode_base64(Scram#scram.storedkey) == StoredKey
-    end.
+    ejabberd_riak:delete(passwd, {User, Server}).
 
 export(_Server) ->
     [{passwd,
index 8514b9cf17baf9f7b2722190119780c3328936d6..d682634f006209acd9ada67e06137709e1922579 100644 (file)
 
 -behaviour(ejabberd_auth).
 
--export([start/1, stop/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, get_password/2,
-        get_password_s/2, is_user_exists/2, remove_user/2,
-        remove_user/3, store_type/0, plain_password_required/0,
+-export([start/1, stop/1, set_password/3, try_register/3,
+        get_users/2, count_users/2, get_password/2,
+        remove_user/2, store_type/1, plain_password_required/1,
         convert_to_scram/1]).
 
 -include("ejabberd.hrl").
@@ -54,397 +49,82 @@ start(_Host) -> ok.
 
 stop(_Host) -> ok.
 
-plain_password_required() ->
-    case is_scrammed() of
-      false -> false;
-      true -> true
-    end.
-
-store_type() ->
-    case is_scrammed() of
-      false -> plain; %% allows: PLAIN DIGEST-MD5 SCRAM
-      true -> scram %% allows: PLAIN SCRAM
-    end.
+plain_password_required(Server) ->
+    store_type(Server) == scram.
 
-%% @spec (User, AuthzId, Server, Password) -> true | false | {error, Error}
-check_password(User, AuthzId, Server, Password) ->
-    if AuthzId /= <<>> andalso AuthzId /= User ->
-        false;
-    true ->
-        LServer = jid:nameprep(Server),
-        LUser = jid:nodeprep(User),
-    if (LUser == error) or (LServer == error) ->
-            false;
-       (LUser == <<>>) or (LServer == <<>>) ->
-            false;
-       true ->
-            case is_scrammed() of
-                true ->
-                    try sql_queries:get_password_scram(LServer, LUser) of
-                        {selected,
-                         [{StoredKey, ServerKey, Salt, IterationCount}]} ->
-                            Scram =
-                                #scram{storedkey = StoredKey,
-                                       serverkey = ServerKey,
-                                       salt = Salt,
-                                       iterationcount = IterationCount},
-                            is_password_scram_valid_stored(Password, Scram, LUser, LServer);
-                        {selected, []} ->
-                            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 sql_queries:get_password(LServer, LUser) of
-                        {selected, [{Password}]} ->
-                            Password /= <<"">>;
-                        {selected, [{_Password2}]} ->
-                            false; %% Password is not correct
-                        {selected, []} ->
-                            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.
+store_type(Server) ->
+    ejabberd_auth:password_format(Server).
 
-%% @spec (User, AuthzId, Server, Password, Digest, DigestGen) -> true | false | {error, Error}
-check_password(User, AuthzId, Server, Password, Digest,
-              DigestGen) ->
-    if AuthzId /= <<>> andalso AuthzId /= User ->
-        false;
-    true ->
-        LServer = jid:nameprep(Server),
-        LUser = jid:nodeprep(User),
-    if (LUser == error) or (LServer == error) ->
-            false;
-       (LUser == <<>>) or (LServer == <<>>) ->
-            false;
-       true ->
-            case is_scrammed() of
-                false ->
-                    try sql_queries:get_password(LServer, LUser) of
-                        %% Account exists, check if password is valid
-                        {selected, [{Passwd}]} ->
-                            DigRes = if Digest /= <<"">> ->
-                                             Digest == DigestGen(Passwd);
-                                        true -> false
-                                     end,
-                            if DigRes -> true;
-                               true -> (Passwd == Password) and (Password /= <<"">>)
-                            end;
-                        {selected, []} ->
-                            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()) ->
-%%       ok | {error, invalid_jid}
 set_password(User, Server, Password) ->
-    LServer = jid:nameprep(Server),
-    LUser = jid:nodeprep(User),
-    LPassword = jid:resourceprep(Password),
-    if (LUser == error) or (LServer == error) ->
-            {error, invalid_jid};
-       (LUser == <<>>) or (LServer == <<>>) ->
-            {error, invalid_jid};
-       LPassword == error ->
-          {error, invalid_password};
-       true ->
-            case is_scrammed() of
-                true ->
-                    Scram = password_to_scram(Password),
-                    case catch sql_queries:set_password_scram_t(
-                                 LServer,
-                                 LUser,
-                                 Scram#scram.storedkey,
-                                 Scram#scram.serverkey,
-                                 Scram#scram.salt,
-                                 Scram#scram.iterationcount
-                                )
-                        of
-                        {atomic, ok} -> ok;
-                        Other -> {error, Other}
-                    end;
-                false ->
-                    case catch sql_queries:set_password_t(LServer,
-                                                           LUser, Password)
-                        of
-                        {atomic, ok} -> ok;
-                        Other -> {error, Other}
-                    end
-            end
+    Res = if is_record(Password, scram) ->
+                 sql_queries:set_password_scram_t(
+                   Server, User,
+                   Password#scram.storedkey, Password#scram.serverkey,
+                   Password#scram.salt, Password#scram.iterationcount);
+            true ->
+                 sql_queries:set_password_t(Server, User, Password)
+         end,
+    case Res of
+       {atomic, _} ->
+           ok;
+       {aborted, Reason} ->
+           ?ERROR_MSG("failed to write to SQL table: ~p", [Reason]),
+           {error, db_failure}
     end.
 
-%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid}
 try_register(User, Server, Password) ->
-    LServer = jid:nameprep(Server),
-    LUser = jid:nodeprep(User),
-    LPassword = jid:resourceprep(Password),
-    if (LUser == error) or (LServer == error) ->
-            {error, invalid_jid};
-       (LUser == <<>>) or (LServer == <<>>) ->
-            {error, invalid_jid};
-       LPassword == error and not is_record(Password, scram) ->
-          {error, invalid_password};
-       true ->
-            case is_scrammed() of
-                true ->
-                    Scram = case is_record(Password, scram) of
-                        true -> Password;
-                        false -> password_to_scram(Password)
-                    end,
-                    case catch sql_queries:add_user_scram(
-                                 LServer,
-                                 LUser,
-                                 Scram#scram.storedkey,
-                                 Scram#scram.serverkey,
-                                 Scram#scram.salt,
-                                 Scram#scram.iterationcount
-                                ) of
-                        {updated, 1} -> {atomic, ok};
-                        _ -> {atomic, exists}
-                    end;
-                false ->
-                    case catch sql_queries:add_user(LServer, LUser,
-                                                     Password) of
-                        {updated, 1} -> {atomic, ok};
-                        _ -> {atomic, exists}
-                    end
-            end
+    Res = if is_record(Password, scram) ->
+                 sql_queries:add_user_scram(
+                   Server, User,
+                   Password#scram.storedkey, Password#scram.serverkey,
+                   Password#scram.salt, Password#scram.iterationcount);
+            true ->
+                 sql_queries:add_user(Server, User, Password)
+         end,
+    case Res of
+       {updated, 1} -> ok;
+       _ -> {error, exists}
     end.
 
-dirty_get_registered_users() ->
-    Servers = ejabberd_config:get_vh_by_auth_method(sql),
-    lists:flatmap(fun (Server) ->
-                         get_vh_registered_users(Server)
-                 end,
-                 Servers).
-
-get_vh_registered_users(Server) ->
-    case jid:nameprep(Server) of
-        error -> [];
-        <<>> -> [];
-        LServer ->
-            case catch sql_queries:list_users(LServer) of
-                {selected, Res} ->
-                    [{U, LServer} || {U} <- Res];
-                _ -> []
-            end
+get_users(Server, Opts) ->
+    case sql_queries:list_users(Server, Opts) of
+       {selected, Res} ->
+           [{U, Server} || {U} <- Res];
+       _ -> []
     end.
 
-get_vh_registered_users(Server, Opts) ->
-    case jid:nameprep(Server) of
-        error -> [];
-        <<>> -> [];
-        LServer ->
-            case catch sql_queries:list_users(LServer, Opts) of
-                {selected, Res} ->
-                    [{U, LServer} || {U} <- Res];
-                _ -> []
-            end
-    end.
-
-get_vh_registered_users_number(Server) ->
-    case jid:nameprep(Server) of
-        error -> 0;
-        <<>> -> 0;
-        LServer ->
-            case catch sql_queries:users_number(LServer) of
-                {selected, [{Res}]} ->
-                    Res;
-                _ -> 0
-            end
-    end.
-
-get_vh_registered_users_number(Server, Opts) ->
-    case jid:nameprep(Server) of
-        error -> 0;
-        <<>> -> 0;
-        LServer ->
-            case catch sql_queries:users_number(LServer, Opts) of
-                {selected, [{Res}]} ->
-                    Res;
-                _Other -> 0
-            end
+count_users(Server, Opts) ->
+    case sql_queries:users_number(Server, Opts) of
+       {selected, [{Res}]} ->
+           Res;
+       _Other -> 0
     end.
 
 get_password(User, Server) ->
-    LServer = jid:nameprep(Server),
-    LUser = jid:nodeprep(User),
-    if (LUser == error) or (LServer == error) ->
-            false;
-       (LUser == <<>>) or (LServer == <<>>) ->
-            false;
-       true ->
-            case is_scrammed() of
-                true ->
-                    case catch sql_queries:get_password_scram(
-                                 LServer, LUser) of
-                        {selected,
-                         [{StoredKey, ServerKey, Salt, IterationCount}]} ->
-                            {misc:decode_base64(StoredKey),
-                             misc:decode_base64(ServerKey),
-                             misc:decode_base64(Salt),
-                             IterationCount};
-                        _ -> false
-                    end;
-                false ->
-                    case catch sql_queries:get_password(LServer, LUser)
-                        of
-                        {selected, [{Password}]} -> Password;
-                        _ -> false
-                    end
-            end
-    end.
-
-get_password_s(User, Server) ->
-    LServer = jid:nameprep(Server),
-    LUser = jid:nodeprep(User),
-    if (LUser == error) or (LServer == error) ->
-            <<"">>;
-       (LUser == <<>>) or (LServer == <<>>) ->
-            <<"">>;
-       true ->
-            case is_scrammed() of
-                false ->
-                    case catch sql_queries:get_password(LServer, LUser) of
-                        {selected, [{Password}]} -> Password;
-                        _ -> <<"">>
-                    end;
-                true -> <<"">>
-            end
+    case sql_queries:get_password_scram(Server, User) of
+       {selected, [{Password, <<>>, <<>>, 0}]} ->
+           {ok, Password};
+       {selected, [{StoredKey, ServerKey, Salt, IterationCount}]} ->
+           {ok, #scram{storedkey = StoredKey,
+                       serverkey = ServerKey,
+                       salt = Salt,
+                       iterationcount = IterationCount}};
+       {selected, []} ->
+           error;
+       Err ->
+           ?ERROR_MSG("Failed to read password for user ~s@~s: ~p",
+                      [User, Server, Err]),
+           error
     end.
 
-%% @spec (User, Server) -> true | false | {error, Error}
-is_user_exists(User, Server) ->
-    LServer = jid:nameprep(Server),
-    LUser = jid:nodeprep(User),
-    if (LUser == error) or (LServer == error) ->
-            false;
-       (LUser == <<>>) or (LServer == <<>>) ->
-            false;
-       true ->
-         try sql_queries:get_password(LServer, LUser) of
-           {selected, [{_Password}]} ->
-               true; %% Account exists
-           {selected, []} ->
-               false; %% Account does not exist
-           {error, Error} -> {error, Error}
-         catch
-           _:B -> {error, B}
-         end
-    end.
-
-%% @spec (User, Server) -> ok | error
-%% @doc Remove user.
-%% Note: it may return ok even if there was some problem removing the user.
 remove_user(User, Server) ->
-    LServer = jid:nameprep(Server),
-    LUser = jid:nodeprep(User),
-    if (LUser == error) or (LServer == error) ->
-            error;
-       (LUser == <<>>) or (LServer == <<>>) ->
-            error;
-       true ->
-         catch sql_queries:del_user(LServer, LUser),
-         ok
-    end.
-
-%% @spec (User, Server, Password) -> ok | error | not_exists | not_allowed
-%% @doc Remove user if the provided password is correct.
-remove_user(User, Server, Password) ->
-    LServer = jid:nameprep(Server),
-    LUser = jid:nodeprep(User),
-    if (LUser == error) or (LServer == error) ->
-            error;
-       (LUser == <<>>) or (LServer == <<>>) ->
-            error;
-       true ->
-            case is_scrammed() of
-                true ->
-                    case check_password(User, <<"">>, Server, Password) of
-                        true ->
-                            remove_user(User, Server),
-                            ok;
-                        false -> not_allowed
-                    end;
-                false ->
-                    F = fun () ->
-                                Result = sql_queries:del_user_return_password(
-                                           LServer, LUser, Password),
-                                case Result of
-                                    {selected, [{Password}]} -> ok;
-                                    {selected, []} -> not_exists;
-                                    _ -> not_allowed
-                                end
-                        end,
-                    {atomic, Result} = sql_queries:sql_transaction(
-                                         LServer, F),
-                    Result
-            end
-    end.
-
-%%%
-%%% SCRAM
-%%%
-
-is_scrammed() ->
-    scram == ejabberd_auth:password_format(?MYNAME).
-
-password_to_scram(Password) ->
-    password_to_scram(Password,
-                     ?SCRAM_DEFAULT_ITERATION_COUNT).
-
-password_to_scram(Password, IterationCount) ->
-    Salt = randoms:bytes(?SALT_LENGTH),
-    SaltedPassword = scram:salted_password(Password, Salt,
-                                          IterationCount),
-    StoredKey =
-       scram:stored_key(scram:client_key(SaltedPassword)),
-    ServerKey = scram:server_key(SaltedPassword),
-    #scram{storedkey = misc:encode_base64(StoredKey),
-          serverkey = misc:encode_base64(ServerKey),
-          salt = misc:encode_base64(Salt),
-          iterationcount = IterationCount}.
-
-is_password_scram_valid_stored(Pass, {scram,Pass,<<>>,<<>>,0}, LUser, LServer) ->
-    ?INFO_MSG("Apparently, SQL auth method and scram password formatting are "
-       "enabled, but the password of user '~s' in the 'users' table is not "
-       "scrammed. You may want to execute this command: "
-       "ejabberdctl convert_to_scram ~s", [LUser, LServer]),
-    false;
-is_password_scram_valid_stored(Password, Scram, _, _) ->
-    is_password_scram_valid(Password, Scram).
-
-is_password_scram_valid(Password, Scram) ->
-    case jid:resourceprep(Password) of
-       error ->
-           false;
-       _ ->
-           IterationCount = Scram#scram.iterationcount,
-           Salt = misc:decode_base64(Scram#scram.salt),
-           SaltedPassword = scram:salted_password(Password, Salt,
-                                                  IterationCount),
-           StoredKey =
-               scram:stored_key(scram:client_key(SaltedPassword)),
-           misc:decode_base64(Scram#scram.storedkey) == StoredKey
+    case sql_queries:del_user(Server, User) of
+       {updated, _} ->
+           ok;
+       Err ->
+           ?ERROR_MSG("failed to delete user ~s@~s: ~p",
+                      [User, Server, Err]),
+           {error, db_failure}
     end.
 
 -define(BATCH_SIZE, 1000).
@@ -485,7 +165,7 @@ convert_to_scram(Server) ->
                                                     "password of user ~s@~s",
                                                     [LUser, LServer]);
                                              _ ->
-                                                 Scram = password_to_scram(Password),
+                                                 Scram = ejabberd_auth:password_to_scram(Password),
                                                  set_password_scram_t(
                                                    LUser,
                                                    Scram#scram.storedkey,
index aea280591053ab5f18c5115890b50f8f0d217222..ecb4908a7e3cae26046aba3d2b079517efa87d21 100644 (file)
@@ -135,7 +135,7 @@ export_host(Dir, FnH, Host) ->
         {ok, Fd} ->
             print(Fd, make_piefxis_xml_head()),
             print(Fd, make_piefxis_host_head(Host)),
-            Users = ejabberd_auth:get_vh_registered_users(Host),
+            Users = ejabberd_auth:get_users(Host),
             case export_users(Users, Host, Fd) of
                 ok ->
                     print(Fd, make_piefxis_host_tail()),
@@ -402,9 +402,9 @@ process_user(#xmlel{name = <<"user">>, attrs = Attrs, children = Els},
             stop("Invalid 'user': ~s", [Name]);
         LUser ->
             case ejabberd_auth:try_register(LUser, LServer, Pass) of
-                {atomic, _} ->
+                ok ->
                     process_user_els(Els, State#state{user = LUser});
-                Err ->
+                {error, Err} ->
                     stop("Failed to create user '~s': ~p", [Name, Err])
             end
     end.
index 5050ac0954e625843f5aac4fcb48108359760fde..6fdac19710e5c4a3574df333dad837ee0fa1d9a6 100644 (file)
@@ -1370,7 +1370,7 @@ list_vhosts2(Lang, Hosts) ->
                                 OnlineUsers =
                                     length(ejabberd_sm:get_vh_session_list(Host)),
                                 RegisteredUsers =
-                                    ejabberd_auth:get_vh_registered_users_number(Host),
+                                    ejabberd_auth:count_users(Host),
                                 ?XE(<<"tr">>,
                                     [?XE(<<"td">>,
                                          [?AC(<<"../server/", Host/binary,
@@ -1388,7 +1388,7 @@ list_vhosts2(Lang, Hosts) ->
 
 list_users(Host, Query, Lang, URLFunc) ->
     Res = list_users_parse_query(Query, Host),
-    Users = ejabberd_auth:get_vh_registered_users(Host),
+    Users = ejabberd_auth:get_users(Host),
     SUsers = lists:sort([{S, U} || {U, S} <- Users]),
     FUsers = case length(SUsers) of
               N when N =< 100 ->
@@ -1469,7 +1469,7 @@ list_users_parse_query(Query, Host) ->
     end.
 
 list_users_in_diapason(Host, Diap, Lang, URLFunc) ->
-    Users = ejabberd_auth:get_vh_registered_users(Host),
+    Users = ejabberd_auth:get_users(Host),
     SUsers = lists:sort([{S, U} || {U, S} <- Users]),
     [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>),
     N1 = binary_to_integer(S1),
@@ -1565,7 +1565,7 @@ su_to_list({Server, User}) ->
 get_stats(global, Lang) ->
     OnlineUsers = ejabberd_sm:connected_users_number(),
     RegisteredUsers = lists:foldl(fun (Host, Total) ->
-                                         ejabberd_auth:get_vh_registered_users_number(Host)
+                                         ejabberd_auth:count_users(Host)
                                            + Total
                                  end,
                                  0, ?MYHOSTS),
@@ -1589,7 +1589,7 @@ get_stats(Host, Lang) ->
     OnlineUsers =
        length(ejabberd_sm:get_vh_session_list(Host)),
     RegisteredUsers =
-       ejabberd_auth:get_vh_registered_users_number(Host),
+       ejabberd_auth:count_users(Host),
     [?XAE(<<"table">>, [],
          [?XE(<<"tbody">>,
               [?XE(<<"tr">>,
index 54f44953c60edddfd627839d1d8da72fe867324c..70f32bf8fca20361c83b9fa1f5b856907782dc4f 100644 (file)
@@ -83,7 +83,7 @@ try_register(User, Server, Password) ->
     case call_port(Server,
                   [<<"tryregister">>, User, Server, Password])
        of
-      true -> {atomic, ok};
+      true -> ok;
       false -> {error, not_allowed}
     end.
 
index 133b2fd29085be14a492092e4bd6ffe49e724363..982772af0741aff4e3fcbd133eecb84eee507cb9 100644 (file)
@@ -810,14 +810,14 @@ histogram([], _Integral, _Current, Count, Hist) ->
 
 delete_old_users(Days) ->
     %% Get the list of registered users
-    Users = ejabberd_auth:dirty_get_registered_users(),
+    Users = ejabberd_auth:get_users(),
 
     {removed, N, UR} = delete_old_users(Days, Users),
     {ok, io_lib:format("Deleted ~p users: ~p", [N, UR])}.
 
 delete_old_users_vhost(Host, Days) ->
     %% Get the list of registered users
-    Users = ejabberd_auth:get_vh_registered_users(Host),
+    Users = ejabberd_auth:get_users(Host),
 
     {removed, N, UR} = delete_old_users(Days, Users),
     {ok, io_lib:format("Deleted ~p users: ~p", [N, UR])}.
@@ -1285,7 +1285,7 @@ subscribe_roster({Name1, Server1, Group1, Nick1}, [{Name2, Server2, Group2, Nick
     subscribe_roster({Name1, Server1, Group1, Nick1}, Roster).
 
 push_alltoall(S, G) ->
-    Users = ejabberd_auth:get_vh_registered_users(S),
+    Users = ejabberd_auth:get_users(S),
     Users2 = build_list_users(G, Users, []),
     subscribe_all(Users2),
     ok.
@@ -1499,14 +1499,14 @@ stats(Name) ->
     case Name of
        <<"uptimeseconds">> -> trunc(element(1, erlang:statistics(wall_clock))/1000);
        <<"processes">> -> length(erlang:processes());
-       <<"registeredusers">> -> lists:foldl(fun(Host, Sum) -> ejabberd_auth:get_vh_registered_users_number(Host) + Sum end, 0, ?MYHOSTS);
+       <<"registeredusers">> -> lists:foldl(fun(Host, Sum) -> ejabberd_auth:count_users(Host) + Sum end, 0, ?MYHOSTS);
        <<"onlineusersnode">> -> length(ejabberd_sm:dirty_get_my_sessions_list());
        <<"onlineusers">> -> length(ejabberd_sm:dirty_get_sessions_list())
     end.
 
 stats(Name, Host) ->
     case Name of
-       <<"registeredusers">> -> ejabberd_auth:get_vh_registered_users_number(Host);
+       <<"registeredusers">> -> ejabberd_auth:count_users(Host);
        <<"onlineusers">> -> length(ejabberd_sm:get_vh_session_list(Host))
     end.
 
index 35d179c0ca1413bd4b771f88bdba4aecd3185ffd..379cd3ca01e5ec1003d202cc808926cf989ff13f 100644 (file)
@@ -633,7 +633,7 @@ announce_all(#message{to = To} = Packet) ->
              Dest = jid:make(User, Server),
              ejabberd_router:route(
                xmpp:set_from_to(add_store_hint(Packet), Local, Dest))
-      end, ejabberd_auth:get_vh_registered_users(To#jid.lserver)).
+      end, ejabberd_auth:get_users(To#jid.lserver)).
 
 announce_all_hosts_all(#message{to = To} = Packet) ->
     Local = jid:make(To#jid.server),
@@ -642,7 +642,7 @@ announce_all_hosts_all(#message{to = To} = Packet) ->
              Dest = jid:make(User, Server),
              ejabberd_router:route(
                xmpp:set_from_to(add_store_hint(Packet), Local, Dest))
-      end, ejabberd_auth:dirty_get_registered_users()).
+      end, ejabberd_auth:get_users()).
 
 announce_online(#message{to = To} = Packet) ->
     announce_online1(ejabberd_sm:get_vh_session_list(To#jid.lserver),
index b9db1e51124ca4dbba783962456c9e1b7a2ef84b..f3eb496d876df1b7b38786d13442ce94b311be43 100644 (file)
@@ -547,7 +547,7 @@ get_local_items({_, Host}, [<<"all users">>], _Server,
 get_local_items({_, Host},
                [<<"all users">>, <<$@, Diap/binary>>], _Server,
                _Lang) ->
-    Users = ejabberd_auth:get_vh_registered_users(Host),
+    Users = ejabberd_auth:get_users(Host),
     SUsers = lists:sort([{S, U} || {U, S} <- Users]),
     try
        [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>),
@@ -661,7 +661,7 @@ get_online_vh_users(Host) ->
     end.
 
 get_all_vh_users(Host) ->
-    case catch ejabberd_auth:get_vh_registered_users(Host)
+    case catch ejabberd_auth:get_users(Host)
        of
       {'EXIT', _Reason} -> [];
       Users ->
@@ -1194,7 +1194,7 @@ get_form(_Host, ?NS_ADMINL(<<"user-stats">>), Lang) ->
                                   required = true}]}};
 get_form(Host,
         ?NS_ADMINL(<<"get-registered-users-num">>), Lang) ->
-    Num = integer_to_binary(ejabberd_auth:get_vh_registered_users_number(Host)),
+    Num = integer_to_binary(ejabberd_auth:count_users(Host)),
     {result, completed,
      #xdata{type = form,
            fields = [?HFIELD(),
index af4ba02f4d75ebab9bd7707928bf231faf410fa1..5167370c1d6cdae13a82967465a1a706b2c1caa9 100644 (file)
@@ -323,7 +323,7 @@ try_register(User, Server, Password, SourceRaw, Lang) ->
                            case ejabberd_auth:try_register(User, Server,
                                                            Password)
                                of
-                             {atomic, ok} ->
+                             ok ->
                                  send_welcome_message(JID),
                                  send_registration_notifications(
                                     ?MODULE, JID, Source),
@@ -331,7 +331,7 @@ try_register(User, Server, Password, SourceRaw, Lang) ->
                              Error ->
                                  remove_timeout(Source),
                                  case Error of
-                                   {atomic, exists} ->
+                                   {error, exists} ->
                                        Txt = <<"User already exists">>,
                                        {error, xmpp:err_conflict(Txt, Lang)};
                                    {error, invalid_jid} ->
index cd19bb65a9ae686878a19d3ca19cc4ae8dea6ebe..d5e4112c3b9a87ba4a02c0a21184fce46dc2a2a6 100644 (file)
@@ -510,8 +510,8 @@ register_account2(Username, Host, Password) ->
     case ejabberd_auth:try_register(Username, Host,
                                    Password)
        of
-      {atomic, Res} ->
-         {success, Res, {Username, Host, Password}};
+      ok ->
+         {success, ok, {Username, Host, Password}};
       Other -> Other
     end.
 
index 67b5870a2f62d71aea707cf1e655232274b126e6..c25b13f66ab1e0be0bc8fec81274aad160579663 100644 (file)
@@ -450,7 +450,7 @@ get_online_users(Host) ->
 get_group_users(Host1, Group1) ->
     {Host, Group} = split_grouphost(Host1, Group1),
     case get_group_opt(Host, Group, all_users, false) of
-      true -> ejabberd_auth:get_vh_registered_users(Host);
+      true -> ejabberd_auth:get_users(Host);
       false -> []
     end
       ++
@@ -462,7 +462,7 @@ get_group_users(Host1, Group1) ->
 
 get_group_users(Host, Group, GroupOpts) ->
     case proplists:get_value(all_users, GroupOpts, false) of
-      true -> ejabberd_auth:get_vh_registered_users(Host);
+      true -> ejabberd_auth:get_users(Host);
       false -> []
     end
       ++
index 92a6627c55ed9f23e81c4e6a406a3cb2a3b9d3c7..2bdbdbd3327051b8ffba3e5e353349cd71433711 100644 (file)
@@ -119,7 +119,7 @@ get_local_stat(Server, [], Name)
 get_local_stat(Server, [], Name)
     when Name == <<"users/total">> ->
     case catch
-          ejabberd_auth:get_vh_registered_users_number(Server)
+          ejabberd_auth:count_users(Server)
        of
       {'EXIT', _Reason} ->
          ?STATERR(500, <<"Internal Server Error">>);
@@ -134,7 +134,7 @@ get_local_stat(_Server, [], Name)
 get_local_stat(_Server, [], Name)
     when Name == <<"users/all-hosts/total">> ->
     NumUsers = lists:foldl(fun (Host, Total) ->
-                                  ejabberd_auth:get_vh_registered_users_number(Host)
+                                  ejabberd_auth:count_users(Host)
                                     + Total
                           end,
                           0, ?MYHOSTS),
index 17bbc1d0a4dab5a786f531c706415247a11ea48e..f575724c6fc4715fd92fa41cfcb00a4846c71bcd 100644 (file)
@@ -129,7 +129,7 @@ convert_data(Host, "accounts", User, [Data]) ->
            Pass
     end,
     case ejabberd_auth:try_register(User, Host, Password) of
-       {atomic, ok} ->
+       ok ->
            ok;
        Err ->
            ?ERROR_MSG("failed to register user ~s@~s: ~p",
index 76be5f806ae7a4458ea521012695d57efdbb6e3e..6bd96002aa8ce38c97b32b6e2229c74e0465e308 100644 (file)
@@ -468,8 +468,7 @@ re_register(Config) ->
     User = ?config(user, Config),
     Server = ?config(server, Config),
     Pass = ?config(password, Config),
-    {atomic, ok} = ejabberd_auth:try_register(User, Server, Pass),
-    ok.
+    ok = ejabberd_auth:try_register(User, Server, Pass).
 
 match_failure(Received, [Match]) when is_list(Match)->
     ct:fail("Received input:~n~n~p~n~ndon't match expected patterns:~n~n~s", [Received, Match]);