|
Server IP : 45.113.226.95 / Your IP : 216.73.216.239 Web Server : LiteSpeed System : Linux bharat.hostitbro.com 5.14.0-611.13.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 11 04:57:59 EST 2025 x86_64 User : digita21 ( 1701) PHP Version : 8.3.30 Disable Function : mail MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF Directory (0555) : /lib/node_modules/../ |
| [ Home ] | [ C0mmand ] | [ Upload File ] |
|---|
#!/usr/bin/bash
# dprint level message
# print a message to stderr if requested debug level
# is greater than DEBUG_LEVEL global variable
dprint()
{
_level=$1
shift
case "$DEBUG_LEVEL" in
[0-9])
if [ "0$_level" -le "0$DEBUG_LEVEL" ] ; then
echo 1>&2 "$0: $*"
fi
;;
*)
err 1 "DEBUG_LEVEL variable contains garbage"
;;
esac
}
# warn message
# print warning message to stderr
warn()
{
echo 1>&2 "$0: WARNING: $*"
}
# err return_code message
# print error message to stderr and terminate execution
err()
{
_code=$1
shift
echo 1>&2 "$0: ERROR: $*"
_dsn_file="/usr/share/imunifyemail/imunifyemail.dsn"
if [ -n "$REPORT_ERROR" -a "$REPORT_ERROR" = "yes" \
-a -x /usr/bin/sentry-cli \
-a -r "$_dsn_file" ]
then
/usr/bin/env SENTRY_DSN=$(head -1 "$_dsn_file") \
/usr/bin/sentry-cli send-event \
-e "source:ie-config" \
-e "errorcode:$_code" \
-r "2.2.8" \
-m "$0: ERROR: $*" > /dev/null
if [ $? -eq 0 ] ; then
dprint 1 "(the error message reported)"
fi
fi
backup_cleanup "$BACKUP"
exit $_code
}
# getpwuid_dir id
# securely get user home directory by the given id
getpwuid_dir()
{
_id=$1
awk -F: -v id="$_id" '(id == $3) {print $6}' /etc/passwd
}
# auth_root
# check if the user is authenticated to use this script
auth_root()
{
if [ $(id -u) -ne 0 ] ; then
err 2 "must be root to run this command"
fi
}
# fqfn path
# check and resolve path to fully qualified file name
fqfn()
{
if [ -e "$1" ]; then
echo "$(cd $(dirname "$1") && pwd)/$(basename "$1")"
else
warn "$1 not found"
echo ""
fi
}
# backup_file archive files...
# pack given files into archive for backup
# please note, it's okay to have some files missed
backup_file()
{
_archive=$1
shift
if [ -z "$_archive" ] ; then
warn "no backup archive name given"
return
fi
# create empty $_archive so the subsequent tar -u can succeed
if [ ! -f "$_archive" ] ; then
umask 077
touch "$_archive" || \
err 3 "$_archive: can't open archive for writing"
fi
for _arg in $*; do
_file=$(fqfn "$_arg" | sed 's:^/::')
# backup only once!
if [ -s "$_archive" ] && \
tar -tf "$_archive" | grep -q "^$_file$" ; then
continue
fi
if [ -n "$_file" -a -r "/$_file" ] ; then
dprint 2 " backing up /$_file"
if ! tar -uf "$_archive" -C/ "$_file" ; then
err 3 "$_file can't be backed up"
fi
fi
done
}
# backup_cleanup archive
# remove unused backup archive or notify user
backup_cleanup()
{
_archive="$1"
if [ -n "$_archive" ] ; then
if [ -s "$_archive" ] ; then
dprint 1 "backup file is at $_archive"
else
dprint 3 "remove unused backup file"
if [ -f "$_archive" ] ; then
rm "$_archive"
fi
fi
fi
}
old_backup_cleanup()
{
backup_files=($(ls -1 "$HOME" | grep imunifyemail-backup | sort))
two_weeks_ago_ts=$(date +%s --date='-2 weeks')
for i in "${backup_files[@]}";do
ts=$(echo "$i" | cut -d - -f 3)
if [ "$ts" -lt "$two_weeks_ago_ts" ]; then
rm "$HOME/$i"
fi
done
}
#### CONSTANTS ####
QUARANTINE_ENV_FILE="/etc/imunifyemail/quarantine.env"
DEC_NODE_ENV_FILE="/etc/imunifyemail/dec-node.env"
RSPAMD_OVERRIDE_D_FOLDER="/etc/rspamd/override.d"
RSPMAD_OVERRIDED_WORKER_CONTROLLER_INC="/etc/rspamd/override.d/worker-controller.inc"
RSPAMD_OVERRIDED_IE_SPAMFILTER_CONF="/etc/rspamd/override.d/ie-spamfilter.conf"
INCOMING_FILTER_CONF_FILE="/etc/ie_incoming_conf.json"
# cfg_qtoken token
# install new security token for the Quarantine
cfg_qtoken()
{
_name="cfg_qtoken"
_token="$1"
dprint 1 "$_name: set node token $1"
# In the case if there's no token given, generate a random string.
# To obtain at least 512 bits key from a-zA-Z0-9 sequence it's
# required at least ceil(512/log2(26+26+10)) symbols.
if [ -z "$_token" ] ; then
dprint 2 "$_name: generating new security token"
_token=$(tr -cd a-zA-Z0-9 < /dev/urandom | head -c 86)
fi
if ! echo "$_token" | grep -qE '^[a-zA-Z0-9]+$' ; then
err 1 "$_name: token must be of alphanumeric characters only"
fi
override_section_of_rspamd_imunifyemail_conf quarantine api_token "\"$_token\""
override_quarantine_env SERVER_RSPAMDTOKEN "$_token"
}
# cfg_nport port
# set DEC node server address port
cfg_nport()
{
_name="cfg_nport"
_port="$1"
if [ -z "$_port" ] ; then
dprint 2 "$_name: empty port, skip"
return 0
fi
if ! echo "$_port" | grep -qE '^[0-9]+$' ; then
err 1 "$_name: $_port: invalid port number"
fi
override_section_of_rspamd_imunifyemail_conf sampler api_url "http://localhost:$_port/v1/message"
override_dec_node_env SERVER_ADDRESS ":${_port}"
}
# cfg_ntoken token
# install new security token for the DEC
cfg_ntoken()
{
_name="cfg_ntoken"
_token="$1"
dprint 1 "$_name: set node token $1"
# In the case if there's no token given, generate a random string.
# To obtain at least 512 bits key from a-zA-Z0-9 sequence it's
# required at least ceil(512/log2(26+26+10)) symbols.
if [ -z "$_token" ] ; then
dprint 2 "$_name: generating new security token"
_token=$(tr -cd a-zA-Z0-9 < /dev/urandom | head -c 86)
fi
if ! echo "$_token" | grep -qE '^[a-zA-Z0-9]+$' ; then
err 1 "$_name: token must be of alphanumeric characters only"
fi
override_section_of_rspamd_imunifyemail_conf sampler api_token "\"$_token\""
override_dec_node_env SERVER_TOKEN "$_token"
override_quarantine_env DECNODE_TOKEN "$_token"
}
# cfg_nsr [rate]
# set sampling rate for the node
cfg_nsr()
{
_name="cfg_nsr"
_rate="$1"
if [ -z "$_rate" ] ; then
dprint 2 "$_name: empty rate value, skip"
return 0
fi
if ! echo "$_rate" | grep -qE '^([0-9]|[1-9][0-9]|100)$' ; then
err 1 "$_name: rate value must be in range of [0..100]"
fi
override_section_of_rspamd_imunifyemail_conf sampler sampling_freq "$_rate"
/bin/systemctl restart rspamd.service
}
# print_version ["packages"]
# print package version number
print_version()
{
_packages=$1
_pkgtool=$(which rpm 2>&1)
if [ $? -eq 0 ] ; then
if [ -n "$_packages" -a "$_packages" = "packages" ] ; then
rpm -qa --queryformat "%{NAME}:%{VERSION}:%{RELEASE}\n" \
"imunifyemail*" | grep -v "debuginfo" | sort
else
rpm -qa --queryformat "%{VERSION}-%{RELEASE}\n" \
imunifyemail | sed 's/-\([0-9][0-9]*\).*/-\1/'
fi
return 0
fi
_pkgtool=$(which dpkg 2>&1)
if [ $? -eq 0 ] ; then
if [ -n "$_packages" -a "$_packages" = "packages" ] ; then
dpkg-query -W -f='${binary:Package}:${Version}:${Whatever}\n' | grep '^imunifyemail' | sed 's/:$//'
else
dpkg -s "imunifyemail" \
| sed -n 's/^Version: \([0-9][0-9.-]*\).*/\1/p'
fi
return 0
fi
err 6 "print_version: no known package tool found"
}
add_user_in_group()
{
_group=$1
_user=$2
_auig_name="add_user_in_group(user=$_user, group=$_group)"
if groups "$_user" | grep -w "$_group"; then
dprint 1 "$_auig_name: user already in the group, skip"
else
dprint 1 "$_auig_name: adding user to the group"
usermod -a -G "$_group" "$_user"
fi
}
override_quarantine_env()
{
_create_file_and_set_perms "$QUARANTINE_ENV_FILE" _imunifyemail _imunify
_override_conf_file "$QUARANTINE_ENV_FILE" "$1" "$2"
}
override_dec_node_env()
{
_create_file_and_set_perms "$DEC_NODE_ENV_FILE" _imunifyemail _imunify
_override_conf_file "$DEC_NODE_ENV_FILE" "$1" "$2"
}
override_section_of_rspamd_imunifyemail_conf()
{
_section=$1
_key=$2
_value=$3
case "$_section" in
sampler|quarantine|cpanel)
_file_name="$RSPAMD_OVERRIDE_D_FOLDER/$_section.conf"
_create_file_and_set_perms "$_file_name" root _rspamd
_override_conf_file "$_file_name" "$_key" "$_value"
;;
*)
err 1 "override_section_of_rspamd_imunifyemail_conf(section=$_section, key=$_key): unknown section"
;;
esac
}
override_ie_spamfilter_conf()
{
_create_file_and_set_perms "$RSPAMD_OVERRIDED_IE_SPAMFILTER_CONF" root mail
_override_conf_file "$RSPAMD_OVERRIDED_IE_SPAMFILTER_CONF" "$1" "$2"
}
_override_conf_file()
{
_conf_file=$1
_key=$2
_value=$3
_ocf_name="_override_conf_file(conf_file=$_conf_file, key=$_key)"
dprint 2 "$_ocf_name"
# validate parameters
if [ -z "$_key" ] || [ -z "$_value" ] || [ -z "$_conf_file" ]; then
err 100 "$_ocf_name: wrong parameters"
fi
# append or edit env_file file
if grep -q "${_key}" "$_conf_file" 2>/dev/null; then
sed -i 's/'"$_key"'=.*/'"$_key"'='"$_value"'/g' "$_conf_file" || err 250 "$_ocf_name: unexpected error (sed)"
else
echo "$_key=$_value" >> "$_conf_file"
fi
}
_create_file_and_set_perms()
{
_file_name=$1
_user=$2
_group=$3
_permissions=$4
# set default permissions if it doesn't provided
if [ -z "$_permissions" ]; then
_permissions="640"
fi
_cfsp_name="_create_file_and_set_perms(file_name=$_file_name, user=$_user, group=$_group, permissions=$_permissions)"
if ! test -f "$_file_name"; then
dprint 2 "$_cfsp_name: creating file"
touch "$_file_name"
fi
_sf_stat=$(stat --format '%a:%U:%G' "$_file_name")
if [ "$_sf_stat" != "$_permissions:$_user:$_group" ] ; then
dprint 1 "$_cfsp_name: set permissions"
chown "$_user":"$_group" "$_file_name"
chmod $_permissions "$_file_name"
fi
}
_add_line_to_file() {
local file="$1"
local value="$2"
local case_sensitive="${3:-false}"
local cdb="$4"
local lock_file="${file}.lock"
local temp_file="${file}.tmp"
local _ocf_name="_add_line_to_file(conf_file=$file, value=$value, cdb=$cdb)"
dprint 2 "$_ocf_name"
# validate parameters
if [ -z "$value" ] || [ -z "$file" ]; then
err 100 "$_ocf_name: wrong parameters"
fi
# Create the file if it doesn't exist
if [ ! -f "$file" ]; then
touch "$file"
fi
# Use flock to ensure only one process can modify the file at a time
(
flock -e 200 # Acquire an exclusive lock
if [ "$case_sensitive" = true ]; then
grep_cmd="grep -q"
else
grep_cmd="grep -qi"
fi
# Check if the line already exists (case-insensitive)
if ! eval "$grep_cmd" "^${value}$" "$file"; then
# Write the current content to a temporary file and append the new line
if cat "$file" > "$temp_file" && echo "$value" >> "$temp_file"; then
# Move the temp file to the original file atomically
if mv "$temp_file" "$file"; then
if [ ! -z "$cdb" ]; then
if ! cdb -c -m "$cdb" "$file"; then
err 1 "Failed to create cdb file"
fi
fi
echo "The config added successfully to $file"
else
rm -f "$temp_file" # Clean up the temp file if the move fails
err 1 "Failed to replace the original file."
fi
else
err 1 "Failed to write to the temporary file."
fi
fi
) 200>"$lock_file" # Lock file descriptor 200 using the lock file
# Remove the lock file after the operation
rm -f "$lock_file"
}
_remove_line_from_file() {
local file="$1"
local value="$2"
local case_sensitive="${3:-false}"
local cdb="$4"
local temp_file="${file}.tmp"
local lock_file="${file}.lock"
local _ocf_name="_remove_line_from_file(conf_file=$file, value=$value)"
dprint 2 "$_ocf_name"
# validate parameters
if [ -z "$value" ] || [ -z "$file" ]; then
err 100 "$_ocf_name: wrong parameters"
fi
if [ -f "$file" ]; then
# Use flock to ensure only one process can modify the file at a time
(
flock -e 200 # Acquire an exclusive lock
# Escape any / characters in the value
local escaped=$(echo "$value" | sed 's/\//\\\//g')
# Set sed command based on case sensitivity
if [ "$case_sensitive" = true ]; then
sed_cmd="sed '/^${escaped}$/d'"
else
sed_cmd="sed '/^${escaped}$/I d'"
fi
# Use sed to delete the matching line in a case-insensitive way
if eval "${sed_cmd}" "$file" > "$temp_file"; then
# Move the temp file to the original file atomically
if mv "$temp_file" "$file"; then
if [ ! -z "$cdb" ]; then
if ! cdb -c -m "$cdb" "$file"; then
err 1 "Failed to create cdb file"
fi
fi
echo "The config removed successfully from $file"
else
rm -f "$temp_file" # Clean up the temp file if the move fails
err 1 "Failed to replace the original file."
fi
else
err 1 "Failed to write to the temporary file."
fi
) 200>"$lock_file" # Lock file descriptor 200 using the lock file
# Remove the lock file after the operation
rm -f "$lock_file"
fi
}
_incoming_filtration_state()
{
if [ ! -f "$INCOMING_FILTER_CONF_FILE" ]; then
echo "disabled"
elif grep -q '"enabled"' $INCOMING_FILTER_CONF_FILE; then
echo "enabled"
else
echo "disabled"
fi
}
_toggle_incoming_filtration()
{
in_state=$1
_tif_name="_toggle_incoming_filtration(state=$in_state)"
case $in_state in
enabled|disabled|enabled_stat)
if [ -f "$INCOMING_FILTER_CONF_FILE" ]; then
if ! grep -q '"state"' $INCOMING_FILTER_CONF_FILE; then
err 250 "malformed $INCOMING_FILTER_CONF_FILE file"
fi
sed -i 's/\("state":\s*"\)[^"]*"/\1'"$in_state"'"/' "$INCOMING_FILTER_CONF_FILE" || \
err 250 "$_tif_name: unexpected error (sed)"
else
_create_file_and_set_perms $INCOMING_FILTER_CONF_FILE _imunifyemail mail 640
echo "{ \"state\": \"${in_state}\" }" > "$INCOMING_FILTER_CONF_FILE"
fi
dprint 2 "restarting ie-quarantine service"
# should we also catch errors from the folowing?
/bin/systemctl restart ie-quarantine.service
;;
*)
err "$_tif_name: unsupported state value"
esac
dprint 1 "$_tif_name: incoming email filtering has been changed to $in_state."
}