????

Your IP : 18.222.218.204


Current Path : /usr/share/imunify360-webshield/
Upload File :
Current File : //usr/share/imunify360-webshield/webshieldctl

#!/bin/bash

if [ "$IM360_DEBUG_SHELL" = "1" ]; then
    echo "IM360_ARGV: <$0 [$@]>"
    set -x
else
    :
fi

# For backwards compatibility with CentOS 6 only.
WEBSHIELD='imunify360-webshield'

JOBFILE=/etc/cron.d/imunify360-webshield-check

STATEFILE="/usr/share/imunify360-webshield/.webshieldctl.status"
VIRTSERVER_CONF="/etc/imunify360-webshield/virtserver.conf"
WEBSHIELD_ANTIBOT_CONF="/etc/imunify360-webshield/splashscreen-antibot.conf"

# What mode is desired based on agent config & environment.
# Can be one of: standalone, apache, nginx
TARGET_MODULARITY_MODE='undefined'

SSL_UNIT='imunify360-webshield-ssl-cache'
WAFD_UNIT='imunify360-wafd'
MAIN_UNIT='undefined'

OUR_MODULES_DIR=/usr/share/imunify360-webshield/modules
NGINX_MODULE_CONF=/etc/nginx/modules-enabled/40-imunify360-access-checker.conf
NGINX_CHECKER_CONF=/etc/nginx/conf.d/imunify360-access-checker.conf

# TODO: consider removing this file and instead using `webshieldctl mode` where needed
STATE_PATH=/usr/share/imunify360-webshield/modularity_mode

# In CloudWays environment we integrate with their Nginx server
is_cloudways() {
    hostname -f 2>/dev/null | grep -qE '^.+\.(cloudwaysapps|cloudwaysstagingapps)\.com$' && return 0
    [ -x /usr/local/sbin/apm ] && /usr/local/sbin/apm info | grep -qi cloudways
}

# In Apache2nginx environment we integrate with ea-nginx
is_apache2nginx_enabled(){
    [ -f /var/lib/apache2nginx/state ] && grep -q '^on$' /var/lib/apache2nginx/state
}

# Both support only `nginx` modularity mode
is_nginx_mode_required(){
    is_cloudways || is_apache2nginx_enabled
}

# In both, standalone proxy imunify360-webshield should not be running.
# It is only used in `standalone` mode (for all ports) and `apache` mode (for hosting panel ports).
should_proxy_be_running(){
    is_webshield_on && ! is_nginx_mode_required
}

detect_mode() {
    # WEBSHIELD_ENABLE is the agent config state (WEBSHIELD.enable) passed from the parent
    if [ "$WEBSHIELD_ENABLE" = "false" ]; then
        TARGET_WEBSHIELD_STATE=disabled
    elif [ "$WEBSHIELD_ENABLE" = "true" ]; then
        TARGET_WEBSHIELD_STATE=enabled
    else
        # TODO: remove - probably unneccessary artifact from EL6 days to unify
        # sysvinit and systemd interfaces.
        old_state=$(<"$STATEFILE")
        if [ "$old_state" = "enabled" ] || [ "$old_state" = "activated" ] || [ "$old_state" = "started" ]; then
            TARGET_WEBSHIELD_STATE=enabled
        else
            TARGET_WEBSHIELD_STATE=disabled
        fi
    fi

    if is_nginx_mode_required; then
        # Assuming nginx module mode - the only supported option in Cloudways and Apache2nginx environment
        TARGET_MODULARITY_MODE=nginx
    elif is_apache_module_supported; then
        # WEBSHIELD_MODE is the agent config state (WEBSHIELD.mode) passed from the parent
        if [ "$WEBSHIELD_MODE" = module ]; then
            TARGET_MODULARITY_MODE=apache
        elif [ "$WEBSHIELD_MODE" = proxy ]; then
            TARGET_MODULARITY_MODE=standalone
        elif [ -s "$STATE_PATH" ]; then  # maintain the current mode
            TARGET_MODULARITY_MODE=$(<"$STATE_PATH")
        else
            TARGET_MODULARITY_MODE=standalone
        fi
        # Assuming $TARGET_MODULARITY_MODE mode
    else
        # Assuming standalone (proxy) module mode - the only supported option in this environment
        TARGET_MODULARITY_MODE=standalone
    fi

    if [ "$TARGET_MODULARITY_MODE" = nginx ]; then
        export MAIN_UNIT=nginx
    elif [ "$TARGET_MODULARITY_MODE" = apache ]; then
        export MAIN_UNIT=$(get_unit)
    else
        export MAIN_UNIT=$WEBSHIELD
    fi

    # if cPanel, override path to NGINX_MODULE_CONF and OUR_MODULES_DIR
    if is_cpanel && is_apache2nginx_enabled; then
        NGINX_MODULE_CONF=/etc/nginx/conf.d/modules/ea-nginx-wafcl-module.conf
        OUR_MODULES_DIR=/usr/lib64/nginx/modules
    fi
}

is_cpanel(){
    if [ -x /usr/local/cpanel/cpanel ];then
        return 0
    fi
    return 1
}

is_redhat(){
    if [ -e /etc/redhat-release ];then
        return 0
    fi
    return 1
}

has_apache(){
    if which apachectl &>/dev/null; then
        return 0
    fi
    return 1
}

is_apache_module_supported(){
    has_apache && is_cpanel && [ ! -d /usr/local/lsws ]
}

# Are we in an environment where we can switch between standalone (proxy) and module-based modes?
is_supported(){
    if is_apache_module_supported; then
        [ "$1" = "out" ] && echo yes
        return 0
    fi
    [ "$1" = "out" ] && echo no
    return 1
}

get_apache_root(){
    echo $(apachectl -V | awk -F= '/HTTPD_ROOT/{gsub("\042", "", $2);print $2}')
}

put_apache_conf(){
    local access_checker_conf="/usr/share/imunify360-webshield/access_checker.conf"
    local filename="access_checker.conf"
    local changed=0
    if is_apache_module_supported; then
        local root=$(get_apache_root)
        if is_redhat;then
            if [ -d $root/conf.d ];then
                if ! cmp -s "$access_checker_conf" "$root/conf.d/$filename"; then
                    cp "$access_checker_conf" "$root/conf.d/$filename"
                    changed=1
                fi
            fi
        else
            # By default debian-based apache has modules configs in ROOT/mods-available folder
            # and enables the modules with placing a symlink to the config file into ROOT/mods-enabled.
            # Ubuntu-based cpanel keeps configs in ROOT/conf.d
            if [ -d $root/conf.d ];then
                if ! cmp -s "$access_checker_conf" "$root/conf.d/$filename"; then
                    cp "$access_checker_conf" "$root/conf.d/$filename"
                    changed=1
                fi
            elif [ -d $root/mods-available ] && [ -d $root/mods-enabled ];then
                if ! cmp -s "$access_checker_conf" "$root/mods-enabled/$filename"; then
                    cp "$access_checker_conf" "$root/mods-available/$filename"
                    ln -s "$root/mods-available/$filename" "$root/mods-enabled/$filename"
                    changed=1
                fi
            # But we've seen different debian apache setups
            elif [ -d $root/mods-enabled ];then
                if ! cmp -s "$access_checker_conf" "$root/mods-enabled/$filename"; then
                    cp "$access_checker_conf" "$root/mods-enabled/$filename"
                    changed=1
                fi
            fi
        fi
    fi
    if [ $changed -eq 0 ];then
        echo "noop"
    fi
}

remove_apache_conf(){
    local root=$(get_apache_root)
    local changed=0
    if [ -f "$root/conf.d/access_checker.conf" ];then
        rm -f "$root/conf.d/access_checker.conf"
        changed=1
    fi
    if [ -f "$root/mods-enabled/access_checker.conf" ];then
        rm -f "$root/mods-enabled/access_checker.conf"
        changed=1
    fi
    if [ $changed -eq 0 ];then
        echo "noop"
    fi
}

check_apache_config(){
    apachectl configtest
}

get_unit(){
    if is_redhat;then
	    # Both ea-apache and httpd packages supply the same unit: httpd
        echo httpd
    else
        # Ubuntu-based cPanel runs httpd unit. However, it returns 0 even on missing unit file
        # So we check output '0/1 unit files listed'
        if [ $(systemctl list-unit-files httpd.service 2>&1 | awk '/unit files listed/{print $1}') = '1' ];then
            echo httpd
        else
            echo apache2
        fi
    fi
}

# the webshield is running as a separate entity
is_standalone() {
    [ "$TARGET_MODULARITY_MODE" = standalone ]
}

# We supplied our module for a hoster's NGINX. No webshield is running
is_nginx(){
    [ "$TARGET_MODULARITY_MODE" = nginx ]
}

# We supplied our module for a hoster's Apache.
# Webshield is running as well and serves non-HTTP/HTTPS ports
is_apache(){
    [ "$TARGET_MODULARITY_MODE" = apache ]
}

is_webshield_on(){
    [ "$TARGET_WEBSHIELD_STATE" = enabled ]
}

is_uninstall(){
    [ "$UNINSTALL" = 1 ]
}

# In Apache2nginx env we must add and configure the module
# even if Webshield is off, to implement Coraza-based WAF.
should_configure_nginx(){
    is_nginx && (is_webshield_on || is_apache2nginx_enabled) && ! is_uninstall
}
# In Apache env we only need the module if Webshield is enabled.
should_configure_apache(){
    is_apache && is_webshield_on && ! is_uninstall
}

cleanup_configs() {
    case "${1:-$TARGET_MODULARITY_MODE}" in
        nginx)
            remove_nginx_config
            ;;
        apache)
            remove_apache_conf
            ;;
    esac
}

put_nginx_conf() {
    local changed=0
    local version=$(nginx -v 2>&1 | grep -oP '(\d+[.]){2}\d+')
    local mod_path="$OUR_MODULES_DIR"/"ngx_http_access_checker_module_${version}.so"

    if is_apache2nginx_enabled && is_cpanel; then
        # ea-nginx-mod-wafcl is required by Coraza-based WAF
        # It is always installed by "apache2nginx setup" script, regardless of Imunify360 installation.
        mod_path="$OUR_MODULES_DIR"/"ngx_http_waf_module.so"
    fi

    if ! [ -s "$mod_path" ]; then
        echo "ERROR: Unable to find nginx module for version '$version'." >&2
        return 1
    fi

    # WARN: Explicit check that the path is exist and it is a directory
    # cause simple 'echo' to a file will raise error with an ambiguous message
    # "No such file or directory" like you're trying to *READ* from the file.
    # "dirname" does not check type of its argument and just cut everything
    # following the last slash.
    local path=''
    for path in "$NGINX_MODULE_CONF" "$NGINX_CHECKER_CONF"; do
        if ! [ -d $(dirname "$path") ]; then
            echo "ERROR: Unable to find directory for config '$path'." >&2
            return 1
        fi
    done

    if ! nginx -t ; then
        echo "ERROR: Invalid nginx config before installing module." >&2
        return 1
    fi

    local content="load_module ${mod_path};"
    if ! cmp -s "$NGINX_MODULE_CONF" <(echo "$content") ; then
        echo "$content" >| "$NGINX_MODULE_CONF" || return 1
        changed=1
    fi

    local content="access_checker unix:/var/run/imunify360/libiplists-daemon.sock;"
    if ! cmp -s "$NGINX_CHECKER_CONF" <(echo "$content") ; then
        echo "$content" >| "$NGINX_CHECKER_CONF" || return 1
        changed=1
    fi

    if [ $changed -eq 0 ];then
        echo "noop"
    fi
}

remove_nginx_config() {
    if [ -f "$NGINX_MODULE_CONF" ] || [ -f "$NGINX_CHECKER_CONF" ]; then
        rm -vf "$NGINX_MODULE_CONF" "$NGINX_CHECKER_CONF"
    else
        echo "noop"
    fi
}

prepare_configs() {
    case "${1:-$TARGET_MODULARITY_MODE}" in
        nginx)
            put_nginx_conf
            ;;
        apache)
            put_apache_conf
            ;;
    esac
}

check_nginx() {
    [ -s "$NGINX_MODULE_CONF" ] || return 1
    [ -s "$NGINX_CHECKER_CONF" ] || return 1
    nginx -T 2> /dev/null | grep -qE '^access_checker\s+unix:/[^.]+[.]sock;$' || return 1
    local pid=''
    pid=$(pgrep -f 'nginx:\s+master') || return 1
    # pid=1 is acquired by init.
    [[ "$pid" =~ ^([2-9]|[1-9][0-9]+)$ ]] || return 1
    grep -qP '/ngx_http_access_checker_module_(\d+[.]){2}\d+[.]so$' /proc/"$pid"/maps
}

check_configs() {
    case "${1:-$TARGET_MODULARITY_MODE}" in
        nginx)
            check_nginx
            ;;
        apache)
            check_apache_config
            ;;
    esac
}

has_hosting_panel(){
    local checks=(
        /usr/local/cpanel/cpanel
        /usr/sbin/plesk
        /usr/local/directadmin/custombuild/build
    )
    for i in ${checks[@]};do
        [ -e $i ] && return 0
    done
    return 1
}

count_processes(){
    local count=$(ps aux | grep -c '[i]m360:\|webshield-[s]sl-cache')
    echo $count
}

check_running(){
    # for hosts with hosting panels we expect 5 processes to be running.
    # otherwise 4 ones (ssl-cache is not expected to be run on no-panel hosts)
    local num=$(count_processes)
    local expected
    if has_hosting_panel; then expected=3; else expected=2; fi
    [ $num -ge $expected ] && return 0
    return 1
}

check_stopped(){
    local num=$(count_processes)
    [ $num -eq 0 ] && return 0
    return 1
}

enable_for_systemd(){
    dry_run=${1:-no}
    # Enable/disable the proxy server if needed
    if ! should_proxy_be_running && systemctl --quiet is-enabled $WEBSHIELD; then
        echo "$WEBSHIELD should not be running"
        if [ $dry_run = 'no' ]; then
            systemctl stop $WEBSHIELD || failed=1
            systemctl disable $WEBSHIELD || failed=1
            systemctl mask $WEBSHIELD || failed=1
        fi
        CONFIGURATION_MODIFIED=yes
    elif should_proxy_be_running && ! systemctl --quiet is-enabled $WEBSHIELD; then
        echo "$WEBSHIELD should be enabled in $TARGET_MODULARITY_MODE mode"
        if [ $dry_run = 'no' ]; then
            systemctl unmask $WEBSHIELD || failed=1
            systemctl enable $WEBSHIELD || failed=1
        fi
        CONFIGURATION_MODIFIED=yes
    fi

    for unit in $WAFD_UNIT $SSL_UNIT; do
        if ! systemctl --quiet is-enabled $unit; then
            if [ $dry_run = 'no' ]; then
                systemctl enable $unit || return $?
            fi
            CONFIGURATION_MODIFIED=yes
        fi
    done
}

safe_reload() {
    # WARN: In some cases 'reload-or-restart' action is not applicable
    # and need to be done directly.
    if systemctl --quiet is-active $1 ; then
        systemctl reload $1
    else
        systemctl restart $1
    fi
}

start_for_systemd(){
    echo "Ensuring $TARGET_MODULARITY_MODE mode is configured correctly"
    local failed=0

    # Cleanup configs from any previous mode
    if ! should_configure_apache && [ "$(cleanup_configs apache)" != "noop" ]; then
        echo "Apache config removed"
        safe_reload "$(get_unit)"
        CONFIGURATION_MODIFIED=yes
    fi
    if ! should_configure_nginx && [ "$(cleanup_configs nginx)" != "noop" ]; then
        echo "Nginx config removed"
        safe_reload nginx
        CONFIGURATION_MODIFIED=yes
    fi

    # Install required configs if missing
    if should_configure_apache && [ "$(prepare_configs apache)" != "noop" ]; then
        echo "Adding Apache config"
        if ! safe_reload "$(get_unit)"; then
            echo "Reverting Apache config"
            failed=1
            cleanup_configs apache
        fi
        CONFIGURATION_MODIFIED=yes
    fi
    if should_configure_nginx && [ "$(prepare_configs nginx)" != "noop" ]; then
        echo "Adding Nginx config"
        if ! nginx -t || ! safe_reload nginx; then
            echo "Reverting Nginx config"
            failed=1
            cleanup_configs nginx
        fi
        CONFIGURATION_MODIFIED=yes
    fi

    # Start the proxy server if needed
    if should_proxy_be_running; then
        state="$(systemctl is-active $WEBSHIELD 2>&1)"
        if [ "$state" != "active" ] && [ "$state" != "reloading" ]; then
            echo "$WEBSHIELD should be running in $TARGET_MODULARITY_MODE mode"
            systemctl unmask $WEBSHIELD || failed=1
            CONFIGURATION_MODIFIED=yes
        fi
    fi

    echo "$TARGET_MODULARITY_MODE" >| "$STATE_PATH"

    if [ $CONFIGURATION_MODIFIED = "yes" ]; then
        echo "Restarting the services due to configuration changes"
        systemctl stop $SSL_UNIT || failed=1
        systemctl stop $WEBSHIELD || failed=1
    fi

    systemctl start $WAFD_UNIT || return $?  # Must always be running
    if ! systemctl start $SSL_UNIT; then
        # WARN: Ignore error cause ssl-cache will exit if there is no panel.
        has_hosting_panel && return 1 || :
    fi
    if should_proxy_be_running; then
        # In apache mode we expect both apache and webshield are running: apache
        # for HTTP/HTTPS ports and webshield for the rest of them (like 2082/2083)
        # WARN: Sometimes Apache unit can not be reloaded and must to be restarted.
        systemctl start $WEBSHIELD || failed=1
    fi

    if [ $failed -ne 0 ]; then
        echo "Failed to ensure $TARGET_MODULARITY_MODE mode is configured correctly"
        return $failed
    fi
}

# Ths method installs all correct configs and reloads/restarts all services for
# any specific mode of operation **regardless of the current state**.
# It is fully idempotent, calling it multiple times with the same parameters
# (`TARGET_WEBSHIELD_STATE`, `TARGET_MODULARITY_MODE`) is safe and would exit
# with `NOOP_EXIT_CODE` if everything is already configured correctly.
# It will not restart services unless necessary (unless configuration has changed).
#
# Implementing every separate transition in every environment is not sustainable:
# * off -> standalone (installation or WEBSHIELD.enableswitch while WEBSHIELD_MODE=proxy)
# * standalone -> off (removal or WEBSHIELD.enable while WEBSHIELD_MODE=proxy)
# * off -> apache (cpanel, installation or WEBSHIELD.enable switch while WEBSHIELD_MODE=module)
# * apache -> off (cpanel, removal or WEBSHIELD.enable switch while WEBSHIELD_MODE=module)
# * standalone -> apache (cpanel, WEBSHIELD_MODE change)
# * apache -> standalone (cpanel, WEBSHIELD_MODE change)
# * apache -> nginx (cpanel, apache2nginx installation)
# * nginx -> apache (cpanel, apache2nginx removal while WEBSHIELD_MODE=module)
# * nginx -> standalone (cpanel, apache2nginx removal while WEBSHIELD_MODE=proxy)
# * etc. (probably forgot about several more)
# So instead, this method does:
# * anything -> apache
# * anything -> nginx
# * anything -> standalone
activate_for_systemd(){
    local RV
    enable_for_systemd
    RV=$?
    [ $RV -ne 0 ] && return $RV
    start_for_systemd
}

disable_for_systemd(){
    local failed=0
    # we don't disable wafd because it's used
    # for ip-list functionality
    systemctl disable $SSL_UNIT || failed=1
    # Remove configs that should not be there
    if ! should_configure_apache && [ "$(cleanup_configs apache)" != "noop" ]; then
        systemctl reload "$(get_unit)"
    fi
    if ! should_configure_nginx && [ "$(cleanup_configs nginx)" != "noop" ]; then
        systemctl reload nginx
    fi
    systemctl disable $WEBSHIELD || failed=1
    return $failed
}

stop_for_systemd(){
    local failed=0
    systemctl stop $SSL_UNIT || failed=1

    # Remove configs that should not be there
    if ! should_configure_apache && [ "$(cleanup_configs apache)" != "noop" ]; then
        systemctl reload "$(get_unit)"
    fi
    if ! should_configure_nginx && [ "$(cleanup_configs nginx)" != "noop" ]; then
        systemctl reload nginx
    fi
    systemctl stop $WEBSHIELD || failed=1

    return $failed
}

deactivate_for_systemd(){
    local RV
    stop_for_systemd
    RV=$?
    [ $RV -ne 0 ] && return $RV
    disable_for_systemd
}

do_terminate(){
    # Called on uninstall - must remove all configs!
    UNINSTALL=1
    WEBSHIELD_ENABLE=${WEBSHIELD_ENABLE:-false}
    stop_for_systemd
    systemctl stop $WAFD_UNIT
    local RV0=$?
    disable_for_systemd
    local RV=$?
    # We run both command but return success only if both of them succeded
    if [ $RV -ne 0 ]; then
        return $RV
    fi
    return $RV0
}

do_enable(){
    enable_for_systemd

    local rv=$?
    if [ $rv == 0 ]; then
        echo "enabled" > $STATEFILE
    fi
    return $rv
}

do_disable(){
    WEBSHIELD_ENABLE=${WEBSHIELD_ENABLE:-false}
    disable_for_systemd

    local rv=$?
    if [ $rv == 0 ]; then
        echo "disabled" > $STATEFILE
    fi
    return $rv
}

do_start(){
    start_for_systemd

    local rv=$?
    if [ $rv == 0 ]; then
        echo "started" > $STATEFILE
    fi
    return $rv
}

do_stop(){
    stop_for_systemd

    local rv=$?
    if [ $rv == 0 ]; then
        echo "stopped" > $STATEFILE
    fi
    return $rv
}

do_activate(){
    activate_for_systemd

    local rv=$?
    if [ $rv == 0 ]; then
        echo "activated" > $STATEFILE
    fi
    if [ $CONFIGURATION_MODIFIED = 'no' ]; then
        return ${NOOP_EXIT_CODE:-0}
    fi
    return $rv
}

do_deactivate(){
    WEBSHIELD_ENABLE=${WEBSHIELD_ENABLE:-false}
    detect_mode
    local changed=0
    if is_active; then
        deactivate_for_systemd
        changed=1
    fi

    local rv=$?
    if [ $rv == 0 ]; then
        echo "deactivated" > $STATEFILE
    fi
    if [ $changed -eq 0 ]; then
        echo "Not active, nothing to deactivate"
        return ${NOOP_EXIT_CODE:-0}
    fi
    return $rv
}

is_enabled(){
    enable_for_systemd 'dry-run'  # Expect no changes if the correct set of servies is enabled
    [ $CONFIGURATION_MODIFIED != 'yes' ]
}

is_active(){
    if is_standalone; then
        if check_running; then
            echo "$MAIN_UNIT is running"
            return 0
        else
            echo "$MAIN_UNIT is not running"
            return 1
        fi
    fi
    local name='undefined'
    local state='undefined'
    local units=($MAIN_UNIT $WAFD_UNIT $SSL_UNIT)
    local failed=0
    for name in ${units[@]}; do
        state="$(systemctl is-active $name 2>&1)"
        if [ "$state" = "active" ]; then
            echo "Unit '$name' is active."
        elif [ "$state" = "reloading" ]; then
            echo "Unit '$name' is reloading."
        else
            # WARN: ssl-cache must be processed in its very special way, see below.
            if ! [ "$name" = $SSL_UNIT ]; then
                echo "ERROR: Unit '$name' is NOT active, result='$state'." >&2
                failed=1
                continue
            fi
            if has_hosting_panel; then
                echo "ERROR: Unit '$SSL_UNIT' is NOT active, result '$state'." >&2
                failed=1
            else
                echo "WARNING: Unit '$SSL_UNIT' is NOT active, result '$state' (ignored)." >&2
            fi
        fi
    done
    if [ $failed -eq 0 ]; then
        if ! check_configs; then
            echo "WARNING: Web server is not configured." >&2
            failed=1
        fi
    fi
    return $failed
}

do_restart(){
    do_stop
    do_start
}

do_enable_splashscreen(){
    is_standalone || return ${NOOP_EXIT_CODE:-0}
    local ss_state=$(awk '$1 == "splashscreen_antibot" {gsub(";","",$2);print $2}' $WEBSHIELD_ANTIBOT_CONF)
    if [ "$ss_state" = on ];then
        echo "splashscreen is already enabled"
        return ${NOOP_EXIT_CODE:-0}
    fi
    sed -i -e "/splashscreen_antibot/ {s/off/on/}" $WEBSHIELD_ANTIBOT_CONF
    do_restart
}

do_disable_splashscreen(){
    is_standalone || return ${NOOP_EXIT_CODE:-0}
    local ss_state=$(awk '$1 == "splashscreen_antibot" {gsub(";","",$2);print $2}' $WEBSHIELD_ANTIBOT_CONF)
    if [ "$ss_state" = off ];then
        echo "splashscreen is already disabled"
        return ${NOOP_EXIT_CODE:-0}
    fi
    sed -i -e "/splashscreen_antibot/ {s/on/off/}" $WEBSHIELD_ANTIBOT_CONF
    do_restart
}

do_enable_cpanelprotection(){
    is_standalone || return ${NOOP_EXIT_CODE:-0}
    local cp_state=$(awk '$2 == "$cpanel_protection" {gsub(";","",$3);print $3}' $VIRTSERVER_CONF)
    if [ "$cp_state" = 1 ];then
        echo "cpanel_protection is already enabled"
        return ${NOOP_EXIT_CODE:-0}
    fi
    sed -i -e '/$cpanel_protection/ {s/0/1/}' $VIRTSERVER_CONF
    do_restart
}

do_disable_cpanelprotection(){
    is_standalone || return ${NOOP_EXIT_CODE:-0}
    local cp_state=$(awk '$2 == "$cpanel_protection" {gsub(";","",$3);print $3}' $VIRTSERVER_CONF)
    if [ "$cp_state" = 0 ];then
        echo "cpanel_protection is already disabled"
        return ${NOOP_EXIT_CODE:-0}
    fi
    sed -i -e '/$cpanel_protection/ {s/1/0/}' $VIRTSERVER_CONF
    do_restart
}

do_reload(){
    # WARN: Ignoring errors here is for the compatibility with sysvinit script
    # which contains bug - on action "reload" it always exits with code 0.
    # try-reload-or-restart is supported only from version 229,
    # which is not the case for Centos7. The difference between try-reload-or-restart
    # and reload-or-restart is that former does nothing unless the service is running.
    if systemctl --quiet is-active $SSL_UNIT;then
        systemctl reload-or-restart $SSL_UNIT || :
    fi
    if systemctl --quiet is-active $WAFD_UNIT;then
        systemctl reload-or-restart $WAFD_UNIT || :
    fi
    if systemctl --quiet is-active $MAIN_UNIT;then
        systemctl reload-or-restart $MAIN_UNIT || :
    fi
}

set_mode(){  # TODO: Kept for compatibility, but we should use `activate` directly instead.
    WEBSHIELD_MODE=$1
    detect_mode
    do_activate
}

configure() {
    deactivate_for_systemd || true
    systemctl unmask $WEBSHIELD || true
    is_nginx_mode_required && systemctl mask $WEBSHIELD || true
    activate_for_systemd || true
    # During upgrade we may get a new version of the .so module
    # even if there are no changes in configs required.
    # Restarting nginx just in case.
    # WARNING: 'reload' is not enough, 'restart' must be used!
    should_configure_nginx && systemctl restart nginx || true
}

print_help(){
    echo "enable                    : enables webshield starting on boot (without actully starting it)"
    echo "is-enabled                : shows if the webshield is enabled to start on boot"
    echo "is-active                 : shows if the webshield is running now"
    echo "disable                   : disables webshield starting on boot (without actully stopping it)"
    echo "start                     : starts webshield (without enabling its starting on boot)"
    echo "stop                      : stops webshield (without disabling its starting on boot)"
    echo "activate                  : enables webshield starting on boot and starts it right away"
    echo "deactivate                : stops webshield right away and disables its starting on boot"
    echo "terminate                 : stops webshield and wafd right away and disables its starting on boot"
    echo "enable-splashscreen       : enables splashscreen functionality for webshield"
    echo "disable-splashscreen      : disables splashscreen functionality for webshield"
    echo "enable-cpanelprotection   : enables cpanelprotection functionality for webshield"
    echo "disable-cpanelprotection  : disables cpanelprotection functionality for webshield"
    echo "mode                      : shows the current module"
    echo "mode-module               : if possible switch from standalone to module-based mode"
    echo "mode-proxy                : if possible switch from module-based to standalone mode"
    echo "mode-supported            : prints if switching to module-based mode is supported for current system"
    echo "reload                    : reload settings without restart"
}

detect_mode
CONFIGURATION_MODIFIED=no

case "$1" in
    enable)
        do_enable
        ;;
    disable)
        do_disable
        ;;
    is-enabled)
        is_enabled
        ;;
    is-active)
        is_active
        ;;
    start)
        do_start
        ;;
    stop)
        do_stop
        ;;
    activate)
        do_activate
        ;;
    deactivate)
        do_deactivate
        ;;
    terminate)
        do_terminate
        ;;
    enable-splashscreen)
        do_enable_splashscreen
        ;;
    disable-splashscreen)
        do_disable_splashscreen
        ;;
    enable-cpanelprotection)
        do_enable_cpanelprotection
        ;;
    disable-cpanelprotection)
        do_disable_cpanelprotection
        ;;
    reload)
        do_reload
        ;;
    mode)
        if [ "$2" = module ]; then
            set_mode 'module'
        elif [ "$2" = proxy ]; then
            set_mode 'proxy'
        elif [ "$2" = supported ]; then
            is_supported 'out'
        elif [ -z "$2" ]; then
            if [ "$TARGET_MODULARITY_MODE" = standalone ]; then
                echo proxy
            else
                echo "$TARGET_MODULARITY_MODE"
            fi
        else
            echo "Unknown mode: $2. Exit"
            exit
        fi
        ;;
    mode-proxy)
        set_mode 'proxy'
        ;;
    mode-module)
        set_mode 'module'
        ;;
    mode-supported)
        is_supported 'out'
        ;;
    is-apache)
        is_apache
        ;;
    is-nginx)
        is_nginx
        ;;
    is-cloudways)
        is_cloudways
        ;;
    is-standalone)
        is_standalone
        ;;
    configure)
        configure
        ;;
    help)
        print_help
        ;;
    *)
        echo "Usage: $0 {enable|disable|start|stop|activate|deactivate|is-enabled|is-active|enable-splashscreen|disable-splashscreen|enable-cpanelprotection|disable-cpanelprotection|reload|mode|mode proxy|mode module|mode supported|is-apache|is-nginx|is-cloudways|is-standalone|help}"
        exit 2
esac