mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-24 17:29:28 +01:00
Merge branch '2.2.x' of gitorious.process-one.net:+ejabberd-developers/ejabberd/maincustomers into 2.2.x
This commit is contained in:
commit
bde46896d6
2
README
2
README
@ -20,7 +20,7 @@ To compile ejabberd you need:
|
||||
- GNU Iconv 1.8 or higher, for the IRC Transport
|
||||
(mod_irc). Optional. Not needed on systems with GNU Libc.
|
||||
- ImageMagick's Convert program. Optional. For CAPTCHA challenges.
|
||||
- exmpp 0.9.2 or higher. Optional. For import/export XEP-0227 files.
|
||||
- exmpp 0.9.6 or higher. Optional. For import/export XEP-0227 files.
|
||||
|
||||
|
||||
1. Compile and install on *nix systems
|
||||
|
@ -356,7 +356,7 @@ Don’t use R14A or R14B because <A HREF="http://www.erlang.org/cgi-bin/ezm
|
||||
</LI><LI CLASS="li-itemize">PAM library. Optional. For Pluggable Authentication Modules (PAM). See section <A HREF="#pam">3.1.4</A>.
|
||||
</LI><LI CLASS="li-itemize">GNU Iconv 1.8 or higher, for the IRC Transport (mod_irc). Optional. Not needed on systems with GNU Libc. See section <A HREF="#modirc">3.3.8</A>.
|
||||
</LI><LI CLASS="li-itemize">ImageMagick’s Convert program. Optional. For CAPTCHA challenges. See section <A HREF="#captcha">3.1.8</A>.
|
||||
</LI><LI CLASS="li-itemize">exmpp 0.9.2 or higher. Optional. For import/export user data with <A HREF="http://xmpp.org/extensions/xep-0227.html">XEP-0227</A> XML files.
|
||||
</LI><LI CLASS="li-itemize">exmpp 0.9.6 or higher. Optional. For import/export user data with <A HREF="http://xmpp.org/extensions/xep-0227.html">XEP-0227</A> XML files.
|
||||
</LI></UL><P> <A NAME="download"></A> </P><!--TOC subsection Download Source Code-->
|
||||
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc10">2.4.2</A>  <A HREF="#download">Download Source Code</A></H3><!--SEC END --><P> <A NAME="download"></A>
|
||||
</P><P>Released versions of <TT>ejabberd</TT> are available in the ProcessOne <TT>ejabberd</TT> downloads page:
|
||||
@ -2994,7 +2994,7 @@ The default option value is an empty list: <TT>[]</TT>.
|
||||
This option sets the minimum informational entropy for passwords. The value <TT>Entropy</TT>
|
||||
is a number of bits of entropy. The recommended minimum is 32 bits.
|
||||
The default is 0, i.e. no checks are performed.
|
||||
</DD><DT CLASS="dt-description"><B><TT>{welcome_message, Message}</TT></B></DT><DD CLASS="dd-description"> Set a welcome message that
|
||||
</DD><DT CLASS="dt-description"><B><TT>{welcome_message, {Subject, Body}}</TT></B></DT><DD CLASS="dd-description"> Set a welcome message that
|
||||
is sent to each newly registered account. The first string is the subject, and
|
||||
the second string is the message body.
|
||||
In the body you can set a newline with the characters: <CODE>\n</CODE>
|
||||
|
@ -80,6 +80,7 @@
|
||||
\newcommand{\modoffline}{\module{mod\_offline}}
|
||||
\newcommand{\modofflineodbc}{\module{mod\_offline\_odbc}}
|
||||
\newcommand{\modping}{\module{mod\_ping}}
|
||||
\newcommand{\modprescounter}{\module{mod\_pres\_counter}}
|
||||
\newcommand{\modprivacy}{\module{mod\_privacy}}
|
||||
\newcommand{\modprivacyodbc}{\module{mod\_privacy\_odbc}}
|
||||
\newcommand{\modprivate}{\module{mod\_private}}
|
||||
@ -321,7 +322,7 @@ To compile \ejabberd{} on a `Unix-like' operating system, you need:
|
||||
\item PAM library. Optional. For Pluggable Authentication Modules (PAM). See section \ref{pam}.
|
||||
\item GNU Iconv 1.8 or higher, for the IRC Transport (mod\_irc). Optional. Not needed on systems with GNU Libc. See section \ref{modirc}.
|
||||
\item ImageMagick's Convert program. Optional. For CAPTCHA challenges. See section \ref{captcha}.
|
||||
\item exmpp 0.9.2 or higher. Optional. For import/export user data with \xepref{0227} XML files.
|
||||
\item exmpp 0.9.6 or higher. Optional. For import/export user data with \xepref{0227} XML files.
|
||||
\end{itemize}
|
||||
|
||||
\makesubsection{download}{Download Source Code}
|
||||
@ -2540,6 +2541,7 @@ The following table lists all modules included in \ejabberd{}.
|
||||
\hline \ahrefloc{modoffline}{\modoffline{}} & Offline message storage (\xepref{0160}) & \\
|
||||
\hline \ahrefloc{modoffline}{\modofflineodbc{}} & Offline message storage (\xepref{0160}) & supported DB (*) \\
|
||||
\hline \ahrefloc{modping}{\modping{}} & XMPP Ping and periodic keepalives (\xepref{0199}) & \\
|
||||
\hline \ahrefloc{modprescounter}{\modprivacy{}} & Detect presence subscription flood & \\
|
||||
\hline \ahrefloc{modprivacy}{\modprivacy{}} & Blocking Communication (XMPP IM) & \\
|
||||
\hline \ahrefloc{modprivacy}{\modprivacyodbc{}} & Blocking Communication (XMPP IM) & supported DB (*) \\
|
||||
\hline \ahrefloc{modprivate}{\modprivate{}} & Private XML Storage (\xepref{0049}) & \\
|
||||
@ -3564,6 +3566,39 @@ and if a client does not answer to the ping in less than 32 seconds, its connect
|
||||
]}.
|
||||
\end{verbatim}
|
||||
|
||||
\makesubsection{modprescounter}{\modprescounter{}}
|
||||
\ind{modules!\modprescounter{}}
|
||||
|
||||
This module detects flood/spam in presence subscription stanza traffic.
|
||||
If a user sends or receives more of those stanzas in a time interval,
|
||||
the exceeding stanzas are silently dropped, and warning is logged.
|
||||
|
||||
Configuration options:
|
||||
\begin{description}
|
||||
\titem{\{count, StanzaNumber\}}\ind{options!count}
|
||||
The number of subscription presence stanzas
|
||||
(subscribe, unsubscribe, subscribed, unsubscribed)
|
||||
allowed for any direction (input or output)
|
||||
per time interval.
|
||||
Please note that two users subscribing to each other usually generate
|
||||
4 stanzas, so the recommended value is 4 or more.
|
||||
The default value is: 5.
|
||||
\titem{\{interval, Seconds\}}\ind{options!interval}
|
||||
The time interval defined in seconds.
|
||||
The default value is 60.
|
||||
\end{description}
|
||||
|
||||
This example enables the module, and allows up to 5 presence subscription stanzas
|
||||
to be sent or received by the users in 60 seconds:
|
||||
\begin{verbatim}
|
||||
{modules,
|
||||
[
|
||||
...
|
||||
{mod_pres_counter, [{count, 5}, {interval, 60}]},
|
||||
...
|
||||
]}.
|
||||
\end{verbatim}
|
||||
|
||||
\makesubsection{modprivacy}{\modprivacy{}}
|
||||
\ind{modules!\modprivacy{}}\ind{Blocking Communication}\ind{Privacy Rules}\ind{protocols!RFC 3921: XMPP IM}
|
||||
|
||||
@ -3808,7 +3843,7 @@ Protect registrations with CAPTCHA (see section \ref{captcha}). The default is \
|
||||
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.
|
||||
The default is 0, i.e. no checks are performed.
|
||||
\titem{\{welcome\_message, Message\}} \ind{options!welcomem}Set a welcome message that
|
||||
\titem{\{welcome\_message, \{Subject, Body\}\}} \ind{options!welcomem}Set a welcome message that
|
||||
is sent to each newly registered account. The first string is the subject, and
|
||||
the second string is the message body.
|
||||
In the body you can set a newline with the characters: \verb|\n|
|
||||
|
@ -511,6 +511,7 @@
|
||||
%%{mod_muc_log,[]},
|
||||
{mod_offline, [{access_max_user_messages, max_user_offline_messages}]},
|
||||
{mod_ping, []},
|
||||
%%{mod_pres_counter,[{count, 5}, {interval, 60}]},
|
||||
{mod_privacy, []},
|
||||
{mod_private, []},
|
||||
%%{mod_proxy65,[]},
|
||||
@ -545,9 +546,17 @@
|
||||
%%
|
||||
%%{registration_watchers, ["admin1@example.org"]},
|
||||
|
||||
%%
|
||||
%% Only clients in the server machine can register accounts
|
||||
%%
|
||||
{ip_access, [{allow, "127.0.0.0/8"},
|
||||
{deny, "0.0.0.0/0"}]},
|
||||
|
||||
%%
|
||||
%% Local c2s or remote s2s users cannot register accounts
|
||||
%%
|
||||
%%{access_from, deny},
|
||||
|
||||
{access, register}
|
||||
]},
|
||||
%%{mod_register_web, [
|
||||
|
@ -2422,7 +2422,7 @@ resend_offline_messages(StateData) ->
|
||||
Rs when is_list(Rs) ->
|
||||
lists:foreach(
|
||||
fun({route,
|
||||
From, To, {xmlelement, Name, Attrs, Els} = Packet}) ->
|
||||
From, To, {xmlelement, _Name, _Attrs, _Els} = Packet}) ->
|
||||
Pass = case privacy_check_packet(StateData, From, To, Packet, in) of
|
||||
allow ->
|
||||
true;
|
||||
@ -2431,11 +2431,11 @@ resend_offline_messages(StateData) ->
|
||||
end,
|
||||
if
|
||||
Pass ->
|
||||
Attrs2 = jlib:replace_from_to_attrs(
|
||||
jlib:jid_to_string(From),
|
||||
jlib:jid_to_string(To),
|
||||
Attrs),
|
||||
FixedPacket = {xmlelement, Name, Attrs2, Els},
|
||||
%% Attrs2 = jlib:replace_from_to_attrs(
|
||||
%% jlib:jid_to_string(From),
|
||||
%% jlib:jid_to_string(To),
|
||||
%% Attrs),
|
||||
%% FixedPacket = {xmlelement, Name, Attrs2, Els},
|
||||
%% Use route instead of send_element to go through standard workflow
|
||||
ejabberd_router:route(From, To, Packet);
|
||||
%% send_element(StateData, FixedPacket),
|
||||
|
@ -54,7 +54,7 @@ init(ProcessName, ExtPrg) ->
|
||||
register(ProcessName, self()),
|
||||
process_flag(trap_exit,true),
|
||||
Port = open_port({spawn, ExtPrg}, [{packet,2}]),
|
||||
loop(Port, ?INIT_TIMEOUT).
|
||||
loop(Port, ?INIT_TIMEOUT, ProcessName, ExtPrg).
|
||||
|
||||
stop(Host) ->
|
||||
lists:foreach(
|
||||
@ -108,23 +108,27 @@ get_instances(Server) ->
|
||||
_ -> 1
|
||||
end.
|
||||
|
||||
loop(Port, Timeout) ->
|
||||
loop(Port, Timeout, ProcessName, ExtPrg) ->
|
||||
receive
|
||||
{call, Caller, Msg} ->
|
||||
Port ! {self(), {command, encode(Msg)}},
|
||||
port_command(Port, encode(Msg)),
|
||||
receive
|
||||
{Port, {data, Data}} ->
|
||||
?DEBUG("extauth call '~p' received data response:~n~p", [Msg, Data]),
|
||||
Caller ! {eauth, decode(Data)};
|
||||
Caller ! {eauth, decode(Data)},
|
||||
loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg);
|
||||
{Port, Other} ->
|
||||
?ERROR_MSG("extauth call '~p' received strange response:~n~p", [Msg, Other]),
|
||||
Caller ! {eauth, false}
|
||||
Caller ! {eauth, false},
|
||||
loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg)
|
||||
after
|
||||
Timeout ->
|
||||
?ERROR_MSG("extauth call '~p' didn't receive response", [Msg]),
|
||||
Caller ! {eauth, false}
|
||||
end,
|
||||
loop(Port, ?CALL_TIMEOUT);
|
||||
Caller ! {eauth, false},
|
||||
unregister(ProcessName),
|
||||
spawn(?MODULE, init, [ProcessName, ExtPrg]),
|
||||
exit(port_terminated)
|
||||
end;
|
||||
stop ->
|
||||
Port ! {self(), close},
|
||||
receive
|
||||
|
134
src/mod_pres_counter.erl
Normal file
134
src/mod_pres_counter.erl
Normal file
@ -0,0 +1,134 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : mod_pres_counter.erl
|
||||
%%% Author : Ahmed Omar
|
||||
%%% Purpose : Presence subscription flood prevention
|
||||
%%% Created : 23 Sep 2010 by Ahmed Omar
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2010 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
%%% published by the Free Software Foundation; either version 2 of the
|
||||
%%% License, or (at your option) any later version.
|
||||
%%%
|
||||
%%% This program is distributed in the hope that it will be useful,
|
||||
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
%%% General Public License for more details.
|
||||
%%%
|
||||
%%% You should have received a copy of the GNU General Public License
|
||||
%%% along with this program; if not, write to the Free Software
|
||||
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
%%% 02111-1307 USA
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(mod_pres_counter).
|
||||
|
||||
-behavior(gen_mod).
|
||||
|
||||
-export([start/2,
|
||||
stop/1,
|
||||
check_packet/6]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
|
||||
-record(pres_counter, {dir, start, count, logged = false}).
|
||||
|
||||
start(Host, _Opts) ->
|
||||
ejabberd_hooks:add(privacy_check_packet, Host,
|
||||
?MODULE, check_packet, 25),
|
||||
ok.
|
||||
|
||||
stop(Host) ->
|
||||
ejabberd_hooks:delete(privacy_check_packet, Host,
|
||||
?MODULE, check_packet, 25),
|
||||
ok.
|
||||
|
||||
check_packet(_, _User, Server,
|
||||
_PrivacyList,
|
||||
{From, To, {xmlelement, Name, Attrs, _}},
|
||||
Dir) ->
|
||||
case Name of
|
||||
"presence" ->
|
||||
IsSubscription =
|
||||
case xml:get_attr_s("type", Attrs) of
|
||||
"subscribe" -> true;
|
||||
"subscribed" -> true;
|
||||
"unsubscribe" -> true;
|
||||
"unsubscribed" -> true;
|
||||
_ -> false
|
||||
end,
|
||||
if
|
||||
IsSubscription ->
|
||||
JID = case Dir of
|
||||
in -> To;
|
||||
out -> From
|
||||
end,
|
||||
update(Server, JID, Dir);
|
||||
true ->
|
||||
allow
|
||||
end;
|
||||
_ ->
|
||||
allow
|
||||
end.
|
||||
|
||||
update(Server, JID, Dir) ->
|
||||
%% get options
|
||||
StormCount = gen_mod:get_module_opt(Server, ?MODULE, count, 5),
|
||||
TimeInterval = gen_mod:get_module_opt(Server, ?MODULE, interval, 60),
|
||||
{MegaSecs, Secs, _MicroSecs} = now(),
|
||||
TimeStamp = MegaSecs * 1000000 + Secs,
|
||||
case read(Dir) of
|
||||
undefined ->
|
||||
write(Dir, #pres_counter{dir = Dir,
|
||||
start = TimeStamp,
|
||||
count = 1}),
|
||||
allow;
|
||||
#pres_counter{start = TimeStart, count = Count, logged = Logged} = R ->
|
||||
%% record for this key exists, check if we're
|
||||
%% within TimeInterval seconds, and whether the StormCount is
|
||||
%% high enough. or else just increment the count.
|
||||
if
|
||||
TimeStamp - TimeStart > TimeInterval ->
|
||||
write(Dir, R#pres_counter{
|
||||
start = TimeStamp,
|
||||
count = 1}),
|
||||
allow;
|
||||
(Count =:= StormCount) and Logged ->
|
||||
{stop, deny};
|
||||
Count =:= StormCount ->
|
||||
write(Dir, R#pres_counter{logged = true}),
|
||||
case Dir of
|
||||
in ->
|
||||
?WARNING_MSG(
|
||||
"User ~s is being flooded, "
|
||||
"ignoring received presence subscriptions",
|
||||
[jlib:jid_to_string(JID)]);
|
||||
out ->
|
||||
IP = ejabberd_sm:get_user_ip(
|
||||
JID#jid.luser,
|
||||
JID#jid.lserver,
|
||||
JID#jid.lresource),
|
||||
?WARNING_MSG(
|
||||
"Flooder detected: ~s, on IP: ~s "
|
||||
"ignoring sent presence subscriptions~n",
|
||||
[jlib:jid_to_string(JID),
|
||||
jlib:ip_to_list(IP)])
|
||||
end,
|
||||
{stop, deny};
|
||||
true ->
|
||||
write(Dir, R#pres_counter{
|
||||
start = TimeStamp,
|
||||
count = Count + 1}),
|
||||
allow
|
||||
end
|
||||
end.
|
||||
|
||||
read(K)->
|
||||
get({pres_counter, K}).
|
||||
|
||||
write(K, V)->
|
||||
put({pres_counter, K}, V).
|
@ -554,9 +554,12 @@ get_user_list(_, User, Server) ->
|
||||
end.
|
||||
|
||||
|
||||
%% From is the sender, To is the destination.
|
||||
%% If Dir = out, User@Server is the sender account (From).
|
||||
%% If Dir = in, User@Server is the destination account (To).
|
||||
check_packet(_, User, Server,
|
||||
#userlist{list = List, needdb = NeedDb},
|
||||
{From, To, {xmlelement, PName, _, _}},
|
||||
{From, To, {xmlelement, PName, Attrs, _}},
|
||||
Dir) ->
|
||||
case List of
|
||||
[] ->
|
||||
@ -565,48 +568,36 @@ check_packet(_, User, Server,
|
||||
PType = case PName of
|
||||
"message" -> message;
|
||||
"iq" -> iq;
|
||||
"presence" -> presence
|
||||
end,
|
||||
case {PType, Dir} of
|
||||
{message, in} ->
|
||||
LJID = jlib:jid_tolower(From),
|
||||
{Subscription, Groups} =
|
||||
case NeedDb of
|
||||
true -> ejabberd_hooks:run_fold(roster_get_jid_info, jlib:nameprep(Server), {none, []}, [User, Server, LJID]);
|
||||
false -> {[], []}
|
||||
end,
|
||||
check_packet_aux(List, message,
|
||||
LJID, Subscription, Groups);
|
||||
{iq, in} ->
|
||||
LJID = jlib:jid_tolower(From),
|
||||
{Subscription, Groups} =
|
||||
case NeedDb of
|
||||
true -> ejabberd_hooks:run_fold(roster_get_jid_info, jlib:nameprep(Server), {none, []}, [User, Server, LJID]);
|
||||
false -> {[], []}
|
||||
end,
|
||||
check_packet_aux(List, iq,
|
||||
LJID, Subscription, Groups);
|
||||
{presence, in} ->
|
||||
LJID = jlib:jid_tolower(From),
|
||||
{Subscription, Groups} =
|
||||
case NeedDb of
|
||||
true -> ejabberd_hooks:run_fold(roster_get_jid_info, jlib:nameprep(Server), {none, []}, [User, Server, LJID]);
|
||||
false -> {[], []}
|
||||
end,
|
||||
check_packet_aux(List, presence_in,
|
||||
LJID, Subscription, Groups);
|
||||
{presence, out} ->
|
||||
LJID = jlib:jid_tolower(To),
|
||||
{Subscription, Groups} =
|
||||
case NeedDb of
|
||||
true -> ejabberd_hooks:run_fold(roster_get_jid_info, jlib:nameprep(Server), {none, []}, [User, Server, LJID]);
|
||||
false -> {[], []}
|
||||
end,
|
||||
check_packet_aux(List, presence_out,
|
||||
LJID, Subscription, Groups);
|
||||
_ ->
|
||||
allow
|
||||
"presence" ->
|
||||
case xml:get_attr_s("type", Attrs) of
|
||||
%% notification
|
||||
"" -> presence;
|
||||
"unavailable" -> presence;
|
||||
%% subscribe, subscribed, unsubscribe,
|
||||
%% unsubscribed, error, probe, or other
|
||||
_ -> other
|
||||
end
|
||||
end,
|
||||
PType2 = case {PType, Dir} of
|
||||
{message, in} -> message;
|
||||
{iq, in} -> iq;
|
||||
{presence, in} -> presence_in;
|
||||
{presence, out} -> presence_out;
|
||||
{_, _} -> other
|
||||
end,
|
||||
LJID = case Dir of
|
||||
in -> jlib:jid_tolower(From);
|
||||
out -> jlib:jid_tolower(To)
|
||||
end,
|
||||
{Subscription, Groups} =
|
||||
case NeedDb of
|
||||
true -> ejabberd_hooks:run_fold(roster_get_jid_info,
|
||||
jlib:nameprep(Server),
|
||||
{none, []},
|
||||
[User, Server, LJID]);
|
||||
false -> {[], []}
|
||||
end,
|
||||
check_packet_aux(List, PType2, LJID, Subscription, Groups)
|
||||
end.
|
||||
|
||||
check_packet_aux([], _PType, _JID, _Subscription, _Groups) ->
|
||||
@ -646,7 +637,9 @@ is_ptype_match(Item, PType) ->
|
||||
presence_in ->
|
||||
Item#listitem.match_presence_in;
|
||||
presence_out ->
|
||||
Item#listitem.match_presence_out
|
||||
Item#listitem.match_presence_out;
|
||||
other ->
|
||||
false
|
||||
end
|
||||
end.
|
||||
|
||||
|
@ -1271,10 +1271,14 @@ check_default_xmlns(El) ->
|
||||
%% Print a warning in log file if this is not the case.
|
||||
check_bind_module(XmppDomain) ->
|
||||
case gen_mod:is_loaded(XmppDomain, mod_http_bind) of
|
||||
true -> true;
|
||||
false -> ?ERROR_MSG("You are trying to use BOSH (HTTP Bind), but the module mod_http_bind is not started.~n"
|
||||
"Check your 'modules' section in your ejabberd configuration file.",[]),
|
||||
false
|
||||
true -> ok;
|
||||
false -> ?ERROR_MSG("You are trying to use BOSH (HTTP Bind) in host ~p,"
|
||||
" but the module mod_http_bind is not started in"
|
||||
" that host. Configure your BOSH client to connect"
|
||||
" to the correct host, or add your desired host to"
|
||||
" the configuration, or check your 'modules'"
|
||||
" section in your ejabberd configuration file.",
|
||||
[XmppDomain])
|
||||
end.
|
||||
|
||||
make_sid() ->
|
||||
|
Loading…
Reference in New Issue
Block a user