"Fossies" - the Fresh Open Source Software Archive

Member "lynis/lynis" (22 Jul 2021, 51936 Bytes) of package /linux/misc/lynis-3.0.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bash source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "lynis": 3.0.5_vs_3.0.6.

    1 #!/bin/sh
    2 
    3 #################################################################################
    4 #
    5 #   Lynis
    6 # ------------------
    7 #
    8 # Copyright 2007-2013, Michael Boelen
    9 #           2013-now, CISOfy
   10 #
   11 # Web site: https://cisofy.com
   12 #
   13 # Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
   14 # welcome to redistribute it under the terms of the GNU General Public License.
   15 # See LICENSE file for usage of this software.
   16 #
   17 # Lynis is licensed under GPLv3, Plugins are licensed differently (see plugins)
   18 #
   19 #################################################################################
   20 #
   21 # Lynis is an automated auditing tool for Unix based operating systems.
   22 #
   23 #################################################################################
   24 #
   25     # In Solaris /bin/sh is not POSIX, but /usr/xpg4/bin/sh is.
   26     # Switch to /usr/xpg4/bin/sh if it exists and we are not already running it.
   27     if [ "$(uname)" = "SunOS" ]; then
   28         test "$_" != "/usr/xpg4/bin/sh" && test -f /usr/xpg4/bin/sh && exec /usr/xpg4/bin/sh "$0" "$@"
   29     fi
   30 #
   31 #################################################################################
   32 #
   33     # Code quality: don't allow using undefined variables
   34     # Notes: $_ may be empty on FreeBSD
   35     set -o nounset
   36 #
   37 #################################################################################
   38 #
   39     # Program information
   40     PROGRAM_NAME="Lynis"
   41     PROGRAM_AUTHOR="CISOfy"
   42     PROGRAM_AUTHOR_CONTACT="lynis-dev@cisofy.com"
   43     PROGRAM_WEBSITE="https://cisofy.com/lynis/"
   44 
   45     # Version details
   46     PROGRAM_RELEASE_DATE="2021-07-22"
   47     PROGRAM_RELEASE_TIMESTAMP=1626945158
   48     PROGRAM_RELEASE_TYPE="release" # pre-release or release
   49     PROGRAM_VERSION="3.0.6"
   50 
   51     # Source, documentation and license
   52     PROGRAM_SOURCE="https://github.com/CISOfy/lynis"
   53     PROGRAM_PACKAGE="https://packages.cisofy.com/"
   54     PROGRAM_DOCUMENTATION="https://cisofy.com/docs/"
   55     PROGRAM_COPYRIGHT="2007-2021, ${PROGRAM_AUTHOR} - ${PROGRAM_WEBSITE}"
   56     PROGRAM_LICENSE="${PROGRAM_NAME} comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
   57   welcome to redistribute it under the terms of the GNU General Public License.
   58   See the LICENSE file for details about using this software."
   59     PROGRAM_EXTRAINFO="Enterprise support available (compliance, plugins, interface and tools)"
   60 
   61     # Version number of report files (when format changes in future)
   62     REPORT_version_major="1"; REPORT_version_minor="0"
   63     REPORT_version="${REPORT_version_major}.${REPORT_version_minor}"
   64 
   65 
   66 #
   67 #################################################################################
   68 #
   69 # Configure Include path and files
   70 #
   71 #################################################################################
   72 #
   73     # Check setuid bit
   74     if [ -u "$0" ]; then echo "The called binary has the set-user-id bit - As this is unusual, execution will be stopped."; exit 1; fi
   75 
   76     # Work directory
   77     WORKDIR=$(pwd)
   78 
   79     # Test from which directories we can use all functions and tests
   80     USE_CWD=0
   81     if case "$@" in *--usecwd*) true;; *) false;; esac; then
   82         USE_CWD=1
   83         INCLUDEDIR="./include"
   84     else
   85         INCLUDEDIR=""
   86         tINCLUDE_TARGETS="/usr/local/include/lynis /usr/local/lynis/include /usr/share/lynis/include ./include"  # Default paths to check (CWD as last option, in case we run from standalone)
   87         for I in ${tINCLUDE_TARGETS}; do
   88             if [ "${I}" = "./include" ]; then
   89                 if [ -d "${WORKDIR}/include" ]; then INCLUDEDIR="${WORKDIR}/include"; fi
   90             elif [ -d ${I} -a -z "${INCLUDEDIR}" ]; then
   91                 INCLUDEDIR=${I}
   92         break
   93             fi
   94         done
   95     fi
   96 
   97     # Drop out if our include directory can't be found
   98     if [ -z "${INCLUDEDIR}" ]; then
   99         printf "%s" "\nFatal error: can't find include directory\nMake sure to execute ${PROGRAM_NAME} from untarred directory or check your installation."
  100         exit 1
  101     fi
  102 
  103     # Test for database directory
  104     if [ ${USE_CWD} -eq 1 ]; then
  105         DBDIR="./db"
  106     else
  107         DBDIR=""; tDB_TARGETS="/usr/local/share/lynis/db /usr/local/lynis/db /usr/share/lynis/db ./db"
  108         for I in ${tDB_TARGETS}; do
  109             if [ "${I}" = "./db" ]; then
  110                 if [ -d "${WORKDIR}/db" ]; then DBDIR="${WORKDIR}/db"; fi
  111             elif [ -d ${I} -a -z "${DBDIR}" ]; then
  112                 DBDIR="${I}"
  113             fi
  114         done
  115     fi
  116 #
  117 #################################################################################
  118 #
  119     MYID=""
  120     # Check user to determine file permissions later on. If we encounter Solaris, use related id binary instead
  121     if [ -x /usr/xpg4/bin/id ]; then
  122         MYID=$(/usr/xpg4/bin/id -u 2> /dev/null)
  123     elif [ "$(uname)" = "SunOS" ]; then
  124         MYID=$(id | tr '=' ' ' | tr '(' ' ' | awk '{ print $2 }' 2> /dev/null)
  125     else
  126         MYID=$(id -u 2> /dev/null)
  127     fi
  128     if [ -z "${MYID}" ]; then Display "Could not find user ID with id command. Want to help improve Lynis? Raise a ticket at ${PROGRAM_SOURCE}"; ExitFatal; fi
  129 #
  130 #################################################################################
  131 #
  132 # Set basic values and test permissions of the files to include, such as:
  133 # - consts: bin paths, text strings, colors
  134 # - functions: function library
  135 #
  136 #################################################################################
  137 #
  138     # Determine if we are root (UID = 0)
  139     if [ ${MYID} -eq 0 ]; then
  140         PRIVILEGED=1
  141         PENTESTINGMODE=0
  142     else
  143         PRIVILEGED=0
  144         # Set to pentesting mode if scan is without root privileges
  145         PENTESTINGMODE=1
  146     fi
  147 
  148     # Perform a basic check for permissions. After including functions, using SafePerms()
  149     IGNORE_FILE_PERMISSION_ISSUES=0
  150 
  151     FILES_TO_CHECK="consts functions"
  152 
  153     ISSUE=0
  154     ISSUE_TYPE=""
  155     SHOWPERMERROR=0
  156 
  157     for FILE in ${FILES_TO_CHECK}; do
  158         PERMS=$(ls -l ${INCLUDEDIR}/${FILE} | cut -c 2-10)
  159         GROUPPERMS=$(ls -l ${INCLUDEDIR}/${FILE} | cut -c 5-7)
  160         GROUPOWNERID=$(ls -n ${INCLUDEDIR}/${FILE} | awk '{ print $4 }')
  161         OWNER=$(ls -l ${INCLUDEDIR}/${FILE} | awk -F" " '{ print $3 }')
  162         OWNERID=$(ls -n ${INCLUDEDIR}/${FILE} | awk -F" " '{ print $3 }')
  163 
  164         # Check permissions of include/X file (400, 600, 640, 644)
  165         if [ "${PERMS}" = "rwxrwxrwx" ]; then
  166             ISSUE=1; ISSUE_TYPE="perms"; echo "[!] Change file permissions of ${INCLUDEDIR}/${FILE} to 640."; echo "    Command: chmod 640 ${INCLUDEDIR}/${FILE}"
  167         elif [ ! "${PERMS}" = "r--------" -a ! "${PERMS}" = "rw-------" -a ! "${PERMS}" = "rw-r-----" -a ! "${PERMS}" = "rw-r--r--" ]; then
  168             # If group ID equals user ID, we consider permissions to be fine (probably default umask)
  169             if [ ! "${GROUPOWNERID}" = "${OWNERID}" ]; then
  170                 ISSUE=1; ISSUE_TYPE="perms"; echo "[!] Change file permissions of ${INCLUDEDIR}/${FILE} to 640."; echo "    Command: chmod 640 ${INCLUDEDIR}/${FILE}"
  171             fi
  172         fi
  173 
  174         # Check if owner of both files is root user, or the same user which is running Lynis (for pentester mode)
  175         if [ ! "${OWNER}" = "root" -a ! "${OWNERID}" = "0" ]; then
  176             if [ ! "${MYID}" = "${OWNERID}" ]; then
  177                 ISSUE=1; ISSUE_TYPE="owner"; SHOWPERMERROR=1; ISSUE_FILE="${FILE}"; ISSUE_OWNER="${OWNER}"; ISSUE_OWNERID="${OWNERID}"
  178             fi
  179         fi
  180     done
  181 
  182     if [ ${SHOWPERMERROR} -eq 1 ]; then
  183         printf "%s" "
  184 
  185 [!] Change ownership of ${INCLUDEDIR}/${ISSUE_FILE} to 'root' or similar (found: ${ISSUE_OWNER} with UID ${ISSUE_OWNERID}).
  186 
  187     Command:
  188       # chown 0:0 ${INCLUDEDIR}/${ISSUE_FILE}
  189 "
  190     fi
  191 
  192     # Now if there is an issue with permissions, show it to the user and let them decide how to continue.
  193     if [ ${ISSUE} -eq 1 ]; then
  194         printf "\n[X] Security check failed\n\n    Why do I see this error?\n    -------------------------------\n    This is a protection mechanism to prevent the root user from executing user created files. The files may be altered, or including malicious pieces of script.\n\n    What can I do?\n    ---------------------\n    Option 1) Check if a trusted user created the files (e.g. due to using Git, Homebrew or similar).\n              If you trust these files, you can decide to continue this run by pressing ENTER.\n"
  195         if [ "${ISSUE_TYPE}" = "perms" ]; then
  196             printf "\n    Option 2) Change permissions of the related files.\n\n       Commands (full directory):\n         # chmod 640 include/*\n         # ./lynis audit system"
  197         elif [ "${ISSUE_TYPE}" = "owner" ]; then
  198             printf "\n    Option 2) Change ownership of the related files (or full directory).\n\n       Commands (full directory):\n         # cd ..\n         # chown -R 0:0 lynis\n         # cd lynis\n         # ./lynis audit system"
  199         fi
  200         printf "\n\n[ Press ENTER to continue, or CTRL+C to cancel ]"
  201         IGNORE_FILE_PERMISSION_ISSUES=1
  202         read -r void
  203     fi
  204 
  205     # Now include files if permissions are correct, or user decided to continue
  206     . ${INCLUDEDIR}/consts
  207     . ${INCLUDEDIR}/functions
  208 #
  209 #################################################################################
  210 #
  211 # Language settings
  212 #
  213 #################################################################################
  214 #
  215     # Auto detection of language based on shell LANG variable. This is required by the Display() function to deal with multi-bytes characters.
  216     DISPLAY_LANG="${LANG:-}"
  217 
  218     # Extract the short notation of the language (first two characters).
  219     if [ -x "$(command -v locale 2> /dev/null)" ]; then
  220         LANGUAGE=$(locale | egrep "^LANG=" | cut -d= -f2 | cut -d_ -f1 | tr -d '"' | egrep "^[a-z]{2}$")
  221         # Try locale command if shell variable had no value
  222         if [ -z "${DISPLAY_LANG}" ]; then
  223             DISPLAY_LANG=$(locale | egrep "^LANG=" | cut -d= -f2)
  224         fi
  225     else
  226         LANGUAGE="en"
  227     fi
  228 
  229     # Set default language: 'en' (English) if no value is set
  230     if [ -z "${LANGUAGE}" ]; then
  231         LANGUAGE="en"
  232     fi
  233 
  234     # Import translations. First import English to prefill all texts
  235     if [ -f ${DBDIR}/languages/en ]; then
  236         if SafeFile "${DBDIR}/languages/en"; then
  237             . ${DBDIR}/languages/en
  238         else
  239             ExitFatal "Incorrect ownership or permissions of language file (${DBDIR}/languages/en)"
  240         fi
  241     else
  242         echo "Could not find languages directory (file: ${DBDIR}/languages/en)"
  243         exit 1
  244     fi
  245 
  246     # Now that we have determined the language, we unset it from shell
  247     # Some tools with translated strings are very hard to parse
  248     unset LANG
  249 
  250 #
  251 #################################################################################
  252 #
  253 # Traps
  254 #
  255 #################################################################################
  256 #
  257     trap CleanUp INT TERM
  258     trap Status USR1
  259 
  260     # Use safe umask for the files we create
  261     umask 027
  262 #
  263 #################################################################################
  264 #
  265 # Parameter checks
  266 #
  267 #################################################################################
  268 #
  269     SafePerms ${INCLUDEDIR}/parameters
  270     . ${INCLUDEDIR}/parameters
  271 
  272 
  273     # Disable logging if no alternative was provided
  274     if [ ${PRIVILEGED} -eq 0 ]; then
  275         if [ -z "${LOGFILE}" ]; then
  276             # Try creating a log file in home directory
  277             if [ ! -f "$HOME/lynis.log" ]; then
  278                 if [ -L "$HOME/lynis.log" ]; then echo "Log file is symlinked, which can introduce the risk of a symlink attack."; exit 1; fi
  279                 touch "$HOME/lynis.log"
  280                 if [ $? -eq 0 ]; then LOGFILE="$HOME/lynis.log"; else LOGFILE="/dev/null"; fi
  281             else
  282                 LOGFILE="$HOME/lynis.log"
  283             fi
  284         else
  285             if [ -L "${LOGFILE}" ]; then echo "Log file is symlinked, which can introduce the risk of a symlink attack."; exit 1; fi
  286         fi
  287         if [ -z "${REPORTFILE}" ]; then
  288             touch "$HOME/lynis-report.dat"
  289             if [ -L "$HOME/lynis-report.dat" ]; then echo "Report file is symlinked, which can introduce the risk of a symlink attack."; exit 1; fi
  290             if [ $? -eq 0 ]; then REPORTFILE="$HOME/lynis-report.dat"; else REPORTFILE="/dev/null"; fi
  291         else
  292             if [ -L "${REPORTFILE}" ]; then echo "Report file is symlinked, which can introduce the risk of a symlink attack."; exit 1; fi
  293         fi
  294     fi
  295 #
  296 #################################################################################
  297 #
  298 # Program information
  299 #
  300 #################################################################################
  301 #
  302     # CV - Current Version
  303     PROGRAM_AC=$(echo ${PROGRAM_VERSION} | awk '{ print $1 }' | sed 's/[.]//g')
  304     PROGRAM_LV=0
  305 #
  306 #################################################################################
  307 #
  308 # Initialize and default settings
  309 #
  310 #################################################################################
  311 #
  312 
  313     if [ ${QUIET} -eq 0 ]; then
  314         printf "\n${WHITE}[ ${PROGRAM_NAME} ${PROGRAM_VERSION} ]${NORMAL}\n\n################################################################################\n  ${PROGRAM_LICENSE}\n\n  ${PROGRAM_COPYRIGHT}\n  ${PROGRAM_EXTRAINFO}\n################################################################################\n\n"
  315     fi
  316 
  317     if [ "${PROGRAM_RELEASE_TYPE}" = "beta" ]; then
  318         printf "%s" "
  319 ${WHITE}
  320   #########################################################
  321   #   ${YELLOW}BETA VERSION${WHITE}                                        #
  322   #########################################################
  323 
  324   Thank you for testing a beta release. Make sure to read
  325   all available documentation before proceeding and/or
  326   requesting support. Due the nature of beta releases, it
  327   is possible new features give unexpected warnings.
  328 
  329 
  330   #########################################################
  331 ${NORMAL}
  332 "
  333     fi
  334 #
  335 #################################################################################
  336 #
  337     InsertSection "${GEN_INITIALIZE_PROGRAM}"
  338 
  339     # Discover any profiles
  340     DiscoverProfiles
  341 
  342     # Initialize and check profile file, auditor name, log file and report file
  343     if [ -z "${LOGDIR}" ];            then LOGDIR="/var/log"; fi
  344     if [ -z "${AUDITORNAME}" ];       then AUDITORNAME="[Not Specified]"; fi
  345     if [ -z "${LOGFILE}" ];           then LOGFILE="${LOGDIR}/lynis.log"; fi
  346     if [ -z "${REPORTFILE}" ];        then REPORTFILE="${LOGDIR}/lynis-report.dat"; fi
  347 #
  348 #################################################################################
  349 #
  350 # PID :: Check PID file, to avoid multiple instances running at the same time.
  351 #
  352 #################################################################################
  353 #
  354     # Decide where to write our PID file. For unprivileged users this will be in their home directory, or /tmp if their
  355     # home directory isn't set. For root it will be /var/run, or the current working directory if /var/run doesn't exist.
  356     MYHOMEDIR=$(echo ~ 2> /dev/null)
  357     if [ -z "${MYHOMEDIR}" ]; then MYHOMEDIR="/tmp"; fi
  358 
  359     if [ ${PRIVILEGED} -eq 0 ]; then
  360         PIDFILE="${MYHOMEDIR}/lynis.pid"
  361     elif [ -d /var/run ]; then
  362         PIDFILE="/var/run/lynis.pid"
  363     else
  364         PIDFILE="./lynis.pid"
  365     fi
  366 
  367     # Check if there is already a PID file in any of the locations (incorrect termination of previous instance)
  368     if [ -f "${MYHOMEDIR}/lynis.pid" -o -f "./lynis.pid" -o -f "/var/run/lynis.pid" ]; then
  369         printf "%s" "
  370 
  371 ${WARNING}Warning${NORMAL}: ${WHITE}PID file exists, probably another Lynis process is running.${NORMAL}
  372 ------------------------------------------------------------------------------
  373 If you are unsure if another Lynis process is running currently, you are advised
  374 to stop the current process and check the process list first. If you cancelled
  375 a previous instance (by using CTRL+C), you can ignore this message.
  376 
  377 You are advised to check for temporary files after program completion.
  378 ------------------------------------------------------------------------------
  379 
  380 ${YELLOW}Note: ${WHITE}Cancelling the program can leave temporary files behind${NORMAL}
  381 "
  382 
  383         # Quit directly for cron jobs.
  384         if [ ${CRONJOB} -eq 1 ]; then
  385             echo "Quitting, to prevent multiple cron jobs running at the same time"
  386             exit 1 # Manually exit, no cleanups to prevent deleting an active PID file
  387         else
  388             WaitForKeyPress
  389         fi
  390 
  391         # Deleting any stale PID files that might exist. Note: Display function does not work yet at this point
  392         if [ -f "${MYHOMEDIR}/lynis.pid" ]; then rm -f "${MYHOMEDIR}/lynis.pid"; fi
  393         if [ -f "./lynis.pid" ]; then rm -f "./lynis.pid"; fi
  394         if [ -f "/var/run/lynis.pid" ]; then rm -f "/var/run/lynis.pid"; fi
  395     fi
  396 
  397     # Ensure symlink attack is not possible, by confirming there is no symlink of the file already
  398     OURPID=$(echo $$)
  399     if [ -L ${PIDFILE} ]; then
  400         echo "Found symlinked PID file (${PIDFILE}), quitting"
  401         ExitFatal
  402     else
  403         # Create new PID file writable only by owner
  404         echo "${OURPID}" > ${PIDFILE}
  405         chmod 600 ${PIDFILE}
  406     fi
  407 #
  408 #################################################################################
  409 #
  410 # Check program parameters
  411 #
  412 #################################################################################
  413 #
  414     # Bail out if we didn't get any parameter, or incorrect ones
  415     if [ ${PARAMCOUNT} -eq 0 -o ${WRONGOPTION} -eq 1 -o ${VIEWHELP} -eq 1 ]; then
  416         printf "%s" "
  417 
  418   ${GREEN}Usage:${NORMAL} lynis ${CYAN}command ${GRAY}[options]${NORMAL}
  419 
  420 
  421   ${WHITE}Command:${NORMAL}
  422 
  423     ${CYAN}audit${NORMAL}
  424         audit system                  : Perform local security scan
  425         audit system remote <host>    : Remote security scan
  426         audit dockerfile <file>       : Analyze Dockerfile
  427 
  428     ${CYAN}show${NORMAL}
  429         show                          : Show all commands
  430         show version                  : Show ${PROGRAM_NAME} version
  431         show help                     : Show help
  432 
  433     ${CYAN}update${NORMAL}
  434         update info                   : Show update details
  435 
  436 
  437   ${WHITE}Options:${NORMAL}
  438 
  439     ${WHITE}Alternative system audit modes${NORMAL}
  440     ${GRAY}--forensics${NORMAL}                       : Perform forensics on a running or mounted system
  441     ${GRAY}--pentest${NORMAL}                         : Non-privileged, show points of interest for pentesting
  442 
  443     ${WHITE}Layout options${NORMAL}
  444     ${GRAY}--no-colors${NORMAL}                       : Don't use colors in output
  445     ${GRAY}--quiet (-q)${NORMAL}                      : No output
  446     ${GRAY}--reverse-colors${NORMAL}                  : Optimize color display for light backgrounds
  447     ${GRAY}--reverse-colours${NORMAL}                 : Optimize colour display for light backgrounds
  448 
  449     ${WHITE}Misc options${NORMAL}
  450     ${GRAY}--debug${NORMAL}                           : Debug logging to screen
  451     ${GRAY}--no-log${NORMAL}                          : Don't create a log file
  452     ${GRAY}--profile ${BROWN}<profile>${NORMAL}               : Scan the system with the given profile file
  453     ${GRAY}--view-manpage (--man)${NORMAL}            : View man page
  454     ${GRAY}--verbose${NORMAL}                         : Show more details on screen
  455     ${GRAY}--version (-V)${NORMAL}                    : Display version number and quit
  456     ${GRAY}--wait${NORMAL}                            : Wait between a set of tests
  457     ${GRAY}--slow-warning ${BROWN}<seconds>${NORMAL}  : Threshold for slow test warning in seconds (default 10)
  458 
  459     ${WHITE}Enterprise options${NORMAL}
  460     ${GRAY}--plugindir ${BROWN}<path>${NORMAL}                : Define path of available plugins
  461     ${GRAY}--upload${NORMAL}                          : Upload data to central node
  462 
  463     More options available. Run '$0 show options', or use the man page.
  464 
  465 
  466 "
  467 
  468         if [ ${WRONGOPTION} -eq 1 ]; then
  469             echo "  ${RED}Error${NORMAL}: ${WHITE}Invalid option '${WRONGOPTION_value}'${NORMAL}"
  470         else
  471             if [ ${VIEWHELP} -eq 0 ]; then
  472                 echo "  ${RED}No command provided.${WHITE} Exiting..${NORMAL}"
  473                 echo ""
  474             fi
  475         fi
  476         echo ""
  477         # Cleanup PID file if we drop out earlier
  478         RemovePIDFile
  479         # Exit with exit code 1
  480         exit 64
  481     fi
  482 #
  483 #################################################################################
  484 #
  485     if [ ${PRIVILEGED} -eq 0 -a ${CHECK} -eq 1 -a ${QUIET} -eq 0 ]; then
  486         printf "%s" "${WHITE}
  487   ###################################################################
  488   #                                                                 #
  489   #   ${PURPLE}NON-PRIVILEGED SCAN MODE${WHITE}                                      #
  490   #                                                                 #
  491   ###################################################################
  492 ${NORMAL}
  493   ${YELLOW}NOTES:${NORMAL}
  494   --------------
  495   ${WHITE}*${NORMAL} Some tests will be skipped (as they require root permissions)
  496   ${WHITE}*${NORMAL} Some tests might fail silently or give different results
  497 
  498 "
  499         sleep 3
  500         if [ -z "${LOGFILE}" -o "${LOGFILE}" = "/dev/null" ]; then
  501             printf "%s" "
  502   ${RED}WARNING:${NORMAL}
  503   ${WHITE}*${NORMAL} No suggestions or warnings will be displayed in report (due to missing log file)"
  504         fi
  505     fi
  506 #
  507 #################################################################################
  508 #
  509 # OS Detection
  510 #
  511 #################################################################################
  512 #
  513     SafePerms ${INCLUDEDIR}/osdetection
  514     . ${INCLUDEDIR}/osdetection
  515     Display --indent 2 --text "- Detecting OS... " --result "${STATUS_DONE}" --color GREEN
  516 
  517     # Check hostname
  518     case ${OS} in
  519         HP-UX)
  520                     HOSTNAME=$(hostname) ;;
  521         Solaris)
  522                     HOSTNAME=$(uname -n) ;;
  523         *)
  524                     HOSTNAME=$(hostname -s 2> /dev/null) ;;
  525     esac
  526     if [ -z "${HOSTNAME}" ]; then
  527         HOSTNAME=$(hostname 2> /dev/null)
  528         if [ -z "${HOSTNAME}" ]; then HOSTNAME="no-hostname"; fi
  529     fi
  530     FQDN=$(hostname 2> /dev/null)
  531     if [ "${OS}" = "Linux" -a "${HOSTNAME}" = "${FQDN}" ]; then
  532         FQDN=$(hostname -f 2> /dev/null)
  533     fi
  534 
  535 #
  536 #################################################################################
  537 #
  538 # Clear log and report files
  539 #
  540 #################################################################################
  541 #
  542     # Clear log file and test if it's writable
  543     CDATE=$(date "+%Y-%m-%d %H:%M:%S")
  544     if [ ${LOGTEXT} -eq 1 ]; then echo "${CDATE} Starting ${PROGRAM_NAME} ${PROGRAM_VERSION} with PID ${OURPID}, build date ${PROGRAM_RELEASE_DATE}" > ${LOGFILE}; fi
  545     if [ $? -gt 0 ]; then
  546         Display --indent 2 --text "- Clearing log file (${LOGFILE})... " --result "${STATUS_WARNING}" --color RED
  547         echo "${WARNING}Fatal error${NORMAL}: problem while writing to log file. Check location and permissions."
  548         RemovePIDFile
  549         exit 1
  550     fi
  551     LogTextBreak
  552     LogText "### ${PROGRAM_COPYRIGHT} ###"
  553 
  554     # Clear report file (to avoid appending to an existing file)
  555     if [ ${CREATE_REPORT_FILE} -eq 1 ]; then echo "# ${PROGRAM_NAME} Report" > ${REPORTFILE}; fi
  556     Report "report_version_major=${REPORT_version_major}"
  557     Report "report_version_minor=${REPORT_version_minor}"
  558     CDATE=$(date "+%F %H:%M:%S")
  559     Report "report_datetime_start=${CDATE}"
  560     Report "auditor=${AUDITORNAME}"
  561     Report "lynis_version=${PROGRAM_VERSION}"
  562     Report "os=${OS}"
  563     Report "os_name=${OS_NAME}"
  564     Report "os_fullname=${OS_FULLNAME}"
  565     Report "os_version=${OS_VERSION}"
  566     if [ "${OS}" = "Linux" ]; then Report "linux_version=${LINUX_VERSION}"; fi
  567     if [ -n "${OS_KERNELVERSION}" ]; then Report "os_kernel_version=${OS_KERNELVERSION}"; fi
  568     if [ -n "${OS_KERNELVERSION_FULL}" ]; then Report "os_kernel_version_full=${OS_KERNELVERSION_FULL}"; fi
  569 
  570     Report "hostname=${HOSTNAME}"
  571 
  572     if [ -z "${HOSTNAME}" ]; then
  573         HOSTNAME="no-hostname"
  574         LogText "Info: could not find a hostname, using 'no-hostname' instead"
  575         ReportSuggestion "LYNIS" "Check your hostname configuration" "hostname -s"
  576     fi
  577     Report "test_category=${TEST_CATEGORY_TO_CHECK}"
  578     Report "test_group=${TEST_GROUP_TO_CHECK}"
  579 
  580 #
  581 #################################################################################
  582 #
  583 # Read profile, set code checks, define language
  584 #
  585 #################################################################################
  586 #
  587     ParseProfiles
  588 
  589     # Define if we keep working in strict mode (development)
  590     if [ ${SET_STRICT} -eq 0 ]; then
  591         set +u  # Allow uninitialized variables
  592     else
  593         set -u  # Do not allow uninitialized variables
  594     fi
  595 
  596     # Import a different language when configured
  597     if [ ! "${LANGUAGE}" = "en" ]; then
  598         LogText "Language is set to ${LANGUAGE}"
  599         Display --indent 2 --text "- Detecting language and localization" --result "${LANGUAGE}" --color WHITE
  600         if [ ! -f ${DBDIR}/languages/${LANGUAGE} ]; then
  601             Display --indent 4 --text "${YELLOW}Notice:${NORMAL} no language file found for '${LANGUAGE}' (tried: ${DBDIR}/languages/${LANGUAGE})"
  602             if IsDeveloperVersion; then Display --indent 4 --text "See https://github.com/CISOfy/lynis-sdk/blob/master/documentation/10-translations.md for more details to help translate Lynis"; fi
  603             sleep 5
  604         else
  605             if SafeFile "${DBDIR}/languages/${LANGUAGE}"; then
  606                 LogText "Importing language file (${DBDIR}/languages/${LANGUAGE})"
  607                 . ${DBDIR}/languages/${LANGUAGE}
  608                 # Check for missing translations if we are a pre-release or less than a week old
  609                 if grep -E -q -s "^#" ${DBDIR}/languages/${LANGUAGE}; then
  610                     TIME_DIFFERENCE_CHECK=604800 # 1 week
  611                     RELEASE_PLUS_TIMEDIFF=$((PROGRAM_RELEASE_TIMESTAMP + TIME_DIFFERENCE_CHECK))
  612                     if IsDeveloperVersion || [ ${NOW} -lt ${RELEASE_PLUS_TIMEDIFF} ]; then
  613                         Display --indent 4 --text "Translation file (db/languages/${LANGUAGE}) needs an update" --result "OUTDATED" --color RED
  614                         Display --indent 4 --text "======================================================================="
  615                         Display --indent 4 --text "Help other users and translate the missing lines:"
  616                         Display --indent 4 --text "1) Go to: https://github.com/CISOfy/lynis/edit/master/db/languages/${LANGUAGE}"
  617                         Display --indent 4 --text "2) Translate (some of) the lines starting with a hash (#) and remove the leading hash"
  618                         Display --indent 4 --text "3) Commit the changes"
  619                         Display --indent 4 --text "Thank you!"
  620                         Display --indent 4 --text "Note: no lines with a hash? Look if the file recently has been changed by another translator."
  621                         Display --indent 4 --text "======================================================================="
  622                         sleep 30
  623                     fi
  624                 fi
  625             else
  626                 LogText "Could not import language file due to incorrect permissions"
  627             fi
  628 
  629         fi
  630     fi
  631     LogTextBreak
  632 
  633     # Pre-execution tests
  634     if [ ${UPLOAD_DATA} -eq 1 -a -z "${LICENSE_KEY}" ]; then DisplayError "${ERROR_NO_LICENSE}" 64; fi
  635     if [ ${UPLOAD_DATA} -eq 1 -a -z "${UPLOAD_SERVER}" ]; then DisplayError "${ERROR_NO_UPLOAD_SERVER}" 64; fi
  636 
  637 #
  638 #################################################################################
  639 #
  640 # Plugins
  641 #
  642 #################################################################################
  643 #
  644     # Plugin directory test
  645     if [ -z "${PLUGINDIR}" ]; then
  646         #LogText "Result: Searching for plugindir"
  647         tPLUGIN_TARGETS="/usr/local/lynis/plugins /usr/local/share/lynis/plugins /usr/share/lynis/plugins /etc/lynis/plugins ./plugins"
  648         for DIR in ${tPLUGIN_TARGETS}; do
  649             if [ -d ${DIR} -a -z "${PLUGINDIR}" ]; then
  650                 PLUGINDIR=${DIR}
  651                 Debug "Result: found plugindir ${PLUGINDIR}"
  652             fi
  653         done
  654     else
  655         Debug "Plugin was already set before to ${PLUGINDIR} (most likely via program argument or profile)"
  656     fi
  657 
  658     # Drop out if our plugin directory can't be found
  659     if [ -z "${PLUGINDIR}" -o ! -d ${PLUGINDIR} ]; then
  660         echo "Fatal error: can't find plugin directory ${PLUGINDIR}"
  661         echo "Make sure to execute ${PROGRAM_NAME} from untarred directory or check your installation."
  662         exit 1
  663     fi
  664 
  665 #
  666 #################################################################################
  667 #
  668 # Show program information to display
  669 #
  670 #################################################################################
  671 #
  672     if [ ${QUIET} -eq 0 -a ${SHOW_PROGRAM_DETAILS} -eq 1 ]; then
  673         echo ""
  674         echo "  ---------------------------------------------------"
  675         echo "  Program version:           ${PROGRAM_VERSION}"
  676         echo "  Operating system:          ${OS}"
  677         echo "  Operating system name:     ${OS_NAME}"
  678         echo "  Operating system version:  ${OS_VERSION}"
  679         LogText "EOL check: ${EOL}"
  680         if [ ${EOL} -eq 1 ]; then
  681             echo "  End-of-life:               ${WARNING}YES${NORMAL}"
  682             ReportWarning "GEN-0010" "This version ${OS_VERSION} is marked end-of-life as of ${EOL_DATE}"
  683         elif [ ${EOL} -eq 255 ]; then
  684             # TODO - mark as item where community can provide help
  685             LogText "Note: the end-of-life of '${OS_FULLNAME}' could not be checked. Entry missing in software-eol.db?"
  686         fi
  687 
  688         if [ -n "${OS_MODE}" ]; then echo "  Operating system mode:     ${OS_MODE}"; fi
  689         echo "  Kernel version:            ${OS_KERNELVERSION}"
  690         echo "  Hardware platform:         ${HARDWARE}"
  691         echo "  Hostname:                  ${HOSTNAME}"
  692         echo "  ---------------------------------------------------"
  693         echo "  Profiles:                  ${PROFILES}"
  694         echo "  Log file:                  ${LOGFILE}"
  695         echo "  Report file:               ${REPORTFILE}"
  696         echo "  Report version:            ${REPORT_version}"
  697         echo "  Plugin directory:          ${PLUGINDIR}"
  698         echo "  ---------------------------------------------------"
  699         echo "  Auditor:                   ${AUDITORNAME}"
  700         echo "  Language:                  ${LANGUAGE}"
  701         echo "  Test category:             ${TEST_CATEGORY_TO_CHECK}"
  702         echo "  Test group:                ${TEST_GROUP_TO_CHECK}"
  703         if [ ! "${ROOTDIR}" = "/" ]; then echo "  Root directory (custom):   ${ROOTDIR}"; fi
  704         echo "  ---------------------------------------------------"
  705     fi
  706 
  707     LogText "Program version:           ${PROGRAM_VERSION}"
  708     LogText "Operating system:          ${OS}"
  709     LogText "Operating system name:     ${OS_NAME}"
  710     LogText "Operating system version:  ${OS_VERSION}"
  711     if [ -n "${OS_MODE}" ]; then LogText "Operating system mode:     ${OS_MODE}"; fi
  712     LogText "Kernel version:            ${OS_KERNELVERSION}"
  713     if [ -n "${OS_KERNELVERSION_FULL}" ]; then
  714         LogText "Kernel version (full):     ${OS_KERNELVERSION_FULL}"
  715     fi
  716     LogText "Hardware platform:         ${HARDWARE}"
  717     LogText "-----------------------------------------------------"
  718     LogText "Hostname:                  ${HOSTNAME}"
  719     LogText "Auditor:                   ${AUDITORNAME}"
  720     LogText "Profiles:                  ${PROFILES}"
  721     LogText "Work directory:            ${WORKDIR}"
  722     LogText "Include directory:         ${INCLUDEDIR}"
  723     LogText "Plugin directory:          ${PLUGINDIR}"
  724     LogText "-----------------------------------------------------"
  725     LogText "Log file:                  ${LOGFILE}"
  726     LogText "Report file:               ${REPORTFILE}"
  727     LogText "Report version:            ${REPORT_version}"
  728     LogText "-----------------------------------------------------"
  729     LogText "Test category:             ${TEST_CATEGORY_TO_CHECK}"
  730     LogText "Test group:                ${TEST_GROUP_TO_CHECK}"
  731     LogText "BusyBox used:              ${SHELL_IS_BUSYBOX}"
  732 
  733     Report "plugin_directory=${PLUGINDIR}"
  734 
  735     LogTextBreak
  736 #
  737 #################################################################################
  738 #
  739 # Check for program update (and friendly force people to upgrade)
  740 #
  741 #################################################################################
  742 #
  743     LogText "Test: Checking for program update..."
  744     UPDATE_AVAILABLE=0
  745 
  746     if [ ${SKIP_UPGRADE_TEST} -eq 1 ]; then
  747         LogText "Upgrade test skipped due profile option set (skip_upgrade_test)"
  748         PROGRAM_LV="${PROGRAM_AC}"
  749     else
  750         CheckUpdates
  751     fi
  752 
  753     if [ -z "${PROGRAM_AC}" -o -z "${PROGRAM_LV}" ]; then
  754         Display --indent 2 --text "- Program update status... " --result "${STATUS_UNKNOWN}" --color YELLOW
  755         LogText "Result: Update check failed. No network connection?"
  756         LogText "Info: to perform an automatic update check, outbound DNS connections should be allowed (TXT record)."
  757         # Set both to safe values
  758         PROGRAM_AC=0; PROGRAM_LV=0
  759     else
  760         LogText "Current installed version  : ${PROGRAM_AC}"
  761         LogText "Latest stable version      : ${PROGRAM_LV}"
  762         if [ ${PROGRAM_LV} -gt ${PROGRAM_AC} ]; then
  763             # Check if current version is REALLY outdated (10 versions ago)
  764             PROGRAM_MINVERSION=$((PROGRAM_LV - 10))
  765             LogText "Minimum required version   : ${PROGRAM_MINVERSION}"
  766             if [ ${PROGRAM_MINVERSION} -gt ${PROGRAM_AC} ]; then
  767                 Display --indent 2 --text "- Program update status... " --result "${STATUS_WARNING}" --color RED
  768                 LogText "Result: This version is VERY outdated. Newer ${PROGRAM_NAME} release available!"
  769                 ReportWarning "LYNIS" "Version of Lynis is very old and should be updated"
  770                 Report "lynis_update_available=1"
  771                 UPDATE_AVAILABLE=1
  772             else
  773                 Display --indent 2 --text "- Program update status... " --result "${STATUS_UPDATE_AVAILABLE}" --color YELLOW
  774                 LogText "Result: newer ${PROGRAM_NAME} release available!"
  775                 ReportSuggestion "LYNIS" "Version of Lynis outdated, consider upgrading to the latest version"
  776                 Report "lynis_update_available=1"
  777                 UPDATE_AVAILABLE=1
  778             fi
  779         else
  780             if [ ${UPDATE_CHECK_SKIPPED} -eq 0 ]; then
  781                 Display --indent 2 --text "- Program update status... " --result "${STATUS_NO_UPDATE}" --color GREEN
  782                 LogText "No ${PROGRAM_NAME} update available."
  783                 Report "lynis_update_available=0"
  784             else
  785                 Display --indent 2 --text "- Program update status... " --result "${STATUS_SKIPPED}" --color YELLOW
  786                 LogText "Update check skipped due to constraints (e.g. missing dig binary)"
  787                 Report "lynis_update_available=-1"
  788             fi
  789         fi
  790     fi
  791 
  792     # Test for older releases, without testing via update mechanism
  793     if [ "${OS}" = "Solaris" ]; then
  794         NOW=$(nawk 'BEGIN{print srand()}')
  795     else
  796         NOW=$(date "+%s")
  797     fi
  798 
  799     OLD_RELEASE=0
  800     TIME_DIFFERENCE_CHECK=10368000 # 4 months
  801     RELEASE_PLUS_TIMEDIFF=$((PROGRAM_RELEASE_TIMESTAMP + TIME_DIFFERENCE_CHECK))
  802     if [ ${NOW} -gt ${RELEASE_PLUS_TIMEDIFF} ]; then
  803         # Show if release is old, only if we didn't show it with normal update check
  804         if [ ${UPDATE_AVAILABLE} -eq 0 ]; then
  805             ReportSuggestion "LYNIS" "This release is more than 4 months old. Check the website or GitHub to see if there is an update available."
  806         fi
  807         OLD_RELEASE=1
  808     fi
  809 
  810     # Show on screen message if release is very outdated (unless --quiet/--silent is used)
  811     if [ ${UPDATE_AVAILABLE} -eq 1 -a ${QUIET} -eq 0 ]; then
  812         echo ""
  813         echo "      ==============================================================================="
  814         echo "        ${CYAN}${PROGRAM_NAME} ${TEXT_UPDATE_AVAILABLE}${NORMAL}"
  815         echo "      ==============================================================================="
  816         echo ""
  817         if [ ${OLD_RELEASE} -eq 1 ]; then
  818             echo "        ${YELLOW}Current version is more than 4 months old${NORMAL}"
  819             echo ""
  820         fi
  821         if [ ${PROGRAM_LV} -gt 0 ]; then
  822             echo "        Current version : ${YELLOW}${PROGRAM_AC}${NORMAL}   Latest version : ${GREEN}${PROGRAM_LV}${NORMAL}"
  823             echo ""
  824         fi
  825         echo "        ${WHITE}Please update to the latest version.${NORMAL}"
  826         echo "        New releases include additional features, bug fixes, tests, and baselines.${NORMAL}"
  827         echo ""
  828         echo "        Download the latest version:"
  829         echo ""
  830         echo "        Packages (DEB/RPM) -  https://packages.cisofy.com"
  831         echo "        Website (TAR)      -  https://cisofy.com/downloads/"
  832         echo "        GitHub (source)    -  https://github.com/CISOfy/lynis"
  833         echo ""
  834         echo "      ==============================================================================="
  835         echo ""
  836         sleep 5
  837     fi
  838 
  839     LogTextBreak
  840 #
  841 #################################################################################
  842 #
  843     # Check which binaries are available to the scanning process
  844     if [ -f ${INCLUDEDIR}/binaries ]; then
  845         SafePerms ${INCLUDEDIR}/binaries
  846         . ${INCLUDEDIR}/binaries
  847     fi
  848     LogTextBreak
  849 #
  850 #################################################################################
  851 #
  852     # Test if we have a package manager available by testing for a dummy package (should not exist)
  853     if PackageIsInstalled "__dummy__"; then
  854         HAS_PACKAGE_MANAGER=1
  855         LogText "Informational: package manager is used"
  856     else
  857         LogText "Informational: no known package manager for this system"
  858     fi
  859 
  860     # Use hardware detection capabilities
  861     IsVirtualMachine
  862     if IsContainer; then
  863         LogText "Result: ${PROGRAM_NAME} is running in container (${CONTAINER_TYPE})"
  864         Report "container=1"
  865         Report "container_type=${CONTAINER_TYPE}"
  866     else
  867         LogText "Result: ${PROGRAM_NAME} is not running in container"
  868         Report "container=0"
  869     fi
  870     IsNotebook
  871 #
  872 #################################################################################
  873 #
  874     # Check for systemd active
  875     if [ -d /run/systemd/system ]; then
  876         LogText "Result: system is using systemd"
  877         HAS_SYSTEMD=1
  878         Report "systemd=1"
  879     else
  880         LogText "Result: systemd not found"
  881         HAS_SYSTEMD=0
  882         Report "systemd=0"
  883     fi
  884 #
  885 #################################################################################
  886 #
  887     if IsVerbose; then
  888         InsertSection "${SECTION_PROGRAM_DETAILS}"
  889         Display --indent 2 --text "- ${GEN_VERBOSE_MODE}" --result "${STATUS_YES}" --color GREEN
  890         if IsDebug; then
  891             Display --indent 2 --text "- ${GEN_DEBUG_MODE}" --result "${STATUS_YES}" --color GREEN
  892         else
  893             Display --indent 2 --text "- ${GEN_DEBUG_MODE}" --result "${STATUS_NO}" --color RED
  894         fi
  895     fi
  896 #
  897 #################################################################################
  898 #
  899     # Plugins
  900     if [ ${SKIP_PLUGINS} -eq 0 ]; then
  901 
  902         N_PLUGIN=0
  903         N_PLUGIN_ENABLED=0
  904 
  905         # Plugins function
  906         RunPlugins() {
  907             if [ $# -eq 0 ]; then echo "RunPlugins should be started with phase number"; ExitFatal; fi
  908             PLUGIN_PHASE=$1
  909             if [ ${PLUGIN_PHASE} -eq 0 -o ${PLUGIN_PHASE} -gt 2 ]; then echo "Incorrect phase number when calling RunPlugins"; ExitFatal; fi
  910             LogTextBreak
  911             InsertPluginSection "Plugins (${GEN_PHASE} ${PLUGIN_PHASE})"
  912             if [ ${PLUGIN_PHASE} -eq 1 ]; then
  913                 Display --text "${NOTE_PLUGINS_TAKE_TIME}"
  914                 Display --text " "
  915                 LogText "Searching plugins..."
  916             fi
  917 
  918             # Search plugins
  919             FIND_PLUGINS=$(find ${PLUGINDIR} -type f -name "plugin_[a-z]*_phase${PLUGIN_PHASE}" | sort)
  920             for PLUGIN_FILE in ${FIND_PLUGINS}; do
  921                 LogText "Found plugin file: ${PLUGIN_FILE}"
  922                 # Double check if output is a valid file name
  923                 if [ -f ${PLUGIN_FILE} ]; then
  924                     FIND2=$(grep "^# PLUGIN_NAME=" ${PLUGIN_FILE} | awk -F= '{ print $2 }')
  925                     if [ ! "${FIND2}" = "" -a ! "${FIND2}" = "[plugin_name]" ]; then
  926                         if [ ${PLUGIN_PHASE} -eq 1 ]; then N_PLUGIN=$((N_PLUGIN + 1)); fi
  927                         # Check if the plugin is enabled in any of the profiles
  928                         PLUGIN_ENABLED_STATE=0
  929                         for PROFILE in ${PROFILES}; do
  930                             LogText "Action: checking plugin status in profile: ${PROFILE}"
  931                             FIND3=$(grep "^plugin=${FIND2}" ${PROFILE})
  932                             if [ -n "${FIND3}" ]; then
  933                                 FOUND=0
  934                                 for I in ${DISABLED_PLUGINS}; do
  935                                     if [ "${I}" = "${FIND2}" ]; then
  936                                         FOUND=1
  937                                         LogText "Result: plugin ${FIND2} is specifically disabled"
  938                                     fi
  939                                 done
  940                                 if [ ${FOUND} -eq 0 ]; then
  941                                     LogText "Result: plugin enabled in profile (${PROFILE})"
  942                                     PLUGIN_ENABLED_STATE=1
  943                                 fi
  944                             fi
  945                         done
  946                         if [ ${PLUGIN_ENABLED_STATE} -eq 1 ]; then
  947                             LogText "Result: plugin ${FIND2} is enabled"
  948                             PLUGINFILE="${PLUGINDIR}/plugin_${FIND2}_phase${PLUGIN_PHASE}"
  949                             if [ -f ${PLUGINFILE} ]; then
  950                                 PLUGIN_VERSION=$(grep "^# PLUGIN_VERSION=" ${PLUGIN_FILE} | awk -F= '{ print $2 }')
  951                                 PLUGIN_VERSION_NODOTS=$(echo ${PLUGIN_VERSION} | sed 's/.//g')
  952                                 if SafePerms ${PLUGINFILE}; then
  953                                     LogText "Including plugin file: ${PLUGINFILE} (version: ${PLUGIN_VERSION})"
  954                                     Report "plugin_enabled_phase${PLUGIN_PHASE}[]=${FIND2}|${PLUGIN_VERSION}|"
  955                                     if [ ${PLUGIN_PHASE} -eq 1 ]; then N_PLUGIN_ENABLED=$((N_PLUGIN_ENABLED + 1)); fi
  956                                     Display --indent 2 --text "- ${CYAN}Plugin${NORMAL}: ${WHITE}${FIND2}${NORMAL}"
  957                                     if [ ${PLUGIN_PHASE} -eq 1 ]; then Progress "    ["; fi
  958                                     . ${PLUGINFILE}
  959                                     if [ ${PLUGIN_PHASE} -eq 1 ]; then Progress "]"; Progress --finish; fi
  960                                     LogTextBreak
  961                                     LogText "Result: ${FIND2} plugin (phase ${PLUGIN_PHASE}) finished"
  962                                 else
  963                                     LogText "Plugin ${FIND2}: Skipped (bad file permissions, should be 644, 640, 600 or 400)"
  964                                 fi
  965                             else
  966                                 LogText "Plugin ${FIND2}: Skipped for phase ${PLUGIN_PHASE} (no file found: ${PLUGINFILE})"
  967                             fi
  968                         else
  969                             LogText "Plugin ${FIND2}: Skipped (not enabled)"
  970                         fi
  971                     else
  972                         LogText "Skipping plugin file ${PLUGIN_FILE} (no valid plugin name found)"
  973                     fi
  974                 fi
  975                 LogText "--"
  976             done
  977             LogText "Result: Found ${N_PLUGIN} plugins of which ${N_PLUGIN_ENABLED} are enabled"
  978             LogText "Result: Plugins phase ${PLUGIN_PHASE} finished"
  979         }
  980         RunPlugins 1
  981 
  982         if [ ${N_PLUGIN_ENABLED} -eq 0 ]; then
  983             Display --indent 2 --text "- ${GEN_PLUGINS_ENABLED}" --result "${STATUS_NONE}" --color WHITE
  984             Report "plugins_enabled=0"
  985         else
  986             Report "plugins_enabled=1"
  987         fi
  988     fi
  989 #
  990 #################################################################################
  991 #
  992     # Get host ID
  993     LogTextBreak
  994     GetHostID
  995     LogText "hostid-generation: method ${HOSTID_GEN}"
  996     LogText "hostid2-generation: method ${HOSTID2_GEN}"
  997     # Check if result is not empty (no blank, or hash of blank value, or minus, or zeros)
  998     case ${HOSTID} in
  999         "" | "-" | "adc83b19e793491b1c6ea0fd8b46cd9f32e592fc" | "6ef1338f520d075957424741d7ed35ab5966ae97")
 1000             LogText "Info: no HostID found or invalid one"
 1001         ;;
 1002         *)
 1003             LogText "Info: HostID ${HOSTID} looks to be valid"
 1004             Report "hostid=${HOSTID}"
 1005         ;;
 1006     esac
 1007 
 1008     if [ -n "${HOSTID2}" ]; then
 1009         Report "hostid2=${HOSTID2}"
 1010     fi
 1011     if [ -n "${MACHINEID}" ]; then
 1012         LogText "Info: found a machine ID ${MACHINEID}"
 1013         Report "machineid=${MACHINEID}"
 1014     else
 1015         LogText "Info: no machine ID found"
 1016     fi
 1017 #
 1018 #################################################################################
 1019 #
 1020 
 1021     if [ ${RUN_TESTS} -eq 1 ]; then
 1022 
 1023         LogTextBreak
 1024         # Test sections
 1025         if [ "${TEST_GROUP_TO_CHECK}" = "all" ]; then
 1026             LogText "Info: perform tests from all categories"
 1027 
 1028             INCLUDE_TESTS="boot_services kernel memory_processes authentication shells \
 1029                            filesystems usb storage storage_nfs nameservices dns ports_packages networking printers_spoolers \
 1030                            mail_messaging firewalls webservers ssh snmp databases ldap php squid logging \
 1031                            insecure_services banners scheduling accounting time crypto virtualization containers \
 1032                            mac_frameworks file_integrity tooling malware file_permissions homedirs \
 1033                            kernel_hardening hardening"
 1034         else
 1035             INCLUDE_TESTS="${TEST_GROUP_TO_CHECK}"
 1036             LogText "Info: only performing tests from groups: ${TEST_GROUP_TO_CHECK}"
 1037         fi
 1038 
 1039         # Include available tests
 1040         for INCLUDE_TEST in ${INCLUDE_TESTS}; do
 1041             INCLUDE_FILE="${INCLUDEDIR}/tests_${INCLUDE_TEST}"
 1042             if [ -f ${INCLUDE_FILE} ]; then
 1043                 if SafeFile ${INCLUDE_FILE}; then
 1044                     . ${INCLUDE_FILE}
 1045                 else
 1046                     LogText "Exception: skipping test category ${INCLUDE_TEST}, file ${INCLUDE_FILE} has bad permissions (should be 640, 600 or 400)"
 1047                     ReportWarning "NONE" "Invalid permissions on tests file tests_${INCLUDE_TEST}"
 1048                     # Insert a section and warn user also on screen
 1049                     InsertSection "${SECTION_GENERAL}"
 1050                     Display --indent 2 --text "- Running test category ${INCLUDE_TEST}... " --result "${STATUS_SKIPPED}" --color RED
 1051                 fi
 1052             else
 1053                 echo "Error: Can't find file (category: ${INCLUDE_TEST})"
 1054             fi
 1055         done
 1056     fi
 1057 #
 1058 #################################################################################
 1059 #
 1060 
 1061     if [ ${RUN_TESTS} -eq 1 ]; then
 1062 
 1063         InsertSection "${SECTION_CUSTOM_TESTS}"
 1064         LogText "Test: Checking for tests_custom file"
 1065         # Custom tests
 1066         if [ -f ${INCLUDEDIR}/tests_custom ]; then
 1067             LogText "Result: tests_custom file found in include directory"
 1068             if SafePerms ${INCLUDEDIR}/tests_custom; then
 1069                 Display --indent 2 --text "- Start custom tests... "
 1070                 LogText "Result: file permissions fine, running custom tests"
 1071                 . ${INCLUDEDIR}/tests_custom
 1072             else
 1073                 LogText "Exception: skipping custom tests, file has bad permissions (should be 640, 600 or 400)"
 1074                 ReportWarning "NONE" "Invalid permissions on custom tests file"
 1075                 Display --indent 2 --text "- Running custom tests... " --result "${STATUS_WARNING}" --color RED
 1076             fi
 1077         else
 1078             Display --indent 2 --text "- Running custom tests... " --result "${STATUS_NONE}" --color WHITE
 1079         fi
 1080     fi
 1081 #
 1082 #################################################################################
 1083 #
 1084 # Run helpers
 1085 #
 1086 #################################################################################
 1087 #
 1088     if [ ${RUN_HELPERS} -eq 1 ]; then
 1089         if [ ! "${HELPER}" = "" ]; then
 1090             LogText "Helper tool is $HELPER"
 1091             if [ -f ${INCLUDEDIR}/helper_${HELPER} ]; then
 1092                 SafePerms ${INCLUDEDIR}/helper_${HELPER}
 1093                 LogText "Running helper tool ${HELPER} with params: ${HELPER_PARAMS}"
 1094                 InsertPluginSection "Helper: ${HELPER}"
 1095                 . ${INCLUDEDIR}/helper_${HELPER} ${HELPER_PARAMS}
 1096             else
 1097                 echo "Error, could not find helper"
 1098             fi
 1099         fi
 1100     fi
 1101 #
 1102 #################################################################################
 1103 #
 1104 # Run phase 2 of plugins
 1105 #
 1106 #################################################################################
 1107 #
 1108     if [ ${SKIP_PLUGINS} -eq 0 ]; then
 1109         RunPlugins 2
 1110         if [ ${N_PLUGIN_ENABLED} -gt 1 ]; then
 1111             Display --indent 2 --text "- Plugins (phase 2)" --result "${STATUS_DONE}" --color GREEN
 1112         fi
 1113     fi
 1114 #
 1115 #################################################################################
 1116 #
 1117 # Show test results overview
 1118 #
 1119 #################################################################################
 1120 #
 1121     # Store total performed tests
 1122     Report "lynis_tests_done=${CTESTS_PERFORMED}"
 1123     CDATE=$(date "+%F %H:%M:%S")
 1124     Report "report_datetime_end=${CDATE}"
 1125 
 1126     # Show report
 1127     if [ -f ${INCLUDEDIR}/report ]; then SafePerms ${INCLUDEDIR}/report; . ${INCLUDEDIR}/report; fi
 1128 
 1129     # Show tool tips
 1130     if [ -f ${INCLUDEDIR}/tool_tips ]; then SafePerms ${INCLUDEDIR}/tool_tips; . ${INCLUDEDIR}/tool_tips; fi
 1131 
 1132     LogText "================================================================================"
 1133     LogText "Tests performed:     ${CTESTS_PERFORMED}"
 1134     LogText "Total tests:         ${TOTAL_TESTS}"
 1135     LogText "Active plugins:      ${N_PLUGIN_ENABLED}"
 1136     LogText "Total plugins:       ${N_PLUGIN}"
 1137     LogText "================================================================================"
 1138     Report "tests_executed=${TESTS_EXECUTED}"
 1139     Report "tests_skipped=${TESTS_SKIPPED}"
 1140     Report "finish=true"
 1141 
 1142     # Upload data
 1143     if [ ${UPLOAD_DATA} -eq 1 ]; then
 1144         if [ -f ${INCLUDEDIR}/data_upload ]; then
 1145             SafePerms ${INCLUDEDIR}/data_upload
 1146             . ${INCLUDEDIR}/data_upload
 1147         else
 1148             echo "Fatal error: can't find upload_data script"
 1149         fi
 1150     fi
 1151 
 1152     LogText "${PROGRAM_NAME} ${PROGRAM_VERSION}"
 1153     LogText "${PROGRAM_COPYRIGHT}"
 1154     LogText "${PROGRAM_EXTRAINFO}"
 1155     LogText "Program ended successfully"
 1156     LogText "================================================================================"
 1157 
 1158     # Tool tips
 1159 
 1160     if [ ${QUIET} -eq 0 ]; then
 1161 
 1162         if [ -z "${CUSTOM_PROFILE}" ]; then DisplayToolTip "Enhance ${PROGRAM_NAME} audits by adding your settings to custom.prf (see ${DEFAULT_PROFILE} for all settings)"; fi
 1163     fi
 1164 
 1165     # Clean exit (Delete PID file)
 1166     if [ ${TOTAL_WARNINGS} -gt 0 ]; then
 1167         # Use exit code 78 if we found any warnings (and enabled)
 1168         if [ ${ERROR_ON_WARNINGS} -eq 1 ]; then
 1169             ExitCustom 78
 1170         else
 1171             ExitClean
 1172         fi
 1173     else
 1174         ExitClean
 1175     fi
 1176 
 1177     # The End
 1178 
 1179 #
 1180 #================================================================================
 1181 # Lynis - Copyright 2007-2021, Michael Boelen, CISOfy - https://cisofy.com