2014-08-26 17:33:55 +02:00
#!/bin/sh
#################################################################################
#
# Lynis
# ------------------
#
2016-03-17 13:35:37 +01:00
# Copyright 2007-2013, Michael Boelen
2019-01-31 14:47:35 +01:00
# 2013-now, CISOfy
2016-08-22 21:45:48 +02:00
#
2015-07-22 16:27:17 +02:00
# Web site: https://cisofy.com
2014-08-26 17:33:55 +02:00
#
# Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
# welcome to redistribute it under the terms of the GNU General Public License.
# See LICENSE file for usage of this software.
#
2014-12-09 00:44:51 +01:00
# Lynis is licensed under GPLv3, Plugins are licensed differently (see plugins)
#
2014-08-26 17:33:55 +02:00
#################################################################################
#
# Lynis is an automated auditing tool for Unix based operating systems.
#
#################################################################################
2017-03-09 12:29:09 +01:00
#
2019-07-14 11:50:02 +02:00
# In Solaris /bin/sh is not POSIX, but /usr/xpg4/bin/sh is.
# Switch to /usr/xpg4/bin/sh if it exists and we are not already running it.
if [ "$(uname)" = "SunOS" ]; then
test "$_" != "/usr/xpg4/bin/sh" && test -f /usr/xpg4/bin/sh && exec /usr/xpg4/bin/sh "$0" "$@"
fi
2019-07-03 15:07:46 +02:00
#
#################################################################################
#
2019-07-14 11:50:02 +02:00
# Code quality: don't allow using undefined variables
# Notes: $_ may be empty on FreeBSD
set -o nounset
2017-03-09 12:29:09 +01:00
#
#################################################################################
2014-08-26 17:33:55 +02:00
#
# Program information
2016-04-05 11:28:11 +02:00
PROGRAM_NAME="Lynis"
2016-03-16 20:18:31 +01:00
PROGRAM_AUTHOR="CISOfy"
PROGRAM_AUTHOR_CONTACT="lynis-dev@cisofy.com"
2019-07-15 19:05:57 +02:00
PROGRAM_WEBSITE="https://cisofy.com/lynis/"
2016-04-05 11:28:11 +02:00
# Version details
2019-11-18 11:03:38 +01:00
PROGRAM_RELEASE_DATE="2019-11-18"
PROGRAM_RELEASE_TIMESTAMP=1574071362
2019-08-21 14:51:51 +02:00
PROGRAM_RELEASE_TYPE="pre-release" # pre-release or release
2019-06-29 19:29:42 +02:00
PROGRAM_VERSION="3.0.0"
2016-04-05 11:28:11 +02:00
# Source, documentation and license
PROGRAM_SOURCE="https://github.com/CISOfy/lynis"
2019-07-15 19:05:57 +02:00
PROGRAM_PACKAGE="https://packages.cisofy.com/"
PROGRAM_DOCUMENTATION="https://cisofy.com/docs/"
2019-01-31 14:47:35 +01:00
PROGRAM_COPYRIGHT="2007-2019, ${PROGRAM_AUTHOR} - ${PROGRAM_WEBSITE}"
2016-03-16 20:18:31 +01:00
PROGRAM_LICENSE="${PROGRAM_NAME} comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
2016-04-05 11:28:11 +02:00
welcome to redistribute it under the terms of the GNU General Public License.
See the LICENSE file for details about using this software."
2016-07-26 16:00:36 +02:00
PROGRAM_EXTRAINFO="Enterprise support available (compliance, plugins, interface and tools)"
2016-03-16 20:18:31 +01:00
2014-08-26 17:33:55 +02:00
# Version number of report files (when format changes in future)
REPORT_version_major="1"; REPORT_version_minor="0"
REPORT_version="${REPORT_version_major}.${REPORT_version_minor}"
2016-07-26 15:00:05 +02:00
2016-07-28 11:39:10 +02:00
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
# Configure Include path and files
#
#################################################################################
#
2019-07-10 19:28:26 +02:00
# Check setuid bit
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
2016-05-15 13:41:03 +02:00
# Work directory
2017-03-06 08:41:21 +01:00
WORKDIR=$(pwd)
2016-05-15 13:41:03 +02:00
2015-12-16 13:41:32 +01:00
# Test from which directories we can use all functions and tests
2019-07-25 11:34:58 +02:00
USE_CWD=0
if case "$@" in *--usecwd*) true;; *) false;; esac; then
USE_CWD=1
INCLUDEDIR="./include"
else
INCLUDEDIR=""
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)
for I in ${tINCLUDE_TARGETS}; do
if [ "${I}" = "./include" ]; then
if [ -d "${WORKDIR}/include" ]; then INCLUDEDIR="${WORKDIR}/include"; fi
elif [ -d ${I} -a -z "${INCLUDEDIR}" ]; then
INCLUDEDIR=${I}
fi
done
fi
2015-12-16 13:41:32 +01:00
2019-07-14 11:50:02 +02:00
# Drop out if our include directory can't be found
if [ -z "${INCLUDEDIR}" ]; then
printf "%s" "\nFatal error: can't find include directory\nMake sure to execute ${PROGRAM_NAME} from untarred directory or check your installation."
2016-06-11 14:09:41 +02:00
exit 1
2016-07-12 20:32:15 +02:00
fi
2016-08-09 15:16:13 +02:00
2019-07-14 11:50:02 +02:00
# Test for database directory
2019-07-25 11:34:58 +02:00
if [ ${USE_CWD} -eq 1 ]; then
DBDIR="./db"
else
DBDIR=""; tDB_TARGETS="/usr/local/share/lynis/db /usr/local/lynis/db /usr/share/lynis/db ./db"
for I in ${tDB_TARGETS}; do
if [ "${I}" = "./db" ]; then
if [ -d "${WORKDIR}/db" ]; then DBDIR="${WORKDIR}/db"; fi
elif [ -d ${I} -a -z "${DBDIR}" ]; then
DBDIR="${I}"
fi
done
fi
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
MYID=""
2015-12-16 13:41:32 +01:00
# Check user to determine file permissions later on. If we encounter Solaris, use related id binary instead
2014-08-26 17:33:55 +02:00
if [ -x /usr/xpg4/bin/id ]; then
2016-07-05 12:11:38 +02:00
MYID=$(/usr/xpg4/bin/id -u 2> /dev/null)
2019-07-14 11:50:02 +02:00
elif [ "$(uname)" = "SunOS" ]; then
2016-07-05 12:11:38 +02:00
MYID=$(id | tr '=' ' ' | tr '(' ' ' | awk '{ print $2 }' 2> /dev/null)
else
MYID=$(id -u 2> /dev/null)
2014-08-26 17:33:55 +02:00
fi
2018-03-16 17:25:18 +01:00
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
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2019-07-14 11:50:02 +02:00
# Set basic values and test permissions of the files to include, such as:
# - consts: bin paths, text strings, colors
# - functions: function library
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2019-07-14 11:50:02 +02:00
# Determine if we are root (UID = 0)
if [ ${MYID} -eq 0 ]; then
PRIVILEGED=1
PENTESTINGMODE=0
else
2019-07-17 23:25:40 +02:00
PRIVILEGED=0
# Set to pentesting mode if scan is without root privileges
2019-07-14 11:50:02 +02:00
PENTESTINGMODE=1
fi
2014-08-26 17:33:55 +02:00
# Perform a basic check for permissions. After including functions, using SafePerms()
2019-07-03 15:07:46 +02:00
IGNORE_FILE_PERMISSION_ISSUES=0
2016-05-02 15:04:54 +02:00
FILES_TO_CHECK="consts functions"
2014-09-04 15:35:10 +02:00
2014-08-26 17:33:55 +02:00
ISSUE=0
2016-05-02 15:04:54 +02:00
ISSUE_TYPE=""
2015-04-21 14:12:05 +02:00
SHOWPERMERROR=0
2015-04-19 22:10:51 +02:00
2016-05-02 15:04:54 +02:00
for FILE in ${FILES_TO_CHECK}; do
2016-10-23 16:26:22 +02:00
PERMS=$(ls -l ${INCLUDEDIR}/${FILE} | cut -c 2-10)
GROUPPERMS=$(ls -l ${INCLUDEDIR}/${FILE} | cut -c 5-7)
GROUPOWNERID=$(ls -n ${INCLUDEDIR}/${FILE} | awk '{ print $4 }')
OWNER=$(ls -l ${INCLUDEDIR}/${FILE} | awk -F" " '{ print $3 }')
OWNERID=$(ls -n ${INCLUDEDIR}/${FILE} | awk -F" " '{ print $3 }')
2016-05-02 15:04:54 +02:00
# Check permissions of include/X file (400, 600, 640, 644)
if [ "${PERMS}" = "rwxrwxrwx" ]; then
ISSUE=1; ISSUE_TYPE="perms"; echo "[!] Change file permissions of ${INCLUDEDIR}/${FILE} to 640."; echo " Command: chmod 640 ${INCLUDEDIR}/${FILE}"
elif [ ! "${PERMS}" = "r--------" -a ! "${PERMS}" = "rw-------" -a ! "${PERMS}" = "rw-r-----" -a ! "${PERMS}" = "rw-r--r--" ]; then
# If group ID equals user ID, we consider permissions to be fine (probably default umask)
if [ ! "${GROUPOWNERID}" = "${OWNERID}" ]; then
ISSUE=1; ISSUE_TYPE="perms"; echo "[!] Change file permissions of ${INCLUDEDIR}/${FILE} to 640."; echo " Command: chmod 640 ${INCLUDEDIR}/${FILE}"
2015-04-27 19:43:04 +02:00
fi
fi
2016-05-02 15:04:54 +02:00
# Check if owner of both files is root user, or the same user which is running Lynis (for pentester mode)
if [ ! "${OWNER}" = "root" -a ! "${OWNERID}" = "0" ]; then
2016-05-02 15:08:38 +02:00
if [ ! "${MYID}" = "${OWNERID}" ]; then
2016-05-02 15:04:54 +02:00
ISSUE=1; ISSUE_TYPE="owner"; SHOWPERMERROR=1; ISSUE_FILE="${FILE}"; ISSUE_OWNER="${OWNER}"; ISSUE_OWNERID="${OWNERID}"
2015-04-27 19:43:04 +02:00
fi
fi
2016-05-02 15:04:54 +02:00
done
2016-10-23 16:26:22 +02:00
if [ ${SHOWPERMERROR} -eq 1 ]; then
2017-03-07 20:23:08 +01:00
printf "%s" "
2016-04-04 13:18:35 +02:00
2016-05-02 15:04:54 +02:00
[!] Change ownership of ${INCLUDEDIR}/${ISSUE_FILE} to 'root' or similar (found: ${ISSUE_OWNER} with UID ${ISSUE_OWNERID}).
2016-04-04 13:18:35 +02:00
Command:
2016-05-02 15:04:54 +02:00
# chown 0:0 ${INCLUDEDIR}/${ISSUE_FILE}
2016-04-04 13:18:35 +02:00
"
2016-10-23 16:26:22 +02:00
fi
2014-09-04 15:35:10 +02:00
2016-03-16 20:29:05 +01:00
# Now if there is an issue with permissions, show it to the user and let them decide how to continue.
if [ ${ISSUE} -eq 1 ]; then
2016-05-02 15:04:54 +02:00
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"
if [ "${ISSUE_TYPE}" = "perms" ]; then
printf "\n Option 2) Change permissions of the related files.\n\n Commands (full directory):\n # chmod 640 include/*\n # ./lynis audit system"
elif [ "${ISSUE_TYPE}" = "owner" ]; then
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"
fi
printf "\n\n[ Press ENTER to continue, or CTRL+C to cancel ]"
2019-07-03 15:07:46 +02:00
IGNORE_FILE_PERMISSION_ISSUES=1
2019-09-17 14:04:30 +02:00
read -r void
2014-08-26 17:33:55 +02:00
fi
2016-05-02 15:04:54 +02:00
# Now include files if permissions are correct, or user decided to continue
2016-03-16 20:29:05 +01:00
. ${INCLUDEDIR}/consts
. ${INCLUDEDIR}/functions
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2019-07-14 11:50:02 +02:00
# Language settings
#
#################################################################################
#
# Auto detection of language based on shell LANG variable. This is required by the Display() function to deal with multi-bytes characters.
DISPLAY_LANG="${LANG:-}"
# Extract the short notation of the language (first two characters).
if [ -x "$(command -v locale 2> /dev/null)" ]; then
LANGUAGE=$(locale | egrep "^LANG=" | cut -d= -f2 | cut -d_ -f1 | egrep "^[a-z]{2}$")
2019-08-20 14:18:15 +02:00
# Try locale command if shell variable had no value
if [ -z "${DISPLAY_LANG}" ]; then
DISPLAY_LANG=$(locale | egrep "^LANG=" | cut -d= -f2)
fi
2019-08-20 14:22:36 +02:00
else
LANGUAGE="en"
2019-07-14 11:50:02 +02:00
fi
# Set default language: 'en' (English) if no value is set
if [ -z "${LANGUAGE}" ]; then
LANGUAGE="en"
fi
# Import translations. First import English to prefill all texts
if [ -f ${DBDIR}/languages/en ]; then
if SafeFile "${DBDIR}/languages/en"; then
. ${DBDIR}/languages/en
else
ExitFatal "Incorrect ownership or permissions of language file (${DBDIR}/languages/en)"
fi
else
echo "Could not find languages directory (file: ${DBDIR}/languages/en)"
exit 1
fi
#
#################################################################################
#
2014-08-26 17:33:55 +02:00
# Traps
#
#################################################################################
#
2019-11-18 08:00:03 +01:00
trap CleanUp INT TERM
2019-11-18 10:19:43 +01:00
trap Status USR1
2014-08-26 17:33:55 +02:00
# Use safe umask for the files we create
umask 027
2014-09-08 14:17:53 +02:00
#
#################################################################################
#
# Parameter checks
#
#################################################################################
#
SafePerms ${INCLUDEDIR}/parameters
. ${INCLUDEDIR}/parameters
2014-09-08 15:51:11 +02:00
# Disable logging if no alternative was provided
2014-09-25 16:56:47 +02:00
if [ ${PRIVILEGED} -eq 0 ]; then
2016-10-23 16:26:22 +02:00
if [ -z "${LOGFILE}" ]; then
2016-05-02 15:13:37 +02:00
# Try creating a log file in temporary directory
2016-08-26 14:05:20 +02:00
if [ ! -f /tmp/lynis.log ]; then
2017-11-25 16:37:28 +01:00
if [ -L /tmp/lynis.log ]; then echo "Log file is symlinked, which can introduce the risk of a symlink attack."; exit 1; fi
2016-08-26 14:05:20 +02:00
touch /tmp/lynis.log
if [ $? -eq 0 ]; then LOGFILE="/tmp/lynis.log"; else LOGFILE="/dev/null"; fi
else
LOGFILE="/tmp/lynis.log"
fi
2017-11-25 16:37:28 +01:00
else
if [ -L "${LOGFILE}" ]; then echo "Log file is symlinked, which can introduce the risk of a symlink attack."; exit 1; fi
2016-05-02 15:13:37 +02:00
fi
2016-10-23 16:26:22 +02:00
if [ -z "${REPORTFILE}" ]; then
2016-05-02 15:13:37 +02:00
touch /tmp/lynis-report.dat
2017-11-25 16:37:28 +01:00
if [ -L /tmp/lynis-report.dat ]; then echo "Report file is symlinked, which can introduce the risk of a symlink attack."; exit 1; fi
2016-05-02 15:13:37 +02:00
if [ $? -eq 0 ]; then REPORTFILE="/tmp/lynis-report.dat"; else REPORTFILE="/dev/null"; fi
2017-11-25 16:37:28 +01:00
else
if [ -L "${REPORTFILE}" ]; then echo "Report file is symlinked, which can introduce the risk of a symlink attack."; exit 1; fi
2014-09-21 13:04:36 +02:00
fi
2014-09-08 15:51:11 +02:00
fi
2014-09-08 14:17:53 +02:00
#
2014-08-26 17:33:55 +02:00
#################################################################################
#
# Program information
#
#################################################################################
#
# CV - Current Version
2017-03-06 08:41:21 +01:00
PROGRAM_AC=$(echo ${PROGRAM_VERSION} | awk '{ print $1 }' | sed 's/[.]//g')
2014-08-26 17:33:55 +02:00
PROGRAM_LV=0
#
#################################################################################
#
# Initialize and default settings
#
#################################################################################
#
2014-09-08 15:42:12 +02:00
if [ ${QUIET} -eq 0 ]; then
2016-07-26 16:00:36 +02:00
printf "\n${WHITE}[ ${PROGRAM_NAME} ${PROGRAM_VERSION} ]${NORMAL}\n\n################################################################################\n ${PROGRAM_LICENSE}\n\n ${PROGRAM_COPYRIGHT}\n ${PROGRAM_EXTRAINFO}\n################################################################################\n\n"
2014-09-08 15:42:12 +02:00
fi
2016-05-17 18:12:49 +02:00
if [ "${PROGRAM_RELEASE_TYPE}" = "beta" ]; then
2016-04-04 13:18:35 +02:00
printf "%s" "
${WHITE}
#########################################################
# ${YELLOW}BETA VERSION${WHITE} #
#########################################################
Thank you for testing a beta release. Make sure to read
all available documentation before proceeding and/or
requesting support. Due the nature of beta releases, it
is possible new features give unexpected warnings.
#########################################################
${NORMAL}
"
2014-08-26 17:33:55 +02:00
fi
#
#################################################################################
#
2016-06-18 11:15:57 +02:00
InsertSection "${GEN_INITIALIZE_PROGRAM}"
2014-08-26 17:33:55 +02:00
2016-07-05 16:48:32 +02:00
# Discover any profiles
DiscoverProfiles
2015-10-14 16:49:57 +02:00
2014-08-26 17:33:55 +02:00
# Initialize and check profile file, auditor name, log file and report file
2017-08-08 14:52:59 +02:00
if [ -z "${LOGDIR}" ]; then LOGDIR="/var/log"; fi
2016-10-23 16:26:22 +02:00
if [ -z "${AUDITORNAME}" ]; then AUDITORNAME="[Not Specified]"; fi
2017-08-08 14:52:59 +02:00
if [ -z "${LOGFILE}" ]; then LOGFILE="${LOGDIR}/lynis.log"; fi
if [ -z "${REPORTFILE}" ]; then REPORTFILE="${LOGDIR}/lynis-report.dat"; fi
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
# PID :: Check PID file, to avoid multiple instances running at the same time.
#
#################################################################################
#
2015-09-13 16:51:39 +02:00
# Decide where to write our PID file. For unprivileged users this will be in their home directory, or /tmp if their
2017-03-06 08:41:21 +01:00
# home directory isn't set. For root it will be /var/run, or the current working directory if /var/run doesn't exist.
2016-10-23 16:26:22 +02:00
MYHOMEDIR=$(echo ~ 2> /dev/null)
2017-03-14 16:41:47 +01:00
if [ -z "${MYHOMEDIR}" ]; then MYHOMEDIR="/tmp"; fi
2015-09-13 16:51:39 +02:00
if [ ${PRIVILEGED} -eq 0 ]; then
PIDFILE="${MYHOMEDIR}/lynis.pid"
elif [ -d /var/run ]; then
PIDFILE="/var/run/lynis.pid"
else
PIDFILE="./lynis.pid"
fi
# Check if there is already a PID file in any of the locations (incorrect termination of previous instance)
if [ -f "${MYHOMEDIR}/lynis.pid" -o -f "./lynis.pid" -o -f "/var/run/lynis.pid" ]; then
2016-04-04 13:18:35 +02:00
printf "%s" "
${WARNING}Warning${NORMAL}: ${WHITE}PID file exists, probably another Lynis process is running.${NORMAL}
------------------------------------------------------------------------------
2018-03-16 17:25:18 +01:00
If you are unsure if another Lynis process is running currently, you are advised
to stop the current process and check the process list first. If you cancelled
a previous instance (by using CTRL+C), you can ignore this message.
2016-04-04 13:18:35 +02:00
You are advised to check for temporary files after program completion.
------------------------------------------------------------------------------
${YELLOW}Note: ${WHITE}Cancelling the program can leave temporary files behind${NORMAL}
"
2015-10-14 16:49:57 +02:00
2016-04-15 14:41:08 +02:00
# Quit directly for cron jobs.
2016-04-15 14:38:05 +02:00
if [ ${CRONJOB} -eq 1 ]; then
echo "Quitting, to prevent multiple cron jobs running at the same time"
exit 1 # Manually exit, no cleanups to prevent deleting an active PID file
2017-03-09 12:29:09 +01:00
else
2018-03-16 17:25:18 +01:00
WaitForKeyPress
2016-04-15 14:38:05 +02:00
fi
2015-10-14 16:49:57 +02:00
# Deleting any stale PID files that might exist. Note: Display function does not work yet at this point
2015-09-13 16:51:39 +02:00
if [ -f "${MYHOMEDIR}/lynis.pid" ]; then rm -f "${MYHOMEDIR}/lynis.pid"; fi
if [ -f "./lynis.pid" ]; then rm -f "./lynis.pid"; fi
if [ -f "/var/run/lynis.pid" ]; then rm -f "/var/run/lynis.pid"; fi
2014-08-26 17:33:55 +02:00
fi
2015-09-13 21:35:02 +02:00
# Ensure symlink attack is not possible, by confirming there is no symlink of the file already
2016-10-23 16:26:22 +02:00
OURPID=$(echo $$)
2015-09-13 21:35:02 +02:00
if [ -L ${PIDFILE} ]; then
echo "Found symlinked PID file (${PIDFILE}), quitting"
ExitFatal
2016-10-23 16:26:22 +02:00
else
2015-09-13 21:35:02 +02:00
# Create new PID file writable only by owner
echo "${OURPID}" > ${PIDFILE}
chmod 600 ${PIDFILE}
fi
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
# Check program parameters
#
#################################################################################
#
# Bail out if we didn't get any parameter, or incorrect ones
if [ ${PARAMCOUNT} -eq 0 -o ${WRONGOPTION} -eq 1 -o ${VIEWHELP} -eq 1 ]; then
2016-04-04 13:18:35 +02:00
printf "%s" "
2016-04-23 17:00:42 +02:00
${GREEN}Usage:${NORMAL} lynis ${CYAN}command ${GRAY}[options]${NORMAL}
2016-04-04 13:18:35 +02:00
2016-04-12 21:59:00 +02:00
${WHITE}Command:${NORMAL}
2016-04-04 13:18:35 +02:00
2016-04-12 21:59:00 +02:00
${CYAN}audit${NORMAL}
2016-05-14 15:44:30 +02:00
audit system : Perform local security scan
audit system remote <host> : Remote security scan
2016-04-04 13:18:35 +02:00
audit dockerfile <file> : Analyze Dockerfile
2016-04-12 21:59:00 +02:00
${CYAN}show${NORMAL}
2016-07-13 13:19:23 +02:00
show : Show all commands
2016-04-12 21:59:00 +02:00
show version : Show ${PROGRAM_NAME} version
show help : Show help
${CYAN}update${NORMAL}
2016-04-04 13:18:35 +02:00
update info : Show update details
2016-04-12 21:59:00 +02:00
${WHITE}Options:${NORMAL}
2019-08-21 13:41:23 +02:00
${WHITE}Alternative system audit modes${NORMAL}
${GRAY}--forensics${NORMAL} : Perform forensics on a running or mounted system
${GRAY}--pentest${NORMAL} : Non-privileged, show points of interest for pentesting
2016-04-23 17:00:42 +02:00
${WHITE}Layout options${NORMAL}
2016-04-23 17:06:10 +02:00
${GRAY}--no-colors${NORMAL} : Don't use colors in output
2016-05-14 15:44:30 +02:00
${GRAY}--quiet (-q)${NORMAL} : No output
2016-04-23 17:06:10 +02:00
${GRAY}--reverse-colors${NORMAL} : Optimize color display for light backgrounds
2016-04-23 17:00:42 +02:00
${WHITE}Misc options${NORMAL}
2016-04-23 17:06:10 +02:00
${GRAY}--debug${NORMAL} : Debug logging to screen
2019-08-21 13:41:23 +02:00
${GRAY}--no-log${NORMAL} : Don't create a log file
${GRAY}--profile ${BROWN}<profile>${NORMAL} : Scan the system with the given profile file
2016-04-23 17:06:10 +02:00
${GRAY}--view-manpage (--man)${NORMAL} : View man page
${GRAY}--verbose${NORMAL} : Show more details on screen
${GRAY}--version (-V)${NORMAL} : Display version number and quit
2019-08-21 13:41:23 +02:00
${GRAY}--wait${NORMAL} : Wait between a set of tests
2016-04-23 17:00:42 +02:00
${WHITE}Enterprise options${NORMAL}
2018-05-02 12:42:32 +02:00
${GRAY}--plugindir ${BROWN}<path>${NORMAL} : Define path of available plugins
2016-04-23 17:06:10 +02:00
${GRAY}--upload${NORMAL} : Upload data to central node
2016-04-04 13:18:35 +02:00
2016-05-10 11:48:35 +02:00
More options available. Run '$0 show options', or use the man page.
2016-04-04 13:18:35 +02:00
2019-08-21 13:41:23 +02:00
2016-04-04 13:18:35 +02:00
"
2014-08-26 17:33:55 +02:00
if [ ${WRONGOPTION} -eq 1 ]; then
2015-01-30 20:01:07 +01:00
echo " ${RED}Error${NORMAL}: ${WHITE}Invalid option '${WRONGOPTION_value}'${NORMAL}"
2017-04-30 17:59:35 +02:00
else
2014-08-26 17:33:55 +02:00
if [ ${VIEWHELP} -eq 0 ]; then
2016-06-11 14:09:41 +02:00
echo " ${RED}No command provided.${WHITE} Exiting..${NORMAL}"
2016-04-23 17:00:42 +02:00
echo ""
2014-08-26 17:33:55 +02:00
fi
fi
echo ""
# Cleanup PID file if we drop out earlier
RemovePIDFile
# Exit with exit code 1
2015-09-10 08:36:26 +02:00
exit 64
2014-08-26 17:33:55 +02:00
fi
#
#################################################################################
2014-09-25 16:56:47 +02:00
#
2017-10-29 16:55:55 +01:00
if [ ${PRIVILEGED} -eq 0 -a ${CHECK} -eq 1 -a ${QUIET} -eq 0 ]; then
2016-05-03 13:49:55 +02:00
printf "%s" "${WHITE}
2016-04-04 13:18:35 +02:00
###################################################################
# #
2016-05-02 15:38:10 +02:00
# ${PURPLE}NON-PRIVILEGED SCAN MODE${WHITE} #
2016-04-04 13:18:35 +02:00
# #
###################################################################
${NORMAL}
${YELLOW}NOTES:${NORMAL}
--------------
${WHITE}*${NORMAL} Some tests will be skipped (as they require root permissions)
${WHITE}*${NORMAL} Some tests might fail silently or give different results
2016-05-03 13:49:55 +02:00
2016-04-04 13:18:35 +02:00
"
2016-05-03 13:49:55 +02:00
sleep 3
2017-03-14 16:41:47 +01:00
if [ -z "${LOGFILE}" -o "${LOGFILE}" = "/dev/null" ]; then
2016-04-04 13:18:35 +02:00
printf "%s" "
2016-05-02 15:13:37 +02:00
${RED}WARNING:${NORMAL}
2016-05-03 13:49:55 +02:00
${WHITE}*${NORMAL} No suggestions or warnings will be displayed in report (due to missing log file)"
2014-09-25 16:56:47 +02:00
fi
fi
#
#################################################################################
2014-08-26 17:33:55 +02:00
#
# OS Detection
#
#################################################################################
#
SafePerms ${INCLUDEDIR}/osdetection
. ${INCLUDEDIR}/osdetection
Display --indent 2 --text "- Detecting OS... " --result DONE --color GREEN
# Check hostname
case ${OS} in
HP-UX)
2016-10-16 17:07:34 +02:00
HOSTNAME=$(hostname) ;;
2014-08-26 17:33:55 +02:00
Solaris)
2016-10-16 17:07:34 +02:00
HOSTNAME=$(uname -n) ;;
2014-08-26 17:33:55 +02:00
*)
2016-10-16 17:07:34 +02:00
HOSTNAME=$(hostname -s 2> /dev/null) ;;
2014-08-26 17:33:55 +02:00
esac
2016-10-16 17:07:34 +02:00
if [ -z "${HOSTNAME}" ]; then
HOSTNAME=$(hostname 2> /dev/null)
if [ -z "${HOSTNAME}" ]; then HOSTNAME="no-hostname"; fi
fi
FQDN=$(hostname 2> /dev/null)
2014-08-26 17:33:55 +02:00
if [ "${OS}" = "Linux" -a "${HOSTNAME}" = "${FQDN}" ]; then
2016-10-16 17:07:34 +02:00
FQDN=$(hostname -f 2> /dev/null)
2014-08-26 17:33:55 +02:00
fi
#
#################################################################################
#
2015-01-30 20:01:07 +01:00
# Clear log and report files
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
# Clear log file and test if it's writable
2016-07-11 10:32:14 +02:00
CDATE=$(date "+%Y-%m-%d %H:%M:%S")
2016-08-26 14:05:20 +02:00
if [ ${LOGTEXT} -eq 1 ]; then echo "${CDATE} Starting ${PROGRAM_NAME} ${PROGRAM_VERSION} with PID ${OURPID}, build date ${PROGRAM_RELEASE_DATE}" > ${LOGFILE}; fi
2015-01-30 20:01:07 +01:00
if [ $? -gt 0 ]; then
2014-08-26 17:33:55 +02:00
Display --indent 2 --text "- Clearing log file (${LOGFILE})... " --result WARNING --color RED
echo "${WARNING}Fatal error${NORMAL}: problem while writing to log file. Check location and permissions."
RemovePIDFile
exit 1
fi
2016-04-28 12:58:03 +02:00
LogTextBreak
2016-04-27 15:37:07 +02:00
LogText "### ${PROGRAM_COPYRIGHT} ###"
2014-08-26 17:33:55 +02:00
# Clear report file (to avoid appending to an existing file)
2016-10-13 20:15:00 +02:00
if [ ${CREATE_REPORT_FILE} -eq 1 ]; then echo "# ${PROGRAM_NAME} Report" > ${REPORTFILE}; fi
2016-04-27 15:37:07 +02:00
Report "report_version_major=${REPORT_version_major}"
Report "report_version_minor=${REPORT_version_minor}"
2016-10-23 16:26:22 +02:00
CDATE=$(date "+%F %H:%M:%S")
2016-04-27 15:37:07 +02:00
Report "report_datetime_start=${CDATE}"
Report "auditor=${AUDITORNAME}"
Report "lynis_version=${PROGRAM_VERSION}"
Report "os=${OS}"
Report "os_name=${OS_NAME}"
Report "os_fullname=${OS_FULLNAME}"
Report "os_version=${OS_VERSION}"
if [ "${OS}" = "Linux" ]; then Report "linux_version=${LINUX_VERSION}"; fi
2019-07-16 13:20:30 +02:00
if [ -n "${OS_KERNELVERSION}" ]; then Report "os_kernel_version=${OS_KERNELVERSION}"; fi
if [ -n "${OS_KERNELVERSION_FULL}" ]; then Report "os_kernel_version_full=${OS_KERNELVERSION_FULL}"; fi
2016-07-11 10:32:14 +02:00
2016-04-27 15:37:07 +02:00
Report "hostname=${HOSTNAME}"
2016-03-16 20:18:31 +01:00
2016-10-23 16:26:22 +02:00
if [ -z "${HOSTNAME}" ]; then
2016-03-16 20:18:31 +01:00
HOSTNAME="no-hostname"
LogText "Info: could not find a hostname, using 'no-hostname' instead"
ReportSuggestion "LYNIS" "Check your hostname configuration" "hostname -s"
fi
2016-07-24 17:22:00 +02:00
Report "test_category=${TEST_CATEGORY_TO_CHECK}"
Report "test_group=${TEST_GROUP_TO_CHECK}"
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2016-07-28 11:39:10 +02:00
# Read profile, set code checks, define language
2016-04-13 12:09:26 +02:00
#
#################################################################################
#
2016-07-05 16:48:32 +02:00
ParseProfiles
2016-06-11 14:09:41 +02:00
2016-07-28 11:39:10 +02:00
# Define if we keep working in strict mode (development)
if [ ${SET_STRICT} -eq 0 ]; then
set +u # Allow uninitialized variables
else
set -u # Do not allow unitialized variables
fi
2016-06-11 14:09:41 +02:00
# Import a different language when configured
2016-06-11 14:34:21 +02:00
if [ ! "${LANGUAGE}" = "en" ]; then
LogText "Language is set to ${LANGUAGE}"
2016-06-18 09:41:51 +02:00
Display --indent 2 --text "- Detecting language and localization" --result "${LANGUAGE}" --color WHITE
2016-06-11 14:09:41 +02:00
if [ ! -f ${DBDIR}/languages/${LANGUAGE} ]; then
2016-06-18 09:41:51 +02:00
Display --indent 4 --text "${YELLOW}Notice:${NORMAL} no language file found for '${LANGUAGE}' (tried: ${DBDIR}/languages/${LANGUAGE})"
2018-03-16 17:25:18 +01:00
if IsDeveloperVersion; then Display --indent 4 --text "See https://github.com/CISOfy/lynis-sdk/documentation/10-translations.md for more details to help translate Lynis"; fi
2016-06-18 09:41:51 +02:00
sleep 5
2017-03-09 12:29:09 +01:00
else
2016-06-11 14:09:41 +02:00
LogText "Importing language file (${DBDIR}/languages/${LANGUAGE})"
. ${DBDIR}/languages/${LANGUAGE}
fi
fi
2016-06-11 14:34:21 +02:00
LogTextBreak
2016-07-31 11:48:04 +02:00
# Pre-execution tests
if [ ${UPLOAD_DATA} -eq 1 -a -z "${LICENSE_KEY}" ]; then DisplayError "${ERROR_NO_LICENSE}" 64; fi
if [ ${UPLOAD_DATA} -eq 1 -a -z "${UPLOAD_SERVER}" ]; then DisplayError "${ERROR_NO_UPLOAD_SERVER}" 64; fi
2016-04-13 12:09:26 +02:00
#
#################################################################################
#
# Plugins
#
#################################################################################
#
# Plugin directory test
2017-03-14 16:41:47 +01:00
if [ -z "${PLUGINDIR}" ]; then
2016-04-27 15:37:07 +02:00
#LogText "Result: Searching for plugindir"
2016-04-13 12:09:26 +02:00
tPLUGIN_TARGETS="/usr/local/lynis/plugins /usr/local/share/lynis/plugins /usr/share/lynis/plugins /etc/lynis/plugins ./plugins"
2017-04-30 17:59:35 +02:00
for DIR in ${tPLUGIN_TARGETS}; do
if [ -d ${DIR} -a -z "${PLUGINDIR}" ]; then
PLUGINDIR=${DIR}
2016-04-13 12:09:26 +02:00
Debug "Result: found plugindir ${PLUGINDIR}"
fi
done
2017-04-30 17:59:35 +02:00
else
2016-04-13 12:09:26 +02:00
Debug "Plugin was already set before to ${PLUGINDIR} (most likely via program argument or profile)"
fi
# Drop out if our plugin directory can't be found
2016-10-23 16:26:22 +02:00
if [ -z "${PLUGINDIR}" -o ! -d ${PLUGINDIR} ]; then
2016-04-13 12:09:26 +02:00
echo "Fatal error: can't find plugin directory ${PLUGINDIR}"
echo "Make sure to execute ${PROGRAM_NAME} from untarred directory or check your installation."
exit 1
fi
#
#################################################################################
#
2014-08-26 17:33:55 +02:00
# Show program information to display
#
#################################################################################
#
2015-04-30 01:27:10 +02:00
if [ ${QUIET} -eq 0 -a ${SHOW_PROGRAM_DETAILS} -eq 1 ]; then
2014-08-26 17:33:55 +02:00
echo ""
echo " ---------------------------------------------------"
2016-04-05 11:28:11 +02:00
echo " Program version: ${PROGRAM_VERSION}"
2014-08-26 17:33:55 +02:00
echo " Operating system: ${OS}"
echo " Operating system name: ${OS_NAME}"
2015-09-07 17:35:07 +02:00
echo " Operating system version: ${OS_VERSION}"
2019-02-26 16:15:15 +01:00
LogText "EOL check: ${EOL}"
if [ ${EOL} -eq 1 ]; then
echo " End-of-life: ${WARNING}YES${NORMAL}"
ReportWarning "GEN-0010" "This version ${OS_VERSION} is marked end-of-life as of ${EOL_DATE}"
2019-04-15 19:20:51 +02:00
elif [ ${EOL} -eq 255 ]; then
# TODO - mark as item where community can provide help
LogText "Note: the end-of-life of '${OS_FULLNAME}' could not be checked. Entry missing in software-eol.db?"
2019-02-26 16:15:15 +01:00
fi
2019-07-16 13:20:30 +02:00
if [ -n "${OS_MODE}" ]; then echo " Operating system mode: ${OS_MODE}"; fi
2014-08-26 17:33:55 +02:00
echo " Kernel version: ${OS_KERNELVERSION}"
echo " Hardware platform: ${HARDWARE}"
echo " Hostname: ${HOSTNAME}"
2016-07-24 17:22:00 +02:00
echo " ---------------------------------------------------"
2016-04-07 16:24:11 +02:00
echo " Profiles: ${PROFILES}"
2014-08-26 17:33:55 +02:00
echo " Log file: ${LOGFILE}"
echo " Report file: ${REPORTFILE}"
echo " Report version: ${REPORT_version}"
echo " Plugin directory: ${PLUGINDIR}"
echo " ---------------------------------------------------"
2016-07-24 17:22:00 +02:00
echo " Auditor: ${AUDITORNAME}"
2017-09-17 20:15:57 +02:00
echo " Language: ${LANGUAGE}"
2016-07-24 17:22:00 +02:00
echo " Test category: ${TEST_CATEGORY_TO_CHECK}"
echo " Test group: ${TEST_GROUP_TO_CHECK}"
2016-08-15 20:01:23 +02:00
if [ ! "${ROOTDIR}" = "/" ]; then echo " Root directory (custom): ${ROOTDIR}"; fi
2016-07-24 17:22:00 +02:00
echo " ---------------------------------------------------"
2014-08-26 17:33:55 +02:00
fi
2016-04-27 15:37:07 +02:00
LogText "Program version: ${PROGRAM_VERSION}"
LogText "Operating system: ${OS}"
LogText "Operating system name: ${OS_NAME}"
LogText "Operating system version: ${OS_VERSION}"
2019-07-16 13:20:30 +02:00
if [ -n "${OS_MODE}" ]; then LogText "Operating system mode: ${OS_MODE}"; fi
2016-04-27 15:37:07 +02:00
LogText "Kernel version: ${OS_KERNELVERSION}"
2019-07-16 13:20:30 +02:00
if [ -n "${OS_KERNELVERSION_FULL}" ]; then
2017-03-07 20:23:08 +01:00
LogText "Kernel version (full): ${OS_KERNELVERSION_FULL}"
2016-04-27 15:37:07 +02:00
fi
LogText "Hardware platform: ${HARDWARE}"
LogText "-----------------------------------------------------"
LogText "Hostname: ${HOSTNAME}"
LogText "Auditor: ${AUDITORNAME}"
LogText "Profiles: ${PROFILES}"
LogText "Work directory: ${WORKDIR}"
LogText "Include directory: ${INCLUDEDIR}"
LogText "Plugin directory: ${PLUGINDIR}"
LogText "-----------------------------------------------------"
LogText "Log file: ${LOGFILE}"
LogText "Report file: ${REPORTFILE}"
LogText "Report version: ${REPORT_version}"
LogText "-----------------------------------------------------"
2016-07-24 17:22:00 +02:00
LogText "Test category: ${TEST_CATEGORY_TO_CHECK}"
LogText "Test group: ${TEST_GROUP_TO_CHECK}"
2016-04-27 15:37:07 +02:00
LogText "BusyBox used: ${SHELL_IS_BUSYBOX}"
Report "plugin_directory=${PLUGINDIR}"
2016-04-13 12:09:26 +02:00
2016-04-28 12:58:03 +02:00
LogTextBreak
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2016-03-16 20:18:31 +01:00
# Check for program update (and friendly force people to upgrade)
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2016-04-27 15:37:07 +02:00
LogText "Test: Checking for program update..."
2014-08-26 17:33:55 +02:00
UPDATE_AVAILABLE=0
2017-03-09 12:29:09 +01:00
2014-08-26 17:33:55 +02:00
if [ ${SKIP_UPGRADE_TEST} -eq 1 ]; then
2016-04-27 15:37:07 +02:00
LogText "Upgrade test skipped due profile option set (skip_upgrade_test)"
2014-08-26 17:33:55 +02:00
PROGRAM_LV="${PROGRAM_AC}"
2016-10-23 16:26:22 +02:00
else
2014-08-26 17:33:55 +02:00
CheckUpdates
fi
2017-03-09 12:29:09 +01:00
2017-03-14 16:41:47 +01:00
if [ -z "${PROGRAM_AC}" -o -z "${PROGRAM_LV}" ]; then
2014-08-26 17:33:55 +02:00
Display --indent 2 --text "- Program update status... " --result UNKNOWN --color YELLOW
2016-04-27 15:37:07 +02:00
LogText "Result: Update check failed. No network connection?"
LogText "Info: to perform an automatic update check, outbound DNS connections should be allowed (TXT record)."
2014-08-26 17:33:55 +02:00
# Set both to safe values
PROGRAM_AC=0; PROGRAM_LV=0
2016-10-23 16:26:22 +02:00
else
2016-04-27 15:37:07 +02:00
LogText "Current installed version : ${PROGRAM_AC}"
LogText "Latest stable version : ${PROGRAM_LV}"
2014-08-26 17:33:55 +02:00
if [ ${PROGRAM_LV} -gt ${PROGRAM_AC} ]; then
# Check if current version is REALLY outdated (10 versions ago)
2019-09-17 14:04:30 +02:00
PROGRAM_MINVERSION=$((PROGRAM_LV - 10))
2016-04-27 15:37:07 +02:00
LogText "Minimum required version : ${PROGRAM_MINVERSION}"
2014-08-26 17:33:55 +02:00
if [ ${PROGRAM_MINVERSION} -gt ${PROGRAM_AC} ]; then
Display --indent 2 --text "- Program update status... " --result "WARNING" --color RED
2016-04-27 15:37:07 +02:00
LogText "Result: This version is VERY outdated. Newer ${PROGRAM_NAME} release available!"
2016-03-16 20:18:31 +01:00
ReportWarning "LYNIS" "Version of Lynis is very old and should be updated"
2016-04-27 15:37:07 +02:00
Report "lynis_update_available=1"
2014-08-26 17:33:55 +02:00
UPDATE_AVAILABLE=1
2016-10-23 16:26:22 +02:00
else
2014-08-26 17:33:55 +02:00
Display --indent 2 --text "- Program update status... " --result "UPDATE AVAILABLE" --color YELLOW
2016-04-27 15:37:07 +02:00
LogText "Result: newer ${PROGRAM_NAME} release available!"
2016-03-16 20:18:31 +01:00
ReportSuggestion "LYNIS" "Version of Lynis outdated, consider upgrading to the latest version"
2016-04-27 15:37:07 +02:00
Report "lynis_update_available=1"
2014-08-26 17:33:55 +02:00
UPDATE_AVAILABLE=1
fi
2016-10-23 16:26:22 +02:00
else
2014-08-26 17:33:55 +02:00
if [ ${UPDATE_CHECK_SKIPPED} -eq 0 ]; then
Display --indent 2 --text "- Program update status... " --result "NO UPDATE" --color GREEN
2016-04-27 15:37:07 +02:00
LogText "No ${PROGRAM_NAME} update available."
Report "lynis_update_available=0"
2016-10-23 16:26:22 +02:00
else
2014-08-26 17:33:55 +02:00
Display --indent 2 --text "- Program update status... " --result "SKIPPED" --color YELLOW
2016-04-27 15:37:07 +02:00
LogText "Update check skipped due to constraints (e.g. missing dig binary)"
Report "lynis_update_available=-1"
2014-08-26 17:33:55 +02:00
fi
fi
fi
2016-03-16 20:18:31 +01:00
# Test for older releases, without testing via update mechanism
2017-04-30 17:59:35 +02:00
if [ "${OS}" = "Solaris" ]; then
A bunch of Solaris compatibility tweaks (#367)
* Work around Solaris' /bin/sh not being POSIX.
If /usr/xpg4/bin/sh is present, we are (definitely?) on Solaris or
a derivative, and /bin/sh cannot be trusted to support POSIX, but
/usr/xpg4/bin/sh can be. Exec it right away.
* Work around Solaris 'which' command oddity.
Solaris' (at least) 'which' command outputs not-found errors to STDOUT
instead of STDERR.
This makes "did we get any output from which" checks insufficient;
piping to grep -v the "no foo in ..." message should work.
Note that this patch set includes all such uses of which that I could
find, including ones that should never be reached on Solaris (i.e. only
executed on some other OS) just for consistency.
* Improved alternate-sh exec to avoid looping.
* Solaris' /usr/ucb/echo supports -n.
* Check for the best hash type that openssl supports.
When using openssl to generate hashes, do not assume it supports
sha256; try that, then sha1, then give up and use md5.
* Solaris does not support sed -i; use a tempfile.
* Use the full path for modinfo.
When running as non-root, /usr/sbin/ might not be in PATH.
include/tests_accounting already calls modinfo by full path, but
include/tests_kernel did not.
* Solaris find does not support -maxdepth.
This mirrors the logic already in tests_homedirs.
* Use PSBINARY instead of ps.
* Work around Solaris' date not supporting +%s.
Printing nawk's srand value is a bizarre but apparently once popular
workaround for there being no normal userland command to print
UNIX epoch seconds. A perl one-liner is the other common approach,
but nawk may be more reliably present on Solaris than perl.
* Revert to using sha1 for HOSTID.
* Whitespace cleanup for openssl hash tests.
2017-03-08 17:24:24 +01:00
NOW=$(nawk 'BEGIN{print srand()}')
2017-04-30 17:59:35 +02:00
else
A bunch of Solaris compatibility tweaks (#367)
* Work around Solaris' /bin/sh not being POSIX.
If /usr/xpg4/bin/sh is present, we are (definitely?) on Solaris or
a derivative, and /bin/sh cannot be trusted to support POSIX, but
/usr/xpg4/bin/sh can be. Exec it right away.
* Work around Solaris 'which' command oddity.
Solaris' (at least) 'which' command outputs not-found errors to STDOUT
instead of STDERR.
This makes "did we get any output from which" checks insufficient;
piping to grep -v the "no foo in ..." message should work.
Note that this patch set includes all such uses of which that I could
find, including ones that should never be reached on Solaris (i.e. only
executed on some other OS) just for consistency.
* Improved alternate-sh exec to avoid looping.
* Solaris' /usr/ucb/echo supports -n.
* Check for the best hash type that openssl supports.
When using openssl to generate hashes, do not assume it supports
sha256; try that, then sha1, then give up and use md5.
* Solaris does not support sed -i; use a tempfile.
* Use the full path for modinfo.
When running as non-root, /usr/sbin/ might not be in PATH.
include/tests_accounting already calls modinfo by full path, but
include/tests_kernel did not.
* Solaris find does not support -maxdepth.
This mirrors the logic already in tests_homedirs.
* Use PSBINARY instead of ps.
* Work around Solaris' date not supporting +%s.
Printing nawk's srand value is a bizarre but apparently once popular
workaround for there being no normal userland command to print
UNIX epoch seconds. A perl one-liner is the other common approach,
but nawk may be more reliably present on Solaris than perl.
* Revert to using sha1 for HOSTID.
* Whitespace cleanup for openssl hash tests.
2017-03-08 17:24:24 +01:00
NOW=$(date "+%s")
fi
2016-03-16 20:18:31 +01:00
OLD_RELEASE=0
TIME_DIFFERENCE_CHECK=10368000 # 4 months
2019-09-17 14:04:30 +02:00
RELEASE_PLUS_TIMEDIFF=$((PROGRAM_RELEASE_TIMESTAMP + TIME_DIFFERENCE_CHECK))
2016-03-16 20:18:31 +01:00
if [ ${NOW} -gt ${RELEASE_PLUS_TIMEDIFF} ]; then
# Show if release is old, only if we didn't show it with normal update check
if [ ${UPDATE_AVAILABLE} -eq 0 ]; then
ReportSuggestion "LYNIS" "This release is more than 4 months old. Consider upgrading"
fi
OLD_RELEASE=1
fi
2017-12-30 18:40:13 +01:00
# Show on screen message if release is very outdated (unless --quiet/--silent is used)
if [ ${UPDATE_AVAILABLE} -eq 1 -a ${QUIET} -eq 0 ]; then
2016-03-16 20:18:31 +01:00
echo ""
echo " ==============================================================================="
2016-06-18 11:15:57 +02:00
echo " ${CYAN}${PROGRAM_NAME} ${TEXT_UPDATE_AVAILABLE}${NORMAL}"
2016-03-16 20:18:31 +01:00
echo " ==============================================================================="
echo ""
if [ ${OLD_RELEASE} -eq 1 ]; then
echo " ${YELLOW}Current version is more than 4 months old${NORMAL}"
2016-07-20 10:51:34 +02:00
echo ""
fi
if [ ${PROGRAM_LV} -gt 0 ]; then
2016-03-16 20:18:31 +01:00
echo " Current version : ${YELLOW}${PROGRAM_AC}${NORMAL} Latest version : ${GREEN}${PROGRAM_LV}${NORMAL}"
2016-07-20 10:51:34 +02:00
echo ""
2016-03-16 20:18:31 +01:00
fi
echo " ${WHITE}Please update to the latest version.${NORMAL}"
2018-01-12 15:29:39 +01:00
echo " New releases include additional features, bug fixes, tests, and baselines.${NORMAL}"
2016-03-16 20:18:31 +01:00
echo ""
2016-07-20 10:51:34 +02:00
echo " Download the latest version:"
2017-12-30 18:40:13 +01:00
echo ""
2016-07-20 10:51:34 +02:00
echo " Packages (DEB/RPM) - https://packages.cisofy.com"
2018-01-12 15:29:39 +01:00
echo " Website (TAR) - https://cisofy.com/downloads/"
echo " GitHub (source) - https://github.com/CISOfy/lynis"
2016-03-16 20:18:31 +01:00
echo ""
echo " ==============================================================================="
echo ""
sleep 5
fi
2016-04-28 12:58:03 +02:00
LogTextBreak
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
# Check which binaries are available to the scanning process
if [ -f ${INCLUDEDIR}/binaries ]; then
SafePerms ${INCLUDEDIR}/binaries
. ${INCLUDEDIR}/binaries
fi
2016-04-28 12:58:03 +02:00
LogTextBreak
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2016-08-13 16:38:07 +02:00
# Use hardware detection capabilities
2014-11-04 00:32:59 +01:00
IsVirtualMachine
2016-10-16 15:13:04 +02:00
if IsContainer; then
LogText "Result: ${PROGRAM_NAME} is running in container (${CONTAINER_TYPE})"
Report "container=1"
Report "container_type=${CONTAINER_TYPE}"
else
LogText "Result: ${PROGRAM_NAME} is not running in container"
Report "container=0"
fi
2016-08-13 16:38:07 +02:00
IsNotebook
2014-11-04 00:32:59 +01:00
#
#################################################################################
#
2018-01-17 15:56:19 +01:00
# Check for systemd active
if [ -d /run/systemd/system ]; then
2017-08-17 20:30:08 +02:00
LogText "Result: system is using systemd"
2016-03-24 17:15:39 +01:00
HAS_SYSTEMD=1
Report "systemd=1"
2016-10-23 16:26:22 +02:00
else
2017-08-17 20:28:32 +02:00
LogText "Result: systemd not found"
2018-01-17 15:56:19 +01:00
HAS_SYSTEMD=0
2016-03-24 17:15:39 +01:00
Report "systemd=0"
fi
#
#################################################################################
#
2016-04-19 21:09:48 +02:00
if IsVerbose; then
InsertSection "Program Details"
2016-06-18 11:15:57 +02:00
Display --indent 2 --text "- ${GEN_VERBOSE_MODE}" --result "YES" --color GREEN
2016-04-19 21:09:48 +02:00
if IsDebug; then
2016-06-18 11:15:57 +02:00
Display --indent 2 --text "- ${GEN_DEBUG_MODE}" --result "YES" --color GREEN
2017-04-30 17:59:35 +02:00
else
2016-06-18 11:15:57 +02:00
Display --indent 2 --text "- ${GEN_DEBUG_MODE}" --result "NO" --color RED
2016-04-19 21:09:48 +02:00
fi
fi
#
#################################################################################
#
2016-04-05 11:28:11 +02:00
# Plugins
2016-07-05 17:26:27 +02:00
if [ ${SKIP_PLUGINS} -eq 0 ]; then
2015-10-01 22:41:57 +02:00
2016-01-19 12:09:42 +01:00
N_PLUGIN=0
N_PLUGIN_ENABLED=0
2015-10-01 22:41:57 +02:00
# Plugins function
2016-05-09 13:47:57 +02:00
RunPlugins() {
2016-01-19 12:09:42 +01:00
if [ $# -eq 0 ]; then echo "RunPlugins should be started with phase number"; ExitFatal; fi
PLUGIN_PHASE=$1
if [ ${PLUGIN_PHASE} -eq 0 -o ${PLUGIN_PHASE} -gt 2 ]; then echo "Incorrect phase number when calling RunPlugins"; ExitFatal; fi
2016-04-28 12:58:03 +02:00
LogTextBreak
2016-06-11 14:09:41 +02:00
InsertPluginSection "Plugins (${GEN_PHASE} ${PLUGIN_PHASE})"
2016-01-19 12:09:42 +01:00
if [ ${PLUGIN_PHASE} -eq 1 ]; then
2016-06-18 11:15:57 +02:00
Display --text "${NOTE_PLUGINS_TAKE_TIME}"
2016-01-19 12:09:42 +01:00
Display --text " "
2016-04-27 15:37:07 +02:00
LogText "Searching plugins..."
2016-01-19 12:09:42 +01:00
fi
2015-01-30 20:01:07 +01:00
2016-01-19 12:09:42 +01:00
# Search plugins
2016-05-09 13:47:57 +02:00
FIND_PLUGINS=$(find ${PLUGINDIR} -type f -name "plugin_[a-z]*_phase${PLUGIN_PHASE}" | sort)
2016-01-19 12:09:42 +01:00
for PLUGIN_FILE in ${FIND_PLUGINS}; do
2016-04-27 15:37:07 +02:00
LogText "Found plugin file: ${PLUGIN_FILE}"
2016-01-19 12:09:42 +01:00
# Double check if output is a valid file name
if [ -f ${PLUGIN_FILE} ]; then
2017-03-06 08:41:21 +01:00
FIND2=$(grep "^# PLUGIN_NAME=" ${PLUGIN_FILE} | awk -F= '{ print $2 }')
2016-01-19 12:09:42 +01:00
if [ ! "${FIND2}" = "" -a ! "${FIND2}" = "[plugin_name]" ]; then
2019-09-17 14:04:30 +02:00
if [ ${PLUGIN_PHASE} -eq 1 ]; then N_PLUGIN=$((N_PLUGIN + 1)); fi
2016-04-07 16:24:11 +02:00
# Check if the plugin is enabled in any of the profiles
PLUGIN_ENABLED_STATE=0
for PROFILE in ${PROFILES}; do
2016-04-27 15:37:07 +02:00
LogText "Action: checking plugin status in profile: ${PROFILE}"
2017-03-06 08:41:21 +01:00
FIND3=$(grep "^plugin=${FIND2}" ${PROFILE})
2019-07-16 13:20:30 +02:00
if [ -n "${FIND3}" ]; then
2019-07-03 15:39:26 +02:00
FOUND=0
for I in ${DISABLED_PLUGINS}; do
if [ "${I}" = "${FIND2}" ]; then
FOUND=1
LogText "Result: plugin ${FIND2} is specifically disabled"
fi
done
if [ ${FOUND} -eq 0 ]; then
LogText "Result: plugin enabled in profile (${PROFILE})"
PLUGIN_ENABLED_STATE=1
fi
2016-04-07 16:24:11 +02:00
fi
done
if [ ${PLUGIN_ENABLED_STATE} -eq 1 ]; then
2016-04-27 15:37:07 +02:00
LogText "Result: plugin ${FIND2} is enabled"
2016-01-19 12:09:42 +01:00
PLUGINFILE="${PLUGINDIR}/plugin_${FIND2}_phase${PLUGIN_PHASE}"
if [ -f ${PLUGINFILE} ]; then
2017-03-06 08:41:21 +01:00
PLUGIN_VERSION=$(grep "^# PLUGIN_VERSION=" ${PLUGIN_FILE} | awk -F= '{ print $2 }')
PLUGIN_VERSION_NODOTS=$(echo ${PLUGIN_VERSION} | sed 's/.//g')
2016-05-09 13:47:57 +02:00
if SafePerms ${PLUGINFILE}; then
2016-04-27 15:37:07 +02:00
LogText "Including plugin file: ${PLUGINFILE} (version: ${PLUGIN_VERSION})"
Report "plugin_enabled_phase${PLUGIN_PHASE}[]=${FIND2}|${PLUGIN_VERSION}|"
2019-09-17 14:04:30 +02:00
if [ ${PLUGIN_PHASE} -eq 1 ]; then N_PLUGIN_ENABLED=$((N_PLUGIN_ENABLED + 1)); fi
2016-01-19 12:09:42 +01:00
Display --indent 2 --text "- ${CYAN}Plugin${NORMAL}: ${WHITE}${FIND2}${NORMAL}"
if [ ${PLUGIN_PHASE} -eq 1 ]; then Progress " ["; fi
. ${PLUGINFILE}
if [ ${PLUGIN_PHASE} -eq 1 ]; then Progress "]"; Progress --finish; fi
2016-04-28 12:58:03 +02:00
LogTextBreak
2016-04-27 15:37:07 +02:00
LogText "Result: ${FIND2} plugin (phase ${PLUGIN_PHASE}) finished"
2016-10-23 16:26:22 +02:00
else
2016-05-09 13:47:57 +02:00
LogText "Plugin ${FIND2}: Skipped (bad file permissions, should be 644, 640, 600 or 400)"
2016-01-19 12:09:42 +01:00
fi
2016-10-23 16:26:22 +02:00
else
2016-05-09 13:47:57 +02:00
LogText "Plugin ${FIND2}: Skipped for phase ${PLUGIN_PHASE} (no file found: ${PLUGINFILE})"
2015-01-30 20:01:07 +01:00
fi
2016-10-23 16:26:22 +02:00
else
2016-04-27 15:37:07 +02:00
LogText "Plugin ${FIND2}: Skipped (not enabled)"
2014-08-26 17:33:55 +02:00
fi
2016-10-23 16:26:22 +02:00
else
2016-04-27 15:37:07 +02:00
LogText "Skipping plugin file ${PLUGIN_FILE} (no valid plugin name found)"
2014-08-26 17:33:55 +02:00
fi
fi
2016-04-27 15:37:07 +02:00
LogText "--"
2016-01-19 12:09:42 +01:00
done
2016-04-27 15:37:07 +02:00
LogText "Result: Found ${N_PLUGIN} plugins of which ${N_PLUGIN_ENABLED} are enabled"
2016-05-09 13:47:57 +02:00
LogText "Result: Plugins phase ${PLUGIN_PHASE} finished"
2015-10-01 22:41:57 +02:00
}
RunPlugins 1
2015-01-30 20:01:07 +01:00
if [ ${N_PLUGIN_ENABLED} -eq 0 ]; then
2016-06-18 11:15:57 +02:00
Display --indent 2 --text "- ${GEN_PLUGINS_ENABLED}" --result "NONE" --color WHITE
2016-04-27 15:37:07 +02:00
Report "plugins_enabled=0"
2016-10-23 16:26:22 +02:00
else
2016-04-27 15:37:07 +02:00
Report "plugins_enabled=1"
2014-08-26 17:33:55 +02:00
fi
fi
#
#################################################################################
#
# Get host ID
2016-04-28 12:58:03 +02:00
LogTextBreak
2014-08-26 17:33:55 +02:00
GetHostID
2015-03-03 10:59:46 +01:00
# Check if result is not empty (no blank, or hash of blank value, or minus, or zeros)
if [ ! "${HOSTID}" = "-" -a ! "${HOSTID}" = "" -a ! "${HOSTID}" = "adc83b19e793491b1c6ea0fd8b46cd9f32e592fc" -a ! "${HOSTID}" = "6ef1338f520d075957424741d7ed35ab5966ae97" ]; then
2016-04-27 15:37:07 +02:00
LogText "Info: found valid HostID ${HOSTID}"
Report "hostid=${HOSTID}"
2016-10-23 16:26:22 +02:00
else
2016-04-27 15:37:07 +02:00
LogText "Info: no HostID found or invalid one"
2014-08-26 17:33:55 +02:00
fi
2018-06-28 16:29:16 +02:00
if [ ! "${HOSTID2}" = "" ]; then
Report "hostid2=${HOSTID2}"
fi
2014-09-19 16:44:04 +02:00
if [ ! "${MACHINEID}" = "" ]; then
2016-04-27 15:37:07 +02:00
LogText "Info: found a machine ID ${MACHINEID}"
Report "machineid=${MACHINEID}"
2016-10-23 16:26:22 +02:00
else
2016-04-27 15:37:07 +02:00
LogText "Info: no machine ID found"
2014-09-19 16:44:04 +02:00
fi
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2015-01-30 20:01:07 +01:00
if [ ${RUN_TESTS} -eq 1 ]; then
2016-04-28 12:58:03 +02:00
LogTextBreak
2015-01-30 20:01:07 +01:00
# Test sections
2016-07-24 17:22:00 +02:00
if [ "${TEST_GROUP_TO_CHECK}" = "all" ]; then
2016-04-27 15:37:07 +02:00
LogText "Info: perform tests from all categories"
2015-01-30 20:01:07 +01:00
INCLUDE_TESTS="boot_services kernel memory_processes authentication shells \
2018-05-02 13:19:01 +02:00
filesystems usb storage storage_nfs nameservices dns ports_packages networking printers_spools \
2015-05-27 12:34:19 +02:00
mail_messaging firewalls webservers ssh snmp databases ldap php squid logging \
insecure_services banners scheduling accounting time crypto virtualization containers \
2015-07-22 17:35:03 +02:00
mac_frameworks file_integrity tooling malware file_permissions homedirs \
2015-05-27 12:34:19 +02:00
kernel_hardening hardening"
2016-10-23 16:26:22 +02:00
else
2016-07-24 17:22:00 +02:00
INCLUDE_TESTS="${TEST_GROUP_TO_CHECK}"
LogText "Info: only performing tests from groups: ${TEST_GROUP_TO_CHECK}"
2015-01-30 20:01:07 +01:00
fi
2014-08-26 17:33:55 +02:00
2015-01-30 20:01:07 +01:00
# Include available tests
for INCLUDE_TEST in ${INCLUDE_TESTS}; do
2016-05-02 15:44:52 +02:00
INCLUDE_FILE="${INCLUDEDIR}/tests_${INCLUDE_TEST}"
if [ -f ${INCLUDE_FILE} ]; then
2019-07-12 13:14:41 +02:00
if SafeFile ${INCLUDE_FILE}; then
2016-05-02 15:44:52 +02:00
. ${INCLUDE_FILE}
2016-10-23 16:26:22 +02:00
else
2016-05-02 15:44:52 +02:00
LogText "Exception: skipping test category ${INCLUDE_TEST}, file ${INCLUDE_FILE} has bad permissions (should be 640, 600 or 400)"
2016-08-10 07:24:10 +02:00
ReportWarning "NONE" "Invalid permissions on tests file tests_${INCLUDE_TEST}"
2016-05-02 15:44:52 +02:00
# Insert a section and warn user also on screen
InsertSection "General"
Display --indent 2 --text "- Running test category ${INCLUDE_TEST}... " --result "SKIPPED" --color RED
fi
2016-10-23 16:26:22 +02:00
else
2016-05-02 15:44:52 +02:00
echo "Error: Can't find file (category: ${INCLUDE_TEST})"
2015-01-30 20:01:07 +01:00
fi
done
fi
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
2015-01-30 20:01:07 +01:00
if [ ${RUN_TESTS} -eq 1 ]; then
2016-06-18 11:15:57 +02:00
InsertSection "${SECTION_CUSTOM_TESTS}"
2016-04-27 15:37:07 +02:00
LogText "Test: Checking for tests_custom file"
2015-01-30 20:01:07 +01:00
# Custom tests
if [ -f ${INCLUDEDIR}/tests_custom ]; then
2016-04-27 15:37:07 +02:00
LogText "Result: tests_custom file found in include directory"
2016-05-02 17:12:43 +02:00
if SafePerms ${INCLUDEDIR}/tests_custom; then
2015-01-30 20:01:07 +01:00
Display --indent 2 --text "- Start custom tests... "
2016-04-27 15:37:07 +02:00
LogText "Result: file permissions fine, running custom tests"
2015-01-30 20:01:07 +01:00
. ${INCLUDEDIR}/tests_custom
2016-10-23 16:26:22 +02:00
else
2016-04-27 15:37:07 +02:00
LogText "Exception: skipping custom tests, file has bad permissions (should be 640, 600 or 400)"
2016-08-10 07:24:10 +02:00
ReportWarning "NONE" "Invalid permissions on custom tests file"
2015-01-30 20:01:07 +01:00
Display --indent 2 --text "- Running custom tests... " --result "WARNING" --color RED
fi
2016-10-23 16:26:22 +02:00
else
2015-01-30 20:01:07 +01:00
Display --indent 2 --text "- Running custom tests... " --result "NONE" --color WHITE
fi
fi
#
#################################################################################
#
# Run helpers
#
#################################################################################
#
if [ ${RUN_HELPERS} -eq 1 ]; then
if [ ! "${HELPER}" = "" ]; then
2016-04-27 15:37:07 +02:00
LogText "Helper tool is $HELPER"
2015-01-30 20:01:07 +01:00
if [ -f ${INCLUDEDIR}/helper_${HELPER} ]; then
SafePerms ${INCLUDEDIR}/helper_${HELPER}
2016-04-27 15:37:07 +02:00
LogText "Running helper tool ${HELPER} with params: ${HELPER_PARAMS}"
2015-04-29 12:21:52 +02:00
InsertPluginSection "Helper: ${HELPER}"
2015-01-30 20:01:07 +01:00
. ${INCLUDEDIR}/helper_${HELPER} ${HELPER_PARAMS}
2016-10-23 16:26:22 +02:00
else
2015-01-30 20:01:07 +01:00
echo "Error, could not find helper"
fi
2014-08-26 17:33:55 +02:00
fi
fi
2015-10-01 22:41:57 +02:00
#
#################################################################################
#
# Run phase 2 of plugins
#
#################################################################################
#
2016-07-05 17:26:27 +02:00
if [ ${SKIP_PLUGINS} -eq 0 ]; then
2015-10-01 22:41:57 +02:00
RunPlugins 2
2016-05-09 13:47:57 +02:00
if [ ${N_PLUGIN_ENABLED} -gt 1 ]; then
Display --indent 2 --text "- Plugins (phase 2)" --result "DONE" --color GREEN
fi
2015-10-01 22:41:57 +02:00
fi
2014-08-26 17:33:55 +02:00
#
#################################################################################
#
# Show test results overview
#
#################################################################################
#
# Store total performed tests
2016-04-27 15:37:07 +02:00
Report "lynis_tests_done=${CTESTS_PERFORMED}"
2016-10-23 16:26:22 +02:00
CDATE=$(date "+%F %H:%M:%S")
2016-04-27 15:37:07 +02:00
Report "report_datetime_end=${CDATE}"
2014-08-26 17:33:55 +02:00
# Show report
if [ -f ${INCLUDEDIR}/report ]; then SafePerms ${INCLUDEDIR}/report; . ${INCLUDEDIR}/report; fi
2015-09-10 21:04:50 +02:00
# Show tool tips
2019-03-14 10:45:08 +01:00
if [ -f ${INCLUDEDIR}/tool_tips ]; then SafePerms ${INCLUDEDIR}/tool_tips; . ${INCLUDEDIR}/tool_tips; fi
2015-09-10 21:04:50 +02:00
2016-04-27 15:37:07 +02:00
LogText "================================================================================"
LogText "Tests performed: ${CTESTS_PERFORMED}"
LogText "Total tests: ${TOTAL_TESTS}"
LogText "Active plugins: ${N_PLUGIN_ENABLED}"
LogText "Total plugins: ${N_PLUGIN}"
LogText "================================================================================"
Report "tests_executed=${TESTS_EXECUTED}"
Report "tests_skipped=${TESTS_SKIPPED}"
Report "finish=true"
2014-08-26 17:33:55 +02:00
# Upload data
if [ ${UPLOAD_DATA} -eq 1 ]; then
if [ -f ${INCLUDEDIR}/data_upload ]; then
SafePerms ${INCLUDEDIR}/data_upload
. ${INCLUDEDIR}/data_upload
2016-10-23 16:26:22 +02:00
else
2014-08-26 17:33:55 +02:00
echo "Fatal error: can't find upload_data script"
fi
fi
2016-04-27 15:37:07 +02:00
LogText "${PROGRAM_NAME} ${PROGRAM_VERSION}"
LogText "${PROGRAM_COPYRIGHT}"
LogText "${PROGRAM_EXTRAINFO}"
LogText "Program ended successfully"
LogText "================================================================================"
2015-02-03 18:05:09 +01:00
2019-09-10 14:51:25 +02:00
# Tool tips
if [ ${QUIET} -eq 0 ]; then
if [ -z "${CUSTOM_PROFILE}" ]; then DisplayToolTip "Enhance ${PROGRAM_NAME} audits by adding your settings to custom.prf (see ${DEFAULT_PROFILE} for all settings)"; fi
fi
2016-07-05 18:18:54 +02:00
2014-08-26 17:33:55 +02:00
# Clean exit (Delete PID file)
2015-09-10 09:18:41 +02:00
if [ ${TOTAL_WARNINGS} -gt 0 ]; then
2016-04-25 10:18:09 +02:00
# Use exit code 78 if we found any warnings (and enabled)
if [ ${ERROR_ON_WARNINGS} -eq 1 ]; then
ExitCustom 78
2016-10-23 16:26:22 +02:00
else
2016-04-25 10:18:09 +02:00
ExitClean
fi
2016-10-23 16:26:22 +02:00
else
2015-09-10 09:18:41 +02:00
ExitClean
fi
2014-08-26 17:33:55 +02:00
# The End
#
#================================================================================
2019-01-31 14:47:35 +01:00
# Lynis - Copyright 2007-2019, Michael Boelen, CISOfy - https://cisofy.com