File: /volume1/@appstore/MailPlus-Server/bin/clamav-unofficial-sigs.sh
#!/bin/bash
# shellcheck disable=SC2154
# shellcheck disable=SC2128
################################################################################
# This is property of eXtremeSHOK.com
# You are free to use, modify and distribute, however you may not remove this notice.
# Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
# License: BSD (Berkeley Software Distribution)
################################################################################
#
# Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
#
# Originially based on Script provided by Bill Landry (unofficialsigs@gmail.com).
#
################################################################################
#
# THERE ARE NO USER CONFIGURABLE OPTIONS IN THIS SCRIPT
# ALL CONFIGURATION OPTIONS ARE LOCATED IN THE INCLUDED CONFIGURATION FILE
#
################################################################################
# add PATH to find clamscan
PATH="${PATH}:/var/packages/MailPlus-Server/target/bin"
################################################################################
###### ####### # # ####### ####### ####### ###### ### #######
# # # # ## # # # # # # # # #
# # # # # # # # # # # # # # #
# # # # # # # # # # ##### # # # #
# # # # # # # # # # # # # # #
# # # # # ## # # # # # # # #
###### ####### # # ####### # ####### ###### ### #
################################################################################
# Detect to make sure the entire script is avilable, fail if the script is missing contents
if [ "$(tail -n 1 "$0" | head -n 1 | cut -c 1-7)" != "exit \$?" ] ; then
echo "FATAL ERROR: Script is incomplete, please redownload"
exit 1
fi
# Trap the keyboard interrupt (Ctrl + C)
trap xshok_control_c SIGINT
################################################################################
# HELPER FUNCTIONS
################################################################################
# Support user config settings for applying file and directory access permissions.
function perms () {
if [ -n "$clam_user" ] && [ -n "$clam_group" ] ; then
"${@:-}"
fi
}
# Prompt a user if they should complete an action with Y or N
# Usage: xshok_prompt_confirm
# if xshok_prompt_confirm; then
# xshok_prompt_confirm && echo "accepted"
# xshok_prompt_confirm && echo "yes" || echo "no"
# shellcheck disable=SC2120
function xshok_prompt_confirm () { # optional_message
message="${1:-Are you sure?}"
while true; do
read -r -p "$message [y/N]" response < /dev/tty
case "$response" in
[yY]) return 0 ;;
[nN]) return 1 ;;
*) printf " \033[31m %s \n\033[0m" "invalid input"
esac
done
}
# Create a pid file
function xshok_create_pid_file () { # pid.file
if [ "$1" ] ; then
pidfile="$1"
echo $$ > "$pidfile"
if [ $? -ne 0 ] ; then
xshok_pretty_echo_and_log "ERROR: Could not create PID file: $pidfile"
exit 1
fi
else
xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
exit 1
fi
}
# Intercept ctrl+c and calls the cleanup function
function xshok_control_c () {
echo
xshok_pretty_echo_and_log "--------------| Exiting ... Please wait |--------------" "-"
xshok_cleanup
exit $?
}
# Cleanup function
function xshok_cleanup () {
# Wait for all processes to end
wait
xshok_pretty_echo_and_log " Powered By https://eXtremeSHOK.com " "#"
return $?
}
# Check if the current running user is the root user, otherwise return false
function xshok_is_root () {
if [ "$(uname -s)" == "SunOS" ] ; then
id_bin="/usr/xpg4/bin/id"
else
id_bin="$(which id 2> /dev/null)"
fi
if [ "$($id_bin -u)" == 0 ] ; then
return 0
else
return 1 # Not root
fi
}
# Check if its a file, otherwise return false
function xshok_is_file () { # filepath
filepath="$1"
if [ -f "${filepath}" ] ; then
return 0 ;
else
return 1 ; # Not a file
fi
}
# Check if filepath is a subdir, otherwise return false
# Usage: xshok_is_subdir "filepath"
# xshok_is_subdir "/root/" - false
# xshok_is_subdir "/usr/local/etc" && echo "yes" - yes
function xshok_is_subdir () { # filepath
shopt -s extglob; filepath="${filepath%%+(/)}"
if [ -d "$filepath" ] ; then
res="${filepath//[^\/]}"
if [ "${#res}" -gt 1 ] ; then
return 0 ;
else
return 1 ; # Not a subdir
fi
else
return 1 ; # Not a dir
fi
}
# Create a dir and set the ownership
function xshok_mkdir_ownership () { # path
if [ "$1" ] ; then
mkdir -p "$1" 2>/dev/null
if [ $? -ne 0 ] ; then
xshok_pretty_echo_and_log "ERROR: Could not create directory: $1"
exit 1
fi
perms chown -f "$clam_user:$clam_group" "$1" > /dev/null 2>&1
else
xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
exit 1
fi
}
# Check if a user and group exists on the system otherwise return false
# Usage:
# xshok_is_subdir "username" && echo "user found" || echo "no"
# xshok_is_subdir "username" "groupname" && echo "user and group found" || echo "no"
function xshok_user_group_exists () { # username groupname
if [ "$(uname -s)" == "SunOS" ] ; then
id_bin="/usr/xpg4/bin/id"
else
id_bin="$(which id 2> /dev/null)"
fi
if [ "$2" ] ; then
if [ "$(uname -s)" == "Darwin" ] ; then
#use ruby, as this is the best way. Ruby is always avilable as brew uses ruby
ruby -e 'require "etc"; puts Etc::getgrnam("_clamav").gid' > /dev/null 2>&1
ret="$?"
else
# getent_bin="$(which getent 2> /dev/null)"
# $getent_bin group "$2" >/dev/null 2>&1
synogroup_bin="$(which synogroup 2> /dev/null)"
$synogroup_bin --get "$2" >/dev/null 2>&1
ret="$?"
fi
fi
if [ "$1" ] ; then
$id_bin -u "$1" > /dev/null 2>&1
if [ $? -eq 0 ]; then
if [ "$2" ] ; then
if [ "$ret" -eq 0 ]; then
return 0 ; # User and group exists
else
return 1 ; # Group does NOT exist
fi
else
return 0 ; # User exists
fi
else
return 1 ; # User does NOT exist
fi
else
xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
exit 1
fi
}
# Handle comments with/out borders and logging.
# Usage:
# pretty_echo_and_log "one"
# one
# pretty_echo_and_log "two" "-"
# ---
# two
# ---
# pretty_echo_and_log "three" "=" "8"
# ========
# three
# ========
# pretty_echo_and_log "" "/\" "7"
# /\/\/\/\/\/\
# type: e = error, w= warning ""
function xshok_pretty_echo_and_log () { # "string" "repeating" "count" "type"
# Handle comments
if [ "$comment_silence" == "no" ] ; then
if [ "${#@}" -eq 1 ] ; then
echo "$1"
else
myvar=""
if [ -n "$3" ] ; then
mycount="$3"
else
mycount="${#1}"
fi
for (( n = 0; n < mycount; n++ )) ; do
myvar="$myvar$2"
done
if [ -n "$1" ] ; then
echo -e "$myvar\n$1\n$myvar"
else
echo -e "$myvar"
fi
fi
fi
# Handle logging
if [ "$enable_log" == "yes" ] ; then
if [ ! -e "$log_file_path/$log_file_name" ] ; then
# xshok_mkdir_ownership "$log_file_path"
mkdir -p "$log_file_path"
touch "$log_file_path/$log_file_name" 2>/dev/null
perms chown -f "$clam_user:$clam_group" "$log_file_path/$log_file_name"
fi
if [ ! -w "$log_file_path/$log_file_name" ] ; then
echo "Warning: Logging Disabled, as file not writable: $log_file_path/$log_file_name"
enable_log="no"
else
echo "$(date "+%b %d %T")" "$1" >> "$log_file_path/$log_file_name"
fi
fi
}
# Check if the $2 value is not null and does not start with -
function xshok_check_s2 () { # value1 value2
if [ "$1" ] ; then
if [[ "$1" =~ ^-.* ]] ; then
xshok_pretty_echo_and_log "ERROR: Missing value for option or value begins with -" "="
exit 1
fi
else
xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
exit 1
fi
}
# Time remaining information function
function xshok_draw_time_remaining () { #time_remaining #update_hours #name
if [ "$1" ] && [ "$2" ]; then
time_remaining="$1"
hours_left="$((time_remaining / 3600))"
minutes_left="$((time_remaining % 3600 / 60))"
xshok_pretty_echo_and_log "$2 hours have not yet elapsed since the last $3 update check"
xshok_pretty_echo_and_log "No update check was performed at this time" "-"
xshok_pretty_echo_and_log "Next check will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
fi
}
# Download function
function xshok_file_download () { #outputfile #url
if [ "$1" ] && [ "$2" ]; then
if [ -n "$wget_bin" ] ; then
# shellcheck disable=SC2086
$wget_bin $wget_proxy_https $wget_proxy_http $wget_insecure $wget_output_level --connect-timeout="$downloader_connect_timeout" --random-wait --tries="$downloader_tries" --timeout="$downloader_max_time" --output-document="$1" "$2"
result=$?
else
# shellcheck disable=SC2086
$curl_bin $curl_proxy $curl_insecure $curl_output_level --connect-timeout "$downloader_connect_timeout" --remote-time --location --retry "$downloader_tries" --max-time "$downloader_max_time" --output "$1" "$2"
result=$?
fi
return $result
fi
}
# Auto update
function xshok_auto_update () { # version
xshok_pretty_echo_and_log "Performing automatic update..."
# Download new version
echo -n "Downloading latest version..."
xshok_file_download "$0.tmp" "$UPDATE_BASE/$SELF"
result=$?
if [ "$result" -ne 0 ]; then
echo "Failed: Error while trying to get new version!"
echo "File requested: $UPDATE_BASE/$SELF"
exit 1
fi
echo "Done."
# Copy over modes from old version
OCTAL_MODE="$(stat -c "%a" "$SELF")"
if ! chmod "$OCTAL_MODE" "${0}.tmp" ; then
echo "Failed: Error while trying to set mode on ${0}.tmp."
exit 1
fi
# Generate the update script
cat > xshok_update_script.sh << EOF
#!/bin/bash
# Overwrite old file with new
if mv "$0.tmp" "$0"; then
echo "Done. Update complete."
rm \$0
else
echo "Failed! The update was not completed."
fi
EOF
echo -n "Inserting update process..."
# Replaced with $0, so code will update and then call itself with the same parameters it had
#exec /bin/bash xshok_update_script.sh
exec "$0" "$@"
}
# Handle list of database files
function clamav_files () {
echo "$clam_dbs/$db" >> "$current_tmp"
if [ "$keep_db_backup" == "yes" ] ; then
echo "$clam_dbs/$db-bak" >> "$current_tmp"
fi
}
# Manage the databases and allow multi-dimensions as well as global overrides
# Since the datbases are basically a multi-dimentional associative arrays in bash
# ratings: LOW| MEDIUM| HIGH| REQUIRED| LOWONLY| MEDIUMONLY| LOWMEDIUMONLY | MEDIUMHIGHONLY | HIGHONLY| DISABLED
function xshok_database () { # rating database_array
# Assign
current_rating="$1"
declare -a current_dbs=( "${@:2}" )
# Zero
declare -a new_dbs=( )
if [ -n "${current_dbs[0]}" ] ; then
if [ ${#current_dbs} -ge 1 ] ; then
for db_name in "${current_dbs[@]}" ; do
# Checks
if [ "$enable_yararules" == "no" ] ; then # YARA rules are disabled
if [[ "$db_name" == *".yar"* ]] ; then # If it's the value you want to delete
continue # Skip to the next value
fi
fi
if [ -z "$current_rating" ] ; then # YARA rules are disabled
new_dbs+=( "$db_name" )
else
if [[ ! "$db_name" = *"|"* ]] ; then # This old format
new_dbs+=( "$db_name" )
else
db_name_rating="${db_name#*|}"
db_name="${db_name%|*}"
if [ "$db_name_rating" != "DISABLED" ] ; then
if [ "$db_name_rating" == "$current_rating" ] ; then
new_dbs+=( "$db_name" )
elif [ "$db_name_rating" == "REQUIRED" ] ; then
new_dbs+=( "$db_name" )
elif [ "$current_rating" == "LOW" ] ; then
if [ "$db_name_rating" == "LOWONLY" ] || [ "$db_name_rating" == "LOW" ] || [ "$db_name_rating" == "LOWMEDIUM" ] ; then
new_dbs+=( "$db_name" )
fi
elif [ "$current_rating" == "MEDIUM" ] ; then
if [ "$db_name_rating" == "MEDIUMONLY" ] || [ "$db_name_rating" == "MEDIUM" ] || [ "$db_name_rating" == "LOW" ] || [ "$db_name_rating" == "LOWMEDIUM" ] ; then
new_dbs+=( "$db_name" )
fi
elif [ "$current_rating" == "HIGH" ] ; then
if [ "$db_name_rating" == "HIGH" ] || [ "$db_name_rating" == "MEDIUM" ] || [ "$db_name_rating" == "LOW" ] ; then
new_dbs+=( "$db_name" )
fi
fi
fi
fi
fi
done
fi
fi
echo "${new_dbs[@]}" | xargs # Remove extra whitespace
}
################################################################################
# ADDITIONAL PROGRAM FUNCTIONS
################################################################################
# Generates a man config and installs it
function install_man () {
if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
exit 1
fi
echo ""
echo "Generating man file for install...."
# Use defined varibles or attempt to use default varibles
if [ ! -e "$man_dir/$man_filename" ] ; then
mkdir -p "$man_dir"
touch "$man_dir/$man_filename" 2>/dev/null
fi
if [ ! -w "$man_dir/$man_filename" ] ; then
echo "ERROR: man install aborted, as file not writable: $man_dir/$man_filename"
else
BOLD="\fB"
#REV=""
NORM="\fR"
manresult="$(help_and_usage "man")"
# Our template..
cat << EOF > "$man_dir/$man_filename"
.\" Manual page for eXtremeSHOK.com ClamAV Unofficial Signature Updater
.TH clamav-unofficial-sigs 8 "$script_version_date" "Version: $script_version" "SCRIPT COMMANDS"
.SH NAME
clamav-unofficial-sigs \- Download, test, and install third-party ClamAV signature databases.
.SH SYNOPSIS
.B clamav-unofficial-sigs
.RI [ options ]
.SH DESCRIPTION
\fBclamav-unofficial-sigs\fP provides a simple way to download, test, and update third-party signature databases provided by Sanesecurity, FOXHOLE, OITC, Scamnailer, BOFHLAND, CRDF, Porcupine, Securiteinfo, MalwarePatrol, Yara-Rules Project, etc. It will also generate and install cron, logrotate, and man files.
.SH UPDATES
Script updates can be found at: \fBhttps://github.com/extremeshok/clamav-unofficial-sigs\fP
.SH OPTIONS
This script follows the standard GNU command line syntax.
.LP
$manresult
.SH SEE ALSO
.BR clamd (8),
.BR clamscan (1)
.SH COPYRIGHT
Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
.TP
You are free to use, modify and distribute, however you may not remove this notice.
.SH LICENSE
BSD (Berkeley Software Distribution)
.SH BUGS
Report bugs to \fBhttps://github.com/extremeshok/clamav-unofficial-sigs\fP
.SH AUTHOR
Adrian Jon Kriel :: admin@extremeshok.com
Originially based on Script provide by Bill Landry
EOF
fi
echo "Completed: man installed, as file: $man_dir/$man_filename"
}
# Generate a logrotate config and install it
function install_logrotate () {
if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
exit 1
fi
echo ""
echo "Generating logrotate file for install...."
# Use defined varibles or attempt to use default varibles
if [ -z "$logrotate_user" ] ; then
logrotate_user="$clam_user";
fi
if [ -z "$logrotate_group" ] ; then
logrotate_group="$clam_group";
fi
if [ -z "$logrotate_log_file_full_path" ] ; then
logrotate_log_file_full_path="$log_file_path/$log_file_name"
fi
if [ ! -e "$logrotate_dir/$logrotate_filename" ] ; then
mkdir -p "$logrotate_dir"
touch "$logrotate_dir/$logrotate_filename" 2>/dev/null
fi
if [ ! -w "$logrotate_dir/$logrotate_filename" ] ; then
echo "ERROR: logrotate install aborted, as file not writable: $logrotate_dir/$logrotate_filename"
else
# Our template..
cat << EOF > "$logrotate_dir/$logrotate_filename"
# https://eXtremeSHOK.com ######################################################
# This file contains the logrotate settings for clamav-unofficial-sigs.sh
###################
# This is property of eXtremeSHOK.com
# You are free to use, modify and distribute, however you may not remove this notice.
# Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
##################
#
# Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
#
# Originially based on:
# Script provide by Bill Landry (unofficialsigs@gmail.com).
#
# License: BSD (Berkeley Software Distribution)
#
##################
# Automatically Generated: $(date)
##################
#
# This logrotate file will rotate the logs generated by the clamav-unofficial-sigs.sh
#
# To Adjust the logrotate values, edit your configs and run
# bash clamav-unofficial-sigs.sh --install-logrotate to generate a new file.
$logrotate_log_file_full_path {
weekly
rotate 4
missingok
notifempty
compress
create 0640 $logrotate_user $logrotate_group
}
EOF
fi
echo "Completed: logrotate installed, as file: $logrotate_dir/$logrotate_filename"
}
# Generate a cron config and install it
function install_cron () {
if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
exit 1
fi
echo ""
echo "Generating cron file for install...."
# Use defined varibles or attempt to use default varibles
if [ -z "$cron_minute" ] ; then
cron_minute="$(( ( RANDOM % 59 ) + 1 ))"
fi
if [ -z "$cron_user" ] ; then
cron_user="$clam_user";
fi
if [ -z "$cron_bash" ] ; then
cron_bash="$(which bash 2> /dev/null)"
fi
if [ -z "$cron_script_full_path" ] ; then
cron_script_full_path="$this_script_full_path"
fi
if [ ! -e "$cron_dir/$cron_filename" ] ; then
mkdir -p "$cron_dir"
touch "$cron_dir/$cron_filename" 2>/dev/null
fi
if [ ! -w "$cron_dir/$cron_filename" ] ; then
echo "ERROR: cron install aborted, as file not writable: $cron_dir/$cron_filename"
else
# Our template..
cat << EOF > "$cron_dir/$cron_filename"
# https://eXtremeSHOK.com ######################################################
# This file contains the cron settings for clamav-unofficial-sigs.sh
###################
# This is property of eXtremeSHOK.com
# You are free to use, modify and distribute, however you may not remove this notice.
# Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
##################
#
# Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
#
# Originially based on:
# Script provide by Bill Landry (unofficialsigs@gmail.com).
#
# License: BSD (Berkeley Software Distribution)
#
##################
# Automatically Generated: $(date)
##################
#
# This cron file will execute the clamav-unofficial-sigs.sh script that
# currently supports updating third-party signature databases provided
# by Sanesecurity, SecuriteInfo, MalwarePatrol, OITC, etc.
#
# The script is set to run hourly, at a random minute past the hour, and the
# script itself is set to randomize the actual execution time between
# 60 - 600 seconds. To Adjust the cron values, edit your configs and run
# bash clamav-unofficial-sigs.sh --install-cron to generate a new file.
$cron_minute * * * * $cron_user [ -x $cron_script_full_path ] && $cron_bash $cron_script_full_path > /dev/null
# https://eXtremeSHOK.com ######################################################
EOF
fi
echo "Completed: cron installed, as file: $cron_dir/$cron_filename"
}
# Decode a third-party signature either by signature name
function decode_third_party_signature_by_signature_name () {
echo ""
echo "Input a third-party signature name to decode (e.g: Sanesecurity.Junk.15248) or"
echo "a hexadecimal encoded data string and press enter (do not include '.UNOFFICIAL'"
echo "in the signature name nor add quote marks to any input string):"
read -r input
input="$(echo "$input" | tr -d "'" | tr -d '"')"
if echo "$input" | $grep_bin "\." > /dev/null ; then
cd "$clam_dbs" || exit
sig="$($grep_bin "$input:" ./*.ndb)"
if [ -n "$sig" ] ; then
db_file="${sig%:*}"
echo "$input found in: $db_file"
echo "$input signature decodes to:"
echo "$sig" | cut -d ":" -f 5 | perl -pe 's/([a-fA-F0-9]{2})|(\{[^}]*\}|\([^)]*\))/defined $2 ? $2 : chr(hex $1)/eg'
else
echo "Signature '$input' could not be found."
echo "This script will only decode ClamAV 'UNOFFICIAL' third-Party,"
echo "non-image based, signatures as found in the *.ndb databases."
fi
else
echo "Here is the decoded hexadecimal input string:"
echo "$input" | perl -pe 's/([a-fA-F0-9]{2})|(\{[^}]*\}|\([^)]*\))/defined $2 ? $2 : chr(hex $1)/eg'
fi
}
# Hexadecimal encode an entire input string
function hexadecimal_encode_entire_input_string () {
echo ""
echo "Input the data string that you want to hexadecimal encode and then press enter. Do not include"
echo "any quotes around the string unless you want them included in the hexadecimal encoded output:"
read -r input
echo "Here is the hexadecimal encoded input string:"
echo "$input" | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg'
}
# Hexadecimal encode a formatted input string
function hexadecimal_encode_formatted_input_string () {
echo ""
echo "Input a formated data string containing spacing fields '{}, (), *' that you want to hexadecimal"
echo "encode, without encoding the spacing fields, and then press enter. Do not include any quotes"
echo "around the string unless you want them included in the hexadecimal encoded output:"
read -r input
echo "Here is the hexadecimal encoded input string:"
echo "$input" | perl -pe 's/(\{[^}]*\}|\([^)]*\)|\*)|(.)/defined $1 ? $1 : sprintf("%02lx", ord $2)/eg'
}
# GPG verify a specific Sanesecurity database file
function gpg_verify_specific_sanesecurity_database_file () { # databasefile
echo ""
if [ "$enable_gpg" == "no" ] ; then
xshok_pretty_echo_and_log "Notice: GnuPG / signature verification disabled" "-"
else
if [ "$1" ] ; then
db_file="$(echo "$1" | awk -F "/" '{print $NF}')"
if [ -r "$work_dir_sanesecurity/$db_file" ] ; then
echo "GPG signature testing database file: $work_dir_sanesecurity/$db_file"
if [ -r "$work_dir_sanesecurity/$db_file".sig ] ; then
"$gpg_bin" -q --trust-model always --no-default-keyring --homedir "$work_dir_gpg" --keyring "$work_dir_gpg"/ss-keyring.gpg --verify "$work_dir_sanesecurity"/"$db_file".sig "$work_dir_sanesecurity"/"$db_file"
if [ $? -ne 0 ]; then
"$gpg_bin" -q --always-trust --no-default-keyring --homedir "$work_dir_gpg" --keyring "$work_dir_gpg"/ss-keyring.gpg --verify "$work_dir_sanesecurity"/"$db_file".sig "$work_dir_sanesecurity"/"$db_file"
if [ $? -eq 0 ]; then
exit 0
else
exit 1
fi
else
exit 0
fi
else
echo "Signature '${db_file}.sig' cannot be found."
fi
else
echo "File '$db_file' cannot be found or is not a Sanesecurity database file."
echo "Only the following Sanesecurity and OITC databases can be GPG signature tested:"
ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_sanesecurity"
fi
else
xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
exit 1
fi
exit 1
fi
}
# Output system and configuration information
function output_system_configuration_information () {
echo ""
echo "*** SCRIPT VERSION ***"
echo "$this_script_name $script_version ($script_version_date)"
echo "*** SYSTEM INFORMATION ***"
$uname_bin -a
echo "*** CLAMSCAN LOCATION & VERSION ***"
echo "$clamscan_bin"
$clamscan_bin --version | head -1
echo "*** RSYNC LOCATION & VERSION ***"
echo "$rsync_bin"
$rsync_bin --version | head -1
if [ -n "$wget_bin" ] ; then
echo "*** WGET LOCATION & VERSION ***"
echo "$wget_bin"
$wget_bin --version | head -1
else
echo "*** CURL LOCATION & VERSION ***"
echo "$curl_bin"
$curl_bin --version | head -1
fi
if [ "$enable_gpg" == "yes" ] ; then
echo "*** GPG LOCATION & VERSION ***"
echo "$gpg_bin"
$gpg_bin --version | head -1
fi
echo "*** SCRIPT WORKING DIRECTORY INFORMATION ***"
echo "$work_dir"
echo "*** CLAMAV DIRECTORY INFORMATION ***"
echo "$clam_dbs"
echo "*** SCRIPT CONFIGURATION SETTINGS ***"
if [ "$custom_config" != "no" ] ; then
if [ -d "$custom_config" ] ; then
# Assign the custom config dir and remove trailing / (removes / and //)
echo "Custom Configuration Directory: $config_dir"
else
echo "Custom Configuration File: $custom_config"
fi
else
echo "Configuration Directory: $config_dir"
fi
}
# Make a signature database from an ascii file
function make_signature_database_from_ascii_file () {
echo ""
echo "
The '-m' script flag provides a way to create a ClamAV hexadecimal signature database (*.ndb) file
from a list of data strings stored in a clear-text ascii file, with one data string entry per line.
- Hexadecimal encoding can be either 'full' or 'formatted' on a per line basis:
Full line encoding should be used if there are no formatted spacing entries [{}, (), *]
included on the line. Prefix unformatted lines with: '-:' (no quote marks).
Example:
-:This signature contains no formatted spacing fields
Encodes to:
54686973207369676e617475726520636f6e7461696e73206e6f20666f726d61747465642073706163696e67206669656c6473
Formatted line encoding should be used if there are user added spacing entries [{}, (), *]
included on the line. Prefix formatted lines with '=:' (no quote marks).
Example:
=:This signature{-10}contains several(25|26|27)formatted spacing*fields
Encodes to:
54686973207369676e6174757265{-10}636f6e7461696e73207365766572616c(25|26|27)666f726d61747465642073706163696e67*6669656c6473
Use 'full' encoding if you want to encode everything on the line [including {}, (), *] and 'formatted'
encoding if you want to encode everything on the line except the formatted character spacing fields.
The prefixes ('-:' and '=:') will be stripped from the line before hexadecimal encoding is done.
If no prefix is found at the beginning of the line, full line encoding will be done (default).
- It is assumed that the signatures will be created for email scanning purposes, thus the '4'
target type is used and full file scanning is enabled (see ClamAV signatures.pdf for details).
- Line numbering will be done automatically by the script.
" | command sed 's/^ //g'
echo -n "Do you wish to continue? "
if xshok_prompt_confirm ; then
echo -n "Enter the source file as /path/filename: "
read -r source
if [ -r "$source" ] ; then
source_file="$(basename "$source")"
echo "What signature prefix would you like to use? For example: 'Phish.Domains'"
echo "will create signatures that looks like: 'Phish.Domains.1:4:*:HexSigHere'"
echo -n "Enter signature prefix: "
read -r prefix
path_file="$(echo "$source" | cut -d "." -f -1 | command sed 's/$/.ndb/')"
db_file="$(basename "$path_file")"
rm -f "$path_file"
total="$(wc -l "$source" | cut -d " " -f 1)"
line_num="1"
while read -r line ; do
line_prefix="$(echo "$line" | awk -F ":" '{print $1}')"
if [ "$line_prefix" == "-" ] ; then
echo "$line" | cut -d ":" -f 2- | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg' | command sed "s/^/$prefix\.$line_num:4:\*:/" >> "$path_file"
elif [ "$line_prefix" == "=" ] ; then
echo "$line" | cut -d ":" -f 2- | perl -pe 's/(\{[^}]*\}|\([^)]*\)|\*)|(.)/defined $1 ? $1 : sprintf("%02lx", ord $2)/eg' | command sed "s/^/$prefix\.$line_num:4:\*:/" >> "$path_file"
else
echo "$line" | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg' | command sed "s/^/$prefix\.$line_num:4:\*:/" >> "$path_file"
fi
echo "Hexadecimal encoding $source_file line: $line_num of $total"
line_num="$((line_num + 1))"
done < "$source"
else
echo "Source file not found, exiting..."
exit
fi
echo "Signature database file created at: $path_file"
if $clamscan_bin --quiet -d "$path_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
echo "Clamscan reports database integrity tested good."
echo -n "Would you like to move '$db_file' into '$clam_dbs' and reload databases?"
if xshok_prompt_confirm ; then
if ! cmp -s "$path_file" "$clam_dbs/$db_file" ; then
if $rsync_bin -pcqt "$path_file" "$clam_dbs" ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
perms chmod -f 0644 "$clam_dbs"/"$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
$clamd_restart_opt
echo "Signature database '$db_file' was successfully implemented and ClamD databases reloaded."
else
echo "Failed to add/update '$db_file', ClamD database not reloaded."
fi
else
echo "Database '$db_file' has not changed - skipping"
fi
else
echo "No action taken."
fi
else
echo "Clamscan reports that '$db_file' signature database integrity tested bad."
fi
fi
}
# Remove the clamav-unofficial-sigs script
function remove_script () {
echo ""
if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
echo "use '$pkg_rm' to remove the script and all of its associated files and databases from the system."
else
cron_file_full_path="$cron_dir/$cron_filename"
logrotate_file_full_path="$logrotate_dir/$logrotate_filename"
man_file_full_path="$man_dir/$man_filename"
echo "This will remove the workdir ($work_dir), logrotate file ($logrotate_file_full_path), cron file ($cron_file_full_path), man file ($man_file_full_path)"
echo "Are you sure you want to remove the clamav-unofficial-sigs script and all of its associated files, third-party databases, and work directory from the system?"
if xshok_prompt_confirm ; then
echo "This can not be undone are you sure ?"
if xshok_prompt_confirm ; then
if [ -r "$work_dir_work_configs/purge.txt" ] ; then
while read -r file ; do
xshok_is_file "$file" && rm -f -- "$file"
echo " Removed file: $file"
done < "$work_dir_work_configs"/purge.txt
if [ -r "$cron_file_full_path" ] ; then
xshok_is_file "$cron_file_full_path" && rm -f "$cron_file_full_path"
echo " Removed file: $cron_file_full_path"
fi
if [ -r "$logrotate_file_full_path" ] ; then
xshok_is_file "$logrotate_file_full_path" && rm -f "$logrotate_file_full_path"
echo " Removed file: $logrotate_file_full_path"
fi
if [ -r "$man_file_full_path" ] ; then
xshok_is_file "$man_file_full_path" && rm -f "$man_file_full_path"
echo " Removed file: $man_file_full_path"
fi
# Rather keep the configs
#rm -f -- "$default_config" && echo " Removed file: $default_config"
#rm -f -- "$0" && echo " Removed file: $0"
xshok_is_subdir "$work_dir" && rm -rf -- "${work_dir:?}" && echo " Removed script working directories: $work_dir"
echo " The clamav-unofficial-sigs script and all of its associated files, third-party"
echo " databases, and work directories have been successfully removed from the system."
else
echo " Cannot locate 'purge.txt' file in $work_dir_work_configs."
echo " Files and signature database will need to be removed manually."
fi
else
echo "Aborted"
fi
else
echo "Aborted"
fi
fi
}
# Clamscan integrity test a specific database file
function clamscan_integrity_test_specific_database_file () { # databasefile
echo ""
if [ "$1" ] ; then
input="$(echo "$1" | awk -F "/" '{print $NF}')"
db_file="$(find "$work_dir" -name "$input")"
if [ -r "$db_file" ] ; then
echo "Clamscan integrity testing: $db_file"
$clamscan_bin --quiet -d "$db_file" "$work_dir_work_configs/scan-test.txt"
if [ $? -eq 0 ]; then
echo "Clamscan reports that '$input' database integrity tested GOOD"
exit 0
else
echo "Clamscan reports that '$input' database integrity tested BAD"
exit 1
fi
else
echo "File '$input' cannot be found."
echo "Here is a list of third-party databases that can be clamscan integrity tested:"
echo "=== Sanesecurity ==="
ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_sanesecurity"
echo "=== SecuriteInfo ==="
ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_securiteinfo"
echo "=== MalwarePatrol ==="
ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_malwarepatrol"
echo "=== Linux Malware Detect ==="
ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_linuxmalwaredetect"
echo "=== Linux Malware Detect ==="
ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_yararulesproject"
echo "=== User Defined Databases ==="
ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_add"
echo "Check the file name and try again..."
fi
else
xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
exit 1
fi
}
# Output names of any third-party signatures that triggered during the HAM directory scan
function output_signatures_triggered_during_ham_directory_scan () {
echo ""
if [ -n "$ham_dir" ] ; then
if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
echo "The following third-party signatures triggered hits during the HAM Directory scan:"
$grep_bin -h -f "$work_dir_work_configs/whitelist.hex" "$work_dir"/*/*.ndb | cut -d ":" -f 1
else
echo "No third-party signatures have triggered hits during the HAM Directory scan."
fi
else
echo "Ham directory scanning is not currently enabled in the script's configuration file."
fi
}
# Adds a signature whitelist entry in the newer ClamAV IGN2 format
function add_signature_whitelist_entry () {
echo ""
echo "Input a third-party signature name that you wish to whitelist due to false-positives"
echo "and press enter (do not include '.UNOFFICIAL' in the signature name nor add quote"
echo "marks to the input string):"
read -r input
if [ -n "$input" ] ; then
cd "$clam_dbs" || exit
input="$(echo "$input" | tr -d "'" | tr -d '"')"
sig_full="$($grep_bin -H "$input" ./*.*db)"
sig_name="$(echo "$sig_full" | cut -d ":" -f 2)"
if [ -n "$sig_name" ] ; then
if ! $grep_bin "$sig_name" my-whitelist.ign2 > /dev/null 2>&1 ; then
cp -f my-whitelist.ign2 "$work_dir_work_configs" 2>/dev/null
echo "$sig_name" >> "$work_dir_work_configs/my-whitelist.ign2"
echo "$sig_full" >> "$work_dir_work_configs/tracker.txt"
if $clamscan_bin --quiet -d "$work_dir_work_configs/my-whitelist.ign2" "$work_dir_work_configs/scan-test.txt" ; then
if $rsync_bin -pcqt "$work_dir_work_configs/my-whitelist.ign2" "$clam_dbs" ; then
perms chown -f "$clam_user:$clam_group" my-whitelist.ign2
if [ ! -s "$work_dir_work_configs/monitor-ign.txt" ] ; then
# Create "monitor-ign.txt" file for clamscan database integrity testing.
echo "This is the monitor ignore file..." > "$work_dir_work_configs/monitor-ign.txt"
fi
perms chmod -f 0644 my-whitelist.ign2 "$work_dir_work_configs/monitor-ign.txt"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/local.ign"
fi
clamscan_reload_dbs
echo "Signature '$input' has been added to my-whitelist.ign2 and"
echo "all databases have been reloaded. The script will track any changes"
echo "to the offending signature and will automatically remove it if the"
echo "signature is modified or removed from the third-party database."
else
echo "Failed to successfully update my-whitelist.ign2 file - SKIPPING."
fi
else
echo "Clamscan reports my-whitelist.ign2 database integrity is bad - SKIPPING."
fi
else
echo "Signature '$input' already exists in my-whitelist.ign2 - no action taken."
fi
else
echo "Signature '$input' could not be found."
echo "This script will only create a whitelise entry in my-whitelist.ign2 for ClamAV"
echo "'UNOFFICIAL' third-Party signatures as found in the *.ndb *.hdb *.db databases."
fi
else
echo "No input detected - no action taken."
fi
}
# Clamscan reload database
function clamscan_reload_dbs () {
# Reload all clamd databases if updates detected and $reload_dbs" is set to "yes"
if [ "$reload_dbs" == "yes" ] ; then
if [ "$do_clamd_reload" != "0" ] ; then
if [ "$do_clamd_reload" == "1" ] ; then
xshok_pretty_echo_and_log "Update(s) detected, reloading ClamAV databases" "="
elif [ "$do_clamd_reload" == "2" ] ; then
xshok_pretty_echo_and_log "Database removal(s) detected, reloading ClamAV databases" "="
elif [ "$do_clamd_reload" == "3" ] ; then
xshok_pretty_echo_and_log "File 'local.ign' has changed, reloading ClamAV databases" "="
elif [ "$do_clamd_reload" == "4" ] ; then
xshok_pretty_echo_and_log "File 'my-whitelist.ign2' has changed, reloading ClamAV databases" "="
else
xshok_pretty_echo_and_log "Update(s) detected, reloading ClamAV databases" "="
fi
if [[ "$($clamd_reload_opt 2>&1)" = *"ERROR"* ]] ; then
xshok_pretty_echo_and_log "ERROR: Failed to reload, trying again" "-"
if [ -r "$clamd_pid" ] ; then
mypid="$(cat "$clamd_pid")"
kill -USR2 "$mypid"
if [ $? -eq 0 ] ; then
xshok_pretty_echo_and_log "ClamAV databases Reloaded" "="
else
xshok_pretty_echo_and_log "ERROR: Failed to reload, forcing clamd to restart" "-"
if [ -z "$clamd_restart_opt" ] ; then
xshok_pretty_echo_and_log "WARNING: Check the script's configuration file, 'reload_dbs' enabled but no 'clamd_restart_opt'" "*"
else
$clamd_restart_opt > /dev/null
if [ $? -eq 0 ] ; then
xshok_pretty_echo_and_log "ClamAV Restarted" "="
else
xshok_pretty_echo_and_log "ClamAV NOT Restarted" "-"
fi
fi
fi
else
xshok_pretty_echo_and_log "ERROR: Failed to reload, forcing clamd to restart" "-"
if [ -z "$clamd_restart_opt" ] ; then
xshok_pretty_echo_and_log "WARNING: Check the script's configuration file, 'reload_dbs' enabled but no 'clamd_restart_opt'" "*"
else
$clamd_restart_opt > /dev/null
if [ $? -eq 0 ] ; then
xshok_pretty_echo_and_log "ClamAV Restarted" "="
else
xshok_pretty_echo_and_log "ClamAV NOT Restarted" "-"
fi
fi
fi
else
xshok_pretty_echo_and_log "ClamAV databases Reloaded" "="
fi
else
xshok_pretty_echo_and_log "No updates detected, ClamAV databases were not reloaded" "="
fi
else
xshok_pretty_echo_and_log "Database reload has been disabled in the configuration file" "="
fi
}
# If ClamD status check is enabled ("clamd_socket" variable is uncommented
# and the socket path is correctly specified in "User Edit" section above),
# then test to see if clamd is running or not.
function check_clamav () {
if [ -n "$clamd_socket" ] ; then
if [ -S "$clamd_socket" ] ; then
if [ "$(perl -e 'use IO::Socket::UNIX; print $IO::Socket::UNIX::VERSION,"\n"' 2>/dev/null)" ] ; then
io_socket1="1"
if [ "$(perl -MIO::Socket::UNIX -we '$s = IO::Socket::UNIX->new(shift); $s->print("PING"); print $s->getline; $s->close' "$clamd_socket" 2>/dev/null)" == "PONG" ] ; then
io_socket2="1"
xshok_pretty_echo_and_log "ClamD is running" "="
fi
else
socat="$(which socat 2>/dev/null)"
if [ -n "$socat" ] && [ -x "$socat" ] ; then
socket_cat1="1"
if [ "$( (echo "PING"; sleep 1;) | socat - "$clamd_socket" 2>/dev/null)" == "PONG" ] ; then
socket_cat2="1"
xshok_pretty_echo_and_log "ClamD is running" "="
fi
fi
fi
if [ -z "$io_socket1" ] && [ -z "$socket_cat1" ] ; then
xshok_pretty_echo_and_log "WARNING: socat or perl module 'IO::Socket::UNIX' not found, cannot test if ClamD is running" "*"
else
if [ -z "$io_socket2" ] && [ -z "$socket_cat2" ] ; then
xshok_pretty_echo_and_log "ALERT: CLAMD IS NOT RUNNING!" "="
if [ -n "$clamd_restart_opt" ] ; then
xshok_pretty_echo_and_log "Attempting to start ClamD..." "-"
if [ -n "$io_socket1" ] ; then
$clamd_restart_opt > /dev/null && sleep 5
if [ "$(perl -MIO::Socket::UNIX -we '$s = IO::Socket::UNIX->new(shift); $s->print("PING"); print $s->getline; $s->close' "$clamd_socket" 2>/dev/null)" = "PONG" ] ; then
xshok_pretty_echo_and_log "ClamD was successfully started" "="
else
xshok_pretty_echo_and_log "ERROR: CLAMD FAILED TO START" "="
exit 1
fi
else
if [ -n "$socket_cat1" ] ; then
$clamd_restart_opt > /dev/null && sleep 5
if [ "$( (echo "PING"; sleep 1;) | socat - "$clamd_socket" 2>/dev/null)" == "PONG" ] ; then
xshok_pretty_echo_and_log "ClamD was successfully started" "="
else
xshok_pretty_echo_and_log "ERROR: CLAMD FAILED TO START" "="
exit 1
fi
fi
fi
fi
fi
fi
else
xshok_pretty_echo_and_log "WARNING: $clamd_socket is not a usable socket" "*"
fi
else
xshok_pretty_echo_and_log "WARNING: clamd_socket is not defined in the configuration file" "*"
fi
}
# Check for a new version
function check_new_version () {
if [ -n "$wget_bin" ] ; then
# shellcheck disable=SC2086
latest_version="$($wget_bin $wget_proxy_https $wget_proxy_http $wget_insecure $wget_output_level --connect-timeout="$downloader_connect_timeout" --random-wait --tries="$downloader_tries" --timeout="$downloader_max_time" https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/clamav-unofficial-sigs.sh -O - 2> /dev/null | $grep_bin "script""_version=" | cut -d '"' -f 2)"
else
# shellcheck disable=SC2086
latest_version="$($curl_bin $curl_proxy $curl_insecure $curl_output_level --connect-timeout "$downloader_connect_timeout" --remote-time --location --retry "$downloader_tries" --max-time "$downloader_max_time" https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/clamav-unofficial-sigs.sh 2> /dev/null | $grep_bin "script""_version=" | cut -d '"' -f 2)"
fi
if [ "$latest_version" ] ; then
if [ "$latest_version" != "$script_version" ] ; then
xshok_pretty_echo_and_log "New version : v$latest_version @ https://github.com/extremeshok/clamav-unofficial-sigs" "-"
fi
fi
}
# Check for a new version
function check_new_config_version () {
if [ -n "$wget_bin" ] ; then
# shellcheck disable=SC2086
latest_config_version="$($wget_bin $wget_proxy_https $wget_proxy_http $wget_insecure $wget_output_level --connect-timeout="$downloader_connect_timeout" --random-wait --tries="$downloader_tries" --timeout="$downloader_max_time" https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/config/master.conf -O - 2> /dev/null | $grep_bin "config_version=" | cut -d '"' -f 2)"
else
# shellcheck disable=SC2086
latest_config_version="$($curl_bin $curl_proxy $curl_insecure $curl_output_level --connect-timeout "$downloader_connect_timeout" --remote-time --location --retry "$downloader_tries" --max-time "$downloader_max_time" https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/config/master.conf 2> /dev/null | $grep_bin "config_version=" | cut -d '"' -f 2)"
fi
if [ "$latest_config_version" ] ; then
if [ "$latest_config_version" != "$config_version" ] ; then
xshok_pretty_echo_and_log "New configversion : v${latest_config_version} @ https://github.com/extremeshok/clamav-unofficial-sigs" "-"
fi
fi
}
# Display help and usage
# Usage:
# help_and_usage "1" - enables the man output formatting
# help_and_usage - normal help output formatting
function help_and_usage () {
if [ "$1" ] ; then
# option_format_start
ofs="\fB"
# option_format_end
ofe="\fR"
# option_format_blankline
ofb=".TP"
# option_format_tab_line
oft=" "
else
# option_format_start
ofs="${BOLD}"
# option_format_end
ofe="${NORM}\t"
# option_format_blankline
ofb="\n"
# option_format_tab_line
oft="\n\t"
fi
helpcontents="$(cat << EOF
$ofs Usage: $(basename "$0") $ofe [OPTION] [PATH|FILE]
$ofb
$ofs -c, --config $ofe Use a specific configuration file or directory $oft eg: '-c /your/dir' or ' -c /your/file.name' $oft Note: If a directory is specified the directory must contain atleast: $oft master.conf, os.conf or user.conf $oft Default Directory: $config_dir
$ofb
$ofs -F, --force $ofe Force all databases to be downloaded, could cause ip to be blocked
$ofb
$ofs -h, --help $ofe Display this script's help and usage information
$ofb
$ofs -V, --version $ofe Output script version and date information
$ofb
$ofs -v, --verbose $ofe Be verbose, enabled when not run under cron
$ofb
$ofs -s, --silence $ofe Only output error messages, enabled when run under cron
$ofb
$ofs -d, --decode-sig $ofe Decode a third-party signature either by signature name $oft (eg: Sanesecurity.Junk.15248) or hexadecimal string. $oft This flag will 'NOT' decode image signatures
$ofb
$ofs -e, --encode-string $ofe Hexadecimal encode an entire input string that can $oft be used in any '*.ndb' signature database file
$ofb
$ofs -f, --encode-formatted $ofe Hexadecimal encode a formatted input string containing $oft signature spacing fields '{}, (), *', without encoding $oft the spacing fields, so that the encoded signature $oft can be used in any '*.ndb' signature database file
$ofb
$ofs -g, --gpg-verify $ofe GPG verify a specific Sanesecurity database file $oft eg: '-g filename.ext' (do not include file path)
$ofb
$ofs -i, --information $ofe Output system and configuration information for $oft viewing or possible debugging purposes
$ofb
$ofs -m, --make-database $ofe Make a signature database from an ascii file containing $oft data strings, with one data string per line. Additional $oft information is provided when using this flag
$ofb
$ofs -t, --test-database $ofe Clamscan integrity test a specific database file $oft eg: '-t filename.ext' (do not include file path)
$ofb
$ofs -o, --output-triggered $ofe If HAM directory scanning is enabled in the script's $oft configuration file, then output names of any third-party $oft signatures that triggered during the HAM directory scan
$ofb
$ofs -w, --whitelist $ofe Adds a signature whitelist entry in the newer ClamAV IGN2 $oft format to 'my-whitelist.ign2' in order to temporarily resolve $oft a false-positive issue with a specific third-party signature. $oft Script added whitelist entries will automatically be removed $oft if the original signature is either modified or removed from $oft the third-party signature database
$ofb
$ofs --check-clamav $ofe If ClamD status check is enabled and the socket path is correctly $oft specifiedthen test to see if clamd is running or not
$ofb
$ofs --install-all $ofe Install and generate the cron, logroate and man files, autodetects the values $oft based on your config files
$ofb
$ofs --install-cron $ofe Install and generate the cron file, autodetects the values $oft based on your config files
$ofb
$ofs --install-logrotate $ofe Install and generate the logrotate file, autodetects the $oft values based on your config files
$ofb
$ofs --install-man $ofe Install and generate the man file, autodetects the $oft values based on your config files
$ofb
$ofs --remove-script $ofe Remove the clamav-unofficial-sigs script and all of $oft its associated files and databases from the system
$ofb
EOF
)" # This is very important
if [ "$1" ] ; then
echo "${helpcontents//-/\\-}"
else
echo -e "$helpcontents"
fi
}
################################################################################
# MAIN PROGRAM
################################################################################
# Script Info
script_version="5.6.2"
script_version_date="2017-03-19"
minimum_required_config_version="72"
minimum_yara_clamav_version="0.99"
# Default config files
config_dir="/var/packages/MailPlus-Server/target/etc/clamav-unofficial-sigs"
config_files=( "$config_dir/master.conf" "$config_dir/os.conf" "$config_dir/user.conf" )
# Initialise
config_version="0"
do_clamd_reload="0"
comment_silence="no"
logging_enabled="no"
force_updates="no"
enable_log="no"
custom_config="no"
we_have_a_config="0"
# Solaris which function returns garbage when the program is not found
# only define the new which function if running under Solaris
if [ "$(uname -s)" == "SunOS" ] ; then
which () {
# Use the switch -p to ignore ksh internal commands
ksh whence -p "$@"
}
fi
# Default Binaries & Commands
uname_bin="$(which uname 2> /dev/null)"
clamscan_bin="$(which clamscan 2> /dev/null)"
rsync_bin="$(which rsync 2> /dev/null)"
# Detect support for wget
if [ -x /usr/sfw/bin/wget ] ; then
wget_bin="/usr/sfw/bin/wget"
else
wget_bin="$(which wget 2> /dev/null)"
fi
if [ -z "$wget_bin" ] ; then
curl_bin="$(which curl 2> /dev/null)"
if [ -z "$curl_bin" ] ; then
xshok_pretty_echo_and_log "ERROR: both wget and curl commands are missing, One of them is required" "="
exit 1
fi
fi
# Detect supprot for gnu grep
if [ -x /usr/gnu/bin/grep ] ; then
grep_bin="/usr/gnu/bin/grep"
else
grep_bin="$(which grep 2> /dev/null)"
fi
nslookup_bin="$(which nslookup 2> /dev/null)"
if [ -z "$nslookup_bin" ]; then
xshok_pretty_echo_and_log "ERROR: nslookup command is missing, it is required" "="
exit 1
fi
# dig_bin="$(which dig 2> /dev/null)"
# if [ -z "$dig_bin" ] ; then
# host_bin="$(which host 2> /dev/null)"
# if [ -z "$host_bin" ] ; then
# xshok_pretty_echo_and_log "ERROR: both dig and host commands are missing, One of them is required" "="
# exit 1
# fi
# fi
# Detect if terminal
# if [ -t 1 ] ; then
# # Set fonts
# # Usage: echo "${BOLD}-a${NORM}"
# BOLD="$(tput bold)"
# #REV=$(tput smso)
# NORM="$(tput sgr0)"
# # Verbose
# force_verbose="yes"
# else
# Null fonts
BOLD=""
#REV=""
NORM=""
# Silence
force_verbose="no"
# fi
# Generic command line options
while true ; do
case "$1" in
-c|--config) xshok_check_s2 "$2"; custom_config="$2"; shift 2; break ;;
-F|--force) force_updates="yes"; shift 1; break ;;
-v|--verbose) force_verbose="yes"; shift 1; break ;;
-s|--silence) force_verbose="no"; shift 1; break ;;
*) break ;;
esac
done
# Set the verbosity
if [ "$force_verbose" == "yes" ] ; then
# Verbose
downloader_silence="no"
rsync_silence="no"
gpg_silence="no"
comment_silence="no"
else
# Silence
downloader_silence="yes"
rsync_silence="yes"
gpg_silence="yes"
comment_silence="yes"
fi
xshok_pretty_echo_and_log "" "#" "80"
xshok_pretty_echo_and_log " eXtremeSHOK.com ClamAV Unofficial Signature Updater"
xshok_pretty_echo_and_log " Version: v$script_version ($script_version_date)"
xshok_pretty_echo_and_log " Required Configuration Version: v$minimum_required_config_version"
xshok_pretty_echo_and_log " Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com"
xshok_pretty_echo_and_log "" "#" "80"
# Generic command line options
while true ; do
case "$1" in
-h|--help) help_and_usage; exit ;;
-V|--version) exit ;;
*) break ;;
esac
done
# CONFIG LOADING AND ERROR CHECKING ##############################################
if [ "$custom_config" != "no" ] ; then
if [ -d "$custom_config" ] ; then
# Assign the custom config dir and remove trailing / (removes / and //)
shopt -s extglob; custom_config="${custom_config%%+(/)}"
config_files=( "$config_dir/master.conf" "$config_dir/os.conf" "$config_dir/user.conf" )
else
config_files=( "$custom_config" )
fi
fi
for config_file in "${config_files[@]}" ; do
if [ -r "$config_file" ] ; then # Exists and readable
we_have_a_config="1"
# Config stripping
xshok_pretty_echo_and_log "Loading config: $config_file" "="
if [ "$(uname -s)" == "SunOS" ] ; then
# Solaris FIXES only, i had issues with running with a single command..
clean_config="$(command sed -e '/^#.*/d' "$config_file")" # Comment line
#clean_config="$(echo "$clean_config" | sed -e 's/#[[:space:]].*//')" # Comment line (duplicated)
clean_config=${clean_config//\#*/} # Comment line (duplicated)
clean_config="$(echo "$clean_config" | sed -e '/^[[:blank:]]*#/d;s/#.*//')" # Comments at end of line
#clean_config="$(echo "$clean_config" | sed -e 's/^[ \t]*//;s/[ \t]*$//')" # trailing and leading whitespace
clean_config="$(echo "$clean_config" | xargs)"
clean_config="$(echo "$clean_config" | sed -e '/^\s*$/d')" # Blank lines
elif [ "$(uname -s)" == "Darwin" ] ; then
# MacOS / OS X fixes, had issues with running with a single command and with SunOS work around..
clean_config="$(command sed -e '/^#.*/d' "$config_file")" # Comment line
clean_config="$(echo "$clean_config" | sed -e 's/#[[:space:]].*//')" # Comment line (duplicated)
clean_config="$(echo "$clean_config" | sed -e '/^[[:blank:]]*#/d;s/#.*//')" # Comments at end of line
#clean_config="$(echo "$clean_config" | sed -e 's/^[ \t]*//;s/[ \t]*$//')" # trailing and leading whitespace
#clean_config="$(echo "$clean_config" | xargs)"
clean_config="$(echo "$clean_config" | sed -e '/^\s*$/d')" # Blank lines
else
# Delete lines beginning with #
# Delete from " #" to end of the line
# Delete from "# " to end of the line
# Delete both trailing and leading whitespace
# Delete all trailing whitespace
# Delete all empty lines
clean_config="$(command sed -e '/^#.*/d' -e 's/[[:space:]]#.*//' -e 's/#[[:space:]].*//' -e 's/^[ \t]*//;s/[ \t]*$//' -e '/^\s*$/d' "$config_file")"
fi
#fix eval of |
clean_config="${clean_config//|/\\|}"
# Config error checking
# Check "" are an even number
config_check="${clean_config//[^\"]}"
if [ "$(( ${#config_check} % 2 ))" -eq 1 ] ; then
xshok_pretty_echo_and_log "ERROR: Your configuration has errors, every \" requires a closing \"" "="
exit 1
fi
# Check there is an = for every set of "" optional whitespace \s* between = and "
config_check_vars="$(echo "$clean_config" | $grep_bin -c '=\s*\"' )"
if [ $(( ${#config_check} / 2 )) -ne "$config_check_vars" ] ; then
xshok_pretty_echo_and_log "ERROR: Your configuration has errors, every = requires a pair of \"\"" "="
exit 1
fi
# backslash pipe
#clean_config="${clean_config//|/\|}"
# Config loading
for i in "${clean_config[@]}" ; do
eval "$(echo "${i}" | command sed -e 's/[[:space:]]*$//' 2> /dev/null)"
done
fi
done
# Assign the log_file_path earlier and remove trailing / (removes / and //)
shopt -s extglob; log_file_path="${log_file_path%%+(/)}"
# Only start logging once all the configs have been loaded
if [ "$logging_enabled" == "yes" ] ; then
enable_log="yes"
fi
# Make sure we have a readable config file
if [ "$we_have_a_config" == "0" ] ; then
xshok_pretty_echo_and_log "ERROR: Config file/s could NOT be read/loaded" "="
xshok_pretty_echo_and_log "Note: Possible fix would be to checkl the config dir $config_dir exists and contains config files"
exit 1
fi
# Prevent some issues with an incomplete or only a user.conf being loaded
if [ "$config_version" == "0" ] ; then
xshok_pretty_echo_and_log "ERROR: Config file/s are missing important contents" "="
xshok_pretty_echo_and_log "Note: Possible fix would be to point the script to the dir with the configs"
exit 1
fi
# Config version validation
if [ "$config_version" -lt "$minimum_required_config_version" ] ; then
xshok_pretty_echo_and_log "ERROR: Your config version $config_version is not compatible with the min required version $minimum_required_config_version" "="
exit 1
fi
# Check to see if the script's "USER CONFIGURATION FILE" has been completed.
if [ "$user_configuration_complete" != "yes" ] ; then
xshok_pretty_echo_and_log "WARNING: SCRIPT CONFIGURATION HAS NOT BEEN COMPLETED" "*"
xshok_pretty_echo_and_log "Please review the script configuration files"
xshok_pretty_echo_and_log "and uncomment the following line in user.conf"
xshok_pretty_echo_and_log "#user_configuration_complete=\"yes\""
exit 1
fi
# Assign the directories and remove trailing / (removes / and //)
shopt -s extglob; work_dir="${work_dir%%+(/)}"
# Allow overriding of all the individual workdirs, this is mainly to aid package maintainers
if [ -z "$work_dir_sanesecurity" ] ; then
work_dir_sanesecurity="$(echo "$work_dir/$sanesecurity_dir" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_sanesecurity="${work_dir_sanesecurity%%+(/)}"
fi
if [ -z "$work_dir_securiteinfo" ] ; then
work_dir_securiteinfo="$(echo "$work_dir/$securiteinfo_dir" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_securiteinfo="${work_dir_securiteinfo%%+(/)}"
fi
if [ -z "$work_dir_linuxmalwaredetect" ] ; then
work_dir_linuxmalwaredetect="$(echo "$work_dir/$linuxmalwaredetect_dir" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_malwarepatrol="${work_dir_malwarepatrol%%+(/)}"
fi
if [ -z "$work_dir_malwarepatrol" ] ; then
work_dir_malwarepatrol="$(echo "$work_dir/$malwarepatrol_dir" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_malwarepatrol="${work_dir_malwarepatrol%%+(/)}"
fi
if [ -z "$work_dir_yararulesproject" ] ; then
work_dir_yararulesproject="$(echo "$work_dir/$yararulesproject_dir" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_yararulesproject="${work_dir_yararulesproject%%+(/)}"
fi
if [ -z "$work_dir_add" ] ; then
work_dir_add="$(echo "$work_dir/$add_dir" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_add="${work_dir_add%%+(/)}"
fi
if [ -z "$work_dir_work_configs" ] ; then
work_dir_work_configs="$(echo "$work_dir/$work_dir_configs" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_work_configs="${work_dir_work_configs%%+(/)}"
fi
if [ -z "$work_dir_gpg" ] ; then
work_dir_gpg="$(echo "$work_dir/$gpg_dir" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_gpg="${work_dir_gpg%%+(/)}"
fi
if [ -z "$work_dir_pid" ] ; then
work_dir_pid="$(echo "$work_dir/$pid_dir" | sed 's:/*$::')"
else
shopt -s extglob; work_dir_pid="${work_dir_pid%%+(/)}"
fi
# Assign defaults if not defined
if [ -z "$cron_dir" ] ; then
cron_dir="/etc/cron.d"
fi
shopt -s extglob; cron_dir="${cron_dir%%+(/)}"
if [ -z "$cron_filename" ] ; then
cron_filename="clamav-unofficial-sigs"
fi
if [ -z "$logrotate_dir" ] ; then
logrotate_dir="/etc/logrotate.d"
fi
shopt -s extglob; logrotate_dir="${logrotate_dir%%+(/)}"
if [ -z "$logrotate_filename" ] ; then
logrotate_filename="clamav-unofficial-sigs"
fi
if [ -z "$man_dir" ] ; then
man_dir="/usr/share/man/man8"
fi
shopt -s extglob; man_dir="${man_dir%%+(/)}"
if [ -z "$man_filename" ] ; then
man_filename="clamav-unofficial-sigs.8"
fi
if [ -z "$man_log_file_full_path" ] ; then
man_log_file_full_path="$log_file_path/$log_file_name"
fi
# dont assign , but remove trailing /
shopt -s extglob; clam_dbs="${clam_dbs%%+(/)}"
# SANITY checks
# Check default Binaries & Commands are defined
if [ "$reload_dbs" == "yes" ] ; then
if [ -z "$clamd_reload_opt" ] ; then
xshok_pretty_echo_and_log "ERROR: Missing clamd_reload_opt" "="
exit 1
fi
fi
if [ -z "$uname_bin" ] ; then
xshok_pretty_echo_and_log "ERROR: uname (uname_bin) not found" "="
exit 1
fi
if [ -z "$clamscan_bin" ] ; then
xshok_pretty_echo_and_log "ERROR: clamscan binary (clamscan_bin) not found" "="
exit 1
fi
if [ -z "$rsync_bin" ] ; then
xshok_pretty_echo_and_log "ERROR: rsync binary (rsync_bin) not found" "="
exit 1
fi
if [ -z "$wget_bin" ] ; then
if [ -z "$curl_bin" ] ; then
xshok_pretty_echo_and_log "ERROR: wget and curl binaries not found, script requires either wget or curl" "="
exit 1
fi
fi
# Check if GPG is enabled and the binary is found
if [ "$enable_gpg" == "yes" ] ; then
if [ -z "$gpg_bin" ] ; then
if [ -x /opt/csw/bin/gpg ] ; then
gpg_bin="/opt/csw/bin/gpg"
else
gpg_bin="$(which gpg 2> /dev/null)"
fi
if [ -z "$gpg_bin" ] ; then
gpg_bin="$(which gpg2 2> /dev/null)"
fi
fi
if [ -z "$gpg_bin" ] ; then
enable_gpg="no"
fi
if [ ! -x "$gpg_bin" ] ; then
enable_gpg="no"
fi
fi
if [ "$enable_gpg" != "yes" ] ; then
xshok_pretty_echo_and_log "Notice: GnuPG / signature verification disabled" "-"
fi
# Check default directories are defined
if [ -z "$work_dir" ] ; then
xshok_pretty_echo_and_log "ERROR: working directory (work_dir) not defined" "="
exit 1
fi
if [ -z "$clam_dbs" ] ; then
xshok_pretty_echo_and_log "ERROR: clam database directory (clam_dbs) not defined" "="
exit 1
fi
# Check default directories are writable
if [ -e "$work_dir" ] ; then
if [ ! -w "$work_dir" ] ; then
xshok_pretty_echo_and_log "ERROR: working directory (work_dir) not writable $work_dir" "="
exit 1
fi
fi
if [ ! -w "$clam_dbs" ] ; then
xshok_pretty_echo_and_log "ERROR: clam database directory (clam_dbs) not writable $clam_dbs" "="
exit 1
fi
# Reset the update timers to force a full update.
if [ "$force_updates" == "yes" ] ; then
xshok_pretty_echo_and_log "Force Updates: enabled"
sanesecurity_update_hours="0"
securiteinfo_update_hours="0"
linuxmalwaredetect_update_hours="0"
malwarepatrol_update_hours="0"
yararulesproject_update_hours="0"
additional_update_hours="0"
fi
# Enable pid file to prevent issues with multiple instances
# opted not to use flock as it appears to have issues with some systems
if [ "$enable_locking" == "yes" ] ; then
xshok_mkdir_ownership "$work_dir_pid"
pid_file_fullpath="$work_dir_pid/clamav-unofficial-sigs.pid"
if [ -f "$pid_file_fullpath" ] ; then
pid_file_pid="$(cat "$pid_file_fullpath")"
ps -p "$pid_file_pid" > /dev/null 2>&1
if [ $? -eq 0 ] ; then
xshok_pretty_echo_and_log "ERROR: Only one instance can run at the same time." "="
exit 1
else
xshok_create_pid_file "$pid_file_fullpath"
fi
else
xshok_create_pid_file "$pid_file_fullpath"
fi
# Run this wehen the script exits
trap -- "rm -f $pid_file_fullpath" EXIT
fi
# Verify the clam_user and clam_group actually exists on the system
if ! xshok_user_group_exists "$clam_user" "$clam_group" ; then
xshok_pretty_echo_and_log "ERROR: Either the user: $clam_user and/or group: $clam_group does not exist on the system." "="
exit 1
fi
# Silence rsync output and only report errors - useful if script is run via cron.
if [ "$rsync_silence" == "yes" ] ; then
rsync_output_level="--quiet"
else
rsync_output_level="--progress"
fi
# If the local rsync client supports the "--no-motd" flag, then enable it.
if $rsync_bin --help | $grep_bin -q "no-motd" > /dev/null ; then
no_motd="--no-motd"
fi
# If the local rsync client supports the "--contimeout" flag, then enable it.
if $rsync_bin --help | $grep_bin -q "contimeout" > /dev/null ; then
connect_timeout="--contimeout=$rsync_connect_timeout"
fi
# Silence wget output and only report errors - useful if script is run via cron.
if [ "$downloader_silence" == "yes" ] ; then
wget_output_level="--quiet" #--quiet
curl_output_level="--silent --show-error"
else
wget_output_level="--no-verbose"
curl_output_level=""
fi
# Suppress ssl warnings
if [ "$downloader_ignore_ssl" == "yes" ] ; then
wget_insecure="--no-check-certificate"
curl_insecure="--insecure"
else
wget_insecure=""
curl_insecure=""
fi
# This scripts name and path
this_script_name="$(basename "$0")"
this_script_path="$( cd "$(dirname "$0")" || exit ; pwd -P )"
this_script_full_path="$this_script_path/$this_script_name"
# Set the script to 755 permissions
if xshok_is_root ; then
if [ "$setmode" == "yes" ] ; then
if [ ! -x "$this_script_path/$this_script_name" ] ; then
chmod 755 "$this_script_path/$this_script_name"
xshok_pretty_echo_and_log "Fixing permission on $this_script_path/$this_script_name" "="
fi
fi
else
# Disable setmode
setmode="no"
fi
################################################################################
# MAIN LOGIC
################################################################################
while true; do
case "$1" in
-d|--decode-sig) decode_third_party_signature_by_signature_name; exit ;;
-e|--encode-string) hexadecimal_encode_entire_input_string; exit ;;
-f|--encode-formatted) hexadecimal_encode_formatted_input_string; exit ;;
-g|--gpg-verify) xshok_check_s2 "$2"; gpg_verify_specific_sanesecurity_database_file "$2"; exit ;;
-i|--information) output_system_configuration_information; exit ;;
-m|--make-database) make_signature_database_from_ascii_file; exit ;;
-t|--test-database) xshok_check_s2 "$2"; clamscan_integrity_test_specific_database_file "$2"; exit ;;
-o|--output-triggered) output_signatures_triggered_during_ham_directory_scan; exit ;;
-w|--whitelist) add_signature_whitelist_entry; exit ;;
--check-clamav) check_clamav; exit ;;
--install-all) install_cron; install_logrotate; install_man; exit ;;
--install-cron) install_cron; exit ;;
--install-logrotate) install_logrotate; exit ;;
--install-man) install_man; exit ;;
--remove-script) remove_script; exit ;;
*) break ;;
esac
done
xshok_pretty_echo_and_log "Preparing Databases" "="
# Check yararule support is available
if [ "$enable_yararules" == "yes" ] ; then
current_clamav_version="$($clamscan_bin -V | cut -d " " -f 2 | cut -d "/" -f 1 | awk -F "." '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }')"
minimum_yara_clamav_version="$(echo "$minimum_yara_clamav_version" | awk -F "." '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }')"
# Check current clamav version against the minimum required version for yara support
if [ "$current_clamav_version" -le "$minimum_yara_clamav_version" ] ; then # Older
yararulesproject_enabled="no"
enable_yararules="no"
xshok_pretty_echo_and_log "Notice: Yararules Disabled due to clamav being older than the minimum required version"
fi
else
yararulesproject_enabled="no"
enable_yararules="no"
fi
# Generate the signature databases
if [ "$sanesecurity_enabled" == "yes" ] ; then
if [ -n "$sanesecurity_dbs" ] ; then
if [ -n "$sanesecurity_dbs_rating" ] ; then
temp_db="$(xshok_database "$sanesecurity_dbs_rating" "${sanesecurity_dbs[@]}")"
else
temp_db="$(xshok_database "$default_dbs_rating" "${sanesecurity_dbs[@]}")"
fi
sanesecurity_dbs=( )
sanesecurity_dbs=( $temp_db )
fi
fi
if [ "$securiteinfo_enabled" == "yes" ] ; then
if [ -n "$securiteinfo_dbs" ] ; then
if [ -n "$securiteinfo_dbs_rating" ] ; then
temp_db="$(xshok_database "$securiteinfo_dbs_rating" "${securiteinfo_dbs[@]}")"
else
temp_db="$(xshok_database "$default_dbs_rating" "${securiteinfo_dbs[@]}")"
fi
securiteinfo_dbs=( )
securiteinfo_dbs=( $temp_db )
fi
fi
if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
if [ -n "$linuxmalwaredetect_dbs" ] ; then
if [ -n "$linuxmalwaredetect_dbs_rating" ] ; then
temp_db="$(xshok_database "$linuxmalwaredetect_dbs_rating" "${linuxmalwaredetect_dbs[@]}")"
else
temp_db="$(xshok_database "$default_dbs_rating" "${linuxmalwaredetect_dbs[@]}")"
fi
linuxmalwaredetect_dbs=( )
linuxmalwaredetect_dbs=( $temp_db )
fi
fi
if [ "$yararulesproject_enabled" == "yes" ] ; then
if [ -n "$yararulesproject_dbs" ] ; then
if [ -n "$yararulesproject_dbs_rating" ] ; then
temp_db="$(xshok_database "$yararulesproject_dbs_rating" "${yararulesproject_dbs[@]}")"
else
temp_db="$(xshok_database "$default_dbs_rating" "${yararulesproject_dbs[@]}")"
fi
yararulesproject_dbs=( )
yararulesproject_dbs=( $temp_db )
fi
fi
# Set the variables for MalwarePatrol
if [ "$malwarepatrol_free" == "yes" ] ; then
malwarepatrol_product_code="8"
malwarepatrol_list="clamav_basic"
else
if [ -z $malwarepatrol_list ] ; then
malwarepatrol_list="clamav_basic"
fi
if [ -z $malwarepatrol_product_code ] ; then
# Not sure, it may be better to return an error.
malwarepatrol_product_code=8
fi
fi
if [ $malwarepatrol_list == "clamav_basic" ] ; then
malwarepatrol_db="malwarepatrol.db"
else
malwarepatrol_db="malwarepatrol.ndb"
fi
malwarepatrol_url="$malwarepatrol_url?product=$malwarepatrol_product_code&list=$malwarepatrol_list"
# If "ham_dir" variable is set, then create initial whitelist files (skipped if first-time script run).
test_dir="$work_dir/test"
if [ -n "$ham_dir" ] && [ -d "$work_dir" ] && [ ! -d "$test_dir" ] ; then
if [ -d "$ham_dir" ] ; then
xshok_mkdir_ownership "$test_dir"
cp -f "$work_dir"/*/*.ndb "$test_dir"
$clamscan_bin --infected --no-summary -d "$test_dir" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' >> "$work_dir_work_configs/whitelist.txt"
$grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir"/* | cut -d "*" -f 2 | sort | uniq > "$work_dir_work_configs/whitelist.hex"
cd "$test_dir" || exit
for db_file in * ; do
[[ -e $db_file ]] || break # Handle the case of no files
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$db_file" > "$db_file-tmp"
mv -f "$db_file-tmp" "$db_file"
if $clamscan_bin --quiet -d "$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
if $rsync_bin -pcqt "$db_file" "$clam_dbs" ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
do_clamd_reload=1
fi
fi
done
if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
xshok_pretty_echo_and_log "Initial HAM directory scan whitelist file created in $work_dir_work_configs"
else
xshok_pretty_echo_and_log "No false-positives detected in initial HAM directory scan"
fi
else
xshok_pretty_echo_and_log "WARNING: Cannot locate HAM directory: $ham_dir"
xshok_pretty_echo_and_log "Skipping initial whitelist file creation. Fix 'ham_dir' path in config file"
fi
fi
# Check to see if the working directories have been created. If not, create them. Otherwise, ignore and proceed with script.
xshok_mkdir_ownership "$work_dir"
xshok_mkdir_ownership "$work_dir_securiteinfo"
xshok_mkdir_ownership "$work_dir_malwarepatrol"
xshok_mkdir_ownership "$work_dir_linuxmalwaredetect"
xshok_mkdir_ownership "$work_dir_sanesecurity"
xshok_mkdir_ownership "$work_dir_yararulesproject"
xshok_mkdir_ownership "$work_dir_work_configs"
xshok_mkdir_ownership "$work_dir_gpg"
xshok_mkdir_ownership "$work_dir_add"
# Set secured access permissions to the GPG directory
perms chmod -f 0700 "$work_dir_gpg"
if [ "$enable_gpg" == "yes" ] ; then
# If we haven't done so yet, download Sanesecurity public GPG key and import to custom keyring.
if [ ! -s "$work_dir_gpg/publickey.gpg" ] ; then
xshok_file_download "$work_dir_gpg/publickey.gpg" "$sanesecurity_gpg_url"
ret="$?"
if [ "$ret" -ne 0 ] ; then
xshok_pretty_echo_and_log "ALERT: Could not download Sanesecurity public GPG key" "*"
exit 1
else
xshok_pretty_echo_and_log "Sanesecurity public GPG key successfully downloaded"
rm -f -- "$work_dir_gpg/ss-keyring.gp*"
if ! $gpg_bin -q --no-options --no-default-keyring --homedir "$work_dir_gpg" --keyring "$work_dir_gpg/ss-keyring.gpg" --import "$work_dir_gpg/publickey.gpg" 2>/dev/null ; then
xshok_pretty_echo_and_log "ALERT: could not import Sanesecurity public GPG key to custom keyring" "*"
exit 1
else
chmod -f 0644 "$work_dir_gpg/*.*"
xshok_pretty_echo_and_log "Sanesecurity public GPG key successfully imported to custom keyring"
fi
fi
fi
# If custom keyring is missing, try to re-import Sanesecurity public GPG key.
if [ ! -s "$work_dir_gpg/ss-keyring.gpg" ] ; then
rm -f -- "$work_dir_gpg/ss-keyring.gp*"
if ! $gpg_bin -q --no-options --no-default-keyring --homedir "$work_dir_gpg" --keyring "$work_dir_gpg/ss-keyring.gpg" --import "$work_dir_gpg/publickey.gpg" 2>/dev/null ; then
xshok_pretty_echo_and_log "ALERT: Custom keyring MISSING or CORRUPT! Could not import Sanesecurity public GPG key to custom keyring" "*"
exit 1
else
chmod -f 0644 "$work_dir_gpg/*.*"
xshok_pretty_echo_and_log "Sanesecurity custom keyring MISSING! GPG key successfully re-imported to custom keyring"
fi
fi
fi
# Database update check, time randomization section. This script now
# provides support for both bash and non-bash enabled system shells.
if [ "$enable_random" == "yes" ] ; then
if [ -n "$RANDOM" ] ; then
sleep_time="$((RANDOM * $((max_sleep_time - min_sleep_time)) / 32767 + min_sleep_time))"
else
sleep_time="0"
while [ "$sleep_time" -lt "$min_sleep_time" ] || [ "$sleep_time" -gt "$max_sleep_time" ] ; do
sleep_time="$(head -n 1 /dev/urandom | cksum | awk '{print $2}')"
done
fi
if [ ! -t 0 ] ; then
xshok_pretty_echo_and_log "$(date) - Pausing database file updates for $sleep_time seconds..."
sleep "$sleep_time"
xshok_pretty_echo_and_log "$(date) - Pause complete, checking for new database files..."
fi
fi
# Create "scan-test.txt" file for clamscan database integrity testing.
if [ ! -s "$work_dir_work_configs/scan-test.txt" ] ; then
echo "This is the clamscan test file..." > "$work_dir_work_configs/scan-test.txt"
fi
# If rsync proxy is defined in the config file, then export it for use.
if [ -n "$rsync_proxy" ] ; then
RSYNC_PROXY="$rsync_proxy"
export RSYNC_PROXY
fi
# Create $current_dbsfiles containing lists of current and previously active 3rd-party databases
# so that databases and/or backup files that are no longer being used can be removed.
current_tmp="$work_dir_work_configs/current-dbs.tmp"
current_dbs_file="$work_dir_work_configs/current-dbs.txt"
if [ "$sanesecurity_enabled" == "yes" ] ; then
# Create the Sanesecurity rsync "include" file (defines which files to download).
sanesecurity_include_dbs="$work_dir_work_configs/ss-include-dbs.txt"
if [ -n "${sanesecurity_dbs[0]}" ] ; then
rm -f -- "$sanesecurity_include_dbs" "$work_dir_sanesecurity/*.sha256"
for db_file in "${sanesecurity_dbs[@]}" ; do
echo "$db_file" >> "$sanesecurity_include_dbs"
echo "$db_file.sig" >> "$sanesecurity_include_dbs"
echo "$work_dir_sanesecurity/$db_file" >> "$current_tmp"
echo "$work_dir_sanesecurity/$db_file.sig" >> "$current_tmp"
clamav_files
done
fi
fi
if [ "$securiteinfo_enabled" == "yes" ] ; then
if [ -n "${securiteinfo_dbs[0]}" ] ; then
for db in "${securiteinfo_dbs[@]}" ; do
echo "$work_dir_securiteinfo/$db" >> "$current_tmp"
clamav_files
done
fi
fi
if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
if [ -n "${linuxmalwaredetect_dbs[0]}" ] ; then
for db in "${linuxmalwaredetect_dbs[@]}" ; do
echo "$work_dir_linuxmalwaredetect/$db" >> "$current_tmp"
clamav_files
done
fi
fi
if [ "$malwarepatrol_enabled" == "yes" ] ; then
if [ -n "$malwarepatrol_db" ] ; then
echo "$work_dir_malwarepatrol/$malwarepatrol_db" >> "$current_tmp"
clamav_files
fi
fi
if [ "$yararulesproject_enabled" == "yes" ] ; then
if [ -n "${yararulesproject_dbs[0]}" ] ; then
for db in "${yararulesproject_dbs[@]}" ; do
if echo "$db" | $grep_bin -q "/"; then
db="$(echo "$db" | cut -d "/" -f 2)"
fi
echo "$work_dir_yararulesproject/$db" >> "$current_tmp"
clamav_files
done
fi
fi
if [ "$additional_enabled" == "yes" ] ; then
if [ -n "$additional_dbs" ] ; then
for db in "${additional_dbs[@]}" ; do
echo "$work_dir_add/$db" >> "$current_tmp"
clamav_files
done
fi
fi
sort "$current_tmp" > "$current_dbs_file" 2>/dev/null
rm -f "$current_tmp"
# Remove 3rd-party databases and/or backup files that are no longer being used.
if [ "$remove_disabled_databases" == "yes" ] ; then
previous_dbs="$work_dir_work_configs/previous-dbs.txt"
sort "$current_dbs_file" > "$previous_dbs" 2>/dev/null
# Do not remove the current_dbs_file
#rm -f "$current_dbs_file"
db_changes="$work_dir_work_configs/db-changes.txt"
if [ ! -s "$previous_dbs" ] ; then
cp -f "$current_dbs_file" "$previous_dbs" 2>/dev/null
fi
diff "$current_dbs_file" "$previous_dbs" 2>/dev/null | $grep_bin ">" | awk '{print $2}' > "$db_changes"
if [ -r "$db_changes" ] ; then
if $grep_bin -vq "bak" "$db_changes" 2>/dev/null ; then
do_clamd_reload="2"
fi
while read -r file ; do
rm -f -- "$file"
xshok_pretty_echo_and_log "Unused/Disabled file removed: $file"
done < "$db_changes"
fi
fi
# Create "purge.txt" file for package maintainers to support package uninstall.
purge="$work_dir_work_configs/purge.txt"
cp -f "$current_dbs_file" "$purge"
{
echo "$work_dir_work_configs/current-dbs.txt"
echo "$work_dir_work_configs/db-changes.txt"
echo "$work_dir_work_configs/last-mbl-update.txt"
echo "$work_dir_work_configs/last-si-update.txt"
echo "$work_dir_work_configs/local.ign"
echo "$work_dir_work_configs/monitor-ign.txt"
echo "$work_dir_work_configs/my-whitelist.ign2"
echo "$work_dir_work_configs/tracker.txt"
echo "$work_dir_work_configs/previous-dbs.txt"
echo "$work_dir_work_configs/scan-test.txt"
echo "$work_dir_work_configs/ss-include-dbs.txt"
echo "$work_dir_work_configs/whitelist.hex"
echo "$work_dir_gpg/publickey.gpg"
echo "$work_dir_gpg/secring.gpg"
echo "$work_dir_gpg/ss-keyring.gpg*"
echo "$work_dir_gpg/trustdb.gpg"
echo "$log_file_path/$log_file_name*"
echo "$work_dir_work_configs/purge.txt"
} >> "$purge"
# Check and save current system time since epoch for time related database downloads.
# However, if unsuccessful, issue a warning that we cannot calculate times since epoch.
if [ -n "${securiteinfo_dbs[0]}" ] || [ -n "$malwarepatrol_db" ] ; then
current_time="$(date "+%s" 2> /dev/null)"
current_time="${current_time//[^0-9]/}"
current_time="$((current_time + 0))"
if [ "$current_time" -le 0 ] ; then
current_time="$(perl -le print+time 2> /dev/null)"
fi
if [ "$current_time" -le 0 ] ; then
xshok_pretty_echo_and_log "WARNING: No support for 'date +%s' or 'perl' was not found , SecuriteInfo and MalwarePatrol updates bypassed" "="
securiteinfo_dbs=()
malwarepatrol_db=()
fi
fi
################################################################
# Check for Sanesecurity database & GPG signature file updates #
################################################################
if [ "$sanesecurity_enabled" == "yes" ] ; then
if [ -n "${sanesecurity_dbs[0]}" ] ; then
if [ ${#sanesecurity_dbs} -lt 1 ] ; then
xshok_pretty_echo_and_log "Failed sanesecurity_dbs config is invalid or not defined - SKIPPING"
else
if [ -r "$work_dir_work_configs/last-ss-update.txt" ] ; then
last_sanesecurity_update="$(cat "$work_dir_work_configs/last-ss-update.txt")"
else
last_sanesecurity_update="0"
fi
db_file=""
update_interval="$((sanesecurity_update_hours * 3600))"
time_interval="$((current_time - last_sanesecurity_update))"
if [ "$time_interval" -ge $((update_interval - 600)) ] ; then
echo "$current_time" > "$work_dir_work_configs/last-ss-update.txt"
xshok_pretty_echo_and_log "Sanesecurity Database & GPG Signature File Updates" "="
xshok_pretty_echo_and_log "Checking for Sanesecurity updates..."
# sanesecurity_mirror_ips="$(dig +ignore +short "$sanesecurity_url")"
sanesecurity_mirror_ips="$(nslookup $sanesecurity_url | grep ^Name -A1 | grep Address | grep -v '#' | cut -f 2 -d ' ')"
# Add fallback to host if dig returns no records
# if [ ${#sanesecurity_mirror_ips} -lt 1 ] ; then
# sanesecurity_mirror_ips="$(host -t A "$sanesecurity_url" | sed -n '/has address/{s/.*address \([^ ]*\).*/\1/;p;}')"
# fi
if [ ${#sanesecurity_mirror_ips} -ge 1 ] ; then
for sanesecurity_mirror_ip in $sanesecurity_mirror_ips ; do
sanesecurity_mirror_name=""
# sanesecurity_mirror_name="$(dig +short -x "$sanesecurity_mirror_ip" | command sed 's/\.$//')"
sanesecurity_mirror_name="$(nslookup $sanesecurity_mirror_ip | grep "name =" | sed 's/.*name \= //' | sed 's/\.$//')"
# Add fallback to host if dig returns no records
# if [ -z "$sanesecurity_mirror_name" ] ; then
# sanesecurity_mirror_name="$(host "$sanesecurity_mirror_ip" | sed -n '/name pointer/{s/.*pointer \([^ ]*\).*\.$/\1/;p;}')"
# fi
sanesecurity_mirror_site_info="$sanesecurity_mirror_name $sanesecurity_mirror_ip"
xshok_pretty_echo_and_log "Sanesecurity mirror site used: $sanesecurity_mirror_site_info"
# shellcheck disable=SC2086
$rsync_bin $rsync_output_level $no_motd --files-from="$sanesecurity_include_dbs" -ctuz $connect_timeout --timeout="$rsync_max_time" "rsync://$sanesecurity_mirror_ip/sanesecurity" "$work_dir_sanesecurity" 2>/dev/null
ret="$?"
if [ "$ret" -eq 0 ] || [ "$ret" -eq 23 ] ; then # The correct way, 23 is some files were not transfered, can be ignored and we can assume a success
sanesecurity_rsync_success="1"
for db_file in "${sanesecurity_dbs[@]}" ; do
if ! cmp -s "$work_dir_sanesecurity/$db_file" "$clam_dbs/$db_file" ; then
xshok_pretty_echo_and_log "Testing updated Sanesecurity database file: $db_file"
if [ "$enable_gpg" == "yes" ] ; then
if ! $gpg_bin --trust-model always -q --no-default-keyring --homedir "$work_dir_gpg" --keyring "$work_dir_gpg/ss-keyring.gpg" --verify "$work_dir_sanesecurity/$db_file.sig" "$work_dir_sanesecurity/$db_file" 2>/dev/null ; then
$gpg_bin --always-trust -q --no-default-keyring --homedir "$work_dir_gpg" --keyring "$work_dir_gpg/ss-keyring.gpg" --verify "$work_dir_sanesecurity/$db_file.sig" "$work_dir_sanesecurity/$db_file" 2>/dev/null
ret="$?"
else
ret="0"
fi
if [ "$ret" -eq 0 ] ; then
test "$gpg_silence" = "no" && xshok_pretty_echo_and_log "Sanesecurity GPG Signature tested good on $db_file database"
else
xshok_pretty_echo_and_log "Sanesecurity GPG Signature test FAILED on $db_file database - SKIPPING"
fi
fi
if [ "$ret" -eq 0 ] ; then
db_ext="${db_file#*.}"
if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
if $clamscan_bin --quiet -d "$work_dir_sanesecurity/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_sanesecurity/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_sanesecurity/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$work_dir_sanesecurity/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated Sanesecurity production database file: $db_file"
sanesecurity_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update Sanesecurity production database file: $db_file - SKIPPING"
false
fi
else
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_sanesecurity/$db_file" > "$test_dir/$db_file"
$clamscan_bin --infected --no-summary -d "$test_dir/$db_file" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' > "$work_dir_work_configs/whitelist.txt"
$grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f 2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested BAD"
# DO NOT KILL THIS DB
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$test_dir/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated Sanesecurity production database file: $db_file"
sanesecurity_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update Sanesecurity production database file: $db_file - SKIPPING"
fi
fi
fi
fi
done
if [ ! "$sanesecurity_update" == "1" ] ; then
xshok_pretty_echo_and_log "No Sanesecurity database file updates found" "-"
break
else
break
fi
else
xshok_pretty_echo_and_log "Connection to $sanesecurity_mirror_site_info failed - Trying next mirror site..."
fi
done
if [ ! "$sanesecurity_rsync_success" == "1" ] ; then
xshok_pretty_echo_and_log "Access to all Sanesecurity mirror sites failed - Check for connectivity issues"
xshok_pretty_echo_and_log "or signature database name(s) misspelled in the script's configuration file."
fi
else
xshok_pretty_echo_and_log "No Sanesecurity mirror sites found - Check for dns/connectivity issues"
fi
else
xshok_pretty_echo_and_log "Sanesecurity Database File Updates" "="
xshok_draw_time_remaining "$((update_interval - time_interval))" "$sanesecurity_update_hours" "sanesecurity"
fi
fi
fi
else
if [ -n "${sanesecurity_dbs[0]}" ] ; then
if [ "$remove_disabled_databases" == "yes" ] ; then
xshok_pretty_echo_and_log "Removing disabled Sanesecurity Database files"
for db_file in "${sanesecurity_dbs[@]}" ; do
if echo "$db_file" | $grep_bin -q "|"; then
db_file="${db_file%|*}"
fi
if [ -r "$work_dir_sanesecurity/$db_file" ] ; then
xshok_pretty_echo_and_log "Removing $work_dir_sanesecurity/$db_file"
rm -f "$work_dir_sanesecurity/$db_file"
do_clamd_reload=1
fi
if [ -r "$clam_dbs/$db_file" ] ; then
xshok_pretty_echo_and_log "Removing $clam_dbs/$db_file"
rm -f "$clam_dbs/$db_file"
do_clamd_reload=1
fi
done
fi
fi
fi
##############################################################################################################################################
# Check for updated SecuriteInfo database files every set number of hours as defined in the "USER CONFIGURATION" section of this script #
##############################################################################################################################################
if [ "$securiteinfo_enabled" == "yes" ] ; then
if [ "$securiteinfo_authorisation_signature" != "YOUR-SIGNATURE-NUMBER" ] ; then
if [ -n "$securiteinfo_dbs" ] ; then
if [ ${#securiteinfo_dbs} -lt 1 ] ; then
xshok_pretty_echo_and_log "Failed securiteinfo_dbs config is invalid or not defined - SKIPPING"
else
rm -f "$work_dir_securiteinfo/*.gz"
if [ -r "$work_dir_work_configs/last-si-update.txt" ] ; then
last_securiteinfo_update="$(cat "$work_dir_work_configs/last-si-update.txt")"
else
last_securiteinfo_update="0"
fi
db_file=""
loop=""
update_interval="$((securiteinfo_update_hours * 3600))"
time_interval="$((current_time - last_securiteinfo_update))"
if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
echo "$current_time" > "$work_dir_work_configs/last-si-update.txt"
xshok_pretty_echo_and_log "SecuriteInfo Database File Updates" "="
xshok_pretty_echo_and_log "Checking for SecuriteInfo updates..."
securiteinfo_updates="0"
for db_file in "${securiteinfo_dbs[@]}" ; do
if [ "$loop" == "1" ] ; then
xshok_pretty_echo_and_log "---"
fi
xshok_pretty_echo_and_log "Checking for updated SecuriteInfo database file: $db_file"
securiteinfo_db_update="0"
xshok_file_download "$work_dir_securiteinfo/$db_file" "$securiteinfo_url/$securiteinfo_authorisation_signature/$db_file"
ret="$?"
if [ "$ret" -eq 0 ] ; then
loop="1"
if ! cmp -s "$work_dir_securiteinfo/$db_file" "$clam_dbs/$db_file" ; then
if [ $? -eq 0 ] ; then
db_ext="${db_file#*.}"
xshok_pretty_echo_and_log "Testing updated SecuriteInfo database file: $db_file"
if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ]
then
if $clamscan_bin --quiet -d "$work_dir_securiteinfo/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
then
xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_securiteinfo/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_securiteinfo/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$work_dir_securiteinfo/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated SecuriteInfo production database file: $db_file"
securiteinfo_updates=1
securiteinfo_db_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update SecuriteInfo production database file: $db_file - SKIPPING"
fi
else
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_securiteinfo/$db_file" > "$test_dir/$db_file"
$clamscan_bin --infected --no-summary -d "$test_dir/$db_file" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' > "$work_dir_work_configs/whitelist.txt"
$grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f 2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
then
xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested BAD"
rm -f "$work_dir_securiteinfo/$db_file"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_securiteinfo/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_securiteinfo/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$test_dir/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated SecuriteInfo production database file: $db_file"
securiteinfo_updates=1
securiteinfo_db_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update SecuriteInfo production database file: $db_file - SKIPPING"
fi
fi
fi
fi
else
xshok_pretty_echo_and_log "Failed connection to $securiteinfo_url - SKIPPED SecuriteInfo $db_file update"
fi
if [ "$securiteinfo_db_update" != "1" ] ; then
xshok_pretty_echo_and_log "No updated SecuriteInfo $db_file database file found" "-"
fi
done
if [ "$securiteinfo_updates" != "1" ] ; then
xshok_pretty_echo_and_log "No SecuriteInfo database file updates found" "-"
fi
else
xshok_pretty_echo_and_log "SecuriteInfo Database File Updates" "="
xshok_draw_time_remaining "$((update_interval - time_interval))" "$securiteinfo_update_hours" "SecuriteInfo"
fi
fi
fi
fi
else
if [ -n "$securiteinfo_dbs" ] ; then
if [ "$remove_disabled_databases" == "yes" ] ; then
xshok_pretty_echo_and_log "Removing disabled SecuriteInfo Database files"
for db_file in "${securiteinfo_dbs[@]}" ; do
if echo "$db_file" | $grep_bin -q "|"; then
db_file="${db_file%|*}"
fi
if [ -r "$work_dir_securiteinfo/$db_file" ] ; then
xshok_pretty_echo_and_log "Removing $work_dir_securiteinfo/$db_file"
rm -f "$work_dir_securiteinfo/$db_file"
do_clamd_reload=1
fi
if [ -r "$clam_dbs/$db_file" ] ; then
xshok_pretty_echo_and_log "Removing $clam_dbs/$db_file"
rm -f "$clam_dbs/$db_file"
do_clamd_reload=1
fi
done
fi
fi
fi
##############################################################################################################################################
# Check for updated linuxmalwaredetect database files every set number of hours as defined in the "USER CONFIGURATION" section of this script
##############################################################################################################################################
if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
if [ -n "${linuxmalwaredetect_dbs[0]}" ] ; then
if [ ${#linuxmalwaredetect_dbs} -lt 1 ] ; then
xshok_pretty_echo_and_log "Failed linuxmalwaredetect_dbs config is invalid or not defined - SKIPPING"
else
rm -f "$work_dir_linuxmalwaredetect/*.gz"
if [ -r "$work_dir_work_configs/last-linuxmalwaredetect-update.txt" ] ; then
last_linuxmalwaredetect_update="$(cat "$work_dir_work_configs/last-linuxmalwaredetect-update.txt")"
else
last_linuxmalwaredetect_update="0"
fi
db_file=""
loop=""
update_interval="$((linuxmalwaredetect_update_hours * 3600))"
time_interval="$((current_time - last_linuxmalwaredetect_update))"
if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
echo "$current_time" > "$work_dir_work_configs/last-linuxmalwaredetect-update.txt"
xshok_pretty_echo_and_log "linuxmalwaredetect Database File Updates" "="
xshok_pretty_echo_and_log "Checking for linuxmalwaredetect updates..."
linuxmalwaredetect_updates="0"
for db_file in "${linuxmalwaredetect_dbs[@]}" ; do
if [ "$loop" == "1" ] ; then
xshok_pretty_echo_and_log "---"
fi
xshok_pretty_echo_and_log "Checking for updated linuxmalwaredetect database file: $db_file"
linuxmalwaredetect_db_update="0"
xshok_file_download "$work_dir_linuxmalwaredetect/$db_file" "$linuxmalwaredetect_url/$db_file"
ret="$?"
if [ "$ret" -eq 0 ] ; then
loop="1"
if ! cmp -s "$work_dir_linuxmalwaredetect/$db_file" "$clam_dbs/$db_file" ; then
if [ $? -eq 0 ] ; then
db_ext="${db_file#*.}"
xshok_pretty_echo_and_log "Testing updated linuxmalwaredetect database file: $db_file"
if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
if $clamscan_bin --quiet -d "$work_dir_linuxmalwaredetect/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
then
xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_linuxmalwaredetect/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_linuxmalwaredetect/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$work_dir_linuxmalwaredetect/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/local.ign"
fi
xshok_pretty_echo_and_log "Successfully updated linuxmalwaredetect production database file: $db_file"
linuxmalwaredetect_updates=1
linuxmalwaredetect_db_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update linuxmalwaredetect production database file: $db_file - SKIPPING"
fi
else
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_linuxmalwaredetect/$db_file" > "$test_dir/$db_file"
$clamscan_bin --infected --no-summary -d "$test_dir/$db_file" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' > "$work_dir_work_configs/whitelist.txt"
$grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f 2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_linuxmalwaredetect/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_linuxmalwaredetect/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$test_dir/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated linuxmalwaredetect production database file: $db_file"
linuxmalwaredetect_updates=1
linuxmalwaredetect_db_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update linuxmalwaredetect production database file: $db_file - SKIPPING"
fi
fi
fi
fi
else
xshok_pretty_echo_and_log "WARNING: Failed connection to $linuxmalwaredetect_url - SKIPPED linuxmalwaredetect $db_file update"
fi
if [ "$linuxmalwaredetect_db_update" != "1" ] ; then
xshok_pretty_echo_and_log "No updated linuxmalwaredetect $db_file database file found"
fi
done
if [ "$linuxmalwaredetect_updates" != "1" ] ; then
xshok_pretty_echo_and_log "No linuxmalwaredetect database file updates found" "-"
fi
else
xshok_pretty_echo_and_log "linuxmalwaredetect Database File Updates" "="
xshok_draw_time_remaining "$((update_interval - time_interval))" "$linuxmalwaredetect_update_hours" "linuxmalwaredetect"
fi
fi
fi
else
if [ -n "${linuxmalwaredetect_dbs[0]}" ] ; then
if [ "$remove_disabled_databases" == "yes" ] ; then
xshok_pretty_echo_and_log "Removing disabled linuxmalwaredetect Database files"
for db_file in "${linuxmalwaredetect_dbs[@]}" ; do
if echo "$db_file" | $grep_bin -q "|"; then
db_file="${db_file%|*}"
fi
if [ -r "$work_dir_linuxmalwaredetect/$db_file" ] ; then
xshok_pretty_echo_and_log "Removing $work_dir_linuxmalwaredetect/$db_file"
rm -f "$work_dir_linuxmalwaredetect/$db_file"
do_clamd_reload=1
fi
if [ -r "$clam_dbs/$db_file" ] ; then
xshok_pretty_echo_and_log "Removing $clam_dbs/$db_file"
rm -f "$clam_dbs/$db_file"
do_clamd_reload=1
fi
done
fi
fi
fi
##########################################################################################################################################
# Download MalwarePatrol database file every set number of hours as defined in the "USER CONFIGURATION" section of this script. #
##########################################################################################################################################
if [ "$malwarepatrol_enabled" == "yes" ] ; then
if [ "$malwarepatrol_receipt_code" != "YOUR-RECEIPT-NUMBER" ] ; then
if [ -n "$malwarepatrol_db" ] ; then
if [ -r "$work_dir_work_configs/last-mbl-update.txt" ] ; then
last_malwarepatrol_update="$(cat "$work_dir_work_configs/last-mbl-update.txt")"
else
last_malwarepatrol_update="0"
fi
db_file=""
update_interval="$((malwarepatrol_update_hours * 3600))"
time_interval="$((current_time - last_malwarepatrol_update))"
if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
echo "$current_time" > "$work_dir_work_configs"/last-mbl-update.txt
xshok_pretty_echo_and_log "Checking for MalwarePatrol updates..."
# Delete the old MBL (mbl.db) database file if it exists and start using the newer
# format (mbl.ndb) database file instead.
# test -e $clam_dbs/$malwarepatrol_db -o -e $clam_dbs/$malwarepatrol_db-bak && rm -f -- "$clam_dbs/mbl.d*"
# Remove the .db is the new format if ndb and
# symetrically
if [ "$malwarepatrol_db" == "malwarepatrol.db" ] && [ -f "$clam_dbs/malwarepatrol.ndb" ] ; then
rm "$clam_dbs/malwarepatrol.ndb";
fi
if [ "$malwarepatrol_db" == "malwarepatrol.ndb" ] && [ -f "$clam_dbs/malwarepatrol.db" ] ; then
rm "$clam_dbs/malwarepatrol.db";
fi
xshok_pretty_echo_and_log "MalwarePatrol $db_file Database File Update" "="
malwarepatrol_reloaded=0
if [ "$malwarepatrol_free" == "yes" ] ; then
xshok_file_download "$work_dir_malwarepatrol/$malwarepatrol_db" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code"
ret="$?"
if [ "$ret" -eq 0 ] ; then
if ! cmp -s "$work_dir_malwarepatrol/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db" ; then
if [ $? -eq 0 ] ; then
malwarepatrol_reloaded=1
else
malwarepatrol_reloaded=2
fi
fi
else # Wget failed
malwarepatrol_reloaded=-1
fi
else # The not free branch
xshok_file_download "$work_dir_malwarepatrol/$malwarepatrol_db.md5" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code&hash=1"
ret="$?"
if [ "$ret" -eq 0 ] ; then
if [ -f "$clam_dbs/$malwarepatrol_db" ] ; then
malwarepatrol_md5="$(openssl md5 -r "$clam_dbs/$malwarepatrol_db" 2>/dev/null | cut -d " " -f 1)"
if [ ! "$malwarepatrol_md5" ] ; then
# Fallback for missing -r option
malwarepatrol_md5="$(openssl md5 "$clam_dbs/$malwarepatrol_db" 2>/dev/null | cut -d " " -f 2)"
fi
fi
malwarepatrol_md5_new="$(cat "$work_dir_malwarepatrol/$malwarepatrol_db.md5")"
if [ -n "$malwarepatrol_md5_new" ] && [ "$malwarepatrol_md5" != "$malwarepatrol_md5_new" ] ; then
xshok_file_download "$work_dir_malwarepatrol/$malwarepatrol_db" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code"
ret="$?"
if [ "$ret" -eq 0 ] ; then
malwarepatrol_reloaded="1"
else # Wget DB fail
malwarepatrol_reloaded="-1"
fi # Wget DB
fi # MD5 not equal
else # Wget MD5 fail
malwarepatrol_reloaded="-1"
fi # Wget MD5
fi
case "$malwarepatrol_reloaded" in
1) # Database was updated, need test and reload
xshok_pretty_echo_and_log "Testing updated MalwarePatrol database file: $malwarepatrol_db"
if $clamscan_bin --quiet -d "$work_dir_malwarepatrol/$malwarepatrol_db" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_malwarepatrol/$malwarepatrol_db" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_malwarepatrol/$malwarepatrol_db"
fi
fi
false
fi \
&& (
test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db-bak" 2>/dev/null
true
) \
&& if $rsync_bin -pcqt "$work_dir_malwarepatrol/$malwarepatrol_db" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$malwarepatrol_db"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$malwarepatrol_db"
fi
xshok_pretty_echo_and_log "Successfully updated MalwarePatrol production database file: $malwarepatrol_db"
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update MalwarePatrol production database file: $malwarepatrol_db - SKIPPING"
fi
;; # The strange case when $? != 0 in the original
2)
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_malwarepatrol/$malwarepatrol_db" > "$test_dir/$malwarepatrol_db"
$clamscan_bin --infected --no-summary -d "$test_dir/$malwarepatrol_db" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' > "$work_dir_work_configs/whitelist.txt"
$grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$malwarepatrol_db" | cut -d "*" -f 2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$malwarepatrol_db" > "$test_dir/$malwarepatrol_db-tmp"
mv -f "$test_dir/$malwarepatrol_db-tmp" "$test_dir/$malwarepatrol_db"
if $clamscan_bin --quiet -d "$test_dir/$malwarepatrol_db" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$test_dir/$malwarepatrol_db" ; then
xshok_pretty_echo_and_log "Removed invalid database: $test_dir/$malwarepatrol_db"
fi
fi
false
fi \
&& (
test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db-bak" 2>/dev/null
true
) \
&& if $rsync_bin -pcqt "$test_dir/$malwarepatrol_db" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$malwarepatrol_db"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$malwarepatrol_db"
fi
xshok_pretty_echo_and_log "Successfully updated MalwarePatrol production database file: $malwarepatrol_db"
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update MalwarePatrol production database file: $malwarepatrol_db - SKIPPING"
fi
;;
0) # The database did not update
xshok_pretty_echo_and_log "MalwarePatrol signature database ($malwarepatrol_db) did not change - skipping"
;;
-1) # Wget failed
xshok_pretty_echo_and_log "WARNING - Failed connection to $malwarepatrol_url - SKIPPED MalwarePatrol $malwarepatrol_db update"
;;
esac
else
xshok_pretty_echo_and_log "MalwarePatrol Database File Update" "="
xshok_draw_time_remaining "$((update_interval - time_interval))" "$malwarepatrol_update_hours" "MalwarePatrol"
fi
fi
fi
else
if [ -n "$malwarepatrol_db" ] ; then
if [ "$remove_disabled_databases" == "yes" ] ; then
xshok_pretty_echo_and_log "Removing disabled MalwarePatrol Database file"
if [ -r "$work_dir_malwarepatrol/$malwarepatrol_db" ] ; then
rm -f "$work_dir_malwarepatrol/$malwarepatrol_db"
do_clamd_reload=1
fi
if [ -r "$clam_dbs/$malwarepatrol_db" ] ; then
rm -f "$clam_dbs/$malwarepatrol_db"
do_clamd_reload=1
fi
fi
fi
fi
##############################################################################################################################################
# Check for updated yararulesproject database files every set number of hours as defined in the "USER CONFIGURATION" section of this script
##############################################################################################################################################
if [ "$yararulesproject_enabled" == "yes" ] ; then
if [ -n "${yararulesproject_dbs[0]}" ] ; then
if [ ${#yararulesproject_dbs} -lt 1 ] ; then
xshok_pretty_echo_and_log "Failed yararulesproject_dbs config is invalid or not defined - SKIPPING"
else
rm -f "$work_dir_yararulesproject/*.gz"
if [ -r "$work_dir_work_configs/last-yararulesproject-update.txt" ] ; then
last_yararulesproject_update="$(cat "$work_dir_work_configs/last-yararulesproject-update.txt")"
else
last_yararulesproject_update="0"
fi
db_file=""
loop=""
update_interval="$((yararulesproject_update_hours * 3600))"
time_interval="$((current_time - last_yararulesproject_update))"
if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
echo "$current_time" > "$work_dir_work_configs/last-yararulesproject-update.txt"
xshok_pretty_echo_and_log "Yara-Rules Database File Updates" "="
xshok_pretty_echo_and_log "Checking for yararulesproject updates..."
yararulesproject_updates="0"
for db_file in "${yararulesproject_dbs[@]}" ; do
if echo "$db_file" | $grep_bin -q "/"; then
yr_dir="/$(echo "$db_file" | cut -d "/" -f 1)"
db_file="$(echo "$db_file" | cut -d "/" -f 2)"
else yr_dir=""
fi
if [ "$loop" == "1" ] ; then
xshok_pretty_echo_and_log "---"
fi
xshok_pretty_echo_and_log "Checking for updated yararulesproject database file: $db_file"
yararulesproject_db_update="0"
xshok_file_download "$work_dir_yararulesproject/$db_file" "$yararulesproject_url/$yr_dir/$db_file"
ret="$?"
if [ "$ret" -eq 0 ] ; then
loop="1"
if ! cmp -s "$work_dir_yararulesproject/$db_file" "$clam_dbs/$db_file" ; then
if [ $? -eq 0 ] ; then
db_ext="${db_file#*.}"
xshok_pretty_echo_and_log "Testing updated yararulesproject database file: $db_file"
if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
if $clamscan_bin --quiet -d "$work_dir_yararulesproject/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
then
xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_yararulesproject/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_yararulesproject/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$work_dir_yararulesproject/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated yararulesproject production database file: $db_file"
yararulesproject_updates=1
yararulesproject_db_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update yararulesproject production database file: $db_file - SKIPPING"
fi
else
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_yararulesproject/$db_file" > "$test_dir/$db_file"
$clamscan_bin --infected --no-summary -d "$test_dir/$db_file" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' > "$work_dir_work_configs/whitelist.txt"
$grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f 2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_yararulesproject/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_yararulesproject/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$test_dir/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated yararulesproject production database file: $db_file"
yararulesproject_updates=1
yararulesproject_db_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update yararulesproject production database file: $db_file - SKIPPING"
fi
fi
fi
fi
else
xshok_pretty_echo_and_log "WARNING: Failed connection to $yararulesproject_url - SKIPPED yararulesproject $db_file update"
fi
if [ "$yararulesproject_db_update" != "1" ] ; then
xshok_pretty_echo_and_log "No updated yararulesproject $db_file database file found"
fi
done
if [ "$yararulesproject_updates" != "1" ] ; then
xshok_pretty_echo_and_log "No yararulesproject database file updates found" "-"
fi
else
xshok_pretty_echo_and_log "Yara-Rules Database File Updates" "="
xshok_draw_time_remaining "$((update_interval - time_interval))" "$yararulesproject_update_hours" "yararulesproject"
fi
fi
fi
else
if [ -n "${yararulesproject_dbs[0]}" ] ; then
if [ "$remove_disabled_databases" == "yes" ] ; then
xshok_pretty_echo_and_log "Removing disabled yararulesproject Database files"
for db_file in "${yararulesproject_dbs[@]}" ; do
if echo "$db_file" | $grep_bin -q "/"; then
db_file="$(echo "$db_file" | cut -d "/" -f 2)"
fi
if echo "$db_file" | $grep_bin -q "|"; then
db_file="${db_file%|*}"
fi
if [ -r "$work_dir_yararulesproject/$db_file" ] ; then
rm -f "$work_dir_yararulesproject/$db_file"
do_clamd_reload="1"
fi
if [ -r "$clam_dbs/$db_file" ] ; then
rm -f "$clam_dbs/$db_file"
do_clamd_reload=1
fi
done
fi
fi
fi
##############################################################################################################################################
# Check for updated additional database files every set number of hours as defined in the "USER CONFIGURATION" section of this script
##############################################################################################################################################
if [ "$additional_enabled" == "yes" ] ; then
if [ -n "$additional_dbs" ] ; then
if [ ${#additional_dbs} -lt 1 ] ; then
xshok_pretty_echo_and_log "Failed additional_dbs config is invalid or not defined - SKIPPING"
else
rm -f "$work_dir_add/*.gz"
if [ -r "$work_dir_work_configs/last-additional-update.txt" ] ; then
last_additional_update="$(cat "$work_dir_work_configs/last-additional-update.txt")"
else
last_additional_update="0"
fi
db_file=""
loop=""
update_interval="$((additional_update_hours * 3600))"
time_interval="$((current_time - last_additional_update))"
if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
echo "$current_time" > "$work_dir_work_configs/last-additional-update.txt"
xshok_pretty_echo_and_log "Additional Database File Updates" "="
xshok_pretty_echo_and_log "Checking for additional updates..."
additional_updates="0"
for db_url in "${additional_dbs[@]}" ; do
# Left for future dir manipulation
# if echo "$db_file" | $grep_bin -q "/"; then
# add_dir="/$(echo "$db_file" | cut -d "/" -f 1)"
# db_file="$(echo "$db_file" | cut -d "/" -f 2)"
# else
# add_dir=""
# fi
#cleanup any leading and trailing whitespace.
db_url="$(echo -e "$db_url" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
db_file="$(basename "$db_url")"
if [ "$loop" == "1" ] ; then
xshok_pretty_echo_and_log "---"
fi
xshok_pretty_echo_and_log "Checking for updated additional database file: $db_file"
additional_db_update="0"
if [ "${db_url%:*}" == "rsync" ] ; then
# shellcheck disable=SC2086
$rsync_bin $rsync_output_level $no_motd -ctuz $connect_timeout --timeout="$rsync_max_time" --exclude=*.txt --exclude=*.sha256 --exclude=*.sig --exclude=*.gz "$db_url" "$work_dir_add" 2>/dev/null
ret="$?"
else
xshok_file_download "$work_dir_add/$db_file" "$db_url"
ret="$?"
fi
# This needs enhancement for rsync, as it will only work with single files...
# Maybe better to process each file inside work_dir_add in its own for loop.
if [ "$ret" -eq 0 ] ; then
loop="1"
if ! cmp -s "$work_dir_add/$db_file" "$clam_dbs/$db_file" ; then
if [ $? -eq 0 ] ; then
db_ext="${db_file#*.}"
xshok_pretty_echo_and_log "Testing updated additional database file: $db_file"
if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
if $clamscan_bin --quiet -d "$work_dir_add/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
then
xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_add/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_add/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$work_dir_add/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated additional production database file: $db_file"
additional_updates=1
additional_db_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update additional production database file: $db_file - SKIPPING"
fi
else
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_add/$db_file" > "$test_dir/$db_file"
$clamscan_bin --infected --no-summary -d "$test_dir/$db_file" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' > "$work_dir_work_configs/whitelist.txt"
$grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f 2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
$grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested good"
true
else
xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested BAD"
if [ "$remove_bad_database" == "yes" ] ; then
if rm -f "$work_dir_add/$db_file" ; then
xshok_pretty_echo_and_log "Removed invalid database: $work_dir_add/$db_file"
fi
fi
false
fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$db_file" "$clam_dbs/$db_file-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$test_dir/$db_file" "$clam_dbs" 2>/dev/null ; then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/$db_file"
fi
xshok_pretty_echo_and_log "Successfully updated additional production database file: $db_file"
additional_updates=1
additional_db_update=1
do_clamd_reload=1
else
xshok_pretty_echo_and_log "Failed to successfully update additional production database file: $db_file - SKIPPING"
fi
fi
fi
fi
else
xshok_pretty_echo_and_log "WARNING: Failed connection to $db_url - SKIPPED additional $db_file update"
fi
if [ "$additional_db_update" != "1" ] ; then
xshok_pretty_echo_and_log "No updated additional $db_file database file found"
fi
done
if [ "$additional_updates" != "1" ] ; then
xshok_pretty_echo_and_log "No additional database file updates found" "-"
fi
else
xshok_pretty_echo_and_log "Additional Database File Updates" "="
xshok_draw_time_remaining "$((update_interval - time_interval))" "$additional_update_hours" "additionaldatabaseupdate"
fi
fi
fi
else
if [ -n "$additional_dbs" ] ; then
if [ "$remove_disabled_databases" == "yes" ] ; then
xshok_pretty_echo_and_log "Removing disabled additional Database files"
for db_file in "${additional_dbs[@]}" ; do
if echo "$db_file" | $grep_bin -q "/"; then
db_file="$(echo "$db_file" | cut -d "/" -f 2)"
fi
if [ -r "$work_dir_add/$db_file" ] ; then
rm -f "$work_dir_add/$db_file"
do_clamd_reload=1
fi
if [ -r "$clam_dbs/$db_file" ] ; then
rm -f "$clam_dbs/$db_file"
do_clamd_reload=1
fi
done
fi
fi
fi
###################################################
# Generate whitelists
###################################################
# Check to see if the local.ign file exists, and if it does, check to see if any of the script
# added bypass entries can be removed due to offending signature modifications or removals.
if [ -r "$clam_dbs/local.ign" ] && [ -s "$work_dir_work_configs/monitor-ign.txt" ] ; then
ign_updated=0
cd "$clam_dbs" || exit
cp -f local.ign "$work_dir_work_configs/local.ign"
cp -f "$work_dir_work_configs/monitor-ign.txt" "$work_dir_work_configs/monitor-ign-old.txt"
xshok_pretty_echo_and_log "" "=" "80"
while read -r entry ; do
sig_file="$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $1}')"
sig_hex="$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $NF}')"
sig_name_old="$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $3}')"
sig_ign_old="$($grep_bin ":$sig_name_old" "$work_dir_work_configs/local.ign")"
sig_old="$(echo "$entry" | tr -d "\r" | cut -d ":" -f 3-)"
sig_new="$($grep_bin -hwF ":$sig_hex" "$sig_file" | tr -d "\r" 2>/dev/null)"
sig_mon_new="$($grep_bin -HwF -n ":$sig_hex" "$sig_file" | tr -d "\r")"
if [ -n "$sig_new" ] ; then
if [ "$sig_old" != "$sig_new" ] || [ "$entry" != "$sig_mon_new" ] ; then
sig_name_new="$(echo "$sig_new" | tr -d "\r" | awk -F ":" '{print $1}')"
sig_ign_new="$(echo "$sig_mon_new" | cut -d ":" -f 1-3)"
perl -i -ne "print unless /$sig_ign_old/" "$work_dir_work_configs/monitor-ign.txt"
echo "$sig_mon_new" >> "$work_dir_work_configs/monitor-ign.txt"
perl -p -i -e "s/$sig_ign_old/$sig_ign_new/" "$work_dir_work_configs/local.ign"
xshok_pretty_echo_and_log "$sig_name_old hexadecimal signature is unchanged, however signature name and/or line placement"
xshok_pretty_echo_and_log "in $sig_file has changed to $sig_name_new - updated local.ign to reflect this change."
ign_updated=1
fi
else
perl -i -ne "print unless /$sig_ign_old/" "$work_dir_work_configs/monitor-ign.txt" "$work_dir_work_configs/local.ign"
xshok_pretty_echo_and_log "$sig_name_old signature has been removed from $sig_file, entry removed from local.ign."
ign_updated=1
fi
done < "$work_dir_work_configs/monitor-ign-old.txt"
if [ "$ign_updated" == "1" ] ; then
if $clamscan_bin --quiet -d "$work_dir_work_configs/local.ign" "$work_dir_work_configs/scan-test.txt"
then
if $rsync_bin -pcqt "$work_dir_work_configs/local.ign" "$clam_dbs"
then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/local.ign"
perms chmod -f 0644 "$clam_dbs/local.ign" "$work_dir_work_configs/monitor-ign.txt"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/local.ign"
fi
do_clamd_reload=3
else
xshok_pretty_echo_and_log "Failed to successfully update local.ign file - SKIPPING"
fi
else
xshok_pretty_echo_and_log "Clamscan reports local.ign database integrity is bad - SKIPPING"
fi
else
xshok_pretty_echo_and_log "No whitelist signature changes found in local.ign" "="
fi
fi
# Check to see if my-whitelist.ign2 file exists, and if it does, check to see if any of the script
# added whitelist entries can be removed due to offending signature modifications or removals.
if [ -r "$clam_dbs/my-whitelist.ign2" ] && [ -s "$work_dir_work_configs/tracker.txt" ] ; then
ign2_updated=0
cd "$clam_dbs" || exit
cp -f my-whitelist.ign2 "$work_dir_work_configs/my-whitelist.ign2"
xshok_pretty_echo_and_log "" "=" "80"
while read -r entry ; do
sig_file="$(echo "$entry" | cut -d ":" -f 1)"
sig_full="$(echo "$entry" | cut -d ":" -f 2-)"
sig_name="$(echo "$entry" | cut -d ":" -f 2)"
if ! $grep_bin -F "$sig_full" "$sig_file" > /dev/null 2>&1 ; then
perl -i -ne "print unless /$sig_name$/" "$work_dir_work_configs/my-whitelist.ign2"
perl -i -ne "print unless /:$sig_name:/" "$work_dir_work_configs/tracker-tmp.txt"
xshok_pretty_echo_and_log "$sig_name signature no longer exists in $sig_file, whitelist entry removed from my-whitelist.ign2"
ign2_updated="1"
fi
done < "$work_dir_work_configs/tracker.txt"
mv -f "$work_dir_work_configs/tracker-tmp.txt" "$work_dir_work_configs/tracker.txt"
xshok_pretty_echo_and_log "" "=" "80"
if [ "$ign2_updated" == "1" ]
then
if $clamscan_bin --quiet -d "$work_dir_work_configs/my-whitelist.ign2" "$work_dir_work_configs/scan-test.txt"
then
if $rsync_bin -pcqt "$work_dir_work_configs/my-whitelist.ign2" "$clam_dbs"
then
perms chown -f "$clam_user:$clam_group" "$clam_dbs/my-whitelist.ign2"
perms chmod -f 0644 "$clam_dbs/my-whitelist.ign2" "$work_dir_work_configs/tracker.txt"
if [ "$selinux_fixes" == "yes" ] ; then
restorecon "$clam_dbs/my-whitelist.ign2"
restorecon "$work_dir_work_configs/tracker.txt"
fi
do_clamd_reload=4
else
xshok_pretty_echo_and_log "Failed to successfully update my-whitelist.ign2 file - SKIPPING"
fi
else
xshok_pretty_echo_and_log "Clamscan reports my-whitelist.ign2 database integrity is bad - SKIPPING"
fi
else
xshok_pretty_echo_and_log "No whitelist signature changes found in my-whitelist.ign2"
fi
fi
# Check for non-matching whitelist.hex signatures and remove them from the whitelist file (signature modified or removed).
if [ -n "$ham_dir" ] ; then
if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
$grep_bin -h -f "$work_dir_work_configs/whitelist.hex" "$work_dir"/*/*.ndb | cut -d "*" -f 2 | tr -d "\r" | sort | uniq > "$work_dir_work_configs/whitelist.tmp"
mv -f "$work_dir_work_configs/whitelist.tmp" "$work_dir_work_configs/whitelist.hex"
rm -f "$work_dir_work_configs/whitelist.txt"
rm -f "$test_dir"/*.*
xshok_pretty_echo_and_log "WARNING: Signature(s) triggered on HAM directory scan - signature(s) removed" "*"
else
xshok_pretty_echo_and_log "No signatures triggered on HAM directory scan" "="
fi
fi
# Set appropriate directory and file permissions to all production signature files
# and set file access mode to 0644 on all working directory files.
if [ "$setmode" == "yes" ] ; then
xshok_pretty_echo_and_log "Setting permissions and ownership" "="
perms chown -f -R "$clam_user:$clam_group" "$work_dir"
if ! find "$work_dir" -type f -exec chmod -f 0644 "{}" "+" 2>/dev/null ; then
if ! find "$work_dir" -type f -print0 | xargs -0 chmod -f 0644 2>/dev/null ; then
find "$work_dir" -type f -exec chmod -f 0644 "{}" ";"
fi
fi
# If enabled, set file access mode for all production signature database files to 0644.
perms chown -f -R "$clam_user:$clam_group" "$clam_dbs"
if ! find "$clam_dbs" -type f -exec chmod -f 0644 "{}" "+" 2>/dev/null ; then
if ! find "$clam_dbs" -type f -print0 | xargs -0 chmod -f 0644 2>/dev/null ; then
find "$clam_dbs" -type f -exec chmod -f 0644 "{}" ";"
fi
fi
fi
# Reload all clamd databases
clamscan_reload_dbs
xshok_pretty_echo_and_log "Issue tracker : https://github.com/extremeshok/clamav-unofficial-sigs/issues" "-"
check_new_version
check_new_config_version
xshok_cleanup
# And lastly we exit, Note: the exit is always on the 2nd last line
exit $?