mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-26 16:26:24 +01:00
Document every functions to clarify the types to give and returned.
PR: EJABP-1 SVN Revision: 1852
This commit is contained in:
parent
35926b96b4
commit
b5c8b99272
@ -1,3 +1,9 @@
|
||||
2009-01-23 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
|
||||
|
||||
* src/cyrsasl.erl, src/cyrsasl_plain.erl, src/cyrsasl_anonymous.erl,
|
||||
src/cyrsasl_digest.erl: Document every functions to clarify the types
|
||||
to give and returned.
|
||||
|
||||
2009-01-23 Badlop <badlop@process-one.net>
|
||||
|
||||
* src/odbc/mysql.sql: Fix complain about comment syntax
|
||||
|
132
src/cyrsasl.erl
132
src/cyrsasl.erl
@ -34,18 +34,39 @@
|
||||
server_start/3,
|
||||
server_step/2]).
|
||||
|
||||
%% @type saslmechanism() = {sasl_mechanism, Mechanism, Module, Require_Plain}
|
||||
%% Mechanism = string()
|
||||
%% Module = atom()
|
||||
%% Require_Plain = bool().
|
||||
%% Registry entry of a supported SASL mechanism.
|
||||
|
||||
-record(sasl_mechanism, {mechanism, module, require_plain_password}).
|
||||
|
||||
%% @type saslstate() = {sasl_state, Service, Myname, Realm, GetPassword, CheckPassword, Mech_Mod, Mech_State}
|
||||
%% Service = string()
|
||||
%% Myname = string()
|
||||
%% Realm = string()
|
||||
%% GetPassword = function()
|
||||
%% CheckPassword = function()
|
||||
%% Mech_Mod = atom()
|
||||
%% Mech_State = term().
|
||||
%% State of this process.
|
||||
|
||||
-record(sasl_state, {service, myname, realm,
|
||||
get_password, check_password,
|
||||
mech_mod, mech_state}).
|
||||
|
||||
-export([behaviour_info/1]).
|
||||
|
||||
%% @hidden
|
||||
|
||||
behaviour_info(callbacks) ->
|
||||
[{mech_new, 3}, {mech_step, 2}];
|
||||
behaviour_info(_Other) ->
|
||||
undefined.
|
||||
|
||||
%% @spec () -> ok
|
||||
|
||||
start() ->
|
||||
ets:new(sasl_mechanism, [named_table,
|
||||
public,
|
||||
@ -55,35 +76,46 @@ start() ->
|
||||
cyrsasl_anonymous:start([]),
|
||||
ok.
|
||||
|
||||
%% @spec (Mechanism, Module, Require_Plain) -> true
|
||||
%% Mechanism = string()
|
||||
%% Module = atom()
|
||||
%% Require_Plain = bool()
|
||||
|
||||
register_mechanism(Mechanism, Module, RequirePlainPassword) ->
|
||||
ets:insert(sasl_mechanism,
|
||||
#sasl_mechanism{mechanism = Mechanism,
|
||||
module = Module,
|
||||
require_plain_password = RequirePlainPassword}).
|
||||
|
||||
%%% TODO: use callbacks
|
||||
%%-include("ejabberd.hrl").
|
||||
%%-include("jlib.hrl").
|
||||
%%check_authzid(_State, Props) ->
|
||||
%% AuthzId = xml:get_attr_s(authzid, Props),
|
||||
%% case jlib:string_to_jid(AuthzId) of
|
||||
%% error ->
|
||||
%% {error, "invalid-authzid"};
|
||||
%% JID ->
|
||||
%% LUser = jlib:nodeprep(xml:get_attr_s(username, Props)),
|
||||
%% {U, S, R} = jlib:jid_tolower(JID),
|
||||
%% case R of
|
||||
%% "" ->
|
||||
%% {error, "invalid-authzid"};
|
||||
%% _ ->
|
||||
%% case {LUser, ?MYNAME} of
|
||||
%% {U, S} ->
|
||||
%% ok;
|
||||
%% _ ->
|
||||
%% {error, "invalid-authzid"}
|
||||
%% end
|
||||
%% end
|
||||
%% end.
|
||||
% TODO use callbacks
|
||||
%-include("ejabberd.hrl").
|
||||
%-include("jlib.hrl").
|
||||
%check_authzid(_State, Props) ->
|
||||
% AuthzId = xml:get_attr_s(authzid, Props),
|
||||
% case jlib:string_to_jid(AuthzId) of
|
||||
% error ->
|
||||
% {error, "invalid-authzid"};
|
||||
% JID ->
|
||||
% LUser = jlib:nodeprep(xml:get_attr_s(username, Props)),
|
||||
% {U, S, R} = jlib:jid_tolower(JID),
|
||||
% case R of
|
||||
% "" ->
|
||||
% {error, "invalid-authzid"};
|
||||
% _ ->
|
||||
% case {LUser, ?MYNAME} of
|
||||
% {U, S} ->
|
||||
% ok;
|
||||
% _ ->
|
||||
% {error, "invalid-authzid"}
|
||||
% end
|
||||
% end
|
||||
% end.
|
||||
|
||||
%% @spec (State, Props) -> ok | {error, 'not-authorized'}
|
||||
%% State = saslstate()
|
||||
%% Props = [{Key, Value}]
|
||||
%% Key = atom()
|
||||
%% Value = string()
|
||||
|
||||
check_credentials(_State, Props) ->
|
||||
case proplists:get_value(username, Props) of
|
||||
@ -96,6 +128,10 @@ check_credentials(_State, Props) ->
|
||||
end
|
||||
end.
|
||||
|
||||
%% @spec (Host) -> [Mechanism]
|
||||
%% Host = string()
|
||||
%% Mechanism = string()
|
||||
|
||||
listmech(Host) ->
|
||||
RequirePlainPassword = ejabberd_auth:plain_password_required(Host),
|
||||
|
||||
@ -112,6 +148,14 @@ listmech(Host) ->
|
||||
['$1']}]),
|
||||
filter_anonymous(Host, Mechs).
|
||||
|
||||
%% @spec (Service, ServerFQDN, UserRealm, SecFlags, GetPassword, CheckPassword) -> saslstate()
|
||||
%% Service = string()
|
||||
%% ServerFQDN = string()
|
||||
%% UserRealm = string()
|
||||
%% SecFlags = [term()]
|
||||
%% GetPassword = function()
|
||||
%% CheckPassword = function()
|
||||
|
||||
server_new(Service, ServerFQDN, UserRealm, _SecFlags,
|
||||
GetPassword, CheckPassword) ->
|
||||
#sasl_state{service = Service,
|
||||
@ -120,6 +164,22 @@ server_new(Service, ServerFQDN, UserRealm, _SecFlags,
|
||||
get_password = GetPassword,
|
||||
check_password = CheckPassword}.
|
||||
|
||||
%% @spec (State, Mech, ClientIn) -> Ok | Continue | Error
|
||||
%% State = saslstate()
|
||||
%% Mech = string()
|
||||
%% ClientIn = string()
|
||||
%% Ok = {ok, Props}
|
||||
%% Props = [Prop]
|
||||
%% Prop = [{Key, Value}]
|
||||
%% Key = atom()
|
||||
%% Value = string()
|
||||
%% Continue = {continue, ServerOut, New_State}
|
||||
%% ServerOut = string()
|
||||
%% New_State = saslstate()
|
||||
%% Error = {error, Reason} | {error, Username, Reason}
|
||||
%% Reason = term()
|
||||
%% Username = string()
|
||||
|
||||
server_start(State, Mech, ClientIn) ->
|
||||
case lists:member(Mech, listmech(State#sasl_state.myname)) of
|
||||
true ->
|
||||
@ -139,6 +199,21 @@ server_start(State, Mech, ClientIn) ->
|
||||
{error, 'invalid-mechanism'}
|
||||
end.
|
||||
|
||||
%% @spec (State, ClientIn) -> Ok | Continue | Error
|
||||
%% State = saslstate()
|
||||
%% ClientIn = string()
|
||||
%% Ok = {ok, Props}
|
||||
%% Props = [Prop]
|
||||
%% Prop = [{Key, Value}]
|
||||
%% Key = atom()
|
||||
%% Value = string()
|
||||
%% Continue = {continue, ServerOut, New_State}
|
||||
%% ServerOut = string()
|
||||
%% New_State = saslstate()
|
||||
%% Error = {error, Reason} | {error, Username, Reason}
|
||||
%% Reason = term()
|
||||
%% Username = string()
|
||||
|
||||
server_step(State, ClientIn) ->
|
||||
Module = State#sasl_state.mech_mod,
|
||||
MechState = State#sasl_state.mech_state,
|
||||
@ -159,8 +234,15 @@ server_step(State, ClientIn) ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
%% Remove the anonymous mechanism from the list if not enabled for the given
|
||||
%% host
|
||||
%% @spec (Host, Mechs) -> [Filtered_Mechs]
|
||||
%% Host = string()
|
||||
%% Mechs = [Mech]
|
||||
%% Mech = string()
|
||||
%% Filtered_Mechs = [Mech]
|
||||
%%
|
||||
%% @doc Remove the anonymous mechanism from the list if not enabled for
|
||||
%% the given host.
|
||||
|
||||
filter_anonymous(Host, Mechs) ->
|
||||
case ejabberd_auth_anonymous:is_sasl_anonymous_enabled(Host) of
|
||||
true -> Mechs;
|
||||
|
@ -31,18 +31,42 @@
|
||||
|
||||
-behaviour(cyrsasl).
|
||||
|
||||
%% @type mechstate() = {state, Server}
|
||||
%% Server = string().
|
||||
|
||||
-record(state, {server}).
|
||||
|
||||
%% @spec (Opts) -> true
|
||||
%% Opts = term()
|
||||
|
||||
start(_Opts) ->
|
||||
cyrsasl:register_mechanism("ANONYMOUS", ?MODULE, false),
|
||||
ok.
|
||||
|
||||
%% @spec () -> ok
|
||||
|
||||
stop() ->
|
||||
ok.
|
||||
|
||||
%% @spec (Host, GetPassword, CheckPassword) -> {ok, State}
|
||||
%% Host = string()
|
||||
%% GetPassword = function()
|
||||
%% CheckPassword = function()
|
||||
%% State = mechstate()
|
||||
|
||||
mech_new(Host, _GetPassword, _CheckPassword) ->
|
||||
{ok, #state{server = Host}}.
|
||||
|
||||
%% @spec (State, ClientIn) -> Ok | Error
|
||||
%% State = mechstate()
|
||||
%% ClientIn = string()
|
||||
%% Ok = {ok, Props}
|
||||
%% Props = [Prop]
|
||||
%% Prop = {username, Username} | {auth_module, AuthModule}
|
||||
%% Username = string()
|
||||
%% AuthModule = ejabberd_auth_anonymous
|
||||
%% Error = {error, 'not-authorized'}
|
||||
|
||||
mech_step(State, _ClientIn) ->
|
||||
%% We generate a random username:
|
||||
User = lists:concat([randoms:get_string() | tuple_to_list(now())]),
|
||||
|
@ -18,21 +18,56 @@
|
||||
|
||||
-behaviour(cyrsasl).
|
||||
|
||||
%% @type mechstate() = {state, Step, Nonce, Username, AuthzId, GetPassword, AuthModule, Host}
|
||||
%% Step = 1 | 3 | 5
|
||||
%% Nonce = string()
|
||||
%% Username = string()
|
||||
%% AuthzId = string()
|
||||
%% GetPassword = function()
|
||||
%% AuthModule = atom()
|
||||
%% Host = string().
|
||||
|
||||
-record(state, {step, nonce, username, authzid, get_password, auth_module,
|
||||
host}).
|
||||
|
||||
%% @spec (Opts) -> true
|
||||
%% Opts = term()
|
||||
|
||||
start(_Opts) ->
|
||||
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, true).
|
||||
|
||||
%% @spec () -> ok
|
||||
|
||||
stop() ->
|
||||
ok.
|
||||
|
||||
%% @spec (Host, GetPassword, CheckPassword) -> {ok, State}
|
||||
%% Host = string()
|
||||
%% GetPassword = function()
|
||||
%% CheckPassword = function()
|
||||
%% State = mechstate()
|
||||
|
||||
mech_new(Host, GetPassword, _CheckPassword) ->
|
||||
{ok, #state{step = 1,
|
||||
nonce = randoms:get_string(),
|
||||
host = Host,
|
||||
get_password = GetPassword}}.
|
||||
|
||||
%% @spec (State, ClientIn) -> Ok | Continue | Error
|
||||
%% State = mechstate()
|
||||
%% ClientIn = string()
|
||||
%% Ok = {ok, Props}
|
||||
%% Props = [Prop]
|
||||
%% Prop = {username, Username} | {authzid, AuthzId} | {auth_module, AuthModule}
|
||||
%% Username = string()
|
||||
%% AuthzId = string()
|
||||
%% AuthModule = atom()
|
||||
%% Continue = {continue, ServerOut, New_State}
|
||||
%% ServerOut = string()
|
||||
%% New_State = mechstate()
|
||||
%% Error = {error, Reason} | {error, Reason, Username}
|
||||
%% Reason = term()
|
||||
|
||||
mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
|
||||
{continue,
|
||||
"nonce=\"" ++ Nonce ++
|
||||
@ -85,9 +120,16 @@ mech_step(A, B) ->
|
||||
?DEBUG("SASL DIGEST: A ~p B ~p", [A,B]),
|
||||
{error, 'bad-protocol'}.
|
||||
|
||||
%% @spec (S) -> [{Key, Value}] | bad
|
||||
%% S = string()
|
||||
%% Key = string()
|
||||
%% Value = string()
|
||||
|
||||
parse(S) ->
|
||||
parse1(S, "", []).
|
||||
|
||||
%% @hidden
|
||||
|
||||
parse1([$= | Cs], S, Ts) ->
|
||||
parse2(Cs, lists:reverse(S), "", Ts);
|
||||
parse1([$, | Cs], [], Ts) ->
|
||||
@ -101,6 +143,8 @@ parse1([], [], T) ->
|
||||
parse1([], _S, _T) ->
|
||||
bad.
|
||||
|
||||
%% @hidden
|
||||
|
||||
parse2([$\" | Cs], Key, Val, Ts) ->
|
||||
parse3(Cs, Key, Val, Ts);
|
||||
parse2([C | Cs], Key, Val, Ts) ->
|
||||
@ -108,6 +152,8 @@ parse2([C | Cs], Key, Val, Ts) ->
|
||||
parse2([], _, _, _) ->
|
||||
bad.
|
||||
|
||||
%% @hidden
|
||||
|
||||
parse3([$\" | Cs], Key, Val, Ts) ->
|
||||
parse4(Cs, Key, Val, Ts);
|
||||
parse3([$\\, C | Cs], Key, Val, Ts) ->
|
||||
@ -117,6 +163,8 @@ parse3([C | Cs], Key, Val, Ts) ->
|
||||
parse3([], _, _, _) ->
|
||||
bad.
|
||||
|
||||
%% @hidden
|
||||
|
||||
parse4([$, | Cs], Key, Val, Ts) ->
|
||||
parse1(Cs, "", [{Key, lists:reverse(Val)} | Ts]);
|
||||
parse4([$\s | Cs], Key, Val, Ts) ->
|
||||
@ -127,6 +175,10 @@ parse4([], Key, Val, Ts) ->
|
||||
parse1([], "", [{Key, lists:reverse(Val)} | Ts]).
|
||||
|
||||
|
||||
%% @spec (DigestURICase, JabberHost) -> bool()
|
||||
%% DigestURICase = string()
|
||||
%% JabberHost = string()
|
||||
%%
|
||||
%% @doc Check if the digest-uri is valid.
|
||||
%% RFC-2831 allows to provide the IP address in Host,
|
||||
%% however ejabberd doesn't allow that.
|
||||
@ -134,6 +186,7 @@ parse4([], Key, Val, Ts) ->
|
||||
%% is provided by several hosts (being one of them server3.example.org),
|
||||
%% then digest-uri can be like xmpp/server3.example.org/jabber.example.org
|
||||
%% In that case, ejabberd only checks the service name, not the host.
|
||||
|
||||
is_digesturi_valid(DigestURICase, JabberHost) ->
|
||||
DigestURI = exmpp_stringprep:to_lower(DigestURICase),
|
||||
case catch string:tokens(DigestURI, "/") of
|
||||
@ -148,14 +201,20 @@ is_digesturi_valid(DigestURICase, JabberHost) ->
|
||||
|
||||
|
||||
|
||||
%% @hidden
|
||||
|
||||
digit_to_xchar(D) when (D >= 0) and (D < 10) ->
|
||||
D + 48;
|
||||
digit_to_xchar(D) ->
|
||||
D + 87.
|
||||
|
||||
%% @hidden
|
||||
|
||||
hex(S) ->
|
||||
hex(S, []).
|
||||
|
||||
%% @hidden
|
||||
|
||||
hex([], Res) ->
|
||||
lists:reverse(Res);
|
||||
hex([N | Ns], Res) ->
|
||||
@ -163,6 +222,16 @@ hex([N | Ns], Res) ->
|
||||
digit_to_xchar(N div 16) | Res]).
|
||||
|
||||
|
||||
%% @spec (KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) -> string()
|
||||
%% KeyVals = [{Key, Value}]
|
||||
%% Key = string()
|
||||
%% Value = string()
|
||||
%% User = string()
|
||||
%% Passwd = string()
|
||||
%% Nonce = string()
|
||||
%% AuthzId = nil() | string()
|
||||
%% A2Prefix = string()
|
||||
|
||||
response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) ->
|
||||
Realm = proplists:get_value("realm", KeyVals, ""),
|
||||
CNonce = proplists:get_value("cnonce", KeyVals, ""),
|
||||
|
@ -31,18 +31,44 @@
|
||||
|
||||
-behaviour(cyrsasl).
|
||||
|
||||
%% @type mechstate() = {state, CheckPassword}
|
||||
%% CheckPassword = function().
|
||||
|
||||
-record(state, {check_password}).
|
||||
|
||||
%% @spec (Opts) -> true
|
||||
%% Opts = term()
|
||||
|
||||
start(_Opts) ->
|
||||
cyrsasl:register_mechanism("PLAIN", ?MODULE, false),
|
||||
ok.
|
||||
|
||||
%% @spec () -> ok
|
||||
|
||||
stop() ->
|
||||
ok.
|
||||
|
||||
%% @spec (Host, GetPassword, CheckPassword) -> {ok, State}
|
||||
%% Host = string()
|
||||
%% GetPassword = function()
|
||||
%% CheckPassword = function()
|
||||
%% State = mechstate()
|
||||
|
||||
mech_new(_Host, _GetPassword, CheckPassword) ->
|
||||
{ok, #state{check_password = CheckPassword}}.
|
||||
|
||||
%% @spec (State, ClientIn) -> Ok | Error
|
||||
%% State = mechstate()
|
||||
%% ClientIn = string()
|
||||
%% Ok = {ok, Props}
|
||||
%% Props = [Prop]
|
||||
%% Prop = {username, Username} | {authzid, AuthzId} | {auth_module, AuthModule}
|
||||
%% Username = string()
|
||||
%% AuthzId = string()
|
||||
%% AuthModule = atom()
|
||||
%% Error = {error, Reason} | {error, Reason, Username}
|
||||
%% Reason = term()
|
||||
|
||||
mech_step(State, ClientIn) ->
|
||||
case parse(ClientIn) of
|
||||
[AuthzId, User, Password] ->
|
||||
@ -58,9 +84,13 @@ mech_step(State, ClientIn) ->
|
||||
end.
|
||||
|
||||
|
||||
%% @hidden
|
||||
|
||||
parse(S) ->
|
||||
parse1(S, "", []).
|
||||
|
||||
%% @hidden
|
||||
|
||||
parse1([0 | Cs], S, T) ->
|
||||
parse1(Cs, "", [lists:reverse(S) | T]);
|
||||
parse1([C | Cs], S, T) ->
|
||||
|
Loading…
Reference in New Issue
Block a user