mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-28 16:34:13 +01:00
New ip_access option restricts which IPs can register (thanks to Alexey Shchepin)(EJAB-915)
This commit is contained in:
parent
6f3713a67d
commit
7f3a5066c6
@ -3779,6 +3779,12 @@ change it by defining access rule in this option. Use with care: allowing regist
|
|||||||
from s2s leads to uncontrolled massive accounts creation by rogue users.
|
from s2s leads to uncontrolled massive accounts creation by rogue users.
|
||||||
\titem{\{captcha\_protected, false|true\}} \ind{options!captcha\_protected}
|
\titem{\{captcha\_protected, false|true\}} \ind{options!captcha\_protected}
|
||||||
Protect registrations with CAPTCHA (see section \ref{captcha}). The default is \term{false}.
|
Protect registrations with CAPTCHA (see section \ref{captcha}). The default is \term{false}.
|
||||||
|
\titem{\{ip\_access, [ \{allow|deny, IPaddress\}, ...]\}} \ind{options!ip\_access}
|
||||||
|
Define rules to allow or deny account registration depending
|
||||||
|
in the IP address of the XMPP client.
|
||||||
|
If there is no matching IP mask, the default rule is ``allow''.
|
||||||
|
IPv6 addresses are supported, but not tested.
|
||||||
|
The default option value is an empty list: \term{[]}.
|
||||||
\titem{\{password\_strength, Entropy\}} \ind{options!password\_strength}
|
\titem{\{password\_strength, Entropy\}} \ind{options!password\_strength}
|
||||||
This option sets the minimum informational entropy for passwords. The value \term{Entropy}
|
This option sets the minimum informational entropy for passwords. The value \term{Entropy}
|
||||||
is a number of bits of entropy. The recommended minimum is 32 bits.
|
is a number of bits of entropy. The recommended minimum is 32 bits.
|
||||||
@ -3806,7 +3812,8 @@ Default value: 600 seconds.
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Next example prohibits the registration of too short account names:
|
\item Next example prohibits the registration of too short account names,
|
||||||
|
and allows to create accounts only to clients of the local network:
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
{acl, shortname, {user_glob, "?"}}.
|
{acl, shortname, {user_glob, "?"}}.
|
||||||
{acl, shortname, {user_glob, "??"}}.
|
{acl, shortname, {user_glob, "??"}}.
|
||||||
@ -3819,7 +3826,10 @@ Examples:
|
|||||||
{modules,
|
{modules,
|
||||||
[
|
[
|
||||||
...
|
...
|
||||||
{mod_register, [{access, register}]},
|
{mod_register, [{access, register},
|
||||||
|
{ip_access, [{allow, "127.0.0.0/8"},
|
||||||
|
{deny, "0.0.0.0/0"}]}
|
||||||
|
]},
|
||||||
...
|
...
|
||||||
]}.
|
]}.
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
|
@ -545,6 +545,9 @@
|
|||||||
%%
|
%%
|
||||||
%%{registration_watchers, ["admin1@example.org"]},
|
%%{registration_watchers, ["admin1@example.org"]},
|
||||||
|
|
||||||
|
{ip_access, [{allow, "127.0.0.0/8"},
|
||||||
|
{deny, "0.0.0.0/0"}]},
|
||||||
|
|
||||||
{access, register}
|
{access, register}
|
||||||
]},
|
]},
|
||||||
%%{mod_register_web, [
|
%%{mod_register_web, [
|
||||||
|
@ -88,7 +88,7 @@ unauthenticated_iq_register(Acc, _Server, _IQ, _IP) ->
|
|||||||
Acc.
|
Acc.
|
||||||
|
|
||||||
process_iq(From, To, IQ) ->
|
process_iq(From, To, IQ) ->
|
||||||
process_iq(From, To, IQ, jlib:jid_tolower(jlib:jid_remove_resource(From))).
|
process_iq(From, To, IQ, jlib:jid_tolower(From)).
|
||||||
|
|
||||||
process_iq(From, To,
|
process_iq(From, To,
|
||||||
#iq{type = Type, lang = Lang, sub_el = SubEl, id = ID} = IQ,
|
#iq{type = Type, lang = Lang, sub_el = SubEl, id = ID} = IQ,
|
||||||
@ -311,17 +311,22 @@ try_set_password(User, Server, Password, IQ, SubEl, Lang) ->
|
|||||||
sub_el = [SubEl, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)]}
|
sub_el = [SubEl, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)]}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
try_register(User, Server, Password, Source, Lang) ->
|
try_register(User, Server, Password, SourceRaw, Lang) ->
|
||||||
case jlib:is_nodename(User) of
|
case jlib:is_nodename(User) of
|
||||||
false ->
|
false ->
|
||||||
{error, ?ERR_BAD_REQUEST};
|
{error, ?ERR_BAD_REQUEST};
|
||||||
_ ->
|
_ ->
|
||||||
JID = jlib:make_jid(User, Server, ""),
|
JID = jlib:make_jid(User, Server, ""),
|
||||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access, all),
|
Access = gen_mod:get_module_opt(Server, ?MODULE, access, all),
|
||||||
case acl:match_rule(Server, Access, JID) of
|
IPAccess = get_ip_access(Server),
|
||||||
deny ->
|
case {acl:match_rule(Server, Access, JID),
|
||||||
|
check_ip_access(SourceRaw, IPAccess)} of
|
||||||
|
{deny, _} ->
|
||||||
{error, ?ERR_FORBIDDEN};
|
{error, ?ERR_FORBIDDEN};
|
||||||
allow ->
|
{_, deny} ->
|
||||||
|
{error, ?ERR_FORBIDDEN};
|
||||||
|
{allow, allow} ->
|
||||||
|
Source = may_remove_resource(SourceRaw),
|
||||||
case check_timeout(Source) of
|
case check_timeout(Source) of
|
||||||
true ->
|
true ->
|
||||||
case is_strong_password(Server, Password) of
|
case is_strong_password(Server, Password) of
|
||||||
@ -536,3 +541,95 @@ is_strong_password(Server, Password) ->
|
|||||||
[Wrong]),
|
[Wrong]),
|
||||||
true
|
true
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%%%
|
||||||
|
%%% ip_access management
|
||||||
|
%%%
|
||||||
|
|
||||||
|
may_remove_resource({_, _, _} = From) ->
|
||||||
|
jlib:jid_remove_resource(From);
|
||||||
|
may_remove_resource(From) ->
|
||||||
|
From.
|
||||||
|
|
||||||
|
get_ip_access(Host) ->
|
||||||
|
IPAccess = gen_mod:get_module_opt(Host, ?MODULE, ip_access, []),
|
||||||
|
lists:flatmap(
|
||||||
|
fun({Access, S}) ->
|
||||||
|
case parse_ip_netmask(S) of
|
||||||
|
{ok, IP, Mask} ->
|
||||||
|
[{Access, IP, Mask}];
|
||||||
|
error ->
|
||||||
|
?ERROR_MSG("mod_register: invalid "
|
||||||
|
"network specification: ~p",
|
||||||
|
[S]),
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end, IPAccess).
|
||||||
|
|
||||||
|
parse_ip_netmask(S) ->
|
||||||
|
case string:tokens(S, "/") of
|
||||||
|
[IPStr] ->
|
||||||
|
case inet_parse:address(IPStr) of
|
||||||
|
{ok, {_, _, _, _} = IP} ->
|
||||||
|
{ok, IP, 32};
|
||||||
|
{ok, {_, _, _, _, _, _, _, _} = IP} ->
|
||||||
|
{ok, IP, 128};
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end;
|
||||||
|
[IPStr, MaskStr] ->
|
||||||
|
case catch list_to_integer(MaskStr) of
|
||||||
|
Mask when is_integer(Mask),
|
||||||
|
Mask >= 0 ->
|
||||||
|
case inet_parse:address(IPStr) of
|
||||||
|
{ok, {_, _, _, _} = IP} when Mask =< 32 ->
|
||||||
|
{ok, IP, Mask};
|
||||||
|
{ok, {_, _, _, _, _, _, _, _} = IP} when Mask =< 128 ->
|
||||||
|
{ok, IP, Mask};
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end.
|
||||||
|
|
||||||
|
check_ip_access(_Source, []) ->
|
||||||
|
allow;
|
||||||
|
check_ip_access({User, Server, Resource}, IPAccess) ->
|
||||||
|
case ejabberd_sm:get_user_ip(User, Server, Resource) of
|
||||||
|
{IPAddress, _PortNumber} -> check_ip_access(IPAddress, IPAccess);
|
||||||
|
_ -> true
|
||||||
|
end;
|
||||||
|
check_ip_access({_, _, _, _} = IP,
|
||||||
|
[{Access, {_, _, _, _} = Net, Mask} | IPAccess]) ->
|
||||||
|
IPInt = ip_to_integer(IP),
|
||||||
|
NetInt = ip_to_integer(Net),
|
||||||
|
M = bnot ((1 bsl (32 - Mask)) - 1),
|
||||||
|
if
|
||||||
|
IPInt band M =:= NetInt band M ->
|
||||||
|
Access;
|
||||||
|
true ->
|
||||||
|
check_ip_access(IP, IPAccess)
|
||||||
|
end;
|
||||||
|
check_ip_access({_, _, _, _, _, _, _, _} = IP,
|
||||||
|
[{Access, {_, _, _, _, _, _, _, _} = Net, Mask} | IPAccess]) ->
|
||||||
|
IPInt = ip_to_integer(IP),
|
||||||
|
NetInt = ip_to_integer(Net),
|
||||||
|
M = bnot ((1 bsl (128 - Mask)) - 1),
|
||||||
|
if
|
||||||
|
IPInt band M =:= NetInt band M ->
|
||||||
|
Access;
|
||||||
|
true ->
|
||||||
|
check_ip_access(IP, IPAccess)
|
||||||
|
end;
|
||||||
|
check_ip_access(IP, [_ | IPAccess]) ->
|
||||||
|
check_ip_access(IP, IPAccess).
|
||||||
|
|
||||||
|
ip_to_integer({IP1, IP2, IP3, IP4}) ->
|
||||||
|
(((((IP1 bsl 8) bor IP2) bsl 8) bor IP3) bsl 8) bor IP4;
|
||||||
|
ip_to_integer({IP1, IP2, IP3, IP4, IP5, IP6, IP7, IP8}) ->
|
||||||
|
(((((((((((((IP1 bsl 16) bor IP2) bsl 16) bor IP3) bsl 16) bor IP4)
|
||||||
|
bsl 16) bor IP5) bsl 16) bor IP6) bsl 16) bor IP7) bsl 16) bor IP8.
|
||||||
|
Loading…
Reference in New Issue
Block a user