25
1
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:
Jean-Sébastien Pédron 2009-01-23 10:10:33 +00:00
parent 35926b96b4
commit b5c8b99272
5 changed files with 236 additions and 25 deletions

View File

@ -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> 2009-01-23 Badlop <badlop@process-one.net>
* src/odbc/mysql.sql: Fix complain about comment syntax * src/odbc/mysql.sql: Fix complain about comment syntax

View File

@ -34,18 +34,39 @@
server_start/3, server_start/3,
server_step/2]). 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}). -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, -record(sasl_state, {service, myname, realm,
get_password, check_password, get_password, check_password,
mech_mod, mech_state}). mech_mod, mech_state}).
-export([behaviour_info/1]). -export([behaviour_info/1]).
%% @hidden
behaviour_info(callbacks) -> behaviour_info(callbacks) ->
[{mech_new, 3}, {mech_step, 2}]; [{mech_new, 3}, {mech_step, 2}];
behaviour_info(_Other) -> behaviour_info(_Other) ->
undefined. undefined.
%% @spec () -> ok
start() -> start() ->
ets:new(sasl_mechanism, [named_table, ets:new(sasl_mechanism, [named_table,
public, public,
@ -55,35 +76,46 @@ start() ->
cyrsasl_anonymous:start([]), cyrsasl_anonymous:start([]),
ok. ok.
%% @spec (Mechanism, Module, Require_Plain) -> true
%% Mechanism = string()
%% Module = atom()
%% Require_Plain = bool()
register_mechanism(Mechanism, Module, RequirePlainPassword) -> register_mechanism(Mechanism, Module, RequirePlainPassword) ->
ets:insert(sasl_mechanism, ets:insert(sasl_mechanism,
#sasl_mechanism{mechanism = Mechanism, #sasl_mechanism{mechanism = Mechanism,
module = Module, module = Module,
require_plain_password = RequirePlainPassword}). require_plain_password = RequirePlainPassword}).
%%% TODO: use callbacks % TODO use callbacks
%%-include("ejabberd.hrl"). %-include("ejabberd.hrl").
%%-include("jlib.hrl"). %-include("jlib.hrl").
%%check_authzid(_State, Props) -> %check_authzid(_State, Props) ->
%% AuthzId = xml:get_attr_s(authzid, Props), % AuthzId = xml:get_attr_s(authzid, Props),
%% case jlib:string_to_jid(AuthzId) of % case jlib:string_to_jid(AuthzId) of
%% error -> % error ->
%% {error, "invalid-authzid"}; % {error, "invalid-authzid"};
%% JID -> % JID ->
%% LUser = jlib:nodeprep(xml:get_attr_s(username, Props)), % LUser = jlib:nodeprep(xml:get_attr_s(username, Props)),
%% {U, S, R} = jlib:jid_tolower(JID), % {U, S, R} = jlib:jid_tolower(JID),
%% case R of % case R of
%% "" -> % "" ->
%% {error, "invalid-authzid"}; % {error, "invalid-authzid"};
%% _ -> % _ ->
%% case {LUser, ?MYNAME} of % case {LUser, ?MYNAME} of
%% {U, S} -> % {U, S} ->
%% ok; % ok;
%% _ -> % _ ->
%% {error, "invalid-authzid"} % {error, "invalid-authzid"}
%% end % end
%% end % end
%% end. % end.
%% @spec (State, Props) -> ok | {error, 'not-authorized'}
%% State = saslstate()
%% Props = [{Key, Value}]
%% Key = atom()
%% Value = string()
check_credentials(_State, Props) -> check_credentials(_State, Props) ->
case proplists:get_value(username, Props) of case proplists:get_value(username, Props) of
@ -96,6 +128,10 @@ check_credentials(_State, Props) ->
end end
end. end.
%% @spec (Host) -> [Mechanism]
%% Host = string()
%% Mechanism = string()
listmech(Host) -> listmech(Host) ->
RequirePlainPassword = ejabberd_auth:plain_password_required(Host), RequirePlainPassword = ejabberd_auth:plain_password_required(Host),
@ -112,6 +148,14 @@ listmech(Host) ->
['$1']}]), ['$1']}]),
filter_anonymous(Host, Mechs). 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, server_new(Service, ServerFQDN, UserRealm, _SecFlags,
GetPassword, CheckPassword) -> GetPassword, CheckPassword) ->
#sasl_state{service = Service, #sasl_state{service = Service,
@ -120,6 +164,22 @@ server_new(Service, ServerFQDN, UserRealm, _SecFlags,
get_password = GetPassword, get_password = GetPassword,
check_password = CheckPassword}. 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) -> server_start(State, Mech, ClientIn) ->
case lists:member(Mech, listmech(State#sasl_state.myname)) of case lists:member(Mech, listmech(State#sasl_state.myname)) of
true -> true ->
@ -139,6 +199,21 @@ server_start(State, Mech, ClientIn) ->
{error, 'invalid-mechanism'} {error, 'invalid-mechanism'}
end. 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) -> server_step(State, ClientIn) ->
Module = State#sasl_state.mech_mod, Module = State#sasl_state.mech_mod,
MechState = State#sasl_state.mech_state, MechState = State#sasl_state.mech_state,
@ -159,8 +234,15 @@ server_step(State, ClientIn) ->
{error, Error} {error, Error}
end. end.
%% Remove the anonymous mechanism from the list if not enabled for the given %% @spec (Host, Mechs) -> [Filtered_Mechs]
%% host %% 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) -> filter_anonymous(Host, Mechs) ->
case ejabberd_auth_anonymous:is_sasl_anonymous_enabled(Host) of case ejabberd_auth_anonymous:is_sasl_anonymous_enabled(Host) of
true -> Mechs; true -> Mechs;

View File

@ -31,18 +31,42 @@
-behaviour(cyrsasl). -behaviour(cyrsasl).
%% @type mechstate() = {state, Server}
%% Server = string().
-record(state, {server}). -record(state, {server}).
%% @spec (Opts) -> true
%% Opts = term()
start(_Opts) -> start(_Opts) ->
cyrsasl:register_mechanism("ANONYMOUS", ?MODULE, false), cyrsasl:register_mechanism("ANONYMOUS", ?MODULE, false),
ok. ok.
%% @spec () -> ok
stop() -> stop() ->
ok. ok.
%% @spec (Host, GetPassword, CheckPassword) -> {ok, State}
%% Host = string()
%% GetPassword = function()
%% CheckPassword = function()
%% State = mechstate()
mech_new(Host, _GetPassword, _CheckPassword) -> mech_new(Host, _GetPassword, _CheckPassword) ->
{ok, #state{server = Host}}. {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) -> mech_step(State, _ClientIn) ->
%% We generate a random username: %% We generate a random username:
User = lists:concat([randoms:get_string() | tuple_to_list(now())]), User = lists:concat([randoms:get_string() | tuple_to_list(now())]),

View File

@ -18,21 +18,56 @@
-behaviour(cyrsasl). -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, -record(state, {step, nonce, username, authzid, get_password, auth_module,
host}). host}).
%% @spec (Opts) -> true
%% Opts = term()
start(_Opts) -> start(_Opts) ->
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, true). cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, true).
%% @spec () -> ok
stop() -> stop() ->
ok. ok.
%% @spec (Host, GetPassword, CheckPassword) -> {ok, State}
%% Host = string()
%% GetPassword = function()
%% CheckPassword = function()
%% State = mechstate()
mech_new(Host, GetPassword, _CheckPassword) -> mech_new(Host, GetPassword, _CheckPassword) ->
{ok, #state{step = 1, {ok, #state{step = 1,
nonce = randoms:get_string(), nonce = randoms:get_string(),
host = Host, host = Host,
get_password = GetPassword}}. 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, _) -> mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
{continue, {continue,
"nonce=\"" ++ Nonce ++ "nonce=\"" ++ Nonce ++
@ -85,9 +120,16 @@ mech_step(A, B) ->
?DEBUG("SASL DIGEST: A ~p B ~p", [A,B]), ?DEBUG("SASL DIGEST: A ~p B ~p", [A,B]),
{error, 'bad-protocol'}. {error, 'bad-protocol'}.
%% @spec (S) -> [{Key, Value}] | bad
%% S = string()
%% Key = string()
%% Value = string()
parse(S) -> parse(S) ->
parse1(S, "", []). parse1(S, "", []).
%% @hidden
parse1([$= | Cs], S, Ts) -> parse1([$= | Cs], S, Ts) ->
parse2(Cs, lists:reverse(S), "", Ts); parse2(Cs, lists:reverse(S), "", Ts);
parse1([$, | Cs], [], Ts) -> parse1([$, | Cs], [], Ts) ->
@ -101,6 +143,8 @@ parse1([], [], T) ->
parse1([], _S, _T) -> parse1([], _S, _T) ->
bad. bad.
%% @hidden
parse2([$\" | Cs], Key, Val, Ts) -> parse2([$\" | Cs], Key, Val, Ts) ->
parse3(Cs, Key, Val, Ts); parse3(Cs, Key, Val, Ts);
parse2([C | Cs], Key, Val, Ts) -> parse2([C | Cs], Key, Val, Ts) ->
@ -108,6 +152,8 @@ parse2([C | Cs], Key, Val, Ts) ->
parse2([], _, _, _) -> parse2([], _, _, _) ->
bad. bad.
%% @hidden
parse3([$\" | Cs], Key, Val, Ts) -> parse3([$\" | Cs], Key, Val, Ts) ->
parse4(Cs, Key, Val, Ts); parse4(Cs, Key, Val, Ts);
parse3([$\\, C | Cs], Key, Val, Ts) -> parse3([$\\, C | Cs], Key, Val, Ts) ->
@ -117,6 +163,8 @@ parse3([C | Cs], Key, Val, Ts) ->
parse3([], _, _, _) -> parse3([], _, _, _) ->
bad. bad.
%% @hidden
parse4([$, | Cs], Key, Val, Ts) -> parse4([$, | Cs], Key, Val, Ts) ->
parse1(Cs, "", [{Key, lists:reverse(Val)} | Ts]); parse1(Cs, "", [{Key, lists:reverse(Val)} | Ts]);
parse4([$\s | Cs], Key, Val, Ts) -> parse4([$\s | Cs], Key, Val, Ts) ->
@ -127,6 +175,10 @@ parse4([], Key, Val, Ts) ->
parse1([], "", [{Key, lists:reverse(Val)} | Ts]). parse1([], "", [{Key, lists:reverse(Val)} | Ts]).
%% @spec (DigestURICase, JabberHost) -> bool()
%% DigestURICase = string()
%% JabberHost = string()
%%
%% @doc Check if the digest-uri is valid. %% @doc Check if the digest-uri is valid.
%% RFC-2831 allows to provide the IP address in Host, %% RFC-2831 allows to provide the IP address in Host,
%% however ejabberd doesn't allow that. %% 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), %% 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 %% 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. %% In that case, ejabberd only checks the service name, not the host.
is_digesturi_valid(DigestURICase, JabberHost) -> is_digesturi_valid(DigestURICase, JabberHost) ->
DigestURI = exmpp_stringprep:to_lower(DigestURICase), DigestURI = exmpp_stringprep:to_lower(DigestURICase),
case catch string:tokens(DigestURI, "/") of 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) -> digit_to_xchar(D) when (D >= 0) and (D < 10) ->
D + 48; D + 48;
digit_to_xchar(D) -> digit_to_xchar(D) ->
D + 87. D + 87.
%% @hidden
hex(S) -> hex(S) ->
hex(S, []). hex(S, []).
%% @hidden
hex([], Res) -> hex([], Res) ->
lists:reverse(Res); lists:reverse(Res);
hex([N | Ns], Res) -> hex([N | Ns], Res) ->
@ -163,6 +222,16 @@ hex([N | Ns], Res) ->
digit_to_xchar(N div 16) | 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) -> response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) ->
Realm = proplists:get_value("realm", KeyVals, ""), Realm = proplists:get_value("realm", KeyVals, ""),
CNonce = proplists:get_value("cnonce", KeyVals, ""), CNonce = proplists:get_value("cnonce", KeyVals, ""),

View File

@ -31,18 +31,44 @@
-behaviour(cyrsasl). -behaviour(cyrsasl).
%% @type mechstate() = {state, CheckPassword}
%% CheckPassword = function().
-record(state, {check_password}). -record(state, {check_password}).
%% @spec (Opts) -> true
%% Opts = term()
start(_Opts) -> start(_Opts) ->
cyrsasl:register_mechanism("PLAIN", ?MODULE, false), cyrsasl:register_mechanism("PLAIN", ?MODULE, false),
ok. ok.
%% @spec () -> ok
stop() -> stop() ->
ok. ok.
%% @spec (Host, GetPassword, CheckPassword) -> {ok, State}
%% Host = string()
%% GetPassword = function()
%% CheckPassword = function()
%% State = mechstate()
mech_new(_Host, _GetPassword, CheckPassword) -> mech_new(_Host, _GetPassword, CheckPassword) ->
{ok, #state{check_password = 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) -> mech_step(State, ClientIn) ->
case parse(ClientIn) of case parse(ClientIn) of
[AuthzId, User, Password] -> [AuthzId, User, Password] ->
@ -58,9 +84,13 @@ mech_step(State, ClientIn) ->
end. end.
%% @hidden
parse(S) -> parse(S) ->
parse1(S, "", []). parse1(S, "", []).
%% @hidden
parse1([0 | Cs], S, T) -> parse1([0 | Cs], S, T) ->
parse1(Cs, "", [lists:reverse(S) | T]); parse1(Cs, "", [lists:reverse(S) | T]);
parse1([C | Cs], S, T) -> parse1([C | Cs], S, T) ->