From: Badlop Date: Tue, 23 Dec 2008 01:02:44 +0000 (+0000) Subject: * src/cyrsasl_digest.erl: Check digest-uri in SASL digest X-Git-Tag: v2.1.0~18^2~510 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=af2fa5b5f53106e9d374ce654876f2c7e0cec0cf;p=ejabberd * src/cyrsasl_digest.erl: Check digest-uri in SASL digest authentication (thanks to Paul Guyot)(EJAB-569) SVN Revision: 1743 --- diff --git a/ChangeLog b/ChangeLog index 7cb4969b5..8574d1808 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2008-12-23 Badlop + * src/cyrsasl_digest.erl: Check digest-uri in SASL digest + authentication (thanks to Paul Guyot)(EJAB-569) + * src/odbc/odbc_queries.erl: Fix removal of private_storage of an account when the account is removed @@ -7,9 +10,6 @@ account is removed (EJAB-720) * src/mod_privacy_odbc.erl: Likewise -2008-12-19 Christophe Romain - - 2008-12-19 Christophe Romain * src/mod_pubsub/mod_pubsub.erl: Fix send_last_published_item issue diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl index 5395205d7..0d27dbb68 100644 --- a/src/cyrsasl_digest.erl +++ b/src/cyrsasl_digest.erl @@ -18,7 +18,8 @@ -behaviour(cyrsasl). --record(state, {step, nonce, username, authzid, get_password, auth_module}). +-record(state, {step, nonce, username, authzid, get_password, auth_module, + host}). start(_Opts) -> cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, true). @@ -26,9 +27,10 @@ start(_Opts) -> stop() -> ok. -mech_new(_Host, GetPassword, _CheckPassword) -> +mech_new(Host, GetPassword, _CheckPassword) -> {ok, #state{step = 1, nonce = randoms:get_string(), + host = Host, get_password = GetPassword}}. mech_step(#state{step = 1, nonce = Nonce} = State, _) -> @@ -41,27 +43,35 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) -> bad -> {error, "bad-protocol"}; KeyVals -> + DigestURI = xml:get_attr_s("digest-uri", KeyVals), UserName = xml:get_attr_s("username", KeyVals), - AuthzId = xml:get_attr_s("authzid", KeyVals), - case (State#state.get_password)(UserName) of - {false, _} -> + case is_digesturi_valid(DigestURI, State#state.host) of + false -> + ?DEBUG("User login not authorized because digest-uri " + "seems invalid: ~p", [DigestURI]), {error, "not-authorized", UserName}; - {Passwd, AuthModule} -> - Response = response(KeyVals, UserName, Passwd, - Nonce, AuthzId, "AUTHENTICATE"), - case xml:get_attr_s("response", KeyVals) of - Response -> - RspAuth = response(KeyVals, - UserName, Passwd, - Nonce, AuthzId, ""), - {continue, - "rspauth=" ++ RspAuth, - State#state{step = 5, - auth_module = AuthModule, - username = UserName, - authzid = AuthzId}}; - _ -> - {error, "not-authorized", UserName} + true -> + AuthzId = xml:get_attr_s("authzid", KeyVals), + case (State#state.get_password)(UserName) of + {false, _} -> + {error, "not-authorized", UserName}; + {Passwd, AuthModule} -> + Response = response(KeyVals, UserName, Passwd, + Nonce, AuthzId, "AUTHENTICATE"), + case xml:get_attr_s("response", KeyVals) of + Response -> + RspAuth = response(KeyVals, + UserName, Passwd, + Nonce, AuthzId, ""), + {continue, + "rspauth=" ++ RspAuth, + State#state{step = 5, + auth_module = AuthModule, + username = UserName, + authzid = AuthzId}}; + _ -> + {error, "not-authorized", UserName} + end end end end; @@ -75,7 +85,6 @@ mech_step(A, B) -> ?DEBUG("SASL DIGEST: A ~p B ~p", [A,B]), {error, "bad-protocol"}. - parse(S) -> parse1(S, "", []). @@ -118,6 +127,23 @@ parse4([], Key, Val, Ts) -> parse1([], "", [{Key, lists:reverse(Val)} | Ts]). +%% @doc Check if the digest-uri is valid. +%% RFC-2831 allows to provide the IP address in Host, +%% however ejabberd doesn't allow that. +%% If the service (for example jabber.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 +%% In that case, ejabberd only checks the service name, not the host. +is_digesturi_valid(DigestURICase, JabberHost) -> + DigestURI = stringprep:tolower(DigestURICase), + case catch string:tokens(DigestURI, "/") of + ["xmpp", Host] when Host == JabberHost -> + true; + ["xmpp", _Host, ServName] when ServName == JabberHost -> + true; + _ -> + false + end.