From 609a1d07cff1f4cc57856df0bda436edec86111c Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 27 Sep 2017 15:04:57 +0200 Subject: [PATCH] harden ejabberdctl (#1977) --- ejabberdctl.template | 99 ++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 2fa554108..75e3d2032 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -7,6 +7,7 @@ ERL_MAX_PORTS=32000 ERL_PROCESSES=250000 ERL_MAX_ETS_TABLES=1400 FIREWALL_WINDOW="" +INET_DIST_INTERFACE="" ERLANG_NODE=ejabberd@localhost # define default environment variables @@ -16,7 +17,7 @@ EPMD="{{epmd}}" INSTALLUSER="{{installuser}}" # check the proper system user is used -case `id -un` in +case $(id -un) in "$INSTALLUSER") EXEC_CMD="as_current_user" ;; @@ -40,7 +41,7 @@ esac # parse command line parameters for arg; do - case $1 in + case $arg in -n|--node) ERLANG_NODE_ARG=$2; shift;; -s|--spool) SPOOL_DIR=$2; shift;; -l|--logs) LOGS_DIR=$2; shift;; @@ -55,25 +56,25 @@ for arg; do done # define ejabberd variables if not already defined from the command line -: ${ETC_DIR:={{sysconfdir}}/ejabberd} -: ${LOGS_DIR:={{localstatedir}}/log/ejabberd} -: ${SPOOL_DIR:={{localstatedir}}/lib/ejabberd} -: ${EJABBERD_CONFIG_PATH:="$ETC_DIR"/ejabberd.yml} -: ${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR"/ejabberdctl.cfg} +: "${ETC_DIR:="{{sysconfdir}}/ejabberd"}" +: "${LOGS_DIR:="{{localstatedir}}/log/ejabberd"}" +: "${SPOOL_DIR:="{{localstatedir}}/lib/ejabberd"}" +: "${EJABBERD_CONFIG_PATH:="$ETC_DIR/ejabberd.yml"}" +: "${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR/ejabberdctl.cfg"}" [ -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" -: ${EJABBERD_DOC_PATH:={{docdir}}} -: ${EJABBERD_LOG_PATH:="$LOGS_DIR"/ejabberd.log} +: "${EJABBERD_DOC_PATH:="{{docdir}}"}" +: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}" # define erl parameters 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#*-}" 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) - if [ "$INET_DIST_INTERFACE2" != "" ] ; then + if [ -n "$INET_DIST_INTERFACE2" ] ; then ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2" fi fi @@ -115,12 +116,12 @@ exec_cmd() exec_erl() { NODE=$1; shift - exec_cmd "$ERL" ${S:--}name $NODE $ERLANG_OPTS "$@" + exec_cmd "$ERL" ${S:--}name "$NODE" $ERLANG_OPTS "$@" } exec_iex() { NODE=$1; shift - exec_cmd "$IEX" -${S:--}name $NODE --erl "$ERLANG_OPTS" "$@" + exec_cmd "$IEX" -${S:--}name "$NODE" --erl "$ERLANG_OPTS" "$@" } # usage @@ -143,7 +144,7 @@ debugwarning() echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" echo " EJABBERD_BYPASS_WARNINGS=true" echo "Press return to continue" - read foo + read -r echo "" fi } @@ -166,7 +167,7 @@ livewarning() echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" echo " EJABBERD_BYPASS_WARNINGS=true" echo "Press return to continue" - read foo + read -r echo "" fi } @@ -196,12 +197,12 @@ help() uid() { uuid=$(uuidgen 2>/dev/null) - [ -z "$uuid" -a -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid) - [ -z "$uuid" ] && uuid=$(printf "%X" $RANDOM$(date +%M%S)$$) + [ -z "$uuid" ] && [ -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid) + [ -z "$uuid" ] && uuid=$(printf "%X" "${RANDOM:-$$}$(date +%M%S)") uuid=${uuid%%-*} - [ $# -eq 0 ] && echo ${uuid}-${ERLANG_NODE} - [ $# -eq 1 ] && echo ${uuid}-${1}-${ERLANG_NODE} - [ $# -eq 2 ] && echo ${uuid}-${1}@${2} + [ $# -eq 0 ] && echo "${uuid}-${ERLANG_NODE}" + [ $# -eq 1 ] && echo "${uuid}-${1}-${ERLANG_NODE}" + [ $# -eq 2 ] && echo "${uuid}-${1}@${2}" } # stop epmd if there is no other running node @@ -215,19 +216,17 @@ stop_epmd() check_start() { "$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." 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 # return: 0 OK, 1 KO - timeout=$2 + timeout="$2" status=4 - while [ $status -ne $1 ] ; do - sleep $3 - timeout=`expr $timeout - 1` + while [ "$status" -ne "$1" ] ; do + sleep "$3" + timeout=$((timeout - 1)) if [ $timeout -eq 0 ] ; then - status=$1 + status="$1" else - exec_erl $(uid ctl) -hidden -noinput -s ejabberd_ctl \ - -extra $ERLANG_NODE $NO_TIMEOUT status > /dev/null - status=$? + exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \ + -extra "$ERLANG_NODE" $NO_TIMEOUT status > /dev/null + status="$?" fi done [ $timeout -gt 0 ] @@ -263,37 +262,37 @@ cd "$SPOOL_DIR" || { case $1 in start) check_start - exec_erl $ERLANG_NODE $EJABBERD_OPTS -noinput -detached + exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput -detached ;; foreground) check_start - exec_erl $ERLANG_NODE $EJABBERD_OPTS -noinput + exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput ;; live) livewarning check_start - exec_erl $ERLANG_NODE $EJABBERD_OPTS + exec_erl "$ERLANG_NODE" $EJABBERD_OPTS ;; debug) debugwarning - exec_erl $(uid debug) -hidden -remsh $ERLANG_NODE + exec_erl "$(uid debug)" -hidden -remsh "$ERLANG_NODE" ;; 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 ;; iexdebug) debugwarning - exec_iex $(uid debug) --remsh "$ERLANG_NODE" + exec_iex "$(uid debug)" --remsh "$ERLANG_NODE" ;; iexlive) livewarning - exec_iex $ERLANG_NODE --erl "$EJABBERD_OPTS" --app ejabberd + exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS" --app ejabberd ;; ping) PEER=${2:-$ERLANG_NODE} [ "$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'"')])' \ -s erlang halt -output text ;; @@ -304,8 +303,8 @@ case $1 in wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout ;; *) - exec_erl $(uid ctl) -hidden -noinput -s ejabberd_ctl \ - -extra $ERLANG_NODE $NO_TIMEOUT "$@" + exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \ + -extra "$ERLANG_NODE" $NO_TIMEOUT "$@" result=$? case $result in 2|3) help;;