25
1
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:
Badlop 2010-11-05 19:00:16 +01:00
parent 6f3713a67d
commit 7f3a5066c6
3 changed files with 117 additions and 7 deletions

View File

@ -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.
\titem{\{captcha\_protected, false|true\}} \ind{options!captcha\_protected}
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}
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.
@ -3806,7 +3812,8 @@ Default value: 600 seconds.
Examples:
\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}
{acl, shortname, {user_glob, "?"}}.
{acl, shortname, {user_glob, "??"}}.
@ -3819,7 +3826,10 @@ Examples:
{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}

View File

@ -545,6 +545,9 @@
%%
%%{registration_watchers, ["admin1@example.org"]},
{ip_access, [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}]},
{access, register}
]},
%%{mod_register_web, [

View File

@ -88,7 +88,7 @@ unauthenticated_iq_register(Acc, _Server, _IQ, _IP) ->
Acc.
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,
#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)]}
end.
try_register(User, Server, Password, Source, Lang) ->
try_register(User, Server, Password, SourceRaw, Lang) ->
case jlib:is_nodename(User) of
false ->
{error, ?ERR_BAD_REQUEST};
_ ->
JID = jlib:make_jid(User, Server, ""),
Access = gen_mod:get_module_opt(Server, ?MODULE, access, all),
case acl:match_rule(Server, Access, JID) of
deny ->
IPAccess = get_ip_access(Server),
case {acl:match_rule(Server, Access, JID),
check_ip_access(SourceRaw, IPAccess)} of
{deny, _} ->
{error, ?ERR_FORBIDDEN};
allow ->
{_, deny} ->
{error, ?ERR_FORBIDDEN};
{allow, allow} ->
Source = may_remove_resource(SourceRaw),
case check_timeout(Source) of
true ->
case is_strong_password(Server, Password) of
@ -536,3 +541,95 @@ is_strong_password(Server, Password) ->
[Wrong]),
true
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.