#!/bin/bash ### Copyright 1999-2023. Plesk International GmbH. All rights reserved. # vim:ft=sh: set -e usage() { if [ -n "$*" ]; then echo "drwebmng: $*" >&2 echo "Use '--help' option to get help on the utility usage" >&2 exit 2 fi cat <<-EOT Usage: drwebmng COMMAND [OPTIONS] --add-check --mailname= --type={"from"|"to"|"any"|"incoming"|"outgoing"} [--no-restart-service] Add rule check into antivirus configuration file --remove-check --mailname= [--no-restart-service] Delete rule check from antivirus configuration file -p, --start Start drweb service -o, --stop Stop drweb service -s, --status Show drweb service status -r, --restart Restart drweb service -l, --reload Reload drweb service -e, --on Turn on drweb -d, --off Turn off drweb -u, --update Reload, turn on or turn off drweb depending on the handlers state -t, --setup-trial-vhost Set up support for drweb trial license in sw-cp-server -h, --help Display this help and exit EOT exit 2 } mail_handler_add() { local direction="$1" local mailname="$2" if [ "$direction" = "in" ]; then "$MAIL_HANDLERS_BIN" --add --name "$DRWEB_HOOK_NAME" --mailname "$mailname" \ --priority "$DRWEB_HOOK_PRIORITY" --executable "$HOOK_DIR/$DRWEB_HOOK_NAME" \ --enabled --dont-preserve-on-restore \ --queue "before-queue" --type "recipient" elif [ "$direction" = "out" ]; then "$MAIL_HANDLERS_BIN" --add --name "$DRWEB_HOOK_NAME" --mailname "$mailname" \ --priority "$DRWEB_HOOK_PRIORITY" --executable "$HOOK_DIR/$DRWEB_HOOK_NAME" \ --enabled --dont-preserve-on-restore \ --queue "before-remote" --type "sender" fi } mail_handler_remove() { local direction="$1" local mailname="$2" if [ "$direction" = "in" ]; then "$MAIL_HANDLERS_BIN" --remove --name "$DRWEB_HOOK_NAME" --mailname "$mailname" \ --queue "before-queue" --type "recipient" elif [ "$direction" = "out" ]; then "$MAIL_HANDLERS_BIN" --remove --name "$DRWEB_HOOK_NAME" --mailname "$mailname" \ --queue "before-remote" --type "sender" fi } mail_handler_set() { local direction="$1" local mailname="$2" if [ "$direction" = "none" ]; then mail_handler_remove "in" "$mailname" mail_handler_remove "out" "$mailname" elif [ "$direction" = "any" ]; then mail_handler_add "in" "$mailname" mail_handler_add "out" "$mailname" elif [ "$direction" = "incoming" -o "$direction" = "to" ]; then mail_handler_add "in" "$mailname" mail_handler_remove "out" "$mailname" elif [ "$direction" = "outgoing" -o "$direction" = "from" ]; then mail_handler_remove "in" "$mailname" mail_handler_add "out" "$mailname" fi } drweb_service() { local action="$1" /bin/systemctl "$action" "$DRWEBD_SERVICE.service" } do_start() { drweb_service start } do_stop() { drweb_service stop } do_status() { if drweb_service is-active > /dev/null; then echo "is running" else echo "is stopped" fi } do_restart() { drweb_service restart } do_reload() { if drweb_service is-active > /dev/null; then drweb_service reload else echo "Skip drweb antivirus daemon reloading - service is stopped" >&2 fi } setup_swcpserver() { local action="$1" [ "$action" = "enable" -o "$action" = "disable" ] if [ "$action" = "enable" ]; then # allow TLSv1 connections in sw-cp-server if there is no key in the drwebd directory [ ! -r "$DRWEB_SWCPSERVER_CONF" ] || return 0 cp -fT "$DRWEB_SWCPSERVER_CONF_TPL" "$DRWEB_SWCPSERVER_CONF" # listen to ipv6 only if it is available if [ -n "`cat /proc/net/if_inet6`" ]; then cp -fT "$DRWEB_SWCPSERVER_IPV6_TPL" "$DRWEB_SWCPSERVER_IPV6" fi /usr/sbin/sw-cp-serverd -q -t && "$PLESKRC_BIN" sw-cp-server try-reload || { echo "Unable to setup sw-cp-server to receive connections from drweb." >&2 rm -f "$DRWEB_SWCPSERVER_IPV6" rm -f "$DRWEB_SWCPSERVER_CONF" return 1 } elif [ -r "$DRWEB_SWCPSERVER_CONF" ]; then rm -f "$DRWEB_SWCPSERVER_IPV6" rm -f "$DRWEB_SWCPSERVER_CONF" "$PLESKRC_BIN" sw-cp-server try-reload fi } register_service() { local action="$1" [ "$action" = "enable" -o "$action" = "disable" ] local REGISTER_SERVICE_BIN="$PRODUCT_ROOT_D/admin/sbin/register_service" "$REGISTER_SERVICE_BIN" "--$action" "$DRWEBD_SERVICE" || { echo "Unable to $action drweb antivirus daemon" >&2 return 1 } } watchdog_monit_service() { local action="$1" [ "$action" = "monit" -o "$action" = "unmonit" ] local WATCHDOG_BIN="$PRODUCT_ROOT_D/admin/bin/modules/watchdog/wd" [ -x "$WATCHDOG_BIN" ] || { echo "Skipped setting up monitoring in WatchDog as it is not accessible" >&2 return 0 } "$WATCHDOG_BIN" "--$action-service=$DRWEB_WD_SERVICE" || { echo "Unable to $action drweb in WatchDog" >&2 return 1 } } do_on() { do_setup_trial_vhost register_service enable do_start watchdog_monit_service monit } do_off() { setup_swcpserver disable watchdog_monit_service unmonit do_stop register_service disable } do_update() { local allow_reload="$1" local ignore_current_state="$2" local handlers_count="` "$MAIL_HANDLERS_BIN" --list --json | python3 -c " import sys, json handlers = json.load(sys.stdin)['handlers'] print(sum(1 for h in handlers if h['name'] == '$DRWEB_HOOK_NAME' and h['enabled'])) " `" local was_running= ! drweb_service is-active > /dev/null || was_running="yes" local needs_to_be_running= ! [ "$handlers_count" -gt 0 ] || needs_to_be_running="yes" if [ "$was_running" != "$needs_to_be_running" -o -n "$ignore_current_state" ]; then if [ -n "$needs_to_be_running" ]; then do_on else do_off fi fi if [ -n "$allow_reload" -a -n "$was_running" -a -n "$needs_to_be_running" ]; then drweb_service reload fi } do_setup_trial_vhost() { setup_swcpserver "`[ -r "$DRWEB_KEY" ] && echo disable || echo enable`" } # --- environment and constants setup --- unset GREP_OPTIONS umask 022 PRODUCT_ROOT_D='/opt/psa' MAIL_HANDLERS_BIN="$PRODUCT_ROOT_D/admin/sbin/mail_handlers_control" PLESKRC_BIN="$PRODUCT_ROOT_D/admin/sbin/pleskrc" DRWEBD_SERVICE=drwebd DRWEB_HOOK_NAME='drweb' DRWEB_HOOK_PRIORITY='20' DRWEB_KEY='/opt/drweb/drweb32.key' DRWEB_SWCPSERVER_CONF='/etc/sw-cp-server/conf.d/plesk-drweb-local.conf' DRWEB_SWCPSERVER_CONF_TPL='/etc/drweb/swcpserver.plesk-drweb-local.conf.tpl' DRWEB_SWCPSERVER_IPV6='/etc/sw-cp-server/conf.d/plesk-drweb-local.ipv6.inc' DRWEB_SWCPSERVER_IPV6_TPL='/etc/drweb/swcpserver.plesk-drweb-local.ipv6.inc.tpl' DRWEB_WD_SERVICE='drweb' HOOK_DIR='/opt/psa/handlers/hooks' # --- parse args --- opt_mailnames=() opt_type= opt_allow_restart="yes" opt_cmd= TEMP=`getopt -o posrleduth \ --long add-check,remove-check,mailname:,type:,no-restart-service,start,stop,status,restart,reload,on,off,update,setup-trial-vhost,help \ -n drwebmng -- "$@"` || exit 2 eval set -- "$TEMP" declare -A CMD_SHORT_TO_LONG=( [-p]=--start [-o]=--stop [-s]=--status [-r]=--restart [-l]=--reload [-e]=--on [-d]=--off [-u]=--update [-t]=--setup-trial-vhost ) while [ "$#" -gt 0 ]; do case "$1" in -h|--help) usage ;; --mailname) IFS=, opt_mailnames+=($2) shift ;; --type) [ -z "$opt_type" ] || usage "Use '--type' only once" opt_type="$2" shift ;; --no-restart-service) opt_allow_restart= ;; --add-check|--remove-check) [ -z "$opt_cmd" ] || usage "Specify only one command, got '$opt_cmd' and '$1'" opt_cmd="$1" ;; --[a-z]*) [[ "$1" =~ ^(`echo "${CMD_SHORT_TO_LONG[@]}" | tr " " "|"`)$ ]] || usage "Unrecognized option '$1'" [ -z "$opt_cmd" ] || usage "Specify only one command, got '$opt_cmd' and '$1'" opt_cmd="$1" ;; -[a-z]) [[ "$1" =~ ^(`echo "${!CMD_SHORT_TO_LONG[@]}" | tr " " "|"`)$ ]] || usage "Unrecognized option '$1'" [ -z "$opt_cmd" ] || usage "Specify only one command, got '$opt_cmd' and '$1'" opt_cmd="${CMD_SHORT_TO_LONG[$1]}" ;; --) shift break ;; *) usage "Unrecognized option '$1'" ;; esac shift done [ -z "$*" ] || usage "Positional arguments are not accepted" [ -n "$opt_cmd" ] || usage "Command is empty" [ "$opt_cmd" != "--add-check" ] || [ -n "${opt_mailnames[*]}" -a -n "$opt_type" ] || usage "Command '$opt_cmd' requires '--mailname' and '--type' options" [ "$opt_cmd" != "--remove-check" ] || [ -n "${opt_mailnames[*]}" ] || usage "Command '$opt_cmd' requires '--mailname' option" [ -n "$opt_allow_restart" ] || [ "$opt_cmd" = "--add-check" -o "$opt_cmd" = "--remove-check" ] || usage "Option '--no-restart-service' is accepted only by '--add-check' and '--remove-check' commands" [ -z "$opt_type" ] || [ "$opt_type" = "from" -o "$opt_type" = "to" -o "$opt_type" = "any" \ -o "$opt_type" = "incoming" -o "$opt_type" = "outgoing" ] || usage "Unsupported '--type' option value: '$opt_type'" # --- execute --- case "$opt_cmd" in --add-check) for mailname in "${opt_mailnames[@]}"; do mail_handler_set "$opt_type" "$mailname" done do_update "$opt_allow_restart" ;; --remove-check) for mailname in "${opt_mailnames[@]}"; do mail_handler_set "none" "$mailname" done do_update "$opt_allow_restart" ;; --start) do_start ;; --stop) do_stop ;; --status) do_status ;; --restart) do_restart ;; --reload) do_reload ;; --on) do_on ;; --off) do_off ;; --update) do_update --allow-reload --ignore-current-state ;; --setup-trial-vhost) do_setup_trial_vhost ;; esac