25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-24 16:23:40 +01:00

ejabberdctl: support concurrent connections with bound conn names

If flock is available, ejabberdctl will use it to grab one
of a bound number of connection names. This allows concurrent
connections while using a bound number of atoms.

Using PID, timestamps or random strings for transient connection IDs
(which would avoid the need for flock) uses an unbound number of atoms.
This can effectively DoS servers, as these connection names are
not garbage collected.
This commit is contained in:
Martin Langhoff 2010-01-24 14:39:15 +01:00 committed by Badlop
parent 50b0ef4db9
commit 6557136426
2 changed files with 81 additions and 7 deletions

View File

@ -108,6 +108,9 @@ MSGSDIR = $(PRIVDIR)/msgs
# /var/lib/ejabberd/ # /var/lib/ejabberd/
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
# /var/lock/ejabberdctl
CTLLOCKDIR = $(DESTDIR)@localstatedir@/lock/ejabberdctl
# /var/lib/ejabberd/.erlang.cookie # /var/lib/ejabberd/.erlang.cookie
COOKIEFILE = $(SPOOLDIR)/.erlang.cookie COOKIEFILE = $(SPOOLDIR)/.erlang.cookie
@ -226,6 +229,12 @@ install: all
install -d -m 750 $(O_USER) $(SPOOLDIR) install -d -m 750 $(O_USER) $(SPOOLDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT) $(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(SPOOLDIR) chmod -R 750 $(SPOOLDIR)
# ejabberdctl lock directory
install -d -m 750 $(O_USER) $(CTLLOCKDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(CTLLOCKDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(CTLLOCKDIR)
[ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; } [ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; }
# #
# Log directory # Log directory
@ -261,6 +270,7 @@ uninstall-all: uninstall-binary
rm -rf $(ETCDIR) rm -rf $(ETCDIR)
rm -rf $(EJABBERDDIR) rm -rf $(EJABBERDDIR)
rm -rf $(SPOOLDIR) rm -rf $(SPOOLDIR)
rm -rf $(CTLLOCKDIR)
rm -rf $(LOGDIR) rm -rf $(LOGDIR)
clean: clean-recursive clean-local clean-devdoc clean: clean-recursive clean-local clean-devdoc

View File

@ -14,6 +14,17 @@ ERLANG_NODE=$NODE@$HOST
ERL=@erl@ ERL=@erl@
INSTALLUSER=@installuser@ INSTALLUSER=@installuser@
# Control number of connections identifiers
# using flock if available. Expects a linux-style
# flock that can lock a file descriptor.
MAXCONNID=100
CONNLOCKDIR=@LOCALSTATEDIR@/lock/ejabberdctl
FLOCK='/usr/bin/flock'
if [ ! -x "$FLOCK" ];then
FLOCK=""
fi
# parse command line parameters # parse command line parameters
ARGS= ARGS=
while [ $# -ne 0 ] ; do while [ $# -ne 0 ] ; do
@ -228,13 +239,54 @@ help ()
ctl () ctl ()
{ {
COMMAND=$@ COMMAND=$@
$EXEC_CMD "$ERL \
$NAME ctl-${ERLANG_NODE} \ if [ ! "$FLOCK" ];then
-noinput \ # no flock, simply invoke ctlexec()
-hidden \ CTL_CONN="ctl-${EJABBERD_NODE}"
-pa $EJABBERD_EBIN_PATH \ ctlexec $CTL_CONN $COMMAND
-s ejabberd_ctl -extra $ERLANG_NODE $COMMAND" result=$?
result=$? else
# we have flock so we get a lock
# on one of a limited number of
# conn names -- this allows
# concurrent invokations using a bound
# number of atoms
for N in $(seq 1 $MAXCONNID); do
CTL_CONN="ejabberdctl-$N"
CTL_LOCKFILE="$CONNLOCKDIR/$CTL_CONN"
(
exec 8>"$CTL_LOCKFILE"
if flock --nb 8; then
ctlexec $CTL_CONN $COMMAND
ssresult=$?
# segregate from possible flock exit(1)
ssresult=$(expr $ssresult \* 10)
exit $ssresult
else
exit 1
fi
)
result=$?
if [ $result -eq 1 ]; then
# means we errored out in flock
# rather than in the exec - stay in the loop
# trying other conn names...
badlock=1
else
badlock=""
break;
fi
done
result=$(expr $result / 10)
fi
if [ "$badlock" ];then
echo "Ran out of connections to try. Your ejabberd processes" >&2
echo "may be stuck or this is a very busy server. For very" >&2
echo "busy servers, consider raising MAXCONNIDS" >&2
exit 1;
fi
case $result in case $result in
0) :;; 0) :;;
1) :;; 1) :;;
@ -244,6 +296,18 @@ ctl ()
return $result return $result
} }
ctlexec ()
{
CONN_NAME=$1; shift
COMMAND=$@
$EXEC_CMD "$ERL \
$NAME ${CONN_NAME} \
-noinput \
-hidden \
-pa $EJABBERD_EBIN_PATH \
-s ejabberd_ctl -extra $ERLANG_NODE $COMMAND"
}
# display ctl usage # display ctl usage
usage () usage ()
{ {