File: //usr/local/cwaf/installer.sh
#! /usr/bin/env bash
#
# Comodo WAF Install Script
#
#################################################
#################################################
# VARS AND VARIOUS SETTINGS
#################################################
. ./vars.sh
export PERL_MM_USE_DEFAULT=1
touch $INSTALL_LOGFILE
export STATS_FILE='INFO.TXT'
#set -x
#exec 2>/tmp/err
#################################################
# PREREQS AND SUCH
#################################################
# non-root?
if [ `uname` = "FreeBSD" ]; then
if [ `id -u` != "0" ]; then
echo "ERROR: root privileges required"
exit 1
fi
else
if [ x"$UID" != x"0" -o x"$EUID" != x"0" ]; then
echo "ERROR: root privileges required"
exit 1
fi
fi
# cmdline args
show_help() {
echo "Args are:"
echo " --examples # examples of usage"
echo " --update # update existing cwaf (requires --path for standalone)"
echo " --mode=<cpanel|plesk|webmin|directadmin|standalone> # installation/update mode"
echo " --prompt=<auto|dialog|readline> # interactive installation mode (ignored if --update or --batch)"
echo " --path=</path/to/cwaf> # default installation path (required for standalone)"
echo "For batch install:"
echo " --batch # install in batch mode (requires --login and --password)"
echo " --login=<CWAF user login> # CWAF user login (required)"
echo " --password=<CWAF user password> # CWAF user password (required)"
echo " --platform=<Apache|LiteSpeed|Nginx> # web platform: Apache, LiteSpeed, Nginx"
}
show_examples() {
echo "Examples of usage:"
echo " $0 (Simple install)"
echo " $0 --prompt=readline (Install without color dialogs)"
echo " $0 --update --mode=cpanel (Update in cPanel mode)"
echo " $0 --update --mode=standalone --path=/opt/cwaf (Update in standalone mode)"
echo " $0 --batch --login=login --password=password (Batch install for cPanel, Plesk and Webmin, default platform Apache)"
echo " $0 --batch --login=login --password=password --platform=LiteSpeed (Batch install for cPanel and Plesk, platform LiteSpeed)"
echo " $0 --batch --login=login --password=password --mode=standalone --path=/opt/cwaf (Batch install in standalone mode)"
}
export INSTALL_MODE='auto'
export SHOW='auto'
export UPDATE='no'
export BATCH_MODE='no'
export INSTALL_PATH=''
# default web platform
export CWAF_PLATFORM='Apache'
# default modsecurity major version
export MODSEC_FAMILY='2'
while [[ $# -gt 0 ]] && [[ ."$1" = .--* ]] ; do
opt="$1";
shift;
case "$opt" in
"--" ) break 2
;;
"--mode") INSTALL_MODE=$1
shift
;;
"--mode="*) INSTALL_MODE="${opt#*=}"
;;
"--prompt") SHOW=$1
shift
;;
"--prompt="*) SHOW="${opt#*=}"
;;
"--update") UPDATE='yes'
;;
"--batch") BATCH_MODE='yes'
;;
"--path") INSTALL_PATH=$1
shift
;;
"--path="*) INSTALL_PATH="${opt#*=}"
;;
"--login") CWAF_LOGIN=$1
shift
;;
"--login="*) CWAF_LOGIN="${opt#*=}"
;;
"--password") CWAF_PASSWORD=$1
shift
;;
"--password="*) CWAF_PASSWORD="${opt#*=}"
;;
"--platform") CWAF_PLATFORM=$1
shift
;;
"--platform="*) CWAF_PLATFORM="${opt#*=}"
;;
"--help") show_help
exit 0
;;
"--examples") show_examples
exit 0
;;
*) echo "Invalid option: $opt"
show_help
exit 1
;;
esac
done
# install path
if [ -n "$INSTALL_PATH" ]; then
CWAF_INSTALL_PATH="$INSTALL_PATH"
fi
# prepare dialog params
if [ `uname` = "FreeBSD" ]; then
export DIALOG_BIN=`which dialog`
export DIALOG=${DIALOG_BIN}' --no-mouse --stdout --trim --no-cr-wrap --no-collapse --keep-window --backtitle "Comodo WAF Installer (version $CWAF_VERSION)" --title "| Log file '$INSTALL_LOGFILE' (use TAB to switch) |" --begin 2 2 --tailboxbg $INSTALL_LOGFILE $TBH $TBW --and-widget --keep-window'
else
export DIALOG_BIN="./bin/dialog"
export DIALOGRC="./bin/dialog.rc"
export DIALOG='./bin/dialog --no-mouse --stdout --trim --no-cr-wrap --no-collapse --keep-window --backtitle "Comodo WAF Installer (version $CWAF_VERSION)" --title "| Log file '$INSTALL_LOGFILE' (use TAB to switch) |" --begin 2 2 --tailboxbg $INSTALL_LOGFILE $TBH $TBW --and-widget --keep-window'
fi
# readline/dialog option
case "$SHOW" in
"dialog") SHOW="dialog"
;;
"readline") SHOW="read"
;;
"auto") if ${DIALOG_BIN} --version 1>/dev/null 2>&1; then
SHOW="dialog"
else
SHOW="read"
fi
;;
*) echo "Invalid prompt mode"
show_help
exit 1
;;
esac
# installation mode
case "$INSTALL_MODE" in
"cpanel")
INSTALL_PATH="$CWAF_CPANEL_PATH"
;;
"plesk")
INSTALL_PATH="$CWAF_PLESK_PATH"
;;
"webmin")
INSTALL_PATH="$CWAF_WEBMIN_PATH"
;;
"directadmin")
INSTALL_PATH="$CWAF_DA_PATH"
;;
"standalone")
INSTALL_PATH="$CWAF_STANDALONE_PATH"
;;
"auto")
:
;;
*) echo "Invalid installation mode"
show_help
exit 1
;;
esac
COLS=${COLUMNS:=`tput cols`}
LINS=${LINES:=`tput lines`}
export TBW=`expr $COLS - 6`
export TBH=`expr $LINS - 4`
#export DIALOGRC="./bin/dialog.rc"
#export DIALOG_BIN="./bin/dialog"
#export DIALOG='./bin/dialog --no-mouse --stdout --trim --no-cr-wrap --no-collapse --keep-window --backtitle "Comodo WAF Installer (version $CWAF_VERSION)" --title "| Log file '$INSTALL_LOGFILE' (use TAB to switch) |" --begin 2 2 --tailboxbg $INSTALL_LOGFILE $TBH $TBW --and-widget --keep-window'
# check install mode
if [ x"$INSTALL_MODE" == x"auto" ]; then
if [ -x $CPANEL_BIN ]; then
INSTALL_MODE="cpanel"
elif [ -x $PLESK_BIN ]; then
INSTALL_MODE="plesk"
elif [ -f $WEBMIN_CONF ]; then
INSTALL_MODE="webmin"
elif [ -x $DA_BIN ]; then
INSTALL_MODE="directadmin"
else
INSTALL_MODE="standalone"
fi
fi
# batch/update mode
if [ x"$UPDATE" == x"yes" -o x"$BATCH_MODE" == x"yes" ]; then
if [ x"$BATCH_MODE" == x"yes" ]; then
if [ -z "$CWAF_LOGIN" -o -z "$CWAF_PASSWORD" ]; then
echo "Options '--login' and '--password' required in 'batch' mode"
show_help
exit 1
fi
if [ -z "$INSTALL_PATH" -a x"$INSTALL_MODE" == x"standalone" ]; then
echo "Option '--path' required in 'standalone' mode"
show_help
exit 1
fi
fi
# update/batch mode should not show windows and such
SHOW="read"
fi
#################################################
# MISC FUNCS
#################################################
# collect some stats
collect_stats() {
echo "$*" >> $STATS_FILE
}
# log a string
# -q - not show, just log to file
log() {
if [ x"$1" == x"-q" ]; then
QUIET="yes"
shift
fi
echo -ne "`date +'%d-%m-%Y %H:%M:%S'` $*\n" >> $INSTALL_LOGFILE
if [ -z "$QUIET" -a x"$SHOW" == x"read" ]; then
echo >&2 "| LOG : $*"
fi
}
# log stdin
log2() {
while read LINE; do
log $* "$LINE"
done
}
# backup some files or dirs
# instdir file1 file2 ...
backup_files() {
IDIR=${1}
shift
for F in ${*}; do
if [ -d "${IDIR}/${F}" ]; then
for FF in ${IDIR}/${F}/*.conf; do
[ -f "${FF}" ] && cp -f ${FF} ${FF}.backup
done
elif [ -f "${IDIR}/${F}" ]; then
cp -f ${IDIR}/${F} ${IDIR}/${F}.backup
fi
done
}
# encrypt password
encrypt_password() {
PASS=$1
if [ ! -f "$BASE64_BIN" ]; then
echo "$PASS"
return 0
fi
HEADER='$2y$17$'
# use base64 do decrypt
RESULT=$(echo -n "$PASS" | $BASE64_BIN 2>&1)
# add blowfish header '$2y$17$'
echo "$HEADER$RESULT"
return 1
}
# decrypt password if encrypted
decrypt_password() {
PASS=$1
if [ ! -f "$BASE64_BIN" ]; then
echo "$PASS"
return 0
fi
HEADER='$2y$17$'
# password contain blowfish header ?
if [[ $PASS == *$HEADER* ]]; then
# remove header and decrypt
INP=${PASS#$HEADER}
RESULT=$(echo -n "$INP" | $BASE64_BIN -d 2>&1)
echo "$RESULT"
return 1
else
# password was unencrypted, return
echo "$PASS"
return 1
fi
}
# check if password encrypted
is_password_encrypted() {
PASS=$1
HEADER='$2y$17$'
# password contain blowfish header ?
if [[ $PASS == *$HEADER* ]]; then
return 1
else
return 0
fi
}
# check if web platform supported
# return yes or no
is_platform_supported() {
TEST_PLATFORM=$1
case "$TEST_PLATFORM" in
"Apache")
if [ x"$MODSEC_VERSION" == x"unknown" ]; then
echo "no"
else
echo "yes"
fi
;;
"LiteSpeed")
if [ x"$LITESPEED_MODSEC" == x"unknown" ]; then
echo "no"
else
echo "yes"
fi
;;
"Nginx")
if [ x"$NGINX_MODSEC" == x"unknown" ]; then
echo "no"
else
echo "yes"
fi
;;
*)
echo "no"
;;
esac
}
# get Plesk conf params (file and list of params are the arguments)
get_plesk_params() {
FILE=$1
shift
for PARM in ${*}; do
eval PLESK_${PARM}=`grep "$PARM " $FILE | sed -r "s/$PARM (.*)/\1/"`
done
return 1
}
# reset conf params (from-file, to-file and list of params are the arguments)
reset_params() {
FROM_FILE=$1
TO_FILE=$2
shift
shift
local FROMPARM
local TOPARAM
for PARM in ${*}; do
TOPARAM=`grep "$PARM " $TO_FILE 2>&1`
FROMPARM=`grep "$PARM " $FROM_FILE | sed -r "s/$PARM (.*)/\1/" 2>&1`
if [ ! -z "$FROMPARM" ]; then
sed -ri "s=$TOPARAM=$PARM $FROMPARM=g" $TO_FILE
fi
done
return 1
}
# get standalone update mode path from the config
get_standalone_path() {
FILE='/etc/cwaf/main.conf'
PARM='cwaf_path'
STANDALONE_PATH=`grep $PARM $FILE | sed -r "s/$PARM=\"(.*)\"/\1/"`
echo $STANDALONE_PATH
}
# install protection rules
install_rules() {
if [ x"$UPDATE" != x"yes" ]; then
if ${SHOW}_yesno "Do you want to protect your server with default rule set?"; then
if $CWAF_INSTALL_PATH/scripts/updater.pl 2>&1 1>/dev/null; then
log "Rules updated successfully"
rm -f "$CWAF_INSTALL_PATH/etc/first.run"
if $CWAF_INSTALL_PATH/scripts/cwaf-cli.pl -xa 230040 2>&1 1>/dev/null; then
log "Default exclude list created"
else
${SHOW}_message "Warning! Default exclude list has not been created automatically. Try manual exclude list update"
log "Warning! Default exclude list has not been created automatically. Try manual exclude list update"
fi
else
${SHOW}_message "Warning! Rules have not been updated. Check your credentials and try again later manually"
log "Warning! Rules have not been updated. Check your credentials and try again later manually"
fi
fi
fi
}
#################################################
# INTERACTION FUNCTIONS
#################################################
####### YESNO ######
read_yesno() {
if [ x"$BATCH_MODE" == x"yes" ]; then
return 0
else
read -e -p">> ${1} [y/n]: " RES 1>&2
case $RES in
Y*|y*) return 0;;
esac
return 1
fi
}
dialog_yesno() {
eval "$DIALOG --title '| Please answer |' --yesno '${1}' 0 0"
}
######## LOGIN AND PASSWORD ########
read_login() {
if [ ! -z "$CWAF_LOGIN" -a x"$BATCH_MODE" == x"yes" ]; then
echo "$CWAF_LOGIN"
else
read -i "${2}" -e -p ">> $1: " RES 1>&2
echo "$RES"
fi
}
read_pass() {
if [ ! -z "$CWAF_PASSWORD" -a x"$BATCH_MODE" == x"yes" ]; then
echo "$CWAF_PASSWORD"
else
echo -n "${1}: " 1>&2
X='x'
while [ "$X" ]; do
read -s -n1 X 1>&2
RES="${RES}${X}"
echo -n '*' 1>&2
done
echo 1>&2
echo "$RES"
fi
}
dialog_login() {
eval "$DIALOG --title '| Login |' --max-input 128 --inputbox '${1}' 0 0 '${2}'"
}
dialog_pass() {
eval "$DIALOG --title '| Password |' --max-input 128 --insecure --passwordbox '${1}' 0 0"
}
######## INPUT ###########
read_input() {
if [ x"$BATCH_MODE" == x"yes" ]; then
echo "${2}"
else
read -i "${2}" -e -p ">> $1: " RES 1>&2
echo "$RES"
fi
}
dialog_input() {
eval "$DIALOG --title '| Input |' --inputbox '${1}' 0 0 '${2}'"
}
######## ERROR MESSAGE ###########
read_error() {
echo "ERROR: ${*}" 1>&2
}
dialog_error() {
eval "$DIALOG --title '| ******** ERROR ******** |' --msgbox '${*}' 0 0"
}
###### MESSAGE #########
read_message() {
echo '+------------------------------------------------------'
echo -e "${*}" | sed 's/^/| /g' 1>&2
echo '+------------------------------------------------------'
}
dialog_message() {
eval "$DIALOG --title '| Information |' --msgbox '${*}' 0 0"
}
###### CWAF_PLATFORM ######
dialog_platform() {
TMPFILE="/tmp/file.tmp.$$"
eval "$DIALOG --radiolist '${1}' 10 45 3 \
'Apache' 'Apache Web Server' on \
'LiteSpeed' 'LiteSpeed Web Server' off \
'Nginx' 'Nginx Web Server' off \
2> $TMPFILE"
RETVAL=$?
CHOICE=`cat $TMPFILE`
rm -rf $TMPFILE
case $RETVAL in
0)
echo "${CHOICE}" ;;
1)
echo '' ;;
255)
echo '' ;;
esac
}
read_platform() {
if [ ! -z "$CWAF_PLATFORM" -a x"$BATCH_MODE" == x"yes" ]; then
echo "$CWAF_PLATFORM"
else
while true; do
SELECTION=''
read -p "${1}
[1] Apache
[2] LiteSpeed
[3] Nginx
[1] >> " RES 1>&2
case $RES in
1)
SELECTION='Apache' ;;
2)
SELECTION='LiteSpeed' ;;
3)
SELECTION='Nginx' ;;
'')
SELECTION='Apache' ;;
*)
SELECTION='' ;;
esac
if [ -z "$SELECTION" ]; then
${SHOW}_message "You should select your WEB platform. Please press 1, 2 or 3."
continue
fi
break
done
echo "${SELECTION}"
fi
}
get_platform() {
if [ -f $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF ]; then
CWAF_PLATFORM=`grep '^cwaf_platform=' $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF | sed -r 's/^cwaf_platform=\"(.*)\"/\1/'`
if [ -z "$CWAF_PLATFORM" ]; then
CWAF_PLATFORM='Apache'
fi
else
CWAF_PLATFORM='Apache'
fi
echo $CWAF_PLATFORM
}
get_password() {
if [ -f $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF ]; then
CWAF_PASSWORD=`grep '^cwaf_passwd=' $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF | sed -r 's/^cwaf_passwd=\"(.*)\"/\1/'`
echo $CWAF_PASSWORD
fi
}
# code by Martynas Bendorius, www.martynas.it
usergroup_add() {
OS=`uname`
DEBIAN_VERSION=/etc/debian_version
if [ ${OS} = "FreeBSD" ]; then
PW=/usr/sbin/pw
if ! /usr/bin/grep -q "^${2}:" < /etc/group; then
${PW} groupadd ${2}
fi
if ! /usr/bin/id ${1} > /dev/null; then
${PW} useradd -g ${2} -n ${1} -s /sbin/nologin
fi
elif [ -e ${DEBIAN_VERSION} ]; then
if ! /usr/bin/id ${1} > /dev/null; then
adduser --system --group --no-create-home \
--disabled-login --force-badname ${1} > /dev/null
fi
else
if ! /usr/bin/id ${1} > /dev/null; then
/usr/sbin/useradd -r -s /bin/false ${1}
fi
fi
}
# check if user exists.
# Return 0/1 if user exists/not exist
check_user() {
if /usr/bin/id ${1} > /dev/null; then
return 0
else
return 1
fi
}
####### GAUGE ########
# err... it is not a pure gauge, but with embedded cpan... ugly
read_gauge() {
GAUGE=0
FACTOR=`expr 100 / $(echo $* | wc -w)`
for M in ${*}; do
log "Installing $M ... ${GAUGE}%"
$CPAN_BIN -f -i $M 2>&1 | log2
if [ $? -ne 0 ]; then
echo "FAILED! see $INSTALL_LOGFILE"
break
fi
GAUGE=`expr $GAUGE + $FACTOR`
done
echo "DONE"
}
dialog_gauge() {
GAUGE=0
FACTOR=`expr 100 / $(echo $* | wc -w)`
(for M in ${*}; do
log "Installing $M"
echo "XXX"
echo "$GAUGE"
echo "Running $CPAN_BIN -f -i $M"
echo "XXX"
$CPAN_BIN -f -i $M 2>&1 | log2
if [ $? -ne 0 ]; then
break
fi
GAUGE=`expr $GAUGE + $FACTOR`
done; echo -e "XXX\n100\nDONE, PRESS ENTER\nXXX") | eval "$DIALOG --title 'Please wait' --gauge preparing 7 50"
}
function remove_ea3_hooks {
log "Removing EasyApache 3 CWAF hooks"
if [ -f /scripts/posteasyapache ]; then
sed -i '/#CWAF_HOOK/d' /scripts/posteasyapache > /dev/null 2>&1
fi
if [ -f /scripts/preeasyapache ]; then
sed -i '/#CWAF_HOOK/d' /scripts/preeasyapache > /dev/null 2>&1
fi
}
########################################################
# INSTALLERS
########################################################
perl_install_missed() {
# check CPAN
if [ ! -x "$CPAN_BIN" ]; then
${SHOW}_error "CPAN is not installed!\nPlease install it, then rerun this installation."
exit 1
fi
# test for old CPAN
CENTOS_VERSION_MAGOR=`check_centos`
if [ x"$CENTOS_VERSION_MAGOR" == x"5" -a ! -d "/root/.cpan" ]; then
#echo "no" | cpan
return 1
fi
# configure CPAN
$CPAN_BIN -A CPAN::Version 2>&1 | log2
${SHOW}_gauge ${*}
return 0
}
########################################################
# CHECKERS
########################################################
# check for cpanel installed, return version
check_cpanel() {
if [ -x $CPANEL_BIN ]; then
CPANEL_VERSION=$($CPANEL_BIN -V | sed -r 's=^([0-9.]+)(.*)=\1=g')
log "Found cPanel version $CPANEL_VERSION"
else
log "No cPanel found"
return 1
fi
echo "$CPANEL_VERSION"
return 0
}
# check for plesk installed, return version
check_plesk() {
if [ -x $PLESK_BIN ]; then
PLESK_VERSION=$($PLESK_BIN version | grep "Product version" | grep -oE "[0-9\.]{4}")
log "Found Plesk version $PLESK_VERSION"
else
log "No Plesk found"
return 1
fi
echo "$PLESK_VERSION"
return 0
}
# check for cpanel installed, return version
check_directadmin() {
if [ -x $DA_BIN ]; then
DA_VERSION=$($DA_PATH/directadmin v | grep -oE "[v0-9\.]+")
log "Found DirectAdmin version $DA_VERSION"
else
log "No DirectAdmin found"
return 1
fi
echo "$DA_VERSION"
return 0
}
# check for webmin installed, return version
check_webmin() {
if [ -f $WEBMIN_CONF ]; then
WEBMIN_VERSION=$(cat /etc/webmin/version)
log "Found Webmin version $WEBMIN_VERSION"
else
log "No Webmin found"
return 1
fi
echo "$WEBMIN_VERSION"
return 0
}
# check if Easy Apache 4 is available
check_ea4() {
if [ -e "/etc/cpanel/ea4/is_ea4" ]; then
return 0
else
return 1
fi
}
# check for apachectl, return version
check_apache() {
if [ ! -f "$APACHECTL_BIN" ]; then
log "No APACHECTL found"
APACHE_VERSION='unknown'
echo "$APACHE_VERSION"
return 1
fi
APACHE_VERSION=$($APACHECTL_BIN -v 2>&1 | grep '^Server version: Apache' | sed -r 's=^(Server version.+)(/)([0-9.]+)(.*)=\3=g')
if [ -z "$APACHE_VERSION" ]; then
log "Failed to aquire APACHE version"
APACHE_VERSION='unknown'
echo "$APACHE_VERSION"
return 1
fi
log "Found APACHE version $APACHE_VERSION"
echo "$APACHE_VERSION"
return 0
}
# check for modsecurity, return version
check_modsec() {
# check for apache syntax
APACHE_SYNTAX=$($APACHECTL_BIN -t 2>&1 | grep 'Syntax OK')
if [ -z "$APACHE_SYNTAX" ]; then
log "WARNING: Syntax error in Apache config file"
${SHOW}_message "Apache config syntax should be correct to check ModSecurity version."
MODSEC_VERSION='unknown'
log "No MODSECURITY detected"
echo "$MODSEC_VERSION"
return 1
fi
# check if apache running
APACHE_RUNNING=$(\
ps axo args | \
awk '{print $1}' | \
egrep -w '(httpd|httpd2|apache|apache2)' \
)
if [ -z "$APACHE_RUNNING" ]; then
log "WARNING: Apache is not started"
${SHOW}_message "Running Apache required to check ModSecurity version."
MODSEC_VERSION='unknown'
log "No MODSECURITY detected"
echo "$MODSEC_VERSION"
return 1
fi
# check for modsecurity
if ! ($APACHECTL_BIN -M 2>&1 | grep -qw 'security2_module'); then
MODSEC_VERSION='unknown'
log "No MODSECURITY detected"
echo "$MODSEC_VERSION"
return 1
fi
# check mod_security version ( not very reliable but it works)
# 1. get running apache pid
# 2. find loaded .so location (via /proc/PID/maps)
# 3. get version string from .so
# MODSEC_VERSION=$(\
# ps ax | \
# egrep -w '(httpd|apache|apache2)' | \
# grep -v grep | awk '{print $1}' | \
# xargs -l1 -I_APID_ grep '/mod_security2.so' /proc/_APID_/maps | \
# tail -n1 | \
# awk '{print $6}' | \
# xargs -l1 strings | \
# grep '^ModSecurity for Apache/' | \
# tail -n1 | \
# sed -r -e 's/^ModSecurity for Apache\/([0-9.]+).*/\1/' \
# )
# get process ID
PROC_ID=$(ps axo pid,args | awk '{print $1 " " $2}' | egrep -e '/(httpd|httpd2|apache|apache2)' | grep -v grep | head -n1 | awk '{print $1}')
# time for backup plan
if [ -z "$PROC_ID" ]; then
PROC_ID=$(ps axo pid,args | awk '{print $1 " " $2}' | egrep -w '(httpd|httpd2|apache|apache2)' | grep -v grep | grep -v nimbus | head -n1 | awk '{print $1}')
fi
# get mod_security library
if [ $(uname) == 'FreeBSD' ]; then
MODSEC_LIB=$(grep '/mod_security2.so' /proc/${PROC_ID}/map | head -n1 | awk '{print $13}')
else
MODSEC_LIB=$(grep '/mod_security2.so' /proc/${PROC_ID}/maps | head -n1 | awk '{print $6}')
fi
# get mod_security version
if [ -n "$MODSEC_LIB" ]; then
MODSEC_VERSION=$(strings ${MODSEC_LIB} | grep 'ModSecurity for Apache/' | head -n1 | cut -d/ -f2 | awk '{print $1}')
fi
# failed?
if [ -z "$MODSEC_VERSION" ]; then
MODSEC_VERSION='unknown'
log "Failed to aquire MODSECURITY version"
echo "$MODSEC_VERSION"
return 1
fi
echo "$MODSEC_VERSION"
log "Found MODSECURITY version $MODSEC_VERSION"
return 0
}
check_litespeed() {
TEST_LITESPEED=$(which lshttpd 2>&1)
if [ -x "$TEST_LITESPEED" ]; then
LITESPEED_BIN="$TEST_LITESPEED"
log "Found LiteSpeed binary $LITESPEED_BIN"
fi
if [ ! -x "$LITESPEED_BIN" ]; then
LITESPEED_VERSION='unknown'
echo "$LITESPEED_VERSION"
log "LiteSpeed binary $LITESPEED_BIN not found!"
return 1
fi
LITESPEED_VERSION=$($LITESPEED_BIN -v 2>&1 | grep -F "LiteSpeed" | sed -r -e 's/^LiteSpeed\/(.*)/\1/')
OPEN_LITESPEED=$($LITESPEED_BIN -v 2>&1 | grep -iF "LiteSpeed" | grep -iF "Open")
if [ -z "$LITESPEED_VERSION" ]; then
LITESPEED_VERSION='unknown'
echo "$LITESPEED_VERSION"
log "Failed to get LiteSpeed version"
return 1
fi
log "Found LiteSpeed version $LITESPEED_VERSION"
if [ "${LITESPEED_VERSION/Open}" = "$LITESPEED_VERSION" -o ! -z "$OPEN_LITESPEED" ] ; then
echo "$LITESPEED_VERSION"
log "Mod Security supported"
return 0
else
echo "$LITESPEED_VERSION"
log "Mod Security NOT supported in this version of LiteSpeed"
return 1
fi
}
is_open_ls() {
TEST_LITESPEED=$(which lshttpd 2>&1)
if [ -x "$TEST_LITESPEED" ]; then
LITESPEED_BIN="$TEST_LITESPEED"
fi
if [ ! -x "$LITESPEED_BIN" ]; then
echo "NO"
return
fi
TEST_OPEN_LITESPEED=$($LITESPEED_BIN -v 2>&1 | grep -iF "LiteSpeed" | grep -iF "Open" )
if [ -z "$TEST_OPEN_LITESPEED" ] ; then
echo "NO"
else
echo "YES"
fi
}
nginx_binary() {
# check where is nginx binary located
TEST_NGINX=$(which nginx 2>&1)
if [ -x "$TEST_NGINX" ]; then
NGINX_BIN="$TEST_NGINX"
else
# check standard path
if [ -x "/usr/sbin/nginx" ]; then
NGINX_BIN="/usr/sbin/nginx"
fi
fi
if [ -x "$NGINX_BIN" ]; then
log "Found Nginx binary $NGINX_BIN"
echo "$NGINX_BIN"
else
log "Nginx binary $NGINX_BIN not found!"
echo ''
fi
}
nginx_conf() {
# find config path
# /usr/local/nginx/sbin/nginx -t
CONF_STR=`$NGINX_BIN -t 2>&1 | grep 'syntax is ok'`
if [ -n "$CONF_STR" ]; then
CONF_STR=`echo "$CONF_STR" | sed -r -e 's/.*file (\/.*) syntax is ok/\1/'`
fi
# check found config path and default paths
if [ -r "$CONF_STR" ]; then
log "Nginx config found: $CONF_STR"
NGINX_CONF=$CONF_STR
elif [ -r '/usr/local/nginx/conf/nginx.conf' ]; then
log "Nginx config found: /usr/local/nginx/conf/nginx.conf"
NGINX_CONF='/usr/local/nginx/conf/nginx.conf'
elif [ -r '/etc/nginx/nginx.conf' ]; then
log "Nginx config found: /etc/nginx/nginx.conf"
NGINX_CONF='/etc/nginx/nginx.conf'
elif [ -r '/usr/local/etc/nginx/nginx.conf' ]; then
log "Nginx config found: /usr/local/etc/nginx/nginx.conf"
NGINX_CONF='/usr/local/etc/nginx/nginx.conf'
else
log "Nginx configuration not found"
echo 'unknown'
return 1
fi
echo "$NGINX_CONF"
return 0
}
check_nginx() {
if [ ! -x "$NGINX_BIN" ]; then
echo 'unknown'
return 1
fi
# check if mod security v.2 enabled
TEST_MODSEC=`$NGINX_BIN -V 2>&1 | grep -iF "modsecurity"`
# test for mod security v.3
if [ -z "$TEST_MODSEC" ] ; then
TEST=`$NGINX_BIN -V 2>&1 | grep -iF "with-compat"`
if [ ! -z "$TEST" ] ; then
CONF=`nginx_conf`
TEST_MODSEC=`grep -iF "modsecurity" $CONF 2>/dev/null`
fi
fi
# get nginx version
NGINX_VERSION=`$NGINX_BIN -v 2>&1 | grep -F "nginx version" | sed -r -e 's/^nginx version: nginx\/(.*)/\1/'`
if [ -z "$NGINX_VERSION" ]; then
NGINX_VERSION='unknown'
log "Failed to get Nginx version"
echo "$NGINX_VERSION"
return 1
fi
log "Found Nginx version $NGINX_VERSION"
if [ -z "$TEST_MODSEC" ] ; then
log "Mod Security NOT supported in this version of Nginx"
echo "$NGINX_VERSION"
return 1
else
log "Mod Security supported"
echo "$NGINX_VERSION"
return 0
fi
}
check_modsec_family() {
# default version is '2'
if [ ! -x "$NGINX_BIN" -a x"$OPEN_LITESPEED" == x"NO" ]; then
echo '2'
return 1
fi
# OpenLitespeed support modsec 3
if [ x"$OPEN_LITESPEED" == x"YES" ] ; then
echo "3"
return 0
fi
# check if nginx compiled with dynamic modules support (which introduced in ver 3)
TEST_MODSEC=`$NGINX_BIN -V 2>&1 | grep -iF "with-compat"`
if [ ! -z "$TEST_MODSEC" ] ; then
echo "3"
return 0
fi
# check if nginx compiled with modsec 2 support
TEST_MODSEC=`$NGINX_BIN -V 2>&1 | grep -iF "modsecurity"`
if [ ! -z "$TEST_MODSEC" ] ; then
echo "2"
return 0
fi
echo '2'
return 1
}
# check if apache httpd.conf contain
check_httpd_conf() {
# EA4 does not require this check
if check_ea4 ; then
return 0
fi
if [ -f $CPANEL_APACHE_CONF ]; then
TEST_CONFIG=`grep $CPANEL_MODSECFILE $CPANEL_APACHE_CONF`
if [ -z "$TEST_CONFIG" ]; then
${SHOW}_message "$CPANEL_MODSECFILE not found in $CPANEL_APACHE_CONF!\nPlease add the line\nInclude \"$CPANEL_MODSECCONF\"\ninto $CWAF_PLATFORM config file ($CPANEL_APACHE_CONF).\n"
fi
fi
}
# check package version over allowed list
supported_version() {
VER=$1
shift
for V in ${*}; do
if echo "$VER" | grep -q "^${V}"; then
return 0
fi
done
return 1
}
# compare version: which is more recent?
recent_version() {
echo -e "${1}\n${2}\n" | sort -n | tail -n1
}
# check for installed perl modules, return list of not found
check_perl_modules() {
MISSED=''
for M in ${*}; do
if ! $PERL_BIN -M${M} -le 1 2>/dev/null 1>&2; then
log "PERL module $M is NOT found"
MISSED="$MISSED $M"
fi
done
if [ -z "$MISSED" ]; then
return 0
fi
echo "$MISSED"
return 1
}
# check for perl binary
check_perl_bin() {
PERL_BIN=`which perl 2>/dev/null`
if [ -x "$PERL_BIN" ]; then
echo "$PERL_BIN"
return 0
elif [ -x "$CPANEL_PERL" ]; then
echo "$CPANEL_PERL"
return 0
else
echo "unknown"
return 1
fi
}
# check for centos version
check_centos() {
if [ -f /etc/redhat-release ]; then
OS_NAME=`cat /etc/redhat-release | sed -r "s/^(.*) release (.*)\.(.*)/\1/"`
OS_VERSION_MAGOR=`cat /etc/redhat-release | sed -r "s/^(.*) release ([0-9]+)\.(.*)/\2/"`
if [ x"$OS_NAME" == x"CentOS" -o x"$OS_NAME" == x"CentOS Linux" ]; then
echo "$OS_VERSION_MAGOR"
return 0
fi
fi
echo "0"
return 1
}
########################################################
# FUNCTIONS
########################################################
sudo_add() {
local SUDO_USER=$1
# check CentOS 5
if [ -f /etc/redhat-release ]; then
OS_VERSION_MAGOR=`check_centos`
LINE_EXIST=`cat /etc/sudoers | grep '/etc/sudoers.d' 2>/dev/null`
# add /etc/sudoers.d for CentOS 5
if [ x"$OS_VERSION_MAGOR" == x"5" -a -z "$LINE_EXIST" ]; then
if [ ! -d "/etc/sudoers.d" ]; then
mkdir -p /etc/sudoers.d
chmod 750 /etc/sudoers.d
fi
echo -ne "\n## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)\n" >> /etc/sudoers
echo "#includedir /etc/sudoers.d" >> /etc/sudoers
fi
fi
# sudoers file creation
echo "Defaults:root !requiretty" > $CWAF_SUDOERS_FILE 2>&1 | log2
echo "Defaults:$SUDO_USER !requiretty" >> $CWAF_SUDOERS_FILE 2>&1 | log2
echo "$SUDO_USER ALL=(ALL) NOPASSWD: $CWAF_INSTALL_PATH/scripts/cwaf-wrapper.pl" >> $CWAF_SUDOERS_FILE 2>&1 | log2
# add nginx binary to sudoers
if [ x"$CWAF_PLATFORM" == x"Nginx" ]; then
echo "$SUDO_USER ALL=(ALL) NOPASSWD: $NGINX_BIN" >> $CWAF_SUDOERS_FILE 2>&1 | log2
fi
chmod 440 $CWAF_SUDOERS_FILE 2>&1 | log2
}
suid_prepare() {
local SUID_USER=$1
local GCC_BIN=$(which gcc)
if [ ! -x "$GCC_BIN" ]; then
${SHOW}_error "Not found GCC compiler, exiting"
exit 1
fi
sedi "s=%SUID_USER%=$SUID_USER=g $CWAF_INSTALL_PATH/scripts/suid.c"
sedi "s=%PERL_BIN%=$PERL_BIN=g $CWAF_INSTALL_PATH/scripts/suid.c"
sedi "s=%WRAPPER_BIN%=$CWAF_INSTALL_PATH/$CWAF_WRAPPER_BIN=g $CWAF_INSTALL_PATH/scripts/suid.c"
$GCC_BIN -o "$CWAF_INSTALL_PATH/scripts/suid" $CWAF_INSTALL_PATH/scripts/suid.c
chown root:$SUID_USER "$CWAF_INSTALL_PATH/scripts/suid"
chmod 4111 "$CWAF_INSTALL_PATH/scripts/suid"
rm -f "$CWAF_SUDOERS_FILE" 2>/dev/null 1>&2
}
# do necessary nginx setup
prepare_nginx() {
# prepare included conf file for nginx
sedi "s=rules/\*.conf=rules/rules.conf.main=g $CWAF_INSTALL_PATH/etc/cwaf.conf"
# process for non update mode
if [ x"$UPDATE" != x"yes" ]; then
### Nginx support operations
log "Preparing Nginx configuration"
if [ x"$INSTALL_MODE" == x"directadmin" ]; then
# nginx for directadmin
mkdir -p /var/log/nginx/modsec_audit
chmod 1733 /var/log/nginx/modsec_audit
mkdir -p "$CWAF_INSTALL_PATH/conf"
cp -fva "$DA_NGINX_MSCONF" "$CWAF_INSTALL_PATH/$DA_PLUGIN_MSCONF" 2>&1 | log2
if [ ! -d /etc/modsecurity.d ]; then
mkdir -p /etc/modsecurity.d
fi
rm -f /etc/modsecurity.d/*
echo "IncludeOptional $CWAF_INSTALL_PATH/etc/cwaf.conf" > "/etc/modsecurity.d/comodo_rules.conf.main" 2>&1 | log2
else
# creating necessary directories
log "mkdir -p $CWAF_INSTALL_PATH/nginx"
if ! mkdir -p "$CWAF_INSTALL_PATH/nginx" 2>/dev/null; then
log "Failed"
${SHOW}_error "Failed to create directory '$CWAF_INSTALL_PATH/nginx'!"
exit 1
fi
log "mkdir -p $CWAF_LOG_DIR/nginx"
if ! mkdir -p "$CWAF_LOG_DIR/nginx" 2>/dev/null; then
log "Failed"
${SHOW}_error "Failed to create directory '$CWAF_LOG_DIR/nginx'!"
exit 1
fi
# copy ModSec config for Nginx
cp -fva "$CWAF_INSTALL_PATH/etc/modsec2_nginx.conf" "$CWAF_INSTALL_PATH/nginx/modsec2_nginx.conf" 2>&1 | log2
# change ModSec config for Nginx
NGINX_CONF=`nginx_conf`
if [ x"$NGINX_CONF" == x"unknown" ]; then
log "Nginx config not found automatically. Please add the following lines into your Nginx config file for 'location /' scope:"
log "For ModSecurity 2.x:"
log "ModSecurityEnabled on;"
log "ModSecurityConfig $CWAF_INSTALL_PATH/nginx/modsec2_nginx.conf;"
log "For ModSecurity 3.x:"
log "modsecurity on;"
log "modsecurity_rules_file $CWAF_INSTALL_PATH/nginx/modsec2_nginx.conf;"
${SHOW}_message "Attention!\nNginx configuration file is not found automatically.\nPlease place the following lines to your Nginx config file:\nFor ModSecurity 2.x:\nModSecurityEnabled on;\nModSecurityConfig $CWAF_INSTALL_PATH/nginx/modsec2_nginx.conf;\nFor ModSecurity 3.x:\nmodsecurity on;\nmodsecurity_rules_file $CWAF_INSTALL_PATH/nginx/modsec2_nginx.conf;"
else
log "Preparing Mod Security config for Nginx: $NGINX_CONF"
"$CWAF_INSTALL_PATH/$CWAF_WRAPPER_BIN" modify_nginx_conf $NGINX_CONF $MODSEC_FAMILY 2>&1 | log2
sedi "s%^web_config=.*%web_config=$NGINX_CONF%g $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF"
fi
fi
fi
}
# prepare path to config for mod_security
modsec_conf_path() {
if [ x"$CWAF_PLATFORM" == x"Nginx" ]; then
# this is nginx + directadmin
if [ x"$INSTALL_MODE" == x"directadmin" ]; then
echo "$CWAF_INSTALL_PATH/$DA_PLUGIN_MSCONF"
return 1
# this is pure nginx
else
echo "$CWAF_INSTALL_PATH/nginx/modsec2_nginx.conf"
return 1
fi
elif [ x"$INSTALL_MODE" == x"cpanel" ]; then
echo "$CPANEL_MODSECCONF"
return 1
elif [ x"$INSTALL_MODE" == x"plesk" ]; then
echo "$PLESK_HTTPD_INCLUDE_D/$PLESK_MODSECFILE"
return 1
elif [ x"$INSTALL_MODE" == x"webmin" ]; then
# fix for apache2 Debian
if [ -d '/etc/apache2/conf.d' ]; then
WM_MODSECCONF="/etc/apache2/conf.d/$WEBMIN_MODSECFILE"
elif [ -d '/etc/apache2/conf-enabled' ]; then
WM_MODSECCONF="/etc/apache2/conf-enabled/$WEBMIN_MODSECFILE"
else
WM_MODSECCONF="$WEBMIN_APACHE_CONFDIR/$WEBMIN_MODSECFILE"
fi
echo "$WM_MODSECCONF"
return 1
elif [ x"$INSTALL_MODE" == x"directadmin" ]; then
# this is directadmin + apache
echo "$CWAF_INSTALL_PATH/$DA_PLUGIN_MSCONF"
return 1
elif [ x"$INSTALL_MODE" == x"standalone" ]; then
# this is standalone mode
echo "$CWAF_INSTALL_PATH/$STANDALONE_MSCONF"
return 1
fi
}
# sed wrapper for various system
sedi() {
if [ $(uname) == 'FreeBSD' ]; then
sed -i '' $1
else
sed -i $1
fi
}
########################################################
# MAIN PART
########################################################
log 'Starting the installation'
# show greeting
${SHOW}_message "Greetings!\nThis is a Comodo WAF Installation script.\nIf you encounter any errors during the installation,\nyou may examine log file $INSTALL_LOGFILE for more info." || exit 1
collect_stats "CWAF Version $CWAF_VERSION installed at `date`"
# check for apache and its version
log "----------------Checking Apache-----------------------"
APACHECTL_BIN=`which apachectl 2>/dev/null`
APACHE2CTL_BIN=`which apache2ctl 2>/dev/null`
if [ -x "$APACHE2CTL_BIN" ]; then
APACHECTL_BIN="$APACHE2CTL_BIN"
fi
if [ -x "$APACHECTL_BIN" ]; then
APACHECTL_BIN="$APACHECTL_BIN"
fi
log "Found APACHE2CTL '$APACHECTL_BIN'"
APACHE_VERSION=`check_apache`
if [ $? -ne 0 ]; then
${SHOW}_message "No working apache installation found"
elif ! supported_version $APACHE_VERSION $APACHE_SUPPORTED_VERSIONS ; then
${SHOW}_message "Installed apache version $APACHE_VERSION is NOT supported"
fi
# check for modsecurity and its version
MODSEC_VERSION=`check_modsec`
if [ $? -ne 0 ]; then
${SHOW}_message "No installed ModSecurity for Apache found"
elif ! supported_version $MODSEC_VERSION $MODSEC_SUPPORTED_VERSIONS ; then
${SHOW}_message "Warning: installed mod_security version $MODSEC_VERSION is NOT fully tested"
fi
# check for LiteSpeed
log "---------------Checking LiteSpeed---------------------"
OPEN_LITESPEED=`is_open_ls`
LITESPEED_VERSION=`check_litespeed`
if [ $? -ne 0 ]; then
${SHOW}_message "Not found LiteSpeed web server with mod_security enabled"
LITESPEED_MODSEC='unknown'
fi
# check for Nginx
log "-----------------Checking Nginx-----------------------"
NGINX_BIN=`nginx_binary`
NGINX_VERSION=`check_nginx`
MODSEC_FAMILY=`check_modsec_family`
if [ $? -ne 0 ]; then
${SHOW}_message "Not found Nginx web server with mod_security enabled"
NGINX_MODSEC='unknown'
fi
log "------------------------------------------------------"
# check prerequisites and exit
if [ x"$APACHE_VERSION" == x"unknown" ] && [ x"$LITESPEED_VERSION" == x"unknown" ] && [ x"$NGINX_VERSION" == x"unknown" ]; then
${SHOW}_error "Not found suitable web server, exiting"
exit 1
fi
#if [ x"$BATCH_MODE" == x"no" ]; then
if [ x"$MODSEC_VERSION" == x"unknown" ] && [ x"$LITESPEED_MODSEC" == x"unknown" ] && [ x"$NGINX_MODSEC" == x"unknown" ]; then
${SHOW}_error "Not found mod_security, exiting"
exit 1
fi
#fi
collect_stats "Found Apache version $APACHE_VERSION"
collect_stats "Found Apache's ModSecurity version $MODSEC_VERSION"
if [ x"$LITESPEED_VERSION" != x"unknown" ]; then
collect_stats "Found LiteSpeed version $LITESPEED_VERSION"
if [ x"$LITESPEED_MODSEC" != x"unknown" ]; then
collect_stats "LiteSpeed supports ModSecurity"
else
collect_stats "LiteSpeed not supports ModSecurity"
fi
fi
if [ x"$NGINX_VERSION" != x"unknown" ]; then
collect_stats "Found Nginx version $NGINX_VERSION"
if [ x"$NGINX_MODSEC" != x"unknown" ]; then
collect_stats "Nginx supports ModSecurity"
else
collect_stats "Nginx not supports ModSecurity"
fi
fi
if [ x"$UPDATE" == x"no" ]; then
if [ x"$MODSEC_VERSION" != x"unknown" ] && [ x"$LITESPEED_MODSEC" == x"unknown" ] && [ x"$NGINX_MODSEC" == x"unknown" ]; then
CWAF_PLATFORM="Apache"
log "No suitable LiteSpeed/Nginx web servers found."
log "Assigning WEB Platform: $CWAF_PLATFORM"
fi
if [ x"$MODSEC_VERSION" == x"unknown" ] && [ x"$LITESPEED_MODSEC" != x"unknown" ] && [ x"$NGINX_MODSEC" == x"unknown" ]; then
CWAF_PLATFORM="LiteSpeed"
log "No suitable Apache/nginx web servers found. Assigning WEB Platform: $CWAF_PLATFORM"
log "Assigning WEB Platform: $CWAF_PLATFORM"
fi
if [ x"$MODSEC_VERSION" == x"unknown" ] && [ x"$LITESPEED_MODSEC" == x"unknown" ] && [ x"$NGINX_MODSEC" != x"unknown" ]; then
CWAF_PLATFORM="Nginx"
log "No suitable Apache/LiteSpeed web servers found. Assigning WEB Platform: $CWAF_PLATFORM"
log "Assigning WEB Platform: $CWAF_PLATFORM"
fi
fi
# check for local perl (FreeBSD)
PERL_BIN=`check_perl_bin`
if [ $? -ne 0 ]; then
${SHOW}_error "Perl binary not found"
exit 1
fi
# check for installation mode: cpanel, plesk, directadmin, standalone or auto
if [ x"$INSTALL_MODE" != x"standalone" ]; then
CPANEL_VERSION=`check_cpanel`
if [ $? -ne 0 ]; then
PLESK_VERSION=`check_plesk`
if [ $? -ne 0 ]; then
DA_VERSION=`check_directadmin`
if [ $? -ne 0 ]; then
WEBMIN_VERSION=`check_webmin`
if [ $? -ne 0 ]; then
if [ x"$UPDATE" == x"yes" ]; then
${SHOW}_error "No web host management panel found, exiting"
exit 1
fi
else
if [ x"$UPDATE" == x"no" ]; then
${SHOW}_yesno "Found Webmin version $WEBMIN_VERSION, continue installation?" || exit 1
else
${SHOW}_message "Found Webmin version $WEBMIN_VERSION"
fi
INSTALL_MODE='webmin'
CWAF_INSTALL_PATH="$CWAF_WEBMIN_PATH"
collect_stats "Found Webmin version $WEBMIN_VERSION"
fi
else
if [ x"$UPDATE" == x"no" ]; then
${SHOW}_yesno "Found DirectAdmin version $DA_VERSION, continue installation?" || exit 1
else
${SHOW}_message "Found DirectAdmin version $DA_VERSION"
fi
INSTALL_MODE='directadmin'
CWAF_INSTALL_PATH="$CWAF_DA_PATH"
collect_stats "Found DirectAdmin version $DA_VERSION"
fi
else
if [ x"$UPDATE" == x"no" ]; then
${SHOW}_yesno "Found Plesk version $PLESK_VERSION, continue installation?" || exit 1
else
${SHOW}_message "Found Plesk version $PLESK_VERSION"
fi
INSTALL_MODE='plesk'
CWAF_INSTALL_PATH="$CWAF_PLESK_PATH"
collect_stats "Found Plesk version $PLESK_VERSION"
fi
else
if [ x"$UPDATE" == x"no" ]; then
${SHOW}_yesno "Found cPanel version $CPANEL_VERSION, continue installation?" || exit 1
else
${SHOW}_message "Found cPanel version $CPANEL_VERSION"
fi
INSTALL_MODE='cpanel'
CWAF_INSTALL_PATH="$CWAF_CPANEL_PATH"
if [ -x $CPANEL_PERL ]; then
PERL_BIN="$CPANEL_PERL"
fi
if [ -x $CPANEL_CPAN ]; then
CPAN_BIN="$CPANEL_CPAN"
fi
collect_stats "Found cPanel version $CPANEL_VERSION"
fi
fi
# standalone install confirmation and path
if [ x"$INSTALL_MODE" == x"standalone" ]; then
# fresh install in standalone mode
if [ x"$UPDATE" == x"no" ]; then
${SHOW}_yesno "No web host management panel found, continue in 'standalone' mode?" || exit 1
# batch mode fix
if [ x"$BATCH_MODE" != x"yes" ]; then
CWAF_INSTALL_PATH="$CWAF_STANDALONE_PATH"
fi
fi
# update in standalone mode
if [ x"$UPDATE" == x"yes" ]; then
CWAF_INSTALL_PATH=`get_standalone_path`
${SHOW}_message "CWAF installed at: $CWAF_INSTALL_PATH"
# exit if cwaf dir does not exist (in update mode)
if [ ! -d "$CWAF_INSTALL_PATH" ]; then
log "CWAF directory not found, update failed"
${SHOW}_error "CWAF directory not found, update failed"
exit 1
fi
fi
fi
# check required prerequisites before install
# check sudo
if [ x"$INSTALL_MODE" == x"plesk" ] || [ x"$INSTALL_MODE" == x"directadmin" ]; then
SUDO_BIN=`which sudo`
if [ ! -x "$SUDO_BIN" ]; then
${SHOW}_error "Not found SUDO utility.\nSUDO required for plugin.\nPlease setup it manually, then rerun this installation."
exit 1
fi
if [ ! -d "$CWAF_SUDOERS_PATH" ]; then
if [ -d "/usr/local/etc/sudoers.d" ]; then
export CWAF_SUDOERS_PATH="/usr/local/etc/sudoers.d"
export CWAF_SUDOERS_FILE="$CWAF_SUDOERS_PATH/cwaf"
else
# check if this is CentOS 5 for which SUDO directory created in sudo_add.
OS_VERSION_MAGOR=`check_centos`
if [ x"$OS_VERSION_MAGOR" == x"5" ]; then
log "CentOS 5 found, SUDO dir will be created..."
else
${SHOW}_error "Not found SUDO directory $CWAF_SUDOERS_PATH.\nPlease fix this manually, then rerun this installation."
exit 1
fi
fi
fi
fi
# determine web platform for update mode
if [ x"$UPDATE" == x"yes" ]; then
CWAF_PLATFORM=`get_platform`
log "Selected WEB Platform: $CWAF_PLATFORM"
fi
# perl and cpan may be redefined
log "Using PERL $PERL_BIN"
log "Using CPAN $CPAN_BIN"
# check required perl modules and install if needed
if [ x"$INSTALL_MODE" == x"cpanel" ]; then
PERL_REQUIRED_MODULES=$(echo "$PERL_REQUIRED_MODULES $PERL_REQUIRED_MODULES_CPANEL")
elif [ x"$INSTALL_MODE" == x"plesk" ]; then
PERL_REQUIRED_MODULES=$(echo "$PERL_REQUIRED_MODULES $PERL_REQUIRED_MODULES_PLESK")
elif [ x"$INSTALL_MODE" == x"webmin" ]; then
PERL_REQUIRED_MODULES=$(echo "$PERL_REQUIRED_MODULES $PERL_REQUIRED_MODULES_WEBMIN")
elif [ x"$INSTALL_MODE" == x"directadmin" ]; then
PERL_REQUIRED_MODULES=$(echo "$PERL_REQUIRED_MODULES $PERL_REQUIRED_MODULES_DIRECTADMIN")
elif [ x"$INSTALL_MODE" == x"standalone" ]; then
PERL_REQUIRED_MODULES=$(echo "$PERL_REQUIRED_MODULES $PERL_REQUIRED_MODULES_STANDALONE")
fi
PERL_MISSED_MODS=`check_perl_modules $PERL_REQUIRED_MODULES`
if [ -n "$PERL_MISSED_MODS" ]; then
if [ x"$UPDATE" == x"yes" ]; then
${SHOW}_error "Some required perl modules are missed, exiting"
exit 1
fi
${SHOW}_yesno "Some required perl modules are missed. Install them? This can take a while."
if [ $? -ne 0 ]; then
${SHOW}_info "Please install perl modules $PERL_MISSED_MODS manually and run installation script again"
exit 1
fi
if ! perl_install_missed $PERL_MISSED_MODS; then
${SHOW}_error "CPAN is not configured!\nPlease run\n$CPAN_BIN\nand configure it manually, then rerun this installation."
exit 1
fi
fi
# set web user if required
if [ x"$INSTALL_MODE" == x"plesk" ]; then
WEB_USER=$PLESK_USER
elif [ x"$INSTALL_MODE" == x"directadmin" ]; then
WEB_USER=$DA_USER
elif [ x"$INSTALL_MODE" == x"standalone" ]; then
WEB_USER=$STANDALONE_USER
else
WEB_USER='root'
fi
# ask some questinos in non-update mode
if [ x"$UPDATE" == x"no" ]; then
# count available web platforms
PLATFORM_COUNT=0
if [ x"$MODSEC_VERSION" != x"unknown" ]; then
PLATFORM_COUNT=$((PLATFORM_COUNT+1))
fi
if [ x"$LITESPEED_MODSEC" != x"unknown" ]; then
PLATFORM_COUNT=$((PLATFORM_COUNT+1))
fi
if [ x"$NGINX_MODSEC" != x"unknown" ]; then
PLATFORM_COUNT=$((PLATFORM_COUNT+1))
fi
# ask for Web platform if several present
if [ "$PLATFORM_COUNT" -gt 1 ]; then
# repeat until break or correct platform selected
while true; do
CWAF_PLATFORM=`${SHOW}_platform " Please select your WEB platform"` || exit 1
if [ -z "${CWAF_PLATFORM}" ]; then
${SHOW}_error "WEB platform is not selected";
exit 1
fi
if [ x`is_platform_supported "$CWAF_PLATFORM"` == x"yes" ]; then
break
else
${SHOW}_message "Selected WEB platform $CWAF_PLATFORM is not supported";
continue
fi
done
log "Selected WEB Platform: $CWAF_PLATFORM"
fi
# prompt for CWAF login
while true; do
CWAF_LOGIN=`${SHOW}_login "Enter CWAF login" "$CWAF_LOGIN"` || exit 1
if [ -z "$CWAF_LOGIN" ]; then
${SHOW}_error "Login name may not be empty"
continue
fi
break
done
# prompt for CWAF password
while true; do
P1=`${SHOW}_pass "Enter password for '$CWAF_LOGIN' (will not be shown)"` || exit 1
if [ -z "$P1" ]; then
${SHOW}_error "Password may not be empty"
continue
fi
P2=`${SHOW}_pass "Confirm password for '$CWAF_LOGIN' (will not be shown)"` || exit 1
if [ x"$P1" != x"$P2" ]; then
${SHOW}_error "Passwords do not match"
continue
fi
#CWAF_PASSWORD="$P1"
CWAF_PASSWORD=$(encrypt_password "$P1")
break
done
# standalone: ask for target dir
if [ x"$INSTALL_MODE" == x"standalone" ] && [ x"$BATCH_MODE" != x"yes" ]; then # STANDALONE NON BATCH MODE
# ask for install dir
CPATH="$CWAF_INSTALL_PATH"
while true; do
CPATH=`${SHOW}_input "Enter absolute CWAF installation path prefix (/cwaf will be appended)" "$CPATH"` || exit 1
if [ -z "$CPATH" ]; then
${SHOW}_error "Install path prefix may not be empty"
continue
fi
if echo "$CPATH" | egrep -vq '^/[a-zA-Z0-9./_+-]+$'; then
${SHOW}_error "Invalid path specified ($CPATH)"
continue
fi
CWAF_INSTALL_PATH=`echo "$CPATH/cwaf" | sed -r 's=/+=/=g'`
if [ -d "$CWAF_INSTALL_PATH" ]; then
${SHOW}_yesno "Install into '$CWAF_INSTALL_PATH' (WARNING: its content will be overwritten!) ?" || continue
else
${SHOW}_yesno "Install into '$CWAF_INSTALL_PATH' ?" || continue
fi
break
done
fi
# create a dir if not exists
if [ ! -d "$CWAF_INSTALL_PATH" ]; then
log "mkdir -p $CWAF_INSTALL_PATH"
if ! mkdir -p "$CWAF_INSTALL_PATH" 2>/dev/null; then
log "Failed"
${SHOW}_error "Failed to create directory '$CWAF_INSTALL_PATH'!"
exit 1
fi
fi
fi # non-update mode
collect_stats "WEB Platform: $CWAF_PLATFORM"
if [ x"$INSTALL_MODE" == x"plesk" ]; then
# load Plesk conf parameters
get_plesk_params $PLESK_CONF $PLESK_HTTPD_CONF_REQUIRED
fi
# check for Debian config style
if [ -d "/var/log/apache2" ];then
APACHE_LOG_DIR='/var/log/apache2'
fi
if [ x"$INSTALL_MODE" == x"webmin" ]; then
if [ -d "/etc/apache2/conf.d" ];then
WEBMIN_MODSECCONF="/etc/apache2/conf.d/$WEBMIN_MODSECFILE"
elif [ -d "/etc/apache2/conf-enabled" ];then
WEBMIN_MODSECCONF="/etc/apache2/conf-enabled/$WEBMIN_MODSECFILE"
fi
fi
CWAF_MODSEC_PATH=`modsec_conf_path`
# subst data in configs and some files
log "Preparing files ..."
for F in $SUBST_FILES; do
echo "Preparing file $F"
sedi "s=%CWAF_VERSION%=$CWAF_VERSION=g $F"
sedi "s=%CWAF_PATH%=$CWAF_INSTALL_PATH=g $F"
sedi "s=%CWAF_LOGIN%=$CWAF_LOGIN=g $F"
sedi "s/%CWAF_PASSWD%/$CWAF_PASSWORD/g $F"
sedi "s=%CWAF_PLATFORM%=$CWAF_PLATFORM=g $F"
sedi "s=%MODSEC_FAMILY%=$MODSEC_FAMILY=g $F"
sedi "s=%CWAF_LOG_DIR%=$CWAF_LOG_DIR=g $F"
sedi "s=%CWAF_MODSEC_PATH%=$CWAF_MODSEC_PATH=g $F"
sedi "s=%APACHE_LOGDIR%=$APACHE_LOG_DIR=g $F"
sedi "s=%WEB_USER%=$WEB_USER=g $F"
if [ x"$INSTALL_MODE" != x"cpanel" ]; then
sedi "s=%CWAF_CGIDIR%=$CWAF_INSTALL_PATH/web=g $F"
else
sedi "s=%CWAF_CGIDIR%=$CPANEL_CWAF_CGIDIR=g $F"
fi
done 2>&1 | log2
# fix for update cpanel to 11.86
if [ x"$INSTALL_MODE" == x"cpanel" ]; then
if [ -e "/usr/local/cpanel/3rdparty/perl/514/lib64/perl5/cpanel_lib/x86_64-linux-64int/Comodo" ]; then
rm -rf "/usr/local/cpanel/3rdparty/perl/514/lib64/perl5/cpanel_lib/x86_64-linux-64int/Comodo"
fi
# fix for update perl from 5.14 to 5.22 on cpanel 56.0
if [ -e "/opt/cpanel/perl5/514/site_lib/Comodo" -a -e "/opt/cpanel/perl5/522" ]; then
rm -rf "/opt/cpanel/perl5/514/site_lib/Comodo"
rm -rf "/opt/cpanel/perl5/514/site_lib/x86_64-linux-64int/auto/Comodo"
fi
fi
# install our own perl modules
#log "Installing Comodo perl modules"
#(cd "modules/CPAN"; $PERL_BIN Makefile.PL 2>&1; make install 2>&1) | log2
log "Uninstalling previous Comodo perl modules"
(cd "scripts"; ./uninstall_perl_mods.pl --module > /dev/null 2>&1)
# fix perms
log "Fixing perms"
chmod -v 0600 "etc/main.conf" 2>&1 | log2
chmod -v +x web/cpanel/*.cgi scripts/* 2>&1 | log2
chmod -v 0100 "$CWAF_WRAPPER_BIN" 2>&1 | log2
# preserve main config in update mode
if [ x"$UPDATE" == x"yes" ]; then
cp -fva "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF" "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF-bak" 2>&1 | log2
cp -fva "$CWAF_INSTALL_PATH/$CWAF_USER_CONF" "$CWAF_INSTALL_PATH/$CWAF_USER_CONF-bak" 2>&1 | log2
cp -fva "$CWAF_INSTALL_PATH/$CWAF_GUI_CONF" "$CWAF_INSTALL_PATH/$CWAF_GUI_CONF-bak" > /dev/null 2>&1
fi
# backup some files
if [ x"$INSTALL_MODE" == x"cpanel" ]; then
backup_files "$CWAF_INSTALL_PATH" "$CPANEL_BACKUP_FILES"
elif [ x"$INSTALL_MODE" == x"plesk" ]; then
backup_files "$CWAF_INSTALL_PATH" "$PLESK_BACKUP_FILES"
elif [ x"$INSTALL_MODE" == x"standalone" ]; then
backup_files "$CWAF_INSTALL_PATH" "$STANDALONE_BACKUP_FILES"
fi
# some cleanups
log "Cleaning up some old files..."
if [ -d /usr/local/cpanel/whostmgr/docroot/cgi/cwaf ]; then
rm -rf /usr/local/cpanel/whostmgr/docroot/cgi/cwaf/* 2>&1 | log2
fi
# copy everything into install dir
log "Copying files to $CWAF_INSTALL_PATH"
cp -afR * "$CWAF_INSTALL_PATH" 2>&1 | log2
# restore main config file
if [ x"$UPDATE" == x"yes" ]; then
cp -fva "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF-bak" "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF" 2>&1 | log2
cp -fva "$CWAF_INSTALL_PATH/$CWAF_USER_CONF-bak" "$CWAF_INSTALL_PATH/$CWAF_USER_CONF" 2>&1 | log2
cp -fva "$CWAF_INSTALL_PATH/$CWAF_GUI_CONF-bak" "$CWAF_INSTALL_PATH/$CWAF_GUI_CONF" > /dev/null 2>&1
# apply changes if needed
if [ -s "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF_SKEL" ]; then
log "Updating main config file"
while read L; do
# get substring from begin of string to '=' sign
#TEST=`expr match "$L" '\(.*=\)'` - changed for FreeBSD
TEST=`expr "$L" : '\(.*=\)'`
if ! grep -q "^$TEST" "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF"; then
echo -e "\n$L" >> "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF"
fi
done < "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF_SKEL"
rm -f "$CWAF_INSTALL_PATH/$CWAF_MAIN_CONF_SKEL"
fi
# encrypt password in update mode
CWAF_PLAINPASSWORD=$(get_password)
if [ ! -z "$CWAF_PLAINPASSWORD" ]; then
CWAF_PASSWORD=$(decrypt_password "$CWAF_PLAINPASSWORD")
CWAF_ENCPASSWORD=$(encrypt_password "$CWAF_PASSWORD")
sedi "s/cwaf_passwd=\"$CWAF_PLAINPASSWORD\"/cwaf_passwd=\"$CWAF_ENCPASSWORD\"/g $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF"
CWAF_PASSWORD="$CWAF_ENCPASSWORD"
fi
else
# create first run file if not update
touch "$CWAF_INSTALL_PATH/$FIRSTRUN_FILE"
fi
# prepare some dirs and files
log "Preparing dirs"
if [ ! -e "$CWAF_INSTALL_PATH/rules" ]; then
ln -sv "$CWAF_INSTALL_PATH/tmp/EMPTY" "$CWAF_INSTALL_PATH/rules" 2>&1 | log2
fi
# create log dir
if [ ! -e "$CWAF_LOG_DIR" ]; then
mkdir -p "$CWAF_LOG_DIR" 2>&1 | log2
if [ x"$CWAF_PLATFORM" == x"Nginx" ]; then
mkdir -p "$CWAF_LOG_DIR/nginx" 2>&1 | log2
fi
fi
if [ ! -e "$CWAF_INSTALL_PATH/logs" ]; then
ln -svf "$CWAF_LOG_DIR" "$CWAF_INSTALL_PATH/logs" 2>&1 | log2
fi
# link CWAF etc folder to /etc/cwaf
if [ ! -d "$CWAF_ETC_DIR" ]; then
ln -svf "$CWAF_INSTALL_PATH/etc" "$CWAF_ETC_DIR" 2>&1 | log2
else
rm -vf "$CWAF_ETC_DIR" 2>&1 | log2
ln -svf "$CWAF_INSTALL_PATH/etc" "$CWAF_ETC_DIR" 2>&1 | log2
fi
# delete standalone files
if [ x"$INSTALL_MODE" != x"standalone" ]; then
rm -vf "$CWAF_INSTALL_PATH/$CWAF_GUI_CONF" > /dev/null 2>&1
rm -vf "$CWAF_INSTALL_PATH/scripts/standalone-gui.pl" > /dev/null 2>&1
fi
### Postinstall Block for each mode
if [ x"$INSTALL_MODE" == x"standalone" ]; then
# preparing modsec2.conf example
log "Preparing ModSecurity example config files"
mkdir -p "$CWAF_INSTALL_PATH/etc/examples"
sedi "s=%HTTPD_LOG_D%=logs=g $CWAF_INSTALL_PATH/etc/modsec2_plesk.conf"
mv -vf "$CWAF_INSTALL_PATH/etc/modsec2_cpanel.conf" "$CWAF_INSTALL_PATH/etc/examples/modsec2_cpanel-example.conf" 2>&1 | log2
mv -vf "$CWAF_INSTALL_PATH/etc/modsec2_plesk.conf" "$CWAF_INSTALL_PATH/etc/examples/modsec2-example.conf" 2>&1 | log2
if [ x"$CWAF_PLATFORM" != x"Nginx" ]; then
mv -vf "$CWAF_INSTALL_PATH/etc/modsec2_nginx.conf" "$CWAF_INSTALL_PATH/etc/examples/modsec2_nginx-example.conf" 2>&1 | log2
fi
mv -vf "$CWAF_INSTALL_PATH/etc/modsec2_da_ap.conf" "$CWAF_INSTALL_PATH/etc/examples/modsec2_da_ap-example.conf" 2>&1 | log2
mv -vf "$CWAF_INSTALL_PATH/etc/modsec2_da_nginx.conf" "$CWAF_INSTALL_PATH/etc/examples/modsec2_da_nginx-example.conf" 2>&1 | log2
mv -vf "$CWAF_INSTALL_PATH/etc/modsec2_webmin.conf" "$CWAF_INSTALL_PATH/etc/examples/modsec2_webmin-example.conf" 2>&1 | log2
# preparing modsecurity config
log "Setting Up ModSecurity config"
if [ x"$CWAF_PLATFORM" == x"Nginx" ]; then
prepare_nginx
fi
# preparing templates and js
sedi "s=\"cwaf\/=\"\/cwaf\/=g $CWAF_INSTALL_PATH/web/cwaf/tpl/index.html"
sedi "s=cwaf/img/exclude.png=/cwaf/img/exclude.png=g $CWAF_INSTALL_PATH/web/cwaf/js/cwaf_catalog.js"
# make link to cwaf common files
unlink "$CWAF_INSTALL_PATH/web/standalone/cwaf" > /dev/null 2>&1
ln -svf "$CWAF_INSTALL_PATH/web/cwaf" "$CWAF_INSTALL_PATH/web/standalone/cwaf" 2>&1 | log2
# non-update standalone: create default exclude list
if [ x"$UPDATE" != x"yes" ]; then
WEB_CONFIG=`${SHOW}_input "If you have non-standart Apache/nginx config path enter it here" "$WEB_CONFIG"` || exit 1
sedi "s/^web_config=.*/web_config=$WEB_CONFIG/g $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF"
# install standalone gui
if ${SHOW}_yesno "Do you want to use HTTP GUI to manage CWAF rules?"; then
#STANDALONE_GUI_IP=`${SHOW}_input "Enter IP Address where HTTP GUI will listen" "$STANDALONE_GUI_IP"` || exit 1
STANDALONE_GUI_PORT=`${SHOW}_input "Enter Port where HTTP GUI will listen on $STANDALONE_GUI_IP" "$STANDALONE_GUI_PORT"` || exit 1
STANDALONE_USER=`${SHOW}_input "Existing username which will be used to run HTTP GUI from" "$STANDALONE_USER"` || exit 1
check_user "$STANDALONE_USER"
if [ $? -ne 0 ]; then
${SHOW}_message "Warning! User $STANDALONE_USER not found! Please do not forget to add user after install."
log "Warning! User $STANDALONE_USER not found! Please do not forget to add user after install."
fi
log "Preparing Standalone HTTP GUI configuration"
sedi "s=%GUI_IP%=$STANDALONE_GUI_IP=g $CWAF_INSTALL_PATH/$CWAF_GUI_CONF"
sedi "s=%GUI_PORT%=$STANDALONE_GUI_PORT=g $CWAF_INSTALL_PATH/$CWAF_GUI_CONF"
sedi "s/^web_user=.*/web_user=$STANDALONE_USER/g $CWAF_INSTALL_PATH/etc/main.conf"
else
# remove scripts
rm -f "$CWAF_INSTALL_PATH/$CWAF_GUI_CONF" > /dev/null 2>&1
rm -f "$CWAF_INSTALL_PATH/scripts/standalone-gui.pl" > /dev/null 2>&1
fi
# install protection rules
install_rules
fi
# standalone gui mode
if [ -f "$CWAF_INSTALL_PATH/$CWAF_GUI_CONF" ]; then
# get user from config for update
if [ x"$UPDATE" == x"yes" ]; then
STANDALONE_USER=`grep '^web_user=' $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF | sed -r 's/^web_user=(.*)/\1/'`
# set default values for update mode
sedi "s=%GUI_IP%=$STANDALONE_GUI_IP=g $CWAF_INSTALL_PATH/$CWAF_GUI_CONF"
sedi "s=%GUI_PORT%=$STANDALONE_GUI_PORT=g $CWAF_INSTALL_PATH/$CWAF_GUI_CONF"
fi
# change owner for cwaf
chown -R $STANDALONE_USER "$CWAF_INSTALL_PATH" 2>&1 | log2
chown -R $STANDALONE_USER "$CWAF_LOG_DIR" 2>&1 | log2
# compile suid wrapper
suid_prepare "$STANDALONE_USER"
# set permissions for standalone GUI script
chmod -v 700 "$CWAF_INSTALL_PATH/scripts/standalone-gui.pl" 2>&1 | log2
chmod -v 600 "$CWAF_INSTALL_PATH/$CWAF_GUI_CONF" 2>&1 | log2
fi
if [ x"$CWAF_PLATFORM" == x"Nginx" ]; then
${SHOW}_message "Installation complete!\n To update ModSecurity ruleset run\n$CWAF_INSTALL_PATH/scripts/updater.pl\nRestart $CWAF_PLATFORM after that.\nYou may find useful utility $CWAF_INSTALL_PATH/scripts/cwaf-cli.pl\nAlso you may examine file\n$CWAF_INSTALL_PATH/$STATS_FILE\nfor some useful software information."
else
${SHOW}_message "Installation complete!\nPlease add the line:\n Include \"$CWAF_MODSEC_PATH\"\nto $CWAF_PLATFORM config file.\nTo update ModSecurity ruleset run\n $CWAF_INSTALL_PATH/scripts/updater.pl\nRestart $CWAF_PLATFORM after that.\nYou may find useful utility $CWAF_INSTALL_PATH/scripts/cwaf-cli.pl\nAlso you may examine file\n $CWAF_INSTALL_PATH/$STATS_FILE\nfor some useful software information."
fi
log "All Done!"
log "Exiting"
exit 0
elif [ x"$INSTALL_MODE" == x"cpanel" ]; then
# cpanel mode has some more work to do
# register in cpanel (version 11.38 and higher only)
log "Register Comodo WAF Cpanel Application"
RES=`recent_version $CPANEL_VERSION $CPANEL_LOWER_VERSION`
if [ x"$RES" == x"$CPANEL_VERSION" ]; then
sed -i '/^#ACLS/d' web/cpanel/cwaf_catalog.cgi
sed -i '/^#ACLS/d' web/cpanel/cwaf_main.cgi
sed -i '/^#ACLS/d' web/cpanel/addon_cwaf.cgi
sed -i '/^#WHMADDON/d' web/cpanel/addon_cwaf.cgi
if [ ! -d "$CPANEL_APPCONFIG_PATH" ]; then
mkdir -vp "$CPANEL_APPCONFIG_PATH" 2>&1 | log2
fi
cp -avf etc/addon_cwaf.conf "$CPANEL_APPCONFIG_PATH" 2>&1 | log2
log "Register Comodo WAF in Cpanel AppConfig"
$CPANEL_APPCONFIG "$CPANEL_APPCONFIG_PATH/addon_cwaf.conf" 2>&1 | log2
fi
# install files into whostmgr
log "Registering Comodo WAF in Host Manager"
cp -afR web/cpanel/* /usr/local/cpanel/whostmgr/docroot/cgi 2>&1 | log2
if [ ! -d /usr/local/cpanel/whostmgr/docroot/cgi/cwaf ]; then
mkdir /usr/local/cpanel/whostmgr/docroot/cgi/cwaf 2>&1 | log2
fi
cp -afR web/cwaf/* /usr/local/cpanel/whostmgr/docroot/cgi/cwaf 2>&1 | log2
cp -afR web/cwaf_sharedlib.pl /usr/local/cpanel/whostmgr/docroot/cgi/cwaf_sharedlib.pl 2>&1 | log2
if [ x"$CWAF_PLATFORM" != x"Nginx" ]; then
# prepare cpanel apache
if [ -d "$CPANEL_APACHE_CONFDIR" ];then
# do not replace modsec config in update mode
if [ x"$UPDATE" != x"yes" ]; then
if [ -r "$CPANEL_MODSECCONF" -a ! -r "$CPANEL_CWAFBACKUP_MODSECCONF" ]; then
log "Saving Original Mod_security configuration in $CPANEL_CWAFBACKUP_MODSECCONF"
cp -vf "$CPANEL_MODSECCONF" "$CPANEL_CWAFBACKUP_MODSECCONF" 2>&1 | log2
fi
log "Copy Comodo WAF Mod_security configuration to Apache HTTPD directory"
cp -vf "$CPANEL_MODSECSRC" "$CPANEL_MODSECCONF" 2>&1 | log2
else
if [ check_ea4 -a ! -e "$CPANEL_MODSECCONF" ]; then
log "Copy Comodo WAF Mod_security configuration to Apache (EasyApache 4)"
cp -vf "$CPANEL_MODSECSRC" "$CPANEL_MODSECCONF" 2>&1 | log2
sedi "s#cwaf_modsec_conf=/usr/local/apache/conf/modsec2.conf#cwaf_modsec_conf=$CPANEL_MODSECCONF#g $CWAF_INSTALL_PATH/$CWAF_MAIN_CONF"
fi
fi
else
log "Apache HTTPD configuration directory not found"
fi
# modify easyapache 3
if ! check_ea4 ; then
log "Installing EasyApache 3 CWAF scripts"
if [ -f /scripts/posteasyapache ]; then
if ! grep -q "CWAF_HOOK" /scripts/posteasyapache ; then
echo "$CWAF_INSTALL_PATH/scripts/EasyApache/posteasyapache #CWAF_HOOK" >> /scripts/posteasyapache
fi
else
echo -e "#!/bin/sh\n\n$CWAF_INSTALL_PATH/scripts/EasyApache/posteasyapache #CWAF_HOOK" > /scripts/posteasyapache
chmod +x /scripts/posteasyapache
fi
if [ -f /scripts/preeasyapache ]; then
if ! grep -q "CWAF_HOOK" /scripts/preeasyapache ; then
echo "$CWAF_INSTALL_PATH/scripts/EasyApache/preeasyapache #CWAF_HOOK" >> /scripts/preeasyapache
fi
else
echo -e "#!/bin/sh\n\n$CWAF_INSTALL_PATH/scripts/EasyApache/preeasyapache #CWAF_HOOK" > /scripts/preeasyapache
chmod +x /scripts/preeasyapache
fi
else
remove_ea3_hooks
fi
# check if config is valid for Apache/Litespeed
check_httpd_conf
else
# nginx cpanel setup
prepare_nginx
fi
# install protection rules
install_rules
# all done (cpanel mode)
log "All Done!"
${SHOW}_message "Installation complete!\nYou may examine log file\n$INSTALL_LOGFILE\nfor errors in case not everything went flawless.\nAlso you may examine file\n$CWAF_INSTALL_PATH/$STATS_FILE\nfor some useful software information."
exit 0
elif [ x"$INSTALL_MODE" == x"plesk" ]; then
# plesk mode has some more work to do
# register in plesk
log "Register Comodo WAF Plesk Extention"
cp -afR $CWAF_INSTALL_PATH/web/plesk/plugin/* $PLESK_PRODUCT_ROOT_D/admin 2>&1 | log2
$PLESK_PRODUCT_ROOT_D/bin/extension -r cwaf 2>&1 | log2
# change owner for cwaf
chown -R $PLESK_USER "$CWAF_INSTALL_PATH" 2>&1 | log2
chown -R $PLESK_USER "$CWAF_LOG_DIR" 2>&1 | log2
# make link to cwaf common files
ln -svf "$CWAF_INSTALL_PATH/web/cwaf" "$PLESK_PRODUCT_ROOT_D/admin/htdocs/modules/cwaf/cwaf" 2>&1 | log2
for F in $CWAF_INSTALL_PATH/web/cwaf/js/cwaf*.js; do
log "Preparing file $F"
sedi "s=cwaf_main.cgi=cwaf_main.php=g $F"
sedi "s=cwaf_catalog.cgi=cwaf_catalog.php=g $F"
done 2>&1 | log2
# compile suid wrapper
suid_prepare "$PLESK_USER"
# prepare Plesk config for Apache/Litespeed
if [ x"$CWAF_PLATFORM" != x"Nginx" ]; then
# change Plesk config during install only
if [ x"$UPDATE" != x"yes" ]; then
log "Setting Up ModSecurity config"
# fix for apache2 Debian
if [ -f "$PLESK_HTTPD_CONF_D/mods-enabled/security2.conf" -o -f "$PLESK_HTTPD_CONF_D/mods-enabled/security2.conf.cwaf_backup" ]; then
PLESK_SECURITY2_PATH="$PLESK_HTTPD_CONF_D/mods-enabled"
else
PLESK_SECURITY2_PATH=$PLESK_HTTPD_INCLUDE_D
fi
# prepare plesk apache
mv -vf $PLESK_SECURITY2_PATH/security2.conf $PLESK_SECURITY2_PATH/security2.conf.cwaf_backup 2>&1 | log2
sedi "s=%HTTPD_LOG_D%=$PLESK_HTTPD_LOG_D=g etc/modsec2_plesk.conf"
sedi "s=%CWAF_MODSEC_CONF%=$PLESK_HTTPD_INCLUDE_D/$PLESK_MODSECFILE=g etc/*.conf"
cp -avf etc/modsec2_plesk.conf $PLESK_HTTPD_INCLUDE_D/$PLESK_MODSECFILE | log2
chown $PLESK_USER $PLESK_HTTPD_INCLUDE_D/$PLESK_MODSECFILE | log2
# edit cwaf modsec file for Plesk with user defined parameters
reset_params $PLESK_SECURITY2_PATH/security2.conf.cwaf_backup $PLESK_HTTPD_INCLUDE_D/$PLESK_MODSECFILE $CWAF_MODSEC_PARAMS
reset_params $PLESK_HTTPD_CONF_D/plesk.conf.d/server.conf $PLESK_HTTPD_INCLUDE_D/$PLESK_MODSECFILE $CWAF_MODSEC_PARAMS
# borrow custom user config from standart Plesk plugin
if [ -f "$PLESK_HTTPD_CONF_D/plesk.conf.d/modsecurity.conf" ]; then
if [ "$( wc -c < "$PLESK_HTTPD_CONF_D/plesk.conf.d/modsecurity.conf" )" -gt 1 ]; then
echo -ne "\n# Custom directives from core Web Application Firewall module\n" >> "$CWAF_INSTALL_PATH/etc/httpd/custom_user.conf"
cat "$PLESK_HTTPD_CONF_D/plesk.conf.d/modsecurity.conf" >> "$CWAF_INSTALL_PATH/etc/httpd/custom_user.conf"
echo -ne "\n" >> "$CWAF_INSTALL_PATH/etc/httpd/custom_user.conf"
fi
fi
fi
else
# prepare Plesk config for Nginx
prepare_nginx
fi
# install protection rules
install_rules
# all done (plesk mode)
log "All Done!"
${SHOW}_message "Installation complete!\nYou may examine log file\n$INSTALL_LOGFILE\nfor errors in case not everything went flawless.\nAlso you may examine file\n$CWAF_INSTALL_PATH/$STATS_FILE\nfor some useful software information."
exit 0
elif [ x"$INSTALL_MODE" == x"webmin" ]; then
# webmin mode has some more work to do
WEBMIN_ROOT=$(cat $WEBMIN_CONF | grep "^root" | sed -r -e 's/^root=(.*)/\1/')
# prepare for the registering
# log "cd to $CWAF_INSTALL_PATH/web/webmin"
cd "$CWAF_INSTALL_PATH/web/webmin" && tar -zcf cwaf.wbm.tgz cwaf && cd - > /dev/null
# register in webmin (just copying)
log "Register Comodo WAF Webmin Plugin"
$WEBMIN_ROOT/install-module.pl $CWAF_INSTALL_PATH/web/webmin/cwaf.wbm.tgz 2>&1 | log2
# make link to cwaf common files
ln -svf "$CWAF_INSTALL_PATH/web/cwaf" "$WEBMIN_ROOT/cwaf/cwaf" 2>&1 | log2
mv -vf "$CWAF_INSTALL_PATH/web/cwaf/tpl/index_webmin.html" "$CWAF_INSTALL_PATH/web/cwaf/tpl/index.html" 2>&1 | log2
# prepare Webmin config for Apache/Litespeed
if [ x"$CWAF_PLATFORM" != x"Nginx" ]; then
# change Webmin config during install only
if [ x"$UPDATE" != x"yes" ]; then
# fix for apache2 Debian
if [ -f "/etc/apache2/mods-enabled/mod-security.conf" ]; then
mv -vf "/etc/apache2/mods-enabled/mod-security.conf" "/etc/apache2/mods-enabled/security2.conf.cwaf_backup" 2>&1 | log2
fi
# fix for apache2 Ubuntu
if [ -f "/etc/apache2/mods-enabled/security2.conf" ]; then
mv -vf "/etc/apache2/mods-enabled/security2.conf" "/etc/apache2/mods-enabled/security2.conf.cwaf_backup" 2>&1 | log2
fi
log "Copy Comodo WAF Mod_security configuration to Apache HTTPD directory"
cp -vf etc/modsec2_webmin.conf "$WEBMIN_MODSECCONF" 2>&1 | log2
fi
else
# prepare Webmin config for Nginx
prepare_nginx
fi
# install protection rules
install_rules
# all done (webmin mode)
log "All Done!"
${SHOW}_message "Installation complete!\nYou may examine log file\n$INSTALL_LOGFILE\nfor errors in case not everything went flawless.\nAlso you may examine file\n$CWAF_INSTALL_PATH/$STATS_FILE\nfor some useful software information."
exit 0
elif [ x"$INSTALL_MODE" == x"directadmin" ]; then
# directadmin mode has some more work to do
log "Preparing DirectAdmin configuration"
# make dir and copy files if required
if [ ! -d "$DA_PLUGIN_DIR" ]; then
# plugin not installed, prepare directory
mkdir -pv "$DA_PLUGIN_DIR" 2>&1 | log2
else
# plugin installed, clear directory
rm -rf "$DA_PLUGIN_DIR/*" 2>&1 | log2
#mkdir -pv "$DA_PLUGIN_DIR" 2>&1 | log2
fi
log "Copy plugin content"
cp -aR web/directadmin/* "$DA_PLUGIN_DIR" 2>&1 | log2
# just copy CSS and JS
log "Copy Styles and JavaScript"
rm -rf "$DA_PLUGIN_DIR/images/" 2>&1 | log2
mkdir -pv "$DA_PLUGIN_DIR/images/" 2>&1 | log2
cp -afR web/cwaf/css/ "$DA_PLUGIN_DIR/images/css/" 2>&1 | log2
cp -afR web/cwaf/img/ "$DA_PLUGIN_DIR/images/img/" 2>&1 | log2
cp -afR web/cwaf/js/ "$DA_PLUGIN_DIR/images/js/" 2>&1 | log2
# copy plugin.conf and hooks
cp -afRv web/directadmin/plugin.conf "$DA_PLUGIN_DIR/plugin.conf" 2>&1 | log2
cp -afRv web/directadmin/hooks/admin_img.html "$DA_PLUGIN_DIR/hooks/admin_img.html" 2>&1 | log2
cp -afRv web/directadmin/hooks/admin_txt.html "$DA_PLUGIN_DIR/hooks/admin_txt.html" 2>&1 | log2
# modify file web/cwaf/tpl/index.html : replace '"cwaf/' to '"./images/'
sedi "s=\"cwaf\/=\"\.\/images\/=g $CWAF_INSTALL_PATH/web/cwaf/tpl/index.html"
# modify files web/cwaf/js/*: replace "cwaf_main.cgi" to "cwaf_main.raw", replace "cwaf_catalog.cgi" to "cwaf_catalog.raw"
for F in $DA_PLUGIN_DIR/images/js/cwaf*.js; do
log "Preparing file $F"
sedi "s=cwaf_main.cgi=cwaf_main.raw=g $F"
sedi "s=cwaf_catalog.cgi=cwaf_catalog.raw=g $F"
sedi "s=cwaf/img/exclude.png=./images/img/exclude.png=g $F"
done 2>&1 | log2
chown -R diradmin "$DA_PLUGIN_DIR" 2>/dev/null
# adding user if required
usergroup_add "$DA_USER" "$DA_USER"
# compile suid wrapper
suid_prepare "$DA_USER"
if [ x"$CWAF_PLATFORM" != x"Nginx" ]; then
# prepare directadmin apache
# change directadmin config during install only
if [ x"$UPDATE" != x"yes" ]; then
log "Setting Up ModSecurity config"
mkdir -p "$CWAF_INSTALL_PATH/conf"
if [ x"$OPEN_LITESPEED" == x"NO" ]; then
# copy apache/litespeed modsec conf
cp -fva "$DA_APACHE_MSCONF" "$CWAF_INSTALL_PATH/$DA_PLUGIN_MSCONF" 2>&1 | log2
else
# copy open litespeed modsec conf
cp -fva "$DA_OPENLS_MSCONF" "$CWAF_INSTALL_PATH/$DA_PLUGIN_MSCONF" 2>&1 | log2
fi
if [ ! -d /etc/modsecurity.d ]; then
mkdir -p /etc/modsecurity.d
fi
rm -f /etc/modsecurity.d/*
echo "IncludeOptional $CWAF_INSTALL_PATH/etc/cwaf.conf" > "/etc/modsecurity.d/comodo_rules.conf.main" 2>&1 | log2
fi
else
# nginx directadmin setup
prepare_nginx
fi
# change owner for cwaf
chown -R "$DA_USER" "$CWAF_INSTALL_PATH" 2>&1 | log2
chown -R "$DA_USER" "$CWAF_LOG_DIR" 2>&1 | log2
# fix permissions for suid wrapper
chown root:$DA_USER "$CWAF_INSTALL_PATH/scripts/suid" 2>&1 | log2
chmod 4111 "$CWAF_INSTALL_PATH/scripts/suid" 2>&1 | log2
# all done (cpanel mode)
log "All Done!"
${SHOW}_message "Installation complete!\nYou may examine log file\n$INSTALL_LOGFILE\nfor errors in case not everything went flawless.\nAlso you may examine file\n$CWAF_INSTALL_PATH/$STATS_FILE\nfor some useful software information."
exit 0
fi
exit 0