diff options
author | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2017-05-11 14:37:21 +0300 |
---|---|---|
committer | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2017-05-11 14:37:21 +0300 |
commit | 633b68db1130c81551b063f3aa15d599b0d355e5 (patch) | |
tree | df2f0be4b75b001e8e47d1778e8e01637a9dfbcd /src/ejabberd_auth_riak.erl | |
parent | Use misc:atom_to_binary/1 instead of the deprecated jlib.erl (#1510) (diff) |
Use cache for authentication backends
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`.
Diffstat (limited to 'src/ejabberd_auth_riak.erl')
-rw-r--r-- | src/ejabberd_auth_riak.erl | 264 |
1 files changed, 33 insertions, 231 deletions
diff --git a/src/ejabberd_auth_riak.erl b/src/ejabberd_auth_riak.erl index 74f0f73ca..fccaba102 100644 --- a/src/ejabberd_auth_riak.erl +++ b/src/ejabberd_auth_riak.erl @@ -32,15 +32,10 @@ -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"). @@ -49,258 +44,65 @@ -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, |