harden ejabberdctl (#1977)

This commit is contained in:
Christophe Romain 2017-09-27 15:04:57 +02:00
parent 8c026582ab
commit 609a1d07cf
1 changed files with 49 additions and 50 deletions

View File

@ -7,6 +7,7 @@ ERL_MAX_PORTS=32000
ERL_PROCESSES=250000 ERL_PROCESSES=250000
ERL_MAX_ETS_TABLES=1400 ERL_MAX_ETS_TABLES=1400
FIREWALL_WINDOW="" FIREWALL_WINDOW=""
INET_DIST_INTERFACE=""
ERLANG_NODE=ejabberd@localhost ERLANG_NODE=ejabberd@localhost
# define default environment variables # define default environment variables
@ -16,7 +17,7 @@ EPMD="{{epmd}}"
INSTALLUSER="{{installuser}}" INSTALLUSER="{{installuser}}"
# check the proper system user is used # check the proper system user is used
case `id -un` in case $(id -un) in
"$INSTALLUSER") "$INSTALLUSER")
EXEC_CMD="as_current_user" EXEC_CMD="as_current_user"
;; ;;
@ -40,7 +41,7 @@ esac
# parse command line parameters # parse command line parameters
for arg; do for arg; do
case $1 in case $arg in
-n|--node) ERLANG_NODE_ARG=$2; shift;; -n|--node) ERLANG_NODE_ARG=$2; shift;;
-s|--spool) SPOOL_DIR=$2; shift;; -s|--spool) SPOOL_DIR=$2; shift;;
-l|--logs) LOGS_DIR=$2; shift;; -l|--logs) LOGS_DIR=$2; shift;;
@ -55,25 +56,25 @@ for arg; do
done done
# define ejabberd variables if not already defined from the command line # define ejabberd variables if not already defined from the command line
: ${ETC_DIR:={{sysconfdir}}/ejabberd} : "${ETC_DIR:="{{sysconfdir}}/ejabberd"}"
: ${LOGS_DIR:={{localstatedir}}/log/ejabberd} : "${LOGS_DIR:="{{localstatedir}}/log/ejabberd"}"
: ${SPOOL_DIR:={{localstatedir}}/lib/ejabberd} : "${SPOOL_DIR:="{{localstatedir}}/lib/ejabberd"}"
: ${EJABBERD_CONFIG_PATH:="$ETC_DIR"/ejabberd.yml} : "${EJABBERD_CONFIG_PATH:="$ETC_DIR/ejabberd.yml"}"
: ${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR"/ejabberdctl.cfg} : "${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR/ejabberdctl.cfg"}"
[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH" [ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH"
[ "$ERLANG_NODE_ARG" != "" ] && ERLANG_NODE=$ERLANG_NODE_ARG [ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG"
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s" [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
: ${EJABBERD_DOC_PATH:={{docdir}}} : "${EJABBERD_DOC_PATH:="{{docdir}}"}"
: ${EJABBERD_LOG_PATH:="$LOGS_DIR"/ejabberd.log} : "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
# define erl parameters # define erl parameters
ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS"
if [ "$FIREWALL_WINDOW" != "" ] ; then if [ -n "$FIREWALL_WINDOW" ] ; then
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}"
fi fi
if [ "$INET_DIST_INTERFACE" != "" ] ; then if [ -n "$INET_DIST_INTERFACE" ] ; then
INET_DIST_INTERFACE2=$("$ERL" -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt) INET_DIST_INTERFACE2=$("$ERL" -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt)
if [ "$INET_DIST_INTERFACE2" != "" ] ; then if [ -n "$INET_DIST_INTERFACE2" ] ; then
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2" ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2"
fi fi
fi fi
@ -115,12 +116,12 @@ exec_cmd()
exec_erl() exec_erl()
{ {
NODE=$1; shift NODE=$1; shift
exec_cmd "$ERL" ${S:--}name $NODE $ERLANG_OPTS "$@" exec_cmd "$ERL" ${S:--}name "$NODE" $ERLANG_OPTS "$@"
} }
exec_iex() exec_iex()
{ {
NODE=$1; shift NODE=$1; shift
exec_cmd "$IEX" -${S:--}name $NODE --erl "$ERLANG_OPTS" "$@" exec_cmd "$IEX" -${S:--}name "$NODE" --erl "$ERLANG_OPTS" "$@"
} }
# usage # usage
@ -143,7 +144,7 @@ debugwarning()
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
echo " EJABBERD_BYPASS_WARNINGS=true" echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press return to continue" echo "Press return to continue"
read foo read -r
echo "" echo ""
fi fi
} }
@ -166,7 +167,7 @@ livewarning()
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
echo " EJABBERD_BYPASS_WARNINGS=true" echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press return to continue" echo "Press return to continue"
read foo read -r
echo "" echo ""
fi fi
} }
@ -196,12 +197,12 @@ help()
uid() uid()
{ {
uuid=$(uuidgen 2>/dev/null) uuid=$(uuidgen 2>/dev/null)
[ -z "$uuid" -a -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid) [ -z "$uuid" ] && [ -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid)
[ -z "$uuid" ] && uuid=$(printf "%X" $RANDOM$(date +%M%S)$$) [ -z "$uuid" ] && uuid=$(printf "%X" "${RANDOM:-$$}$(date +%M%S)")
uuid=${uuid%%-*} uuid=${uuid%%-*}
[ $# -eq 0 ] && echo ${uuid}-${ERLANG_NODE} [ $# -eq 0 ] && echo "${uuid}-${ERLANG_NODE}"
[ $# -eq 1 ] && echo ${uuid}-${1}-${ERLANG_NODE} [ $# -eq 1 ] && echo "${uuid}-${1}-${ERLANG_NODE}"
[ $# -eq 2 ] && echo ${uuid}-${1}@${2} [ $# -eq 2 ] && echo "${uuid}-${1}@${2}"
} }
# stop epmd if there is no other running node # stop epmd if there is no other running node
@ -215,19 +216,17 @@ stop_epmd()
check_start() check_start()
{ {
"$EPMD" -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && { "$EPMD" -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && {
ps ux | grep -v grep | grep -q " $ERLANG_NODE " && { pgrep -f "$ERLANG_NODE" >/dev/null && {
echo "ERROR: The ejabberd node '$ERLANG_NODE' is already running." echo "ERROR: The ejabberd node '$ERLANG_NODE' is already running."
exit 4 exit 4
} || {
ps ux | grep -v grep | grep -q beam && {
echo "ERROR: The ejabberd node '$ERLANG_NODE' is registered,"
echo " but no related beam process has been found."
echo "Shutdown all other erlang nodes, and call 'epmd -kill'."
exit 5
} || {
"$EPMD" -kill >/dev/null
}
} }
pgrep beam >/dev/null && {
echo "ERROR: The ejabberd node '$ERLANG_NODE' is registered,"
echo " but no related beam process has been found."
echo "Shutdown all other erlang nodes, and call 'epmd -kill'."
exit 5
}
"$EPMD" -kill >/dev/null
} }
} }
@ -236,17 +235,17 @@ wait_status()
{ {
# args: status try delay # args: status try delay
# return: 0 OK, 1 KO # return: 0 OK, 1 KO
timeout=$2 timeout="$2"
status=4 status=4
while [ $status -ne $1 ] ; do while [ "$status" -ne "$1" ] ; do
sleep $3 sleep "$3"
timeout=`expr $timeout - 1` timeout=$((timeout - 1))
if [ $timeout -eq 0 ] ; then if [ $timeout -eq 0 ] ; then
status=$1 status="$1"
else else
exec_erl $(uid ctl) -hidden -noinput -s ejabberd_ctl \ exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
-extra $ERLANG_NODE $NO_TIMEOUT status > /dev/null -extra "$ERLANG_NODE" $NO_TIMEOUT status > /dev/null
status=$? status="$?"
fi fi
done done
[ $timeout -gt 0 ] [ $timeout -gt 0 ]
@ -263,37 +262,37 @@ cd "$SPOOL_DIR" || {
case $1 in case $1 in
start) start)
check_start check_start
exec_erl $ERLANG_NODE $EJABBERD_OPTS -noinput -detached exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput -detached
;; ;;
foreground) foreground)
check_start check_start
exec_erl $ERLANG_NODE $EJABBERD_OPTS -noinput exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput
;; ;;
live) live)
livewarning livewarning
check_start check_start
exec_erl $ERLANG_NODE $EJABBERD_OPTS exec_erl "$ERLANG_NODE" $EJABBERD_OPTS
;; ;;
debug) debug)
debugwarning debugwarning
exec_erl $(uid debug) -hidden -remsh $ERLANG_NODE exec_erl "$(uid debug)" -hidden -remsh "$ERLANG_NODE"
;; ;;
etop) etop)
exec_erl $(uid top) -hidden -node $ERLANG_NODE -s etop \ exec_erl "$(uid top)" -hidden -node "$ERLANG_NODE" -s etop \
-s erlang halt -output text -s erlang halt -output text
;; ;;
iexdebug) iexdebug)
debugwarning debugwarning
exec_iex $(uid debug) --remsh "$ERLANG_NODE" exec_iex "$(uid debug)" --remsh "$ERLANG_NODE"
;; ;;
iexlive) iexlive)
livewarning livewarning
exec_iex $ERLANG_NODE --erl "$EJABBERD_OPTS" --app ejabberd exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS" --app ejabberd
;; ;;
ping) ping)
PEER=${2:-$ERLANG_NODE} PEER=${2:-$ERLANG_NODE}
[ "$PEER" = "${PEER%.*}" ] && PS="-s" [ "$PEER" = "${PEER%.*}" ] && PS="-s"
exec_cmd "$ERL" ${PS:--}name $(uid ping $(hostname $PS)) $ERLANG_OPTS \ exec_cmd "$ERL" ${PS:--}name "$(uid ping "$(hostname $PS)")" $ERLANG_OPTS \
-noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \ -noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \
-s erlang halt -output text -s erlang halt -output text
;; ;;
@ -304,8 +303,8 @@ case $1 in
wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout
;; ;;
*) *)
exec_erl $(uid ctl) -hidden -noinput -s ejabberd_ctl \ exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
-extra $ERLANG_NODE $NO_TIMEOUT "$@" -extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
result=$? result=$?
case $result in case $result in
2|3) help;; 2|3) help;;