aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBadlop <badlop@process-one.net>2012-03-16 14:16:17 +0100
committerBadlop <badlop@process-one.net>2012-03-16 14:16:17 +0100
commit983da9c887d6cb64812087cba961dc85f349e1f9 (patch)
treef9128c34253cb8e26939be7d82fe1bd64bad3383 /src
parentAssume we have only one CPU when an auto-detection fails (EJAB-1516) (diff)
Relax digest-uri handling (thanks to Daniel Willmann)(EJAB-1529)
This patch introduces a new config option - fqdn - to set the fully qualified domain name of the host: {fqdn, "foo.example.com"}. This fixes a problem with Pidgin not being able to log in on a server that used SRV records.
Diffstat (limited to 'src')
-rw-r--r--src/cyrsasl_digest.erl38
-rw-r--r--src/ejabberd.cfg.example3
-rw-r--r--src/ejabberd_config.erl3
3 files changed, 34 insertions, 10 deletions
diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl
index 99c8e2a0e..134a86daf 100644
--- a/src/cyrsasl_digest.erl
+++ b/src/cyrsasl_digest.erl
@@ -37,9 +37,11 @@
-behaviour(cyrsasl).
-record(state, {step, nonce, username, authzid, get_password, check_password, auth_module,
- host}).
+ host, hostfqdn}).
start(_Opts) ->
+ Fqdn = get_local_fqdn(),
+ ?INFO_MSG("FQDN used to check DIGEST-MD5 SASL authentication: ~p", [Fqdn]),
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, digest).
stop() ->
@@ -49,6 +51,7 @@ mech_new(Host, GetPassword, _CheckPassword, CheckPasswordDigest) ->
{ok, #state{step = 1,
nonce = randoms:get_string(),
host = Host,
+ hostfqdn = get_local_fqdn(),
get_password = GetPassword,
check_password = CheckPasswordDigest}}.
@@ -64,10 +67,11 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
KeyVals ->
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
UserName = xml:get_attr_s("username", KeyVals),
- case is_digesturi_valid(DigestURI, State#state.host) of
+ case is_digesturi_valid(DigestURI, State#state.host, State#state.hostfqdn) of
false ->
?DEBUG("User login not authorized because digest-uri "
- "seems invalid: ~p", [DigestURI]),
+ "seems invalid: ~p (checking for Host ~p, FQDN ~p)", [DigestURI,
+ State#state.host, State#state.hostfqdn]),
{error, "not-authorized", UserName};
true ->
AuthzId = xml:get_attr_s("authzid", KeyVals),
@@ -154,21 +158,35 @@ parse4([], Key, Val, Ts) ->
%% 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) ->
+%% then acceptable digest-uris would be:
+%% xmpp/server3.example.org/jabber.example.org, xmpp/server3.example.org and
+%% xmpp/jabber.example.org
+%% The last version is not actually allowed by the RFC, but implemented by popular clients
+is_digesturi_valid(DigestURICase, JabberDomain, JabberFQDN) ->
DigestURI = stringprep:tolower(DigestURICase),
case catch string:tokens(DigestURI, "/") of
- ["xmpp", Host] when Host == JabberHost ->
+ ["xmpp", Host] when (Host == JabberDomain) or (Host == JabberFQDN) ->
true;
- ["xmpp", _Host, ServName] when ServName == JabberHost ->
+ ["xmpp", Host, ServName] when (ServName == JabberDomain) and (Host == JabberFQDN) ->
true;
_ ->
false
end.
-
-
+get_local_fqdn() ->
+ case (catch get_local_fqdn2()) of
+ Str when is_list(Str) -> Str;
+ _ -> "unknown-fqdn, please configure fqdn option in ejabberd.cfg!"
+ end.
+get_local_fqdn2() ->
+ case ejabberd_config:get_local_option(fqdn) of
+ ConfiguredFqdn when is_list(ConfiguredFqdn) ->
+ ConfiguredFqdn;
+ _undefined ->
+ {ok, Hostname} = inet:gethostname(),
+ {ok, {hostent, Fqdn, _, _, _, _}} = inet:gethostbyname(Hostname),
+ Fqdn
+ end.
digit_to_xchar(D) when (D >= 0) and (D < 10) ->
D + 48;
diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example
index 57eab41bd..a4068ad96 100644
--- a/src/ejabberd.cfg.example
+++ b/src/ejabberd.cfg.example
@@ -222,6 +222,9 @@
%% Store the plain passwords or hashed for SCRAM:
%%{auth_password_format, plain}.
%%{auth_password_format, scram}.
+%%
+%% Define the FQDN if ejabberd doesn't detect it:
+%%{fqdn, "server3.example.com"}.
%%
%% Authentication using external script
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl
index b1b67fee7..503537e76 100644
--- a/src/ejabberd_config.erl
+++ b/src/ejabberd_config.erl
@@ -374,6 +374,9 @@ process_term(Term, State) ->
State;
{hosts, _Hosts} ->
State;
+ {fqdn, HostFQDN} ->
+ ?DEBUG("FQDN set to: ~p", [HostFQDN]),
+ add_option(fqdn, HostFQDN, State);
{host_config, Host, Terms} ->
lists:foldl(fun(T, S) -> process_host_term(T, Host, S) end,
State, Terms);