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