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