inicijalna verzija
[clamav-unofficial-sigs.git] / clamav-unofficial-sigs
1 #!/bin/bash
2 ################################################################################
3 # This is property of eXtremeSHOK.com
4 # You are free to use, modify and distribute, however you may not remove this notice.
5 # Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
6 ################################################################################
7
8 # Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
9 #
10 # Originially based on: 
11 # Script provide by Bill Landry (unofficialsigs@gmail.com).
12 #
13 # License: BSD (Berkeley Software Distribution)
14 #
15 ################################################################################
16 #
17 #    THERE ARE NO USER CONFIGURABLE OPTIONS IN THIS SCRIPT
18 #   ALL CONFIGURATION OPTIONS ARE LOCATED IN THE INCLUDED CONFIGURATION FILE 
19 #
20 ################################################################################
21
22 ################################################################################
23
24     ######  #######    #     # ####### #######    ####### ######  ### ####### 
25     #     # #     #    ##    # #     #    #       #       #     #  #     #    
26     #     # #     #    # #   # #     #    #       #       #     #  #     #    
27     #     # #     #    #  #  # #     #    #       #####   #     #  #     #    
28     #     # #     #    #   # # #     #    #       #       #     #  #     #    
29     #     # #     #    #    ## #     #    #       #       #     #  #     #    
30     ######  #######    #     # #######    #       ####### ######  ###    #    
31
32 ################################################################################
33
34 # Detect to make sure the entire script is avilable, fail if the script is missing contents
35 if [ ! "$( tail -1 "$0" | head -1 | cut -c1-7 )" == "exit \$?" ] ; then
36   echo "FATAL ERROR: Script is incomplete, please redownload"
37   exit 1
38 fi
39
40 # trap the keyboard interrupt (ctrl+c)
41 trap xshok_control_c SIGINT
42
43 ################################################################################
44 # HELPER FUNCTIONS
45 ################################################################################
46
47 # Function to support user config settings for applying file and directory access permissions.
48 function perms () {
49   if [ -n "$clam_user" ] && [ -n "$clam_group" ] ; then
50     "${@:-}"
51   fi
52 }
53
54 # Function to prompt a user if they should complete an action with Y or N
55 # usage: xshok_prompt_confirm
56 # if xshok_prompt_confirm; then
57 # xshok_prompt_confirm && echo "accepted"
58 # xshok_prompt_confirm && echo "yes" || echo "no"
59 function xshok_prompt_confirm () { #optional_message
60   message="${1:-Are you sure?}"
61   while true; do
62     read -r -p "$message [y/N]" response  </dev/tty
63     case $response in
64       [yY]) return 0 ;;
65       [nN]) return 1 ;;
66       *) printf " \033[31m %s \n\033[0m" "invalid input"
67     esac 
68   done  
69 }
70
71 # Function to create a pid file
72 function xshok_create_pid_file { #pid.file
73   if [ "$1" ] ; then
74     pidfile="$1"
75     echo $$ > "$pidfile"
76     if [ $? -ne 0 ] ;  then
77       xshok_pretty_echo_and_log "ERROR: Could not create PID file: $pidfile"
78       exit 1
79     fi
80   else
81     xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
82     exit 1
83   fi
84 }
85
86 # Function to intercept ctrl+c and calls the cleanup function
87 function xshok_control_c () {
88   echo -en "\n"
89   xshok_pretty_echo_and_log "--------------| Exiting ... Please wait |--------------" "-"
90   xshok_cleanup
91   exit $?
92 }
93
94 # cleanup function
95 function xshok_cleanup () {
96   #wait for all processes to end
97   wait
98   xshok_pretty_echo_and_log "      Powered By https://eXtremeSHOK.com      " "#"
99   return $?
100
101
102 # Function to 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"
106   else
107     id_bin="$(which id)"
108   fi
109   if [ "$($id_bin -u)" = 0 ] ; then
110     return 0 ;
111   else
112     return 1 ;  #not root
113   fi
114 }
115
116 # Function to check if its a file, otherwise return false
117 function xshok_is_file () { #"filepath"
118   filepath="$1"
119   if [ -f "${filepath}" ] ; then
120     return 0 ;
121   else
122     return 1 ;  #not a file
123   fi 
124 }
125
126 # Function to 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   filepath=$(echo "$1" | sed 's:/*$::')
132   if [ -d "$filepath" ] ; then
133     res="${filepath//[^\/]}"
134     if [ "${#res}" -gt 1 ] ; then
135       return 0 ;
136     else
137       return 1 ;  #not a subdir
138     fi
139   else
140     return 1 ;  #not a dir
141   fi
142 }
143
144 # Function to create a dir and set the ownership
145 function xshok_mkdir_ownership () { #"path"
146   if [ "$1" ] ; then
147     mkdir -p "$1" 2>/dev/null
148     if [ $? -ne 0 ] ;  then
149       xshok_pretty_echo_and_log "ERROR: Could not create directory: $1"
150       exit 1
151     fi
152     perms chown -f "$clam_user:$clam_group" "$1" > /dev/null 2>&1
153   else
154     xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
155     exit 1
156   fi
157 }
158
159 # Function to check if a user and group exists on the system otherwise return false
160 # Usage: 
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"
166   else
167     id_bin="$(which id)"
168   fi
169   if [ "$1" ] ; then
170     $id_bin -u "$1" > /dev/null 2>&1
171     if [ $? -eq 0 ]; then
172       if [ "$2" ] ; then
173         $id_bin -g "$2" > /dev/null 2>&1
174         if [ $? -eq 0 ]; then
175           return 0 ; #user and group exists
176         else
177           return 1 ;  #group does NOT exist
178         fi
179        else
180           return 0 ; #user exists
181        fi
182     else
183       return 1 ;  #user does NOT exist
184     fi
185   else
186     xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
187     exit 1
188   fi
189 }
190
191 # Function to handle comments with/out borders and logging.
192 # Usage:
193 # pretty_echo_and_log "one" 
194 # one
195 # pretty_echo_and_log "two" "-" 
196 # ---
197 # two
198 # ---
199 # pretty_echo_and_log "three" "=" "8"
200 # ========
201 # three
202 # ========
203 # pretty_echo_and_log "" "/\" "7"
204 # /\/\/\/\/\/\
205 #type: e = error, w= warning ""
206 function xshok_pretty_echo_and_log () { #"string" "repeating" "count" "type"
207   # handle comments
208   if [ "$comment_silence" = "no" ] ; then
209     if [ "${#@}" = "1" ] ; then
210       echo "$1"
211     else
212       myvar=""
213       if [ -n "$3" ] ; then
214         mycount="$3"
215       else
216         mycount="${#1}"
217       fi
218       for (( n = 0; n < mycount; n++ )) ; do 
219         myvar="$myvar$2"
220       done
221       if [ "$1" != "" ] ; then
222         echo -e "$myvar\n$1\n$myvar"
223       else  
224         echo -e "$myvar"
225       fi
226     fi
227   fi
228
229   # handle logging
230   if [ "$enable_log" == "yes" ] ; then
231     if [ ! -e "$log_file_path/$log_file_name" ] ; then
232         #xshok_mkdir_ownership "$log_file_path"
233         mkdir -p "$log_file_path"
234         touch "$log_file_path/$log_file_name" 2>/dev/null
235         perms chown -f "$clam_user:$clam_group" "$log_file_path/$log_file_name"
236     fi
237     if [ ! -w "$log_file_path/$log_file_name" ] ; then
238       echo "Warning: Logging Disabled, as file not writable: $log_file_path/$log_file_name"
239       enable_log="no"
240     else
241       echo "$(date "+%b %d %T")" "$1" >> "$log_file_path/$log_file_name"
242     fi 
243   fi
244 }
245
246 # function to check if the $2 value is not null and does not start with -
247 function xshok_check_s2 () { #value1 #value2
248   if [ "$1" ] ; then
249     if [[ "$1" =~ ^-.* ]] ; then
250       xshok_pretty_echo_and_log "ERROR: Missing value for option or value begins with -" "="
251       exit 1
252     fi
253   else
254     xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
255     exit 1
256   fi
257 }
258
259 # function to count array elements and output the total element count
260 # required due to compound array assignment
261 # Usage:
262 # array=("one" "two" "three")
263 # xshok_array_count $array
264 # 3
265 function xshok_array_count () { #array
266   k_array=( "$@" )
267   if [ -n "${k_array[*]}" ] ; then
268     i="0"
269     for k in "${k_array[@]}" ; do
270       let i=$i+1;
271     done
272     echo "$i"
273   else
274     echo "0"
275   fi
276 }
277 # function to auto update
278 function xshok_auto_update() { #version
279   xshok_pretty_echo_and_log "Performing automatic update..."
280
281   # Download new version
282   echo -n "Downloading latest version..."
283   if ! wget --quiet --output-document="$0.tmp" $UPDATE_BASE/$SELF ; then
284     echo "Failed: Error while trying to wget new version!"
285     echo "File requested: $UPDATE_BASE/$SELF"
286     exit 1
287   fi
288   echo "Done."
289
290   # Copy over modes from old version
291   OCTAL_MODE=$(stat -c '%a' $SELF)
292   if ! chmod $OCTAL_MODE "$0.tmp" ; then
293     echo "Failed: Error while trying to set mode on $0.tmp."
294     exit 1
295   fi
296
297   # Generate the update script
298   cat > xshok_update_script.sh << EOF
299 #!/bin/bash
300 # Overwrite old file with new
301 if mv "$0.tmp" "$0"; then
302   echo "Done. Update complete."
303   rm \$0
304 else
305   echo "Failed! The update was not completed."
306 fi
307 EOF
308
309
310   echo -n "Inserting update process..."
311   
312   #replaced with $0, so code will update and then call itself with the same parameters it had
313   #exec /bin/bash xshok_update_script.sh
314   exec "$0" "$@"
315 }
316
317 #function to handle list of database files
318 function clamav_files () {
319   echo "$clam_dbs/$db" >> "$current_tmp"
320   if [ "$keep_db_backup" = "yes" ] ; then
321     echo "$clam_dbs/$db-bak" >> "$current_tmp"
322   fi
323 }
324
325 # Function to manage the databases and allow multi-dimensions as well as global overrides
326 # since the datbases are basically a multi-dimentional associative arrays in bash
327 # ratings: LOW| MEDIUM| HIGH| REQUIRED| LOWONLY| MEDIUMONLY| LOWMEDIUMONLY | MEDIUMHIGHONLY | HIGHONLY| DISABLED
328 function xshok_database () { #database #rating
329
330   # assign
331   current_dbs="$1"
332   current_rating="$2"
333   # zero
334   new_dbs=""
335
336   if [ -n "$current_dbs" ] ; then
337     if [ "$(xshok_array_count "$current_dbs")" -ge "1" ] ; then
338       for db_name in $current_dbs ; do
339         #checks
340         if [ "$enable_yararules" == "no" ] ; then #yararules are disabled
341             if [[ "$db_name" = *".yar"* ]] ; then # if it's the value you want to delete
342               continue # skip to the next value
343             fi
344         fi
345         if [ "$current_rating" == "" ] ; then #yararules are disabled
346           new_dbs="$new_dbs $db_name"
347         else
348           if [[ ! "$db_name" = *"|"* ]] ; then # this old format
349             new_dbs="$new_dbs $db_name"
350           else
351             db_name_rating=$(echo "$db_name" | cut -d "|" -f2)
352             db_name=$(echo "$db_name" | cut -d "|" -f1)
353
354             if [ "$db_name_rating" != "DISABLED" ] ; then
355               if [ "$db_name_rating" == "$current_rating" ] ; then
356                 new_dbs="$new_dbs $db_name"
357               elif [ "$db_name_rating" == "REQUIRED" ] ; then
358                 new_dbs="$new_dbs $db_name"
359               elif [ "$current_rating" == "LOW" ] ; then
360                 if [ "$db_name_rating" == "LOWONLY" ] || [ "$db_name_rating" == "LOW" ]  || [ "$db_name_rating" == "LOWMEDIUM" ] ; then
361                   new_dbs="$new_dbs $db_name"   
362                 fi
363               elif [ "$current_rating" == "MEDIUM" ] ; then
364                 if [ "$db_name_rating" == "MEDIUMONLY" ] || [ "$db_name_rating" == "MEDIUM" ] || [ "$db_name_rating" == "LOW" ] || [ "$db_name_rating" == "LOWMEDIUM" ] ; then
365                   new_dbs="$new_dbs $db_name"
366                 fi
367               elif [ "$current_rating" == "HIGH" ] ; then
368                 if [ "$db_name_rating" == "HIGH" ] || [ "$db_name_rating" == "MEDIUM" ] || [ "$db_name_rating" == "LOW" ] ; then
369                   new_dbs="$new_dbs $db_name"
370                 fi
371               fi
372             fi
373           fi
374         fi
375       done
376     fi
377   fi
378   echo "$new_dbs" | xargs #remove extra whitespace
379
380 }
381
382 ################################################################################
383 # ADDITIONAL PROGRAM FUNCTIONS
384 ################################################################################
385
386
387 #generates a man config and installs it
388 function install_man () {
389
390   if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
391     echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
392     exit 1
393   fi
394
395
396   echo ""
397   echo "Generating man file for install...."
398   
399   #Use defined varibles or attempt to use default varibles
400
401   if [ ! -e "$man_dir/$man_filename" ] ; then
402     mkdir -p "$man_dir"
403     touch "$man_dir/$man_filename" 2>/dev/null
404   fi
405   if [ ! -w "$man_dir/$man_filename" ] ; then
406     echo "ERROR: man install aborted, as file not writable: $man_dir/$man_filename"
407   else
408
409 BOLD="\fB"
410 #REV=""
411 NORM="\fR"
412 manresult=$(help_and_usage "man")
413
414 #Our template..
415   cat << EOF > "$man_dir/$man_filename"
416
417 .\" Manual page for eXtremeSHOK.com ClamAV Unofficial Signature Updater
418 .TH clamav-unofficial-sigs 8 "$script_version_date" "Version: $script_version" "SCRIPT COMMANDS"
419 .SH NAME
420 clamav-unofficial-sigs \- Download, test, and install third-party ClamAV signature databases.
421 .SH SYNOPSIS
422 .B clamav-unofficial-sigs
423 .RI [ options ]
424 .SH DESCRIPTION
425 \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.
426 .SH UPDATES
427 Script updates can be found at: \fBhttps://github.com/extremeshok/clamav-unofficial-sigs\fP
428 .SH OPTIONS
429 This script follows the standard GNU command line syntax.
430 .LP
431 $manresult
432 .SH SEE ALSO
433 .BR clamd (8),
434 .BR clamscan (1)
435 .SH COPYRIGHT
436 Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
437 .TP
438 You are free to use, modify and distribute, however you may not remove this notice.
439 .SH LICENSE
440 BSD (Berkeley Software Distribution)
441 .SH BUGS
442 Report bugs to \fBhttps://github.com/extremeshok/clamav-unofficial-sigs\fP
443 .SH AUTHOR
444 Adrian Jon Kriel :: admin@extremeshok.com
445 Originially based on Script provide by Bill Landry
446
447
448 EOF
449
450   fi 
451   echo "Completed: man installed, as file: $man_dir/$man_filename"
452 }
453
454
455 #generates a logrotate config and installs it
456 function install_logrotate () {
457
458   if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
459     echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
460     exit 1
461   fi
462
463   echo ""
464   echo "Generating logrotate file for install...."
465   
466   #Use defined varibles or attempt to use default varibles
467
468   if [ ! -n "$logrotate_user" ] ; then
469     logrotate_user="$clam_user";
470   fi
471   if [ ! -n "$logrotate_group" ] ; then
472     logrotate_group="$clam_group";
473   fi
474   if [ ! -n "$logrotate_log_file_full_path" ] ; then
475     logrotate_log_file_full_path="$log_file_path/$log_file_name"
476   fi
477
478
479   if [ ! -e "$logrotate_dir/$logrotate_filename" ] ; then
480     mkdir -p "$logrotate_dir"
481     touch "$logrotate_dir/$logrotate_filename" 2>/dev/null
482   fi
483   if [ ! -w "$logrotate_dir/$logrotate_filename" ] ; then
484     echo "ERROR: logrotate install aborted, as file not writable: $logrotate_dir/$logrotate_filename"
485   else
486 #Our template..
487   cat << EOF > "$logrotate_dir/$logrotate_filename"
488 # https://eXtremeSHOK.com ######################################################
489 # This file contains the logrotate settings for clamav-unofficial-sigs.sh
490 ###################
491 # This is property of eXtremeSHOK.com
492 # You are free to use, modify and distribute, however you may not remove this notice.
493 # Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
494 ##################
495 #
496 # Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
497
498 # Originially based on: 
499 # Script provide by Bill Landry (unofficialsigs@gmail.com).
500 #
501 # License: BSD (Berkeley Software Distribution)
502 #
503 ##################
504 # Automatically Generated: $(date)
505 ##################
506 #
507 # This logrotate file will rotate the logs generated by the clamav-unofficial-sigs.sh
508 #
509 # To Adjust the logrotate values, edit your configs and run
510 # bash clamav-unofficial-sigs.sh --install-logrotate to generate a new file.
511
512 $logrotate_log_file_full_path {
513   weekly
514   rotate 4
515   missingok
516   notifempty
517   compress
518   create 0644 $logrotate_user $logrotate_group
519 }
520
521 EOF
522
523   fi 
524   echo "Completed: logrotate installed, as file: $logrotate_dir/$logrotate_filename"
525 }
526
527 #generates a cron config and installs it
528 function install_cron () {
529
530   if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
531     echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
532     exit 1
533   fi
534
535   echo ""
536   echo "Generating cron file for install...."
537   
538   #Use defined varibles or attempt to use default varibles
539   if [ ! -n "$cron_minute" ] ; then
540     cron_minute=$(( ( RANDOM % 59 )  + 1 ));
541   fi
542   if [ ! -n "$cron_user" ] ; then
543     cron_user="$clam_user";
544   fi
545   if [ ! -n "$cron_bash" ] ; then
546     cron_bash=$(which bash)
547   fi  
548   if [ ! -n "$cron_script_full_path" ] ; then
549     cron_script_full_path="$this_script_full_path"
550   fi  
551
552   if [ ! -e "$cron_dir/$cron_filename" ] ; then
553     mkdir -p "$cron_dir"
554     touch "$cron_dir/$cron_filename" 2>/dev/null
555   fi
556   if [ ! -w "$cron_dir/$cron_filename" ] ; then
557     echo "ERROR: cron install aborted, as file not writable: $cron_dir/$cron_filename"
558   else
559 #Our template..
560   cat << EOF > "$cron_dir/$cron_filename"
561 # https://eXtremeSHOK.com ######################################################
562 # This file contains the cron settings for clamav-unofficial-sigs.sh
563 ###################
564 # This is property of eXtremeSHOK.com
565 # You are free to use, modify and distribute, however you may not remove this notice.
566 # Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
567 ##################
568 #
569 # Script updates can be found at: https://github.com/extremeshok/clamav-unofficial-sigs
570
571 # Originially based on: 
572 # Script provide by Bill Landry (unofficialsigs@gmail.com).
573 #
574 # License: BSD (Berkeley Software Distribution)
575 #
576 ##################
577 # Automatically Generated: $(date)
578 ##################
579 #
580 # This cron file will execute the clamav-unofficial-sigs.sh script that
581 # currently supports updating third-party signature databases provided
582 # by Sanesecurity, SecuriteInfo, MalwarePatrol, OITC, etc.
583 #
584 # The script is set to run hourly, at a random minute past the hour, and the 
585 # script itself is set to randomize the actual execution time between
586 # 60 - 600 seconds.  To Adjust the cron values, edit your configs and run
587 # bash clamav-unofficial-sigs.sh --install-cron to generate a new file.
588
589 $cron_minute * * * * $cron_user [ -x $cron_script_full_path ] && $cron_bash $cron_script_full_path > /dev/null
590
591 # https://eXtremeSHOK.com ######################################################
592
593 EOF
594
595   fi 
596   echo "Completed: cron installed, as file: $cron_dir/$cron_filename"
597 }
598
599
600 #decode a third-party signature either by signature name
601 function decode_third_party_signature_by_signature_name () {
602   echo ""
603   echo "Input a third-party signature name to decode (e.g: Sanesecurity.Junk.15248) or"
604   echo "a hexadecimal encoded data string and press enter (do not include '.UNOFFICIAL'"
605   echo "in the signature name nor add quote marks to any input string):"
606   read -r input
607   input=$(echo "$input" | tr -d "'" | tr -d '"')
608   if echo "$input" | $grep_bin "\." > /dev/null ; then
609     cd "$clam_dbs" || exit
610     sig=$($grep_bin "$input:" ./*.ndb)
611     if [ -n "$sig" ] ; then
612       db_file=$(echo "$sig" | cut -d ':' -f1)
613       echo "$input found in: $db_file"
614       echo "$input signature decodes to:"
615       echo "$sig" | cut -d ":" -f5 | perl -pe 's/([a-fA-F0-9]{2})|(\{[^}]*\}|\([^)]*\))/defined $2 ? $2 : chr(hex $1)/eg'
616     else
617       echo "Signature '$input' could not be found."
618       echo "This script will only decode ClamAV 'UNOFFICIAL' third-Party,"
619       echo "non-image based, signatures as found in the *.ndb databases."
620     fi
621   else
622     echo "Here is the decoded hexadecimal input string:"
623     echo "$input" | perl -pe 's/([a-fA-F0-9]{2})|(\{[^}]*\}|\([^)]*\))/defined $2 ? $2 : chr(hex $1)/eg'
624   fi
625 }
626
627 #Hexadecimal encode an entire input string
628 function hexadecimal_encode_entire_input_string () {
629   echo ""
630   echo "Input the data string that you want to hexadecimal encode and then press enter.  Do not include"
631   echo "any quotes around the string unless you want them included in the hexadecimal encoded output:"
632   read -r input
633   echo "Here is the hexadecimal encoded input string:"
634   echo "$input" | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg'
635 }
636
637 #Hexadecimal encode a formatted input string
638 function hexadecimal_encode_formatted_input_string () {
639   echo ""
640   echo "Input a formated data string containing spacing fields '{}, (), *' that you want to hexadecimal"
641   echo "encode, without encoding the spacing fields, and then press enter.  Do not include any quotes"
642   echo "around the string unless you want them included in the hexadecimal encoded output:"
643   read -r input
644   echo "Here is the hexadecimal encoded input string:"
645   echo "$input" | perl -pe 's/(\{[^}]*\}|\([^)]*\)|\*)|(.)/defined $1 ? $1 : sprintf("%02lx", ord $2)/eg'
646 }
647
648 #GPG verify a specific Sanesecurity database file
649 function gpg_verify_specific_sanesecurity_database_file () { #databasefile
650   echo ""
651   if [ "$1" ] ; then
652     db_file=$(echo "$1" | awk -F '/' '{print $NF}')
653     if [ -r "$work_dir_sanesecurity/$db_file" ] ; then
654       echo "GPG signature testing database file: $work_dir_sanesecurity/$db_file"
655       if [ -r "$work_dir_sanesecurity/$db_file".sig ] ; then
656         "$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"
657         if [ "$?" != "0" ]; then
658           "$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"
659           if [ "$?" == "0" ]; then
660             exit 0
661           else
662             exit 1
663           fi
664         else
665           exit 0
666         fi
667       else
668         echo "Signature '$db_file.sig' cannot be found."
669       fi
670     else
671       echo "File '$db_file' cannot be found or is not a Sanesecurity database file."
672       echo "Only the following Sanesecurity and OITC databases can be GPG signature tested:"
673       ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_sanesecurity"
674     fi
675   else
676     xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
677     exit 1
678   fi
679 }
680
681 #Output system and configuration information
682 function output_system_configuration_information () {
683   echo ""
684   echo "*** SCRIPT VERSION ***"
685   echo "$this_script_name $script_version ($script_version_date)"
686   echo "*** SYSTEM INFORMATION ***"
687   $uname_bin -a
688   echo "*** CLAMSCAN LOCATION & VERSION ***"
689   echo "$clamscan_bin"
690   $clamscan_bin --version | head -1
691   echo "*** RSYNC LOCATION & VERSION ***"
692   echo "$rsync_bin"
693   $rsync_bin --version | head -1
694   if [ "$wget_bin" != "" ] ; then
695     echo "*** WGET LOCATION & VERSION ***"
696     echo "$wget_bin"
697     $wget_bin --version | head -1
698   else
699     echo "*** CURL LOCATION & VERSION ***"
700     echo "$curl_bin"
701     $curl_bin --version | head -1
702   fi
703   echo "*** GPG LOCATION & VERSION ***"
704   echo "$gpg_bin"
705   $gpg_bin --version | head -1
706   echo "*** SCRIPT WORKING DIRECTORY INFORMATION ***"
707   echo "$work_dir"
708   echo "*** CLAMAV DIRECTORY INFORMATION ***"
709   echo "$clam_dbs"
710   echo "*** SCRIPT CONFIGURATION SETTINGS ***"
711   if [ "$custom_config" != "no" ] ; then
712     if [ -d "$custom_config" ] ; then
713       # Assign the custom config dir and remove trailing / (removes / and //)
714       echo "Custom Configuration Directory: $config_dir"
715     else
716       echo "Custom Configuration File: $custom_config"
717     fi
718   else
719     echo "Configuration Directory: $config_dir"
720   fi
721 }
722
723 #Make a signature database from an ascii file
724 function make_signature_database_from_ascii_file () {
725   echo ""
726   echo "
727   The '-m' script flag provides a way to create a ClamAV hexadecimal signature database (*.ndb) file
728   from a list of data strings stored in a clear-text ascii file, with one data string entry per line.
729
730   - Hexadecimal encoding can be either 'full' or 'formatted' on a per line basis:
731
732   Full line encoding should be used if there are no formatted spacing entries [{}, (), *]
733   included on the line.  Prefix unformatted lines with: '-:' (no quote marks).
734
735   Example:
736
737   -:This signature contains no formatted spacing fields
738
739   Encodes to:
740
741   54686973207369676e617475726520636f6e7461696e73206e6f20666f726d61747465642073706163696e67206669656c6473
742
743   Formatted line encoding should be used if there are user added spacing entries [{}, (), *]
744   included on the line.  Prefix formatted lines with '=:' (no quote marks).
745
746   Example:
747
748   =:This signature{-10}contains several(25|26|27)formatted spacing*fields
749
750   Encodes to:
751
752   54686973207369676e6174757265{-10}636f6e7461696e73207365766572616c(25|26|27)666f726d61747465642073706163696e67*6669656c6473
753
754   Use 'full' encoding if you want to encode everything on the line [including {}, (), *] and 'formatted'
755   encoding if you want to encode everything on the line except the formatted character spacing fields.
756
757   The prefixes ('-:' and '=:') will be stripped from the line before hexadecimal encoding is done.
758   If no prefix is found at the beginning of the line, full line encoding will be done (default).
759
760   - It is assumed that the signatures will be created for email scanning purposes, thus the '4'
761   target type is used and full file scanning is enabled (see ClamAV signatures.pdf for details).
762
763   - Line numbering will be done automatically by the script.
764   " | command sed 's/^          //g'
765   echo -n "Do you wish to continue? "
766   if xshok_prompt_confirm ; then
767
768     echo -n "Enter the source file as /path/filename: "
769     read -r source
770     if [ -r "$source" ] ; then
771       source_file=$(basename "$source")
772
773       echo "What signature prefix would you like to use?  For example: 'Phish.Domains'"
774       echo "will create signatures that looks like: 'Phish.Domains.1:4:*:HexSigHere'"
775
776       echo -n "Enter signature prefix: "
777       read -r prefix
778       path_file=$(echo "$source" | cut -d "." -f-1 | command sed 's/$/.ndb/')
779       db_file=$(basename "$path_file")
780       rm -f "$path_file"
781       total=$(wc -l "$source" | cut -d " " -f1)
782       line_num=1
783
784       while read -r line ; do
785         line_prefix=$(echo "$line" | awk -F ':' '{print $1}')
786         if [ "$line_prefix" = "-" ] ; then
787           echo "$line" | cut -d ":" -f2- | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg' | command sed "s/^/$prefix\.$line_num:4:\*:/" >> "$path_file"
788         elif [ "$line_prefix" = "=" ] ; then
789           echo "$line" | cut -d ":" -f2- | perl -pe 's/(\{[^}]*\}|\([^)]*\)|\*)|(.)/defined $1 ? $1 : sprintf("%02lx", ord $2)/eg' | command sed "s/^/$prefix\.$line_num:4:\*:/" >> "$path_file"
790         else
791           echo "$line" | perl -pe 's/(.)/sprintf("%02lx", ord $1)/eg' | command sed "s/^/$prefix\.$line_num:4:\*:/" >> "$path_file"
792         fi
793         echo "Hexadecimal encoding $source_file line: $line_num of $total"
794         line_num=$((line_num + 1))
795       done < "$source"
796     else
797       echo "Source file not found, exiting..."
798       exit
799     fi
800
801
802     echo "Signature database file created at: $path_file"
803     if $clamscan_bin --quiet -d "$path_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
804
805       echo "Clamscan reports database integrity tested good."
806
807       echo -n "Would you like to move '$db_file' into '$clam_dbs' and reload databases?"
808       if xshok_prompt_confirm ; then
809         if ! cmp -s "$path_file" "$clam_dbs/$db_file" ; then
810           if $rsync_bin -pcqt "$path_file" "$clam_dbs" ; then
811             perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
812             perms chmod -f 0644 "$clam_dbs"/"$db_file"
813             if [ "$selinux_fixes" == "yes" ] ; then
814               restorecon "$clam_dbs/$db_file"
815             fi
816             $clamd_restart_opt
817
818             echo "Signature database '$db_file' was successfully implemented and ClamD databases reloaded."
819           else
820
821             echo "Failed to add/update '$db_file', ClamD database not reloaded."
822           fi
823         else
824
825           echo "Database '$db_file' has not changed - skipping"
826         fi
827       else
828
829         echo "No action taken."
830       fi
831     else
832
833       echo "Clamscan reports that '$db_file' signature database integrity tested bad."
834     fi
835   fi
836 }
837
838 #Remove the clamav-unofficial-sigs script
839 function remove_script () {
840   echo ""
841   if [ -n "$pkg_mgr" ] || [ -n "$pkg_rm" ] ; then
842     echo "This script (clamav-unofficial-sigs) was installed on the system via '$pkg_mgr'"
843     echo "use '$pkg_rm' to remove the script and all of its associated files and databases from the system."
844
845   else
846     cron_file_full_path="$cron_dir/$cron_filename"
847     logrotate_file_full_path="$logrotate_dir/$logrotate_filename"
848     man_file_full_path="$man_dir/$man_filename"
849     
850     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)"
851     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?"
852     if xshok_prompt_confirm ; then
853       echo "This can not be undone are you sure ?"
854       if xshok_prompt_confirm ; then
855         if [ -r "$work_dir_work_configs/purge.txt" ] ; then
856
857           while read -r file ; do
858             xshok_is_file "$file" && rm -f -- "$file"
859             echo "     Removed file: $file"
860           done < "$work_dir_work_configs"/purge.txt
861           if [ -r "$cron_file_full_path" ] ; then
862             xshok_is_file "$cron_file_full_path" && rm -f "$cron_file_full_path"
863             echo "     Removed file: $cron_file_full_path"
864           fi
865           if [ -r "$logrotate_file_full_path" ] ; then
866             xshok_is_file "$logrotate_file_full_path" && rm -f "$logrotate_file_full_path"
867             echo "     Removed file: $logrotate_file_full_path"
868           fi
869           if [ -r "$man_file_full_path" ] ; then
870             xshok_is_file "$man_file_full_path" && rm -f "$man_file_full_path"
871             echo "     Removed file: $man_file_full_path"
872           fi
873           
874           #rather keep the configs
875           #rm -f -- "$default_config" && echo "     Removed file: $default_config"
876           #rm -f -- "$0" && echo "     Removed file: $0"
877           xshok_is_subdir "$work_dir" && rm -rf -- "$work_dir" && echo "     Removed script working directories: $work_dir"
878
879           echo "  The clamav-unofficial-sigs script and all of its associated files, third-party"
880           echo "  databases, and work directories have been successfully removed from the system."
881
882         else
883           echo "  Cannot locate 'purge.txt' file in $work_dir_work_configs."
884           echo "  Files and signature database will need to be removed manually."
885         fi
886       else
887         echo "Aborted"
888       fi
889     else
890       echo "Aborted"
891     fi
892   fi
893 }
894
895 #Clamscan integrity test a specific database file
896 function clamscan_integrity_test_specific_database_file () { #databasefile
897   echo ""
898   if [ "$1" ] ; then
899     input=$(echo "$1" | awk -F '/' '{print $NF}')
900     db_file=$(find "$work_dir" -name "$input")
901     if [ -r "$db_file" ] ; then
902       echo "Clamscan integrity testing: $db_file"
903
904       $clamscan_bin --quiet -d "$db_file" "$work_dir_work_configs/scan-test.txt"
905       if [ "$?" -eq "0" ]; then
906         echo "Clamscan reports that '$input' database integrity tested GOOD"
907         exit 0
908       else
909         echo "Clamscan reports that '$input' database integrity tested BAD"
910         exit 1
911       fi
912     else
913       echo "File '$input' cannot be found."
914       echo "Here is a list of third-party databases that can be clamscan integrity tested:"
915
916       echo "=== Sanesecurity ==="
917       ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_sanesecurity"
918       
919       echo "=== SecuriteInfo ==="
920       ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_securiteinfo"
921       
922       echo "=== MalwarePatrol ==="
923       ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_malwarepatrol"
924
925       echo "=== Linux Malware Detect ==="
926       ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_linuxmalwaredetect"
927
928       echo "=== Linux Malware Detect ==="
929       ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_yararulesproject"
930
931       echo "=== User Defined Databases ==="
932       ls --ignore "*.sig" --ignore "*.md5" --ignore "*.ign2" "$work_dir_add"
933
934       echo "Check the file name and try again..."
935     fi 
936   else
937     xshok_pretty_echo_and_log "ERROR: Missing value for option" "="
938     exit 1
939   fi
940 }
941
942 #output names of any third-party signatures that triggered during the HAM directory scan
943 function output_signatures_triggered_during_ham_directory_scan () {
944   echo ""
945   if [ -n "$ham_dir" ] ; then
946     if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
947       echo "The following third-party signatures triggered hits during the HAM Directory scan:"
948
949       $grep_bin -h -f "$work_dir_work_configs/whitelist.hex" "$work_dir"/*/*.ndb | cut -d ":" -f1
950     else
951       echo "No third-party signatures have triggered hits during the HAM Directory scan."
952     fi
953   else
954     echo "Ham directory scanning is not currently enabled in the script's configuration file."
955   fi
956 }
957
958 #Adds a signature whitelist entry in the newer ClamAV IGN2 format
959 function add_signature_whitelist_entry () {
960   echo ""
961   echo "Input a third-party signature name that you wish to whitelist due to false-positives"
962   echo "and press enter (do not include '.UNOFFICIAL' in the signature name nor add quote"
963   echo "marks to the input string):"
964
965   read -r input
966   if [ -n "$input" ] ; then
967     cd "$clam_dbs" || exit
968     input=$(echo "$input" | tr -d "'" | tr -d '"')
969     sig_full=$($grep_bin -H "$input" ./*.*db)
970     sig_name=$(echo "$sig_full" | cut -d ":" -f2)
971     if [ -n "$sig_name" ] ; then
972       if ! $grep_bin "$sig_name" my-whitelist.ign2 > /dev/null 2>&1 ; then
973         cp -f my-whitelist.ign2 "$work_dir_work_configs" 2>/dev/null
974         echo "$sig_name" >> "$work_dir_work_configs/my-whitelist.ign2"
975         echo "$sig_full" >> "$work_dir_work_configs/tracker.txt"
976         if $clamscan_bin --quiet -d "$work_dir_work_configs/my-whitelist.ign2" "$work_dir_work_configs/scan-test.txt" ; then
977           if $rsync_bin -pcqt "$work_dir_work_configs/my-whitelist.ign2" "$clam_dbs" ; then
978             perms chown -f "$clam_user:$clam_group" my-whitelist.ign2
979
980             if [ ! -s "$work_dir_work_configs/monitor-ign.txt" ] ; then 
981               # Create "monitor-ign.txt" file for clamscan database integrity testing.
982               echo "This is the monitor ignore file..." > "$work_dir_work_configs/monitor-ign.txt"
983             fi
984
985             perms chmod -f 0644 my-whitelist.ign2 "$work_dir_work_configs/monitor-ign.txt"
986             if [ "$selinux_fixes" == "yes" ] ; then
987               restorecon "$clam_dbs/local.ign"
988             fi
989             clamscan_reload_dbs
990
991             echo "Signature '$input' has been added to my-whitelist.ign2 and"
992             echo "all databases have been reloaded.  The script will track any changes"
993             echo "to the offending signature and will automatically remove it if the"
994             echo "signature is modified or removed from the third-party database."
995           else
996
997             echo "Failed to successfully update my-whitelist.ign2 file - SKIPPING."
998           fi
999         else
1000
1001           echo "Clamscan reports my-whitelist.ign2 database integrity is bad - SKIPPING."
1002         fi
1003       else
1004
1005         echo "Signature '$input' already exists in my-whitelist.ign2 - no action taken."
1006       fi
1007     else
1008
1009       echo "Signature '$input' could not be found."
1010
1011       echo "This script will only create a whitelise entry in my-whitelist.ign2 for ClamAV"
1012       echo "'UNOFFICIAL' third-Party signatures as found in the *.ndb *.hdb *.db databases."
1013     fi
1014   else
1015     echo "No input detected - no action taken."
1016   fi
1017 }
1018
1019 #Clamscan reload database
1020 function clamscan_reload_dbs () {
1021   # Reload all clamd databases if updates detected and $reload_dbs" is set to "yes"
1022   if [ "$reload_dbs" = "yes" ] ; then
1023     if [ "$do_clamd_reload" != "0" ] ; then
1024       if [ "$do_clamd_reload" = "1" ] ; then
1025         xshok_pretty_echo_and_log "Update(s) detected, reloading ClamAV databases" "="
1026       elif [ "$do_clamd_reload" = "2" ] ; then
1027         xshok_pretty_echo_and_log "Database removal(s) detected, reloading ClamAV databases" "="
1028       elif [ "$do_clamd_reload" = "3" ] ; then      
1029         xshok_pretty_echo_and_log "File 'local.ign' has changed, reloading ClamAV databases" "="
1030       elif [ "$do_clamd_reload" = "4" ] ; then      
1031         xshok_pretty_echo_and_log "File 'my-whitelist.ign2' has changed, reloading ClamAV databases" "="
1032       else
1033         xshok_pretty_echo_and_log "Update(s) detected, reloading ClamAV databases" "="
1034       fi
1035
1036       if [[ $($clamd_reload_opt 2>&1) = *"ERROR"* ]] ; then
1037         xshok_pretty_echo_and_log "ERROR: Failed to reload, trying again" "-"
1038         if [ -r "$clamd_pid" ] ; then
1039           mypid=$(cat "$clamd_pid")
1040           kill -USR2 "$mypid"
1041           if [ $? -eq  0 ] ; then
1042             xshok_pretty_echo_and_log "ClamAV databases Reloaded" "="
1043           else
1044             xshok_pretty_echo_and_log "ERROR: Failed to reload, forcing clamd to restart" "-"
1045             if [ -z "$clamd_restart_opt" ] ; then      
1046               xshok_pretty_echo_and_log "WARNING: Check the script's configuration file, 'reload_dbs' enabled but no 'clamd_restart_opt'" "*"
1047             else
1048               $clamd_restart_opt
1049               xshok_pretty_echo_and_log "ClamAV Restarted" "="
1050             fi
1051           fi
1052         else
1053           xshok_pretty_echo_and_log "ERROR: Failed to reload, forcing clamd to restart" "="
1054           if [ -z "$clamd_restart_opt" ] ; then      
1055             xshok_pretty_echo_and_log "WARNING: Check the script's configuration file, 'reload_dbs' enabled but no 'clamd_restart_opt'" "*"
1056           else
1057             $clamd_restart_opt
1058             xshok_pretty_echo_and_log "ClamAV Restarted" "="
1059           fi
1060         fi   
1061       else
1062         xshok_pretty_echo_and_log "ClamAV databases Reloaded" "="
1063       fi
1064     else   
1065       xshok_pretty_echo_and_log "No updates detected, ClamAV databases were not reloaded" "="
1066     fi
1067   else      
1068     xshok_pretty_echo_and_log "Database reload has been disabled in the configuration file" "="  
1069   fi
1070
1071 }
1072
1073 # If ClamD status check is enabled ("clamd_socket" variable is uncommented
1074 # and the socket path is correctly specified in "User Edit" section above),
1075 # then test to see if clamd is running or not.
1076 function check_clamav () {
1077   if [ -n "$clamd_socket" ] ; then
1078     if [ -S "$clamd_socket" ] ; then
1079       if [ "$(perl -e 'use IO::Socket::UNIX; print $IO::Socket::UNIX::VERSION,"\n"' 2>/dev/null)" ] ; then
1080         io_socket1=1
1081         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
1082           io_socket2=1
1083           xshok_pretty_echo_and_log "ClamD is running" "="
1084         fi
1085       else
1086         socat="$(which socat 2>/dev/null)"
1087         if [ -n "$socat" ] && [ -x "$socat" ] ; then
1088           socket_cat1=1
1089           if [ "$( (echo "PING"; sleep 1;) | socat - "$clamd_socket" 2>/dev/null)" = "PONG" ] ; then
1090             socket_cat2=1
1091             xshok_pretty_echo_and_log "ClamD is running" "="
1092           fi
1093         fi
1094       fi
1095       if [ -z "$io_socket1" ] && [ -z "$socket_cat1" ] ; then
1096         xshok_pretty_echo_and_log "WARNING: socat or perl module 'IO::Socket::UNIX' not found, cannot test if ClamD is running" "*"
1097       else
1098         if [ -z "$io_socket2" ] && [ -z "$socket_cat2" ] ; then
1099
1100           xshok_pretty_echo_and_log "ALERT: CLAMD IS NOT RUNNING!" "="
1101           if [ -n "$clamd_restart_opt" ] ; then
1102             xshok_pretty_echo_and_log "Attempting to start ClamD..." "-"
1103             if [ -n "$io_socket1" ] ; then
1104               $clamd_restart_opt > /dev/null && sleep 5
1105               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
1106                 xshok_pretty_echo_and_log "ClamD was successfully started" "="
1107               else
1108                 xshok_pretty_echo_and_log "ERROR: CLAMD FAILED TO START" "="
1109                 exit 1
1110               fi
1111             else
1112               if [ -n "$socket_cat1" ] ; then
1113                 $clamd_restart_opt > /dev/null && sleep 5
1114                 if [ "$( (echo "PING"; sleep 1;) | socat - "$clamd_socket" 2>/dev/null)" = "PONG" ] ; then
1115                   xshok_pretty_echo_and_log "ClamD was successfully started" "="
1116                 else
1117                   xshok_pretty_echo_and_log "ERROR: CLAMD FAILED TO START" "="
1118                   exit 1
1119                 fi
1120               fi
1121             fi
1122           fi
1123         fi
1124       fi
1125     else
1126       xshok_pretty_echo_and_log "WARNING: $clamd_socket is not a usable socket" "*"
1127     fi
1128   else
1129     xshok_pretty_echo_and_log "WARNING: clamd_socket is not defined in the configuration file" "*"
1130   fi
1131 }
1132
1133 #function to check for a new version
1134 function check_new_version () {
1135   if [ "$wget_bin" != "" ] ; then
1136     latest_version="$($wget_bin https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/clamav-unofficial-sigs.sh -O - 2> /dev/null | $grep_bin  "script""_version=" | cut -d\" -f2)"
1137   else
1138     latest_version="$($curl_bin https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/clamav-unofficial-sigs.sh 2> /dev/null | $grep_bin  "script""_version=" | cut -d\" -f2)"
1139   fi
1140   if [ "$latest_version" ] ; then
1141     if [ ! "$latest_version" == "$script_version" ] ; then
1142       xshok_pretty_echo_and_log "New version : v$latest_version @ https://github.com/extremeshok/clamav-unofficial-sigs" "-"
1143     fi
1144   fi
1145 }
1146
1147 #function for help and usage
1148 ##usage: 
1149 # help_and_usage "1" - enables the man output formatting
1150 # help_and_usage - normal help output formatting
1151 function help_and_usage () {
1152
1153   if [ "$1" ] ; then
1154     #option_format_start
1155     ofs="\fB"
1156     #option_format_end
1157     ofe="\fR"
1158     #option_format_blankline
1159     ofb=".TP"
1160     #option_format_tab_line
1161     oft=" "
1162   else
1163     #option_format_start
1164     ofs="${BOLD}"
1165     #option_format_end
1166     ofe="${NORM}\t"
1167     #option_format_blankline
1168     ofb="\n"
1169     #option_format_tab_line
1170     oft="\n\t"
1171   fi
1172
1173 helpcontents=$(cat << EOF
1174 $ofs Usage: $(basename "$0") $ofe [OPTION] [PATH|FILE]
1175 $ofb
1176 $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
1177 $ofb 
1178 $ofs -F, --force $ofe Force all databases to be downloaded, could cause ip to be blocked
1179 $ofb 
1180 $ofs -h, --help $ofe Display this script's help and usage information
1181 $ofb 
1182 $ofs -V, --version $ofe Output script version and date information
1183 $ofb 
1184 $ofs -v, --verbose $ofe Be verbose, enabled when not run under cron
1185 $ofb 
1186 $ofs -s, --silence $ofe Only output error messages, enabled when run under cron
1187 $ofb 
1188 $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
1189 $ofb 
1190 $ofs -e, --encode-string $ofe Hexadecimal encode an entire input string that can $oft be used in any '*.ndb' signature database file
1191 $ofb 
1192 $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
1193 $ofb 
1194 $ofs -g, --gpg-verify $ofe GPG verify a specific Sanesecurity database file $oft eg: '-g filename.ext' (do not include file path)
1195 $ofb 
1196 $ofs -i, --information $ofe Output system and configuration information for $oft viewing or possible debugging purposes
1197 $ofb 
1198 $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
1199 $ofb 
1200 $ofs -t, --test-database $ofe Clamscan integrity test a specific database file $oft eg: '-t filename.ext' (do not include file path)
1201 $ofb 
1202 $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
1203 $ofb 
1204 $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
1205 $ofb 
1206 $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
1207 $ofb 
1208 $ofs --install-all $ofe Install and generate the cron, logroate and man files, autodetects the values $oft based on your config files
1209 $ofb
1210 $ofs --install-cron $ofe Install and generate the cron file, autodetects the values $oft based on your config files
1211 $ofb 
1212 $ofs --install-logrotate $ofe Install and generate the logrotate file, autodetects the $oft values based on your config files
1213 $ofb 
1214 $ofs --install-man $ofe Install and generate the man file, autodetects the $oft values based on your config files
1215 $ofb 
1216 $ofs --remove-script $ofe Remove the clamav-unofficial-sigs script and all of $oft its associated files and databases from the system
1217 $ofb 
1218 EOF
1219   ) #this is very important...
1220
1221   if [ "$1" ] ; then
1222     echo "${helpcontents//-/\\-}"
1223   else
1224     echo -e "$helpcontents"
1225   fi
1226 }
1227
1228 ################################################################################
1229 # MAIN PROGRAM
1230 ################################################################################
1231
1232 #Script Info
1233 script_version="5.4.1"
1234 script_version_date="20 July 2016"
1235 minimum_required_config_version="65"
1236 minimum_yara_clamav_version="0.99"
1237
1238 #default config files
1239 config_dir="/etc/clamav-unofficial-sigs"
1240 config_files=("$config_dir/master.conf" "$config_dir/os.conf" "$config_dir/user.conf")
1241
1242 #Initialise 
1243 config_version="0"
1244 do_clamd_reload="0"
1245 comment_silence="no"
1246 logging_enabled="no"
1247 force_updates="no"
1248 enable_log="no"
1249 custom_config="no"
1250 we_have_a_config="0"
1251
1252 ## Solaris which function returns garbage when the program is not found
1253 ## only define the new which function if running under Solaris
1254 if [ "$(uname -s)" = "SunOS" ] ; then
1255   which () {
1256     # use the switch -p to ignore ksh internal commands
1257     ksh whence -p "$@"
1258   }
1259 fi
1260
1261 #Default Binaries & Commands
1262 clamd_reload_opt="clamdscan --reload"
1263 uname_bin=$(which uname)
1264 clamscan_bin=$(which clamscan)
1265 rsync_bin=$(which rsync)
1266 #detect support for wget
1267 if [ -x /usr/sfw/bin/wget ] ; then
1268   wget_bin="/usr/sfw/bin/wget"
1269 else
1270   wget_bin=$(which wget)
1271 fi
1272 if [ "$wget_bin" == "" ] ; then
1273   curl_bin=$(which curl)
1274 fi
1275 #detect supprot for gnu grep
1276 if [ -x /usr/gnu/bin/grep ] ; then
1277   grep_bin="/usr/gnu/bin/grep"
1278 else
1279   grep_bin=$(which grep)
1280 fi
1281 if [ -x /opt/csw/bin/gpg ] ; then
1282   gpg_bin="/opt/csw/bin/gpg"
1283 else
1284   gpg_bin=$(which gpg)
1285 fi
1286 if [ "$gpg_bin" == "" ] ; then
1287   gpg_bin=$(which gpg2)
1288 fi
1289
1290 #Detect if terminal
1291 if [ -t 1 ] ; then
1292   #Set fonts
1293   ##Usage: echo "${BOLD}-a${NORM}"
1294   BOLD=$(tput bold)
1295   #REV=$(tput smso)
1296   NORM=$(tput sgr0)
1297   #Verbose
1298   force_verbose="yes"
1299 else
1300   #Null Fonts
1301   BOLD=''
1302   #REV=''
1303   NORM=''
1304   #silence
1305   force_verbose="no"
1306 fi
1307
1308
1309 # Generic command line options
1310 while true ; do
1311   case "$1" in
1312     -c | --config ) xshok_check_s2 "$2"; custom_config="$2"; shift 2; break ;;
1313     -F | --force ) force_updates="yes"; shift 1; break ;;
1314     -v | --verbose ) force_verbose="yes"; shift 1; break ;;
1315     -s | --silence ) force_verbose="no"; shift 1; break ;;
1316     * ) break ;;
1317   esac
1318 done
1319
1320 #Set the verbosity
1321 if [ "$force_verbose" == "yes" ] ; then
1322   #verbose
1323   downloader_silence="no"
1324   rsync_silence="no"
1325   gpg_silence="no"
1326   comment_silence="no"
1327 else
1328   #silence
1329   downloader_silence="yes"
1330   rsync_silence="yes"
1331   gpg_silence="yes"
1332   comment_silence="yes"
1333 fi
1334
1335 xshok_pretty_echo_and_log "" "#" "80"
1336 xshok_pretty_echo_and_log " eXtremeSHOK.com ClamAV Unofficial Signature Updater"
1337 xshok_pretty_echo_and_log " Version: v$script_version ($script_version_date)"
1338 xshok_pretty_echo_and_log " Required Configuration Version: v$minimum_required_config_version"
1339 xshok_pretty_echo_and_log " Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com"
1340 xshok_pretty_echo_and_log "" "#" "80"
1341
1342 # Generic command line options
1343 while true ; do
1344   case "$1" in
1345     -h | --help ) help_and_usage; exit; break ;;
1346     -V | --version ) exit; break ;;
1347     * ) break ;;
1348   esac
1349 done
1350
1351 ## CONFIG LOADING AND ERROR CHECKING ##############################################
1352 if [ "$custom_config" != "no" ] ; then
1353   if [ -d "$custom_config" ] ; then
1354     # Assign the custom config dir and remove trailing / (removes / and //)
1355     config_dir=$(echo "$custom_config" | sed 's:/*$::')
1356     config_files=("$config_dir/master.conf" "$config_dir/os.conf" "$config_dir/user.conf")
1357   else
1358     config_files=("$custom_config")
1359   fi
1360 fi
1361
1362 for config_file in "${config_files[@]}" ; do
1363   if [ -r "$config_file" ] ; then #exists and readable
1364     we_have_a_config="1"
1365     #config stripping
1366     xshok_pretty_echo_and_log "Loading config: $config_file" "="
1367
1368    
1369
1370     if [ "$(uname -s)" = "SunOS" ] ; then
1371       #Solaris FIXES only, i had issues with running with a single command..
1372       clean_config=$(command sed -e '/^#.*/d' "$config_file") # comment line
1373       clean_config=$(echo "$clean_config" | sed -e 's/#[[:space:]].*//') # comment line (duplicated)
1374       clean_config=$(echo "$clean_config" | sed -e '/^[[:blank:]]*#/d;s/#.*//') #comments at end of line
1375       clean_config=$(echo "$clean_config" | sed -e 's/^[ \t]*//;s/[ \t]*$//') #trailing and leading whitespace
1376       clean_config=$(echo "$clean_config" | sed -e '/^\s*$/d') #blank lines
1377     else 
1378       # delete lines beginning with #
1379       # delete from ' #' to end of the line
1380       # delete from '# ' to end of the line
1381       # delete both trailing and leading whitespace
1382       # delete all trailing whitespace
1383       # delete all empty lines
1384       clean_config=$(command sed -e '/^#.*/d' -e 's/[[:space:]]#.*//' -e 's/#[[:space:]].*//' -e 's/^[ \t]*//;s/[ \t]*$//' -e '/^\s*$/d' "$config_file")
1385     fi
1386     
1387     ### config error checking
1388     # check "" are an even number
1389     config_check="${clean_config//[^\"]}"
1390     if [ $(( ${#config_check} % 2)) -eq 1 ] ; then 
1391       xshok_pretty_echo_and_log "ERROR: Your configuration has errors, every \" requires a closing \"" "="     
1392       exit 1
1393     fi
1394
1395     # check there is an = for every set of "" #optional whitespace \s* between = and "
1396     config_check_vars=$(echo "$clean_config" | $grep_bin -c '=\s*\"' )
1397
1398     if [ $(( ${#config_check} / 2)) -ne "$config_check_vars" ] ; then 
1399       xshok_pretty_echo_and_log "ERROR: Your configuration has errors, every = requires a pair of \"\"" "="    
1400       exit 1
1401     fi
1402
1403     #config loading
1404     for i in "${clean_config[@]}" ; do
1405       eval "$(echo "${i}" | command sed -e 's/[[:space:]]*$//' 2> /dev/null)"
1406     done
1407   fi
1408 done
1409
1410
1411
1412 # Assign the log_file_path earlier and remove trailing / (removes / and //)
1413 log_file_path=$(echo "$log_file_path" | sed 's:/*$::')
1414 #Only start logging once all the configs have been loaded
1415 if [ "$logging_enabled" == "yes" ] ; then
1416   enable_log="yes"
1417 fi
1418
1419 ## Make sure we have a readable config file
1420 if [ "$we_have_a_config" == "0" ] ; then
1421   xshok_pretty_echo_and_log "ERROR: Config file/s could NOT be read/loaded" "="
1422   exit 1
1423 fi
1424
1425 #prevent some issues with an incomplete or only a user.conf being loaded
1426 if [ $config_version  == "0" ] ; then
1427   xshok_pretty_echo_and_log "ERROR: Config file/s are missing important contents" "="
1428   xshok_pretty_echo_and_log "Note: Possible fix would be to point the script to the dir with the configs"
1429   exit 1
1430 fi
1431
1432 #config version validation
1433 if [ $config_version -lt $minimum_required_config_version ] ; then
1434   xshok_pretty_echo_and_log "ERROR: Your config version $config_version is not compatible with the min required version $minimum_required_config_version" "="
1435   exit 1
1436 fi
1437
1438 # Check to see if the script's "USER CONFIGURATION FILE" has been completed.
1439 if [ "$user_configuration_complete" != "yes" ] ; then
1440   xshok_pretty_echo_and_log "WARNING: SCRIPT CONFIGURATION HAS NOT BEEN COMPLETED" "*"
1441   xshok_pretty_echo_and_log "Please review the script configuration files."
1442   exit 1
1443 fi
1444
1445 # Assign the directories and remove trailing / (removes / and //)
1446 work_dir=$(echo "$work_dir" | sed 's:/*$::')
1447
1448 #Allow overriding of all the individual workdirs, this is mainly to aid package maintainers
1449 if [ ! -n "$work_dir_sanesecurity" ] ; then
1450   work_dir_sanesecurity=$(echo "$work_dir/$sanesecurity_dir" | sed 's:/*$::')
1451 else
1452   work_dir_sanesecurity=$(echo "$work_dir_sanesecurity" | sed 's:/*$::')
1453 fi
1454 if [ ! -n "$work_dir_securiteinfo" ] ; then
1455   work_dir_securiteinfo=$(echo "$work_dir/$securiteinfo_dir" | sed 's:/*$::')
1456 else
1457   work_dir_securiteinfo=$(echo "$work_dir_securiteinfo" | sed 's:/*$::')
1458 fi
1459 if [ ! -n "$work_dir_linuxmalwaredetect" ] ; then
1460   work_dir_linuxmalwaredetect=$(echo "$work_dir/$linuxmalwaredetect_dir" | sed 's:/*$::')
1461 else
1462   work_dir_linuxmalwaredetect=$(echo "$work_dir_linuxmalwaredetect" | sed 's:/*$::')
1463 fi
1464 if [ ! -n "$work_dir_malwarepatrol" ] ; then
1465   work_dir_malwarepatrol=$(echo "$work_dir/$malwarepatrol_dir" | sed 's:/*$::')
1466 else
1467   work_dir_malwarepatrol=$(echo "$work_dir_malwarepatrol" | sed 's:/*$::')
1468 fi
1469 if [ ! -n "$work_dir_yararulesproject" ] ; then
1470   work_dir_yararulesproject=$(echo "$work_dir/$yararulesproject_dir" | sed 's:/*$::')
1471 else
1472   work_dir_yararulesproject=$(echo "$work_dir_yararulesproject" | sed 's:/*$::')
1473 fi
1474 if [ ! -n "$work_dir_add" ] ; then
1475   work_dir_add=$(echo "$work_dir/$add_dir" | sed 's:/*$::')
1476 else
1477   work_dir_add=$(echo "$work_dir_add" | sed 's:/*$::')
1478 fi
1479 if [ ! -n "$work_dir_work_configs" ] ; then
1480   work_dir_work_configs=$(echo "$work_dir/$work_dir_configs" | sed 's:/*$::')
1481 else
1482   work_dir_work_configs=$(echo "$work_dir_work_configs" | sed 's:/*$::')
1483 fi
1484 if [ ! -n "$work_dir_gpg" ] ; then
1485   work_dir_gpg=$(echo "$work_dir/$gpg_dir" | sed 's:/*$::')
1486 else
1487   work_dir_gpg=$(echo "$work_dir_gpg" | sed 's:/*$::')
1488 fi
1489
1490 if [ ! -n "$work_dir_pid" ] ; then
1491   work_dir_pid=$(echo "$work_dir/$pid_dir" | sed 's:/*$::')
1492 else
1493   work_dir_pid=$(echo "$work_dir_pid" | sed 's:/*$::')
1494 fi
1495
1496 # Assign defaults if not defined
1497 if [ ! -n "$cron_dir" ] ; then
1498   cron_dir="/etc/cron.d"
1499 fi
1500 cron_dir=$(echo "$cron_dir" | sed 's:/*$::')
1501 if [ ! -n "$cron_filename" ] ; then
1502   cron_filename="clamav-unofficial-sigs"
1503 fi
1504 if [ ! -n "$logrotate_dir" ] ; then
1505   logrotate_dir="/etc/logrotate.d"
1506 fi
1507 logrotate_dir=$(echo "$logrotate_dir" | sed 's:/*$::')
1508 if [ ! -n "$logrotate_filename" ] ; then
1509   logrotate_filename="clamav-unofficial-sigs"
1510 fi  
1511 if [ ! -n "$man_dir" ] ; then
1512   man_dir="/usr/share/man/man8"
1513 fi
1514 man_dir=$(echo "$man_dir" | sed 's:/*$::')
1515 if [ ! -n "$man_filename" ] ; then
1516   man_filename="clamav-unofficial-sigs.8"
1517 fi  
1518 if [ ! -n "$man_log_file_full_path" ] ; then
1519   man_log_file_full_path="$log_file_path/$log_file_name"
1520 fi
1521
1522 ### SANITY checks
1523 #Check default Binaries & Commands are defined
1524 if [ "$clamd_reload_opt" == "" ] ; then
1525   xshok_pretty_echo_and_log "ERROR: Missing clamd_reload_opt" "="
1526   exit 1
1527 fi
1528 if [ "$uname_bin" == "" ] ; then
1529   xshok_pretty_echo_and_log "ERROR: uname (uname_bin) not found" "="
1530   exit 1
1531 fi
1532 if [ "$clamscan_bin" == "" ] ; then
1533   xshok_pretty_echo_and_log "ERROR: clamscan binary (clamscan_bin) not found" "="
1534   exit 1
1535 fi
1536 if [ "$rsync_bin" == "" ] ; then
1537   xshok_pretty_echo_and_log "ERROR: rsync binary (rsync_bin) not found" "="
1538   exit 1
1539 fi
1540 if [ "$wget_bin" == "" ] ; then
1541   if [ "$curl_bin" == "" ] ; then
1542     xshok_pretty_echo_and_log "ERROR: wget and curl binaries not found, script requires either wget or curl" "="
1543     exit 1
1544   fi
1545 fi
1546 if [ "$gpg_bin" == "" ] ; then
1547   xshok_pretty_echo_and_log "ERROR: gpg binary (gpg_bin) not found" "="
1548   exit 1
1549 fi
1550 #Check default directories are defined
1551 if [ "$work_dir" == "" ] ; then
1552   xshok_pretty_echo_and_log "ERROR: working directory (work_dir) not defined" "="
1553   exit 1
1554 fi
1555
1556 # Reset the update timers to force a full update.
1557 if [ "$force_updates" == "yes" ] ; then
1558   xshok_pretty_echo_and_log "Force Updates: enabled" 
1559   sanesecurity_update_hours="0"    
1560   securiteinfo_update_hours="0"
1561   linuxmalwaredetect_update_hours="0"
1562   malwarepatrol_update_hours="0"
1563   yararulesproject_update_hours="0"
1564   additional_update_hours="0"
1565 fi
1566
1567 # Enable pid file to prevent issues with multiple instances
1568 # opted not to use flock as it appears to have issues with some systems
1569 if [ "$enable_locking" == "yes" ] ; then
1570   xshok_mkdir_ownership "$work_dir_pid"
1571   pid_file_fullpath="$work_dir_pid/clamav-unofficial-sigs.pid"
1572   if [ -f "$pid_file_fullpath" ] ; then
1573     pid_file_pid=$(cat "$pid_file_fullpath")
1574     ps -p "$pid_file_pid" > /dev/null 2>&1
1575     if [ $? -eq 0 ] ; then 
1576       xshok_pretty_echo_and_log "ERROR: Only one instance can run at the same time." "="
1577       exit 1
1578     else
1579       xshok_create_pid_file "$pid_file_fullpath"
1580     fi
1581   else
1582       xshok_create_pid_file "$pid_file_fullpath"
1583   fi
1584   # run this wehen the script exits
1585   trap -- "rm -f $pid_file_fullpath" EXIT
1586 fi
1587
1588 # Verify the clam_user and clam_group actually exists on the system
1589 if ! xshok_user_group_exists "$clam_user" "$clam_group" ; then
1590   xshok_pretty_echo_and_log "ERROR: Either the user: $clam_user and/or group: $clam_group does not exist on the system." "="
1591   exit 1
1592 fi
1593
1594 # Silence rsync output and only report errors - useful if script is run via cron.
1595 if [ "$rsync_silence" = "yes" ] ; then
1596   rsync_output_level="--quiet"
1597 else
1598   rsync_output_level="--progress"
1599 fi
1600
1601 # If the local rsync client supports the '--no-motd' flag, then enable it.
1602 if $rsync_bin --help | $grep_bin 'no-motd' > /dev/null ; then
1603   no_motd="--no-motd"
1604 fi
1605
1606 # If the local rsync client supports the '--contimeout' flag, then enable it.
1607 if $rsync_bin --help | $grep_bin 'contimeout' > /dev/null ; then
1608   connect_timeout="--contimeout=$rsync_connect_timeout"
1609 fi
1610
1611 # Silence wget output and only report errors - useful if script is run via cron.
1612 if [ "$downloader_silence" = "yes" ] ; then
1613   wget_output_level="--quiet" #--quiet
1614   curl_output_level="--silent --show-error"
1615 else
1616   wget_output_level="--no-verbose"
1617   curl_output_level=""
1618 fi
1619
1620 #suppress ssl warnings
1621 if [ "$downloader_ignore_ssl" = "yes" ] ; then
1622   wget_insecure="--no-check-certificate"
1623   curl_insecure="--insecure"
1624 else
1625   wget_insecure=""
1626   curl_insecure=""
1627 fi
1628
1629 # This scripts name and path
1630 this_script_name="$(basename "$0")"
1631 this_script_path="$( cd "$(dirname "$0")" ; pwd -P )"
1632 this_script_full_path="$this_script_path/$this_script_name"
1633
1634 #set the script to 755 permissions
1635 if xshok_is_root ; then
1636   if [ "$setmode" == "yes" ] ; then
1637     if [ ! -x "$this_script_path/$this_script_name" ] ; then
1638       chmod 755 "$this_script_path/$this_script_name"
1639       xshok_pretty_echo_and_log "Fixing permission on $this_script_path/$this_script_name" "="
1640     fi
1641   fi
1642 else
1643   #disable setmode
1644   setmode="no"
1645 fi
1646
1647 ################################################################################
1648 # MAIN LOGIC
1649 ################################################################################
1650
1651 while true; do
1652   case "$1" in
1653     -d | --decode-sig ) decode_third_party_signature_by_signature_name; exit; break ;;
1654     -e | --encode-string ) hexadecimal_encode_entire_input_string; exit; break ;;
1655     -f | --encode-formatted ) hexadecimal_encode_formatted_input_string; exit; break ;;
1656     -g | --gpg-verify ) xshok_check_s2 "$2"; gpg_verify_specific_sanesecurity_database_file "$2"; exit; break ;;
1657     -i | --information ) output_system_configuration_information; exit; break ;;
1658     -m | --make-database ) make_signature_database_from_ascii_file; exit; break ;;
1659     -t | --test-database ) xshok_check_s2 "$2"; clamscan_integrity_test_specific_database_file "$2"; exit; break ;;
1660     -o | --output-triggered ) output_signatures_triggered_during_ham_directory_scan; exit; break ;;
1661     -w | --whitelist ) add_signature_whitelist_entry; exit; break ;;
1662     --check-clamav ) check_clamav; exit; break ;;
1663     --install-all ) install_cron; install_logrotate; install_man; exit; break ;;
1664     --install-cron ) install_cron; exit; break ;;
1665     --install-logrotate ) install_logrotate; exit; break ;;
1666     --install-man ) install_man; exit; break ;;
1667     --remove-script ) remove_script; exit; break ;;
1668     * ) break ;;
1669   esac
1670 done
1671
1672 xshok_pretty_echo_and_log "Preparing Databases" "="
1673
1674 # Check yararule support is available
1675 if [ "$enable_yararules" == "yes" ] ; then
1676   current_clamav_version=$($clamscan_bin -V | cut -d " " -f2 | cut -d "/" -f1 | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }')
1677   minimum_yara_clamav_version=$(echo "$minimum_yara_clamav_version" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }')
1678   #Check current clamav version against the minimum required version for yara support
1679   if [ "$current_clamav_version" -lt "$minimum_yara_clamav_version" ] ; then #older
1680     yararulesproject_enabled="no"
1681     enable_yararules="no"
1682     xshok_pretty_echo_and_log "Notice: Yararules Disabled due to clamav being older than the minimum required version"
1683   fi
1684 else
1685   yararulesproject_enabled="no"
1686   enable_yararules="no"
1687 fi
1688
1689 # Generate the signature databases
1690 if [ "$sanesecurity_enabled" == "yes" ] ; then
1691   if [ -n "$sanesecurity_dbs" ] ; then
1692     if [ -n "$sanesecurity_dbs_rating" ] ; then
1693       sanesecurity_dbs="$(xshok_database "$sanesecurity_dbs" "$sanesecurity_dbs_rating")"
1694     else
1695       sanesecurity_dbs="$(xshok_database "$sanesecurity_dbs" "$default_dbs_rating")"
1696     fi
1697   fi
1698 fi
1699 if [ "$securiteinfo_enabled" == "yes" ] ; then
1700   if [ -n "$securiteinfo_dbs" ] ; then
1701     if [ -n "$securiteinfo_dbs_rating" ] ; then
1702       securiteinfo_dbs="$(xshok_database "$securiteinfo_dbs" "$securiteinfo_dbs_rating")"
1703     else
1704       securiteinfo_dbs="$(xshok_database "$securiteinfo_dbs" "$default_dbs_rating")"
1705     fi
1706   fi
1707 fi
1708 if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
1709   if [ -n "$linuxmalwaredetect_dbs" ] ; then
1710     if [ -n "$linuxmalwaredetect_dbs_rating" ] ; then
1711       linuxmalwaredetect_dbs="$(xshok_database "$linuxmalwaredetect_dbs" "$linuxmalwaredetect_dbs_rating")"
1712     else
1713       linuxmalwaredetect_dbs="$(xshok_database "$linuxmalwaredetect_dbs" "$default_dbs_rating")"
1714     fi
1715   fi
1716 fi
1717 if [ "$yararulesproject_enabled" == "yes" ] ; then
1718   if [ -n "$yararulesproject_dbs" ] ; then
1719     if [ -n "$yararulesproject_dbs_rating" ] ; then
1720       yararulesproject_dbs="$(xshok_database "$yararulesproject_dbs" "$yararulesproject_dbs_rating")"
1721     else
1722       yararulesproject_dbs="$(xshok_database "$yararulesproject_dbs" "$default_dbs_rating")"
1723     fi
1724   fi
1725 fi
1726
1727 # Set the variables for MalwarePatrol
1728 if [ "$malwarepatrol_free" == "yes" ] ; then
1729   malwarepatrol_product_code="8"
1730   malwarepatrol_list="clamav_basic"
1731 else
1732   if [ -z $malwarepatrol_list ] ; then
1733     malwarepatrol_list="clamav_basic"
1734   fi
1735   if [ -z $malwarepatrol_product_code ] ; then
1736     # Not sure, it may be better to return an error.
1737     malwarepatrol_product_code=8
1738   fi
1739 fi
1740 if [ $malwarepatrol_list == "clamav_basic" ] ; then
1741   malwarepatrol_db="malwarepatrol.db"
1742 else
1743   malwarepatrol_db="malwarepatrol.ndb"
1744 fi
1745 malwarepatrol_url="$malwarepatrol_url?product=$malwarepatrol_product_code&list=$malwarepatrol_list"
1746
1747 # If "ham_dir" variable is set, then create initial whitelist files (skipped if first-time script run).
1748 test_dir="$work_dir/test"
1749 if [ -n "$ham_dir" ] && [ -d "$work_dir" ] && [ ! -d "$test_dir" ] ; then
1750   if [ -d "$ham_dir" ] ; then
1751     xshok_mkdir_ownership "$test_dir"
1752     cp -f "$work_dir"/*/*.ndb "$test_dir"
1753     $clamscan_bin --infected --no-summary -d "$test_dir" "$ham_dir"/* | command sed 's/\.UNOFFICIAL FOUND//' | awk '{print $NF}' >> "$work_dir_work_configs/whitelist.txt"
1754     $grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir"/* | cut -d "*" -f2 | sort | uniq > "$work_dir_work_configs/whitelist.hex"
1755     cd "$test_dir" || exit
1756     for db_file in * ; do
1757       [[ -e $db_file ]] || break # handle the case of no files
1758       $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$db_file" > "$db_file-tmp"
1759       mv -f "$db_file-tmp" "$db_file"
1760       if $clamscan_bin --quiet -d "$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
1761         if $rsync_bin -pcqt "$db_file" "$clam_dbs" ; then
1762           perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
1763           if [ "$selinux_fixes" == "yes" ] ; then
1764             restorecon "$clam_dbs/$db_file"
1765           fi
1766           do_clamd_reload=1
1767         fi
1768       fi
1769     done
1770     if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
1771       xshok_pretty_echo_and_log "Initial HAM directory scan whitelist file created in $work_dir_work_configs"
1772     else
1773       xshok_pretty_echo_and_log "No false-positives detected in initial HAM directory scan"
1774     fi
1775   else
1776     xshok_pretty_echo_and_log "WARNING: Cannot locate HAM directory: $ham_dir"
1777     xshok_pretty_echo_and_log "Skipping initial whitelist file creation.  Fix 'ham_dir' path in config file"
1778   fi
1779 fi
1780
1781 # Check to see if the working directories have been created. If not, create them.  Otherwise, ignore and proceed with script.
1782 xshok_mkdir_ownership "$work_dir"
1783 xshok_mkdir_ownership "$work_dir_securiteinfo"
1784 xshok_mkdir_ownership "$work_dir_malwarepatrol"
1785 xshok_mkdir_ownership "$work_dir_linuxmalwaredetect"
1786 xshok_mkdir_ownership "$work_dir_sanesecurity"
1787 xshok_mkdir_ownership "$work_dir_yararulesproject"
1788 xshok_mkdir_ownership "$work_dir_work_configs"
1789 xshok_mkdir_ownership "$work_dir_gpg"
1790 xshok_mkdir_ownership "$work_dir_add"
1791
1792 # Set secured access permissions to the GPG directory
1793 perms chmod -f 0700 "$work_dir_gpg"
1794
1795 # If we haven't done so yet, download Sanesecurity public GPG key and import to custom keyring.
1796 if [ ! -s "$work_dir_gpg/publickey.gpg" ] ; then
1797   if [ "$wget_bin" != "" ] ; then
1798     #echo $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="$work_dir_gpg/publickey.gpg" "$sanesecurity_gpg_url"
1799     $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="$work_dir_gpg/publickey.gpg" "$sanesecurity_gpg_url"
1800     ret="$?"
1801   else
1802     #echo $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 "$work_dir_gpg/publickey.gpg" "$sanesecurity_gpg_url"
1803     $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 "$work_dir_gpg/publickey.gpg" "$sanesecurity_gpg_url"
1804     ret="$?"
1805   fi    
1806   if [ "$ret" != "0" ] ; then
1807     xshok_pretty_echo_and_log "ALERT: Could not download Sanesecurity public GPG key" "*"
1808     exit 1
1809   else
1810     xshok_pretty_echo_and_log "Sanesecurity public GPG key successfully downloaded"
1811     rm -f -- "$work_dir_gpg/ss-keyring.gp*"
1812     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
1813       xshok_pretty_echo_and_log "ALERT: could not import Sanesecurity public GPG key to custom keyring" "*"
1814       exit 1
1815     else
1816       chmod -f 0644 "$work_dir_gpg/*.*"
1817       xshok_pretty_echo_and_log "Sanesecurity public GPG key successfully imported to custom keyring"
1818     fi
1819   fi
1820 fi
1821
1822 # If custom keyring is missing, try to re-import Sanesecurity public GPG key.
1823 if [ ! -s "$work_dir_gpg/ss-keyring.gpg" ] ; then
1824   rm -f -- "$work_dir_gpg/ss-keyring.gp*"
1825   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
1826     xshok_pretty_echo_and_log "ALERT: Custom keyring MISSING or CORRUPT!  Could not import Sanesecurity public GPG key to custom keyring" "*"
1827     exit 1
1828   else
1829     chmod -f 0644 "$work_dir_gpg/*.*"
1830     xshok_pretty_echo_and_log "Sanesecurity custom keyring MISSING!  GPG key successfully re-imported to custom keyring"
1831   fi
1832 fi
1833
1834 # Database update check, time randomization section.  This script now
1835 # provides support for both bash and non-bash enabled system shells.
1836 if [ "$enable_random" = "yes" ] ; then
1837   if [ -n "$RANDOM" ] ; then
1838     sleep_time=$((RANDOM * $((max_sleep_time - min_sleep_time)) / 32767 + min_sleep_time))
1839   else
1840     sleep_time=0
1841     while [ "$sleep_time" -lt "$min_sleep_time" ] || [ "$sleep_time" -gt "$max_sleep_time" ] ; do
1842       sleep_time=$(head -1 /dev/urandom | cksum | awk '{print $2}')
1843     done
1844   fi
1845   if [ ! -t 0 ] ; then
1846     xshok_pretty_echo_and_log "$(date) - Pausing database file updates for $sleep_time seconds..."
1847     sleep "$sleep_time"
1848     xshok_pretty_echo_and_log "$(date) - Pause complete, checking for new database files..."
1849   fi
1850 fi
1851
1852 # Create "scan-test.txt" file for clamscan database integrity testing.
1853 if [ ! -s "$work_dir_work_configs/scan-test.txt" ] ; then
1854   echo "This is the clamscan test file..." > "$work_dir_work_configs/scan-test.txt"
1855 fi
1856
1857 # If rsync proxy is defined in the config file, then export it for use.
1858 if [ -n "$rsync_proxy" ] ; then
1859   RSYNC_PROXY="$rsync_proxy"
1860   export RSYNC_PROXY
1861 fi
1862
1863 # Create $current_dbsfiles containing lists of current and previously active 3rd-party databases
1864 # so that databases and/or backup files that are no longer being used can be removed.
1865 current_tmp="$work_dir_work_configs/current-dbs.tmp"
1866 current_dbs="$work_dir_work_configs/current-dbs.txt"
1867
1868 if [ "$sanesecurity_enabled" == "yes" ] ; then
1869   # Create the Sanesecurity rsync "include" file (defines which files to download).
1870   sanesecurity_include_dbs="$work_dir_work_configs/ss-include-dbs.txt"
1871   if [ -n "$sanesecurity_dbs" ] ; then
1872     rm -f -- "$sanesecurity_include_dbs" "$work_dir_sanesecurity/*.sha256"
1873     for db in $sanesecurity_dbs ; do
1874       echo "$db" >> "$sanesecurity_include_dbs"
1875       echo "$db.sig" >> "$sanesecurity_include_dbs"
1876       
1877       echo "$work_dir_sanesecurity/$db" >> "$current_tmp"
1878       echo "$work_dir_sanesecurity/$db.sig" >> "$current_tmp"
1879       clamav_files
1880     done
1881   fi
1882 fi
1883 if [ "$securiteinfo_enabled" == "yes" ] ; then
1884   if [ -n "$securiteinfo_dbs" ] ; then
1885     for db in $securiteinfo_dbs ; do
1886       echo "$work_dir_securiteinfo/$db" >> "$current_tmp"
1887       clamav_files
1888     done
1889   fi
1890 fi
1891 if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
1892   if [ -n "$linuxmalwaredetect_dbs" ] ; then
1893     for db in $linuxmalwaredetect_dbs ; do
1894       echo "$work_dir_linuxmalwaredetect/$db" >> "$current_tmp"
1895       clamav_files
1896     done
1897   fi
1898 fi
1899 if [ "$malwarepatrol_enabled" == "yes" ] ; then
1900   if [ -n "$malwarepatrol_db" ] ; then
1901     echo "$work_dir_malwarepatrol/$malwarepatrol_db" >> "$current_tmp"
1902     clamav_files
1903   fi
1904 fi
1905 if [ "$yararulesproject_enabled" == "yes" ] ; then
1906   if [ -n "$yararulesproject_dbs" ] ; then
1907     for db in $yararulesproject_dbs ; do
1908       if echo "$db" | $grep_bin -q "/"; then
1909         db=$(echo "$db" | cut -d"/" -f2)
1910       fi
1911       echo "$work_dir_yararulesproject/$db" >> "$current_tmp"
1912       clamav_files
1913     done
1914   fi
1915 fi
1916 if [ "$additional_enabled" == "yes" ] ; then
1917   if [ -n "$additional_dbs" ] ; then
1918     for db in $additional_dbs ; do
1919       echo "$work_dir_add/$db" >> "$current_tmp"
1920       clamav_files
1921     done
1922   fi
1923 fi
1924 sort "$current_tmp" > "$current_dbs" 2>/dev/null
1925 rm -f "$current_tmp"
1926
1927 # Remove 3rd-party databases and/or backup files that are no longer being used.
1928 if [ "$remove_disabled_databases" == "yes" ] ; then
1929   previous_dbs="$work_dir_work_configs/previous-dbs.txt"
1930   sort "$current_dbs" > "$previous_dbs" 2>/dev/null
1931   #do not remove the current_dbs
1932   #rm -f "$current_dbs"
1933
1934   db_changes="$work_dir_work_configs/db-changes.txt"
1935   if [ ! -s "$previous_dbs" ] ; then
1936     cp -f "$current_dbs" "$previous_dbs" 2>/dev/null
1937   fi
1938   diff "$current_dbs" "$previous_dbs" 2>/dev/null | $grep_bin '>' | awk '{print $2}' > "$db_changes"
1939   if [ -r "$db_changes" ] ; then
1940     if $grep_bin -vq "bak" "$db_changes" 2>/dev/null ; then
1941       do_clamd_reload=2
1942     fi
1943     while read -r file ; do
1944       rm -f -- "$file"
1945       xshok_pretty_echo_and_log "Unused/Disabled file removed: $file"
1946     done < "$db_changes"
1947   fi
1948 fi
1949
1950 # Create "purge.txt" file for package maintainers to support package uninstall.
1951 purge="$work_dir_work_configs/purge.txt"
1952 cp -f "$current_dbs" "$purge"
1953
1954 echo "$work_dir_work_configs/current-dbs.txt"
1955 echo "$work_dir_work_configs/db-changes.txt"
1956 echo "$work_dir_work_configs/last-mbl-update.txt"
1957 echo "$work_dir_work_configs/last-si-update.txt"
1958 echo "$work_dir_work_configs/local.ign"
1959 echo "$work_dir_work_configs/monitor-ign.txt"
1960 echo "$work_dir_work_configs/my-whitelist.ign2"
1961 echo "$work_dir_work_configs/tracker.txt"
1962 echo "$work_dir_work_configs/previous-dbs.txt"
1963 echo "$work_dir_work_configs/scan-test.txt"
1964 echo "$work_dir_work_configs/ss-include-dbs.txt"
1965 echo "$work_dir_work_configs/whitelist.hex"
1966 echo "$work_dir_gpg/publickey.gpg"
1967 echo "$work_dir_gpg/secring.gpg"
1968 echo "$work_dir_gpg/ss-keyring.gpg*"
1969 echo "$work_dir_gpg/trustdb.gpg"
1970 echo "$log_file_path/$log_file_name*"
1971 echo "$work_dir_work_configs/purge.txt" 
1972 } >> "$purge"
1973
1974 # Check and save current system time since epoch for time related database downloads.
1975 # However, if unsuccessful, issue a warning that we cannot calculate times since epoch.
1976 if [ -n "$securiteinfo_dbs" ] || [ -n "$malwarepatrol_db" ] ; then
1977   current_time=$(date "+%s" 2> /dev/null)
1978   current_time="${current_time//[^0-9]/}"
1979   current_time="$((current_time + 0))"
1980   if [ "$current_time" -le 0 ] ; then
1981     current_time=$(perl -le print+time 2> /dev/null)
1982   fi
1983   if [ "$current_time" -le 0 ] ; then
1984     xshok_pretty_echo_and_log "WARNING: No support for 'date +%s' or 'perl' was not found , SecuriteInfo and MalwarePatrol updates bypassed" "="
1985     securiteinfo_dbs=""
1986     malwarepatrol_db=""
1987   fi
1988 fi
1989
1990 ################################################################
1991 # Check for Sanesecurity database & GPG signature file updates #
1992 ################################################################
1993 if [ "$sanesecurity_enabled" == "yes" ] ; then
1994   if [ -n "$sanesecurity_dbs" ] ; then
1995   ##if [ ${#sanesecurity_dbs[@]} -lt "1" ] ; then ##will not work due to compound array assignment
1996     if [ "$(xshok_array_count "$sanesecurity_dbs")" -lt "1" ] ; then
1997       xshok_pretty_echo_and_log "Failed sanesecurity_dbs config is invalid or not defined - SKIPPING"
1998     else
1999       if [ -r "$work_dir_work_configs/last-ss-update.txt" ] ; then
2000         last_sanesecurity_update=$(cat "$work_dir_work_configs/last-ss-update.txt")
2001       else
2002         last_sanesecurity_update="0"
2003       fi
2004       db_file=""
2005       update_interval=$((sanesecurity_update_hours * 3600))
2006       time_interval=$((current_time - last_sanesecurity_update))
2007       if [ "$time_interval" -ge $((update_interval - 600)) ] ; then
2008         echo "$current_time" > "$work_dir_work_configs/last-ss-update.txt"
2009         xshok_pretty_echo_and_log "Sanesecurity Database & GPG Signature File Updates" "="
2010         xshok_pretty_echo_and_log "Checking for Sanesecurity updates..."
2011
2012         sanesecurity_mirror_ips=$(dig +ignore +short "$sanesecurity_url")
2013         #add fallback to host if dig returns no records
2014         if [ "$(xshok_array_count  "$sanesecurity_mirror_ips")" -lt 1 ] ; then
2015           sanesecurity_mirror_ips=$(host -t A "$sanesecurity_url" | sed -n '/has address/{s/.*address \([^ ]*\).*/\1/;p;}')
2016         fi
2017
2018         if [ "$(xshok_array_count  "$sanesecurity_mirror_ips")" -ge "1" ] ; then
2019           for sanesecurity_mirror_ip in $sanesecurity_mirror_ips ; do
2020             sanesecurity_mirror_name=""
2021             sanesecurity_mirror_name=$(dig +short -x "$sanesecurity_mirror_ip" | command sed 's/\.$//')
2022             #add fallback to host if dig returns no records
2023             if [ "$sanesecurity_mirror_name" == "" ] ; then
2024               sanesecurity_mirror_name=$(host "$sanesecurity_mirror_ip" | sed -n '/name pointer/{s/.*pointer \([^ ]*\).*\.$/\1/;p;}')
2025             fi
2026             sanesecurity_mirror_site_info="$sanesecurity_mirror_name $sanesecurity_mirror_ip"
2027             xshok_pretty_echo_and_log "Sanesecurity mirror site used: $sanesecurity_mirror_site_info"
2028             $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
2029             if [ "$?" -eq "0" ] ; then #the correct way
2030               sanesecurity_rsync_success="1"
2031               for db_file in $sanesecurity_dbs ; do
2032                 if ! cmp -s "$work_dir_sanesecurity/$db_file" "$clam_dbs/$db_file" ; then
2033                   xshok_pretty_echo_and_log "Testing updated Sanesecurity database file: $db_file"
2034                   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
2035                     $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
2036                     ret="$?"
2037                   else
2038                     ret="0"  
2039                   fi
2040                   if [ "$ret" -eq "0" ] ; then
2041                     test "$gpg_silence" = "no" && xshok_pretty_echo_and_log "Sanesecurity GPG Signature tested good on $db_file database"
2042                     true
2043                   else
2044                     xshok_pretty_echo_and_log "Sanesecurity GPG Signature test FAILED on $db_file database - SKIPPING" 
2045                     false
2046                   fi
2047                 if [ "$?" -eq "0" ] ; then
2048                   db_ext=$(echo "$db_file" | cut -d "." -f2)
2049                   if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
2050                     if $clamscan_bin --quiet -d "$work_dir_sanesecurity/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2051                       xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested good"
2052                       true
2053                     else
2054                       xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested BAD"
2055                       if [ "$remove_bad_database" == "yes" ] ; then
2056                         if rm -f "$work_dir_sanesecurity/$db_file" ; then
2057                           xshok_pretty_echo_and_log "Removed invalid database: $work_dir_sanesecurity/$db_file"
2058                         fi
2059                       fi
2060                       false
2061                     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
2062                       perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2063                       if [ "$selinux_fixes" == "yes" ] ; then
2064                         restorecon "$clam_dbs/$db_file"
2065                       fi
2066                       xshok_pretty_echo_and_log "Successfully updated Sanesecurity production database file: $db_file"
2067                       sanesecurity_update=1
2068                       do_clamd_reload=1
2069                     else
2070                       xshok_pretty_echo_and_log "Failed to successfully update Sanesecurity production database file: $db_file - SKIPPING"
2071                       false
2072                     fi
2073                   else
2074                     $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_sanesecurity/$db_file" > "$test_dir/$db_file"
2075                     $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"
2076                     $grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
2077                     $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2078                     mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2079                     if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2080                       xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested good"
2081                       true
2082                     else
2083                       xshok_pretty_echo_and_log "Clamscan reports Sanesecurity $db_file database integrity tested BAD"
2084                       ##DO NOT KILL THIS DB
2085                       false
2086                     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
2087                       perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2088                       if [ "$selinux_fixes" == "yes" ] ; then
2089                         restorecon "$clam_dbs/$db_file"
2090                       fi
2091                       xshok_pretty_echo_and_log "Successfully updated Sanesecurity production database file: $db_file"
2092                       sanesecurity_update=1
2093                       do_clamd_reload=1
2094                     else
2095                       xshok_pretty_echo_and_log "Failed to successfully update Sanesecurity production database file: $db_file - SKIPPING"
2096                     fi
2097                   fi
2098                 fi
2099               fi
2100               done
2101               if [ "$sanesecurity_update" != "1" ] ; then
2102                 xshok_pretty_echo_and_log "No Sanesecurity database file updates found" "-"
2103                 break
2104               else
2105                 break
2106               fi
2107             else
2108               xshok_pretty_echo_and_log "Connection to $sanesecurity_mirror_site_info failed - Trying next mirror site..."
2109             fi
2110           done
2111           if [ "$sanesecurity_rsync_success" != "1" ] ; then
2112             xshok_pretty_echo_and_log "Access to all Sanesecurity mirror sites failed - Check for connectivity issues"
2113             xshok_pretty_echo_and_log "or signature database name(s) misspelled in the script's configuration file."
2114           fi
2115         else
2116           xshok_pretty_echo_and_log "No Sanesecurity mirror sites found - Check for dns/connectivity issues"
2117         fi
2118       else
2119         xshok_pretty_echo_and_log "Sanesecurity Database File Updates" "="
2120
2121         time_remaining=$((update_interval - time_interval))
2122         hours_left=$((time_remaining / 3600))
2123         minutes_left=$((time_remaining % 3600 / 60))
2124         xshok_pretty_echo_and_log "$sanesecurity_update_hours hours have not yet elapsed since the last sanesecurity update check"
2125         xshok_pretty_echo_and_log "No update check was performed at this time" "-"
2126         xshok_pretty_echo_and_log "Next check will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
2127       fi
2128     fi
2129   fi
2130 else
2131   if [ -n "$sanesecurity_dbs" ] ; then
2132     if [ "$remove_disabled_databases" == "yes" ] ; then
2133       xshok_pretty_echo_and_log "Removing disabled Sanesecurity Database files"
2134       for db_file in $sanesecurity_dbs ; do
2135         if [ -r "$work_dir_sanesecurity/$db_file" ] ; then
2136           rm -f "$work_dir_sanesecurity/$db_file"*
2137           do_clamd_reload=1
2138         fi
2139         if [ -r "$clam_dbs/$db_file" ] ; then
2140           rm -f "$clam_dbs/$db_file"
2141           do_clamd_reload=1
2142         fi
2143       done
2144     fi
2145   fi
2146 fi
2147
2148 ##############################################################################################################################################
2149 # Check for updated SecuriteInfo database files every set number of  hours as defined in the "USER CONFIGURATION" section of this script #
2150 ##############################################################################################################################################
2151 if [ "$securiteinfo_enabled" == "yes" ] ; then
2152   if [ "$securiteinfo_authorisation_signature" != "YOUR-SIGNATURE-NUMBER" ] ; then
2153     if [ -n "$securiteinfo_dbs" ] ; then
2154       if [ "$(xshok_array_count "$securiteinfo_dbs")" -lt "1" ] ; then
2155         xshok_pretty_echo_and_log "Failed securiteinfo_dbs config is invalid or not defined - SKIPPING"
2156       else
2157       rm -f "$work_dir_securiteinfo/*.gz"
2158       if [ -r "$work_dir_work_configs/last-si-update.txt" ] ; then
2159         last_securiteinfo_update=$(cat "$work_dir_work_configs/last-si-update.txt")
2160       else
2161         last_securiteinfo_update="0"
2162       fi
2163       db_file=""
2164       loop=""
2165       update_interval=$((securiteinfo_update_hours * 3600))
2166       time_interval=$((current_time - last_securiteinfo_update))
2167       if [ "$time_interval" -ge $((update_interval - 600)) ] ; then
2168         echo "$current_time" > "$work_dir_work_configs/last-si-update.txt"
2169         xshok_pretty_echo_and_log "SecuriteInfo Database File Updates" "="
2170         xshok_pretty_echo_and_log "Checking for SecuriteInfo updates..."
2171         securiteinfo_updates="0" 
2172         for db_file in $securiteinfo_dbs ; do
2173           if [ "$loop" = "1" ] ; then
2174             xshok_pretty_echo_and_log "---"      
2175           fi
2176           xshok_pretty_echo_and_log "Checking for updated SecuriteInfo database file: $db_file"
2177           securiteinfo_db_update="0"
2178           if [ "$wget_bin" != "" ] ; then
2179             $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="$work_dir_securiteinfo/$db_file" "$securiteinfo_url/$securiteinfo_authorisation_signature/$db_file"
2180             ret="$?"
2181           else
2182             $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 "$work_dir_securiteinfo/$db_file" "$securiteinfo_url/$securiteinfo_authorisation_signature/$db_file"
2183             ret="$?"
2184           fi
2185           if [ "$ret" -eq "0" ] ; then
2186             loop="1"
2187             if ! cmp -s "$work_dir_securiteinfo/$db_file" "$clam_dbs/$db_file" ; then
2188               if [ "$?" -eq "0" ] ; then
2189                 db_ext=$(echo "$db_file" | cut -d "." -f2)
2190
2191
2192                 xshok_pretty_echo_and_log "Testing updated SecuriteInfo database file: $db_file"
2193                 if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ]
2194                   then
2195                   if $clamscan_bin --quiet -d "$work_dir_securiteinfo/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2196                     then
2197                     xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested good"
2198                     true
2199                   else
2200                     xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested BAD"
2201                     if [ "$remove_bad_database" == "yes" ] ; then
2202                       if rm -f "$work_dir_securiteinfo/$db_file" ; then
2203                         xshok_pretty_echo_and_log "Removed invalid database: $work_dir_securiteinfo/$db_file"
2204                       fi
2205                     fi
2206                     false
2207                   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
2208                   perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2209                   if [ "$selinux_fixes" == "yes" ] ; then
2210                     restorecon "$clam_dbs/$db_file"
2211                   fi
2212                   xshok_pretty_echo_and_log "Successfully updated SecuriteInfo production database file: $db_file"
2213                   securiteinfo_updates=1
2214                   securiteinfo_db_update=1
2215                   do_clamd_reload=1
2216                 else
2217                   xshok_pretty_echo_and_log "Failed to successfully update SecuriteInfo production database file: $db_file - SKIPPING"
2218                 fi
2219               else
2220                 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_securiteinfo/$db_file" > "$test_dir/$db_file"
2221                 $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"
2222                 $grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
2223                 $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2224                 mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2225                 if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2226                   then
2227                   xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested good"
2228                   true
2229                 else
2230                   xshok_pretty_echo_and_log "Clamscan reports SecuriteInfo $db_file database integrity tested BAD"
2231                   rm -f "$work_dir_securiteinfo/$db_file"
2232                   if [ "$remove_bad_database" == "yes" ] ; then
2233                     if rm -f "$work_dir_securiteinfo/$db_file" ; then
2234                       xshok_pretty_echo_and_log "Removed invalid database: $work_dir_securiteinfo/$db_file"
2235                     fi
2236                   fi
2237                   false
2238                 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
2239                 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2240                 if [ "$selinux_fixes" == "yes" ] ; then
2241                   restorecon "$clam_dbs/$db_file"
2242                 fi
2243                 xshok_pretty_echo_and_log "Successfully updated SecuriteInfo production database file: $db_file"
2244                 securiteinfo_updates=1
2245                 securiteinfo_db_update=1
2246                 do_clamd_reload=1
2247               else
2248                 xshok_pretty_echo_and_log "Failed to successfully update SecuriteInfo production database file: $db_file - SKIPPING"
2249               fi
2250             fi
2251           fi
2252         fi
2253       else
2254         xshok_pretty_echo_and_log "Failed connection to $securiteinfo_url - SKIPPED SecuriteInfo $db_file update"
2255       fi
2256       if [ "$securiteinfo_db_update" != "1" ] ; then          
2257         xshok_pretty_echo_and_log "No updated SecuriteInfo $db_file database file found" "-"
2258       fi
2259     done
2260     if [ "$securiteinfo_updates" != "1" ] ; then
2261       xshok_pretty_echo_and_log "No SecuriteInfo database file updates found" "-"
2262     fi
2263   else
2264     xshok_pretty_echo_and_log "SecuriteInfo Database File Updates" "="
2265
2266     time_remaining=$((update_interval - time_interval))
2267     hours_left=$((time_remaining / 3600))
2268     minutes_left=$((time_remaining % 3600 / 60))
2269     xshok_pretty_echo_and_log "$securiteinfo_update_hours hours have not yet elapsed since the last SecuriteInfo update check"
2270     xshok_pretty_echo_and_log "No update check was performed at this time" "-"
2271     xshok_pretty_echo_and_log "Next check will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
2272   fi
2273   fi
2274   fi
2275   fi
2276 else
2277   if [ -n "$securiteinfo_dbs" ] ; then
2278     if [ "$remove_disabled_databases" == "yes" ] ; then
2279       xshok_pretty_echo_and_log "Removing disabled SecuriteInfo Database files"
2280       for db_file in $securiteinfo_dbs ; do
2281         if [ -r "$work_dir_securiteinfo/$db_file" ] ; then
2282           rm -f "$work_dir_securiteinfo/$db_file"
2283           do_clamd_reload=1
2284         fi
2285         if [ -r "$clam_dbs/$db_file" ] ; then
2286           rm -f "$clam_dbs/$db_file"
2287           do_clamd_reload=1
2288         fi
2289       done
2290     fi
2291   fi
2292 fi
2293
2294
2295 ##############################################################################################################################################
2296 # Check for updated linuxmalwaredetect database files every set number of hours as defined in the "USER CONFIGURATION" section of this script 
2297 ##############################################################################################################################################
2298 if [ "$linuxmalwaredetect_enabled" == "yes" ] ; then
2299   if [ -n "$linuxmalwaredetect_dbs" ] ; then
2300     if [ "$(xshok_array_count "$linuxmalwaredetect_dbs")" -lt "1" ] ; then
2301       xshok_pretty_echo_and_log "Failed linuxmalwaredetect_dbs config is invalid or not defined - SKIPPING"
2302     else
2303     rm -f "$work_dir_linuxmalwaredetect/*.gz"
2304     if [ -r "$work_dir_work_configs/last-linuxmalwaredetect-update.txt" ] ; then
2305       last_linuxmalwaredetect_update=$(cat "$work_dir_work_configs/last-linuxmalwaredetect-update.txt")
2306     else
2307       last_linuxmalwaredetect_update="0"
2308     fi
2309     db_file=""
2310     loop=""
2311     update_interval=$((linuxmalwaredetect_update_hours * 3600))
2312     time_interval=$((current_time - last_linuxmalwaredetect_update))
2313     if [ "$time_interval" -ge $((update_interval - 600)) ] ; then
2314       echo "$current_time" > "$work_dir_work_configs/last-linuxmalwaredetect-update.txt"
2315
2316       xshok_pretty_echo_and_log "linuxmalwaredetect Database File Updates" "="
2317       xshok_pretty_echo_and_log "Checking for linuxmalwaredetect updates..."
2318       linuxmalwaredetect_updates="0"
2319       for db_file in $linuxmalwaredetect_dbs ; do
2320         if [ "$loop" = "1" ] ; then
2321           xshok_pretty_echo_and_log "---"      
2322         fi
2323         xshok_pretty_echo_and_log "Checking for updated linuxmalwaredetect database file: $db_file"
2324
2325         linuxmalwaredetect_db_update="0"
2326         if [ "$wget_bin" != "" ] ; then
2327           $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="$work_dir_linuxmalwaredetect/$db_file" "$linuxmalwaredetect_url/$db_file"
2328           ret="$?"
2329         else
2330           $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 "$work_dir_linuxmalwaredetect/$db_file" "$linuxmalwaredetect_url/$db_file"
2331           ret="$?"
2332         fi
2333         if [ "$ret" -eq "0" ] ; then
2334           loop="1"
2335           if ! cmp -s "$work_dir_linuxmalwaredetect/$db_file" "$clam_dbs/$db_file" ; then
2336             if [ "$?" -eq "0" ] ; then
2337               db_ext=$(echo "$db_file" | cut -d "." -f2)
2338
2339               xshok_pretty_echo_and_log "Testing updated linuxmalwaredetect database file: $db_file"
2340               if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
2341                 if $clamscan_bin --quiet -d "$work_dir_linuxmalwaredetect/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2342                   then
2343                   xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested good"
2344                   true
2345                 else
2346                   xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested BAD"
2347                   if [ "$remove_bad_database" == "yes" ] ; then
2348                     if rm -f "$work_dir_linuxmalwaredetect/$db_file" ; then
2349                       xshok_pretty_echo_and_log "Removed invalid database: $work_dir_linuxmalwaredetect/$db_file"
2350                     fi
2351                   fi
2352                   false
2353                 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
2354                 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2355                 if [ "$selinux_fixes" == "yes" ] ; then
2356                   restorecon "$clam_dbs/local.ign"
2357                 fi
2358                 xshok_pretty_echo_and_log "Successfully updated linuxmalwaredetect production database file: $db_file"
2359                 linuxmalwaredetect_updates=1
2360                 linuxmalwaredetect_db_update=1
2361                 do_clamd_reload=1
2362               else
2363                 xshok_pretty_echo_and_log "Failed to successfully update linuxmalwaredetect production database file: $db_file - SKIPPING"
2364               fi
2365             else
2366               $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_linuxmalwaredetect/$db_file" > "$test_dir/$db_file"
2367               $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"
2368               $grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
2369               $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2370               mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2371               if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2372                 xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested good"
2373                 true
2374               else
2375                 xshok_pretty_echo_and_log "Clamscan reports linuxmalwaredetect $db_file database integrity tested BAD"
2376                 if [ "$remove_bad_database" == "yes" ] ; then
2377                   if rm -f "$work_dir_linuxmalwaredetect/$db_file" ; then
2378                     xshok_pretty_echo_and_log "Removed invalid database: $work_dir_linuxmalwaredetect/$db_file"
2379                   fi
2380                 fi
2381                 false
2382               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
2383               perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2384               if [ "$selinux_fixes" == "yes" ] ; then
2385                 restorecon "$clam_dbs/$db_file"
2386               fi
2387               xshok_pretty_echo_and_log "Successfully updated linuxmalwaredetect production database file: $db_file"
2388               linuxmalwaredetect_updates=1
2389               linuxmalwaredetect_db_update=1
2390               do_clamd_reload=1
2391             else
2392               xshok_pretty_echo_and_log "Failed to successfully update linuxmalwaredetect production database file: $db_file - SKIPPING"
2393             fi
2394           fi
2395         fi
2396       fi
2397     else
2398       xshok_pretty_echo_and_log "WARNING: Failed connection to $linuxmalwaredetect_url - SKIPPED linuxmalwaredetect $db_file update"
2399     fi
2400     if [ "$linuxmalwaredetect_db_update" != "1" ] ; then
2401
2402       xshok_pretty_echo_and_log "No updated linuxmalwaredetect $db_file database file found"
2403     fi
2404   done
2405   if [ "$linuxmalwaredetect_updates" != "1" ] ; then
2406     xshok_pretty_echo_and_log "No linuxmalwaredetect database file updates found" "-"
2407   fi
2408 else
2409
2410   xshok_pretty_echo_and_log "linuxmalwaredetect Database File Updates" "="
2411
2412   time_remaining=$((update_interval - time_interval))
2413   hours_left=$((time_remaining / 3600))
2414   minutes_left=$((time_remaining % 3600 / 60))
2415   xshok_pretty_echo_and_log "$linuxmalwaredetect_update_hours hours have not yet elapsed since the last linux malware detect update check"
2416   xshok_pretty_echo_and_log "No update check was performed at this time" "-"
2417   xshok_pretty_echo_and_log "Next check will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
2418 fi
2419 fi
2420 fi
2421 else
2422   if [ -n "$linuxmalwaredetect_dbs" ] ; then
2423     if [ "$remove_disabled_databases" == "yes" ] ; then
2424       xshok_pretty_echo_and_log "Removing disabled linuxmalwaredetect Database files"
2425       for db_file in $linuxmalwaredetect_dbs ; do
2426         if [ -r "$work_dir_linuxmalwaredetect/$db_file" ] ; then
2427           rm -f "$work_dir_linuxmalwaredetect/$db_file"
2428           do_clamd_reload=1
2429         fi
2430         if [ -r "$clam_dbs/$db_file" ] ; then
2431           rm -f "$clam_dbs/$db_file"
2432           do_clamd_reload=1
2433         fi
2434       done
2435     fi
2436   fi
2437 fi
2438
2439
2440 ##########################################################################################################################################
2441 # Download MalwarePatrol database file every set number of hours as defined in the "USER CONFIGURATION" section of this script.    #
2442 ##########################################################################################################################################
2443 if [ "$malwarepatrol_enabled" == "yes" ] ; then
2444   if [ "$malwarepatrol_receipt_code" != "YOUR-RECEIPT-NUMBER" ] ; then
2445     if [ -n "$malwarepatrol_db" ] ; then
2446       if [ -r "$work_dir_work_configs/last-mbl-update.txt" ] ; then
2447         last_malwarepatrol_update=$(cat "$work_dir_work_configs/last-mbl-update.txt")
2448       else
2449         last_malwarepatrol_update="0"
2450       fi
2451       db_file=""
2452       update_interval=$((malwarepatrol_update_hours * 3600))
2453       time_interval=$((current_time - last_malwarepatrol_update))
2454       if [ "$time_interval" -ge $((update_interval - 600)) ] ; then
2455         echo "$current_time" > "$work_dir_work_configs"/last-mbl-update.txt
2456         xshok_pretty_echo_and_log "Checking for MalwarePatrol updates..."
2457         # Delete the old MBL (mbl.db) database file if it exists and start using the newer
2458         # format (mbl.ndb) database file instead.
2459         # test -e $clam_dbs/$malwarepatrol_db -o -e $clam_dbs/$malwarepatrol_db-bak && rm -f -- "$clam_dbs/mbl.d*"
2460
2461         # remove the .db is th new format if ndb and
2462         # symetrically
2463         if [ "$malwarepatrol_db" == "malwarepatrol.db" ] && [ -f "$clam_dbs/malwarepatrol.ndb" ] ; then
2464           rm "$clam_dbs/malwarepatrol.ndb";
2465         fi
2466
2467         if [ "$malwarepatrol_db" == "malwarepatrol.ndb" ] && [ -f "$clam_dbs/malwarepatrol.db" ] ; then
2468           rm "$clam_dbs/malwarepatrol.db";
2469         fi
2470
2471         xshok_pretty_echo_and_log "MalwarePatrol $db_file Database File Update" "="
2472
2473         malwarepatrol_reloaded=0
2474         if [ "$malwarepatrol_free" == "yes" ] ; then
2475           if [ "$wget_bin" != "" ] ; then
2476             $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="$work_dir_malwarepatrol/$malwarepatrol_db" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code"
2477             ret="$?"
2478           else
2479             $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 "$work_dir_malwarepatrol/$malwarepatrol_db" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code"
2480             ret="$?"
2481           fi
2482           if [ "$ret" -eq "0" ] ; then
2483             if ! cmp -s "$work_dir_malwarepatrol/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db" ; then
2484               if [ "$?" -eq "0" ] ; then
2485                 malwarepatrol_reloaded=1
2486               else
2487                 malwarepatrol_reloaded=2
2488               fi
2489             fi
2490           else # wget failed
2491             malwarepatrol_reloaded=-1
2492           fi
2493
2494         else # The not free branch
2495           if [ "$wget_bin" != "" ] ; then
2496             $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="$work_dir_malwarepatrol/$malwarepatrol_db.md5" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code&hash=1"
2497             ret="$?"
2498           else
2499             $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 "$work_dir_malwarepatrol/$malwarepatrol_db.md5" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code&hash=1"
2500             ret="$?"
2501           fi
2502           if [ "$ret" -eq "0" ] ; then
2503             if [ -f "$clam_dbs/$malwarepatrol_db" ] ; then
2504               malwarepatrol_md5=$(openssl md5 -r "$clam_dbs/$malwarepatrol_db" 2>/dev/null | cut -d" " -f1)
2505               if [ ! "$malwarepatrol_md5" ] ; then
2506                 #fallback for missing -r option
2507                 malwarepatrol_md5=$(openssl md5 "$clam_dbs/$malwarepatrol_db" 2>/dev/null | cut -d" " -f2)
2508               fi
2509             fi
2510             malwarepatrol_md5_new=$(cat "$work_dir_malwarepatrol/$malwarepatrol_db.md5")
2511             if [ -n "$malwarepatrol_md5_new" ] && [ "$malwarepatrol_md5" != "$malwarepatrol_md5_new" ] ; then
2512               if [ "$wget_bin" != "" ] ; then
2513                 $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="$work_dir_malwarepatrol/$malwarepatrol_db" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code"
2514                 ret="$?"
2515               else
2516                 $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 "$work_dir_malwarepatrol/$malwarepatrol_db" "$malwarepatrol_url&receipt=$malwarepatrol_receipt_code"
2517                 ret="$?"
2518               fi
2519               if [ "$ret" -eq "0" ] ; then
2520                 malwarepatrol_reloaded=1
2521               else # wget DB fail
2522                 malwarepatrol_reloaded=-1
2523               fi # wget DB
2524             fi # MD5 not equal
2525           else # wget MD5 fail
2526             malwarepatrol_reloaded=-1
2527           fi # wget md5
2528         fi
2529
2530         case "$malwarepatrol_reloaded" in 
2531           1) # database was updated, need test and reload 
2532           xshok_pretty_echo_and_log "Testing updated MalwarePatrol database file: $malwarepatrol_db"
2533           if $clamscan_bin --quiet -d "$work_dir_malwarepatrol/$malwarepatrol_db" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2534             xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested good"
2535             true
2536           else
2537             xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested BAD"
2538             if [ "$remove_bad_database" == "yes" ] ; then
2539               if rm -f "$work_dir_malwarepatrol/$malwarepatrol_db" ; then
2540                 xshok_pretty_echo_and_log "Removed invalid database: $work_dir_malwarepatrol/$malwarepatrol_db"
2541               fi
2542             fi
2543             false
2544           fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$work_dir_malwarepatrol/$malwarepatrol_db" "$clam_dbs" 2>/dev/null ; then
2545           perms chown -f "$clam_user:$clam_group" "$clam_dbs/$malwarepatrol_db"
2546           if [ "$selinux_fixes" == "yes" ] ; then
2547             restorecon "$clam_dbs/$malwarepatrol_db"
2548           fi
2549           xshok_pretty_echo_and_log "Successfully updated MalwarePatrol production database file: $malwarepatrol_db"
2550           do_clamd_reload=1
2551         else
2552           xshok_pretty_echo_and_log "Failed to successfully update MalwarePatrol production database file: $malwarepatrol_db - SKIPPING"
2553         fi
2554         ;; # The strange case when $? != 0 in the original
2555         2)
2556         $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_malwarepatrol/$malwarepatrol_db" > "$test_dir/$malwarepatrol_db"
2557         $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"
2558         $grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$malwarepatrol_db" | cut -d "*" -f2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
2559         $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$malwarepatrol_db" > "$test_dir/$malwarepatrol_db-tmp"
2560         mv -f "$test_dir/$malwarepatrol_db-tmp" "$test_dir/$malwarepatrol_db"
2561         if $clamscan_bin --quiet -d "$test_dir/$malwarepatrol_db" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2562           xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested good"
2563           true
2564         else
2565           xshok_pretty_echo_and_log "Clamscan reports MalwarePatrol $malwarepatrol_db database integrity tested BAD"
2566           if [ "$remove_bad_database" == "yes" ] ; then
2567             if rm -f "$test_dir/$malwarepatrol_db" ; then
2568               xshok_pretty_echo_and_log "Removed invalid database: $test_dir/$malwarepatrol_db"
2569             fi
2570           fi
2571           false
2572         fi && (test "$keep_db_backup" = "yes" && cp -f "$clam_dbs/$malwarepatrol_db" "$clam_dbs/$malwarepatrol_db-bak" 2>/dev/null ; true) && if $rsync_bin -pcqt "$test_dir/$malwarepatrol_db" "$clam_dbs" 2>/dev/null ; then
2573         perms chown -f "$clam_user:$clam_group" "$clam_dbs/$malwarepatrol_db"
2574         if [ "$selinux_fixes" == "yes" ] ; then
2575           restorecon "$clam_dbs/$malwarepatrol_db"
2576         fi
2577         xshok_pretty_echo_and_log "Successfully updated MalwarePatrol production database file: $malwarepatrol_db"
2578         do_clamd_reload=1
2579       else
2580         xshok_pretty_echo_and_log "Failed to successfully update MalwarePatrol production database file: $malwarepatrol_db - SKIPPING"
2581       fi
2582       ;;
2583       0) # The database did not update
2584       xshok_pretty_echo_and_log "MalwarePatrol signature database ($malwarepatrol_db) did not change - skipping"
2585       ;;
2586       -1) # wget failed
2587       xshok_pretty_echo_and_log "WARNING - Failed connection to $malwarepatrol_url - SKIPPED MalwarePatrol $malwarepatrol_db update"
2588       ;;
2589     esac
2590
2591   else
2592
2593     xshok_pretty_echo_and_log "MalwarePatrol Database File Update" "="
2594
2595     time_remaining=$((update_interval - time_interval))
2596     hours_left=$((time_remaining / 3600))
2597     minutes_left=$((time_remaining % 3600 / 60))
2598     xshok_pretty_echo_and_log "$malwarepatrol_update_hours hours have not yet elapsed since the last MalwarePatrol download"
2599     xshok_pretty_echo_and_log "No database download was performed at this time" "-"
2600     xshok_pretty_echo_and_log "Next download will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
2601   fi
2602 fi
2603 fi
2604 else
2605   if [ -n "$malwarepatrol_db" ] ; then
2606     if [ "$remove_disabled_databases" == "yes" ] ; then
2607       xshok_pretty_echo_and_log "Removing disabled MalwarePatrol Database file"
2608       if [ -r "$work_dir_malwarepatrol/$malwarepatrol_db" ] ; then
2609         rm -f "$work_dir_malwarepatrol/$malwarepatrol_db"
2610         do_clamd_reload=1
2611       fi
2612       if [ -r "$clam_dbs/$malwarepatrol_db" ] ; then
2613         rm -f "$clam_dbs/$malwarepatrol_db"
2614         do_clamd_reload=1
2615       fi
2616     fi
2617   fi
2618 fi
2619
2620 ##############################################################################################################################################
2621 # Check for updated yararulesproject database files every set number of hours as defined in the "USER CONFIGURATION" section of this script 
2622 ##############################################################################################################################################
2623 if [ "$yararulesproject_enabled" == "yes" ] ; then
2624   if [ -n "$yararulesproject_dbs" ] ; then
2625     if [ "$(xshok_array_count "$yararulesproject_dbs")" -lt "1" ] ; then
2626       xshok_pretty_echo_and_log "Failed yararulesproject_dbs config is invalid or not defined - SKIPPING"
2627     else
2628     rm -f "$work_dir_yararulesproject/*.gz"
2629     if [ -r "$work_dir_work_configs/last-yararulesproject-update.txt" ] ; then
2630       last_yararulesproject_update=$(cat "$work_dir_work_configs/last-yararulesproject-update.txt")
2631     else
2632       last_yararulesproject_update="0"
2633     fi
2634     db_file=""
2635     loop=""
2636     update_interval=$((yararulesproject_update_hours * 3600))
2637     time_interval=$((current_time - last_yararulesproject_update))
2638     if [ "$time_interval" -ge $((update_interval - 600)) ] ; then
2639       echo "$current_time" > "$work_dir_work_configs/last-yararulesproject-update.txt"
2640
2641       xshok_pretty_echo_and_log "Yara-Rules Database File Updates" "="
2642       xshok_pretty_echo_and_log "Checking for yararulesproject updates..."
2643       yararulesproject_updates="0"
2644       for db_file in $yararulesproject_dbs ; do
2645         if echo "$db_file" | $grep_bin -q "/"; then
2646           yr_dir="/"$(echo "$db_file" | cut -d"/" -f1)
2647           db_file=$(echo "$db_file" | cut -d"/" -f2)
2648         else yr_dir=""
2649         fi
2650         if [ "$loop" = "1" ] ; then
2651           xshok_pretty_echo_and_log "---"      
2652         fi
2653         xshok_pretty_echo_and_log "Checking for updated yararulesproject database file: $db_file"
2654
2655         yararulesproject_db_update="0"
2656           if [ "$wget_bin" != "" ] ; then
2657             $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="$work_dir_yararulesproject/$db_file" "$yararulesproject_url/$yr_dir/$db_file"
2658             ret="$?"
2659           else
2660             $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 "$work_dir_yararulesproject/$db_file" "$yararulesproject_url/$yr_dir/$db_file"
2661             ret="$?"
2662           fi
2663           if [ "$ret" -eq "0" ] ; then
2664           loop="1"
2665           if ! cmp -s "$work_dir_yararulesproject/$db_file" "$clam_dbs/$db_file" ; then
2666             if [ "$?" -eq "0" ] ; then
2667               db_ext=$(echo "$db_file" | cut -d "." -f2)
2668
2669               xshok_pretty_echo_and_log "Testing updated yararulesproject database file: $db_file"
2670               if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
2671                 if $clamscan_bin --quiet -d "$work_dir_yararulesproject/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2672                   then
2673                   xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested good"
2674                   true
2675                 else
2676                   xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested BAD"
2677                   if [ "$remove_bad_database" == "yes" ] ; then
2678                     if rm -f "$work_dir_yararulesproject/$db_file" ; then
2679                       xshok_pretty_echo_and_log "Removed invalid database: $work_dir_yararulesproject/$db_file"
2680                     fi
2681                   fi
2682                   false
2683                 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
2684                 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2685                 if [ "$selinux_fixes" == "yes" ] ; then
2686                   restorecon "$clam_dbs/$db_file"
2687                 fi
2688                 xshok_pretty_echo_and_log "Successfully updated yararulesproject production database file: $db_file"
2689                 yararulesproject_updates=1
2690                 yararulesproject_db_update=1
2691                 do_clamd_reload=1
2692               else
2693                 xshok_pretty_echo_and_log "Failed to successfully update yararulesproject production database file: $db_file - SKIPPING"
2694               fi
2695             else
2696               $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_yararulesproject/$db_file" > "$test_dir/$db_file"
2697               $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"
2698               $grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
2699               $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2700               mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2701               if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2702                 xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested good"
2703                 true
2704               else
2705                 xshok_pretty_echo_and_log "Clamscan reports yararulesproject $db_file database integrity tested BAD"
2706                 if [ "$remove_bad_database" == "yes" ] ; then
2707                   if rm -f "$work_dir_yararulesproject/$db_file" ; then
2708                     xshok_pretty_echo_and_log "Removed invalid database: $work_dir_yararulesproject/$db_file"
2709                   fi
2710                 fi
2711                 false
2712               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
2713               perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2714               if [ "$selinux_fixes" == "yes" ] ; then
2715                 restorecon "$clam_dbs/$db_file"
2716               fi
2717               xshok_pretty_echo_and_log "Successfully updated yararulesproject production database file: $db_file"
2718               yararulesproject_updates=1
2719               yararulesproject_db_update=1
2720               do_clamd_reload=1
2721             else
2722               xshok_pretty_echo_and_log "Failed to successfully update yararulesproject production database file: $db_file - SKIPPING"
2723             fi
2724           fi
2725         fi
2726       fi
2727     else
2728       xshok_pretty_echo_and_log "WARNING: Failed connection to $yararulesproject_url - SKIPPED yararulesproject $db_file update"
2729     fi
2730     if [ "$yararulesproject_db_update" != "1" ] ; then
2731       xshok_pretty_echo_and_log "No updated yararulesproject $db_file database file found"
2732     fi
2733   done
2734   if [ "$yararulesproject_updates" != "1" ] ; then
2735     xshok_pretty_echo_and_log "No yararulesproject database file updates found" "-"
2736   fi
2737 else
2738
2739   xshok_pretty_echo_and_log "Yara-Rules Database File Updates" "="
2740
2741   time_remaining=$((update_interval - time_interval))
2742   hours_left=$((time_remaining / 3600))
2743   minutes_left=$((time_remaining % 3600 / 60))
2744   xshok_pretty_echo_and_log "$yararulesproject_update_hours hours have not yet elapsed since the last yararulesproject database update check"
2745   xshok_pretty_echo_and_log "No update check was performed at this time" "-"
2746   xshok_pretty_echo_and_log "Next check will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
2747 fi
2748 fi
2749 fi
2750 else
2751   if [ -n "$yararulesproject_dbs" ] ; then
2752     if [ "$remove_disabled_databases" == "yes" ] ; then
2753       xshok_pretty_echo_and_log "Removing disabled yararulesproject Database files"
2754       for db_file in $yararulesproject_dbs ; do
2755         if echo "$db_file" | $grep_bin -q "/"; then
2756           db_file=$(echo "$db_file" | cut -d"/" -f2)
2757         fi
2758         if [ -r "$work_dir_yararulesproject/$db_file" ] ; then
2759           rm -f "$work_dir_yararulesproject/$db_file"
2760           do_clamd_reload=1
2761         fi
2762         if [ -r "$clam_dbs/$db_file" ] ; then
2763           rm -f "$clam_dbs/$db_file"
2764           do_clamd_reload=1
2765         fi
2766       done
2767     fi
2768   fi
2769 fi
2770
2771 ##############################################################################################################################################
2772 # Check for updated additional database files every set number of hours as defined in the "USER CONFIGURATION" section of this script 
2773 ##############################################################################################################################################
2774 if [ "$additional_enabled" == "yes" ] ; then
2775   if [ -n "$additional_dbs" ] ; then
2776     if [ "$(xshok_array_count "$additional_dbs")" -lt "1" ] ; then
2777       xshok_pretty_echo_and_log "Failed additional_dbs config is invalid or not defined - SKIPPING"
2778     else
2779     rm -f "$work_dir_add/*.gz"
2780     if [ -r "$work_dir_work_configs/last-additional-update.txt" ] ; then
2781       last_additional_update=$(cat "$work_dir_work_configs/last-additional-update.txt")
2782     else
2783       last_additional_update="0"
2784     fi
2785     db_file=""
2786     loop=""
2787     update_interval=$((additional_update_hours * 3600))
2788     time_interval=$((current_time - last_additional_update))
2789     if [ "$time_interval" -ge $((update_interval - 600)) ] ; then
2790       echo "$current_time" > "$work_dir_work_configs/last-additional-update.txt"
2791
2792       xshok_pretty_echo_and_log "Additional Database File Updates" "="
2793       xshok_pretty_echo_and_log "Checking for additional updates..."
2794       additional_updates="0"
2795       for db_url in $additional_dbs ; do
2796         # left for future dir manipulation       
2797         # if echo "$db_file" | $grep_bin -q "/"; then
2798         #   add_dir="/"$(echo "$db_file" | cut -d"/" -f1)
2799         #   db_file=$(echo "$db_file" | cut -d"/" -f2)
2800         # else 
2801         #   add_dir=""
2802         # fi
2803        db_file=$(basename "$db_url")
2804
2805         if [ "$loop" = "1" ] ; then
2806           xshok_pretty_echo_and_log "---"      
2807         fi
2808         xshok_pretty_echo_and_log "Checking for updated additional database file: $db_file"
2809
2810         additional_db_update="0"
2811
2812         if [ "$(echo "$db_url" | cut -d ":" -f1)" = "rsync" ] ; then
2813           $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
2814           ret="$?"
2815         else
2816           if [ "$wget_bin" != "" ] ; then
2817             $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="$work_dir_add/$db_file" "$db_url"
2818             ret="$?"
2819           else
2820             $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 "$work_dir_add/$db_file" "$db_url"
2821             ret="$?"
2822           fi
2823         fi
2824
2825         ##this needs enhancement for rsync, as it will only work with single files... maybe better to process each file inside work_dir_add in its own for loop.
2826         if [ "$ret" -eq "0" ] ; then
2827           loop="1"
2828           if ! cmp -s "$work_dir_add/$db_file" "$clam_dbs/$db_file" ; then
2829             if [ "$?" -eq "0" ] ; then
2830               db_ext=$(echo "$db_file" | cut -d "." -f2)
2831
2832               xshok_pretty_echo_and_log "Testing updated additional database file: $db_file"
2833               if [ -z "$ham_dir" ] || [ "$db_ext" != "ndb" ] ; then
2834                 if $clamscan_bin --quiet -d "$work_dir_add/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null
2835                   then
2836                   xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested good"
2837                   true
2838                 else
2839                   xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested BAD"
2840                   if [ "$remove_bad_database" == "yes" ] ; then
2841                     if rm -f "$work_dir_add/$db_file" ; then
2842                       xshok_pretty_echo_and_log "Removed invalid database: $work_dir_add/$db_file"
2843                     fi
2844                   fi
2845                   false
2846                 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
2847                 perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2848                 if [ "$selinux_fixes" == "yes" ] ; then
2849                   restorecon "$clam_dbs/$db_file"
2850                 fi
2851                 xshok_pretty_echo_and_log "Successfully updated additional production database file: $db_file"
2852                 additional_updates=1
2853                 additional_db_update=1
2854                 do_clamd_reload=1
2855               else
2856                 xshok_pretty_echo_and_log "Failed to successfully update additional production database file: $db_file - SKIPPING"
2857               fi
2858             else
2859               $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$work_dir_add/$db_file" > "$test_dir/$db_file"
2860               $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"
2861               $grep_bin -h -f "$work_dir_work_configs/whitelist.txt" "$test_dir/$db_file" | cut -d "*" -f2 | sort | uniq >> "$work_dir_work_configs/whitelist.hex"
2862               $grep_bin -h -v -f "$work_dir_work_configs/whitelist.hex" "$test_dir/$db_file" > "$test_dir/$db_file-tmp"
2863               mv -f "$test_dir/$db_file-tmp" "$test_dir/$db_file"
2864               if $clamscan_bin --quiet -d "$test_dir/$db_file" "$work_dir_work_configs/scan-test.txt" 2>/dev/null ; then
2865                 xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested good"
2866                 true
2867               else
2868                 xshok_pretty_echo_and_log "Clamscan reports additional $db_file database integrity tested BAD"
2869                 if [ "$remove_bad_database" == "yes" ] ; then
2870                   if rm -f "$work_dir_add/$db_file" ; then
2871                     xshok_pretty_echo_and_log "Removed invalid database: $work_dir_add/$db_file"
2872                   fi
2873                 fi
2874                 false
2875               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
2876               perms chown -f "$clam_user:$clam_group" "$clam_dbs/$db_file"
2877               if [ "$selinux_fixes" == "yes" ] ; then
2878                 restorecon "$clam_dbs/$db_file"
2879               fi
2880               xshok_pretty_echo_and_log "Successfully updated additional production database file: $db_file"
2881               additional_updates=1
2882               additional_db_update=1
2883               do_clamd_reload=1
2884             else
2885               xshok_pretty_echo_and_log "Failed to successfully update additional production database file: $db_file - SKIPPING"
2886             fi
2887           fi
2888         fi
2889       fi
2890     else
2891       xshok_pretty_echo_and_log "WARNING: Failed connection to $additional_url - SKIPPED additional $db_file update"
2892     fi
2893     if [ "$additional_db_update" != "1" ] ; then
2894       xshok_pretty_echo_and_log "No updated additional $db_file database file found"
2895     fi
2896   done
2897   if [ "$additional_updates" != "1" ] ; then
2898     xshok_pretty_echo_and_log "No additional database file updates found" "-"
2899   fi
2900 else
2901
2902   xshok_pretty_echo_and_log "Additional Database File Updates" "="
2903
2904   time_remaining=$((update_interval - time_interval))
2905   hours_left=$((time_remaining / 3600))
2906   minutes_left=$((time_remaining % 3600 / 60))
2907   xshok_pretty_echo_and_log "$additional_update_hours hours have not yet elapsed since the last additional database update check"
2908   xshok_pretty_echo_and_log "No update check was performed at this time" "-"
2909   xshok_pretty_echo_and_log "Next check will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
2910 fi
2911 fi
2912 fi
2913 else
2914   if [ -n "$additional_dbs" ] ; then
2915     if [ "$remove_disabled_databases" == "yes" ] ; then
2916       xshok_pretty_echo_and_log "Removing disabled additional Database files"
2917       for db_file in $additional_dbs ; do
2918         if echo "$db_file" | $grep_bin -q "/"; then
2919           db_file=$(echo "$db_file" | cut -d"/" -f2)
2920         fi
2921         if [ -r "$work_dir_add/$db_file" ] ; then
2922           rm -f "$work_dir_add/$db_file"
2923           do_clamd_reload=1
2924         fi
2925         if [ -r "$clam_dbs/$db_file" ] ; then
2926           rm -f "$clam_dbs/$db_file"
2927           do_clamd_reload=1
2928         fi
2929       done
2930     fi
2931   fi
2932 fi
2933
2934 ###################################################
2935 # Generate whitelists
2936 ###################################################
2937 # Check to see if the local.ign file exists, and if it does, check to see if any of the script
2938 # added bypass entries can be removed due to offending signature modifications or removals.
2939 if [ -r "$clam_dbs/local.ign" ] && [ -s "$work_dir_work_configs/monitor-ign.txt" ] ; then
2940   ign_updated=0
2941   cd "$clam_dbs" || exit
2942   cp -f local.ign "$work_dir_work_configs/local.ign"
2943   cp -f "$work_dir_work_configs/monitor-ign.txt" "$work_dir_work_configs/monitor-ign-old.txt"
2944
2945   xshok_pretty_echo_and_log "" "=" "80"
2946   while read -r entry ; do
2947     sig_file=$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $1}')
2948     sig_hex=$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $NF}')
2949     sig_name_old=$(echo "$entry" | tr -d "\r" | awk -F ":" '{print $3}')
2950     sig_ign_old=$($grep_bin ":$sig_name_old" "$work_dir_work_configs/local.ign")
2951     sig_old=$(echo "$entry" | tr -d "\r" | cut -d ":" -f3-)
2952     sig_new=$($grep_bin -hwF ":$sig_hex" "$sig_file" | tr -d "\r" 2>/dev/null)
2953     sig_mon_new=$($grep_bin -HwF -n ":$sig_hex" "$sig_file" | tr -d "\r")
2954     if [ -n "$sig_new" ] ; then
2955       if [ "$sig_old" != "$sig_new" ] || [ "$entry" != "$sig_mon_new" ] ; then
2956         sig_name_new=$(echo "$sig_new" | tr -d "\r" | awk -F ":" '{print $1}')
2957         sig_ign_new=$(echo "$sig_mon_new" | cut -d ":" -f1-3)
2958         perl -i -ne "print unless /$sig_ign_old/" "$work_dir_work_configs/monitor-ign.txt"
2959         echo "$sig_mon_new" >> "$work_dir_work_configs/monitor-ign.txt"
2960         perl -p -i -e "s/$sig_ign_old/$sig_ign_new/" "$work_dir_work_configs/local.ign"
2961         xshok_pretty_echo_and_log "$sig_name_old hexadecimal signature is unchanged, however signature name and/or line placement"
2962         xshok_pretty_echo_and_log "in $sig_file has changed to $sig_name_new - updated local.ign to reflect this change."
2963         ign_updated=1
2964       fi
2965     else
2966       perl -i -ne "print unless /$sig_ign_old/" "$work_dir_work_configs/monitor-ign.txt" "$work_dir_work_configs/local.ign"
2967
2968       xshok_pretty_echo_and_log "$sig_name_old signature has been removed from $sig_file, entry removed from local.ign."
2969       ign_updated=1
2970     fi
2971   done < "$work_dir_work_configs/monitor-ign-old.txt"
2972   if [ "$ign_updated" = "1" ] ; then
2973     if $clamscan_bin --quiet -d "$work_dir_work_configs/local.ign" "$work_dir_work_configs/scan-test.txt"
2974       then
2975       if $rsync_bin -pcqt "$work_dir_work_configs/local.ign" "$clam_dbs"
2976         then
2977         perms chown -f "$clam_user:$clam_group" "$clam_dbs/local.ign"
2978         perms chmod -f 0644 "$clam_dbs/local.ign" "$work_dir_work_configs/monitor-ign.txt"
2979         if [ "$selinux_fixes" == "yes" ] ; then
2980           restorecon "$clam_dbs/local.ign"
2981         fi
2982         do_clamd_reload=3
2983       else
2984         xshok_pretty_echo_and_log "Failed to successfully update local.ign file - SKIPPING"
2985       fi
2986     else
2987       xshok_pretty_echo_and_log "Clamscan reports local.ign database integrity is bad - SKIPPING"
2988     fi
2989   else
2990     xshok_pretty_echo_and_log "No whitelist signature changes found in local.ign" "="
2991   fi
2992 fi
2993
2994 # Check to see if my-whitelist.ign2 file exists, and if it does, check to see if any of the script
2995 # added whitelist entries can be removed due to offending signature modifications or removals.
2996 if [ -r "$clam_dbs/my-whitelist.ign2" ] && [ -s "$work_dir_work_configs/tracker.txt" ] ; then
2997   ign2_updated=0
2998   cd "$clam_dbs" || exit
2999   cp -f my-whitelist.ign2 "$work_dir_work_configs/my-whitelist.ign2"
3000
3001   xshok_pretty_echo_and_log "" "=" "80"
3002
3003   while read -r entry ; do
3004     sig_file=$(echo "$entry" | cut -d ":" -f1)
3005     sig_full=$(echo "$entry" | cut -d ":" -f2-)
3006     sig_name=$(echo "$entry" | cut -d ":" -f2)
3007     if ! $grep_bin -F "$sig_full" "$sig_file" > /dev/null 2>&1 ; then
3008       perl -i -ne "print unless /$sig_name$/" "$work_dir_work_configs/my-whitelist.ign2"
3009       perl -i -ne "print unless /:$sig_name:/" "$work_dir_work_configs/tracker-tmp.txt"
3010
3011       xshok_pretty_echo_and_log "$sig_name signature no longer exists in $sig_file, whitelist entry removed from my-whitelist.ign2"
3012       ign2_updated=1
3013     fi
3014   done < "$work_dir_work_configs/tracker.txt"
3015   mv -f "$work_dir_work_configs/tracker-tmp.txt" "$work_dir_work_configs/tracker.txt"
3016
3017   xshok_pretty_echo_and_log "" "=" "80"
3018   if [ "$ign2_updated" = "1" ]
3019     then
3020     if $clamscan_bin --quiet -d "$work_dir_work_configs/my-whitelist.ign2" "$work_dir_work_configs/scan-test.txt"
3021       then
3022       if $rsync_bin -pcqt "$work_dir_work_configs/my-whitelist.ign2" "$clam_dbs"
3023         then
3024         perms chown -f "$clam_user:$clam_group" "$clam_dbs/my-whitelist.ign2"
3025         perms chmod -f 0644 "$clam_dbs/my-whitelist.ign2" "$work_dir_work_configs/tracker.txt"
3026         if [ "$selinux_fixes" == "yes" ] ; then
3027           restorecon "$clam_dbs/my-whitelist.ign2"
3028           restorecon "$work_dir_work_configs/tracker.txt"
3029         fi
3030         do_clamd_reload=4
3031       else
3032         xshok_pretty_echo_and_log "Failed to successfully update my-whitelist.ign2 file - SKIPPING"
3033       fi
3034     else
3035       xshok_pretty_echo_and_log "Clamscan reports my-whitelist.ign2 database integrity is bad - SKIPPING"
3036     fi
3037   else
3038     xshok_pretty_echo_and_log "No whitelist signature changes found in my-whitelist.ign2"
3039   fi
3040 fi
3041
3042 # Check for non-matching whitelist.hex signatures and remove them from the whitelist file (signature modified or removed).
3043 if [ -n "$ham_dir" ] ; then
3044   if [ -r "$work_dir_work_configs/whitelist.hex" ] ; then
3045     $grep_bin -h -f "$work_dir_work_configs/whitelist.hex" "$work_dir"/*/*.ndb | cut -d "*" -f2 | tr -d "\r" | sort | uniq > "$work_dir_work_configs/whitelist.tmp"
3046     mv -f "$work_dir_work_configs/whitelist.tmp" "$work_dir_work_configs/whitelist.hex"
3047     rm -f "$work_dir_work_configs/whitelist.txt"
3048     rm -f "$test_dir"/*.*
3049     xshok_pretty_echo_and_log "WARNING: Signature(s) triggered on HAM directory scan - signature(s) removed" "*"
3050   else
3051     xshok_pretty_echo_and_log "No signatures triggered on HAM directory scan" "="
3052   fi
3053 fi
3054
3055 # Set appropriate directory and file permissions to all production signature files
3056 # and set file access mode to 0644 on all working directory files.
3057
3058 if [ "$setmode" = "yes" ] ; then
3059   xshok_pretty_echo_and_log "Setting permissions and ownership" "="
3060   perms chown -f -R "$clam_user:$clam_group" "$work_dir"
3061   if ! find "$work_dir" -type f -exec chmod -f 0644 {} + 2>/dev/null ; then
3062     if ! find "$work_dir" -type f -print0 | xargs -0 chmod -f 0644 2>/dev/null ; then
3063       if ! find "$work_dir" -type f -print0 | xargs chmod -f 0644 2>/dev/null ; then
3064         find "$work_dir" -type f -exec chmod -f 0644 {} \;
3065       fi
3066     fi
3067   fi
3068
3069 # If enabled, set file access mode for all production signature database files to 0644.
3070   perms chown -f -R "$clam_user:$clam_group" "$clam_dbs"
3071   if ! find "$clam_dbs" -type f -exec chmod -f 0644 {} + 2>/dev/null ; then
3072     if ! find "$clam_dbs" -type f -print0 | xargs -0 chmod -f 0644 2>/dev/null ; then
3073       if ! find "$clam_dbs" -type f -print0 | xargs chmod -f 0644 2>/dev/null ; then
3074         find "$clam_dbs" -type f -exec chmod -f 0644 {} \;
3075       fi
3076     fi
3077   fi
3078 fi
3079
3080 # Reload all clamd databases  
3081 clamscan_reload_dbs
3082
3083 xshok_pretty_echo_and_log "Issue tracker : https://github.com/extremeshok/clamav-unofficial-sigs/issues" "-"
3084
3085 check_new_version
3086
3087 xshok_cleanup
3088
3089 # And lastly we exit, Note: the exit is always on the 2nd last line
3090 exit $?