diff options
author | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2016-12-31 13:47:35 +0300 |
---|---|---|
committer | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2017-01-02 14:55:06 +0300 |
commit | 666608544b558dccf59ac5c29c314ff11560041b (patch) | |
tree | a69efd638a588832d7a58847dc84a37c55e2ef88 /src/cyrsasl.erl | |
parent | Fix case clauses when using compression (#1431)(thanks to Evgeniy Khramtsov) (diff) |
Improve return values in cyrsasl API
Diffstat (limited to 'src/cyrsasl.erl')
-rw-r--r-- | src/cyrsasl.erl | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index 4b0f5a26..1edf4467 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -31,18 +31,11 @@ -export([start/0, register_mechanism/3, listmech/1, server_new/7, server_start/3, server_step/2, - opt_type/1]). + get_mech/1, format_error/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -%% --export_type([ - mechanism/0, - mechanisms/0, - sasl_mechanism/0 -]). - -record(sasl_mechanism, {mechanism = <<"">> :: mechanism() | '$1', module :: atom(), @@ -51,12 +44,22 @@ -type(mechanism() :: binary()). -type(mechanisms() :: [mechanism(),...]). -type(password_type() :: plain | digest | scram). --type(props() :: [{username, binary()} | - {authzid, binary()} | - {auth_module, atom()}]). +-type sasl_property() :: {username, binary()} | + {authzid, binary()} | + {mechanism, binary()} | + {auth_module, atom()}. +-type sasl_return() :: {ok, [sasl_property()]} | + {ok, [sasl_property()], binary()} | + {continue, binary(), sasl_state()} | + {error, atom(), binary()}. -type(sasl_mechanism() :: #sasl_mechanism{}). - +-type error_reason() :: cyrsasl_digest:error_reason() | + cyrsasl_oauth:error_reason() | + cyrsasl_plain:error_reason() | + cyrsasl_scram:error_reason() | + unsupported_mechanism | nodeprep_failed | + empty_username | aborted. -record(sasl_state, { service, @@ -65,16 +68,16 @@ get_password, check_password, check_password_digest, + mech_name = <<"">>, mech_mod, mech_state }). +-type sasl_state() :: #sasl_state{}. +-export_type([mechanism/0, mechanisms/0, sasl_mechanism/0, error_reason/0, + sasl_state/0, sasl_return/0, sasl_property/0]). -callback mech_new(binary(), fun(), fun(), fun()) -> any(). --callback mech_step(any(), binary()) -> {ok, props()} | - {ok, props(), binary()} | - {continue, binary(), any()} | - {error, atom()} | - {error, atom(), binary()}. +-callback mech_step(any(), binary()) -> sasl_return(). start() -> ets:new(sasl_mechanism, @@ -87,7 +90,25 @@ start() -> cyrsasl_oauth:start([]), ok. -%% +-spec format_error(mechanism() | sasl_state(), error_reason()) -> {atom(), binary()}. +format_error(_, unsupported_mechanism) -> + {'invalid-mechanism', <<"Unsupported mechanism">>}; +format_error(_, nodeprep_failed) -> + {'bad-protocol', <<"Nodeprep failed">>}; +format_error(_, empty_username) -> + {'bad-protocol', <<"Empty username">>}; +format_error(_, aborted) -> + {'aborted', <<"Aborted">>}; +format_error(#sasl_state{mech_mod = Mod}, Reason) -> + Mod:format_error(Reason); +format_error(Mech, Reason) -> + case ets:lookup(sasl_mechanism, Mech) of + [#sasl_mechanism{module = Mod}] -> + Mod:format_error(Reason); + [] -> + {'invalid-mechanism', <<"Unsupported mechanism">>} + end. + -spec register_mechanism(Mechanim :: mechanism(), Module :: module(), PasswordType :: password_type()) -> any(). @@ -105,8 +126,8 @@ register_mechanism(Mechanism, Module, PasswordType) -> check_credentials(_State, Props) -> User = proplists:get_value(authzid, Props, <<>>), case jid:nodeprep(User) of - error -> {error, 'not-authorized'}; - <<"">> -> {error, 'not-authorized'}; + error -> {error, nodeprep_failed}; + <<"">> -> {error, empty_username}; _LUser -> ok end. @@ -128,6 +149,8 @@ listmech(Host) -> ['$1']}]), filter_anonymous(Host, Mechs). +-spec server_new(binary(), binary(), binary(), term(), + fun(), fun(), fun()) -> sasl_state(). server_new(Service, ServerFQDN, UserRealm, _SecFlags, GetPassword, CheckPassword, CheckPasswordDigest) -> #sasl_state{service = Service, myname = ServerFQDN, @@ -135,8 +158,7 @@ server_new(Service, ServerFQDN, UserRealm, _SecFlags, check_password = CheckPassword, check_password_digest = CheckPasswordDigest}. -server_start(State, Mech, undefined) -> - server_start(State, Mech, <<"">>); +-spec server_start(sasl_state(), mechanism(), binary()) -> sasl_return(). server_start(State, Mech, ClientIn) -> case lists:member(Mech, listmech(State#sasl_state.myname)) @@ -150,15 +172,15 @@ server_start(State, Mech, ClientIn) -> State#sasl_state.check_password, State#sasl_state.check_password_digest), server_step(State#sasl_state{mech_mod = Module, + mech_name = Mech, mech_state = MechState}, ClientIn); - _ -> {error, 'no-mechanism'} + _ -> {error, unsupported_mechanism, <<"">>} end; - false -> {error, 'no-mechanism'} + false -> {error, unsupported_mechanism, <<"">>} end. -server_step(State, undefined) -> - server_step(State, <<"">>); +-spec server_step(sasl_state(), binary()) -> sasl_return(). server_step(State, ClientIn) -> Module = State#sasl_state.mech_mod, MechState = State#sasl_state.mech_state, @@ -166,21 +188,25 @@ server_step(State, ClientIn) -> {ok, Props} -> case check_credentials(State, Props) of ok -> {ok, Props}; - {error, Error} -> {error, Error} + {error, Error} -> {error, Error, <<"">>} end; {ok, Props, ServerOut} -> case check_credentials(State, Props) of ok -> {ok, Props, ServerOut}; - {error, Error} -> {error, Error} + {error, Error} -> {error, Error, <<"">>} end; {continue, ServerOut, NewMechState} -> {continue, ServerOut, State#sasl_state{mech_state = NewMechState}}; {error, Error, Username} -> {error, Error, Username}; {error, Error} -> - {error, Error} + {error, Error, <<"">>} end. +-spec get_mech(sasl_state()) -> binary(). +get_mech(#sasl_state{mech_name = Mech}) -> + Mech. + %% Remove the anonymous mechanism from the list if not enabled for the given %% host %% |