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>
* src/odbc/mysql.sql: Fix complain about comment syntax

View File

@ -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;

View File

@ -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())]),

View File

@ -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, ""),

View File

@ -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) ->