mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-30 23:02:00 +02:00
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.
This commit is contained in:
parent
f7b6446c74
commit
983da9c887
|
@ -1231,6 +1231,12 @@ The default value is \term{closeold}.
|
||||||
If the client uses old Jabber Non-SASL authentication (\xepref{0078}),
|
If the client uses old Jabber Non-SASL authentication (\xepref{0078}),
|
||||||
then this option is not respected, and the action performed is \term{closeold}.
|
then this option is not respected, and the action performed is \term{closeold}.
|
||||||
|
|
||||||
|
The option \option{fqdn} allows you to define the Fully Qualified Domain Name
|
||||||
|
of the machine, in case it isn't detected automatically.
|
||||||
|
The FQDN is used to authenticate some clients that use the DIGEST-MD5 SASL mechanism.
|
||||||
|
The option syntax is:
|
||||||
|
\esyntax{\{fqdn, undefined|FqdnString\}.}
|
||||||
|
|
||||||
\makesubsubsection{internalauth}{Internal}
|
\makesubsubsection{internalauth}{Internal}
|
||||||
\ind{internal authentication}\ind{Mnesia}
|
\ind{internal authentication}\ind{Mnesia}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,11 @@
|
||||||
-behaviour(cyrsasl).
|
-behaviour(cyrsasl).
|
||||||
|
|
||||||
-record(state, {step, nonce, username, authzid, get_password, check_password, auth_module,
|
-record(state, {step, nonce, username, authzid, get_password, check_password, auth_module,
|
||||||
host}).
|
host, hostfqdn}).
|
||||||
|
|
||||||
start(_Opts) ->
|
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).
|
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, digest).
|
||||||
|
|
||||||
stop() ->
|
stop() ->
|
||||||
|
@ -49,6 +51,7 @@ mech_new(Host, GetPassword, _CheckPassword, CheckPasswordDigest) ->
|
||||||
{ok, #state{step = 1,
|
{ok, #state{step = 1,
|
||||||
nonce = randoms:get_string(),
|
nonce = randoms:get_string(),
|
||||||
host = Host,
|
host = Host,
|
||||||
|
hostfqdn = get_local_fqdn(),
|
||||||
get_password = GetPassword,
|
get_password = GetPassword,
|
||||||
check_password = CheckPasswordDigest}}.
|
check_password = CheckPasswordDigest}}.
|
||||||
|
|
||||||
|
@ -64,10 +67,11 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
|
||||||
KeyVals ->
|
KeyVals ->
|
||||||
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
|
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
|
||||||
UserName = xml:get_attr_s("username", 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 ->
|
false ->
|
||||||
?DEBUG("User login not authorized because digest-uri "
|
?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};
|
{error, "not-authorized", UserName};
|
||||||
true ->
|
true ->
|
||||||
AuthzId = xml:get_attr_s("authzid", KeyVals),
|
AuthzId = xml:get_attr_s("authzid", KeyVals),
|
||||||
|
@ -154,21 +158,35 @@ parse4([], Key, Val, Ts) ->
|
||||||
%% however ejabberd doesn't allow that.
|
%% however ejabberd doesn't allow that.
|
||||||
%% If the service (for example jabber.example.org)
|
%% If the service (for example jabber.example.org)
|
||||||
%% 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 acceptable digest-uris would be:
|
||||||
%% In that case, ejabberd only checks the service name, not the host.
|
%% xmpp/server3.example.org/jabber.example.org, xmpp/server3.example.org and
|
||||||
is_digesturi_valid(DigestURICase, JabberHost) ->
|
%% 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),
|
DigestURI = stringprep:tolower(DigestURICase),
|
||||||
case catch string:tokens(DigestURI, "/") of
|
case catch string:tokens(DigestURI, "/") of
|
||||||
["xmpp", Host] when Host == JabberHost ->
|
["xmpp", Host] when (Host == JabberDomain) or (Host == JabberFQDN) ->
|
||||||
true;
|
true;
|
||||||
["xmpp", _Host, ServName] when ServName == JabberHost ->
|
["xmpp", Host, ServName] when (ServName == JabberDomain) and (Host == JabberFQDN) ->
|
||||||
true;
|
true;
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end.
|
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) ->
|
digit_to_xchar(D) when (D >= 0) and (D < 10) ->
|
||||||
D + 48;
|
D + 48;
|
||||||
|
|
|
@ -222,6 +222,9 @@
|
||||||
%% Store the plain passwords or hashed for SCRAM:
|
%% Store the plain passwords or hashed for SCRAM:
|
||||||
%%{auth_password_format, plain}.
|
%%{auth_password_format, plain}.
|
||||||
%%{auth_password_format, scram}.
|
%%{auth_password_format, scram}.
|
||||||
|
%%
|
||||||
|
%% Define the FQDN if ejabberd doesn't detect it:
|
||||||
|
%%{fqdn, "server3.example.com"}.
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%% Authentication using external script
|
%% Authentication using external script
|
||||||
|
|
|
@ -374,6 +374,9 @@ process_term(Term, State) ->
|
||||||
State;
|
State;
|
||||||
{hosts, _Hosts} ->
|
{hosts, _Hosts} ->
|
||||||
State;
|
State;
|
||||||
|
{fqdn, HostFQDN} ->
|
||||||
|
?DEBUG("FQDN set to: ~p", [HostFQDN]),
|
||||||
|
add_option(fqdn, HostFQDN, State);
|
||||||
{host_config, Host, Terms} ->
|
{host_config, Host, Terms} ->
|
||||||
lists:foldl(fun(T, S) -> process_host_term(T, Host, S) end,
|
lists:foldl(fun(T, S) -> process_host_term(T, Host, S) end,
|
||||||
State, Terms);
|
State, Terms);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user