2 # shellcheck disable=SC2154
3 # shellcheck disable=SC2128
4 ################################################################################
5 # This is property of eXtremeSHOK.com
6 # You are free to use, modify and distribute, however you may not remove this notice.
7 # Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
8 # License: BSD (Berkeley Software Distribution)
9 ################################################################################
11 # Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
13 # Originially based on Script provided by Bill Landry (unofficialsigs@gmail.com).
15 ################################################################################
17 # THERE ARE NO USER CONFIGURABLE OPTIONS IN THIS SCRIPT
18 # ALL CONFIGURATION OPTIONS ARE LOCATED IN THE INCLUDED CONFIGURATION FILE
20 ################################################################################
22 ###### ####### # # ####### ####### ####### ###### ### #######
23 # # # # ## # # # # # # # # #
24 # # # # # # # # # # # # # # #
25 # # # # # # # # # # ##### # # # #
26 # # # # # # # # # # # # # # #
27 # # # # # ## # # # # # # # #
28 ###### ####### # # ####### # ####### ###### ### #
30 ################################################################################
33 # Detect to make sure the entire script is avilable, fail if the script is missing contents
34 if [ "$(tail -n 1 "$0" | head -n 1 | cut -c 1-7)" != "exit \$?" ] ; then
35 echo "FATAL ERROR: Script is incomplete, please redownload"
39 # Trap the keyboard interrupt (Ctrl + C)
40 trap xshok_control_c SIGINT
42 ################################################################################
44 ################################################################################
46 # Support user config settings for applying file and directory access permissions.
48 if [ -n "$clam_user" ] && [ -n "$clam_group" ] ; then
53 # Prompt a user if they should complete an action with Y or N
54 # Usage: xshok_prompt_confirm
55 # if xshok_prompt_confirm; then
56 # xshok_prompt_confirm && echo "accepted"
57 # xshok_prompt_confirm && echo "yes" || echo "no"
58 # shellcheck disable=SC2120
59 function xshok_prompt_confirm () { # optional_message
60 message="${1:-Are you sure?}"
62 read -r -p "$message [y/N]" response < /dev/tty
66 *) printf " \033[31m %s \n\033[0m" "invalid input"
72 function xshok_create_pid_file () { # pid.file
76 if [ $? -ne 0 ] ; then
77 xshok_pretty_echo_and_log "ERROR: Could not create PID file: $pidfile"
81 xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
86 # Intercept ctrl+c and calls the cleanup function
87 function xshok_control_c () {
89 xshok_pretty_echo_and_log "--------------| Exiting ... Please wait |--------------" "-"
95 function xshok_cleanup () {
96 # Wait for all processes to end
98 xshok_pretty_echo_and_log " Powered By https://eXtremeSHOK.com " "#"
102 # Check if the current running user is the root user, otherwise return false
103 function xshok_is_root () {
104 if [ "$(uname -s)" == "SunOS" ] ; then
105 id_bin="/usr/xpg4/bin/id"
107 id_bin="$(which id 2> /dev/null)"
109 if [ "$($id_bin -u)" == 0 ] ; then
116 # Check if its a file, otherwise return false
117 function xshok_is_file () { # filepath
119 if [ -f "${filepath}" ] ; then
122 return 1 ; # Not a file
126 # Check if filepath is a subdir, otherwise return false
127 # Usage: xshok_is_subdir "filepath"
128 # xshok_is_subdir "/root/" - false
129 # xshok_is_subdir "/usr/local/etc" && echo "yes" - yes
130 function xshok_is_subdir () { # filepath
131 shopt -s extglob; filepath="${filepath%%+(/)}"
132 if [ -d "$filepath" ] ; then
133 res="${filepath//[^\/]}"
134 if [ "${#res}" -gt 1 ] ; then
137 return 1 ; # Not a subdir
140 return 1 ; # Not a dir
144 # Create a dir and set the ownership
145 function xshok_mkdir_ownership () { # path
147 mkdir -p "$1" 2>/dev/null
148 if [ $? -ne 0 ] ; then
149 xshok_pretty_echo_and_log "ERROR: Could not create directory: $1"
152 perms chown -f "$clam_user:$clam_group" "$1" > /dev/null 2>&1
154 xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
159 # Check if a user and group exists on the system otherwise return false
161 # xshok_is_subdir "username" && echo "user found" || echo "no"
162 # xshok_is_subdir "username" "groupname" && echo "user and group found" || echo "no"
163 function xshok_user_group_exists () { # username groupname
164 if [ "$(uname -s)" == "SunOS" ] ; then
165 id_bin="/usr/xpg4/bin/id"
167 id_bin="$(which id 2> /dev/null)"
171 if [ "$(uname -s)" == "Darwin" ] ; then
172 #use ruby, as this is the best way. Ruby is always avilable as brew uses ruby
173 ruby -e 'require "etc"; puts Etc::getgrnam("_clamav").gid' > /dev/null 2>&1
176 getent_bin="$(which getent 2> /dev/null)"
177 $getent_bin group "$2" >/dev/null 2>&1
183 $id_bin -u "$1" > /dev/null 2>&1
184 if [ $? -eq 0 ]; then
186 if [ "$ret" -eq 0 ]; then
187 return 0 ; # User and group exists
189 return 1 ; # Group does NOT exist
192 return 0 ; # User exists
195 return 1 ; # User does NOT exist
198 xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
203 # Handle comments with/out borders and logging.
205 # pretty_echo_and_log "one"
207 # pretty_echo_and_log "two" "-"
211 # pretty_echo_and_log "three" "=" "8"
215 # pretty_echo_and_log "" "/\" "7"
217 # type: e = error, w= warning ""
218 function xshok_pretty_echo_and_log () { # "string" "repeating" "count" "type"
220 if [ "$comment_silence" == "no" ] ; then
221 if [ "${#@}" -eq 1 ] ; then
225 if [ -n "$3" ] ; then
230 for (( n = 0; n < mycount; n++ )) ; do
233 if [ -n "$1" ] ; then
234 echo -e "$myvar\n$1\n$myvar"
242 if [ "$enable_log" == "yes" ] ; then
243 if [ ! -e "$log_file_path/$log_file_name" ] ; then
244 # xshok_mkdir_ownership "$log_file_path"
245 mkdir -p "$log_file_path"
246 touch "$log_file_path/$log_file_name" 2>/dev/null
247 perms chown -f "$clam_user:$clam_group" "$log_file_path/$log_file_name"
249 if [ ! -w "$log_file_path/$log_file_name" ] ; then
250 echo "Warning: Logging Disabled, as file not writable: $log_file_path/$log_file_name"
253 echo "$(date "+%b %d %T")" "$1" >> "$log_file_path/$log_file_name"
258 # Check if the $2 value is not null and does not start with -
259 function xshok_check_s2 () { # value1 value2
261 if [[ "$1" =~ ^-.* ]] ; then
262 xshok_pretty_echo_and_log "ERROR: Missing value for option or value begins with -" "="
266 xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
271 # Time remaining information function
272 function xshok_draw_time_remaining () { #time_remaining #update_hours #name
273 if [ "$1" ] && [ "$2" ]; then
275 hours_left="$((time_remaining / 3600))"
276 minutes_left="$((time_remaining % 3600 / 60))"
277 xshok_pretty_echo_and_log "$2 hours have not yet elapsed since the last $3 update check"
278 xshok_pretty_echo_and_log "No update check was performed at this time" "-"
279 xshok_pretty_echo_and_log "Next check will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
284 function xshok_file_download () { #outputfile #url
285 if [ "$1" ] && [ "$2" ]; then
286 if [ -n "$wget_bin" ] ; then
287 # shellcheck disable=SC2086
288 $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"
291 # shellcheck disable=SC2086
292 $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"
300 function xshok_auto_update () { # version
301 xshok_pretty_echo_and_log "Performing automatic update..."
303 # Download new version
304 echo -n "Downloading latest version..."
306 xshok_file_download "$0.tmp" "$UPDATE_BASE/$SELF"
309 if [ "$result" -ne 0 ]; then
310 echo "Failed: Error while trying to get new version!"
311 echo "File requested: $UPDATE_BASE/$SELF"
316 # Copy over modes from old version
317 OCTAL_MODE="$(stat -c "%a" "$SELF")"
318 if ! chmod "$OCTAL_MODE" "${0}.tmp" ; then
319 echo "Failed: Error while trying to set mode on ${0}.tmp."
323 # Generate the update script
324 cat > xshok_update_script.sh << EOF
326 # Overwrite old file with new
327 if mv "$0.tmp" "$0"; then
328 echo "Done. Update complete."
331 echo "Failed! The update was not completed."
336 echo -n "Inserting update process..."
338 # Replaced with $0, so code will update and then call itself with the same parameters it had
339 #exec /bin/bash xshok_update_script.sh
343 # Handle list of database files
344 function clamav_files () {
345 echo "$clam_dbs/$db" >> "$current_tmp"
346 if [ "$keep_db_backup" == "yes" ] ; then
347 echo "$clam_dbs/$db-bak" >> "$current_tmp"
351 # Manage the databases and allow multi-dimensions as well as global overrides
352 # Since the datbases are basically a multi-dimentional associative arrays in bash
353 # ratings: LOW| MEDIUM| HIGH| REQUIRED| LOWONLY| MEDIUMONLY| LOWMEDIUMONLY | MEDIUMHIGHONLY | HIGHONLY| DISABLED
354 function xshok_database () { # rating database_array
357 declare -a current_dbs=( "${@:2}" )
359 declare -a new_dbs=( )
360 if [ -n "${current_dbs[0]}" ] ; then
361 if [ ${#current_dbs} -ge 1 ] ; then
362 for db_name in "${current_dbs[@]}" ; do
364 if [ "$enable_yararules" == "no" ] ; then # YARA rules are disabled
365 if [[ "$db_name" == *".yar"* ]] ; then # If it's the value you want to delete
366 continue # Skip to the next value
369 if [ -z "$current_rating" ] ; then # YARA rules are disabled
370 new_dbs+=( "$db_name" )
372 if [[ ! "$db_name" = *"|"* ]] ; then # This old format
373 new_dbs+=( "$db_name" )
375 db_name_rating="${db_name#*|}"
376 db_name="${db_name%|*}"
378 if [ "$db_name_rating" != "DISABLED" ] ; then
379 if [ "$db_name_rating" == "$current_rating" ] ; then
380 new_dbs+=( "$db_name" )
381 elif [ "$db_name_rating" == "REQUIRED" ] ; then
382 new_dbs+=( "$db_name" )
383 elif [ "$current_rating" == "LOW" ] ; then
384 if [ "$db_name_rating" == "LOWONLY" ] || [ "$db_name_rating" == "LOW" ] || [ "$db_name_rating" == "LOWMEDIUM" ] ; then
385 new_dbs+=( "$db_name" )
387 elif [ "$current_rating" == "MEDIUM" ] ; then
388 if [ "$db_name_rating" == "MEDIUMONLY" ] || [ "$db_name_rating" == "MEDIUM" ] || [ "$db_name_rating" == "LOW" ] || [ "$db_name_rating" == "LOWMEDIUM" ] ; then
389 new_dbs+=( "$db_name" )
391 elif [ "$current_rating" == "HIGH" ] ; then
392 if [ "$db_name_rating" == "HIGH" ] || [ "$db_name_rating" == "MEDIUM" ] || [ "$db_name_rating" == "LOW" ] ; then
393 new_dbs+=( "$db_name" )
402 echo "${new_dbs[@]}" | xargs # Remove extra whitespace
405 ################################################################################
406 # ADDITIONAL PROGRAM FUNCTIONS
407 ################################################################################
410 # Generates a man config and installs it
411 function install_man () {
413 if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
414 echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
419 echo "Generating man file for install...."
421 # Use defined varibles or attempt to use default varibles
423 if [ ! -e "$man_dir/$man_filename" ] ; then
425 touch "$man_dir/$man_filename" 2>/dev/null
427 if [ ! -w "$man_dir/$man_filename" ] ; then
428 echo "ERROR: man install aborted, as file not writable: $man_dir/$man_filename"
434 manresult="$(help_and_usage "man")"
437 cat << EOF > "$man_dir/$man_filename"
439 .\" Manual page for eXtremeSHOK.com ClamAV Unofficial Signature Updater
440 .TH clamav-unofficial-sigs 8 "$script_version_date" "Version: $script_version" "SCRIPT COMMANDS"
442 clamav-unofficial-sigs \- Download, test, and install third-party ClamAV signature databases.
444 .B clamav-unofficial-sigs
447 \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.
449 Script updates can be found at: \fBhttps://github.com/extremeshok/clamav-unofficial-sigs\fP
451 This script follows the standard GNU command line syntax.
458 Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
460 You are free to use, modify and distribute, however you may not remove this notice.
462 BSD (Berkeley Software Distribution)
464 Report bugs to \fBhttps://github.com/extremeshok/clamav-unofficial-sigs\fP
466 Adrian Jon Kriel :: admin@extremeshok.com
467 Originially based on Script provide by Bill Landry
473 echo "Completed: man installed, as file: $man_dir/$man_filename"
477 # Generate a logrotate config and install it
478 function install_logrotate () {
480 if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
481 echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
486 echo "Generating logrotate file for install...."
488 # Use defined varibles or attempt to use default varibles
490 if [ -z "$logrotate_user" ] ; then
491 logrotate_user="$clam_user";
493 if [ -z "$logrotate_group" ] ; then
494 logrotate_group="$clam_group";
496 if [ -z "$logrotate_log_file_full_path" ] ; then
497 logrotate_log_file_full_path="$log_file_path/$log_file_name"
501 if [ ! -e "$logrotate_dir/$logrotate_filename" ] ; then
502 mkdir -p "$logrotate_dir"
503 touch "$logrotate_dir/$logrotate_filename" 2>/dev/null
505 if [ ! -w "$logrotate_dir/$logrotate_filename" ] ; then
506 echo "ERROR: logrotate install aborted, as file not writable: $logrotate_dir/$logrotate_filename"
509 cat << EOF > "$logrotate_dir/$logrotate_filename"
510 # https://eXtremeSHOK.com ######################################################
511 # This file contains the logrotate settings for clamav-unofficial-sigs.sh
513 # This is property of eXtremeSHOK.com
514 # You are free to use, modify and distribute, however you may not remove this notice.
515 # Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
518 # Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
520 # Originially based on:
521 # Script provide by Bill Landry (unofficialsigs@gmail.com).
523 # License: BSD (Berkeley Software Distribution)
526 # Automatically Generated: $(date)
529 # This logrotate file will rotate the logs generated by the clamav-unofficial-sigs.sh
531 # To Adjust the logrotate values, edit your configs and run
532 # bash clamav-unofficial-sigs.sh --install-logrotate to generate a new file.
534 $logrotate_log_file_full_path {
540 create 0640 $logrotate_user $logrotate_group
546 echo "Completed: logrotate installed, as file: $logrotate_dir/$logrotate_filename"
549 # Generate a cron config and install it
550 function install_cron () {
552 if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
553 echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
558 echo "Generating cron file for install...."
560 # Use defined varibles or attempt to use default varibles
561 if [ -z "$cron_minute" ] ; then
562 cron_minute="$(( ( RANDOM % 59 ) + 1 ))"
564 if [ -z "$cron_user" ] ; then
565 cron_user="$clam_user";
567 if [ -z "$cron_bash" ] ; then
568 cron_bash="$(which bash 2> /dev/null)"
570 if [ -z "$cron_script_full_path" ] ; then
571 cron_script_full_path="$this_script_full_path"
574 if [ ! -e "$cron_dir/$cron_filename" ] ; then
576 touch "$cron_dir/$cron_filename" 2>/dev/null
578 if [ ! -w "$cron_dir/$cron_filename" ] ; then
579 echo "ERROR: cron install aborted, as file not writable: $cron_dir/$cron_filename"
582 cat << EOF > "$cron_dir/$cron_filename"
583 # https://eXtremeSHOK.com ######################################################
584 # This file contains the cron settings for clamav-unofficial-sigs.sh
586 # This is property of eXtremeSHOK.com
587 # You are free to use, modify and distribute, however you may not remove this notice.
588 # Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
591 # Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
593 # Originially based on:
594 # Script provide by Bill Landry (unofficialsigs@gmail.com).
596 # License: BSD (Berkeley Software Distribution)
599 # Automatically Generated: $(date)
602 # This cron file will execute the clamav-unofficial-sigs.sh script that
603 # currently supports updating third-party signature databases provided
604 # by Sanesecurity, SecuriteInfo, MalwarePatrol, OITC, etc.
606 # The script is set to run hourly, at a random minute past the hour, and the
607 # script itself is set to randomize the actual execution time between
608 # 60 - 600 seconds. To Adjust the cron values, edit your configs and run
609 # bash clamav-unofficial-sigs.sh --install-cron to generate a new file.
611 $cron_minute * * * * $cron_user [ -x $cron_script_full_path ] && $cron_bash $cron_script_full_path > /dev/null
613 # https://eXtremeSHOK.com ######################################################
618 echo "Completed: cron installed, as file: $cron_dir/$cron_filename"
622 # Decode a third-party signature either by signature name
623 function decode_third_party_signature_by_signature_name () {
625 echo "Input a third-party signature name to decode (e.g: Sanesecurity.Junk.15248) or"
626 echo "a hexadecimal encoded data string and press enter (do not include '.UNOFFICIAL'"
627 echo "in the signature name nor add quote marks to any input string):"
629 input="$(echo "$input" | tr -d "'" | tr -d '"')"
630 if echo "$input" | $grep_bin "\." > /dev/null ; then
631 cd "$clam_dbs" || exit
632 sig="$($grep_bin "$input:" ./*.ndb)"
633 if [ -n "$sig" ] ; then
635 echo "$input found in: $db_file"
636 echo "$input signature decodes to:"
637 echo "$sig" | cut -d ":" -f 5 | perl -pe 's/([a-fA-F0-9]{2})|(\{[^}]*\}|\([^)]*\))/defined $2 ? $2 : chr(hex $1)/eg'
639 echo "Signature '$input' could not be found."
640 echo "This script will only decode ClamAV 'UNOFFICIAL' third-Party,"
641 echo "non-image based, signatures as found in the *.ndb databases."
644 echo "Here is the decoded hexadecimal input string:"
645 echo "$input" | perl -pe 's/([a-fA-F0-9]{2})|(\{[^}]*\}|\([^)]*\))/defined $2 ? $2 : chr(hex $1)/eg'
649 # Hexadecimal encode an entire input string
650 function hexadecimal_encode_entire_input_string () {
652 echo "Input the data string that you want to hexadecimal encode and then press enter. Do not include"
653 echo "any quotes around the string unless you want them included in the hexadecimal encoded output:"
655 echo "Here is the hexadecimal encoded input string:"
656 echo "$input" | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg'
659 # Hexadecimal encode a formatted input string
660 function hexadecimal_encode_formatted_input_string () {
662 echo "Input a formated data string containing spacing fields '{}, (), *' that you want to hexadecimal"
663 echo "encode, without encoding the spacing fields, and then press enter. Do not include any quotes"
664 echo "around the string unless you want them included in the hexadecimal encoded output:"
666 echo "Here is the hexadecimal encoded input string:"
667 echo "$input" | perl -pe 's/(\{[^}]*\}|\([^)]*\)|\*)|(.)/defined $1 ? $1 : sprintf("%02lx", ord $2)/eg'
670 # GPG verify a specific Sanesecurity database file
671 function gpg_verify_specific_sanesecurity_database_file () { # databasefile
673 if [ "$enable_gpg" == "no" ] ; then
674 xshok_pretty_echo_and_log "Notice: GnuPG / signature verification disabled" "-"
677 db_file="$(echo "$1" | awk -F "/" '{print $NF}')"
678 if [ -r "$work_dir_sanesecurity/$db_file" ] ; then
679 echo "GPG signature testing database file: $work_dir_sanesecurity/$db_file"
680 if [ -r "$work_dir_sanesecurity/$db_file".sig ] ; then
681 "$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"
682 if [ $? -ne 0 ]; then
683 "$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"
684 if [ $? -eq 0 ]; then
693 echo "Signature '${db_file}.sig' cannot be found."
696 echo "File '$db_file' cannot be found or is not a Sanesecurity database file."
697 echo "Only the following Sanesecurity and OITC databases can be GPG signature tested:"
698 ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_sanesecurity"
701 xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
708 # Output system and configuration information
709 function output_system_configuration_information () {
711 echo "*** SCRIPT VERSION ***"
712 echo "$this_script_name $script_version ($script_version_date)"
713 echo "*** SYSTEM INFORMATION ***"
715 echo "*** CLAMSCAN LOCATION & VERSION ***"
717 $clamscan_bin --version | head -1
718 echo "*** RSYNC LOCATION & VERSION ***"
720 $rsync_bin --version | head -1
721 if [ -n "$wget_bin" ] ; then
722 echo "*** WGET LOCATION & VERSION ***"
724 $wget_bin --version | head -1
726 echo "*** CURL LOCATION & VERSION ***"
728 $curl_bin --version | head -1
730 if [ "$enable_gpg" == "yes" ] ; then
731 echo "*** GPG LOCATION & VERSION ***"
733 $gpg_bin --version | head -1
735 echo "*** SCRIPT WORKING DIRECTORY INFORMATION ***"
737 echo "*** CLAMAV DIRECTORY INFORMATION ***"
739 echo "*** SCRIPT CONFIGURATION SETTINGS ***"
740 if [ "$custom_config" != "no" ] ; then
741 if [ -d "$custom_config" ] ; then
742 # Assign the custom config dir and remove trailing / (removes / and //)
743 echo "Custom Configuration Directory: $config_dir"
745 echo "Custom Configuration File: $custom_config"
748 echo "Configuration Directory: $config_dir"
752 # Make a signature database from an ascii file
753 function make_signature_database_from_ascii_file () {
756 The '-m' script flag provides a way to create a ClamAV hexadecimal signature database (*.ndb) file
757 from a list of data strings stored in a clear-text ascii file, with one data string entry per line.
759 - Hexadecimal encoding can be either 'full' or 'formatted' on a per line basis:
761 Full line encoding should be used if there are no formatted spacing entries [{}, (), *]
762 included on the line. Prefix unformatted lines with: '-:' (no quote marks).
766 -:This signature contains no formatted spacing fields
770 54686973207369676e617475726520636f6e7461696e73206e6f20666f726d61747465642073706163696e67206669656c6473
772 Formatted line encoding should be used if there are user added spacing entries [{}, (), *]
773 included on the line. Prefix formatted lines with '=:' (no quote marks).
777 =:This signature{-10}contains several(25|26|27)formatted spacing*fields
781 54686973207369676e6174757265{-10}636f6e7461696e73207365766572616c(25|26|27)666f726d61747465642073706163696e67*6669656c6473
783 Use 'full' encoding if you want to encode everything on the line [including {}, (), *] and 'formatted'
784 encoding if you want to encode everything on the line except the formatted character spacing fields.
786 The prefixes ('-:' and '=:') will be stripped from the line before hexadecimal encoding is done.
787 If no prefix is found at the beginning of the line, full line encoding will be done (default).
789 - It is assumed that the signatures will be created for email scanning purposes, thus the '4'
790 target type is used and full file scanning is enabled (see ClamAV signatures.pdf for details).
792 - Line numbering will be done automatically by the script.
793 " | command sed 's/^ //g'
794 echo -n "Do you wish to continue? "
795 if xshok_prompt_confirm ; then
797 echo -n "Enter the source file as /path/filename: "
799 if [ -r "$source" ] ; then
800 source_file="$(basename "$source")"
802 echo "What signature prefix would you like to use? For example: 'Phish.Domains'"
803 echo "will create signatures that looks like: 'Phish.Domains.1:4:*:HexSigHere'"
805 echo -n "Enter signature prefix: "
807 path_file="$(echo "$source" | cut -d "." -f -1 | command sed 's/$/.ndb/')"
808 db_file="$(basename "$path_file")"
810 total="$(wc -l "$source" | cut -d " " -f 1)"
813 while read -r line ; do
814 line_prefix="$(echo "$line" | awk -F ":" '{print $1}')"
815 if [ "$line_prefix" == "-" ] ; then
816 echo "$line" | cut -d ":" -f 2- | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg' | command sed "s/^/$prefix\.$line_num:4:\*:/" >> "$path_file"
817 elif [ "$line_prefix" == "=" ] ; then
818 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"
820 echo "$line" | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg' | command sed "s/^/$prefix\.$line_num:4:\*:/" >> "$path_file"
822 echo "Hexadecimal encoding $source_file line: $line_num of $total"
823 line_num="$((line_num + 1))"
826 echo "Source file not found, exiting..."
831 echo "Signature database file created at: $path_file"
832 if $clamscan_bin --quiet -d "$path_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
834 echo "Clamscan reports database integrity tested good."
836 echo -n "Would you like to move '$db_file' into '$clam_dbs' and reload databases?"
837 if xshok_prompt_confirm ; then
838 if ! cmp -s "$path_file" "$clam_dbs/$db_file" ; then
839 if $rsync_bin -pcqt "$path_file" "$clam_dbs" ; then
840 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
841 perms chmod -f 0644 "$clam_dbs"/"$db_file"
842 if [ "$selinux_fixes" == "yes" ] ; then
843 restorecon "$clam_dbs/$db_file"
847 echo "Signature database '$db_file' was successfully implemented and ClamD databases reloaded."
850 echo "Failed to add/update '$db_file', ClamD database not reloaded."
854 echo "Database '$db_file' has not changed - skipping"
858 echo "No action taken."
862 echo "Clamscan reports that '$db_file' signature database integrity tested bad."
867 # Remove the clamav-unofficial-sigs script
868 function remove_script () {
870 if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
871 echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
872 echo "use '$pkg_rm' to remove the script and all of its associated files and databases from the system."
875 cron_file_full_path="$cron_dir/$cron_filename"
876 logrotate_file_full_path="$logrotate_dir/$logrotate_filename"
877 man_file_full_path="$man_dir/$man_filename"
879 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)"
880 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?"
881 if xshok_prompt_confirm ; then
882 echo "This can not be undone are you sure ?"
883 if xshok_prompt_confirm ; then
884 if [ -r "$work_dir_work_configs/purge.txt" ] ; then
886 while read -r file ; do
887 xshok_is_file "$file" && rm -f -- "$file"
888 echo " Removed file: $file"
889 done < "$work_dir_work_configs"/purge.txt
890 if [ -r "$cron_file_full_path" ] ; then
891 xshok_is_file "$cron_file_full_path" && rm -f "$cron_file_full_path"
892 echo " Removed file: $cron_file_full_path"
894 if [ -r "$logrotate_file_full_path" ] ; then
895 xshok_is_file "$logrotate_file_full_path" && rm -f "$logrotate_file_full_path"
896 echo " Removed file: $logrotate_file_full_path"
898 if [ -r "$man_file_full_path" ] ; then
899 xshok_is_file "$man_file_full_path" && rm -f "$man_file_full_path"
900 echo " Removed file: $man_file_full_path"
903 # Rather keep the configs
904 #rm -f -- "$default_config" && echo " Removed file: $default_config"
905 #rm -f -- "$0" && echo " Removed file: $0"
906 xshok_is_subdir "$work_dir" && rm -rf -- "${work_dir:?}" && echo " Removed script working directories: $work_dir"
908 echo " The clamav-unofficial-sigs script and all of its associated files, third-party"
909 echo " databases, and work directories have been successfully removed from the system."
912 echo " Cannot locate 'purge.txt' file in $work_dir_work_configs."
913 echo " Files and signature database will need to be removed manually."
924 # Clamscan integrity test a specific database file
925 function clamscan_integrity_test_specific_database_file () { # databasefile
928 input="$(echo "$1" | awk -F "/" '{print $NF}')"
929 db_file="$(find "$work_dir" -name "$input")"
930 if [ -r "$db_file" ] ; then
931 echo "Clamscan integrity testing: $db_file"
933 $clamscan_bin --quiet -d "$db_file" "$work_dir_work_configs/scan-test.txt"
934 if [ $? -eq 0 ]; then
935 echo "Clamscan reports that '$input' database integrity tested GOOD"
938 echo "Clamscan reports that '$input' database integrity tested BAD"
942 echo "File '$input' cannot be found."
943 echo "Here is a list of third-party databases that can be clamscan integrity tested:"
945 echo "=== Sanesecurity ==="
946 ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_sanesecurity"
948 echo "=== SecuriteInfo ==="
949 ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_securiteinfo"
951 echo "=== MalwarePatrol ==="
952 ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_malwarepatrol"
954 echo "=== Linux Malware Detect ==="
955 ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_linuxmalwaredetect"
957 echo "=== Linux Malware Detect ==="
958 ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_yararulesproject"
960 echo "=== User Defined Databases ==="
961 ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_add"
963 echo "Check the file name and try again..."
966 xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
971 # Output names of any third-party signatures that triggered during the HAM directory scan
972 function output_signatures_triggered_during_ham_directory_scan () {
974 if [ -n "$ham_dir" ] ; then
975 if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
976 echo "The following third-party signatures triggered hits during the HAM Directory scan:"
978 $grep_bin -h -f "$work_dir_work_configs/whitelist.hex" "$work_dir"/*/*.ndb | cut -d ":" -f 1
980 echo "No third-party signatures have triggered hits during the HAM Directory scan."
983 echo "Ham directory scanning is not currently enabled in the script's configuration file."
987 # Adds a signature whitelist entry in the newer ClamAV IGN2 format
988 function add_signature_whitelist_entry () {
990 echo "Input a third-party signature name that you wish to whitelist due to false-positives"
991 echo "and press enter (do not include '.UNOFFICIAL' in the signature name nor add quote"
992 echo "marks to the input string):"
995 if [ -n "$input" ] ; then
996 cd "$clam_dbs" || exit
997 input="$(echo "$input" | tr -d "'" | tr -d '"')"
998 sig_full="$($grep_bin -H "$input" ./*.*db)"
999 sig_name="$(echo "$sig_full" | cut -d ":" -f 2)"
1000 if [ -n "$sig_name" ] ; then
1001 if ! $grep_bin "$sig_name" my-whitelist.ign2 > /dev/null 2>&1 ; then
1002 cp -f my-whitelist.ign2 "$work_dir_work_configs" 2>/dev/null
1003 echo "$sig_name" >> "$work_dir_work_configs/my-whitelist.ign2"
1004 echo "$sig_full" >> "$work_dir_work_configs/tracker.txt"
1005 if $clamscan_bin --quiet -d "$work_dir_work_configs/my-whitelist.ign2" "$work_dir_work_configs/scan-test.txt" ; then
1006 if $rsync_bin -pcqt "$work_dir_work_configs/my-whitelist.ign2" "$clam_dbs" ; then
1007 perms chown -f "$clam_user:$clam_group" my-whitelist.ign2
1009 if [ ! -s "$work_dir_work_configs/monitor-ign.txt" ] ; then
1010 # Create "monitor-ign.txt" file for clamscan database integrity testing.
1011 echo "This is the monitor ignore file..." > "$work_dir_work_configs/monitor-ign.txt"
1014 perms chmod -f 0644 my-whitelist.ign2 "$work_dir_work_configs/monitor-ign.txt"
1015 if [ "$selinux_fixes" == "yes" ] ; then
1016 restorecon "$clam_dbs/local.ign"
1020 echo "Signature '$input' has been added to my-whitelist.ign2 and"
1021 echo "all databases have been reloaded. The script will track any changes"
1022 echo "to the offending signature and will automatically remove it if the"
1023 echo "signature is modified or removed from the third-party database."
1026 echo "Failed to successfully update my-whitelist.ign2 file - SKIPPING."
1030 echo "Clamscan reports my-whitelist.ign2 database integrity is bad - SKIPPING."
1034 echo "Signature '$input' already exists in my-whitelist.ign2 - no action taken."
1038 echo "Signature '$input' could not be found."
1040 echo "This script will only create a whitelise entry in my-whitelist.ign2 for ClamAV"
1041 echo "'UNOFFICIAL' third-Party signatures as found in the *.ndb *.hdb *.db databases."
1044 echo "No input detected - no action taken."
1048 # Clamscan reload database
1049 function clamscan_reload_dbs () {
1050 # Reload all clamd databases if updates detected and $reload_dbs" is set to "yes"
1051 if [ "$reload_dbs" == "yes" ] ; then
1052 if [ "$do_clamd_reload" != "0" ] ; then
1053 if [ "$do_clamd_reload" == "1" ] ; then
1054 xshok_pretty_echo_and_log "Update(s) detected, reloading ClamAV databases" "="
1055 elif [ "$do_clamd_reload" == "2" ] ; then
1056 xshok_pretty_echo_and_log "Database removal(s) detected, reloading ClamAV databases" "="
1057 elif [ "$do_clamd_reload" == "3" ] ; then
1058 xshok_pretty_echo_and_log "File 'local.ign' has changed, reloading ClamAV databases" "="
1059 elif [ "$do_clamd_reload" == "4" ] ; then
1060 xshok_pretty_echo_and_log "File 'my-whitelist.ign2' has changed, reloading ClamAV databases" "="
1062 xshok_pretty_echo_and_log "Update(s) detected, reloading ClamAV databases" "="
1065 if [[ "$($clamd_reload_opt 2>&1)" = *"ERROR"* ]] ; then
1066 xshok_pretty_echo_and_log "ERROR: Failed to reload, trying again" "-"
1067 if [ -r "$clamd_pid" ] ; then
1068 mypid="$(cat "$clamd_pid")"
1070 if [ $? -eq 0 ] ; then
1071 xshok_pretty_echo_and_log "ClamAV databases Reloaded" "="
1073 xshok_pretty_echo_and_log "ERROR: Failed to reload, forcing clamd to restart" "-"
1074 if [ -z "$clamd_restart_opt" ] ; then
1075 xshok_pretty_echo_and_log "WARNING: Check the script's configuration file, 'reload_dbs' enabled but no 'clamd_restart_opt'" "*"
1077 $clamd_restart_opt > /dev/null
1078 if [ $? -eq 0 ] ; then
1079 xshok_pretty_echo_and_log "ClamAV Restarted" "="
1081 xshok_pretty_echo_and_log "ClamAV NOT Restarted" "-"
1086 xshok_pretty_echo_and_log "ERROR: Failed to reload, forcing clamd to restart" "-"
1087 if [ -z "$clamd_restart_opt" ] ; then
1088 xshok_pretty_echo_and_log "WARNING: Check the script's configuration file, 'reload_dbs' enabled but no 'clamd_restart_opt'" "*"
1090 $clamd_restart_opt > /dev/null
1091 if [ $? -eq 0 ] ; then
1092 xshok_pretty_echo_and_log "ClamAV Restarted" "="
1094 xshok_pretty_echo_and_log "ClamAV NOT Restarted" "-"
1099 xshok_pretty_echo_and_log "ClamAV databases Reloaded" "="
1102 xshok_pretty_echo_and_log "No updates detected, ClamAV databases were not reloaded" "="
1105 xshok_pretty_echo_and_log "Database reload has been disabled in the configuration file" "="
1110 # If ClamD status check is enabled ("clamd_socket" variable is uncommented
1111 # and the socket path is correctly specified in "User Edit" section above),
1112 # then test to see if clamd is running or not.
1113 function check_clamav () {
1114 if [ -n "$clamd_socket" ] ; then
1115 if [ -S "$clamd_socket" ] ; then
1116 if [ "$(perl -e 'use IO::Socket::UNIX; print $IO::Socket::UNIX::VERSION,"\n"' 2>/dev/null)" ] ; then
1118 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
1120 xshok_pretty_echo_and_log "ClamD is running" "="
1123 socat="$(which socat 2>/dev/null)"
1124 if [ -n "$socat" ] && [ -x "$socat" ] ; then
1126 if [ "$( (echo "PING"; sleep 1;) | socat - "$clamd_socket" 2>/dev/null)" == "PONG" ] ; then
1128 xshok_pretty_echo_and_log "ClamD is running" "="
1132 if [ -z "$io_socket1" ] && [ -z "$socket_cat1" ] ; then
1133 xshok_pretty_echo_and_log "WARNING: socat or perl module 'IO::Socket::UNIX' not found, cannot test if ClamD is running" "*"
1135 if [ -z "$io_socket2" ] && [ -z "$socket_cat2" ] ; then
1137 xshok_pretty_echo_and_log "ALERT: CLAMD IS NOT RUNNING!" "="
1138 if [ -n "$clamd_restart_opt" ] ; then
1139 xshok_pretty_echo_and_log "Attempting to start ClamD..." "-"
1140 if [ -n "$io_socket1" ] ; then
1141 $clamd_restart_opt > /dev/null && sleep 5
1142 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
1143 xshok_pretty_echo_and_log "ClamD was successfully started" "="
1145 xshok_pretty_echo_and_log "ERROR: CLAMD FAILED TO START" "="
1149 if [ -n "$socket_cat1" ] ; then
1150 $clamd_restart_opt > /dev/null && sleep 5
1151 if [ "$( (echo "PING"; sleep 1;) | socat - "$clamd_socket" 2>/dev/null)" == "PONG" ] ; then
1152 xshok_pretty_echo_and_log "ClamD was successfully started" "="
1154 xshok_pretty_echo_and_log "ERROR: CLAMD FAILED TO START" "="
1163 xshok_pretty_echo_and_log "WARNING: $clamd_socket is not a usable socket" "*"
1166 xshok_pretty_echo_and_log "WARNING: clamd_socket is not defined in the configuration file" "*"
1170 # Check for a new version
1171 function check_new_version () {
1172 if [ -n "$wget_bin" ] ; then
1173 # shellcheck disable=SC2086
1174 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)"
1176 # shellcheck disable=SC2086
1177 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)"
1179 if [ "$latest_version" ] ; then
1180 if [ "$latest_version" != "$script_version" ] ; then
1181 xshok_pretty_echo_and_log "New version : v$latest_version @ https://github.com/extremeshok/clamav-unofficial-sigs" "-"
1186 # Check for a new version
1187 function check_new_config_version () {
1188 if [ -n "$wget_bin" ] ; then
1189 # shellcheck disable=SC2086
1190 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)"
1192 # shellcheck disable=SC2086
1193 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)"
1195 if [ "$latest_config_version" ] ; then
1196 if [ "$latest_config_version" != "$config_version" ] ; then
1197 xshok_pretty_echo_and_log "New configversion : v${latest_config_version} @ https://github.com/extremeshok/clamav-unofficial-sigs" "-"
1202 # Display help and usage
1204 # help_and_usage "1" - enables the man output formatting
1205 # help_and_usage - normal help output formatting
1206 function help_and_usage () {
1209 # option_format_start
1213 # option_format_blankline
1215 # option_format_tab_line
1218 # option_format_start
1222 # option_format_blankline
1224 # option_format_tab_line
1228 helpcontents="$(cat << EOF
1229 $ofs Usage: $(basename "$0") $ofe [OPTION] [PATH|FILE]
1231 $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
1233 $ofs -F, --force $ofe Force all databases to be downloaded, could cause ip to be blocked
1235 $ofs -h, --help $ofe Display this script's help and usage information
1237 $ofs -V, --version $ofe Output script version and date information
1239 $ofs -v, --verbose $ofe Be verbose, enabled when not run under cron
1241 $ofs -s, --silence $ofe Only output error messages, enabled when run under cron
1243 $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
1245 $ofs -e, --encode-string $ofe Hexadecimal encode an entire input string that can $oft be used in any '*.ndb' signature database file
1247 $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
1249 $ofs -g, --gpg-verify $ofe GPG verify a specific Sanesecurity database file $oft eg: '-g filename.ext' (do not include file path)
1251 $ofs -i, --information $ofe Output system and configuration information for $oft viewing or possible debugging purposes
1253 $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
1255 $ofs -t, --test-database $ofe Clamscan integrity test a specific database file $oft eg: '-t filename.ext' (do not include file path)
1257 $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
1259 $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
1261 $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
1263 $ofs --install-all $ofe Install and generate the cron, logroate and man files, autodetects the values $oft based on your config files
1265 $ofs --install-cron $ofe Install and generate the cron file, autodetects the values $oft based on your config files
1267 $ofs --install-logrotate $ofe Install and generate the logrotate file, autodetects the $oft values based on your config files
1269 $ofs --install-man $ofe Install and generate the man file, autodetects the $oft values based on your config files
1271 $ofs --remove-script $ofe Remove the clamav-unofficial-sigs script and all of $oft its associated files and databases from the system
1274 )" # This is very important
1276 echo "${helpcontents//-/\\-}"
1278 echo -e "$helpcontents"
1282 ################################################################################
1284 ################################################################################
1287 script_version="5.6.2"
1288 script_version_date="2017-03-19"
1289 minimum_required_config_version="72"
1290 minimum_yara_clamav_version="0.99"
1292 # Default config files
1293 config_dir="/etc/clamav-unofficial-sigs"
1294 config_files=( "$config_dir/master.conf" "$config_dir/os.conf" "$config_dir/user.conf" )
1299 comment_silence="no"
1300 logging_enabled="no"
1304 we_have_a_config="0"
1306 # Solaris which function returns garbage when the program is not found
1307 # only define the new which function if running under Solaris
1308 if [ "$(uname -s)" == "SunOS" ] ; then
1310 # Use the switch -p to ignore ksh internal commands
1315 # Default Binaries & Commands
1316 uname_bin="$(which uname 2> /dev/null)"
1317 clamscan_bin="$(which clamscan 2> /dev/null)"
1318 rsync_bin="$(which rsync 2> /dev/null)"
1319 # Detect support for wget
1320 if [ -x /usr/sfw/bin/wget ] ; then
1321 wget_bin="/usr/sfw/bin/wget"
1323 wget_bin="$(which wget 2> /dev/null)"
1325 if [ -z "$wget_bin" ] ; then
1326 curl_bin="$(which curl 2> /dev/null)"
1327 if [ -z "$curl_bin" ] ; then
1328 xshok_pretty_echo_and_log "ERROR: both wget and curl commands are missing, One of them is required" "="
1333 # Detect supprot for gnu grep
1334 if [ -x /usr/gnu/bin/grep ] ; then
1335 grep_bin="/usr/gnu/bin/grep"
1337 grep_bin="$(which grep 2> /dev/null)"
1340 dig_bin="$(which dig 2> /dev/null)"
1341 if [ -z "$dig_bin" ] ; then
1342 host_bin="$(which host 2> /dev/null)"
1343 if [ -z "$host_bin" ] ; then
1344 xshok_pretty_echo_and_log "ERROR: both dig and host commands are missing, One of them is required" "="
1352 # Detect if terminal
1355 # Usage: echo "${BOLD}-a${NORM}"
1371 # Generic command line options
1374 -c|--config) xshok_check_s2 "$2"; custom_config="$2"; shift 2; break ;;
1375 -F|--force) force_updates="yes"; shift 1; break ;;
1376 -v|--verbose) force_verbose="yes"; shift 1; break ;;
1377 -s|--silence) force_verbose="no"; shift 1; break ;;
1383 if [ "$force_verbose" == "yes" ] ; then
1385 downloader_silence="no"
1388 comment_silence="no"
1391 downloader_silence="yes"
1394 comment_silence="yes"
1397 xshok_pretty_echo_and_log "" "#" "80"
1398 xshok_pretty_echo_and_log " eXtremeSHOK.com ClamAV Unofficial Signature Updater"
1399 xshok_pretty_echo_and_log " Version: v$script_version ($script_version_date)"
1400 xshok_pretty_echo_and_log " Required Configuration Version: v$minimum_required_config_version"
1401 xshok_pretty_echo_and_log " Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com"
1402 xshok_pretty_echo_and_log "" "#" "80"
1404 # Generic command line options
1407 -h|--help) help_and_usage; exit ;;
1408 -V|--version) exit ;;
1413 # CONFIG LOADING AND ERROR CHECKING ##############################################
1414 if [ "$custom_config" != "no" ] ; then
1415 if [ -d "$custom_config" ] ; then
1416 # Assign the custom config dir and remove trailing / (removes / and //)
1417 shopt -s extglob; custom_config="${custom_config%%+(/)}"
1418 config_files=( "$config_dir/master.conf" "$config_dir/os.conf" "$config_dir/user.conf" )
1420 config_files=( "$custom_config" )
1424 for config_file in "${config_files[@]}" ; do
1425 if [ -r "$config_file" ] ; then # Exists and readable
1426 we_have_a_config="1"
1428 xshok_pretty_echo_and_log "Loading config: $config_file" "="
1432 if [ "$(uname -s)" == "SunOS" ] ; then
1433 # Solaris FIXES only, i had issues with running with a single command..
1434 clean_config="$(command sed -e '/^#.*/d' "$config_file")" # Comment line
1435 #clean_config="$(echo "$clean_config" | sed -e 's/#[[:space:]].*//')" # Comment line (duplicated)
1436 clean_config=${clean_config//\#*/} # Comment line (duplicated)
1437 clean_config="$(echo "$clean_config" | sed -e '/^[[:blank:]]*#/d;s/#.*//')" # Comments at end of line
1438 #clean_config="$(echo "$clean_config" | sed -e 's/^[ \t]*//;s/[ \t]*$//')" # trailing and leading whitespace
1439 clean_config="$(echo "$clean_config" | xargs)"
1440 clean_config="$(echo "$clean_config" | sed -e '/^\s*$/d')" # Blank lines
1442 elif [ "$(uname -s)" == "Darwin" ] ; then
1443 # MacOS / OS X fixes, had issues with running with a single command and with SunOS work around..
1444 clean_config="$(command sed -e '/^#.*/d' "$config_file")" # Comment line
1445 clean_config="$(echo "$clean_config" | sed -e 's/#[[:space:]].*//')" # Comment line (duplicated)
1446 clean_config="$(echo "$clean_config" | sed -e '/^[[:blank:]]*#/d;s/#.*//')" # Comments at end of line
1447 #clean_config="$(echo "$clean_config" | sed -e 's/^[ \t]*//;s/[ \t]*$//')" # trailing and leading whitespace
1448 #clean_config="$(echo "$clean_config" | xargs)"
1449 clean_config="$(echo "$clean_config" | sed -e '/^\s*$/d')" # Blank lines
1452 # Delete lines beginning with #
1453 # Delete from " #" to end of the line
1454 # Delete from "# " to end of the line
1455 # Delete both trailing and leading whitespace
1456 # Delete all trailing whitespace
1457 # Delete all empty lines
1458 clean_config="$(command sed -e '/^#.*/d' -e 's/[[:space:]]#.*//' -e 's/#[[:space:]].*//' -e 's/^[ \t]*//;s/[ \t]*$//' -e '/^\s*$/d' "$config_file")"
1462 clean_config="${clean_config//|/\\|}"
1464 # Config error checking
1465 # Check "" are an even number
1466 config_check="${clean_config//[^\"]}"
1467 if [ "$(( ${#config_check} % 2 ))" -eq 1 ] ; then
1468 xshok_pretty_echo_and_log "ERROR: Your configuration has errors, every \" requires a closing \"" "="
1472 # Check there is an = for every set of "" optional whitespace \s* between = and "
1473 config_check_vars="$(echo "$clean_config" | $grep_bin -c '=\s*\"' )"
1475 if [ $(( ${#config_check} / 2 )) -ne "$config_check_vars" ] ; then
1476 xshok_pretty_echo_and_log "ERROR: Your configuration has errors, every = requires a pair of \"\"" "="
1481 #clean_config="${clean_config//|/\|}"
1484 for i in "${clean_config[@]}" ; do
1485 eval "$(echo "${i}" | command sed -e 's/[[:space:]]*$//' 2> /dev/null)"
1491 # Assign the log_file_path earlier and remove trailing / (removes / and //)
1492 shopt -s extglob; log_file_path="${log_file_path%%+(/)}"
1493 # Only start logging once all the configs have been loaded
1494 if [ "$logging_enabled" == "yes" ] ; then
1498 # Make sure we have a readable config file
1499 if [ "$we_have_a_config" == "0" ] ; then
1500 xshok_pretty_echo_and_log "ERROR: Config file/s could NOT be read/loaded" "="
1501 xshok_pretty_echo_and_log "Note: Possible fix would be to checkl the config dir $config_dir exists and contains config files"
1505 # Prevent some issues with an incomplete or only a user.conf being loaded
1506 if [ "$config_version" == "0" ] ; then
1507 xshok_pretty_echo_and_log "ERROR: Config file/s are missing important contents" "="
1508 xshok_pretty_echo_and_log "Note: Possible fix would be to point the script to the dir with the configs"
1512 # Config version validation
1513 if [ "$config_version" -lt "$minimum_required_config_version" ] ; then
1514 xshok_pretty_echo_and_log "ERROR: Your config version $config_version is not compatible with the min required version $minimum_required_config_version" "="
1518 # Check to see if the script's "USER CONFIGURATION FILE" has been completed.
1519 if [ "$user_configuration_complete" != "yes" ] ; then
1520 xshok_pretty_echo_and_log "WARNING: SCRIPT CONFIGURATION HAS NOT BEEN COMPLETED" "*"
1521 xshok_pretty_echo_and_log "Please review the script configuration files"
1522 xshok_pretty_echo_and_log "and uncomment the following line in user.conf"
1523 xshok_pretty_echo_and_log "#user_configuration_complete=\"yes\""
1527 # Assign the directories and remove trailing / (removes / and //)
1528 shopt -s extglob; work_dir="${work_dir%%+(/)}"
1530 # Allow overriding of all the individual workdirs, this is mainly to aid package maintainers
1531 if [ -z "$work_dir_sanesecurity" ] ; then
1532 work_dir_sanesecurity="$(echo "$work_dir/$sanesecurity_dir" | sed 's:/*$::')"
1534 shopt -s extglob; work_dir_sanesecurity="${work_dir_sanesecurity%%+(/)}"
1536 if [ -z "$work_dir_securiteinfo" ] ; then
1537 work_dir_securiteinfo="$(echo "$work_dir/$securiteinfo_dir" | sed 's:/*$::')"
1539 shopt -s extglob; work_dir_securiteinfo="${work_dir_securiteinfo%%+(/)}"
1541 if [ -z "$work_dir_linuxmalwaredetect" ] ; then
1542 work_dir_linuxmalwaredetect="$(echo "$work_dir/$linuxmalwaredetect_dir" | sed 's:/*$::')"
1544 shopt -s extglob; work_dir_malwarepatrol="${work_dir_malwarepatrol%%+(/)}"
1546 if [ -z "$work_dir_malwarepatrol" ] ; then
1547 work_dir_malwarepatrol="$(echo "$work_dir/$malwarepatrol_dir" | sed 's:/*$::')"
1549 shopt -s extglob; work_dir_malwarepatrol="${work_dir_malwarepatrol%%+(/)}"
1551 if [ -z "$work_dir_yararulesproject" ] ; then
1552 work_dir_yararulesproject="$(echo "$work_dir/$yararulesproject_dir" | sed 's:/*$::')"
1554 shopt -s extglob; work_dir_yararulesproject="${work_dir_yararulesproject%%+(/)}"
1556 if [ -z "$work_dir_add" ] ; then
1557 work_dir_add="$(echo "$work_dir/$add_dir" | sed 's:/*$::')"
1559 shopt -s extglob; work_dir_add="${work_dir_add%%+(/)}"
1561 if [ -z "$work_dir_work_configs" ] ; then
1562 work_dir_work_configs="$(echo "$work_dir/$work_dir_configs" | sed 's:/*$::')"
1564 shopt -s extglob; work_dir_work_configs="${work_dir_work_configs%%+(/)}"
1566 if [ -z "$work_dir_gpg" ] ; then
1567 work_dir_gpg="$(echo "$work_dir/$gpg_dir" | sed 's:/*$::')"
1569 shopt -s extglob; work_dir_gpg="${work_dir_gpg%%+(/)}"
1572 if [ -z "$work_dir_pid" ] ; then
1573 work_dir_pid="$(echo "$work_dir/$pid_dir" | sed 's:/*$::')"
1575 shopt -s extglob; work_dir_pid="${work_dir_pid%%+(/)}"
1578 # Assign defaults if not defined
1579 if [ -z "$cron_dir" ] ; then
1580 cron_dir="/etc/cron.d"
1582 shopt -s extglob; cron_dir="${cron_dir%%+(/)}"
1583 if [ -z "$cron_filename" ] ; then
1584 cron_filename="clamav-unofficial-sigs"
1586 if [ -z "$logrotate_dir" ] ; then
1587 logrotate_dir="/etc/logrotate.d"
1589 shopt -s extglob; logrotate_dir="${logrotate_dir%%+(/)}"
1590 if [ -z "$logrotate_filename" ] ; then
1591 logrotate_filename="clamav-unofficial-sigs"
1593 if [ -z "$man_dir" ] ; then
1594 man_dir="/usr/share/man/man8"
1596 shopt -s extglob; man_dir="${man_dir%%+(/)}"
1597 if [ -z "$man_filename" ] ; then
1598 man_filename="clamav-unofficial-sigs.8"
1600 if [ -z "$man_log_file_full_path" ] ; then
1601 man_log_file_full_path="$log_file_path/$log_file_name"
1603 # dont assign , but remove trailing /
1604 shopt -s extglob; clam_dbs="${clam_dbs%%+(/)}"
1607 # Check default Binaries & Commands are defined
1608 if [ "$reload_dbs" == "yes" ] ; then
1609 if [ -z "$clamd_reload_opt" ] ; then
1610 xshok_pretty_echo_and_log "ERROR: Missing clamd_reload_opt" "="
1614 if [ -z "$uname_bin" ] ; then
1615 xshok_pretty_echo_and_log "ERROR: uname (uname_bin) not found" "="
1618 if [ -z "$clamscan_bin" ] ; then
1619 xshok_pretty_echo_and_log "ERROR: clamscan binary (clamscan_bin) not found" "="
1622 if [ -z "$rsync_bin" ] ; then
1623 xshok_pretty_echo_and_log "ERROR: rsync binary (rsync_bin) not found" "="
1626 if [ -z "$wget_bin" ] ; then
1627 if [ -z "$curl_bin" ] ; then
1628 xshok_pretty_echo_and_log "ERROR: wget and curl binaries not found, script requires either wget or curl" "="
1632 # Check if GPG is enabled and the binary is found
1633 if [ "$enable_gpg" == "yes" ] ; then
1634 if [ -z "$gpg_bin" ] ; then
1635 if [ -x /opt/csw/bin/gpg ] ; then
1636 gpg_bin="/opt/csw/bin/gpg"
1638 gpg_bin="$(which gpg 2> /dev/null)"
1640 if [ -z "$gpg_bin" ] ; then
1641 gpg_bin="$(which gpg2 2> /dev/null)"
1644 if [ -z "$gpg_bin" ] ; then
1647 if [ ! -x "$gpg_bin" ] ; then
1651 if [ "$enable_gpg" != "yes" ] ; then
1652 xshok_pretty_echo_and_log "Notice: GnuPG / signature verification disabled" "-"
1654 # Check default directories are defined
1655 if [ -z "$work_dir" ] ; then
1656 xshok_pretty_echo_and_log "ERROR: working directory (work_dir) not defined" "="
1659 if [ -z "$clam_dbs" ] ; then
1660 xshok_pretty_echo_and_log "ERROR: clam database directory (clam_dbs) not defined" "="
1663 # Check default directories are writable
1664 if [ -e "$work_dir" ] ; then
1665 if [ ! -w "$work_dir" ] ; then
1666 xshok_pretty_echo_and_log "ERROR: working directory (work_dir) not writable $work_dir" "="
1670 if [ ! -w "$clam_dbs" ] ; then
1671 xshok_pretty_echo_and_log "ERROR: clam database directory (clam_dbs) not writable $clam_dbs" "="
1675 # Reset the update timers to force a full update.
1676 if [ "$force_updates" == "yes" ] ; then
1677 xshok_pretty_echo_and_log "Force Updates: enabled"
1678 sanesecurity_update_hours="0"
1679 securiteinfo_update_hours="0"
1680 linuxmalwaredetect_update_hours="0"
1681 malwarepatrol_update_hours="0"
1682 yararulesproject_update_hours="0"
1683 additional_update_hours="0"
1686 # Enable pid file to prevent issues with multiple instances
1687 # opted not to use flock as it appears to have issues with some systems
1688 if [ "$enable_locking" == "yes" ] ; then
1689 xshok_mkdir_ownership "$work_dir_pid"
1690 pid_file_fullpath="$work_dir_pid/clamav-unofficial-sigs.pid"
1691 if [ -f "$pid_file_fullpath" ] ; then
1692 pid_file_pid="$(cat "$pid_file_fullpath")"
1693 ps -p "$pid_file_pid" > /dev/null 2>&1
1694 if [ $? -eq 0 ] ; then
1695 xshok_pretty_echo_and_log "ERROR: Only one instance can run at the same time." "="
1698 xshok_create_pid_file "$pid_file_fullpath"
1701 xshok_create_pid_file "$pid_file_fullpath"
1703 # Run this wehen the script exits
1704 trap -- "rm -f $pid_file_fullpath" EXIT
1707 # Verify the clam_user and clam_group actually exists on the system
1708 if ! xshok_user_group_exists "$clam_user" "$clam_group" ; then
1709 xshok_pretty_echo_and_log "ERROR: Either the user: $clam_user and/or group: $clam_group does not exist on the system." "="
1713 # Silence rsync output and only report errors - useful if script is run via cron.
1714 if [ "$rsync_silence" == "yes" ] ; then
1715 rsync_output_level="--quiet"
1717 rsync_output_level="--progress"
1720 # If the local rsync client supports the "--no-motd" flag, then enable it.
1721 if $rsync_bin --help | $grep_bin -q "no-motd" > /dev/null ; then
1725 # If the local rsync client supports the "--contimeout" flag, then enable it.
1726 if $rsync_bin --help | $grep_bin -q "contimeout" > /dev/null ; then
1727 connect_timeout="--contimeout=$rsync_connect_timeout"
1730 # Silence wget output and only report errors - useful if script is run via cron.
1731 if [ "$downloader_silence" == "yes" ] ; then
1732 wget_output_level="--quiet" #--quiet
1733 curl_output_level="--silent --show-error"
1735 wget_output_level="--no-verbose"
1736 curl_output_level=""
1739 # Suppress ssl warnings
1740 if [ "$downloader_ignore_ssl" == "yes" ] ; then
1741 wget_insecure="--no-check-certificate"
1742 curl_insecure="--insecure"
1748 # This scripts name and path
1749 this_script_name="$(basename "$0")"
1750 this_script_path="$( cd "$(dirname "$0")" || exit ; pwd -P )"
1751 this_script_full_path="$this_script_path/$this_script_name"
1753 # Set the script to 755 permissions
1754 if xshok_is_root ; then
1755 if [ "$setmode" == "yes" ] ; then
1756 if [ ! -x "$this_script_path/$this_script_name" ] ; then
1757 chmod 755 "$this_script_path/$this_script_name"
1758 xshok_pretty_echo_and_log "Fixing permission on $this_script_path/$this_script_name" "="
1766 ################################################################################
1768 ################################################################################
1772 -d|--decode-sig) decode_third_party_signature_by_signature_name; exit ;;
1773 -e|--encode-string) hexadecimal_encode_entire_input_string; exit ;;
1774 -f|--encode-formatted) hexadecimal_encode_formatted_input_string; exit ;;
1775 -g|--gpg-verify) xshok_check_s2 "$2"; gpg_verify_specific_sanesecurity_database_file "$2"; exit ;;
1776 -i|--information) output_system_configuration_information; exit ;;
1777 -m|--make-database) make_signature_database_from_ascii_file; exit ;;
1778 -t|--test-database) xshok_check_s2 "$2"; clamscan_integrity_test_specific_database_file "$2"; exit ;;
1779 -o|--output-triggered) output_signatures_triggered_during_ham_directory_scan; exit ;;
1780 -w|--whitelist) add_signature_whitelist_entry; exit ;;
1781 --check-clamav) check_clamav; exit ;;
1782 --install-all) install_cron; install_logrotate; install_man; exit ;;
1783 --install-cron) install_cron; exit ;;
1784 --install-logrotate) install_logrotate; exit ;;
1785 --install-man) install_man; exit ;;
1786 --remove-script) remove_script; exit ;;
1791 xshok_pretty_echo_and_log "Preparing Databases" "="
1793 # Check yararule support is available
1794 if [ "$enable_yararules" == "yes" ] ; then
1795 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); }')"
1796 minimum_yara_clamav_version="$(echo "$minimum_yara_clamav_version" | awk -F "." '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }')"
1797 # Check current clamav version against the minimum required version for yara support
1798 if [ "$current_clamav_version" -le "$minimum_yara_clamav_version" ] ; then # Older
1799 yararulesproject_enabled="no"
1800 enable_yararules="no"
1801 xshok_pretty_echo_and_log "Notice: Yararules Disabled due to clamav being older than the minimum required version"
1804 yararulesproject_enabled="no"
1805 enable_yararules="no"
1808 # Generate the signature databases
1809 if [ "$sanesecurity_enabled" == "yes" ] ; then
1810 if [ -n "$sanesecurity_dbs" ] ; then
1811 if [ -n "$sanesecurity_dbs_rating" ] ; then
1812 temp_db="$(xshok_database "$sanesecurity_dbs_rating" "${sanesecurity_dbs[@]}")"
1814 temp_db="$(xshok_database "$default_dbs_rating" "${sanesecurity_dbs[@]}")"
1816 sanesecurity_dbs=( )
1817 sanesecurity_dbs=( $temp_db )
1820 if [ "$securiteinfo_enabled" == "yes" ] ; then
1821 if [ -n "$securiteinfo_dbs" ] ; then
1822 if [ -n "$securiteinfo_dbs_rating" ] ; then
1823 temp_db="$(xshok_database "$securiteinfo_dbs_rating" "${securiteinfo_dbs[@]}")"
1825 temp_db="$(xshok_database "$default_dbs_rating" "${securiteinfo_dbs[@]}")"
1827 securiteinfo_dbs=( )
1828 securiteinfo_dbs=( $temp_db )
1831 if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
1832 if [ -n "$linuxmalwaredetect_dbs" ] ; then
1833 if [ -n "$linuxmalwaredetect_dbs_rating" ] ; then
1834 temp_db="$(xshok_database "$linuxmalwaredetect_dbs_rating" "${linuxmalwaredetect_dbs[@]}")"
1836 temp_db="$(xshok_database "$default_dbs_rating" "${linuxmalwaredetect_dbs[@]}")"
1838 linuxmalwaredetect_dbs=( )
1839 linuxmalwaredetect_dbs=( $temp_db )
1842 if [ "$yararulesproject_enabled" == "yes" ] ; then
1843 if [ -n "$yararulesproject_dbs" ] ; then
1844 if [ -n "$yararulesproject_dbs_rating" ] ; then
1845 temp_db="$(xshok_database "$yararulesproject_dbs_rating" "${yararulesproject_dbs[@]}")"
1847 temp_db="$(xshok_database "$default_dbs_rating" "${yararulesproject_dbs[@]}")"
1849 yararulesproject_dbs=( )
1850 yararulesproject_dbs=( $temp_db )
1854 # Set the variables for MalwarePatrol
1855 if [ "$malwarepatrol_free" == "yes" ] ; then
1856 malwarepatrol_product_code="8"
1857 malwarepatrol_list="clamav_basic"
1859 if [ -z $malwarepatrol_list ] ; then
1860 malwarepatrol_list="clamav_basic"
1862 if [ -z $malwarepatrol_product_code ] ; then
1863 # Not sure, it may be better to return an error.
1864 malwarepatrol_product_code=8
1867 if [ $malwarepatrol_list == "clamav_basic" ] ; then
1868 malwarepatrol_db="malwarepatrol.db"
1870 malwarepatrol_db="malwarepatrol.ndb"
1872 malwarepatrol_url="$malwarepatrol_url?product=$malwarepatrol_product_code&list=$malwarepatrol_list"
1874 # If "ham_dir" variable is set, then create initial whitelist files (skipped if first-time script run).
1875 test_dir="$work_dir/test"
1876 if [ -n "$ham_dir" ] && [ -d "$work_dir" ] && [ ! -d "$test_dir" ] ; then
1877 if [ -d "$ham_dir" ] ; then
1878 xshok_mkdir_ownership "$test_dir"
1879 cp -f "$work_dir"/*/*.ndb "$test_dir"
1880 $clamscan_bin --infected --no-summary -d "$test_dir" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' >> "$work_dir_work_configs/whitelist.txt"
1881 $grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir"/* | cut -d "*" -f 2 | sort | uniq > "$work_dir_work_configs/whitelist.hex"
1882 cd "$test_dir" || exit
1883 for db_file in * ; do
1884 [[ -e $db_file ]] || break # Handle the case of no files
1885 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$db_file" > "$db_file-tmp"
1886 mv -f "$db_file-tmp" "$db_file"
1887 if $clamscan_bin --quiet -d "$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
1888 if $rsync_bin -pcqt "$db_file" "$clam_dbs" ; then
1889 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
1890 if [ "$selinux_fixes" == "yes" ] ; then
1891 restorecon "$clam_dbs/$db_file"
1897 if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
1898 xshok_pretty_echo_and_log "Initial HAM directory scan whitelist file created in $work_dir_work_configs"
1900 xshok_pretty_echo_and_log "No false-positives detected in initial HAM directory scan"
1903 xshok_pretty_echo_and_log "WARNING: Cannot locate HAM directory: $ham_dir"
1904 xshok_pretty_echo_and_log "Skipping initial whitelist file creation. Fix 'ham_dir' path in config file"
1908 # Check to see if the working directories have been created. If not, create them. Otherwise, ignore and proceed with script.
1909 xshok_mkdir_ownership "$work_dir"
1910 xshok_mkdir_ownership "$work_dir_securiteinfo"
1911 xshok_mkdir_ownership "$work_dir_malwarepatrol"
1912 xshok_mkdir_ownership "$work_dir_linuxmalwaredetect"
1913 xshok_mkdir_ownership "$work_dir_sanesecurity"
1914 xshok_mkdir_ownership "$work_dir_yararulesproject"
1915 xshok_mkdir_ownership "$work_dir_work_configs"
1916 xshok_mkdir_ownership "$work_dir_gpg"
1917 xshok_mkdir_ownership "$work_dir_add"
1919 # Set secured access permissions to the GPG directory
1920 perms chmod -f 0700 "$work_dir_gpg"
1922 if [ "$enable_gpg" == "yes" ] ; then
1923 # If we haven't done so yet, download Sanesecurity public GPG key and import to custom keyring.
1924 if [ ! -s "$work_dir_gpg/publickey.gpg" ] ; then
1925 xshok_file_download "$work_dir_gpg/publickey.gpg" "$sanesecurity_gpg_url"
1927 if [ "$ret" -ne 0 ] ; then
1928 xshok_pretty_echo_and_log "ALERT: Could not download Sanesecurity public GPG key" "*"
1931 xshok_pretty_echo_and_log "Sanesecurity public GPG key successfully downloaded"
1932 rm -f -- "$work_dir_gpg/ss-keyring.gp*"
1933 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
1934 xshok_pretty_echo_and_log "ALERT: could not import Sanesecurity public GPG key to custom keyring" "*"
1937 chmod -f 0644 "$work_dir_gpg/*.*"
1938 xshok_pretty_echo_and_log "Sanesecurity public GPG key successfully imported to custom keyring"
1943 # If custom keyring is missing, try to re-import Sanesecurity public GPG key.
1944 if [ ! -s "$work_dir_gpg/ss-keyring.gpg" ] ; then
1945 rm -f -- "$work_dir_gpg/ss-keyring.gp*"
1946 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
1947 xshok_pretty_echo_and_log "ALERT: Custom keyring MISSING or CORRUPT! Could not import Sanesecurity public GPG key to custom keyring" "*"
1950 chmod -f 0644 "$work_dir_gpg/*.*"
1951 xshok_pretty_echo_and_log "Sanesecurity custom keyring MISSING! GPG key successfully re-imported to custom keyring"
1956 # Database update check, time randomization section. This script now
1957 # provides support for both bash and non-bash enabled system shells.
1958 if [ "$enable_random" == "yes" ] ; then
1959 if [ -n "$RANDOM" ] ; then
1960 sleep_time="$((RANDOM * $((max_sleep_time - min_sleep_time)) / 32767 + min_sleep_time))"
1963 while [ "$sleep_time" -lt "$min_sleep_time" ] || [ "$sleep_time" -gt "$max_sleep_time" ] ; do
1964 sleep_time="$(head -n 1 /dev/urandom | cksum | awk '{print $2}')"
1967 if [ ! -t 0 ] ; then
1968 xshok_pretty_echo_and_log "$(date) - Pausing database file updates for $sleep_time seconds..."
1970 xshok_pretty_echo_and_log "$(date) - Pause complete, checking for new database files..."
1974 # Create "scan-test.txt" file for clamscan database integrity testing.
1975 if [ ! -s "$work_dir_work_configs/scan-test.txt" ] ; then
1976 echo "This is the clamscan test file..." > "$work_dir_work_configs/scan-test.txt"
1979 # If rsync proxy is defined in the config file, then export it for use.
1980 if [ -n "$rsync_proxy" ] ; then
1981 RSYNC_PROXY="$rsync_proxy"
1985 # Create $current_dbsfiles containing lists of current and previously active 3rd-party databases
1986 # so that databases and/or backup files that are no longer being used can be removed.
1987 current_tmp="$work_dir_work_configs/current-dbs.tmp"
1989 current_dbs_file="$work_dir_work_configs/current-dbs.txt"
1991 if [ "$sanesecurity_enabled" == "yes" ] ; then
1992 # Create the Sanesecurity rsync "include" file (defines which files to download).
1993 sanesecurity_include_dbs="$work_dir_work_configs/ss-include-dbs.txt"
1994 if [ -n "${sanesecurity_dbs[0]}" ] ; then
1995 rm -f -- "$sanesecurity_include_dbs" "$work_dir_sanesecurity/*.sha256"
1996 for db_file in "${sanesecurity_dbs[@]}" ; do
1997 echo "$db_file" >> "$sanesecurity_include_dbs"
1998 echo "$db_file.sig" >> "$sanesecurity_include_dbs"
1999 echo "$work_dir_sanesecurity/$db_file" >> "$current_tmp"
2000 echo "$work_dir_sanesecurity/$db_file.sig" >> "$current_tmp"
2005 if [ "$securiteinfo_enabled" == "yes" ] ; then
2006 if [ -n "${securiteinfo_dbs[0]}" ] ; then
2007 for db in "${securiteinfo_dbs[@]}" ; do
2008 echo "$work_dir_securiteinfo/$db" >> "$current_tmp"
2013 if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
2014 if [ -n "${linuxmalwaredetect_dbs[0]}" ] ; then
2015 for db in "${linuxmalwaredetect_dbs[@]}" ; do
2016 echo "$work_dir_linuxmalwaredetect/$db" >> "$current_tmp"
2021 if [ "$malwarepatrol_enabled" == "yes" ] ; then
2022 if [ -n "$malwarepatrol_db" ] ; then
2023 echo "$work_dir_malwarepatrol/$malwarepatrol_db" >> "$current_tmp"
2027 if [ "$yararulesproject_enabled" == "yes" ] ; then
2028 if [ -n "${yararulesproject_dbs[0]}" ] ; then
2029 for db in "${yararulesproject_dbs[@]}" ; do
2030 if echo "$db" | $grep_bin -q "/"; then
2031 db="$(echo "$db" | cut -d "/" -f 2)"
2033 echo "$work_dir_yararulesproject/$db" >> "$current_tmp"
2038 if [ "$additional_enabled" == "yes" ] ; then
2039 if [ -n "$additional_dbs" ] ; then
2040 for db in "${additional_dbs[@]}" ; do
2041 echo "$work_dir_add/$db" >> "$current_tmp"
2046 sort "$current_tmp" > "$current_dbs_file" 2>/dev/null
2047 rm -f "$current_tmp"
2049 # Remove 3rd-party databases and/or backup files that are no longer being used.
2050 if [ "$remove_disabled_databases" == "yes" ] ; then
2051 previous_dbs="$work_dir_work_configs/previous-dbs.txt"
2052 sort "$current_dbs_file" > "$previous_dbs" 2>/dev/null
2053 # Do not remove the current_dbs_file
2054 #rm -f "$current_dbs_file"
2056 db_changes="$work_dir_work_configs/db-changes.txt"
2057 if [ ! -s "$previous_dbs" ] ; then
2058 cp -f "$current_dbs_file" "$previous_dbs" 2>/dev/null
2060 diff "$current_dbs_file" "$previous_dbs" 2>/dev/null | $grep_bin ">" | awk '{print $2}' > "$db_changes"
2061 if [ -r "$db_changes" ] ; then
2062 if $grep_bin -vq "bak" "$db_changes" 2>/dev/null ; then
2065 while read -r file ; do
2067 xshok_pretty_echo_and_log "Unused/Disabled file removed: $file"
2068 done < "$db_changes"
2072 # Create "purge.txt" file for package maintainers to support package uninstall.
2073 purge="$work_dir_work_configs/purge.txt"
2074 cp -f "$current_dbs_file" "$purge"
2076 echo "$work_dir_work_configs/current-dbs.txt"
2077 echo "$work_dir_work_configs/db-changes.txt"
2078 echo "$work_dir_work_configs/last-mbl-update.txt"
2079 echo "$work_dir_work_configs/last-si-update.txt"
2080 echo "$work_dir_work_configs/local.ign"
2081 echo "$work_dir_work_configs/monitor-ign.txt"
2082 echo "$work_dir_work_configs/my-whitelist.ign2"
2083 echo "$work_dir_work_configs/tracker.txt"
2084 echo "$work_dir_work_configs/previous-dbs.txt"
2085 echo "$work_dir_work_configs/scan-test.txt"
2086 echo "$work_dir_work_configs/ss-include-dbs.txt"
2087 echo "$work_dir_work_configs/whitelist.hex"
2088 echo "$work_dir_gpg/publickey.gpg"
2089 echo "$work_dir_gpg/secring.gpg"
2090 echo "$work_dir_gpg/ss-keyring.gpg*"
2091 echo "$work_dir_gpg/trustdb.gpg"
2092 echo "$log_file_path/$log_file_name*"
2093 echo "$work_dir_work_configs/purge.txt"
2096 # Check and save current system time since epoch for time related database downloads.
2097 # However, if unsuccessful, issue a warning that we cannot calculate times since epoch.
2098 if [ -n "${securiteinfo_dbs[0]}" ] || [ -n "$malwarepatrol_db" ] ; then
2099 current_time="$(date "+%s" 2> /dev/null)"
2100 current_time="${current_time//[^0-9]/}"
2101 current_time="$((current_time + 0))"
2102 if [ "$current_time" -le 0 ] ; then
2103 current_time="$(perl -le print+time 2> /dev/null)"
2105 if [ "$current_time" -le 0 ] ; then
2106 xshok_pretty_echo_and_log "WARNING: No support for 'date +%s' or 'perl' was not found , SecuriteInfo and MalwarePatrol updates bypassed" "="
2112 ################################################################
2113 # Check for Sanesecurity database & GPG signature file updates #
2114 ################################################################
2116 if [ "$sanesecurity_enabled" == "yes" ] ; then
2117 if [ -n "${sanesecurity_dbs[0]}" ] ; then
2118 if [ ${#sanesecurity_dbs} -lt 1 ] ; then
2119 xshok_pretty_echo_and_log "Failed sanesecurity_dbs config is invalid or not defined - SKIPPING"
2121 if [ -r "$work_dir_work_configs/last-ss-update.txt" ] ; then
2122 last_sanesecurity_update="$(cat "$work_dir_work_configs/last-ss-update.txt")"
2124 last_sanesecurity_update="0"
2127 update_interval="$((sanesecurity_update_hours * 3600))"
2128 time_interval="$((current_time - last_sanesecurity_update))"
2129 if [ "$time_interval" -ge $((update_interval - 600)) ] ; then
2130 echo "$current_time" > "$work_dir_work_configs/last-ss-update.txt"
2131 xshok_pretty_echo_and_log "Sanesecurity Database & GPG Signature File Updates" "="
2132 xshok_pretty_echo_and_log "Checking for Sanesecurity updates..."
2134 sanesecurity_mirror_ips="$(dig +ignore +short "$sanesecurity_url")"
2135 # Add fallback to host if dig returns no records
2136 if [ ${#sanesecurity_mirror_ips} -lt 1 ] ; then
2137 sanesecurity_mirror_ips="$(host -t A "$sanesecurity_url" | sed -n '/has address/{s/.*address \([^ ]*\).*/\1/;p;}')"
2140 if [ ${#sanesecurity_mirror_ips} -ge 1 ] ; then
2141 for sanesecurity_mirror_ip in $sanesecurity_mirror_ips ; do
2142 sanesecurity_mirror_name=""
2143 sanesecurity_mirror_name="$(dig +short -x "$sanesecurity_mirror_ip" | command sed 's/\.$//')"
2144 # Add fallback to host if dig returns no records
2145 if [ -z "$sanesecurity_mirror_name" ] ; then
2146 sanesecurity_mirror_name="$(host "$sanesecurity_mirror_ip" | sed -n '/name pointer/{s/.*pointer \([^ ]*\).*\.$/\1/;p;}')"
2148 sanesecurity_mirror_site_info="$sanesecurity_mirror_name $sanesecurity_mirror_ip"
2149 xshok_pretty_echo_and_log "Sanesecurity mirror site used: $sanesecurity_mirror_site_info"
2150 # shellcheck disable=SC2086
2151 $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
2153 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
2154 sanesecurity_rsync_success="1"
2155 for db_file in "${sanesecurity_dbs[@]}" ; do
2156 if ! cmp -s "$work_dir_sanesecurity/$db_file" "$clam_dbs/$db_file" ; then
2157 xshok_pretty_echo_and_log "Testing updated Sanesecurity database file: $db_file"
2159 if [ "$enable_gpg" == "yes" ] ; then
2160 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
2161 $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
2166 if [ "$ret" -eq 0 ] ; then
2167 test "$gpg_silence" = "no" && xshok_pretty_echo_and_log "Sanesecurity GPG Signature tested good on $db_file database"
2169 xshok_pretty_echo_and_log "Sanesecurity GPG Signature test FAILED on $db_file database - SKIPPING"
2172 if [ "$ret" -eq 0 ] ; then
2173 db_ext="${db_file#*.}"
2174 if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
2175 if $clamscan_bin --quiet -d "$work_dir_sanesecurity/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2176 xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested good"
2179 xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested BAD"
2180 if [ "$remove_bad_database" == "yes" ] ; then
2181 if rm -f "$work_dir_sanesecurity/$db_file" ; then
2182 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_sanesecurity/$db_file"
2186 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
2187 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2188 if [ "$selinux_fixes" == "yes" ] ; then
2189 restorecon "$clam_dbs/$db_file"
2192 xshok_pretty_echo_and_log "Successfully updated Sanesecurity production database file: $db_file"
2193 sanesecurity_update=1
2196 xshok_pretty_echo_and_log "Failed to successfully update Sanesecurity production database file: $db_file - SKIPPING"
2200 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_sanesecurity/$db_file" > "$test_dir/$db_file"
2201 $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"
2202 $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"
2203 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2204 mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2205 if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2206 xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested good"
2209 xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested BAD"
2210 # DO NOT KILL THIS DB
2212 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
2213 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2214 if [ "$selinux_fixes" == "yes" ] ; then
2215 restorecon "$clam_dbs/$db_file"
2217 xshok_pretty_echo_and_log "Successfully updated Sanesecurity production database file: $db_file"
2218 sanesecurity_update=1
2221 xshok_pretty_echo_and_log "Failed to successfully update Sanesecurity production database file: $db_file - SKIPPING"
2227 if [ ! "$sanesecurity_update" == "1" ] ; then
2228 xshok_pretty_echo_and_log "No Sanesecurity database file updates found" "-"
2234 xshok_pretty_echo_and_log "Connection to $sanesecurity_mirror_site_info failed - Trying next mirror site..."
2237 if [ ! "$sanesecurity_rsync_success" == "1" ] ; then
2238 xshok_pretty_echo_and_log "Access to all Sanesecurity mirror sites failed - Check for connectivity issues"
2239 xshok_pretty_echo_and_log "or signature database name(s) misspelled in the script's configuration file."
2242 xshok_pretty_echo_and_log "No Sanesecurity mirror sites found - Check for dns/connectivity issues"
2245 xshok_pretty_echo_and_log "Sanesecurity Database File Updates" "="
2246 xshok_draw_time_remaining "$((update_interval - time_interval))" "$sanesecurity_update_hours" "sanesecurity"
2251 if [ -n "${sanesecurity_dbs[0]}" ] ; then
2252 if [ "$remove_disabled_databases" == "yes" ] ; then
2253 xshok_pretty_echo_and_log "Removing disabled Sanesecurity Database files"
2254 for db_file in "${sanesecurity_dbs[@]}" ; do
2255 if echo "$db_file" | $grep_bin -q "|"; then
2256 db_file="${db_file%|*}"
2258 if [ -r "$work_dir_sanesecurity/$db_file" ] ; then
2259 xshok_pretty_echo_and_log "Removing $work_dir_sanesecurity/$db_file"
2260 rm -f "$work_dir_sanesecurity/$db_file"
2263 if [ -r "$clam_dbs/$db_file" ] ; then
2264 xshok_pretty_echo_and_log "Removing $clam_dbs/$db_file"
2265 rm -f "$clam_dbs/$db_file"
2273 ##############################################################################################################################################
2274 # Check for updated SecuriteInfo database files every set number of hours as defined in the "USER CONFIGURATION" section of this script #
2275 ##############################################################################################################################################
2276 if [ "$securiteinfo_enabled" == "yes" ] ; then
2277 if [ "$securiteinfo_authorisation_signature" != "YOUR-SIGNATURE-NUMBER" ] ; then
2278 if [ -n "$securiteinfo_dbs" ] ; then
2279 if [ ${#securiteinfo_dbs} -lt 1 ] ; then
2280 xshok_pretty_echo_and_log "Failed securiteinfo_dbs config is invalid or not defined - SKIPPING"
2282 rm -f "$work_dir_securiteinfo/*.gz"
2283 if [ -r "$work_dir_work_configs/last-si-update.txt" ] ; then
2284 last_securiteinfo_update="$(cat "$work_dir_work_configs/last-si-update.txt")"
2286 last_securiteinfo_update="0"
2290 update_interval="$((securiteinfo_update_hours * 3600))"
2291 time_interval="$((current_time - last_securiteinfo_update))"
2292 if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
2293 echo "$current_time" > "$work_dir_work_configs/last-si-update.txt"
2294 xshok_pretty_echo_and_log "SecuriteInfo Database File Updates" "="
2295 xshok_pretty_echo_and_log "Checking for SecuriteInfo updates..."
2296 securiteinfo_updates="0"
2297 for db_file in "${securiteinfo_dbs[@]}" ; do
2298 if [ "$loop" == "1" ] ; then
2299 xshok_pretty_echo_and_log "---"
2301 xshok_pretty_echo_and_log "Checking for updated SecuriteInfo database file: $db_file"
2302 securiteinfo_db_update="0"
2303 xshok_file_download "$work_dir_securiteinfo/$db_file" "$securiteinfo_url/$securiteinfo_authorisation_signature/$db_file"
2305 if [ "$ret" -eq 0 ] ; then
2307 if ! cmp -s "$work_dir_securiteinfo/$db_file" "$clam_dbs/$db_file" ; then
2308 if [ $? -eq 0 ] ; then
2309 db_ext="${db_file#*.}"
2311 xshok_pretty_echo_and_log "Testing updated SecuriteInfo database file: $db_file"
2312 if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ]
2314 if $clamscan_bin --quiet -d "$work_dir_securiteinfo/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2316 xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested good"
2319 xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested BAD"
2320 if [ "$remove_bad_database" == "yes" ] ; then
2321 if rm -f "$work_dir_securiteinfo/$db_file" ; then
2322 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_securiteinfo/$db_file"
2326 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
2327 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2328 if [ "$selinux_fixes" == "yes" ] ; then
2329 restorecon "$clam_dbs/$db_file"
2331 xshok_pretty_echo_and_log "Successfully updated SecuriteInfo production database file: $db_file"
2332 securiteinfo_updates=1
2333 securiteinfo_db_update=1
2336 xshok_pretty_echo_and_log "Failed to successfully update SecuriteInfo production database file: $db_file - SKIPPING"
2339 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_securiteinfo/$db_file" > "$test_dir/$db_file"
2340 $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"
2341 $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"
2342 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2343 mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2344 if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2346 xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested good"
2349 xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested BAD"
2350 rm -f "$work_dir_securiteinfo/$db_file"
2351 if [ "$remove_bad_database" == "yes" ] ; then
2352 if rm -f "$work_dir_securiteinfo/$db_file" ; then
2353 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_securiteinfo/$db_file"
2357 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
2358 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2359 if [ "$selinux_fixes" == "yes" ] ; then
2360 restorecon "$clam_dbs/$db_file"
2362 xshok_pretty_echo_and_log "Successfully updated SecuriteInfo production database file: $db_file"
2363 securiteinfo_updates=1
2364 securiteinfo_db_update=1
2367 xshok_pretty_echo_and_log "Failed to successfully update SecuriteInfo production database file: $db_file - SKIPPING"
2373 xshok_pretty_echo_and_log "Failed connection to $securiteinfo_url - SKIPPED SecuriteInfo $db_file update"
2375 if [ "$securiteinfo_db_update" != "1" ] ; then
2376 xshok_pretty_echo_and_log "No updated SecuriteInfo $db_file database file found" "-"
2379 if [ "$securiteinfo_updates" != "1" ] ; then
2380 xshok_pretty_echo_and_log "No SecuriteInfo database file updates found" "-"
2383 xshok_pretty_echo_and_log "SecuriteInfo Database File Updates" "="
2384 xshok_draw_time_remaining "$((update_interval - time_interval))" "$securiteinfo_update_hours" "SecuriteInfo"
2390 if [ -n "$securiteinfo_dbs" ] ; then
2391 if [ "$remove_disabled_databases" == "yes" ] ; then
2392 xshok_pretty_echo_and_log "Removing disabled SecuriteInfo Database files"
2393 for db_file in "${securiteinfo_dbs[@]}" ; do
2394 if echo "$db_file" | $grep_bin -q "|"; then
2395 db_file="${db_file%|*}"
2397 if [ -r "$work_dir_securiteinfo/$db_file" ] ; then
2398 xshok_pretty_echo_and_log "Removing $work_dir_securiteinfo/$db_file"
2399 rm -f "$work_dir_securiteinfo/$db_file"
2402 if [ -r "$clam_dbs/$db_file" ] ; then
2403 xshok_pretty_echo_and_log "Removing $clam_dbs/$db_file"
2404 rm -f "$clam_dbs/$db_file"
2413 ##############################################################################################################################################
2414 # Check for updated linuxmalwaredetect database files every set number of hours as defined in the "USER CONFIGURATION" section of this script
2415 ##############################################################################################################################################
2416 if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
2417 if [ -n "${linuxmalwaredetect_dbs[0]}" ] ; then
2418 if [ ${#linuxmalwaredetect_dbs} -lt 1 ] ; then
2419 xshok_pretty_echo_and_log "Failed linuxmalwaredetect_dbs config is invalid or not defined - SKIPPING"
2421 rm -f "$work_dir_linuxmalwaredetect/*.gz"
2422 if [ -r "$work_dir_work_configs/last-linuxmalwaredetect-update.txt" ] ; then
2423 last_linuxmalwaredetect_update="$(cat "$work_dir_work_configs/last-linuxmalwaredetect-update.txt")"
2425 last_linuxmalwaredetect_update="0"
2429 update_interval="$((linuxmalwaredetect_update_hours * 3600))"
2430 time_interval="$((current_time - last_linuxmalwaredetect_update))"
2431 if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
2432 echo "$current_time" > "$work_dir_work_configs/last-linuxmalwaredetect-update.txt"
2434 xshok_pretty_echo_and_log "linuxmalwaredetect Database File Updates" "="
2435 xshok_pretty_echo_and_log "Checking for linuxmalwaredetect updates..."
2436 linuxmalwaredetect_updates="0"
2437 for db_file in "${linuxmalwaredetect_dbs[@]}" ; do
2438 if [ "$loop" == "1" ] ; then
2439 xshok_pretty_echo_and_log "---"
2441 xshok_pretty_echo_and_log "Checking for updated linuxmalwaredetect database file: $db_file"
2442 linuxmalwaredetect_db_update="0"
2443 xshok_file_download "$work_dir_linuxmalwaredetect/$db_file" "$linuxmalwaredetect_url/$db_file"
2445 if [ "$ret" -eq 0 ] ; then
2447 if ! cmp -s "$work_dir_linuxmalwaredetect/$db_file" "$clam_dbs/$db_file" ; then
2448 if [ $? -eq 0 ] ; then
2449 db_ext="${db_file#*.}"
2451 xshok_pretty_echo_and_log "Testing updated linuxmalwaredetect database file: $db_file"
2452 if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
2453 if $clamscan_bin --quiet -d "$work_dir_linuxmalwaredetect/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2455 xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested good"
2458 xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested BAD"
2459 if [ "$remove_bad_database" == "yes" ] ; then
2460 if rm -f "$work_dir_linuxmalwaredetect/$db_file" ; then
2461 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_linuxmalwaredetect/$db_file"
2465 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
2466 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2467 if [ "$selinux_fixes" == "yes" ] ; then
2468 restorecon "$clam_dbs/local.ign"
2470 xshok_pretty_echo_and_log "Successfully updated linuxmalwaredetect production database file: $db_file"
2471 linuxmalwaredetect_updates=1
2472 linuxmalwaredetect_db_update=1
2475 xshok_pretty_echo_and_log "Failed to successfully update linuxmalwaredetect production database file: $db_file - SKIPPING"
2478 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_linuxmalwaredetect/$db_file" > "$test_dir/$db_file"
2479 $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"
2480 $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"
2481 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2482 mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2483 if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2484 xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested good"
2487 xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested BAD"
2488 if [ "$remove_bad_database" == "yes" ] ; then
2489 if rm -f "$work_dir_linuxmalwaredetect/$db_file" ; then
2490 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_linuxmalwaredetect/$db_file"
2494 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
2495 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2496 if [ "$selinux_fixes" == "yes" ] ; then
2497 restorecon "$clam_dbs/$db_file"
2499 xshok_pretty_echo_and_log "Successfully updated linuxmalwaredetect production database file: $db_file"
2500 linuxmalwaredetect_updates=1
2501 linuxmalwaredetect_db_update=1
2504 xshok_pretty_echo_and_log "Failed to successfully update linuxmalwaredetect production database file: $db_file - SKIPPING"
2510 xshok_pretty_echo_and_log "WARNING: Failed connection to $linuxmalwaredetect_url - SKIPPED linuxmalwaredetect $db_file update"
2512 if [ "$linuxmalwaredetect_db_update" != "1" ] ; then
2514 xshok_pretty_echo_and_log "No updated linuxmalwaredetect $db_file database file found"
2517 if [ "$linuxmalwaredetect_updates" != "1" ] ; then
2518 xshok_pretty_echo_and_log "No linuxmalwaredetect database file updates found" "-"
2521 xshok_pretty_echo_and_log "linuxmalwaredetect Database File Updates" "="
2522 xshok_draw_time_remaining "$((update_interval - time_interval))" "$linuxmalwaredetect_update_hours" "linuxmalwaredetect"
2527 if [ -n "${linuxmalwaredetect_dbs[0]}" ] ; then
2528 if [ "$remove_disabled_databases" == "yes" ] ; then
2529 xshok_pretty_echo_and_log "Removing disabled linuxmalwaredetect Database files"
2530 for db_file in "${linuxmalwaredetect_dbs[@]}" ; do
2531 if echo "$db_file" | $grep_bin -q "|"; then
2532 db_file="${db_file%|*}"
2534 if [ -r "$work_dir_linuxmalwaredetect/$db_file" ] ; then
2535 xshok_pretty_echo_and_log "Removing $work_dir_linuxmalwaredetect/$db_file"
2536 rm -f "$work_dir_linuxmalwaredetect/$db_file"
2539 if [ -r "$clam_dbs/$db_file" ] ; then
2540 xshok_pretty_echo_and_log "Removing $clam_dbs/$db_file"
2541 rm -f "$clam_dbs/$db_file"
2550 ##########################################################################################################################################
2551 # Download MalwarePatrol database file every set number of hours as defined in the "USER CONFIGURATION" section of this script. #
2552 ##########################################################################################################################################
2553 if [ "$malwarepatrol_enabled" == "yes" ] ; then
2554 if [ "$malwarepatrol_receipt_code" != "YOUR-RECEIPT-NUMBER" ] ; then
2555 if [ -n "$malwarepatrol_db" ] ; then
2556 if [ -r "$work_dir_work_configs/last-mbl-update.txt" ] ; then
2557 last_malwarepatrol_update="$(cat "$work_dir_work_configs/last-mbl-update.txt")"
2559 last_malwarepatrol_update="0"
2562 update_interval="$((malwarepatrol_update_hours * 3600))"
2563 time_interval="$((current_time - last_malwarepatrol_update))"
2564 if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
2565 echo "$current_time" > "$work_dir_work_configs"/last-mbl-update.txt
2566 xshok_pretty_echo_and_log "Checking for MalwarePatrol updates..."
2567 # Delete the old MBL (mbl.db) database file if it exists and start using the newer
2568 # format (mbl.ndb) database file instead.
2569 # test -e $clam_dbs/$malwarepatrol_db -o -e $clam_dbs/$malwarepatrol_db-bak && rm -f -- "$clam_dbs/mbl.d*"
2571 # Remove the .db is the new format if ndb and
2573 if [ "$malwarepatrol_db" == "malwarepatrol.db" ] && [ -f "$clam_dbs/malwarepatrol.ndb" ] ; then
2574 rm "$clam_dbs/malwarepatrol.ndb";
2577 if [ "$malwarepatrol_db" == "malwarepatrol.ndb" ] && [ -f "$clam_dbs/malwarepatrol.db" ] ; then
2578 rm "$clam_dbs/malwarepatrol.db";
2581 xshok_pretty_echo_and_log "MalwarePatrol $db_file Database File Update" "="
2583 malwarepatrol_reloaded=0
2584 if [ "$malwarepatrol_free" == "yes" ] ; then
2585 xshok_file_download "$work_dir_malwarepatrol/$malwarepatrol_db" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code"
2587 if [ "$ret" -eq 0 ] ; then
2588 if ! cmp -s "$work_dir_malwarepatrol/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db" ; then
2589 if [ $? -eq 0 ] ; then
2590 malwarepatrol_reloaded=1
2592 malwarepatrol_reloaded=2
2596 malwarepatrol_reloaded=-1
2598 else # The not free branch
2599 xshok_file_download "$work_dir_malwarepatrol/$malwarepatrol_db.md5" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code&hash=1"
2601 if [ "$ret" -eq 0 ] ; then
2602 if [ -f "$clam_dbs/$malwarepatrol_db" ] ; then
2603 malwarepatrol_md5="$(openssl md5 -r "$clam_dbs/$malwarepatrol_db" 2>/dev/null | cut -d " " -f 1)"
2604 if [ ! "$malwarepatrol_md5" ] ; then
2605 # Fallback for missing -r option
2606 malwarepatrol_md5="$(openssl md5 "$clam_dbs/$malwarepatrol_db" 2>/dev/null | cut -d " " -f 2)"
2609 malwarepatrol_md5_new="$(cat "$work_dir_malwarepatrol/$malwarepatrol_db.md5")"
2610 if [ -n "$malwarepatrol_md5_new" ] && [ "$malwarepatrol_md5" != "$malwarepatrol_md5_new" ] ; then
2611 xshok_file_download "$work_dir_malwarepatrol/$malwarepatrol_db" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code"
2613 if [ "$ret" -eq 0 ] ; then
2614 malwarepatrol_reloaded="1"
2616 malwarepatrol_reloaded="-1"
2619 else # Wget MD5 fail
2620 malwarepatrol_reloaded="-1"
2624 case "$malwarepatrol_reloaded" in
2625 1) # Database was updated, need test and reload
2626 xshok_pretty_echo_and_log "Testing updated MalwarePatrol database file: $malwarepatrol_db"
2627 if $clamscan_bin --quiet -d "$work_dir_malwarepatrol/$malwarepatrol_db" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2628 xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested good"
2631 xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested BAD"
2632 if [ "$remove_bad_database" == "yes" ] ; then
2633 if rm -f "$work_dir_malwarepatrol/$malwarepatrol_db" ; then
2634 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_malwarepatrol/$malwarepatrol_db"
2640 test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db-bak" 2>/dev/null
2643 && if $rsync_bin -pcqt "$work_dir_malwarepatrol/$malwarepatrol_db" "$clam_dbs" 2>/dev/null ; then
2644 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$malwarepatrol_db"
2645 if [ "$selinux_fixes" == "yes" ] ; then
2646 restorecon "$clam_dbs/$malwarepatrol_db"
2648 xshok_pretty_echo_and_log "Successfully updated MalwarePatrol production database file: $malwarepatrol_db"
2651 xshok_pretty_echo_and_log "Failed to successfully update MalwarePatrol production database file: $malwarepatrol_db - SKIPPING"
2653 ;; # The strange case when $? != 0 in the original
2655 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_malwarepatrol/$malwarepatrol_db" > "$test_dir/$malwarepatrol_db"
2656 $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"
2657 $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"
2658 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$malwarepatrol_db" > "$test_dir/$malwarepatrol_db-tmp"
2659 mv -f "$test_dir/$malwarepatrol_db-tmp" "$test_dir/$malwarepatrol_db"
2660 if $clamscan_bin --quiet -d "$test_dir/$malwarepatrol_db" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2661 xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested good"
2664 xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested BAD"
2665 if [ "$remove_bad_database" == "yes" ] ; then
2666 if rm -f "$test_dir/$malwarepatrol_db" ; then
2667 xshok_pretty_echo_and_log "Removed invalid database: $test_dir/$malwarepatrol_db"
2673 test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db-bak" 2>/dev/null
2676 && if $rsync_bin -pcqt "$test_dir/$malwarepatrol_db" "$clam_dbs" 2>/dev/null ; then
2677 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$malwarepatrol_db"
2678 if [ "$selinux_fixes" == "yes" ] ; then
2679 restorecon "$clam_dbs/$malwarepatrol_db"
2681 xshok_pretty_echo_and_log "Successfully updated MalwarePatrol production database file: $malwarepatrol_db"
2684 xshok_pretty_echo_and_log "Failed to successfully update MalwarePatrol production database file: $malwarepatrol_db - SKIPPING"
2687 0) # The database did not update
2688 xshok_pretty_echo_and_log "MalwarePatrol signature database ($malwarepatrol_db) did not change - skipping"
2691 xshok_pretty_echo_and_log "WARNING - Failed connection to $malwarepatrol_url - SKIPPED MalwarePatrol $malwarepatrol_db update"
2696 xshok_pretty_echo_and_log "MalwarePatrol Database File Update" "="
2697 xshok_draw_time_remaining "$((update_interval - time_interval))" "$malwarepatrol_update_hours" "MalwarePatrol"
2702 if [ -n "$malwarepatrol_db" ] ; then
2703 if [ "$remove_disabled_databases" == "yes" ] ; then
2704 xshok_pretty_echo_and_log "Removing disabled MalwarePatrol Database file"
2705 if [ -r "$work_dir_malwarepatrol/$malwarepatrol_db" ] ; then
2706 rm -f "$work_dir_malwarepatrol/$malwarepatrol_db"
2709 if [ -r "$clam_dbs/$malwarepatrol_db" ] ; then
2710 rm -f "$clam_dbs/$malwarepatrol_db"
2717 ##############################################################################################################################################
2718 # Check for updated yararulesproject database files every set number of hours as defined in the "USER CONFIGURATION" section of this script
2719 ##############################################################################################################################################
2720 if [ "$yararulesproject_enabled" == "yes" ] ; then
2721 if [ -n "${yararulesproject_dbs[0]}" ] ; then
2722 if [ ${#yararulesproject_dbs} -lt 1 ] ; then
2723 xshok_pretty_echo_and_log "Failed yararulesproject_dbs config is invalid or not defined - SKIPPING"
2725 rm -f "$work_dir_yararulesproject/*.gz"
2726 if [ -r "$work_dir_work_configs/last-yararulesproject-update.txt" ] ; then
2727 last_yararulesproject_update="$(cat "$work_dir_work_configs/last-yararulesproject-update.txt")"
2729 last_yararulesproject_update="0"
2733 update_interval="$((yararulesproject_update_hours * 3600))"
2734 time_interval="$((current_time - last_yararulesproject_update))"
2735 if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
2736 echo "$current_time" > "$work_dir_work_configs/last-yararulesproject-update.txt"
2738 xshok_pretty_echo_and_log "Yara-Rules Database File Updates" "="
2739 xshok_pretty_echo_and_log "Checking for yararulesproject updates..."
2740 yararulesproject_updates="0"
2741 for db_file in "${yararulesproject_dbs[@]}" ; do
2742 if echo "$db_file" | $grep_bin -q "/"; then
2743 yr_dir="/$(echo "$db_file" | cut -d "/" -f 1)"
2744 db_file="$(echo "$db_file" | cut -d "/" -f 2)"
2747 if [ "$loop" == "1" ] ; then
2748 xshok_pretty_echo_and_log "---"
2750 xshok_pretty_echo_and_log "Checking for updated yararulesproject database file: $db_file"
2751 yararulesproject_db_update="0"
2752 xshok_file_download "$work_dir_yararulesproject/$db_file" "$yararulesproject_url/$yr_dir/$db_file"
2754 if [ "$ret" -eq 0 ] ; then
2756 if ! cmp -s "$work_dir_yararulesproject/$db_file" "$clam_dbs/$db_file" ; then
2757 if [ $? -eq 0 ] ; then
2758 db_ext="${db_file#*.}"
2760 xshok_pretty_echo_and_log "Testing updated yararulesproject database file: $db_file"
2761 if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
2762 if $clamscan_bin --quiet -d "$work_dir_yararulesproject/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2764 xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested good"
2767 xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested BAD"
2768 if [ "$remove_bad_database" == "yes" ] ; then
2769 if rm -f "$work_dir_yararulesproject/$db_file" ; then
2770 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_yararulesproject/$db_file"
2774 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
2775 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2776 if [ "$selinux_fixes" == "yes" ] ; then
2777 restorecon "$clam_dbs/$db_file"
2779 xshok_pretty_echo_and_log "Successfully updated yararulesproject production database file: $db_file"
2780 yararulesproject_updates=1
2781 yararulesproject_db_update=1
2784 xshok_pretty_echo_and_log "Failed to successfully update yararulesproject production database file: $db_file - SKIPPING"
2787 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_yararulesproject/$db_file" > "$test_dir/$db_file"
2788 $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"
2789 $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"
2790 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2791 mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2792 if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2793 xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested good"
2796 xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested BAD"
2797 if [ "$remove_bad_database" == "yes" ] ; then
2798 if rm -f "$work_dir_yararulesproject/$db_file" ; then
2799 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_yararulesproject/$db_file"
2803 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
2804 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2805 if [ "$selinux_fixes" == "yes" ] ; then
2806 restorecon "$clam_dbs/$db_file"
2808 xshok_pretty_echo_and_log "Successfully updated yararulesproject production database file: $db_file"
2809 yararulesproject_updates=1
2810 yararulesproject_db_update=1
2813 xshok_pretty_echo_and_log "Failed to successfully update yararulesproject production database file: $db_file - SKIPPING"
2819 xshok_pretty_echo_and_log "WARNING: Failed connection to $yararulesproject_url - SKIPPED yararulesproject $db_file update"
2821 if [ "$yararulesproject_db_update" != "1" ] ; then
2822 xshok_pretty_echo_and_log "No updated yararulesproject $db_file database file found"
2825 if [ "$yararulesproject_updates" != "1" ] ; then
2826 xshok_pretty_echo_and_log "No yararulesproject database file updates found" "-"
2830 xshok_pretty_echo_and_log "Yara-Rules Database File Updates" "="
2831 xshok_draw_time_remaining "$((update_interval - time_interval))" "$yararulesproject_update_hours" "yararulesproject"
2836 if [ -n "${yararulesproject_dbs[0]}" ] ; then
2837 if [ "$remove_disabled_databases" == "yes" ] ; then
2838 xshok_pretty_echo_and_log "Removing disabled yararulesproject Database files"
2839 for db_file in "${yararulesproject_dbs[@]}" ; do
2840 if echo "$db_file" | $grep_bin -q "/"; then
2841 db_file="$(echo "$db_file" | cut -d "/" -f 2)"
2843 if echo "$db_file" | $grep_bin -q "|"; then
2844 db_file="${db_file%|*}"
2846 if [ -r "$work_dir_yararulesproject/$db_file" ] ; then
2847 rm -f "$work_dir_yararulesproject/$db_file"
2850 if [ -r "$clam_dbs/$db_file" ] ; then
2851 rm -f "$clam_dbs/$db_file"
2859 ##############################################################################################################################################
2860 # Check for updated additional database files every set number of hours as defined in the "USER CONFIGURATION" section of this script
2861 ##############################################################################################################################################
2862 if [ "$additional_enabled" == "yes" ] ; then
2863 if [ -n "$additional_dbs" ] ; then
2864 if [ ${#additional_dbs} -lt 1 ] ; then
2865 xshok_pretty_echo_and_log "Failed additional_dbs config is invalid or not defined - SKIPPING"
2867 rm -f "$work_dir_add/*.gz"
2868 if [ -r "$work_dir_work_configs/last-additional-update.txt" ] ; then
2869 last_additional_update="$(cat "$work_dir_work_configs/last-additional-update.txt")"
2871 last_additional_update="0"
2875 update_interval="$((additional_update_hours * 3600))"
2876 time_interval="$((current_time - last_additional_update))"
2877 if [ "$time_interval" -ge "$((update_interval - 600))" ] ; then
2878 echo "$current_time" > "$work_dir_work_configs/last-additional-update.txt"
2880 xshok_pretty_echo_and_log "Additional Database File Updates" "="
2881 xshok_pretty_echo_and_log "Checking for additional updates..."
2882 additional_updates="0"
2883 for db_url in "${additional_dbs[@]}" ; do
2884 # Left for future dir manipulation
2885 # if echo "$db_file" | $grep_bin -q "/"; then
2886 # add_dir="/$(echo "$db_file" | cut -d "/" -f 1)"
2887 # db_file="$(echo "$db_file" | cut -d "/" -f 2)"
2892 #cleanup any leading and trailing whitespace.
2893 db_url="$(echo -e "$db_url" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
2895 db_file="$(basename "$db_url")"
2897 if [ "$loop" == "1" ] ; then
2898 xshok_pretty_echo_and_log "---"
2900 xshok_pretty_echo_and_log "Checking for updated additional database file: $db_file"
2902 additional_db_update="0"
2904 if [ "${db_url%:*}" == "rsync" ] ; then
2905 # shellcheck disable=SC2086
2906 $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
2909 xshok_file_download "$work_dir_add/$db_file" "$db_url"
2913 # This needs enhancement for rsync, as it will only work with single files...
2914 # Maybe better to process each file inside work_dir_add in its own for loop.
2915 if [ "$ret" -eq 0 ] ; then
2917 if ! cmp -s "$work_dir_add/$db_file" "$clam_dbs/$db_file" ; then
2918 if [ $? -eq 0 ] ; then
2919 db_ext="${db_file#*.}"
2921 xshok_pretty_echo_and_log "Testing updated additional database file: $db_file"
2922 if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
2923 if $clamscan_bin --quiet -d "$work_dir_add/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2925 xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested good"
2928 xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested BAD"
2929 if [ "$remove_bad_database" == "yes" ] ; then
2930 if rm -f "$work_dir_add/$db_file" ; then
2931 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_add/$db_file"
2935 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
2936 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2937 if [ "$selinux_fixes" == "yes" ] ; then
2938 restorecon "$clam_dbs/$db_file"
2940 xshok_pretty_echo_and_log "Successfully updated additional production database file: $db_file"
2941 additional_updates=1
2942 additional_db_update=1
2945 xshok_pretty_echo_and_log "Failed to successfully update additional production database file: $db_file - SKIPPING"
2948 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_add/$db_file" > "$test_dir/$db_file"
2949 $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"
2950 $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"
2951 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2952 mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2953 if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2954 xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested good"
2957 xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested BAD"
2958 if [ "$remove_bad_database" == "yes" ] ; then
2959 if rm -f "$work_dir_add/$db_file" ; then
2960 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_add/$db_file"
2964 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
2965 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2966 if [ "$selinux_fixes" == "yes" ] ; then
2967 restorecon "$clam_dbs/$db_file"
2969 xshok_pretty_echo_and_log "Successfully updated additional production database file: $db_file"
2970 additional_updates=1
2971 additional_db_update=1
2974 xshok_pretty_echo_and_log "Failed to successfully update additional production database file: $db_file - SKIPPING"
2980 xshok_pretty_echo_and_log "WARNING: Failed connection to $db_url - SKIPPED additional $db_file update"
2982 if [ "$additional_db_update" != "1" ] ; then
2983 xshok_pretty_echo_and_log "No updated additional $db_file database file found"
2986 if [ "$additional_updates" != "1" ] ; then
2987 xshok_pretty_echo_and_log "No additional database file updates found" "-"
2990 xshok_pretty_echo_and_log "Additional Database File Updates" "="
2991 xshok_draw_time_remaining "$((update_interval - time_interval))" "$additional_update_hours" "additionaldatabaseupdate"
2996 if [ -n "$additional_dbs" ] ; then
2997 if [ "$remove_disabled_databases" == "yes" ] ; then
2998 xshok_pretty_echo_and_log "Removing disabled additional Database files"
2999 for db_file in "${additional_dbs[@]}" ; do
3000 if echo "$db_file" | $grep_bin -q "/"; then
3001 db_file="$(echo "$db_file" | cut -d "/" -f 2)"
3003 if [ -r "$work_dir_add/$db_file" ] ; then
3004 rm -f "$work_dir_add/$db_file"
3007 if [ -r "$clam_dbs/$db_file" ] ; then
3008 rm -f "$clam_dbs/$db_file"
3016 ###################################################
3017 # Generate whitelists
3018 ###################################################
3019 # Check to see if the local.ign file exists, and if it does, check to see if any of the script
3020 # added bypass entries can be removed due to offending signature modifications or removals.
3021 if [ -r "$clam_dbs/local.ign" ] && [ -s "$work_dir_work_configs/monitor-ign.txt" ] ; then
3023 cd "$clam_dbs" || exit
3024 cp -f local.ign "$work_dir_work_configs/local.ign"
3025 cp -f "$work_dir_work_configs/monitor-ign.txt" "$work_dir_work_configs/monitor-ign-old.txt"
3027 xshok_pretty_echo_and_log "" "=" "80"
3028 while read -r entry ; do
3029 sig_file="$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $1}')"
3030 sig_hex="$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $NF}')"
3031 sig_name_old="$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $3}')"
3032 sig_ign_old="$($grep_bin ":$sig_name_old" "$work_dir_work_configs/local.ign")"
3033 sig_old="$(echo "$entry" | tr -d "\r" | cut -d ":" -f 3-)"
3034 sig_new="$($grep_bin -hwF ":$sig_hex" "$sig_file" | tr -d "\r" 2>/dev/null)"
3035 sig_mon_new="$($grep_bin -HwF -n ":$sig_hex" "$sig_file" | tr -d "\r")"
3036 if [ -n "$sig_new" ] ; then
3037 if [ "$sig_old" != "$sig_new" ] || [ "$entry" != "$sig_mon_new" ] ; then
3038 sig_name_new="$(echo "$sig_new" | tr -d "\r" | awk -F ":" '{print $1}')"
3039 sig_ign_new="$(echo "$sig_mon_new" | cut -d ":" -f 1-3)"
3040 perl -i -ne "print unless /$sig_ign_old/" "$work_dir_work_configs/monitor-ign.txt"
3041 echo "$sig_mon_new" >> "$work_dir_work_configs/monitor-ign.txt"
3042 perl -p -i -e "s/$sig_ign_old/$sig_ign_new/" "$work_dir_work_configs/local.ign"
3043 xshok_pretty_echo_and_log "$sig_name_old hexadecimal signature is unchanged, however signature name and/or line placement"
3044 xshok_pretty_echo_and_log "in $sig_file has changed to $sig_name_new - updated local.ign to reflect this change."
3048 perl -i -ne "print unless /$sig_ign_old/" "$work_dir_work_configs/monitor-ign.txt" "$work_dir_work_configs/local.ign"
3050 xshok_pretty_echo_and_log "$sig_name_old signature has been removed from $sig_file, entry removed from local.ign."
3053 done < "$work_dir_work_configs/monitor-ign-old.txt"
3054 if [ "$ign_updated" == "1" ] ; then
3055 if $clamscan_bin --quiet -d "$work_dir_work_configs/local.ign" "$work_dir_work_configs/scan-test.txt"
3057 if $rsync_bin -pcqt "$work_dir_work_configs/local.ign" "$clam_dbs"
3059 perms chown -f "$clam_user:$clam_group" "$clam_dbs/local.ign"
3060 perms chmod -f 0644 "$clam_dbs/local.ign" "$work_dir_work_configs/monitor-ign.txt"
3061 if [ "$selinux_fixes" == "yes" ] ; then
3062 restorecon "$clam_dbs/local.ign"
3066 xshok_pretty_echo_and_log "Failed to successfully update local.ign file - SKIPPING"
3069 xshok_pretty_echo_and_log "Clamscan reports local.ign database integrity is bad - SKIPPING"
3072 xshok_pretty_echo_and_log "No whitelist signature changes found in local.ign" "="
3076 # Check to see if my-whitelist.ign2 file exists, and if it does, check to see if any of the script
3077 # added whitelist entries can be removed due to offending signature modifications or removals.
3078 if [ -r "$clam_dbs/my-whitelist.ign2" ] && [ -s "$work_dir_work_configs/tracker.txt" ] ; then
3080 cd "$clam_dbs" || exit
3081 cp -f my-whitelist.ign2 "$work_dir_work_configs/my-whitelist.ign2"
3083 xshok_pretty_echo_and_log "" "=" "80"
3085 while read -r entry ; do
3086 sig_file="$(echo "$entry" | cut -d ":" -f 1)"
3087 sig_full="$(echo "$entry" | cut -d ":" -f 2-)"
3088 sig_name="$(echo "$entry" | cut -d ":" -f 2)"
3089 if ! $grep_bin -F "$sig_full" "$sig_file" > /dev/null 2>&1 ; then
3090 perl -i -ne "print unless /$sig_name$/" "$work_dir_work_configs/my-whitelist.ign2"
3091 perl -i -ne "print unless /:$sig_name:/" "$work_dir_work_configs/tracker-tmp.txt"
3093 xshok_pretty_echo_and_log "$sig_name signature no longer exists in $sig_file, whitelist entry removed from my-whitelist.ign2"
3096 done < "$work_dir_work_configs/tracker.txt"
3097 mv -f "$work_dir_work_configs/tracker-tmp.txt" "$work_dir_work_configs/tracker.txt"
3099 xshok_pretty_echo_and_log "" "=" "80"
3100 if [ "$ign2_updated" == "1" ]
3102 if $clamscan_bin --quiet -d "$work_dir_work_configs/my-whitelist.ign2" "$work_dir_work_configs/scan-test.txt"
3104 if $rsync_bin -pcqt "$work_dir_work_configs/my-whitelist.ign2" "$clam_dbs"
3106 perms chown -f "$clam_user:$clam_group" "$clam_dbs/my-whitelist.ign2"
3107 perms chmod -f 0644 "$clam_dbs/my-whitelist.ign2" "$work_dir_work_configs/tracker.txt"
3108 if [ "$selinux_fixes" == "yes" ] ; then
3109 restorecon "$clam_dbs/my-whitelist.ign2"
3110 restorecon "$work_dir_work_configs/tracker.txt"
3114 xshok_pretty_echo_and_log "Failed to successfully update my-whitelist.ign2 file - SKIPPING"
3117 xshok_pretty_echo_and_log "Clamscan reports my-whitelist.ign2 database integrity is bad - SKIPPING"
3120 xshok_pretty_echo_and_log "No whitelist signature changes found in my-whitelist.ign2"
3124 # Check for non-matching whitelist.hex signatures and remove them from the whitelist file (signature modified or removed).
3125 if [ -n "$ham_dir" ] ; then
3126 if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
3127 $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"
3128 mv -f "$work_dir_work_configs/whitelist.tmp" "$work_dir_work_configs/whitelist.hex"
3129 rm -f "$work_dir_work_configs/whitelist.txt"
3130 rm -f "$test_dir"/*.*
3131 xshok_pretty_echo_and_log "WARNING: Signature(s) triggered on HAM directory scan - signature(s) removed" "*"
3133 xshok_pretty_echo_and_log "No signatures triggered on HAM directory scan" "="
3137 # Set appropriate directory and file permissions to all production signature files
3138 # and set file access mode to 0644 on all working directory files.
3140 if [ "$setmode" == "yes" ] ; then
3141 xshok_pretty_echo_and_log "Setting permissions and ownership" "="
3142 perms chown -f -R "$clam_user:$clam_group" "$work_dir"
3143 if ! find "$work_dir" -type f -exec chmod -f 0644 "{}" "+" 2>/dev/null ; then
3144 if ! find "$work_dir" -type f -print0 | xargs -0 chmod -f 0644 2>/dev/null ; then
3145 find "$work_dir" -type f -exec chmod -f 0644 "{}" ";"
3149 # If enabled, set file access mode for all production signature database files to 0644.
3150 perms chown -f -R "$clam_user:$clam_group" "$clam_dbs"
3151 if ! find "$clam_dbs" -type f -exec chmod -f 0644 "{}" "+" 2>/dev/null ; then
3152 if ! find "$clam_dbs" -type f -print0 | xargs -0 chmod -f 0644 2>/dev/null ; then
3153 find "$clam_dbs" -type f -exec chmod -f 0644 "{}" ";"
3158 # Reload all clamd databases
3161 xshok_pretty_echo_and_log "Issue tracker : https://github.com/extremeshok/clamav-unofficial-sigs/issues" "-"
3165 check_new_config_version
3169 # And lastly we exit, Note: the exit is always on the 2nd last line