2014-08-26 17:33:55 +02:00
#!/bin/sh
#################################################################################
#
# Lynis
# ------------------
#
2016-03-13 16:00:39 +01:00
# Copyright 2007-2013, Michael Boelen
2020-03-20 14:50:25 +01:00
# Copyright 2007-2020, CISOfy
2014-08-26 17:33:55 +02:00
#
2016-03-13 16:00:39 +01:00
# Website : https://cisofy.com
# Blog : http://linux-audit.com
# GitHub : https://github.com/CISOfy/lynis
#
# 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-08-26 17:33:55 +02:00
#
#################################################################################
#
# Functions
#
#################################################################################
#
# Function Description
# ----------------------- -------------------------------------------------
# AddHP Add Hardening points to plot a graph later
2016-07-05 16:47:32 +02:00
# AddSetting Addition of setting
2015-05-13 14:45:50 +02:00
# AddSystemGroup Adds a system to a group
2014-08-26 17:33:55 +02:00
# CheckFilePermissions Check file permissions
2017-03-05 15:12:01 +01:00
# CheckItem Test for presence of a string in report file
2014-08-26 17:33:55 +02:00
# CheckUpdates Determine if a new version of Lynis is available
2016-07-05 12:16:49 +02:00
# CleanUp Clean up files before closing program
2016-04-28 12:31:38 +02:00
# CountTests Count number of performed tests
2016-04-13 11:48:02 +02:00
# ContainsString Find the needle (string) in the haystack (another string)
2016-07-05 12:16:49 +02:00
# CreateTempFile Create a temporary file
2014-08-26 17:33:55 +02:00
# Debug Display additional information on the screen (not suited for cronjob)
2015-09-30 18:34:16 +02:00
# DigitsOnly Return only the digits from a string
2014-08-26 17:33:55 +02:00
# DirectoryExists Check if a directory exists on the disk
2016-07-05 16:47:32 +02:00
# DiscoverProfiles Determine available profiles on system
2014-08-26 17:33:55 +02:00
# Display Output text to screen with colors and identation
2016-07-24 13:11:32 +02:00
# DisplayError Show an error on screen
2019-08-21 14:50:32 +02:00
# DisplayException Show an exception on screen
2015-10-01 22:40:29 +02:00
# DisplayManual Output text to screen without any layout
2016-07-05 17:25:19 +02:00
# DisplayToolTip Show a tip for improving usage of the tool
2019-07-07 18:47:55 +02:00
# DisplayWarning Show a clear warning on screen
2019-07-08 15:05:28 +02:00
# Equals Compares two strings
2015-05-26 11:11:15 +02:00
# ExitClean Stop the program (cleanly), with exit code 0
2015-09-10 08:35:09 +02:00
# ExitCustom Stop the program (cleanly), with custom exit code
2015-05-26 11:11:15 +02:00
# ExitFatal Stop the program (cleanly), with exit code 1
2014-08-26 17:33:55 +02:00
# FileExists Check if a file exists on the disk
2017-03-12 16:36:02 +01:00
# FileInstalledByPackage Check if a file is linked to a package
2014-09-17 09:59:18 +02:00
# FileIsEmpty Check if a file is empty
2014-09-08 21:30:54 +02:00
# FileIsReadable Check if a file is readable or directory accessible
2014-08-26 17:33:55 +02:00
# GetHostID Retrieve an unique ID for this host
2019-07-14 15:12:25 +02:00
# GetReportData Request data from report
2019-08-20 14:49:34 +02:00
# HasCorrectFilePermissions Check file permissions and see if they match expected values
2017-04-23 20:19:18 +02:00
# HasData Checks for data in variable
2016-07-05 12:16:49 +02:00
# InsertSection Insert a section block
# InsertPluginSection Insert a section block for plugins
2016-10-16 15:13:04 +02:00
# IsContainer Determine if program runs in a container
2016-04-19 19:44:23 +02:00
# IsDebug Check if --debug is used
2016-04-26 13:40:21 +02:00
# IsDeveloperMode Check if --developer is used
2016-06-18 09:28:53 +02:00
# IsDeveloperVersion Check if program is a developer release
2017-04-23 20:19:18 +02:00
# IsEmpty Check for empty result or variable
2016-08-13 16:38:07 +02:00
# IsNotebook System detection
2016-04-26 21:20:37 +02:00
# IsOwnedByRoot Determine if file or directory is owned by root
2016-08-13 16:38:07 +02:00
# IsRunning Check if a process is running
2016-04-19 19:44:23 +02:00
# IsVerbose Check if --verbose is used
2014-09-12 14:56:19 +02:00
# IsVirtualMachine Check if this system is a virtual machine
2015-03-25 17:31:47 +01:00
# IsWorldExecutable Check if a file is world executable
# IsWorldReadable Check if a file is world readable
# IsWorldWritable Check if a file is world writable
2015-12-22 16:02:32 +01:00
# LogText Log text strings to logfile, prefixed with date/time
2016-04-28 12:31:38 +02:00
# LogTextBreak Insert a separator in log file
2018-02-19 15:01:26 +01:00
# PackageIsInstalled Test for installed package
2014-08-26 17:33:55 +02:00
# ParseNginx Parse nginx configuration lines
2016-07-05 16:47:32 +02:00
# ParseProfiles Parse all available profiles
2016-05-04 21:38:42 +02:00
# ParseTestValues Parse a set of values
2016-03-30 13:45:34 +02:00
# PortIsListening Check if machine is listening on specified protocol and port
2014-11-25 14:22:52 +01:00
# Progress Show progress on screen
2019-07-05 18:35:45 +02:00
# Readonly Mark a variable as read-only data
2017-01-16 12:03:07 +01:00
# Register Register a test (for logging and execution)
2015-12-22 16:02:32 +01:00
# RandomString Show a random string
2016-07-18 19:58:32 +02:00
# RemoveColors Reset all colors
2016-01-11 01:04:04 +01:00
# RemovePIDFile Remove PID file
# RemoveTempFiles Remove temporary files
2015-12-22 16:02:32 +01:00
# Report Add string of data to report file
2016-04-13 16:11:46 +02:00
# ReportDetails Store details of tests which include smaller atomic tests in report
2014-08-26 17:33:55 +02:00
# ReportException Add an exception to the report file (for debugging purposes)
2017-01-16 12:03:07 +01:00
# ReportManual Log manual actions to report file
2014-08-26 17:33:55 +02:00
# ReportSuggestion Add a suggestion to report file
# ReportWarning Add a warning and priority to report file
2019-07-12 13:05:43 +02:00
# SafeFile Security tests to perform on a file before using it
2017-03-07 20:23:08 +01:00
# SafePerms Check if a file has safe permissions
2019-06-29 19:34:12 +02:00
# SafeInput Test provided string to see if it contains unwanted characters
2014-08-26 17:33:55 +02:00
# SearchItem Search a string in a file
2015-10-01 13:16:27 +02:00
# ShowComplianceFinding Display a particular finding regarding compliance or a security standard
2014-09-12 15:33:28 +02:00
# ShowSymlinkPath Show a path behind a symlink
2016-04-19 12:37:00 +02:00
# SkipAtomicTest Test if a subtest needs to be skipped
2019-11-18 10:19:43 +01:00
# Status Show execution status, such as active test being performed
2016-08-16 08:11:51 +02:00
# StoreNginxSettings Save parsed nginx settings to file
2016-01-01 14:56:09 +01:00
# TestValue Evaluate a value in a string or key
2016-07-24 17:22:00 +02:00
# ViewCategories Show available category of tests
# ViewGroups Display test groups
2016-04-28 12:31:38 +02:00
# WaitForKeyPress Wait for user to press a key to continue
#
2014-08-26 17:33:55 +02:00
#################################################################################
2016-04-19 17:48:06 +02:00
################################################################################
# Name : AddHP()
2016-04-28 12:31:38 +02:00
# Description : Add hardening points and count them
#
2019-07-10 19:36:51 +02:00
# Parameters : $1 = points to add (0 or higher)
# $2 = maximum points (at least value of $1 or higher)
2016-04-19 17:48:06 +02:00
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
# Usage : AddHP 1 3
2016-04-19 17:48:06 +02:00
################################################################################
2016-04-19 17:35:45 +02:00
AddHP() {
2014-08-26 17:33:55 +02:00
HPADD=$1; HPADDMAX=$2
2016-05-03 14:57:53 +02:00
HPPOINTS=$((HPPOINTS + HPADD))
HPTOTAL=$((HPTOTAL + HPADDMAX))
2016-03-13 22:35:57 +01:00
if [ ${HPADD} -eq ${HPADDMAX} ]; then
2016-04-19 17:35:45 +02:00
LogText "Hardening: assigned maximum number of hardening points for this item (${HPADDMAX}). Currently having ${HPPOINTS} points (out of ${HPTOTAL})"
2017-04-30 17:59:35 +02:00
else
2016-04-19 17:35:45 +02:00
LogText "Hardening: assigned partial number of hardening points (${HPADD} of ${HPADDMAX}). Currently having ${HPPOINTS} points (out of ${HPTOTAL})"
2016-03-13 22:35:57 +01:00
fi
2016-04-19 17:48:06 +02:00
}
2014-08-26 17:33:55 +02:00
2015-05-13 14:45:50 +02:00
2016-07-05 16:47:32 +02:00
################################################################################
# Name : AddSetting()
# Description : Addition of a setting for display with 'lynis show settings'
#
2019-07-10 19:36:51 +02:00
# Parameters : $1 = setting
# $2 = value
# $3 = description
2016-07-05 16:47:32 +02:00
# Returns : <nothing>
# Usage : AddSetting debug 1 'Debug mode'
################################################################################
AddSetting() {
if [ $# -eq 3 ]; then
2016-07-31 17:18:36 +02:00
SETTING="$1"
VALUE="$2"
DESCRIPTION="$3"
2016-07-05 16:47:32 +02:00
if [ -z "${SETTINGS_FILE}" ]; then
CreateTempFile
SETTINGS_FILE="${TEMP_FILE}"
fi
2019-09-19 14:05:15 +02:00
FIND=$(grep -E "^${SETTING};" ${SETTINGS_FILE})
2016-07-05 16:47:32 +02:00
if [ -z "${FIND}" ]; then
2016-07-31 17:18:36 +02:00
echo "${SETTING};${VALUE};${DESCRIPTION};" >> ${SETTINGS_FILE}
2017-04-30 17:59:35 +02:00
else
2016-07-31 17:18:36 +02:00
Debug "Setting '${SETTING}' was already configured, overwriting previous line '${FIND}' in ${SETTINGS_FILE} with value '${VALUE}'"
# Delete line first, then add new value (inline search and replace is messy)
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
CreateTempFile
TEMP_SETTINGS_FILE="${TEMP_FILE}"
cat ${SETTINGS_FILE} > ${TEMP_SETTINGS_FILE}
sed -e '/^'"${SETTING}"';/d' ${TEMP_SETTINGS_FILE} > ${SETTINGS_FILE}
2019-07-10 19:36:51 +02:00
rm "${TEMP_SETTINGS_FILE}"
2016-07-31 17:18:36 +02:00
echo "${SETTING};${VALUE};${DESCRIPTION};" >> ${SETTINGS_FILE}
2016-07-05 16:47:32 +02:00
fi
else
echo "Error: incorrect call to AddSetting. Needs 3 arguments."
fi
}
2015-05-13 14:45:50 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : AddSystemGroup()
2015-05-13 14:45:50 +02:00
# Description : Adds a system to a group, which can be used for categorizing
2016-04-28 12:31:38 +02:00
#
2019-07-10 19:36:51 +02:00
# Parameters : $1 = group name
2015-05-13 14:45:50 +02:00
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
# Usage : AddSystemGroup "test"
2015-05-13 14:45:50 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
AddSystemGroup() {
2015-12-22 16:02:32 +01:00
Report "system_group[]=$1"
2016-04-28 12:31:38 +02:00
}
2015-05-13 14:45:50 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : CheckFilePermissions()
2016-07-30 12:08:43 +02:00
# Description : Check file permissions
2016-04-28 12:31:38 +02:00
#
2019-07-10 19:36:51 +02:00
# Parameters : Full path to file or directory
2016-04-28 12:31:38 +02:00
# Returns : PERMS (FILE_NOT_FOUND | OK | BAD)
# Notes : This function might be replaced in future
################################################################################
CheckFilePermissions() {
2019-07-10 19:36:51 +02:00
CHECKFILE="$1"
2016-04-28 12:31:38 +02:00
if [ ! -d ${CHECKFILE} -a ! -f ${CHECKFILE} ]; then
2014-08-26 17:33:55 +02:00
PERMS="FILE_NOT_FOUND"
2019-08-17 16:48:46 +02:00
FILEVALUE=""
2017-04-30 17:59:35 +02:00
else
2014-08-26 17:33:55 +02:00
# If 'file' is an directory, use -d
if [ -d ${CHECKFILE} ]; then
2017-03-06 08:41:21 +01:00
FILEVALUE=$(ls -d -l ${CHECKFILE} | cut -c 2-10)
2019-07-18 18:58:11 +02:00
PROFILEVALUE=$(grep '^permdir' ${PROFILE} | grep "=${CHECKFILE}:" | cut -d: -f2)
2017-04-30 17:59:35 +02:00
else
2017-03-06 08:41:21 +01:00
FILEVALUE=$(ls -l ${CHECKFILE} | cut -c 2-10)
2019-07-18 18:58:11 +02:00
PROFILEVALUE=$(grep '^permfile' ${PROFILE} | grep "=${CHECKFILE}:" | cut -d: -f2)
2014-08-26 17:33:55 +02:00
fi
if [ "${FILEVALUE}" = "${PROFILEVALUE}" ]; then PERMS="OK"; else PERMS="BAD"; fi
fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2014-09-08 21:30:54 +02:00
2014-08-26 17:33:55 +02:00
################################################################################
# Name : CheckItem()
# Description : Check if a specific item exists in the report
2016-04-28 12:31:38 +02:00
#
2019-07-10 19:36:51 +02:00
# Parameters : $1 = key
# $2 = value
2019-08-01 14:59:03 +02:00
# Returns : exit code (0 = True, 1 = False)
2019-07-10 19:36:51 +02:00
# Usage : if CheckItem "key" "value"; then ....; fi
2014-08-26 17:33:55 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
CheckItem() {
2017-04-30 17:59:35 +02:00
RETVAL=255
if [ $# -eq 2 ]; then
# Don't search in /dev/null, it's too empty there
if [ ! "${REPORTFILE}" = "/dev/null" ]; then
# Check if we can find the main type (with or without brackets)
LogText "Test: search string $2 in earlier discovered results"
2019-09-19 14:05:15 +02:00
FIND=$(grep -E "^$1(\[\])?=" ${REPORTFILE} | grep -E "$2")
2017-04-30 17:59:35 +02:00
if HasData "${FIND}"; then
RETVAL=0
LogText "Result: found search string (result: $FIND)"
else
LogText "Result: search string NOT found"
RETVAL=1
fi
else
LogText "Skipping search, as /dev/null is being used"
fi
return ${RETVAL}
else
ReportException ${TEST_NO} "Error in function call to CheckItem"
fi
2016-04-10 16:32:21 +02:00
}
################################################################################
2016-04-28 12:31:38 +02:00
# Name : CheckUpdates()
# Description : Determine if there is an update available
2019-07-10 20:22:31 +02:00
#
2016-04-28 12:31:38 +02:00
# Returns : <nothing>
# Usage : CheckUpdates
# Use PROGRAM_LV (latest version) and compare it with actual version (PROGRAM_AC)
2016-04-10 16:32:21 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
CheckUpdates() {
2014-08-26 17:33:55 +02:00
PROGRAM_LV="0000000000"; DB_MALWARE_LV="0000000000"; DB_FILEPERMS_LV="0000000000"
2016-08-23 20:21:26 +02:00
if [ ${RUN_UPDATE_CHECK} -eq 1 ]; then
LYNIS_LV_RECORD="lynis-latest-version.cisofy.com."
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
FIND=$(which dig 2> /dev/null | grep -v "no [^ ]* in")
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2016-08-23 20:21:26 +02:00
PROGRAM_LV=$(dig +short +time=3 -t txt lynis-latest-version.cisofy.com 2> /dev/null | grep -v "connection timed out" | sed 's/[".]//g' | grep "^[1-9][0-9][0-9]$")
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
FIND=$(which host 2> /dev/null | grep -v "no [^ ]* in ")
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2016-08-23 20:21:26 +02:00
PROGRAM_LV=$(host -t txt -W 3 lynis-latest-version.cisofy.com 2> /dev/null | grep -v "connection timed out" | awk '{ if ($1=="lynis-latest-version.cisofy.com" && $3=="text") { print $4 }}' | sed 's/"//g' | grep "^[1-9][0-9][0-9]$")
2014-09-22 04:07:46 +02:00
if [ "${PROGRAM_LV}" = "" ]; then PROGRAM_LV=0; fi
2016-08-23 20:21:26 +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
FIND=$(which drill 2> /dev/null | grep -v "no [^ ]* in ")
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2016-08-23 20:21:26 +02:00
PROGRAM_LV=$(drill txt ${LYNIS_LV_RECORD} | awk '{ if ($1=="lynis-latest-version.cisofy.com." && $4=="TXT") { print $5 }}' | tr -d '"' | grep "^[1-9][0-9][0-9]$")
if [ -z "${PROGRAM_LV}" ]; then PROGRAM_LV=0; fi
else
LogText "Result: dig, drill or host not installed, update check skipped"
UPDATE_CHECK_SKIPPED=1
fi
2014-09-22 04:07:46 +02:00
fi
2014-08-26 17:33:55 +02:00
fi
2016-08-23 20:21:26 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2016-07-05 12:16:49 +02:00
################################################################################
# Name : CleanUp()
2019-07-10 20:22:31 +02:00
# Description : Delete PID and temporary files, stop execution (exit code 1)
#
2019-08-01 14:59:03 +02:00
# Parameters : <none>
# Returns : <nothing>
2019-07-10 20:22:31 +02:00
# Usage : this function is triggered by a manual break by user
2016-07-05 12:16:49 +02:00
################################################################################
CleanUp() {
echo ""; echo "Interrupt detected."
RemovePIDFile
RemoveTempFiles
Display --text "Cleaning up..." --result DONE --color GREEN
ExitFatal
}
2016-04-28 12:31:38 +02:00
################################################################################
# Name : ContainsString()
# Description : Search a specific string (or regular expression) in another
2019-07-10 20:22:31 +02:00
#
2019-08-01 14:59:03 +02:00
# Returns : exit code (0 = True, 1 = False)
2016-04-28 12:31:38 +02:00
# Usage : if ContainsString "needle" "there is a needle in the haystack"; echo "Found"; else "Not found"; fi
################################################################################
ContainsString() {
2016-05-09 14:20:16 +02:00
RETVAL=1
2016-04-28 12:31:38 +02:00
if [ $# -ne 2 ]; then ReportException "ContainsString" "Incorrect number of arguments for ContainsStrings function"; fi
2019-09-19 14:05:15 +02:00
FIND=$(echo "$2" | grep -E "$1")
2016-04-28 12:31:38 +02:00
if [ ! "${FIND}" = "" ]; then RETVAL=0; fi
return ${RETVAL}
}
################################################################################
# Name : CountTests()
2019-07-10 20:22:31 +02:00
# Description : Counter for the number of tests performed
2016-04-28 12:31:38 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : <none>
# Returns : <nothing>
2019-07-10 20:22:31 +02:00
# Usage : Call CountTests to increase number by 1
2016-04-28 12:31:38 +02:00
################################################################################
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
CountTests() {
2016-05-03 14:57:53 +02:00
CTESTS_PERFORMED=$((CTESTS_PERFORMED + 1))
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-01-11 01:04:04 +01:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : CreateTempFile()
2016-01-11 01:04:04 +01:00
# Description : Creates a temporary file
2016-04-28 12:31:38 +02:00
#
# Returns : TEMP_FILE (variable)
# Usage : CreateTempFile
# if [ ! "${TEMP_FILE}" = "" ]; then
# MYTMPFILE="${TEMP_FILE}"
# echo "My temporary file is ${MYTMPFILE}"
# fi
2016-01-11 01:04:04 +01:00
################################################################################
2016-04-28 12:31:38 +02:00
CreateTempFile() {
2016-04-19 10:34:04 +02:00
TEMP_FILE=""
2016-01-11 01:04:04 +01:00
if [ "${OS}" = "AIX" ]; then
2019-09-17 14:04:30 +02:00
RANDOMSTRING1="lynis-$(od -N4 -tu /dev/random | awk 'NR==1 {print $2} {}')"
2016-01-11 01:04:04 +01:00
TEMP_FILE="/tmp/${RANDOMSTRING1}"
touch ${TEMP_FILE}
2017-04-30 17:59:35 +02:00
else
2017-03-06 08:41:21 +01:00
TEMP_FILE=$(mktemp /tmp/lynis.XXXXXXXXXX) || exit 1
2016-01-11 01:04:04 +01:00
fi
if [ ! "${TEMP_FILE}" = "" ]; then
2016-04-28 09:15:54 +02:00
LogText "Action: created temporary file ${TEMP_FILE}"
2017-04-30 17:59:35 +02:00
else
2016-01-11 01:04:04 +01:00
Fatal "Could not create a temporary file"
fi
# Add temporary file to queue for cleanup later
TEMP_FILES="${TEMP_FILES} ${TEMP_FILE}"
2016-04-28 12:31:38 +02:00
}
2016-01-11 01:04:04 +01:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : DirectoryExists()
# Description : Check if a directory exists
#
2019-08-01 14:59:03 +02:00
# Returns : exit code (0 = True, 1 = False)
2016-04-28 12:31:38 +02:00
# Usage : if DirectoryExists; then echo "it exists"; else echo "It does not exist"; fi
################################################################################
2016-01-11 01:04:04 +01:00
2014-08-26 17:33:55 +02:00
# Determine if a directory exists
2016-04-28 12:31:38 +02:00
DirectoryExists() {
2017-04-30 17:59:35 +02:00
if [ $# -eq 0 ]; then ExitFatal "Missing parameter when calling DirectoryExists function"; fi
2014-08-26 17:33:55 +02:00
DIRECTORY_FOUND=0
2015-12-22 16:02:32 +01:00
LogText "Test: checking if directory $1 exists"
2014-08-26 17:33:55 +02:00
if [ -d $1 ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: directory $1 exists"
2014-08-26 17:33:55 +02:00
DIRECTORY_FOUND=1
2016-04-28 12:31:38 +02:00
return 0
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: directory $1 NOT found"
2016-04-28 12:31:38 +02:00
return 1
2014-08-26 17:33:55 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-01-11 01:04:04 +01:00
2015-10-01 22:40:29 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : Debug()
2015-10-01 22:40:29 +02:00
# Description : Show additional information on screen
2016-04-28 12:31:38 +02:00
#
# Input : $1 = text
2019-08-01 14:59:03 +02:00
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
# Usage : Debug "More details"
2015-10-01 22:40:29 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
Debug() {
if [ ${DEBUG} -eq 1 -a $# -gt 0 ]; then echo "${PURPLE}[DEBUG]${NORMAL} $1"; fi
}
2014-08-26 17:33:55 +02:00
2015-10-01 22:40:29 +02:00
2015-09-30 18:34:16 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : DigitsOnly()
2015-09-30 18:34:16 +02:00
# Description : Only extract numbers from a string
2016-04-28 12:31:38 +02:00
#
# Returns : Digits only string (VALUE)
2015-09-30 18:34:16 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
DigitsOnly() {
2015-09-30 18:34:16 +02:00
VALUE=$1
2015-12-22 16:02:32 +01:00
LogText "Value is now: ${VALUE}"
2015-09-30 18:34:16 +02:00
if [ ! "${AWKBINARY}" = "" ]; then
2017-03-06 08:41:21 +01:00
VALUE=$(echo ${VALUE} | grep -Eo '[0-9]{1,}')
2015-09-30 18:34:16 +02:00
fi
2015-12-22 16:02:32 +01:00
LogText "Returning value: ${VALUE}"
2016-04-28 12:31:38 +02:00
}
2015-09-30 18:34:16 +02:00
2015-10-01 22:40:29 +02:00
2016-07-05 16:47:32 +02:00
################################################################################
# Name : DiscoverProfiles()
# Description : Determine which profiles we have available
#
2019-08-01 14:59:03 +02:00
# Returns : <nothing>
2016-07-05 16:47:32 +02:00
# Usage : DiscoverProfiles
################################################################################
DiscoverProfiles() {
# Try to find a default and custom profile, unless one was specified manually
if [ "${PROFILE}" = "" ]; then
CUSTOM_PROFILE=""
DEFAULT_PROFILE=""
PROFILEDIR=""
tPROFILE_NAMES="default.prf custom.prf"
2019-07-25 11:34:58 +02:00
if [ ${USE_CWD} -eq 1 ]; then
tPROFILE_TARGETS="."
else
tPROFILE_TARGETS="/usr/local/etc/lynis /etc/lynis /usr/local/lynis ."
fi
2016-07-05 16:47:32 +02:00
for PNAME in ${tPROFILE_NAMES}; do
for PLOC in ${tPROFILE_TARGETS}; do
# Only use one default.prf
if [ "${PNAME}" = "default.prf" -a ! "${DEFAULT_PROFILE}" = "" ]; then
2017-03-07 20:23:08 +01:00
Debug "Already discovered default.prf - skipping this file (${PLOC}/${PNAME})"
2016-07-05 16:47:32 +02:00
elif [ "${PNAME}" = "custom.prf" -a ! "${CUSTOM_PROFILE}" = "" ]; then
2017-03-07 20:23:08 +01:00
Debug "Already discovered custom.prf - skipping this file (${PLOC}/${PNAME})"
2017-04-30 17:59:35 +02:00
else
2016-07-05 16:47:32 +02:00
if [ "${PLOC}" = "." ]; then FILE="${WORKDIR}/${PNAME}"; else FILE="${PLOC}/${PNAME}"; fi
if [ -r ${FILE} ]; then
PROFILES="${PROFILES} ${FILE}"
case ${PNAME} in
"custom.prf") CUSTOM_PROFILE="${FILE}" ;;
"default.prf") DEFAULT_PROFILE="${FILE}" ;;
esac
# Set profile directory to last match (Lynis could be both installed, and run as a separate download)
if [ "${PLOC}" = "." ]; then PROFILEDIR="${WORKDIR}"; else PROFILEDIR="${PLOC}"; fi
fi
fi
done
done
# Search any profiles defined with --profile
for FILE in ${SEARCH_PROFILES}; do
2019-07-18 11:54:11 +02:00
if [ -r "${FILE}" ]; then
2016-07-05 16:47:32 +02:00
Debug "Found profile defined with --profile"
PROFILES="${PROFILES} ${FILE}"
2019-07-18 11:54:11 +02:00
else
ExitFatal "Could not find or read profile (${FILE})"
2016-07-05 16:47:32 +02:00
fi
done
fi
if [ "${PROFILES}" = "" ]; then
echo "${RED}Fatal error: ${WHITE}No profile defined and could not find default profile${NORMAL}"
echo "Search paths used --> ${tPROFILE_TARGETS}"
ExitCustom 66
2017-04-30 17:59:35 +02:00
else
2017-03-06 08:41:21 +01:00
PROFILES=$(echo ${PROFILES} | sed 's/^ //')
2016-07-05 16:47:32 +02:00
fi
}
2015-10-01 22:40:29 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : Display()
2015-10-01 22:40:29 +02:00
# Description : Show text on screen, with markup
2016-04-28 12:31:38 +02:00
#
# Input : <multiple parameters, see test>
# Returns : <nothing>
2015-10-01 22:40:29 +02:00
################################################################################
2016-04-25 11:10:23 +02:00
Display() {
2016-04-02 18:28:02 +02:00
INDENT=0; TEXT=""; RESULT=""; COLOR=""; SPACES=0; SHOWDEBUG=0
2014-08-26 17:33:55 +02:00
while [ $# -ge 1 ]; do
case $1 in
--color)
shift
case $1 in
GREEN) COLOR=$GREEN ;;
RED) COLOR=$RED ;;
WHITE) COLOR=$WHITE ;;
YELLOW) COLOR=$YELLOW ;;
esac
;;
2016-04-02 18:28:02 +02:00
--debug)
SHOWDEBUG=1
;;
2014-08-26 17:33:55 +02:00
--indent)
shift
INDENT=$1
;;
--result)
2019-01-31 14:27:36 +01:00
shift
2014-08-26 17:33:55 +02:00
RESULT=$1
;;
--text)
2019-01-31 14:27:36 +01:00
shift
2014-08-26 17:33:55 +02:00
TEXT=$1
;;
*)
echo "INVALID OPTION (Display): $1"
2016-01-11 01:04:04 +01:00
ExitFatal
2014-08-26 17:33:55 +02:00
;;
esac
# Go to next parameter
2019-01-31 14:27:36 +01:00
shift
2014-08-26 17:33:55 +02:00
done
2017-10-29 11:26:25 +01:00
if [ -z "${RESULT}" ]; then
2014-08-26 17:33:55 +02:00
RESULTPART=""
2017-04-30 17:59:35 +02:00
else
2014-08-26 17:33:55 +02:00
if [ ${CRONJOB} -eq 0 ]; then
RESULTPART=" [ ${COLOR}${RESULT}${NORMAL} ]"
2017-04-30 17:59:35 +02:00
else
2014-08-26 17:33:55 +02:00
RESULTPART=" [ ${RESULT} ]"
fi
fi
2019-07-16 13:20:30 +02:00
if [ -n "${TEXT}" ]; then
2016-05-09 14:20:16 +02:00
SHOW=0
2016-04-25 11:51:37 +02:00
if [ ${SHOW_WARNINGS_ONLY} -eq 1 ]; then
if [ "${RESULT}" = "WARNING" ]; then SHOW=1; fi
elif [ ${QUIET} -eq 0 ]; then SHOW=1
fi
2016-04-25 11:10:23 +02:00
if [ ${SHOW} -eq 1 ]; then
2016-07-26 15:00:05 +02:00
# Display:
2017-10-29 11:26:25 +01:00
# - for full shells, count with -m instead of -c, to support language locale (older busybox does not have -m)
# - wc needs LANG to deal with multi-bytes characters but LANG has been unset in include/consts
2017-03-06 08:41:21 +01:00
LINESIZE=$(export LC_ALL= ; export LANG="${DISPLAY_LANG}";echo "${TEXT}" | wc -m | tr -d ' ')
2016-04-02 18:28:02 +02:00
if [ ${SHOWDEBUG} -eq 1 ]; then DEBUGTEXT=" [${PURPLE}DEBUG${NORMAL}]"; else DEBUGTEXT=""; fi
2016-05-03 14:57:53 +02:00
if [ ${INDENT} -gt 0 ]; then SPACES=$((62 - INDENT - LINESIZE)); fi
2016-06-18 11:14:50 +02:00
if [ ${SPACES} -lt 0 ]; then SPACES=0; fi
2014-08-26 17:33:55 +02:00
if [ ${CRONJOB} -eq 0 ]; then
2014-09-11 16:11:43 +02:00
# Check if we already have already discovered a proper echo command tool. It not, set it default to 'echo'.
if [ "${ECHOCMD}" = "" ]; then ECHOCMD="echo"; fi
2016-04-02 18:28:02 +02:00
${ECHOCMD} "\033[${INDENT}C${TEXT}\033[${SPACES}C${RESULTPART}${DEBUGTEXT}"
2017-04-30 17:59:35 +02:00
else
2014-08-26 17:33:55 +02:00
echo "${TEXT}${RESULTPART}"
fi
fi
fi
2016-04-25 11:10:23 +02:00
}
2014-08-26 17:33:55 +02:00
2015-10-01 22:40:29 +02:00
2016-07-24 13:11:32 +02:00
################################################################################
# Name : DisplayError()
# Description : Show error on screen
#
2016-07-31 11:46:41 +02:00
# Input : $1 = text (string), $2 = optional exit code (integer)
2016-07-24 13:11:32 +02:00
# Returns : <nothing>
################################################################################
DisplayError() {
2016-07-31 11:46:41 +02:00
EXITCODE=""
if [ $# -gt 1 ]; then EXITCODE=$2; fi
${ECHOCMD} ""
2016-07-24 13:11:32 +02:00
${ECHOCMD} "${WARNING}Error${NORMAL}: ${BOLD}$1${NORMAL}"
${ECHOCMD} ""
2019-07-16 13:20:30 +02:00
if [ -n "${EXITCODE}" ]; then ExitCustom ${EXITCODE}; fi
2016-07-24 13:11:32 +02:00
}
2019-08-21 14:50:32 +02:00
################################################################################
# Name : DisplayException()
# Description : Show a discovered exception on screen
#
# Parameters : $1 = function or test
# $2 = text
# Returns : <nothing>
# Note : This function is usually triggered by ReportException
################################################################################
DisplayException() {
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} "================================================================="
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} " ${WARNING}Exception found!${NORMAL}"
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} " Function/test: [$1]"
${ECHOCMD:-echo} " Message: ${BOLD}$2${NORMAL}"
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} " Help improving the Lynis community with your feedback!"
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} " Steps:"
${ECHOCMD:-echo} " - Ensure you are running the latest version ($0 update check)"
${ECHOCMD:-echo} " - If so, create a GitHub issue at ${PROGRAM_SOURCE}"
${ECHOCMD:-echo} " - Include relevant parts of the log file or configuration file"
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} " Thanks!"
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} "================================================================="
${ECHOCMD:-echo} ""
sleep 5
}
2015-10-01 22:40:29 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : DisplayManual()
2015-10-01 22:40:29 +02:00
# Description : Show text on screen, without any markup
2016-04-28 12:31:38 +02:00
#
# Input : $1 = text (string)
# Returns : <nothing>
2015-10-01 22:40:29 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
DisplayManual() {
if [ ${QUIET} -eq 0 ]; then ${ECHOCMD} "$1"; fi
}
2015-10-01 22:40:29 +02:00
2016-07-05 17:25:19 +02:00
################################################################################
# Name : DisplayToolTip()
# Description : Show tooltip on screen
#
# Input : $1 = text
# Returns : <nothing>
################################################################################
DisplayToolTip() {
2016-07-05 18:18:54 +02:00
# Display tooltip when enabled and no tip has been displayed yet
2019-08-20 16:01:10 +02:00
if [ ${SHOW_TOOL_TIPS} -eq 1 -a ${TOOLTIP_SHOWED} -eq 0 -a ${QUIET} -eq 0 ]; then
2016-08-29 19:31:06 +02:00
# Check if we already have already discovered a proper echo command tool. It not, set it default to 'echo'.
if [ "${ECHOCMD}" = "" ]; then ECHOCMD="echo"; fi
2016-07-05 17:25:19 +02:00
if [ ${CRONJOB} -eq 0 ]; then
2016-07-11 20:06:46 +02:00
printf "\n"
${ECHOCMD} " ${BG_BLUE}[TIP]${NORMAL}: ${LIGHTBLUE}$1${NORMAL}"
printf "\n"
2016-07-05 17:25:19 +02:00
else
2016-08-29 19:31:06 +02:00
${ECHOCMD} " [TIP]: $1"
2016-07-05 17:25:19 +02:00
fi
2016-07-05 18:18:54 +02:00
TOOLTIP_SHOWED=1
2016-07-05 17:25:19 +02:00
fi
}
2019-07-07 18:47:55 +02:00
################################################################################
# Name : DisplayWarning
# Description : Show a warning on the screen
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = text
2019-07-07 18:47:55 +02:00
# Returns : <nothing>
################################################################################
DisplayWarning() {
if [ ${CRONJOB} -eq 0 ]; then
printf "\n"
${ECHOCMD:-echo} " ${BG_WARNING}[WARNING]${NORMAL}: $1${NORMAL}"
printf "\n"
else
${ECHOCMD} " [WARNING]: $1"
fi
}
2019-07-08 15:05:28 +02:00
################################################################################
# Name : Equals()
2019-08-01 14:59:03 +02:00
# Description : Compare two strings after special characters were stripped
2019-07-08 15:05:28 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = string1
# $2 = string2
# Returns : exit code (0 = True, 1 = False)
2019-07-08 15:05:28 +02:00
# Usage : if Equals "${MYDIR}" "/etc"; then echo "Found"; else "Not found"; fi
################################################################################
Equals() {
RETVAL=1
if [ $# -ne 2 ]; then ReportException "Equals" "Incorrect number of arguments for $0 function"; fi
# Strip any strange control characters
INPUT1=$(echo $1 | tr -d '[:cntrl:]<>' | ${SEDBINARY} 's/__space__/ /g' | ${SEDBINARY} 's/:space:/ /g')
INPUT2=$(echo $2 | tr -d '[:cntrl:]<>' | ${SEDBINARY} 's/__space__/ /g' | ${SEDBINARY} 's/:space:/ /g')
if [ "${INPUT1}" = "${INPUT2}" ]; then RETVAL=0; fi
return ${RETVAL}
}
2016-04-28 12:31:38 +02:00
################################################################################
# Name : ExitClean()
# Description : Perform a normal exit of the program, and clean up resources
#
2019-08-01 14:59:03 +02:00
# Parameters : <nothing>
2016-04-28 12:31:38 +02:00
# Returns : <nothing>
# Usage : ExitClean
################################################################################
ExitClean() {
2014-08-26 17:33:55 +02:00
RemovePIDFile
2016-01-11 01:04:04 +01:00
RemoveTempFiles
LogText "${PROGRAM_NAME} ended successfully."
2014-08-26 17:33:55 +02:00
exit 0
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : ExitCustom()
# Description : Perform a normal exit of the program, and clean up resources
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = exit code (optional)
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
# Usage : ExitCustom 35
################################################################################
2016-01-11 01:04:04 +01:00
2016-04-28 12:31:38 +02:00
ExitCustom() {
2015-09-10 08:35:09 +02:00
RemovePIDFile
2016-01-11 01:04:04 +01:00
RemoveTempFiles
2015-09-10 08:35:09 +02:00
# Exit with the exit code given, otherwise use 1
if [ $# -eq 1 ]; then
2016-01-11 01:04:04 +01:00
LogText "${PROGRAM_NAME} ended with exit code $1."
2015-09-10 08:35:09 +02:00
exit $1
2017-04-30 17:59:35 +02:00
else
2016-01-11 01:04:04 +01:00
LogText "${PROGRAM_NAME} ended with exit code 1."
2015-09-10 08:35:09 +02:00
exit 1
fi
2016-04-28 12:31:38 +02:00
}
2015-09-10 08:35:09 +02:00
2016-01-11 01:04:04 +01:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : ExitFatal()
# Description : Perform exit of the program (with code 1), clean up resources
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = text string (optional)
2016-04-28 12:31:38 +02:00
# Returns : <nothing>
# Usage : ExitFatal
################################################################################
ExitFatal() {
2014-08-26 17:33:55 +02:00
RemovePIDFile
2016-01-11 01:04:04 +01:00
RemoveTempFiles
LogText "${PROGRAM_NAME} ended with exit code 1."
2016-08-11 19:03:01 +02:00
if [ $# -eq 1 ]; then
2019-06-30 20:38:05 +02:00
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} "${RED}Fatal error${NORMAL}: ${WHITE}$1${NORMAL}"
${ECHOCMD:-echo} ""
2016-08-11 19:03:01 +02:00
fi
2014-08-26 17:33:55 +02:00
exit 1
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-01-11 01:04:04 +01:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : FileExists()
# Description : Determine if a file exists
2019-08-01 14:59:03 +02:00
#
# Parameters : $1 = path
2016-04-28 12:31:38 +02:00
# Returns : 0 (found), 1 (not found)
# FILE_FOUND (0:found, 1:not found) - deprecated usage
################################################################################
FileExists() {
2017-04-30 17:59:35 +02:00
if [ $# -eq 0 ]; then ExitFatal "Missing parameter when calling FileExists function"; fi
2014-08-26 17:33:55 +02:00
FILE_FOUND=0
2015-12-22 16:02:32 +01:00
LogText "Test: checking if file $1 exists"
2014-08-26 17:33:55 +02:00
if [ -f $1 ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: file $1 exists"
2014-08-26 17:33:55 +02:00
FILE_FOUND=1
2016-04-28 12:31:38 +02:00
return 0
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: file $1 NOT found"
2016-04-28 12:31:38 +02:00
return 1
2014-08-26 17:33:55 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2017-03-12 16:36:02 +01:00
################################################################################
# Name : FileInstalledByPackage()
# Description : Check if a file is part of a package
# Returns : 0 (true), 1 (default: unknown or false)
################################################################################
FileInstalledByPackage() {
exitcode=1
file=$1
find=""
2019-07-16 13:20:30 +02:00
if [ -n "${DPKGBINARY}" ]; then
2017-09-06 12:55:56 +02:00
find=$(${DPKGBINARY} -S "${file}" 2> /dev/null | ${AWKBINARY} -F: '{print $1}')
2019-07-16 13:20:30 +02:00
elif [ -n "${RPMBINARY}" ]; then
2017-09-06 12:55:56 +02:00
find=$(${RPMBINARY} -qf "${file}" 2> /dev/null | ${AWKBINARY} -F- '{print $1}')
2017-03-12 16:36:02 +01:00
fi
2019-07-16 13:20:30 +02:00
if [ -n "${find}" ]; then
2017-09-06 12:55:56 +02:00
LogText "Result: file '${file}' belongs to package (${find})"
2017-03-12 16:36:02 +01:00
exitcode=0
else
2017-09-06 12:55:56 +02:00
LogText "Result: file '${file}' does most likely not belong to a package"
2017-03-12 16:36:02 +01:00
fi
return ${exitcode}
}
2014-09-17 09:59:18 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : FileIsEmpty()
2014-09-17 09:59:18 +02:00
# Description : Check if a file is empty
2016-04-28 12:31:38 +02:00
#
# Returns : 0 (empty), 1 (not empty)
# EMPTY (0 or 1) - deprecated usage
2017-04-30 17:59:35 +02:00
# Usage : if FileIsEmpty /etc/passwd; then
2014-09-17 09:59:18 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
FileIsEmpty() {
2017-04-30 17:59:35 +02:00
if [ $# -eq 0 ]; then ExitFatal "Missing parameter when calling FileIsEmpty function"; fi
2014-09-17 09:59:18 +02:00
EMPTY=0
2015-12-22 16:02:32 +01:00
LogText "Test: checking if file $1 is empty"
2017-10-31 09:05:29 +01:00
if [ ! -s "$1" ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: file $1 is empty"
2014-09-17 09:59:18 +02:00
EMPTY=1
2016-04-28 12:31:38 +02:00
return 0
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: file $1 is NOT empty"
2016-04-28 12:31:38 +02:00
return 1
2014-09-17 09:59:18 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-09-08 21:30:54 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : FileIsReadable()
2014-09-08 21:30:54 +02:00
# Description : Check if a file readable or directory is accessible
2016-04-28 12:31:38 +02:00
#
2015-12-22 16:02:32 +01:00
# Returns : Return code (0 = readable, 1 = not readable)
# Usage : if FileIsReadable /etc/shadow; then echo "File is readable"; fi
2014-09-08 21:30:54 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
FileIsReadable() {
2016-08-11 19:03:01 +02:00
if [ $# -eq 0 ]; then ExitFatal "Function FileIsReadable() called without a file name"; fi
2014-09-08 23:51:27 +02:00
sFILE=$1
2014-09-08 21:30:54 +02:00
CANREAD=0
2016-08-11 19:52:15 +02:00
RETVAL=1
2019-08-20 16:22:00 +02:00
escaped_file=$(echo ${sFILE} | sed 's/\*/\\*/; s/?/\\?/')
2017-03-13 11:57:23 +01:00
LogText "Test: check if we can access ${sFILE} (escaped: ${escaped_file})"
2014-09-08 23:51:27 +02:00
# Check for symlink
2017-08-29 14:33:18 +02:00
if [ -L "${escaped_file}" ]; then
2017-03-13 11:57:23 +01:00
ShowSymlinkPath ${escaped_file}
2019-07-16 13:20:30 +02:00
if [ -n "${SYMLINK}" ]; then escaped_file="${SYMLINK}"; fi
2014-09-08 23:51:27 +02:00
fi
2015-12-22 16:02:32 +01:00
2014-09-08 23:51:27 +02:00
# Only check the file if it isn't a symlink (after previous check)
2017-08-29 14:33:18 +02:00
if [ -L "${escaped_file}" ]; then
2014-09-08 23:51:27 +02:00
OTHERPERMS="-"
2015-12-22 16:02:32 +01:00
LogText "Result: unclear if we can read this file, as this is a symlink"
2014-09-08 23:51:27 +02:00
ReportException "FileIsReadable" "Can not determine symlink ${sFILE}"
2017-08-29 14:33:18 +02:00
elif [ -d "${escaped_file}" ]; then
OTHERPERMS=$(${LSBINARY} -d -l "${escaped_file}" 2> /dev/null | ${CUTBINARY} -c 8)
elif [ -f "${escaped_file}" ]; then
OTHERPERMS=$(${LSBINARY} -d -l "${escaped_file}" 2> /dev/null | ${CUTBINARY} -c 8)
2017-03-13 11:57:23 +01:00
else
2014-09-08 21:30:54 +02:00
OTHERPERMS="-"
fi
2014-09-08 23:51:27 +02:00
2016-04-13 16:11:46 +02:00
# Also check if we are the actual owner of the file (use -d to get directory itself, if its a directory)
2017-08-29 14:33:18 +02:00
FILEOWNER=$(ls -dln "${escaped_file}" 2> /dev/null | ${AWKBINARY} -F" " '{ print $3 }')
2014-09-08 23:51:27 +02:00
if [ "${FILEOWNER}" = "${MYID}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: file is owned by our current user ID (${MYID}), checking if it is readable"
2017-08-29 14:33:18 +02:00
if [ -L "${sFILE}" ]; then
2016-04-13 16:11:46 +02:00
LogText "Result: unclear if we can read this file, as this is a symlink"
2017-03-13 11:57:23 +01:00
ReportException "FileIsReadable" "Can not determine symlink ${escaped_file}"
2017-08-29 14:33:18 +02:00
elif [ -d "${escaped_file}" ]; then
OTHERPERMS=$(${LSBINARY} -d -l "${escaped_file}" 2> /dev/null | ${CUTBINARY} -c 2)
elif [ -f "${escaped_file}" ]; then
OTHERPERMS=$(${LSBINARY} -l "${escaped_file}" 2> /dev/null | ${CUTBINARY} -c 2)
2014-09-08 23:51:27 +02:00
fi
2017-03-13 11:57:23 +01:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: file is not owned by current user ID (${MYID}), but UID ${FILEOWNER}"
2014-09-08 23:51:27 +02:00
fi
2016-07-31 21:18:56 +02:00
# Check if we are root, or have the read bit
if [ "${MYID}" = "0" -o "${OTHERPERMS}" = "r" ]; then
2014-09-08 21:30:54 +02:00
CANREAD=1
2017-03-13 11:57:23 +01:00
LogText "Result: file ${escaped_file} is readable (or directory accessible)."
2016-08-11 19:52:15 +02:00
return 0
2017-03-13 11:57:23 +01:00
else
2015-12-22 16:02:32 +01:00
return 1
2017-03-13 11:57:23 +01:00
LogText "Result: file ${escaped_file} is NOT readable (or directory accessible), symlink, or does not exist. (OTHERPERMS: ${OTHERPERMS})"
2014-09-08 21:30:54 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-09-08 21:30:54 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : GetHostID()
# Description : Create an unique id for the system
#
2019-04-13 13:26:56 +02:00
# Returns : 0 = fetched or created IDs, 1 = failed, 2 = skipped
2016-04-28 12:31:38 +02:00
# Usage : GetHostID
################################################################################
GetHostID() {
2018-02-16 19:29:08 +01:00
2019-04-13 13:26:56 +02:00
if [ ${SKIP_GETHOSTID} -eq 1 ]; then
return 2
fi
2019-07-16 13:20:30 +02:00
if [ -n "${HOSTID}" -a -n "${HOSTID2}" ]; then
2018-02-16 19:29:08 +01:00
Debug "Skipping creation of host identifiers, as they are already configured (via profile)"
2019-04-13 13:26:56 +02:00
return 2
fi
if [ -f "${ROOTDIR}etc/lynis/hostids" ]; then
Debug "Used hostids file to fetch values"
HOSTID=$(grep "^hostid=" ${ROOTDIR}etc/lynis/hostids | awk -F= '{print $2}')
HOSTID2=$(grep "^hostid2=" ${ROOTDIR}etc/lynis/hostids | awk -F= '{print $2}')
return 0
2018-02-16 19:29:08 +01:00
fi
2014-09-25 17:57:25 +02:00
FIND=""
2015-10-23 13:42:23 +02:00
# Avoid some hashes (empty, only zeros)
BLACKLISTED_HASHES="6ef1338f520d075957424741d7ed35ab5966ae97 adc83b19e793491b1c6ea0fd8b46cd9f32e592fc"
2016-05-17 18:07:43 +02:00
# Check which utilities we can use (e.g. lynis show hostids). Normally these are detected during binaries collecting.
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
if [ "${SHA1SUMBINARY}" = "" ]; then SHA1SUMBINARY=$(which sha1sum 2> /dev/null | grep -v "no [^ ]* in "); fi
if [ "${SHA1SUMBINARY}" = "" ]; then SHA1SUMBINARY=$(which sha1 2> /dev/null | grep -v "no [^ ]* in "); fi
if [ "${SHA256SUMBINARY}" = "" ]; then SHA256SUMBINARY=$(which sha256sum 2> /dev/null | grep -v "no [^ ]* in "); fi
if [ "${SHA256SUMBINARY}" = "" ]; then SHA256SUMBINARY=$(which sha256 2> /dev/null | grep -v "no [^ ]* in "); fi
if [ "${CSUMBINARY}" = "" ]; then CSUMBINARY=$(which csum 2> /dev/null | grep -v "no [^ ]* in "); fi
if [ "${OPENSSLBINARY}" = "" ]; then OPENSSLBINARY=$(which openssl 2> /dev/null | grep -v "no [^ ]* in "); fi
if [ "${IFCONFIGBINARY}" = "" ]; then IFCONFIGBINARY=$(which ifconfig 2> /dev/null | grep -v "no [^ ]* in "); fi
if [ "${IPBINARY}" = "" ]; then IPBINARY=$(which ip 2> /dev/null | grep -v "no [^ ]* in "); fi
# If using openssl, use the best hash type it supports
if [ ! "${OPENSSLBINARY}" = "" ]; then
OPENSSL_HASHLIST=$(openssl dgst -h 2>&1)
for OPENSSL_HASHTYPE in sha256 sha1 md5 ; do
if echo "${OPENSSL_HASHLIST}" | grep "^-${OPENSSL_HASHTYPE} " >/dev/null ; then
break
fi
done
fi
2016-05-17 18:07:43 +02:00
2015-03-19 00:03:58 +01:00
if [ ! "${SHA1SUMBINARY}" = "" -o ! "${OPENSSLBINARY}" = "" -o ! "${CSUMBINARY}" = "" ]; then
2014-08-26 17:33:55 +02:00
case "${OS}" in
"AIX")
2015-03-18 15:35:37 +01:00
# Common interfaces: en0 en1 en2, ent0 ent1 ent2
2017-03-06 08:41:21 +01:00
FIND=$(entstat en0 2>/dev/null | grep "Hardware Address" | awk -F ": " '{ print $2 }')
2015-03-18 15:35:37 +01:00
if [ "${FIND}" = "" ]; then
2017-03-06 08:41:21 +01:00
FIND=$(entstat ent0 2>/dev/null | grep "Hardware Address" | awk -F ": " '{ print $2 }')
2015-03-18 15:35:37 +01:00
fi
if [ ! "${FIND}" = "" ]; then
# We have a MAC address, now hashing it
2019-09-17 14:04:30 +02:00
if [ -n "${SHA1SUMBINARY}" ]; then
2017-03-06 08:41:21 +01:00
HOSTID=$(echo ${FIND} | ${SHA1SUMBINARY} | awk '{ print $1 }')
2019-09-17 14:04:30 +02:00
elif [ -n "${CSUMBINARY}" ]; then
2017-03-06 08:41:21 +01:00
HOSTID=$(echo ${FIND} | ${CSUMBINARY} -h SHA1 - | awk '{ print $1 }')
2019-09-17 14:04:30 +02:00
elif [ -n "${OPENSSLBINARY}" ]; then
2017-03-06 08:41:21 +01:00
HOSTID=$(echo ${FIND} | ${OPENSSLBINARY} sha -sha1 | awk '{ print $2 }')
2015-03-18 15:35:37 +01:00
else
ReportException "GetHostID" "No sha1, sha1sum, csum or openssl binary available on AIX"
fi
2017-04-30 17:59:35 +02:00
else
2015-03-18 15:35:37 +01:00
ReportException "GetHostID" "No output from entstat on interfaces: en0, ent0"
fi
2014-08-26 17:33:55 +02:00
;;
"DragonFly" | "FreeBSD")
2017-04-30 17:59:35 +02:00
FIND=$(${IFCONFIGBINARY} | grep ether | head -1 | awk '{ print $2 }' | tr '[:upper:]' '[:lower:]')
if HasData "${FIND}"; then
HOSTID=$(echo ${FIND} | sha1)
else
ReportException "GetHostID" "No MAC address returned on DragonFly or FreeBSD"
fi
2014-08-26 17:33:55 +02:00
;;
2017-10-19 19:37:25 +02:00
"HP-UX")
FIND=$(nwmgr -q info -c lan0 2> /dev/null | awk '{ if ($1=="MAC" && $2=="Address") { print $4 }}')
if HasData "${FIND}"; then
2019-07-16 13:20:30 +02:00
if [ -n "${OPENSSLBINARY}" ]; then
2017-10-19 19:37:25 +02:00
HOSTID=$(echo ${FIND} | ${OPENSSLBINARY} sha -sha1 | awk '{ print $2 }')
else
ReportException "GetHostID" "No openssl binary available on this HP-UX system"
fi
else
ReportException "GetHostID" "No MAC address found by using nwmgr"
fi
;;
2014-08-26 17:33:55 +02:00
"Linux")
2017-04-30 17:59:35 +02:00
2019-01-14 11:13:37 +01:00
# Future change
# Show brief output of ip of links that are UP. Filter out items like 'UNKNOWN' in col 2
# Using the {2} syntax does not work on all systems
# ip -br link show up | sort | awk '$2=="UP" && $3 ~ /^[a-f0-9][a-f0-9]:/ {print $3}'
# Use ifconfig
2019-07-16 13:20:30 +02:00
if [ -n "${IFCONFIGBINARY}" ]; then
2019-01-14 11:13:37 +01:00
# Determine if we have the eth0 interface (not all Linux distro have this, e.g. Arch)
2017-04-30 17:59:35 +02:00
HASETH0=$(${IFCONFIGBINARY} | grep "^eth0")
# Check if we can find it with HWaddr on the line
FIND=$(${IFCONFIGBINARY} 2> /dev/null | grep "^eth0" | grep -v "eth0:" | grep HWaddr | awk '{ print $5 }' | tr '[:upper:]' '[:lower:]')
# If nothing found, then try first for alternative interface. Else other versions of ifconfig (e.g. Slackware/Arch)
if IsEmpty "${FIND}"; then
FIND=$(${IFCONFIGBINARY} 2> /dev/null | grep HWaddr)
if IsEmpty "${FIND}"; then
# If possible directly address eth0 to avoid risking gathering the incorrect MAC address.
# If not, then falling back to getting first interface. Better than nothing.
if HasData "${HASETH0}"; then
FIND=$(${IFCONFIGBINARY} eth0 2> /dev/null | grep "ether " | awk '{ print $2 }' | tr '[:upper:]' '[:lower:]')
else
FIND=$(${IFCONFIGBINARY} 2> /dev/null | grep "ether " | awk '{ print $2 }' | head -1 | tr '[:upper:]' '[:lower:]')
if IsEmpty "${FIND}"; then
ReportException "GetHostID" "No eth0 found (and no ether was found with ifconfig)"
else
LogText "Result: No eth0 found (ether found), using first network interface to determine hostid (with ifconfig)"
2014-08-26 17:33:55 +02:00
fi
fi
2017-04-30 17:59:35 +02:00
else
FIND=$(${IFCONFIGBINARY} 2> /dev/null | grep HWaddr | head -1 | awk '{ print $5 }' | tr '[:upper:]' '[:lower:]')
LogText "GetHostID: No eth0 found (but HWaddr was found), using first network interface to determine hostid, with ifconfig"
2014-08-26 17:33:55 +02:00
fi
2017-04-30 17:59:35 +02:00
fi
2019-01-14 11:13:37 +01:00
2019-07-16 13:20:30 +02:00
elif [ -n "${IPBINARY}" ]; then
2019-01-14 11:13:37 +01:00
# Determine if we have the common available eth0 interface
2019-09-19 14:05:15 +02:00
FIND=$(${IPBINARY} addr show eth0 2> /dev/null | grep -E "link/ether " | head -1 | awk '{ print $2 }' | tr '[:upper:]' '[:lower:]')
2019-01-14 11:13:37 +01:00
if IsEmpty "${FIND}"; then
# Determine the MAC address of first interface with the ip command
2019-09-19 14:05:15 +02:00
FIND=$(${IPBINARY} addr show 2> /dev/null | grep -E "link/ether " | head -1 | awk '{ print $2 }' | tr '[:upper:]' '[:lower:]')
2017-04-30 17:59:35 +02:00
if IsEmpty "${FIND}"; then
2019-01-14 11:13:37 +01:00
ReportException "GetHostID" "Can't create hostid (no MAC addresses found)"
2014-08-26 17:33:55 +02:00
fi
2014-09-25 17:57:25 +02:00
fi
2019-01-14 11:13:37 +01:00
else
ReportException "GetHostID" "Both ip and ifconfig tools are missing"
2017-04-30 17:59:35 +02:00
fi
2014-08-27 12:53:09 +02:00
2017-04-30 17:59:35 +02:00
# Check if we found a HostID
if HasData "${FIND}"; then
LogText "Info: using hardware address ${FIND} to create ID"
HOSTID=$(echo ${FIND} | ${SHA1SUMBINARY} | awk '{ print $1 }')
LogText "Result: Found HostID: ${HOSTID}"
else
ReportException "GetHostID" "Can't create HOSTID, command ip not found"
fi
2014-08-26 17:33:55 +02:00
;;
2016-11-05 11:53:22 +01:00
"macOS")
2017-04-30 17:59:35 +02:00
FIND=$(${IFCONFIGBINARY} en0 | grep ether | head -1 | awk '{ print $2 }' | tr '[:upper:]' '[:lower:]')
if [ ! "${FIND}" = "" ]; then
HOSTID=$(echo ${FIND} | shasum | awk '{ print $1 }')
else
ReportException "GetHostID" "No MAC address returned on macOS"
fi
LYNIS_HOSTID2_PART1=$(hostname -s)
2019-07-16 13:20:30 +02:00
if [ -n "${LYNIS_HOSTID2_PART1}" ]; then
2017-04-30 17:59:35 +02:00
LogText "Info: using hostname ${LYNIS_HOSTID2_PART1}"
LYNIS_HOSTID2_PART2=$(sysctl -n kern.uuid 2> /dev/null)
2019-07-16 13:20:30 +02:00
if [ -n "${LYNIS_HOSTID2_PART2}" ]; then
2017-04-30 17:59:35 +02:00
LogText "Info: using UUID ${LYNIS_HOSTID2_PART2}"
else
LogText "Info: could not create HOSTID2 as kern.uuid sysctl key is missing"
fi
HOSTID2=$(echo "${LYNIS_HOSTID2_PART1}${LYNIS_HOSTID2_PART2}" | shasum -a 256 | awk '{ print $1 }')
else
LogText "Info: could not create HOSTID2 as hostname is missing"
fi
2014-08-26 17:33:55 +02:00
;;
"NetBSD")
2017-04-30 17:59:35 +02:00
FIND=$(${IFCONFIGBINARY} -a | grep "address:" | head -1 | awk '{ print $2 }' | tr '[:upper:]' '[:lower:]')
if HasData "${FIND}"; then
HOSTID=$(echo ${FIND} | sha1)
else
ReportException "GetHostID" "No MAC address returned on NetBSD"
fi
2014-08-26 17:33:55 +02:00
;;
"OpenBSD")
2017-04-30 17:59:35 +02:00
FIND=$(${IFCONFIGBINARY} | grep "lladdr " | head -1 | awk '{ print $2 }' | tr '[:upper:]' '[:lower:]')
if HasData "${FIND}"; then
HOSTID=$(echo ${FIND} | sha1)
else
ReportException "GetHostID" "No MAC address returned on OpenBSD"
fi
2014-08-26 17:33:55 +02:00
;;
"Solaris")
INTERFACES_TO_TEST="e1000g1 net0"
FOUND=0
for I in ${INTERFACES_TO_TEST}; do
2017-03-06 08:41:21 +01:00
FIND=$(${IFCONFIGBINARY} -a | grep "^${I}")
2014-08-26 17:33:55 +02:00
if [ ! "${FIND}" = "" ]; then
2015-12-22 16:02:32 +01:00
FOUND=1; LogText "Found interface ${I} on Solaris"
2014-08-26 17:33:55 +02:00
fi
done
if [ ${FOUND} -eq 1 ]; then
2017-03-06 08:41:21 +01:00
FIND=$(${IFCONFIGBINARY} ${I} | grep ether | awk '{ if ($1=="ether") { print $2 }}')
2014-11-04 02:08:56 +01:00
if [ ! "${SHA1SUMBINARY}" = "" ]; then
2017-03-06 08:41:21 +01:00
HOSTID=$(echo ${FIND} | ${SHA1SUMBINARY} | awk '{ print $1 }')
2016-05-05 17:49:41 +02:00
elif [ ! "${OPENSSLBINARY}" = "" ]; then
2017-03-06 08:41:21 +01:00
HOSTID=$(echo ${FIND} | ${OPENSSLBINARY} sha -sha1 | awk '{ print $2 }')
2017-04-30 17:59:35 +02:00
else
2016-05-05 17:49:41 +02:00
ReportException "GetHostID" "Can not find sha1/sha1sum or openssl"
2014-11-04 02:08:56 +01:00
fi
2017-04-30 17:59:35 +02:00
else
2014-08-26 17:33:55 +02:00
ReportException "GetHostID" "No interface found op Solaris to create HostID"
fi
;;
*)
2014-11-04 02:08:56 +01:00
ReportException "GetHostID" "Can't create HOSTID as OS is not supported yet by this function"
2014-08-26 17:33:55 +02:00
;;
esac
2015-10-23 13:42:23 +02:00
# Remove HOSTID if it contains a default MAC address with a related hash value
if [ ! "${HOSTID}" = "" ]; then
for CHECKHASH in ${BLACKLISTED_HASHES}; do
if [ "${CHECKHASH}" = "${HOSTID}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: hostid is a blacklisted value"
2015-10-23 13:42:23 +02:00
HOSTID=""
fi
done
fi
2017-04-30 17:59:35 +02:00
else
2015-03-18 15:35:37 +01:00
ReportException "GetHostID" "Can't create HOSTID as there is no SHA1 hash tool available (sha1, sha1sum, openssl)"
2014-08-26 17:33:55 +02:00
fi
2014-09-19 16:43:20 +02:00
# Search machine ID
# This applies to IDs generated for systemd
# Optional: DBUS creates ID as well with dbus-uuidgen and is stored in /var/lib/dbus-machine-id (might be symlinked to /etc/machine-id)
sMACHINEIDFILE="/etc/machine-id"
if [ -f ${sMACHINEIDFILE} ]; then
2017-03-06 08:41:21 +01:00
FIND=$(head -1 ${sMACHINEIDFILE} | grep "^[a-f0-9]")
2014-09-19 16:43:20 +02:00
if [ "${FIND}" = "" ]; then
MACHINEID="${FIND}"
fi
fi
2019-09-17 14:04:30 +02:00
if [ -z "${HOSTID}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: no HOSTID available, trying to use SSH key as unique source"
2015-10-22 15:54:51 +02:00
# Create host ID when a MAC address was not found
2016-05-10 14:21:09 +02:00
SSH_KEY_FILES="ssh_host_ed25519_key.pub ssh_host_ecdsa_key.pub ssh_host_dsa_key.pub ssh_host_rsa_key.pub"
2015-10-22 15:54:51 +02:00
if [ -d /etc/ssh ]; then
for I in ${SSH_KEY_FILES}; do
2019-09-17 14:04:30 +02:00
if [ -z "${HOSTID}" ]; then
2015-10-22 15:54:51 +02:00
if [ -f /etc/ssh/${I} ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: found ${I} in /etc/ssh"
2019-09-17 14:04:30 +02:00
if [ -n "${SHA1SUMBINARY}" ]; then
HOSTID=$(${SHA1SUMBINARY} /etc/ssh/${I} | awk '{ print $1 }')
2015-12-22 16:02:32 +01:00
LogText "result: Created HostID with SSH key ($I): ${HOSTID}"
2017-04-30 17:59:35 +02:00
else
2015-10-22 15:54:51 +02:00
ReportException "GetHostID" "Can't create HOSTID with SSH key, as sha1sum binary is missing"
fi
fi
fi
done
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: no /etc/ssh directory found, skipping"
2015-10-22 15:54:51 +02:00
fi
fi
2015-03-09 14:09:59 +01:00
2016-05-05 17:49:41 +02:00
# New style host ID
if [ "${HOSTID2}" = "" ]; then
LogText "Info: creating a HostID (version 2)"
FOUND=0
DATA_SSH=""
# Use public keys
SSH_KEY_FILES="ssh_host_ed25519_key.pub ssh_host_ecdsa_key.pub ssh_host_dsa_key.pub ssh_host_rsa_key.pub"
if [ -d /etc/ssh ]; then
for I in ${SSH_KEY_FILES}; do
if [ ${FOUND} -eq 0 ]; then
if [ -f /etc/ssh/${I} ]; then
2016-10-17 17:16:36 +02:00
LogText "Result: found file ${I} in /etc/ssh, using that to create host identifier"
2016-05-05 17:49:41 +02:00
DATA_SSH=$(cat /etc/ssh/${I})
FOUND=1
fi
fi
done
2017-04-30 17:59:35 +02:00
else
2016-05-05 17:49:41 +02:00
LogText "Result: no /etc/ssh directory found, skipping"
fi
2016-10-17 17:16:36 +02:00
STRING_TO_HASH=""
2019-07-16 13:20:30 +02:00
if [ ${FOUND} -eq 1 -a -n "${DATA_SSH}" ]; then
2016-10-17 17:16:36 +02:00
LogText "Using SSH public key to create the second host identifier"
STRING_TO_HASH="${DATA_SSH}"
else
2019-07-16 13:20:30 +02:00
if [ -n "${MACHINEID}" ]; then
2016-10-17 17:16:36 +02:00
LogText "Using the machine ID to create the second host identifier"
STRING_TO_HASH="${MACHINEID}"
fi
fi
# Check if we have a string to turn into a host identifier
2019-07-16 13:20:30 +02:00
if [ -n "${STRING_TO_HASH}" ]; then
2016-05-05 17:49:41 +02:00
# Create hashes
if [ ! "${SHA256SUMBINARY}" = "" ]; then
2017-01-28 12:11:38 +01:00
HASH2=$(echo ${STRING_TO_HASH} | ${SHA256SUMBINARY} | awk '{ print $1 }')
2016-05-05 17:49:41 +02:00
HASH_HOSTNAME=$(echo ${HOSTNAME} | ${SHA256SUMBINARY} | awk '{ print $1 }')
elif [ ! "${OPENSSLBINARY}" = "" ]; 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
HASH2=$(echo ${STRING_TO_HASH} | ${OPENSSLBINARY} dgst -${OPENSSL_HASHTYPE} | awk '{ print $2 }')
HASH_HOSTNAME=$(echo ${HOSTNAME} | ${OPENSSLBINARY} dgst -${OPENSSL_HASHTYPE} | awk '{ print $2 }')
2016-05-05 17:49:41 +02:00
fi
LogText "Hash (hostname): ${HASH_HOSTNAME}"
2017-01-28 12:11:38 +01:00
LogText "Hash (ssh or machineid): ${HASH2}"
HOSTID2="${HASH2}"
2016-10-17 17:16:36 +02:00
fi
2016-05-05 17:49:41 +02:00
fi
2015-10-22 15:54:51 +02:00
# Show an exception if no HostID could be created, to ensure each system (and scan) has one
2019-04-13 13:26:56 +02:00
if [ -z "${HOSTID}" ]; then
2015-10-22 15:54:51 +02:00
ReportException "GetHostID" "No unique host identifier could be created."
2019-04-13 13:26:56 +02:00
return 1
2019-07-16 13:20:30 +02:00
elif [ -n "${HOSTID2}" ]; then
2018-02-16 19:29:08 +01:00
return 0
2015-10-22 15:54:51 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2019-07-14 15:12:25 +02:00
################################################################################
# Name : GetReportData()
# Description : Request data from report
# Returns : Data (when matches were found)
2019-08-01 14:59:03 +02:00
# Returns : exit code (0 = True, 1 = False, meaning search was cancelled)
# stdout (output of search result)
2019-07-14 15:12:25 +02:00
################################################################################
GetReportData() {
KEY=""
VALID_CHARS="[:alnum:]/:;\-,\._\[\]\n "
if [ $# -eq 0 ]; then ExitFatal "No parameters provided to GetReportData() function"; fi
while [ $# -ge 1 ]; do
case $1 in
--key)
shift
KEY="$1"
;;
--valid-chars)
shift
VALID_CHARS="$1"
;;
*)
ExitFatal "Invalid option provided to GetReportData() function"
;;
esac
# Go to next parameter
shift
done
if [ "${REPORTFILE}" = "/dev/null" ]; then
return 1
else
${AWKBINARY} -v pattern="^${KEY}" -F= '$1 ~ pattern {print $2}' ${REPORTFILE} | ${TRBINARY} -cd "${VALID_CHARS}" | ${TRBINARY} '[:blank:]' '__space__'
fi
return 0
}
2019-09-14 13:23:28 +02:00
################################################################################
# Name : HasCorrectFilePermissions()
# Description : Check file permissions
#
# Parameters : $1 = Full path to file or directory
# $2 = Permissions
# Returns : exit code (0 = correct, 1 = not correct, 2 = file does not exist)
################################################################################
HasCorrectFilePermissions() {
if [ $# -ne 2 ]; then Fatal "Incorrect usage of HasCorrectFilePermissions"; fi
CHECKFILE="$1"
CHECKPERMISSION_FULL="$2"
if [ ! -d ${CHECKFILE} -a ! -f ${CHECKFILE} ]; then
return 2
else
for CHECK_PERMISSION in ${CHECKPERMISSION_FULL}; do
DATA=$(echo ${CHECK_PERMISSION} | ${EGREPBINARY} "[rwx]")
if [ $? -eq 0 ]; then
# add a dummy character as first character so it looks like output is a normal file
CHECK_PERMISSION=$(echo "-${CHECK_PERMISSION}" | ${AWKBINARY} '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf("%0o",k)}')
fi
2019-10-23 20:31:20 +02:00
# Add leading zeros if necessary
CHECK_PERMISSION=$(echo "${CHECK_PERMISSION}" | ${AWKBINARY} '{printf "%03d",$1}')
2019-09-14 13:23:28 +02:00
# First try stat command
LogText "Test: checking if file ${CHECKFILE} is ${CHECK_PERMISSION}"
if [ -n "${STATBINARY}" ]; then
2019-12-13 12:34:56 +01:00
case ${OS} in
2019-12-13 12:40:29 +01:00
*BSD)
2019-12-13 12:34:56 +01:00
DATA=$(${STATBINARY} -f "%OLp" ${CHECKFILE})
;;
*)
# busybox does not support format
if [ ${SHELL_IS_BUSYBOX} -eq 0 ]; then
DATA=$(${STATBINARY} --format=%a ${CHECKFILE})
fi
;;
esac
2019-09-14 13:23:28 +02:00
fi
# See if we can use the find binary
if [ -z "${DATA}" ]; then
case ${OS} in
2019-12-13 12:40:29 +01:00
"AIX" | *BSD)
2019-12-13 12:34:56 +01:00
Debug "Skipping find command, as this operating system does not support -printf parameter"
2019-09-14 13:23:28 +02:00
;;
*)
# Only use find when OS is NOT AIX and binaries are NOT busybox
if [ ${SHELL_IS_BUSYBOX} -eq 0 ]; then
2019-10-23 20:31:20 +02:00
if [ -d ${CHECKFILE} ]; then
DATA=$(${FINDBINARY} ${CHECKFILE} -maxdepth 0 -printf "%m")
else
DATA=$(${FINDBINARY} ${CHECKFILE} -printf "%m")
fi
2019-09-14 13:23:28 +02:00
fi
;;
esac
fi
# Finally use ls command
if [ -z "${DATA}" ]; then
# If 'file' is an directory, use -d
if [ -d ${CHECKFILE} ]; then
DATA=$(${LSBINARY} -d -l ${CHECKFILE} | cut -c 2-10)
else
DATA=$(${LSBINARY} -l ${CHECKFILE} | cut -c 2-10)
fi
fi
# Convert permissions to octal when needed
case ${DATA} in
2019-10-23 20:31:20 +02:00
[-r][-w][-x][-r][-w][-x][-r][-w][-x] )
2019-09-14 13:23:28 +02:00
LogText "Converting value ${DATA} to octal"
2019-10-23 20:31:20 +02:00
# add a dummy character as first character so it looks like output is a normal file
DATA=$(echo "-${DATA}" | ${AWKBINARY} '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf("%0o",k)}')
2019-09-14 13:23:28 +02:00
;;
esac
2019-10-23 20:31:20 +02:00
# Add leading zeros if necessary
DATA=$(echo "${DATA}" | ${AWKBINARY} '{printf "%03d",$1}')
2019-09-14 13:23:28 +02:00
if [ -n "${DATA}" ]; then
if [ "${DATA}" = "${CHECK_PERMISSION}" ]; then
LogText "Outcome: correct permissions (${DATA})"
return 0
fi
else
ReportException "HasCorrectFilePermissions:02" "No data value found, which is unexpected"
fi
done
LogText "Outcome: permissions of file ${CHECKFILE} are not matching expected value (${DATA} != ${CHECKPERMISSION_FULL})"
# No match, return exit code 1
return 1
fi
}
2017-04-23 20:19:18 +02:00
################################################################################
# Name : HasData()
# Description : Check for a filled variable
#
2019-08-01 14:59:03 +02:00
# Returns : exit code (0 = True, 1 = False)
2017-04-23 20:19:18 +02:00
# Usage : if HasData "${FIND}"; then
################################################################################
HasData() {
if [ $# -eq 1 ]; then
2019-07-16 13:20:30 +02:00
if [ -n "$1" ]; then return 0; else return 1; fi
2017-04-23 20:19:18 +02:00
else
ExitFatal "Function HasData called without parameters - look in log to determine where this happened, or use sh -x lynis to see all details."
fi
}
2016-04-28 12:31:38 +02:00
################################################################################
# Name : InsertSection()
# Description : Show a section block on screen
#
2019-08-01 14:59:03 +02:00
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
# Usage : InsertSection
################################################################################
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
InsertSection() {
2014-08-26 17:33:55 +02:00
if [ ${QUIET} -eq 0 ]; then
echo ""
echo "[+] ${SECTION}$1${NORMAL}"
echo "------------------------------------"
fi
2016-04-28 12:31:38 +02:00
LogTextBreak
2015-12-22 16:02:32 +01:00
LogText "Action: Performing tests from category: $1"
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : InsertPlugionSection()
# Description : Insert section block for plugins (different color)
#
2019-08-01 14:59:03 +02:00
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
# Usage : InsertPluginSection
################################################################################
InsertPluginSection() {
2014-08-26 17:33:55 +02:00
if [ ${QUIET} -eq 0 ]; then
echo ""
echo "[+] ${MAGENTA}$1${NORMAL}"
echo "------------------------------------"
fi
2015-12-22 16:02:32 +01:00
LogText "Action: Performing plugin tests"
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-19 19:44:23 +02:00
2016-10-16 15:13:04 +02:00
################################################################################
# Name : IsContainer()
# Description : Determine if we are running in a container
2019-08-01 14:59:03 +02:00
#
# Parameters : <none>
# Returns : exit code (0 = true, 1 = false)
# variable: CONTAINER_TYPE
2016-10-16 15:13:04 +02:00
################################################################################
IsContainer() {
FOUND=0
2017-08-08 14:52:11 +02:00
# Early on we can't use FileIsReadable yet
2016-10-16 15:51:30 +02:00
if [ -e /proc/1/cgroup ]; then
2019-09-17 14:04:30 +02:00
FIND=$(grep -i docker ${ROOTDIR}proc/1/cgroup 2> /dev/null)
2016-10-16 15:13:04 +02:00
if [ $? -eq 0 ]; then
2016-10-16 15:51:30 +02:00
LogText "Result: found Docker in control groups (/proc/1/cgroup), so we are running in Docker container"
2016-10-16 15:13:04 +02:00
CONTAINER_TYPE="Docker"; FOUND=1
EXITCODE=0
fi
fi
2017-07-31 12:51:19 +02:00
if [ -e /proc/1/environ ]; then
2017-08-08 14:52:11 +02:00
FIND=$(grep -qa 'container=lxc' ${ROOTDIR}proc/1/environ 2> /dev/null)
2017-07-31 12:51:19 +02:00
if [ $? -eq 0 ]; then
2019-09-21 16:31:06 +02:00
LogText "Result: found LXC in environment (/proc/1/environ), so we are running in LXC container"
2017-07-31 12:51:19 +02:00
CONTAINER_TYPE="LXC"; FOUND=1
EXITCODE=0
fi
fi
2016-10-16 15:13:04 +02:00
if [ ${FOUND} -eq 0 ]; then
CONTAINER_TYPE=""
EXITCODE=1
fi
return ${EXITCODE}
}
2016-04-19 19:44:23 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : IsDebug()
2016-04-19 19:44:23 +02:00
# Description : Check if --debug option is used to show more details
2019-08-01 14:59:03 +02:00
#
# Parameters : <none>
# Returns : exit code (0 = True, 1 = False)
2016-04-19 19:44:23 +02:00
################################################################################
IsDebug() {
if [ ${DEBUG} -eq 1 ]; then return 0; else return 1; fi
}
2016-04-26 13:40:21 +02:00
################################################################################
# Name : IsDeveloperMode()
# Description : Check if we are in development mode (--developer)
2016-04-28 12:31:38 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : <none>
# Returns : exit code (0 = True, 1 = False)
2016-04-28 12:31:38 +02:00
# Notes : This is set with command line option or as a profile setting
2016-04-26 13:40:21 +02:00
################################################################################
IsDeveloperMode() {
if [ ${DEVELOPER_MODE} -eq 1 ]; then return 0; else return 1; fi
}
2016-06-18 09:28:53 +02:00
################################################################################
# Name : IsDeveloperVersion()
# Description : Check if this version is development or stable release
#
2019-08-01 14:59:03 +02:00
# Parameters : <none>
# Returns : exit code (0 = True, 1 = False)
2016-06-18 09:28:53 +02:00
################################################################################
IsDeveloperVersion() {
2019-08-21 14:50:32 +02:00
if [ "${PROGRAM_RELEASE_TYPE}" = "pre-release" ]; then return 0; else return 1; fi
2016-06-18 09:28:53 +02:00
}
2017-04-23 20:19:18 +02:00
################################################################################
# Name : IsEmpty()
# Description : Check for variable that has no data in it
#
2019-08-01 14:59:03 +02:00
# Returns : exit code (0 = True, 1 = False)
2017-04-23 20:19:18 +02:00
# Usage : if IsEmpty "${FIND}"; then
################################################################################
IsEmpty() {
2017-04-30 17:59:35 +02:00
if [ $# -eq 0 ]; then
2017-04-23 20:19:18 +02:00
ExitFatal "Function IsEmpty called without parameters - look in log to determine where this happened, or use sh -x lynis to see all details."
2017-04-30 17:59:35 +02:00
else
if [ -z "$1" ]; then return 0; else return 1; fi
2017-04-23 20:19:18 +02:00
fi
}
2016-04-02 17:18:19 +02:00
################################################################################
# Name : IsRunning()
# Description : Check if a process is running
2019-07-16 19:04:53 +02:00
#
# Parameters : $1 = search argument
# $2 = optional arguments
2016-04-02 17:18:19 +02:00
# Returns : 0 (process is running), 1 (process not running)
2016-04-28 12:31:38 +02:00
# RUNNING (1 = running, 0 = not running) - will be deprecated
2017-12-24 14:05:55 +01:00
# Notes : PSOPTIONS are declared globally, to prevent testing each call
2020-04-02 09:28:41 +02:00
# Fallback is used on binaries as IsRunning is used for 'show' command
2016-04-02 17:18:19 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
IsRunning() {
2017-04-30 17:59:35 +02:00
if [ $# -eq 0 ]; then ExitFatal "Missing parameter when calling IsRunning function"; fi
2017-10-29 10:54:40 +01:00
pgrep_options="-x"
search=""
2019-07-16 19:04:53 +02:00
FIND=""
PSOPTIONS=""
PARTIAL_SEARCH=1
2017-10-29 10:54:40 +01:00
while [ $# -ge 1 ]; do
case $1 in
--full)
pgrep_options="-f" # replace -x with -f
2019-07-16 19:04:53 +02:00
PARTIAL_SEARCH=0
;;
--user)
shift
users="$1"
2017-10-29 10:54:40 +01:00
;;
*)
search="$1"
;;
esac
shift # Go to next parameter
done
if [ -z "${search}" ]; then ExitFatal "Missing process to search for when using IsRunning function"; fi
2014-08-26 17:33:55 +02:00
RUNNING=0
2019-04-07 19:03:21 +02:00
# AIX does not fully support pgrep options, so using ps instead
2020-04-01 19:02:11 +02:00
if [ "${OS}" != "AIX" ]; then
2019-07-16 19:04:53 +02:00
# When --user is used, perform a search using the -u option
2020-04-02 09:28:41 +02:00
# Initialize users for strict mode
2019-07-17 23:16:47 +02:00
if [ -n "${users:-}" ]; then
2019-09-17 14:04:30 +02:00
for u in ${users}; do
2020-04-02 09:28:41 +02:00
user_uid=$(getent passwd "${u}" 2> /dev/null | ${AWKBINARY:-awk} -F: '{print $3}')
2019-07-16 19:04:53 +02:00
# Only perform search if user exists and we had no match yet
if [ -n "${user_uid}" ]; then
if [ -z "${FIND}" ]; then
LogText "Performing pgrep scan using uid ${user_uid}"
2020-04-01 19:02:11 +02:00
FIND=$(${PGREPBINARY:-pgrep} ${pgrep_options} -u "${user_uid}" "${search}" | ${TRBINARY:-tr} '\n' ' ')
2019-07-16 19:04:53 +02:00
fi
fi
done
else
LogText "Performing pgrep scan without uid"
2020-04-02 09:28:41 +02:00
FIND=$(${PGREPBINARY:-pgrep} ${pgrep_options} "${search}" | ${TRBINARY:-tr} '\n' ' ')
2019-07-16 19:04:53 +02:00
fi
2017-09-16 14:08:26 +02:00
else
2019-09-19 20:01:31 +02:00
if [ "${SHELL_IS_BUSYBOX}" -eq 1 ]; then
2019-07-16 19:04:53 +02:00
# This search is not foolproof
LogText "Performing simple ps scan (busybox)"
2017-12-24 14:05:55 +01:00
PSOPTIONS=" -o args="
2020-04-01 19:02:11 +02:00
FIND=$(${PSBINARY:-ps} ${PSOPTIONS} | ${EGREPBINARY:-egrep} "( |/)${search}" | ${GREPBINARY:-grep} -v "grep")
2019-07-16 19:04:53 +02:00
else
if [ -n "${users}" ]; then
2019-09-17 14:04:30 +02:00
for u in ${users}; do
2020-04-01 19:02:11 +02:00
user_uid=$(getent passwd "${u}" 2> /dev/null | ${AWKBINARY:-awk} -F: '{print $3}')
2019-07-16 19:04:53 +02:00
# Only perform search if user exists and we had no match yet
if [ -n "${user_uid}" ]; then
if [ -z "${FIND}" ]; then
if [ ${PARTIAL_SEARCH} -eq 1 ]; then
LogText "Performing ps scan using partial match and for uid ${user_uid}"
2020-04-01 19:02:11 +02:00
FIND=$(${PSBINARY:-ps} -u "${user_uid}" -o comm= "${search}" | ${AWKBINARY:-awk} -v pattern="${search}" '$0 ~ pattern {print}')
2019-07-16 19:04:53 +02:00
else
LogText "Performing ps scan using exact match and for uid ${user_uid}"
2020-04-01 19:02:11 +02:00
FIND=$(${PSBINARY:-ps} -u "${user_uid}" -o comm= "${search}" | ${AWKBINARY:-awk} -v pattern="^${search}$" '$0 ~ pattern {print}')
2019-07-16 19:04:53 +02:00
fi
fi
fi
done
else
2017-12-24 14:05:55 +01:00
case "${OS}" in
"Linux")
PSOPTIONS=" -o args= -C ${search}"
;;
esac
2019-07-16 19:04:53 +02:00
if [ ${PARTIAL_SEARCH} -eq 1 ]; then
LogText "Performing ps scan using partial match and without uid"
2020-04-01 19:02:11 +02:00
FIND=$(${PSBINARY:-ps} ${PSOPTIONS} | ${AWKBINARY:-awk} -v pattern="${search}" '$0 ~ pattern {print}')
2019-07-16 19:04:53 +02:00
else
LogText "Performing ps scan using exact match and without uid"
2020-04-01 19:02:11 +02:00
FIND=$(${PSBINARY:-ps} ${PSOPTIONS} | ${AWKBINARY:-awk} -v pattern="^${search}$" '$0 ~ pattern {print}')
2019-07-16 19:04:53 +02:00
fi
2017-12-24 14:05:55 +01:00
fi
fi
2017-09-16 14:08:26 +02:00
fi
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2014-08-26 17:33:55 +02:00
RUNNING=1
2017-10-29 10:54:40 +01:00
LogText "IsRunning: process '${search}' found (${FIND})"
2016-04-02 17:18:19 +02:00
return 0
2017-04-30 17:59:35 +02:00
else
2017-10-29 10:54:40 +01:00
LogText "IsRunning: process '${search}' not found"
2016-04-02 17:18:19 +02:00
return 1
2014-08-26 17:33:55 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-19 19:44:23 +02:00
2016-08-13 16:38:07 +02:00
################################################################################
# Name : IsNotebook
# Description : Check if file or directory is owned by root
2019-08-01 14:59:03 +02:00
# Returns : exit code (0 = True, 1 = False, 255 = Unknown)
2016-08-13 16:38:07 +02:00
################################################################################
IsNotebook() {
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
FIND=$(which laptop-detect 2> /dev/null | grep -v "no [^ ]* in ")
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2016-08-13 16:38:07 +02:00
Debug "Testing if we are a notebook"
laptop-detect
if [ $? -eq 0 ]; then SYSTEM_IS_NOTEBOOK=1; Debug "System is a notebook according to laptop-detect"
elif [ $? -eq 1 ]; then SYSTEM_IS_NOTEBOOK=0; Debug "System is a NOT a notebook according to laptop-detect"; fi
Report "notebook=${SYSTEM_IS_NOTEBOOK}"
fi
}
2016-04-26 21:20:37 +02:00
################################################################################
# Name : IsOwnedByRoot
# Description : Check if file or directory is owned by root
# Returns : 0 (true), 1 (false), or 255 (unknown)
################################################################################
IsOwnedByRoot() {
2016-05-09 14:20:16 +02:00
PERMS=""
2016-04-26 21:20:37 +02:00
if [ $# -eq 1 ]; then
FILE="$1"
case $OS in
"AIX")
2017-03-06 08:41:21 +01:00
if [ ! "${ISTATBINARY}" = "" ]; then PERMS=$(${ISTATBINARY} ${FILE} | sed "s/Owner: //" | sed "s/[a-zA-Z() ]//g"); fi
2016-04-26 21:20:37 +02:00
;;
"Linux")
2017-03-06 08:41:21 +01:00
if [ ! "${STATBINARY}" = "" ]; then PERMS=$(${STATBINARY} -c "%u:%g" ${FILE}); fi
2016-04-26 21:20:37 +02:00
;;
"FreeBSD")
2017-03-06 08:41:21 +01:00
if [ ! "${STATBINARY}" = "" ]; then PERMS=$(${STATBINARY} -f "%u:%g" ${FILE}); fi
2016-04-26 21:20:37 +02:00
;;
esac
# Fallback with ls (for other platforms, or when a test did not reveal any output)
if [ "${PERMS}" = "" ]; then
2017-03-06 08:41:21 +01:00
PERMS=$(ls -n ${FILE} | ${AWKBINARY} '{ print $3":"$4 }')
2016-04-26 21:20:37 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2016-04-26 21:20:37 +02:00
ReportException "IsOwnedByRoot" "Functions needs 1 argument"
return 255
fi
if [ "${PERMS}" = "0:0" ]; then
2016-04-26 21:25:14 +02:00
if IsDeveloperMode; then LogText "Debug: found incorrect file permissions on ${FILE}"; fi
2016-04-26 21:20:37 +02:00
return 0
2017-04-30 17:59:35 +02:00
else
2016-04-26 21:20:37 +02:00
return 1
fi
}
2016-04-19 19:44:23 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : IsVerbose()
2016-04-19 19:44:23 +02:00
# Description : Check if --verbose option is used to show more details on screen
2019-08-01 14:59:03 +02:00
#
# Parameters : <none>
# Returns : exit code (0 =true, 1 =false)
2016-04-19 19:44:23 +02:00
################################################################################
IsVerbose() {
if [ ${VERBOSE} -eq 1 ]; then return 0; else return 1; fi
}
2014-09-12 14:56:19 +02:00
################################################################################
# Name : IsVirtualMachine()
2016-07-30 12:08:43 +02:00
# Description : Determine whether it is a virtual machine
2019-08-01 14:59:03 +02:00
# Parameters : <none>
# Returns : exit code (0 = True, 1 = False, 2 = Unknown)
# variable: ISVIRTUALMACHINE (0-2)
# variable: VMTYPE
# variable: VMFULLTYPE
2014-09-12 14:56:19 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
IsVirtualMachine() {
2015-12-22 16:02:32 +01:00
LogText "Test: Determine if this system is a virtual machine"
2014-09-12 14:56:19 +02:00
# 0 = no, 1 = yes, 2 = unknown
ISVIRTUALMACHINE=2; VMTYPE="unknown"; VMFULLTYPE="Unknown"
2015-09-05 18:41:04 +02:00
SHORT=""
2014-12-03 22:45:23 +01:00
2019-04-13 13:26:56 +02:00
if [ ${SKIP_VM_DETECTION} -eq 1 ]; then
return 2
fi
2017-07-31 12:51:19 +02:00
# lxc environ detection
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2017-07-31 12:51:19 +02:00
if [ -f /proc/1/environ ]; then
2017-08-08 14:52:11 +02:00
FIND=$(grep -qa 'container=lxc' /proc/1/environ 2> /dev/null)
if [ $? -eq 0 ]; then
2017-07-31 12:51:19 +02:00
SHORT=lxc
LogText "Result: found ${SHORT}"
fi
fi
else
LogText "Result: skipped lxc environ detection test, as we already found machine type"
fi
2015-09-05 18:41:04 +02:00
# facter
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2016-11-19 13:39:57 +01:00
if [ -x /usr/bin/facter ] || [ -x /usr/local/bin/facter ]; then
2017-03-06 08:41:21 +01:00
case "$(facter is_virtual)" in
2015-09-09 20:24:48 +02:00
"true")
2017-03-06 08:41:21 +01:00
SHORT=$(facter virtual)
2015-12-22 16:02:32 +01:00
LogText "Result: found ${SHORT}"
2015-09-09 20:24:48 +02:00
;;
"false")
2015-12-22 16:02:32 +01:00
LogText "Result: facter says this machine is not a virtual"
2015-09-09 20:24:48 +02:00
;;
esac
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: facter utility not found"
2015-09-09 20:24:48 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: skipped facter test, as we already found machine type"
2015-07-27 12:38:13 +02:00
fi
2015-09-05 18:41:04 +02:00
# systemd
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2015-09-09 20:24:48 +02:00
if [ -x /usr/bin/systemd-detect-virt ]; then
2015-12-22 16:02:32 +01:00
LogText "Test: trying to guess virtualization technology with systemd-detect-virt"
2017-03-06 08:41:21 +01:00
FIND=$(/usr/bin/systemd-detect-virt)
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: found ${FIND}"
2015-09-09 20:24:48 +02:00
SHORT="${FIND}"
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: systemd-detect-virt not found"
2015-09-09 20:24:48 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: skipped systemd test, as we already found machine type"
2015-09-09 20:24:48 +02:00
fi
# lscpu
# Values: VMware
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2015-09-09 20:24:48 +02:00
if [ -x /usr/bin/lscpu ]; then
2015-12-22 16:02:32 +01:00
LogText "Test: trying to guess virtualization with lscpu"
2017-07-31 12:51:19 +02:00
FIND=$(lscpu | grep -i "^Hypervisor Vendor" | awk -F: '{ print $2 }' | sed 's/ //g')
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: found ${FIND}"
2015-09-09 20:24:48 +02:00
SHORT="${FIND}"
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: can't find hypervisor vendor with lscpu"
2015-09-09 20:24:48 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: lscpu not found"
2014-09-12 14:56:19 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: skipped lscpu test, as we already found machine type"
2014-12-03 22:45:23 +01:00
fi
2014-09-19 01:55:55 +02:00
2015-09-05 18:41:04 +02:00
# dmidecode
# Values: VMware Virtual Platform / VirtualBox
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2020-03-31 16:31:41 +02:00
# Try to find dmidecode in case we did not check binaries (e.g. lynis show environment)
if [ ${CHECK_BINARIES} -eq 0 ]; then DMIDECODEBINARY=$(command -v dmidecode 2> /dev/null); fi
2020-03-31 16:25:27 +02:00
if [ -n "${DMIDECODEBINARY}" -a -x "${DMIDECODEBINARY}" -a ${PRIVILEGED} -eq 1 ]; then
2015-12-22 16:02:32 +01:00
LogText "Test: trying to guess virtualization with dmidecode"
2020-03-31 16:25:27 +02:00
FIND=$(${DMIDECODEBINARY} -s system-product-name | awk '{ print $1 }')
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: found ${FIND}"
2015-09-09 20:24:48 +02:00
SHORT="${FIND}"
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: can't find product name with dmidecode"
2015-09-09 20:24:48 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2016-05-03 13:11:28 +02:00
LogText "Result: dmidecode not found (or no access)"
2015-09-05 18:41:04 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: skipped dmidecode test, as we already found machine type"
2015-09-05 18:41:04 +02:00
fi
2020-03-31 16:25:27 +02:00
2015-09-10 08:35:09 +02:00
# Other options
# SaltStack: salt-call grains.get virtual
# < needs snippet >
2014-12-03 22:45:23 +01:00
# Try common guest processes
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Test: trying to guess virtual machine type by running processes"
2014-09-19 01:55:55 +02:00
# VMware
2018-01-17 17:26:30 +01:00
if IsRunning vmware-guestd; then SHORT="vmware"
elif IsRunning vmtoolsd; then SHORT="vmware"
fi
2014-09-19 01:55:55 +02:00
# VirtualBox based on guest services
2018-01-17 17:26:30 +01:00
if IsRunning vboxguest-service; then SHORT="virtualbox"
elif IsRunning VBoxClient; then SHORT="virtualbox"
elif IsRunning VBoxService; then SHORT="virtualbox"
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: skipped processes test, as we already found platform"
2014-12-03 22:45:23 +01:00
fi
2014-12-03 14:10:52 +01:00
2014-12-03 22:45:23 +01:00
# Amazon EC2
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Test: checking specific files for Amazon"
2017-10-31 09:05:29 +01:00
if [ -f /etc/ec2_version -a -s /etc/ec2_version ]; then
2015-09-09 20:24:48 +02:00
SHORT="amazon-ec2"
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: system not hosted on Amazon"
2015-09-09 20:24:48 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: skipped Amazon EC2 test, as we already found platform"
2014-12-03 22:45:23 +01:00
fi
2014-12-03 14:10:52 +01:00
2014-12-03 22:45:23 +01:00
# sysctl values
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2015-12-22 16:02:32 +01:00
LogText "Test: trying to guess virtual machine type by sysctl keys"
2014-12-03 14:10:52 +01:00
2015-09-10 08:35:09 +02:00
# FreeBSD: hw.hv_vendor (remains empty for VirtualBox)
2014-12-03 22:45:23 +01:00
# NetBSD: machdep.dmi.system-product
# OpenBSD: hw.product
2019-09-19 14:05:15 +02:00
FIND=$(sysctl -a 2> /dev/null | grep -E "(hw.product|machdep.dmi.system-product)" | head -1 | sed 's/ = /=/' | awk -F= '{ print $2 }')
2015-09-09 20:24:48 +02:00
if [ ! "${FIND}" = "" ]; then
SHORT="${FIND}"
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: skipped sysctl test, as we already found platform"
2014-09-12 14:56:19 +02:00
fi
2014-09-19 01:55:55 +02:00
2016-05-03 13:15:46 +02:00
# lshw
2018-01-17 17:26:30 +01:00
if [ -z "${SHORT}" ]; then
2016-10-16 15:29:50 +02:00
if [ ${PRIVILEGED} -eq 1 ]; then
if [ -x /usr/bin/lshw ]; then
LogText "Test: trying to guess virtualization with lshw"
2017-03-06 08:41:21 +01:00
FIND=$(lshw -quiet -class system 2> /dev/null | awk '{ if ($1=="product:") { print $2 }}')
2017-04-30 17:59:35 +02:00
if HasData "${FIND}"; then
2016-10-16 15:29:50 +02:00
LogText "Result: found ${FIND}"
SHORT="${FIND}"
fi
2017-04-30 17:59:35 +02:00
else
2016-10-16 15:29:50 +02:00
LogText "Result: lshw not found"
2016-05-03 13:15:46 +02:00
fi
2016-10-16 15:29:50 +02:00
else
LogText "Result: skipped lshw test, as we are non-privileged and need more permissions to run lshw"
2016-05-03 13:15:46 +02:00
fi
2016-10-16 15:29:50 +02:00
else
2016-05-03 13:15:46 +02:00
LogText "Result: skipped lshw test, as we already found machine type"
fi
2017-03-06 08:41:21 +01:00
# Check if we caught some string along all tests
2020-04-02 09:28:41 +02:00
if [ -n "${SHORT}" ]; then
2014-12-03 22:45:23 +01:00
# Lowercase and see if we found a match
2018-07-05 15:57:19 +02:00
SHORT=$(echo ${SHORT} | awk '{ print $1 }' | tr '[:upper:]' '[:lower:]')
2014-12-03 22:45:23 +01:00
case ${SHORT} in
amazon-ec2) ISVIRTUALMACHINE=1; VMTYPE="amazon-ec2"; VMFULLTYPE="Amazon AWS EC2 Instance" ;;
bochs) ISVIRTUALMACHINE=1; VMTYPE="bochs"; VMFULLTYPE="Bochs CPU emulation" ;;
docker) ISVIRTUALMACHINE=1; VMTYPE="docker"; VMFULLTYPE="Docker container" ;;
kvm) ISVIRTUALMACHINE=1; VMTYPE="kvm"; VMFULLTYPE="KVM" ;;
lxc) ISVIRTUALMACHINE=1; VMTYPE="lxc"; VMFULLTYPE="Linux Containers" ;;
2015-05-26 11:11:15 +02:00
lxc-libvirt) ISVIRTUALMACHINE=1; VMTYPE="lxc-libvirt"; VMFULLTYPE="libvirt LXC driver (Linux Containers)" ;;
2014-12-03 22:45:23 +01:00
microsoft) ISVIRTUALMACHINE=1; VMTYPE="microsoft"; VMFULLTYPE="Microsoft Virtual PC" ;;
openvz) ISVIRTUALMACHINE=1; VMTYPE="openvz"; VMFULLTYPE="OpenVZ" ;;
oracle|virtualbox) ISVIRTUALMACHINE=1; VMTYPE="virtualbox"; VMFULLTYPE="Oracle VM VirtualBox" ;;
qemu) ISVIRTUALMACHINE=1; VMTYPE="qemu"; VMFULLTYPE="QEMU" ;;
systemd-nspawn) ISVIRTUALMACHINE=1; VMTYPE="systemd-nspawn"; VMFULLTYPE="Systemd Namespace container" ;;
uml) ISVIRTUALMACHINE=1; VMTYPE="uml"; VMFULLTYPE="User-Mode Linux (UML)" ;;
vmware) ISVIRTUALMACHINE=1; VMTYPE="vmware"; VMFULLTYPE="VMware product" ;;
xen) ISVIRTUALMACHINE=1; VMTYPE="xen"; VMFULLTYPE="XEN" ;;
zvm) ISVIRTUALMACHINE=1; VMTYPE="zvm"; VMFULLTYPE="IBM z/VM" ;;
2016-08-11 10:01:57 +02:00
openstack) ISVIRTUALMACHINE=1; VMTYPE="openstack"; VMFULLTYPE="Openstack Nova" ;;
2015-12-22 16:02:32 +01:00
*) LogText "Result: Unknown virtualization type, so most likely system is physical" ;;
2014-12-03 22:45:23 +01:00
esac
fi
2014-12-03 14:10:52 +01:00
2014-09-19 01:55:55 +02:00
# Check final status
2014-09-12 14:56:19 +02:00
if [ ${ISVIRTUALMACHINE} -eq 1 ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: found virtual machine (type: ${VMTYPE}, ${VMFULLTYPE})"
Report "vm=1"
Report "vmtype=${VMTYPE}"
2015-09-09 20:24:48 +02:00
elif [ ${ISVIRTUALMACHINE} -eq 2 ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: unknown if this system is a virtual machine"
Report "vm=2"
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Result: system seems to be non-virtual"
2014-09-12 14:56:19 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-09-12 14:56:19 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : IsWorldReadable()
# Description : Determines if a file is readable for all users (world)
#
2019-08-01 14:59:03 +02:00
# Input : $1 = path (string)
2016-04-28 12:31:38 +02:00
# Returns : exit code (0 = readable, 1 = not readable, 255 = error)
# Usage : if IsWorldReadable /etc/motd; then echo "File is readable"; fi
################################################################################
IsWorldReadable() {
2017-04-30 17:59:35 +02:00
if [ $# -eq 0 ]; then ExitFatal "Missing parameter when calling IsWorldReadable function"; fi
2015-03-25 17:31:47 +01:00
sFILE=$1
# Check for symlink
if [ -L ${sFILE} ]; then
ShowSymlinkPath ${sFILE}
2016-04-28 12:31:38 +02:00
if [ ! "${SYMLINK}" = "" ]; then sFILE="${SYMLINK}"; fi
2015-03-25 17:31:47 +01:00
fi
2016-04-28 12:31:38 +02:00
if [ -f ${sFILE} -o -d ${sFILE} ]; then
2017-03-06 08:41:21 +01:00
FINDVAL=$(ls -ld ${sFILE} | cut -c 8)
2015-12-22 16:02:32 +01:00
if [ "${FINDVAL}" = "r" ]; then return 0; else return 1; fi
2017-04-30 17:59:35 +02:00
else
2015-03-25 17:31:47 +01:00
return 255
fi
2016-04-28 12:31:38 +02:00
}
2015-03-25 17:31:47 +01:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : IsWorldExecutable()
# Description : Determines if a file is executable for all users (world)
#
2019-08-01 14:59:03 +02:00
# Input : $1 = path (string)
2016-04-28 12:31:38 +02:00
# Returns : exit code (0 = executable, 1 = not executable, 255 = error)
# Usage : if IsWorldExecutable /bin/ps; then echo "File is executable"; fi
################################################################################
2014-08-26 17:33:55 +02:00
# Function IsWorldExecutable
2016-04-28 12:31:38 +02:00
IsWorldExecutable() {
2017-04-30 17:59:35 +02:00
if [ $# -eq 0 ]; then ExitFatal "Missing parameter when calling IsWorldExecutable function"; fi
2014-08-26 17:33:55 +02:00
sFILE=$1
# Check for symlink
if [ -L ${sFILE} ]; then
2015-03-25 17:31:47 +01:00
ShowSymlinkPath ${sFILE}
2016-04-28 12:31:38 +02:00
if [ ! "${SYMLINK}" = "" ]; then sFILE="${SYMLINK}"; fi
2014-08-26 17:33:55 +02:00
fi
2016-04-28 12:31:38 +02:00
if [ -f ${sFILE} -o -d ${sFILE} ]; then
2017-03-06 08:41:21 +01:00
FINDVAL=$(ls -l ${sFILE} | cut -c 10)
2015-12-22 16:02:32 +01:00
if [ "${FINDVAL}" = "x" ]; then return 0; else return 1; fi
2017-04-30 17:59:35 +02:00
else
2015-03-25 17:31:47 +01:00
return 255
2014-08-26 17:33:55 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-26 13:52:26 +02:00
2015-12-22 16:02:32 +01:00
################################################################################
# Name : IsWorldWritable()
# Description : Determines if a file is writable for all users
2016-04-28 12:31:38 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = path
2015-12-22 16:02:32 +01:00
# Returns : exit code (0 = writable, 1 = not writable, 255 = error)
# Usage : if IsWorldWritable /etc/motd; then echo "File is writable"; fi
################################################################################
2016-04-26 13:52:26 +02:00
IsWorldWritable() {
2017-04-30 17:59:35 +02:00
if [ $# -eq 0 ]; then ExitFatal "Missing parameter when calling IsWorldWritable function"; fi
2014-08-26 17:33:55 +02:00
sFILE=$1
FileIsWorldWritable=""
2016-04-26 13:52:26 +02:00
# Only check if target is a file or directory
if [ -f ${sFILE} -o -d ${sFILE} ]; then
2017-03-06 08:41:21 +01:00
FINDVAL=$(ls -ld ${sFILE} | cut -c 9)
2016-04-26 13:52:26 +02:00
if IsDeveloperMode; then Debug "File mode of ${sFILE} is ${FINDVAL}"; fi
2016-04-28 12:31:38 +02:00
if [ "${FINDVAL}" = "w" ]; then return 0; else return 1; fi
2017-04-30 17:59:35 +02:00
else
2015-03-25 17:31:47 +01:00
return 255
2014-08-26 17:33:55 +02:00
fi
2016-04-26 13:52:26 +02:00
}
2014-08-26 17:33:55 +02:00
2015-12-22 16:02:32 +01:00
################################################################################
# Name : LogText()
# Description : Function logtext (redirect data ($1) to log file)
2016-04-28 12:31:38 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = text (string)
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
# Usage : LogText "This line goes into the log file"
2015-12-22 16:02:32 +01:00
################################################################################
2016-04-28 12:31:38 +02:00
LogText() {
2016-08-26 14:05:20 +02:00
if [ ! "${LOGFILE}" = "" -a ${LOGTEXT} -eq 1 ]; then CDATE=$(date "+%Y-%m-%d %H:%M:%S"); echo "${CDATE} $1" >> ${LOGFILE}; fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : LogTextBreak()
2014-08-26 17:33:55 +02:00
# Description : Add a separator to log file between sections, tests etc
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
################################################################################
LogTextBreak() {
2016-08-26 14:05:20 +02:00
if [ ! "${LOGFILE}" = "" -a ${LOGTEXT} -eq 1 ]; then
2016-07-11 10:32:00 +02:00
CDATE=$(date "+%Y-%m-%d %H:%M:%S")
2019-12-13 12:36:19 +01:00
echo "${CDATE} ====" >> ${LOGFILE}
2014-08-26 17:33:55 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2018-02-19 15:01:26 +01:00
################################################################################
# Name : PackageIsInstalled()
2019-04-08 07:53:04 +02:00
# Description : Determines if a package is installed
2018-02-19 15:01:26 +01:00
# Returns : exit code
# Notes : this function is not used yet, but created in advance to allow
# the addition of support for all operating systems
################################################################################
PackageIsInstalled() {
exit_code=255
if [ $# -eq 1 ]; then
package="$1"
else
Fatal "Incorrect usage of PackageIsInstalled function"
fi
2019-07-16 13:20:30 +02:00
if [ -n "${DNFBINARY}" ]; then
2019-04-07 15:52:52 +02:00
output=$(${DNFBINARY} --quiet --cacheonly --noplugins --assumeno info --installed ${package} > /dev/null 2>&1)
2018-02-19 15:01:26 +01:00
exit_code=$?
2019-07-16 13:20:30 +02:00
elif [ -n "${DPKGBINARY}" ]; then
2019-04-08 15:09:18 +02:00
output=$(${DPKGBINARY} -l ${package} 2> /dev/null | ${GREPBINARY} "^ii")
2019-04-07 15:52:52 +02:00
exit_code=$?
2019-07-16 13:20:30 +02:00
elif [ -n "${EQUERYBINARY}" ]; then
2019-04-07 15:52:52 +02:00
output=$(${EQUERYBINARY} --quiet ${package} > /dev/null 2>&1)
exit_code=$? # 0=package installed, 3=package not installed
2019-08-13 20:02:49 +02:00
elif [ -n "${PACMANBINARY}" ]; then
2019-08-13 21:00:43 +02:00
output=$(${PACMANBINARY} -Qs ${PKG} | grep "local/${PKG} " >/dev/null 2>&1)
2019-08-13 20:02:49 +02:00
exit_code=$? # 0=package installed, 1=package not installed
2019-07-16 13:20:30 +02:00
elif [ -n "${PKG_BINARY}" ]; then
2019-04-08 07:53:04 +02:00
output=$(${PKG_BINARY} -N info ${package} >/dev/null 2>&1)
2019-04-07 15:52:52 +02:00
exit_code=$? # 0=package installed, 70=invalid package
2020-03-30 21:12:36 +02:00
elif [ -n "${PKGINFOBINARY}" ]; then
output=$(${PKGINFOBINARY} -q -e ${package} >/dev/null 2>&1)
exit_code=$? # 0=package installed, 1=package not installed
2019-07-16 13:20:30 +02:00
elif [ -n "${RPMBINARY}" ]; then
2019-04-07 15:52:52 +02:00
output=$(${RPMBINARY} --quiet -q ${package} > /dev/null 2>&1)
2018-02-19 15:01:26 +01:00
exit_code=$?
2019-08-04 19:37:55 +02:00
elif [ -n "${SWUPDBINARY}" ]; then
2019-08-04 19:40:02 +02:00
output=$(${SWUPDBINARY} bundle-list > /dev/null 2>&1 | ${GREPBINARY} "^${package}$")
2019-08-04 19:37:55 +02:00
exit_code=$?
2019-07-16 13:20:30 +02:00
elif [ -n "${ZYPPERBINARY}" ]; then
2019-09-17 14:04:30 +02:00
output=$(${ZYPPERBINARY} --quiet --non-interactive search --installed -i ${package} 2> /dev/null | grep "^i")
2019-07-16 13:20:30 +02:00
if [ -n "${output}" ]; then exit_code=0; else exit_code=1; fi
2020-02-21 08:04:08 +01:00
elif [ -n "${XBPSBINARY}" ]; then
output=$(${XBPSBINARY} ${package} 2> /dev/null | ${GREPBINARY} "^ii")
exit_code=$?
2018-02-19 15:01:26 +01:00
else
ReportException "PackageIsInstalled:01"
fi
return ${exit_code}
}
2016-07-11 10:32:00 +02:00
################################################################################
# Name : ParseProfiles()
# Description : Check file permissions and parse data from profiles
2019-08-01 14:59:03 +02:00
# Parameters : <none>
2016-07-11 10:32:00 +02:00
# Returns : <nothing>
################################################################################
2016-07-05 16:47:32 +02:00
ParseProfiles() {
SafePerms ${INCLUDEDIR}/profiles
. ${INCLUDEDIR}/profiles
}
2016-05-04 21:38:42 +02:00
################################################################################
# Name : ParseTestValues()
2016-07-11 10:32:00 +02:00
# Description : Parse values from a specific test
2019-08-01 14:59:03 +02:00
#
# Parameters : $1 = service (e.g. ssh)
# Returns : CHECK_VALUES_ARRAY variable
2016-05-04 21:38:42 +02:00
################################################################################
ParseTestValues() {
2016-05-09 14:20:16 +02:00
RETVAL=1
2016-05-04 21:38:42 +02:00
FOUND=0
CHECK_VALUES_ARRAY=""
if [ $# -gt 0 -a ! "${CHECK_OPTION_ARRAY}" = "" ]; then
for I in ${CHECK_OPTION_ARRAY}; do
Debug "Array value: ${I}"
SPLIT=$(echo ${I} | sed 's/,/\n/g')
for ITEM in ${SPLIT}; do
FUNCTION=""
VALUE=""
SEARCH=""
SERVICE=""
ITEM_KEY=$(echo ${ITEM} | awk -F: '{print $1}')
ITEM_VALUE=$(echo ${ITEM} | awk -F: '{print $2}')
Debug "Array item: ${ITEM_KEY} with value ${ITEM_VALUE}"
case ${ITEM_KEY} in
"function")
case ${ITEM_VALUE} in
"equals")
FUNCTION="eq"
;;
esac
;;
"service")
if [ "${ITEM_VALUE}" = "$1" ]; then
FOUND=1
fi
;;
"value")
VALUE="${ITEM_VALUE}"
;;
*)
echo "Incorrect call to function ParseTestValues"; ExitFatal
;;
esac
if [ ${FOUND} -eq 1 ]; then
CHECK_VALUES_ARRAY="${CHECK_VALUES_ARRAY} ${SEARCH}:${VALUE}:${FUNCTION}:"
FOUND=0
fi
done
done
RETVAL=1
fi
return ${RETVAL}
}
2016-04-28 12:31:38 +02:00
################################################################################
# Name : ParseNginx()
# Description : Parse nginx configuration lines
2019-08-01 14:59:03 +02:00
#
# Parameters : $1 = file (should be readable and tested upfront)
2016-04-28 12:31:38 +02:00
# Returns : <nothing>
################################################################################
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
ParseNginx() {
2016-08-16 08:07:08 +02:00
COUNT=0
BREADCRUMB=""
if [ $# -eq 0 ]; then ExitFatal "No arguments provided to ParseNginx()"; fi
CONFIG_FILE=$1
# Create temporary files
CreateTempFile || ExitFatal "Could not create temporary file"
TMP_NGINX_FILE_RAW="${TEMP_FILE}"
CreateTempFile || ExitFatal "Could not create temporary file"
TMP_NGINX_FILE="${TEMP_FILE}"
# Strip out spaces, tabs and line breaks
awk '{$1=$1;print $0}' ${CONFIG_FILE} > ${TMP_NGINX_FILE_RAW}
# Now clean up the file further (combine lines, remove commented lines and empty lines)
2019-09-17 14:04:30 +02:00
sed 's#\\$##g' ${TMP_NGINX_FILE_RAW} | grep -v "^#" | grep -v "^$" > ${TMP_NGINX_FILE}
2016-08-16 08:07:08 +02:00
LogText "Action: parsing configuration file ${CONFIG_FILE}"
COUNT=$(( COUNT + 1))
2019-09-17 14:04:30 +02:00
FIND=$(sed 's/ /:space:/g' ${TMP_NGINX_FILE})
2016-08-16 08:07:08 +02:00
DEPTH=0
2014-08-26 17:33:55 +02:00
for I in ${FIND}; do
2017-03-06 08:41:21 +01:00
I=$(echo ${I} | sed 's/:space:/ /g' | sed 's/;$//' | sed 's/ #.*$//')
OPTION=$(echo ${I} | awk '{ print $1 }')
VALUE=$(echo ${I}| cut -d' ' -f2-)
2016-08-16 08:07:08 +02:00
LogText "Result: found option ${OPTION} in ${CONFIG_FILE} with value '${VALUE}'"
STORE_SETTING=1
2014-08-26 17:33:55 +02:00
case ${OPTION} in
2016-08-16 08:07:08 +02:00
"events")
BREADCRUMB="${BREADCRUMB}/events"
DEPTH=$(( DEPTH + 1))
STORE_SETTING=0
NGINX_EVENTS_COUNTER=$(( NGINX_EVENTS_COUNTER + 1 ))
;;
"http")
BREADCRUMB="${BREADCRUMB}/http"
DEPTH=$(( DEPTH + 1))
STORE_SETTING=0
NGINX_HTTP_COUNTER=$(( NGINX_HTTP_COUNTER + 1 ))
;;
"location")
BREADCRUMB="${BREADCRUMB}/location"
DEPTH=$(( DEPTH + 1))
STORE_SETTING=0
NGINX_LOCATION_COUNTER=$(( NGINX_LOCATION_COUNTER + 1 ))
;;
"server")
BREADCRUMB="${BREADCRUMB}/server"
DEPTH=$(( DEPTH + 1))
STORE_SETTING=0
NGINX_SERVER_COUNTER=$(( NGINX_SERVER_COUNTER + 1 ))
;;
"}")
BREADCRUMB=$(echo ${BREADCRUMB} | awk -F/ 'sub(FS $NF,x)')
DEPTH=$(( DEPTH - 1))
STORE_SETTING=0
;;
2014-08-26 17:33:55 +02:00
access_log)
if [ "${VALUE}" = "off" ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: found logging disabled for one virtual host"
2014-08-26 17:33:55 +02:00
NGINX_ACCESS_LOG_DISABLED=1
2017-04-30 17:59:35 +02:00
else
2015-03-17 19:02:46 +01:00
if [ ! "${VALUE}" = "" ]; then
2015-04-29 13:53:40 +02:00
# If multiple values follow, select first one
2017-03-06 08:41:21 +01:00
VALUE=$(echo ${VALUE} | awk '{ print $1 }')
2019-09-26 21:24:15 +02:00
# Find both, log files provided with full or relative path
if [ ! -f ${VALUE} -a ! -f "${CONFIG_FILE%nginx.conf}${VALUE}" ]; then
LogText "Result: could not find log file ${VALUE} referenced in nginx configuration"
2015-03-17 19:02:46 +01:00
NGINX_ACCESS_LOG_MISSING=1
fi
2014-08-26 17:33:55 +02:00
fi
fi
;;
# Headers
add_header)
2017-03-06 08:41:21 +01:00
HEADER=$(echo ${VALUE} | awk '{ print $1 }')
HEADER_VALUE=$(echo ${VALUE} | cut -d' ' -f2-)
2015-12-22 16:02:32 +01:00
LogText "Result: found header ${HEADER} with value ${HEADER_VALUE}"
#Report "nginx_header[]=${HEADER}|${HEADER_VALUE}|"
2014-08-26 17:33:55 +02:00
;;
alias)
NGINX_ALIAS_FOUND=1
;;
allow)
NGINX_ALLOW_FOUND=1
;;
autoindex)
;;
deny)
NGINX_DENY_FOUND=1
;;
expires)
NGINX_EXPIRES_FOUND=1
;;
error_log)
2015-07-22 13:44:30 +02:00
# Check if debug is appended
2017-03-06 08:41:21 +01:00
FIND=$(echo ${VALUE} | awk '{ if ($2=="debug") { print 1 } else { print 0 }}')
2014-08-26 17:33:55 +02:00
if [ ${FIND} -eq 1 ]; then
NGINX_ERROR_LOG_DEBUG=1
fi
2015-07-22 13:44:30 +02:00
# Check if log file exists
2017-03-06 08:41:21 +01:00
FILE=$(echo ${VALUE} | awk '{ print $1 }')
2014-08-26 17:33:55 +02:00
if [ ! "${FILE}" = "" ]; then
2019-09-26 21:24:15 +02:00
# Find both, log files provided with full or relative path
if [ ! -f ${FILE} -a ! -f "${CONFIG_FILE%nginx.conf}${FILE}" ]; then
2017-03-07 20:23:08 +01:00
NGINX_ERROR_LOG_MISSING=1
2014-08-26 17:33:55 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2015-12-22 16:02:32 +01:00
LogText "Warning: did not find a filename after error_log in nginx configuration"
2014-08-26 17:33:55 +02:00
fi
;;
error_page)
;;
fastcgi_intercept_errors)
;;
fastcgi_param)
NGINX_FASTCGI_FOUND=1
NGINX_FASTCGI_PARAMS_FOUND=1
;;
fastcgi_pass)
NGINX_FASTCGI_FOUND=1
NGINX_FASTCGI_PASS_FOUND=1
;;
fastcgi_pass_header)
;;
2016-08-16 08:36:42 +02:00
include)
if [ -f "${VALUE}" ]; then
FOUND=0
for CONF in ${NGINX_CONF_FILES}; do
if [ "${CONF}" = "${VALUE}" ]; then FOUND=1; LogText "Found this file already in our configuration files array, not adding to queue"; fi
done
for CONF in ${NGINX_CONF_FILES_ADDITIONS}; do
if [ "${CONF}" = "${VALUE}" ]; then FOUND=1; LogText "Found this file already in our configuration files array (additions), not adding to queue"; fi
done
if [ ${FOUND} -eq 0 ]; then NGINX_CONF_FILES_ADDITIONS="${NGINX_CONF_FILES_ADDITIONS} ${VALUE}"; fi
2019-09-18 20:47:09 +02:00
# Check if include value is a relative path only
elif [ -f "${CONFIG_FILE%nginx.conf}${VALUE%;*}" ]; then
VALUE="${CONFIG_FILE%nginx.conf}${VALUE}"
FOUND=0
for CONF in ${NGINX_CONF_FILES}; do
if [ "${CONF}" = "${VALUE}" ]; then FOUND=1; LogText "Found this file already in our configuration files array, not adding to queue"; fi
done
for CONF in ${NGINX_CONF_FILES_ADDITIONS}; do
if [ "${CONF}" = "${VALUE}" ]; then FOUND=1; LogText "Found this file already in our configuration files array (additions), not adding to queue"; fi
done
if [ ${FOUND} -eq 0 ]; then NGINX_CONF_FILES_ADDITIONS="${NGINX_CONF_FILES_ADDITIONS} ${VALUE}"; fi
# Check for additional config files included as follows
# "include sites-enabled/*.conf"
elif [ $(echo ${VALUE} | grep -F -c "*.conf") -gt 0 ]; then
for FOUND_CONF in $(ls ${CONFIG_FILE%nginx.conf}${VALUE%;*}); do
FOUND=0
for CONF in ${NGINX_CONF_FILES}; do
if [ "${CONF}" = "${FOUND_CONF}" ]; then FOUND=1; LogText "Found this file already in our configuration files array, not adding to queue"; fi
done
for CONF in ${NGINX_CONF_FILES_ADDITIONS}; do
if [ "${CONF}" = "${FOUND_CONF}" ]; then FOUND=1; LogText "Found this file already in our configuration files array (additions), not adding to queue"; fi
done
if [ ${FOUND} -eq 0 ]; then NGINX_CONF_FILES_ADDITIONS="${NGINX_CONF_FILES_ADDITIONS} ${FOUND_CONF}"; fi
done
2016-08-16 08:36:42 +02:00
else
LogText "Result: this include does not point to a file"
fi
;;
2014-08-26 17:33:55 +02:00
index)
;;
keepalive_timeout)
;;
listen)
NGINX_LISTEN_FOUND=1
# Test for ssl on listen statement
2017-03-06 08:41:21 +01:00
FIND_SSL=$(echo ${VALUE} | grep ssl)
2014-08-26 17:33:55 +02:00
if [ ! "${FIND_SSL}" = "" ]; then NGINX_SSL_ON=1; fi
;;
location)
NGINX_LOCATION_FOUND=1
;;
return)
NGINX_RETURN_FOUND=1
;;
root)
NGINX_ROOT_FOUND=1
;;
server_name)
;;
ssl)
if [ "${VALUE}" = "on" ]; then NGINX_SSL_ON=1; fi
;;
ssl_certificate)
2015-12-22 16:02:32 +01:00
LogText "Found SSL certificate in nginx configuration"
2014-08-26 17:33:55 +02:00
;;
ssl_certificate_key)
;;
ssl_ciphers)
NGINX_SSL_CIPHERS=1
;;
ssl_prefer_server_ciphers)
if [ "${VALUE}" = "on" ]; then NGINX_SSL_PREFER_SERVER_CIPHERS=1; fi
;;
ssl_protocols)
2014-10-13 19:36:36 +02:00
NGINX_SSL_PROTOCOLS=1
2017-03-06 08:41:21 +01:00
VALUE=$(echo ${VALUE} | sed 's/;$//' | tr '[:upper:]' '[:lower:]')
2016-04-27 16:09:29 +02:00
for ITEM in ${VALUE}; do
2016-04-27 16:51:12 +02:00
LogText "Result: found protocol ${ITEM}"
case ${ITEM} in
2019-06-24 15:40:18 +02:00
"sslv2" | "sslv3" | "tlsv1")
2016-04-27 16:51:12 +02:00
NGINX_WEAK_SSL_PROTOCOL_FOUND=1
;;
esac
2016-04-27 16:09:29 +02:00
Report "ssl_tls_protocol_enabled[]=${ITEM}"
ReportDetails --service nginx --field protocol --value "${ITEM}"
done
2014-08-26 17:33:55 +02:00
;;
ssl_session_cache)
;;
ssl_session_timeout)
;;
types)
;;
*)
2015-12-22 16:02:32 +01:00
LogText "Found unknown option ${OPTION} in nginx configuration"
2014-08-26 17:33:55 +02:00
;;
esac
2016-08-16 08:07:08 +02:00
if [ ${STORE_SETTING} -eq 1 ]; then
CONFIG_TREE="${BREADCRUMB}"
if [ -z "${CONFIG_TREE}" ]; then CONFIG_TREE="/"; fi
if [ -z "${OPTION}" ]; then OPTION="NA"; fi
if [ -z "${VALUE}" ]; then VALUE="NA"; fi
StoreNginxSettings --config ${CONFIG_FILE} --tree ${CONFIG_TREE} --depth ${DEPTH} --setting ${OPTION} --value "${VALUE}"
fi
2014-08-26 17:33:55 +02:00
done
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-03-30 13:45:34 +02:00
################################################################################
# Name : PortIsListening()
# Description : Check if machine is listening on specified protocol and port
2019-08-01 14:59:03 +02:00
#
# Parameters : $1 = protocol
# $2 = port
# Returns : exit code (0 = listening, 1 = not listening, 255 = can't perform test)
2016-03-30 13:45:34 +02:00
# Usage : if PortIsListening "TCP" 22; then echo "Port is listening"; fi
################################################################################
2016-04-28 12:31:38 +02:00
PortIsListening() {
2019-08-01 14:59:03 +02:00
if [ -z "${LSOFBINARY}" ]; then
2016-03-30 13:45:34 +02:00
return 255
2017-04-30 17:59:35 +02:00
else
2016-03-30 13:45:34 +02:00
if [ $# -eq 2 ] && [ $1 = "TCP" -o $1 = "UDP" ]; then
LogText "Test: find service listening on $1:$2"
2019-09-13 11:47:39 +02:00
if [ $1 = "TCP" ]; then FIND=$(${LSOFBINARY}${LSOF_EXTRA_OPTIONS} -i${1} -s${1}:LISTEN -P -n | grep ":${2} "); else FIND=$(${LSOFBINARY}${LSOF_EXTRA_OPTIONS} -i${1} -P -n | grep ":${2} "); fi
2016-03-30 13:45:34 +02:00
if [ ! "${FIND}" = "" ]; then
LogText "Result: found service listening on port $2 ($1)"
return 0
2017-04-30 17:59:35 +02:00
else
2016-03-30 13:45:34 +02:00
LogText "Result: did not find service listening on port $2 ($1)"
return 1
fi
2017-04-30 17:59:35 +02:00
else
2016-03-30 13:45:34 +02:00
return 255
ReportException ${TEST_NO} "Error in function call to PortIsListening"
fi
fi
2016-04-28 12:31:38 +02:00
}
2016-03-30 13:45:34 +02:00
2016-04-25 11:13:27 +02:00
2014-12-03 22:45:23 +01:00
################################################################################
# Name : Progress()
# Description : Displays progress on screen with dots
2016-04-28 12:31:38 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = --finish or text (string)
2016-04-28 12:31:38 +02:00
# Returns : <nothing>
2014-12-03 22:45:23 +01:00
# Tip : Use this function from Register with the --progress parameter
2015-12-22 16:02:32 +01:00
################################################################################
2016-04-25 11:13:27 +02:00
Progress() {
2014-11-25 14:22:52 +01:00
if [ ${CRONJOB} -eq 0 ]; then
2016-04-25 11:13:27 +02:00
if [ ${QUIET} -eq 0 ]; then
if [ "$1" = "--finish" ]; then
${ECHOCMD} ""
else
# If the No-Break version of echo is known, use that (usually breaks in combination with -e)
if [ ! "${ECHONB}" = "" ]; then
${ECHONB} "$1"
2017-04-30 17:59:35 +02:00
else
2016-04-25 11:13:27 +02:00
${ECHOCMD} -en "$1"
fi
2014-12-03 22:45:23 +01:00
fi
fi
2014-11-25 14:22:52 +01:00
fi
2016-04-25 11:13:27 +02:00
}
2014-08-26 17:33:55 +02:00
2015-12-22 16:02:32 +01:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : RandomString()
2015-12-22 16:02:32 +01:00
# Description : Displays progress on screen with dots
2019-08-01 14:59:03 +02:00
#
# Parameters : $1 = number (amount of characters, optional)
# Returns : RANDOMSTRING variable
2015-12-22 16:02:32 +01:00
# Usage : RandomString 32
################################################################################
RandomString() {
# Check a (pseudo) random character device
2016-05-09 14:20:16 +02:00
if [ -c /dev/urandom ]; then FILE="/dev/urandom"
elif [ -c /dev/random ]; then FILE="/dev/random"
2015-12-22 16:02:32 +01:00
else
Display "Can not use RandomString function, as there is no random device to be used"
fi
2016-05-09 14:20:16 +02:00
if [ $# -eq 0 ]; then SIZE=16; else SIZE=$1; fi
CSIZE=$((SIZE / 2))
2017-03-06 08:41:21 +01:00
RANDOMSTRING=$(head -c ${CSIZE} /dev/urandom | od -An -x | tr -d ' ' | cut -c 1-${SIZE})
2015-12-22 16:02:32 +01:00
}
2014-08-26 17:33:55 +02:00
2019-07-05 18:35:45 +02:00
################################################################################
# Name : Readonly()
# Description : Mark a variable as read-only data
2019-08-01 14:59:03 +02:00
#
# Returns : <nothing>
# Notes : new function, not in use yet
2019-07-05 18:35:45 +02:00
################################################################################
Readonly() {
if [ $# -eq 1 ]; then
if type -t typeset; then
typeset -r $1
else
Debug "No typeset available to mark variable '$1' as read-only variable"
fi
else
ExitFatal "Expected 1 parameter, received none or multiple"
fi
}
2014-08-26 17:33:55 +02:00
################################################################################
# Name : Register()
# Description : Register a test and see if it has to be run
2019-08-01 14:59:03 +02:00
#
# Parameters : multiple, see test
2014-08-26 17:33:55 +02:00
# Returns : SKIPTEST (0 or 1)
2016-04-28 12:31:38 +02:00
################################################################################
2019-07-12 14:20:32 +02:00
GetTimestamp() {
ts=0
case "${OS}" in
"Linux")
ts=$(date "+%s%N")
;;
*)
ts=$(date "+%s")
;;
esac
echo $ts
}
2016-04-25 15:49:00 +02:00
Register() {
2014-08-26 17:33:55 +02:00
# Do not insert a log break, if previous test was not logged
2016-04-28 12:31:38 +02:00
if [ ${SKIPLOGTEST} -eq 0 ]; then LogTextBreak; fi
2016-08-13 10:16:15 +02:00
ROOT_ONLY=0; SKIPTEST=0; SKIPLOGTEST=0; SKIPREASON=""; TEST_NEED_OS=""; PREQS_MET=""
2016-07-24 17:22:00 +02:00
TEST_CATEGORY=""; TEST_NEED_NETWORK=""; TEST_NEED_PLATFORM=""
2016-05-03 14:57:53 +02:00
TOTAL_TESTS=$((TOTAL_TESTS + 1))
2014-08-26 17:33:55 +02:00
while [ $# -ge 1 ]; do
case $1 in
2016-07-24 17:22:00 +02:00
--category)
shift
TEST_CATEGORY=$1
;;
2014-08-26 17:33:55 +02:00
--description)
shift
TEST_DESCRIPTION=$1
;;
--platform)
shift
TEST_NEED_PLATFORM=$1
;;
--network)
shift
TEST_NEED_NETWORK=$1
;;
--os)
shift
TEST_NEED_OS=$1
;;
--preqs-met)
shift
PREQS_MET=$1
;;
2014-11-25 14:22:52 +01:00
--progress)
2014-12-03 22:45:23 +01:00
Progress "."
2014-11-25 14:22:52 +01:00
;;
2014-09-08 15:03:22 +02:00
--root-only)
shift
if [ "$1" = "YES" -o "$1" = "yes" ]; then
2017-03-07 20:23:08 +01:00
ROOT_ONLY=1
elif [ "$1" = "NO" -o "$1" = "no" ]; then
ROOT_ONLY=0
2017-04-30 17:59:35 +02:00
else
2014-09-08 15:03:22 +02:00
Debug "Invalid option for --root-only parameter of Register function"
fi
;;
2016-08-13 10:16:15 +02:00
--skip-reason)
shift
SKIPREASON="$1"
;;
2014-08-26 17:33:55 +02:00
--test-no)
shift
TEST_NO=$1
;;
--weight)
shift
TEST_WEIGHT=$1
;;
*)
echo "INVALID OPTION (Register): $1"
exit 1
;;
esac
# Go to next parameter
shift
done
2019-07-12 14:20:32 +02:00
# Measure timing
CURRENT_TS=$(GetTimestamp)
if [ ${PREVIOUS_TS} -gt 0 ]; then
SLOW_TEST=0
TIME_THRESHOLD=10 # seconds
# Calculate timing and determine if we use seconds or nanoseconds (more precise)
2019-09-17 14:04:30 +02:00
TIME_DIFF=$((CURRENT_TS - PREVIOUS_TS))
2019-07-12 14:20:32 +02:00
if [ ${CURRENT_TS} -gt 1000000000000000000 ]; then
TIME_DIFF_FORMAT="nanoseconds"
2019-09-17 14:04:30 +02:00
TIME_THRESHOLD=$((TIME_THRESHOLD * 1000000000))
2019-07-12 14:20:32 +02:00
if [ ${TIME_DIFF} -gt ${TIME_THRESHOLD} ]; then
SLOW_TEST=1
# Convert back to seconds for readability
TIME_DIFF_FORMAT="seconds"
TIME_DIFF=$(echo ${TIME_DIFF} | ${AWKBINARY} '{printf "%f",$1/1000000000}')
fi
else
TIME_DIFF_FORMAT="seconds"
if [ ${TIME_DIFF} -gt ${TIME_THRESHOLD} ]; then
SLOW_TEST=1
fi
fi
if [ ${SLOW_TEST} -eq 1 ]; then
DisplayWarning "Test ${PREVIOUS_TEST} had a long execution: ${TIME_DIFF} ${TIME_DIFF_FORMAT}"
Report "slow_test[]=${PREVIOUS_TEST},${TIME_DIFF}"
fi
fi
2016-04-19 12:37:00 +02:00
# Skip test if it's configured in profile (old style)
2014-08-26 17:33:55 +02:00
if [ ${SKIPTEST} -eq 0 ]; then
2017-03-06 08:41:21 +01:00
FIND=$(echo "${TEST_SKIP_ALWAYS}" | grep "${TEST_NO}" | tr '[:lower:]' '[:upper:]')
2014-08-26 17:33:55 +02:00
if [ ! "${FIND}" = "" ]; then SKIPTEST=1; SKIPREASON="Skipped by configuration"; fi
fi
2016-04-19 12:37:00 +02:00
# Check if this test is on the list to skip
if [ ${SKIPTEST} -eq 0 ]; then
2017-03-06 08:41:21 +01:00
VALUE=$(echo ${TEST_NO} | tr '[:lower:]' '[:upper:]')
2016-04-19 12:37:00 +02:00
for I in ${SKIP_TESTS}; do
2016-08-13 10:16:15 +02:00
if [ "${I}" = "${VALUE}" ]; then SKIPTEST=1; SKIPREASON="Skipped by profile setting (skip-test)"; fi
2016-04-19 12:37:00 +02:00
done
fi
2015-09-07 17:35:07 +02:00
# Skip if test is not in the list
2014-08-26 17:33:55 +02:00
if [ ${SKIPTEST} -eq 0 -a ! "${TESTS_TO_PERFORM}" = "" ]; then
2017-03-07 20:23:08 +01:00
FIND=$(echo "${TESTS_TO_PERFORM}" | grep "${TEST_NO}")
if [ "${FIND}" = "" ]; then SKIPTEST=1; SKIPREASON="Test not in list of tests to perform"; fi
2014-08-26 17:33:55 +02:00
fi
# Do not run scans which have a higher intensity than what we prefer
if [ ${SKIPTEST} -eq 0 -a "${TEST_WEIGHT}" = "H" -a "${SCAN_TEST_HEAVY}" = "NO" ]; then SKIPTEST=1; SKIPREASON="Test to system intensive for scan mode (H)"; fi
2014-09-08 15:03:22 +02:00
if [ ${SKIPTEST} -eq 0 -a "${TEST_WEIGHT}" = "M" -a "${SCAN_TEST_MEDIUM}" = "NO" ]; then SKIPTEST=1; SKIPREASON="Test to system intensive for scan mode (M)"; fi
2014-08-26 17:33:55 +02:00
2018-01-18 20:26:19 +01:00
# Test if our OS is the same as the requested OS (can be multiple values)
2019-07-16 13:20:30 +02:00
if [ ${SKIPTEST} -eq 0 -a -n "${TEST_NEED_OS}" ]; then
2018-01-18 20:26:19 +01:00
HASMATCH=0
for I in ${TEST_NEED_OS}; do
if [ "${I}" = "${OS}" ]; then HASMATCH=1; fi
done
if [ ${HASMATCH} -eq 0 ]; then
SKIPTEST=1; SKIPREASON="Incorrect guest OS (${TEST_NEED_OS} only)"
if [ ${LOG_INCORRECT_OS} -eq 0 ]; then SKIPLOGTEST=1; fi
2014-08-26 17:33:55 +02:00
fi
fi
2016-07-24 17:22:00 +02:00
# Skip test when it belongs to another category (default is 'all')
2019-07-16 13:20:30 +02:00
if [ ${SKIPTEST} -eq 0 -a -n "${TEST_CATEGORY_TO_CHECK}" -a ! "${TEST_CATEGORY_TO_CHECK}" = "all" -a ! "${TEST_CATEGORY}" = "${TEST_CATEGORY_TO_CHECK}" ]; then
2016-07-24 17:22:00 +02:00
SKIPTEST=1; SKIPREASON="Incorrect category (${TEST_CATEGORY_TO_CHECK} only)"
fi
2014-08-26 17:33:55 +02:00
# Check for correct hardware platform
2019-07-16 13:20:30 +02:00
if [ ${SKIPTEST} -eq 0 -a -n "${TEST_NEED_PLATFORM}" -a ! "${HARDWARE}" = "${TEST_NEED_PLATFORM}" ]; then SKIPTEST=1; SKIPREASON="Incorrect hardware platform"; fi
2014-08-26 17:33:55 +02:00
# Not all prerequisites met, like missing tool
2018-04-23 10:54:44 +02:00
if [ ${SKIPTEST} -eq 0 -a "${PREQS_MET}" = "NO" ]; then SKIPTEST=1; if [ -z "${SKIPREASON}" ]; then SKIPREASON="Prerequisites not met (ie missing tool, other type of Linux distribution)"; fi; fi
2014-08-26 17:33:55 +02:00
2016-11-19 15:38:32 +01:00
# Skip if a test is root only and we are running a non-privileged test
if [ ${SKIPTEST} -eq 0 -a ${ROOT_ONLY} -eq 1 -a ! ${MYID} = "0" ]; then
SKIPTEST=1; SKIPREASON="This test needs root permissions"
SKIPPED_TESTS_ROOTONLY="${SKIPPED_TESTS_ROOTONLY}====${TEST_NO}:space:-:space:${TEST_DESCRIPTION}"
#SkipTest "${TEST_NO}:Test:space:requires:space:root:space:permissions:-:-:"
fi
2014-08-26 17:33:55 +02:00
# Skip test?
if [ ${SKIPTEST} -eq 0 ]; then
# First wait X seconds (depending pause_between_tests)
if [ ${TEST_PAUSE_TIME} -gt 0 ]; then sleep ${TEST_PAUSE_TIME}; fi
# Increase counter for every registered test which is performed
2016-04-28 12:31:38 +02:00
CountTests
2016-05-16 20:56:16 +02:00
if [ ${SKIPLOGTEST} -eq 0 ]; then
LogText "Performing test ID ${TEST_NO} (${TEST_DESCRIPTION})"
if IsVerbose; then Debug "Performing test ID ${TEST_NO} (${TEST_DESCRIPTION})"; fi
fi
2014-08-26 17:33:55 +02:00
TESTS_EXECUTED="${TEST_NO}|${TESTS_EXECUTED}"
2017-04-30 17:59:35 +02:00
else
2016-05-16 20:56:16 +02:00
if [ ${SKIPLOGTEST} -eq 0 ]; then LogText "Skipped test ${TEST_NO} (${TEST_DESCRIPTION})"; fi
2015-12-22 16:02:32 +01:00
if [ ${SKIPLOGTEST} -eq 0 ]; then LogText "Reason to skip: ${SKIPREASON}"; fi
2014-08-26 17:33:55 +02:00
TESTS_SKIPPED="${TEST_NO}|${TESTS_SKIPPED}"
fi
2016-08-13 10:16:15 +02:00
unset SKIPREASON
2019-07-12 14:20:32 +02:00
# Save timestamp for next time the Register function is called
PREVIOUS_TEST="${TEST_NO}"
PREVIOUS_TS="${CURRENT_TS}"
2016-04-25 15:49:00 +02:00
}
2014-08-26 17:33:55 +02:00
2016-07-18 19:58:32 +02:00
################################################################################
# Name : RemoveColors()
2019-08-01 14:59:03 +02:00
# Description : Disabled colors by overriding them (defined in include/consts)
#
# Notes : Can be activated using --no-colors
2016-07-18 19:58:32 +02:00
################################################################################
RemoveColors() {
COLORS=0 # disable most color selections
# Normal color names
CYAN=""
BLUE=""
BROWN=""
DARKGRAY=""
GRAY=""
GREEN=""
LIGHTBLUE=""
MAGENTA=""
PURPLE=""
RED=""
YELLOW=""
WHITE=""
# Colors with background
2016-07-24 13:05:36 +02:00
BG_BLUE=""
2019-07-10 19:36:51 +02:00
BG_WARNING=""
2016-07-24 13:05:36 +02:00
# Semantic names
BAD=""
BOLD=""
HEADER=""
NORMAL=""
NOTICE=""
OK=""
WARNING=""
SECTION=""
2016-07-18 19:58:32 +02:00
}
2016-04-28 12:31:38 +02:00
################################################################################
# Name : RemovePIDFile()
2019-07-10 19:36:51 +02:00
# Description : When defined, remove the file storing the process ID
2019-08-01 14:59:03 +02:00
#
# Parameters : <none>
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
################################################################################
2014-08-26 17:33:55 +02:00
# Remove PID file
2016-04-28 12:31:38 +02:00
RemovePIDFile() {
2014-08-26 17:33:55 +02:00
# Test if PIDFILE is defined, before checking file presence
2019-07-16 13:20:30 +02:00
if [ -n "${PIDFILE}" ]; then
2019-07-10 19:36:51 +02:00
if [ -f "${PIDFILE}" ]; then
rm -f "${PIDFILE}"
2017-03-07 20:23:08 +01:00
LogText "PID file removed (${PIDFILE})"
2017-04-30 17:59:35 +02:00
else
2017-03-07 20:23:08 +01:00
LogText "PID file not found (${PIDFILE})"
fi
2014-08-26 17:33:55 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-01-11 01:04:04 +01:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : RemoveTempFiles()
2019-07-10 19:36:51 +02:00
# Description : When created, delete any temporary file
2016-04-28 12:31:38 +02:00
################################################################################
2016-01-11 01:04:04 +01:00
# Remove any temporary files
2016-04-28 12:31:38 +02:00
RemoveTempFiles() {
2016-01-11 01:04:04 +01:00
if [ ! "${TEMP_FILES}" = "" ]; then
LogText "Temporary files: ${TEMP_FILES}"
# Clean up temp files
for FILE in ${TEMP_FILES}; do
# Temporary files should be in /tmp
2019-09-19 14:05:15 +02:00
TMPFILE=$(echo ${FILE} | grep -E "^/tmp/lynis" | grep -v "\.\.")
2019-07-16 13:20:30 +02:00
if [ -n "${TMPFILE}" ]; then
2019-07-10 19:36:51 +02:00
if [ -f "${TMPFILE}" ]; then
2016-01-11 01:04:04 +01:00
LogText "Action: removing temporary file ${TMPFILE}"
2019-07-10 19:36:51 +02:00
rm -f "${TMPFILE}"
2017-04-30 17:59:35 +02:00
else
2016-01-11 01:04:04 +01:00
LogText "Info: temporary file ${TMPFILE} was already removed"
fi
2017-04-30 17:59:35 +02:00
else
2016-01-11 01:04:04 +01:00
LogText "Found invalid temporary file (${FILE}), not removed. Check your /tmp directory."
fi
done
2017-04-30 17:59:35 +02:00
else
2016-01-11 01:04:04 +01:00
LogText "No temporary files to be deleted"
fi
}
2016-04-28 12:31:38 +02:00
################################################################################
# Name : Report()
2019-07-10 19:36:51 +02:00
# Description : Store data in the report file
2019-08-01 14:59:03 +02:00
#
# Parameters : $1 = data (format: key=value)
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
################################################################################
Report() {
2016-10-14 08:49:00 +02:00
if [ ${CREATE_REPORT_FILE} -eq 1 ]; then echo "$1" >> ${REPORTFILE}; fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-13 16:11:46 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : ReportDetails()
2016-04-13 16:11:46 +02:00
# Description : Adds specific details to the report, in particular when many
# smaller atomic tests are performed. For example sysctl keys,
# and SSH settings.
2016-04-28 12:31:38 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : <multiple fields, see test>
2016-04-28 12:31:38 +02:00
# Returns : <nothing>
2016-04-27 16:09:29 +02:00
# Notes : Need to check for values (strip out semicolons from values)
# Only add fields which are filled in
2016-04-13 16:11:46 +02:00
################################################################################
ReportDetails() {
2016-06-30 11:34:27 +02:00
TEST_DESCRIPTION=""
TEST_FIELD=""
TEST_ID=""
TEST_OTHER=""
TEST_PREFERRED_VALUE=""
TEST_SERVICE=""
TEST_VALUE=""
2016-04-13 16:11:46 +02:00
while [ $# -ge 1 ]; do
2016-04-27 16:09:29 +02:00
2016-04-13 16:11:46 +02:00
case $1 in
--description)
shift
2016-04-27 16:51:12 +02:00
TEST_DESCRIPTION="desc:$1;"
2016-04-13 16:11:46 +02:00
;;
--field)
shift
2016-04-27 16:51:12 +02:00
TEST_FIELD="field:$1;"
2016-04-13 16:11:46 +02:00
;;
--preferredvalue|--preferred-value)
shift
2016-04-27 16:51:12 +02:00
TEST_PREFERRED_VALUE="prefval:$1;"
2016-04-13 16:11:46 +02:00
;;
2016-04-19 09:53:30 +02:00
# Other details
--other)
shift
2016-04-27 16:51:12 +02:00
TEST_OTHER="other:$1;"
2016-04-19 09:55:02 +02:00
;;
2016-04-19 09:53:30 +02:00
--service)
shift
2016-06-30 11:34:27 +02:00
TEST_SERVICE="$1"
2016-04-19 09:53:30 +02:00
;;
2016-04-13 16:11:46 +02:00
--test)
shift
TEST_ID=$1
;;
--value)
shift
2016-04-27 16:51:12 +02:00
TEST_VALUE="value:$1;"
2016-04-13 16:11:46 +02:00
;;
*)
echo "INVALID OPTION (ReportDetails): $1"
ExitFatal
;;
esac
shift # Go to next parameter
done
2016-04-27 16:51:12 +02:00
if [ "${TEST_ID}" = "" ]; then TEST_ID="-"; fi
if [ "${TEST_SERVICE}" = "" ]; then TEST_SERVICE="-"; fi
Report "details[]=${TEST_ID}|${TEST_SERVICE}|${TEST_DESCRIPTION}${TEST_FIELD}${TEST_PREFERRED_VALUE}${TEST_VALUE}${TEST_OTHER}|"
2016-04-13 16:11:46 +02:00
}
2016-04-28 12:31:38 +02:00
################################################################################
# Name : ReportException()
2019-07-10 19:36:51 +02:00
# Description : Store an exceptional event in the report
#
# Parameters : $1 = test ID + colon + 2 numeric characters (TEST-1234:01)
# $2 = string (text)
2019-08-01 14:59:03 +02:00
# Notes : Allow this function with only 1 parameter in strict mode with ${2-Text}
2016-04-28 12:31:38 +02:00
################################################################################
ReportException() {
2019-07-17 23:16:47 +02:00
Report "exception_event[]=$1|${2-NoInfo}|"
LogText "Exception: test has an exceptional event ($1) with text ${2-NoText}"
2019-08-21 14:50:32 +02:00
if [ ${QUIET} -eq 0 ]; then
DisplayException "$1" "$2"
fi
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : ReportManual()
2019-07-10 19:36:51 +02:00
# Description : Add an item to the report that requires manual intervention
#
# Parameters : $1 = string (text)
2016-04-28 12:31:38 +02:00
################################################################################
2014-08-26 17:33:55 +02:00
2016-04-25 10:55:34 +02:00
ReportManual() {
2015-12-22 16:02:32 +01:00
Report "manual_event[]=$1"
LogText "Manual: one or more manual actions are required for further testing of this control/plugin"
2016-04-25 10:55:34 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : ReportSuggestion()
2019-07-10 19:36:51 +02:00
# Description : Log a suggestion to the report file
#
# Parameters : <ID> <Suggestion> <Details> <Solution>
# $1 = Test ID - Lynis ID (use CUST-.... for your own tests)
# $2 = Suggestion - Suggestion text to be displayed
# $3 = Details - Specific item or details
# $4 = Solution - Optional link for additional information:
# * url:https://example.org/how-to-solve-link
# * text:Additional explanation
# * - (dash) for none
2019-08-01 14:59:03 +02:00
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
################################################################################
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
ReportSuggestion() {
2016-05-03 14:57:53 +02:00
TOTAL_SUGGESTIONS=$((TOTAL_SUGGESTIONS + 1))
2016-07-28 11:06:46 +02:00
if [ $# -eq 0 ]; then echo "Not enough arguments provided for function ReportSuggestion"; ExitFatal; fi
if [ $# -ge 1 ]; then TEST="$1"; else TEST="UNKNOWN"; fi
if [ $# -ge 2 ]; then MESSAGE="$2"; else MESSAGE="UNKNOWN"; fi
if [ $# -ge 3 ]; then DETAILS="$3"; else DETAILS="-"; fi
if [ $# -ge 4 ]; then SOLUTION="$4"; else SOLUTION="-"; fi
if [ $# -ge 5 ]; then echo "Too many arguments for function ReportSuggestion"; ExitFatal; fi
2015-12-22 16:02:32 +01:00
Report "suggestion[]=${TEST}|${MESSAGE}|${DETAILS}|${SOLUTION}|"
2016-07-28 11:06:46 +02:00
LogText "Suggestion: ${MESSAGE} [test:${TEST}] [details:${DETAILS}] [solution:${SOLUTION}]"
2016-04-28 12:31:38 +02:00
}
################################################################################
# Name : ReportWarning()
2019-07-10 19:36:51 +02:00
# Description : Log a warning to the report file
2019-08-01 14:59:03 +02:00
#
# Parameters : $1 = test ID
# $2 = message (optional)
# $3 = details (optional)
# $4 = possible solution (optional)
# Returns : <nothing>
2016-04-28 12:31:38 +02:00
################################################################################
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
ReportWarning() {
2016-05-03 14:57:53 +02:00
TOTAL_WARNINGS=$((TOTAL_WARNINGS + 1))
2019-08-01 14:59:03 +02:00
# Old style used L/M/H level as second parameter. This is deprecated as of 3.x
2014-08-26 17:33:55 +02:00
if [ "$2" = "L" -o "$2" = "M" -o "$2" = "H" ]; then
2019-08-01 14:59:03 +02:00
ExitFatal "Deprecated usage of ReportWarning() function"
2016-07-28 11:06:46 +02:00
else
2015-09-24 20:26:32 +02:00
# New style warning format:
# <ID> <Warning> <Details> <Solution>
#
# <ID> Lynis ID (use CUST-.... for your own tests)
# <Warning> Warning text to be displayed
# <Details> Specific item or details
# <Solution> Optional link for additional information:
# * url:http://site/link
# * text:Additional explanation
# * - for none
2016-07-28 11:06:46 +02:00
if [ $# -eq 0 ]; then echo "Not enough arguments provided for function ReportWarning"; ExitFatal; fi
if [ $# -ge 1 ]; then TEST="$1"; else TEST="UNKNOWN"; fi
if [ $# -ge 2 ]; then MESSAGE="$2"; else MESSAGE="UNKNOWN"; fi
if [ $# -ge 3 ]; then DETAILS="$3"; else DETAILS="-"; fi
if [ $# -ge 4 ]; then SOLUTION="$4"; else SOLUTION="-"; fi
if [ $# -ge 5 ]; then echo "Too many arguments for function ReportWarning"; ExitFatal; fi
2014-08-26 17:33:55 +02:00
fi
2015-12-22 16:02:32 +01:00
Report "warning[]=${TEST}|${MESSAGE}|${DETAILS}|${SOLUTION}|"
LogText "Warning: ${MESSAGE} [test:${TEST}] [details:${DETAILS}] [solution:${SOLUTION}]"
2016-04-28 12:31:38 +02:00
}
2015-09-24 21:40:54 +02:00
2014-08-26 17:33:55 +02:00
2019-06-29 19:34:12 +02:00
################################################################################
# Name : SafeInput()
# Description : Test provided string to see if it contains unwanted characters
#
# Input : string + optional class (parameter 2)
2019-08-01 14:59:03 +02:00
# Returns : exit code (0 = input considered to be safe, 1 = validation failed)
2019-06-29 19:34:12 +02:00
################################################################################
SafeInput() {
exitcode=1
# By default remove only control characters
if [ $# -eq 1 ]; then
input="$1"
cleaned=$(echo ${input} | tr -d '[:cntrl:]')
# If know what to test against, then see if input matches the specified class
elif [ $# -eq 2 ]; then
input="$1"
testchars="$2"
cleaned=$(echo $1 | tr -cd "${testchars}")
else
ExitFatal "No argument or too many arguments provided to SafeInput()"
fi
if [ "${cleaned}" = "${input}" ]; then
exitcode=0
fi
return ${exitcode}
}
2019-07-12 13:05:43 +02:00
################################################################################
# Name : SafeFile()
# Description : Check if a file is safe to use
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = file name
# Returns : exit code (0 = OK, 1 = issue)
2019-07-12 13:05:43 +02:00
################################################################################
SafeFile() {
unsafe=0
if [ $# -ne 1 ]; then
ExitFatal "No argument or too many arguments provided to SafeFile()"
else
FILE="$1"
# Generic checks
if [ -g "${FILE}" ]; then
LogText "Security alert: file has setgid attribute"
unsafe=1
# sticky bit
elif [ -k "${FILE}" ]; then
LogText "Security alert: file has sticky bit"
unsafe=1
# symbolic link
elif [ -L "${FILE}" ]; then
LogText "Security alert: file is a symbolic link"
unsafe=1
elif [ -f "${FILE}" ]; then
LogText "Security check: file is normal"
else
unsafe=1
fi
# Perform additional checks based on privilege level
if [ ${PRIVILEGED} -eq 0 ]; then
# File is not owned by active user, but still able to write
if [ ! -O "${FILE}" -a -w "${FILE}" ]; then
unsafe=1
LogText "Security alert: file is not owned by active user, but can write to it"
fi
fi
# Check file permissions
if ! SafePerms "${FILE}"; then
unsafe=1
fi
fi
return ${unsafe}
}
2019-06-29 19:34:12 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : SafePerms()
2019-07-10 19:36:51 +02:00
# Description : Check if a file has safe permissions to be used
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = file name
# $2 = type of file (optional)
2019-07-03 15:07:46 +02:00
# Returns : 0 (file permissions OK) or break
2016-04-28 12:31:38 +02:00
################################################################################
SafePerms() {
2019-07-03 15:07:46 +02:00
exitcode=1
IS_PARAMETERS=0
IS_PROFILE=0
if [ ${IGNORE_FILE_PERMISSION_ISSUES} -eq 0 ]; then
2016-05-02 15:45:27 +02:00
PERMS_OK=0
LogText "Checking permissions of $1"
2019-07-03 15:07:46 +02:00
if [ $# -gt 0 ]; then
if [ $# -eq 2 ]; then
case "$2" in
"parameters")
IS_PARAMETERS=1
;;
"profile")
IS_PROFILE=1
;;
esac
else
FIND=$(echo $1 | grep "/parameters")
if [ $? -eq 0 ]; then IS_PARAMETERS=1; fi
fi
2016-05-02 15:45:27 +02:00
# Check file permissions
2019-07-03 15:07:46 +02:00
if [ ! -f "$1" ]; then
2019-07-14 11:49:14 +02:00
LogText "Fatal error: file $1 does not exist."
ExitFatal "Fatal error: file $1 does not exist"
2019-07-03 15:07:46 +02:00
else
PERMS=$(ls -l $1)
# Owner permissions
OWNER=$(echo ${PERMS} | awk -F" " '{ print $3 }')
OWNERID=$(ls -n $1 | awk -F" " '{ print $3 }')
if [ ${PENTESTINGMODE} -eq 0 -a ${IS_PARAMETERS} -eq 0 ]; then
if [ ! "${OWNER}" = "root" -a ! "${OWNERID}" = "0" ]; then
echo "Fatal error: file $1 should be owned by user 'root' when running it as root (found: ${OWNER})."
ExitFatal
fi
fi
# Group permissions
GROUP=$(echo ${PERMS} | awk -F" " '{ print $4 }')
GROUPID=$(ls -n $1 | awk -F" " '{ print $4 }')
if [ ${PENTESTINGMODE} -eq 0 -a ${IS_PARAMETERS} -eq 0 ]; then
if [ ! "${GROUP}" = "root" -a ! "${GROUP}" = "wheel" -a ! "${GROUPID}" = "0" ]; then
echo "Fatal error: group owner of directory $1 should be owned by root user, wheel or similar (found: ${GROUP})."
ExitFatal
fi
fi
# Owner permissions
OWNER_PERMS=$(echo ${PERMS} | cut -c2-4)
if [ ! "${OWNER_PERMS}" = "rw-" -a ! "${OWNER_PERMS}" = "r--" ]; then
2019-07-14 11:49:14 +02:00
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'owner' should be read-write, or read. Change with: chmod u=rw $1"
2019-07-03 15:07:46 +02:00
ExitFatal
fi
2019-07-14 11:49:14 +02:00
# Group permissions
# TODO - harden this even more by setting default to read-only for group (like 'other')
2019-07-03 15:07:46 +02:00
GROUP_PERMS=$(echo ${PERMS} | cut -c5-7)
if [ ! "${GROUP_PERMS}" = "rw-" -a ! "${GROUP_PERMS}" = "r--" -a ! "${GROUP_PERMS}" = "---" ]; then
2019-07-14 11:49:14 +02:00
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'group' should be read-write, read, or none. Change with: chmod g=r $1"
2019-07-03 15:07:46 +02:00
ExitFatal
fi
# Other permissions
OTHER_PERMS=$(echo ${PERMS} | cut -c8-10)
if [ ! "${OTHER_PERMS}" = "---" -a ! "${OTHER_PERMS}" = "r--" ]; then
2019-07-14 11:49:14 +02:00
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'other' should be denied or read-only. Change with: chmod o=r $1"
2019-07-03 15:07:46 +02:00
ExitFatal
fi
# Set PERMS_OK to 1 if no fatal errors occurred
PERMS_OK=1
LogText "File permissions are OK"
exitcode=0
fi
2017-04-30 17:59:35 +02:00
else
2016-05-02 15:45:27 +02:00
ReportException "SafePerms()" "Invalid number of arguments for function"
fi
2017-04-30 17:59:35 +02:00
else
2016-05-02 15:45:27 +02:00
PERMS_OK=1
2019-07-03 15:07:46 +02:00
exitcode=0
2014-08-26 17:33:55 +02:00
fi
2019-07-03 15:07:46 +02:00
return ${exitcode}
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
################################################################################
# Name : SearchItem()
# Description : Search if a specific string exists in in a file
2016-04-28 12:31:38 +02:00
#
2019-07-10 19:36:51 +02:00
# Parameters : $1 = search key (string)
# $2 = file (string)
# $3 = optional arguments:
# --sensitive - don't store results in log
2016-08-11 19:52:15 +02:00
# Returns : True (0) or False (1)
2014-08-26 17:33:55 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
SearchItem() {
2016-08-11 19:52:15 +02:00
PERFORM_SCAN=0
MASK_LOG=0
2016-08-11 18:46:17 +02:00
RETVAL=1
2016-08-11 19:52:15 +02:00
if [ $# -lt 2 ]; then
ExitFatal "Not enough arguments for function SearchItem()"
elif [ $# -ge 2 ]; then
FILE=$2
STRING=$1
PERFORM_SCAN=1
fi
# Parse any additional arguments
if [ $# -gt 2 ]; then
shift; shift # Skip the first two (string and file)
while [ $# -ge 1 ]; do
case $1 in
"--sensitive") MASK_LOG=1 ;;
esac
shift # Go to next parameter
done
fi
if [ ${PERFORM_SCAN} -eq 1 ]; then
2014-08-26 17:33:55 +02:00
# Don't search in /dev/null, it's too empty there
2016-08-11 19:52:15 +02:00
if [ -f ${FILE} ]; then
2014-08-26 17:33:55 +02:00
# Check if we can find the main type (with or without brackets)
2016-08-11 19:52:15 +02:00
LogText "Test: search string ${STRING} in file ${FILE}"
2019-09-19 14:05:15 +02:00
FIND=$(grep -E "${STRING}" ${FILE})
2019-07-16 13:20:30 +02:00
if [ -n "${FIND}" ]; then
2016-08-11 19:52:15 +02:00
LogText "Result: found search string '${STRING}'"
if [ ${MASK_LOG} -eq 0 ]; then LogText "Full string returned: ${FIND}"; fi
2016-08-11 18:46:17 +02:00
RETVAL=0
2017-04-30 17:59:35 +02:00
else
2016-08-11 19:52:15 +02:00
LogText "Result: search search string '${STRING}' NOT found"
2016-08-11 18:46:17 +02:00
RETVAL=1
2014-08-26 17:33:55 +02:00
fi
2017-04-30 17:59:35 +02:00
else
2016-08-11 19:52:15 +02:00
LogText "Skipping search, file (${FILE}) does not exist"
ReportException "${TEST_NO}" "Test is trying to search for a string in nonexistent file"
2014-08-26 17:33:55 +02:00
fi
2016-08-11 18:46:17 +02:00
else
2016-08-11 19:52:15 +02:00
ReportException "${TEST_NO}" "Search test is skipped, which is unexpected"
2016-08-11 18:46:17 +02:00
fi
return ${RETVAL}
2016-04-28 12:31:38 +02:00
}
2014-08-26 17:33:55 +02:00
2014-09-12 15:33:28 +02:00
2015-10-01 13:16:27 +02:00
################################################################################
# Name : ShowComplianceFinding()
# Description : Display a section of a compliance standard which is not fulfilled
2016-04-28 12:31:38 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : <several parameters, see test>
2016-04-28 12:31:38 +02:00
# Returns : <nothing>
2015-10-01 13:16:27 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
ShowComplianceFinding() {
2015-10-01 13:16:27 +02:00
REASON=""
STANDARD_NAME=""
STANDARD_VERSION=""
STANDARD_SECTION=""
STANDARD_SECTION_TITLE=""
ACTUAL_VALUE=""
EXPECTED_VALUE=""
while [ $# -ge 1 ]; do
case $1 in
--standard)
shift
STANDARD_NAME=$1
;;
--version)
shift
STANDARD_VERSION=$1
;;
--section)
shift
STANDARD_SECTION=$1
;;
--section-title)
shift
STANDARD_SECTION_TITLE=$1
;;
--reason)
shift
REASON=$1
;;
--actual)
shift
ACTUAL_VALUE=$1
;;
--expected)
shift
EXPECTED_VALUE=$1
;;
*)
echo "INVALID OPTION (ShowComplianceFinding): $1"
exit 1
;;
esac
# Go to next parameter
shift
done
# Should we show this non-compliance on screen?
SHOW=0
case ${STANDARD_NAME} in
2015-10-01 22:40:29 +02:00
cis)
if [ ${COMPLIANCE_ENABLE_CIS} -eq 1 ]; then SHOW=1; fi
STANDARD_FRIENDLY_NAME="CIS"
;;
2015-10-01 13:16:27 +02:00
hipaa)
2015-10-01 22:40:29 +02:00
if [ ${COMPLIANCE_ENABLE_HIPAA} -eq 1 ]; then SHOW=1; fi
STANDARD_FRIENDLY_NAME="HIPAA"
2015-10-01 13:16:27 +02:00
;;
iso27001)
2015-10-01 22:40:29 +02:00
if [ ${COMPLIANCE_ENABLE_ISO27001} -eq 1 ]; then SHOW=1; fi
STANDARD_FRIENDLY_NAME="ISO27001"
2015-10-01 13:16:27 +02:00
;;
pci-dss)
2015-10-01 22:40:29 +02:00
if [ ${COMPLIANCE_ENABLE_PCI_DSS} -eq 1 ]; then SHOW=1; fi
STANDARD_FRIENDLY_NAME="PCI DSS"
2015-10-01 13:16:27 +02:00
;;
esac
2015-10-01 22:40:29 +02:00
# Only display if standard is enabled in the profile and mark system as non-compliant
2015-10-01 13:16:27 +02:00
if [ ${SHOW} -eq 1 ]; then
2015-10-01 22:40:29 +02:00
COMPLIANCE_FINDINGS_FOUND=1
DisplayManual " [${WHITE}${STANDARD_FRIENDLY_NAME} ${STANDARD_VERSION}${NORMAL}] - ${CYAN}Section ${STANDARD_SECTION}${NORMAL} - ${WHITE}${STANDARD_SECTION_TITLE}${NORMAL}"
DisplayManual " - Details: ${REASON}"
DisplayManual " - Configuration: ${RED}${ACTUAL_VALUE}${NORMAL} / ${EXPECTED_VALUE}"
DisplayManual ""
2015-10-01 13:16:27 +02:00
fi
2016-04-28 12:31:38 +02:00
}
2015-10-01 13:16:27 +02:00
2014-09-12 15:33:28 +02:00
################################################################################
# Name : ShowSymlinkPath()
# Description : Check if we can find the path behind a symlink
2016-04-28 12:31:38 +02:00
#
2019-08-01 14:59:03 +02:00
# Parameters : $1 = file (string)
2016-04-28 12:31:38 +02:00
# Returns : FOUNDPATH (0 not found, 1 found path), SYMLINK (new path)
2014-09-12 15:33:28 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
ShowSymlinkPath() {
2016-08-11 19:03:01 +02:00
if [ $# -eq 0 ]; then ExitFatal "Function ShowSymlinkPath() called without a file name"; fi
2014-09-12 15:33:28 +02:00
sFILE=$1
FOUNDPATH=0
2015-04-22 00:57:58 +02:00
SYMLINK_USE_PYTHON=0
SYMLINK_USE_READLINK=0
2016-08-11 19:03:01 +02:00
LogText "Action: checking symlink for file ${sFILE}"
2014-09-12 15:33:28 +02:00
# Check for symlink
if [ -L ${sFILE} ]; then
2015-04-22 00:57:58 +02:00
2017-03-07 20:23:08 +01:00
# macOS does not know -f option, nor do some others
if [ "${OS}" = "macOS" ]; then
# If a Python binary is found, use the one in path
if [ ${BINARY_SCAN_FINISHED} -eq 0 -a "${PYTHONBINARY}" = "" ]; 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
FIND=$(which python 2> /dev/null | grep -v "no [^ ]* in ")
2017-03-07 20:23:08 +01:00
if [ ! "${FIND}" = "" ]; then LogText "Setting temporary pythonbinary variable"; PYTHONBINARY="${FIND}"; fi
fi
2016-08-11 19:03:01 +02:00
2017-03-07 20:23:08 +01:00
if [ ! "${PYTHONBINARY}" = "" ]; then
SYMLINK_USE_PYTHON=1
LogText "Note: using Python to determine symlinks"
tFILE=$(python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" $1)
fi
else
if [ ${BINARY_SCAN_FINISHED} -eq 0 -a "${READLINKBINARY}" = "" ]; 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
FIND=$(which readlink 2> /dev/null | grep -v "no [^ ]* in ")
2017-03-07 20:23:08 +01:00
if [ ! "${FIND}" = "" ]; then LogText "Setting temporary readlinkbinary variable"; READLINKBINARY="${FIND}"; fi
fi
2015-04-22 00:57:58 +02:00
2017-03-07 20:23:08 +01:00
if [ ! "${READLINKBINARY}" = "" ]; then
SYMLINK_USE_READLINK=1
LogText "Note: Using real readlink binary to determine symlink on ${sFILE}"
tFILE=$(${READLINKBINARY} -f ${sFILE})
LogText "Result: readlink shows ${tFILE} as output"
2015-04-22 00:57:58 +02:00
fi
2017-03-07 20:23:08 +01:00
fi
# Check if we can find the file now
if [ "${tFILE}" = "" ]; then
LogText "Result: command did not return any value"
elif [ -f ${tFILE} ]; then
sFILE="${tFILE}"
LogText "Result: symlink found, pointing to file ${sFILE}"
FOUNDPATH=1
elif [ -b ${tFILE} ]; then
sFILE="${tFILE}"
LogText "Result: symlink found, pointing to block device ${sFILE}"
FOUNDPATH=1
elif [ -c ${tFILE} ]; then
sFILE="${tFILE}"
LogText "Result: symlink found, pointing to character device ${sFILE}"
FOUNDPATH=1
elif [ -d ${tFILE} ]; then
sFILE="${tFILE}"
LogText "Result: symlink found, pointing to directory ${sFILE}"
FOUNDPATH=1
2017-04-30 17:59:35 +02:00
else
2017-03-07 20:23:08 +01:00
# Check the full path of the symlink, strip the filename, copy the path and linked filename together
tDIR=$(echo ${sFILE} | awk '{match($1, "^.*/"); print substr($1, 1, RLENGTH-1)}')
tFILE="${tDIR}/${tFILE}"
if [ -L ${tFILE} ]; then
LogText "Result: this symlink links to another symlink"
# Ensure that we use a second try with the right tool as well
if [ ${SYMLINK_USE_PYTHON} -eq 1 ]; then
tFILE=$(python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" ${tFILE})
elif [ ${SYMLINK_USE_READLINK} -eq 1 ]; then
tFILE=$(${READLINKBINARY} -f ${tFILE})
fi
# Check if we now have a normal file
if [ -f ${tFILE} ]; then
2014-09-12 15:33:28 +02:00
sFILE="${tFILE}"
2017-03-07 20:23:08 +01:00
LogText "Result: symlink finally found, seems to be file ${sFILE}"
2014-09-12 15:33:28 +02:00
FOUNDPATH=1
2014-10-03 19:16:13 +02:00
elif [ -d ${tFILE} ]; then
2014-09-12 15:33:28 +02:00
sFILE="${tFILE}"
2017-03-07 20:23:08 +01:00
LogText "Result: symlink finally found, seems to be directory ${sFILE}"
2014-09-12 15:33:28 +02:00
FOUNDPATH=1
2014-10-03 19:16:13 +02:00
else
2017-03-07 20:23:08 +01:00
LogText "Result: could not find file ${tFILE}, most likely too complicated symlink or too often linked"
2014-09-12 15:33:28 +02:00
fi
2017-03-07 20:23:08 +01:00
elif [ -f ${tFILE} ]; then
sFILE="${tFILE}"
LogText "Result: symlink found, seems to be file ${sFILE}"
FOUNDPATH=1
elif [ -d ${tFILE} ]; then
sFILE="${tFILE}"
LogText "Result: symlink found, seems to be directory ${sFILE}"
FOUNDPATH=1
else
LogText "Result: file ${tFILE} in ${tDIR} not found"
2014-09-12 15:33:28 +02:00
fi
2017-03-07 20:23:08 +01:00
fi
2017-04-30 17:59:35 +02:00
else
2016-08-11 19:03:01 +02:00
LogText "Result: file ${sFILE} is not a symlink"
2014-09-12 15:33:28 +02:00
fi
# Now check if our new location is actually a file or directory destination
if [ -L ${sFILE} ]; then
2015-12-22 16:02:32 +01:00
LogText "Result: unable to determine symlink, or location ${sFILE} is just another symlink"
2014-09-12 15:33:28 +02:00
FOUNDPATH=0
fi
2014-10-03 19:16:13 +02:00
if [ ${FOUNDPATH} -eq 1 ]; then
SYMLINK="${sFILE}"
2017-04-30 17:59:35 +02:00
else
2014-10-03 19:16:13 +02:00
SYMLINK=""
fi
2016-04-28 12:31:38 +02:00
}
2014-09-12 15:33:28 +02:00
2016-04-19 12:37:00 +02:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : SkipAtomicTest()
2016-04-19 12:37:00 +02:00
# Description : Test if an atomic test should be skipped
2016-04-28 12:31:38 +02:00
#
# Input : String (particular test)
# Returns : 0 (skip test) or 1 (do not skip test)
# Usage : if SkipAtomicTest "ssh-7408:port"; then echo "Skip this atomic test"; fi
2016-04-19 12:37:00 +02:00
################################################################################
SkipAtomicTest() {
2016-05-09 14:20:16 +02:00
RETVAL=255
2016-04-19 12:37:00 +02:00
if [ $# -eq 1 ]; then
2016-05-09 14:20:16 +02:00
STRING=""
2016-04-19 12:37:00 +02:00
RETVAL=1
# Check if this test is on the list to skip
2018-01-11 10:37:56 +01:00
for item in ${SKIP_TESTS}; do
2017-03-06 08:41:21 +01:00
STRING=$(echo $1 | tr '[:lower:]' '[:upper:]')
2018-01-11 10:37:56 +01:00
if [ "${item}" = "${STRING}" ]; then RETVAL=0; LogText "Atomic test ($1) skipped by configuration (skip-test)"; fi
2016-04-19 12:37:00 +02:00
done
2017-04-30 17:59:35 +02:00
else
2016-04-28 12:31:38 +02:00
ReportException "SkipAtomicTest()" "Function called without right number of arguments (1)"
2016-04-19 12:37:00 +02:00
fi
return $RETVAL
}
2019-11-18 10:19:43 +01:00
################################################################################
# Name : Status()
# Description : Reports back the status of tool
#
# Returns : text to screen
# Notes : kill --signal USR1 <PID> or pkill --signal USR1 lynis
################################################################################
Status() {
echo ""
echo "Date / time : $(date "+%Y-%m-%d %H:%M:%S")"
echo "Active test : ${TEST_NO:-NONE}"
echo ""
}
2016-08-16 08:11:51 +02:00
################################################################################
# Name : StoreNginxSettings()
# Description : Store parsed settings from nginx (by ParseNginx)
# Input : multiple options
# Returns : <nothing>
################################################################################
StoreNginxSettings() {
CONFIG_DEPTH=0; CONFIG_FILE=""; CONFIG_SETTING=""; CONFIG_TREE=""; CONFIG_VALUE=""
while [ $# -ge 1 ]; do
case $1 in
--config)
shift
CONFIG_FILE=$1
;;
--depth)
shift
CONFIG_DEPTH=$1
;;
# none | events | server | unknown
--tree)
shift
CONFIG_TREE=$1
case ${CONFIG_TREE} in
"/") CONFIG_COUNTER=0 ;;
"/events") CONFIG_COUNTER=${NGINX_EVENTS_COUNTER=0} ;;
"/http") CONFIG_COUNTER=${NGINX_HTTP_COUNTER=0} ;;
"/server") CONFIG_COUNTER=${NGINX_SERVER_COUNTER=0} ;;
"/server/location") CONFIG_COUNTER=${NGINX_LOCATION_COUNTER=0} ;;
*)
Debug "Unknown configuration tree of nginx ${CONFIG_TREE}"
;;
esac
;;
--setting)
shift
CONFIG_SETTING=$1
;;
--value)
shift
CONFIG_VALUE=$1
;;
*)
echo "INVALID OPTION (StoreNginxSettings): $1 $2"
#ExitFatal
;;
esac
# Go to next parameter
shift
done
if [ -z "${CONFIG_DEPTH}" ]; then CONFIG_DEPTH="0"; fi
if [ -z "${CONFIG_SETTING}" ]; then CONFIG_SETTING="NA"; fi
if [ -z "${CONFIG_TREE}" ]; then CONFIG_TREE="/"; fi
if [ -z "${CONFIG_VALUE}" ]; then CONFIG_VALUE="NA"; fi
Report "nginx_config[]=|file=${CONFIG_FILE}|depth=${CONFIG_DEPTH}|tree=${CONFIG_TREE}|number=${CONFIG_COUNTER}|setting=${CONFIG_SETTING}|value=${CONFIG_VALUE}|"
}
2016-01-01 14:56:09 +01:00
################################################################################
2016-04-28 12:31:38 +02:00
# Name : TestValue()
2016-01-01 14:56:09 +01:00
# Description : Test if a value is good/bad (e.g. according to best practices)
2016-04-28 12:31:38 +02:00
#
# Input : --function <value> --value <value> --search <value>
2016-01-01 14:56:09 +01:00
# Returns : 0 (True) or 1 (False)
# Usage : if TestValue --function contains --value "Full Text" --search "Text"; then echo "Found!"; fi
################################################################################
2016-04-28 12:31:38 +02:00
TestValue() {
2016-05-09 14:20:16 +02:00
RETVAL=255
FIND=""
VALUE=""
RESULT=""
SEARCH=""
CMP1=""; CMP2=""
2016-01-01 14:56:09 +01:00
while [ $# -ge 1 ]; do
case $1 in
--function)
shift
2016-05-09 14:20:16 +02:00
FUNCTION=$1
2016-01-01 14:56:09 +01:00
;;
--value)
shift
VALUE=$1
;;
--search)
shift
SEARCH=$1
;;
*)
echo "INVALID OPTION USED (TestValue): $1"
exit 1
;;
esac
# Go to next parameter
shift
done
if [ "${VALUE}" = "" ]; then echo "No value provided to function (TestValue)"; fi
# Apply the related function
case ${FUNCTION} in
"contains")
2019-09-19 14:05:15 +02:00
FIND=$(echo ${VALUE} | grep -E "${SEARCH}")
2016-05-04 21:38:42 +02:00
if [ "${FIND}" = "" ]; then RETVAL=1; else RETVAL=0; fi
2016-01-01 14:56:09 +01:00
;;
#"gt" | "greater-than") COLOR=$GREEN ;;
2016-05-04 21:38:42 +02:00
"equals")
2017-03-06 08:41:21 +01:00
CMP1=$(echo ${SEARCH} | tr '[:upper:]' '[:lower:'])
CMP2=$(echo ${VALUE} | tr '[:upper:]' '[:lower:'])
2016-05-04 21:38:42 +02:00
if [ "${CMP1}" = "${CMP2}" ]; then RETVAL=0; else RETVAL=1; fi
;;
2016-01-01 14:56:09 +01:00
#"not-equal") COLOR=$WHITE ;;
#"lt" | "less-than") COLOR=$YELLOW ;;
*) echo "INVALID OPTION USED (TestValue, parameter of function: $1)"; exit 1 ;;
esac
2016-05-04 21:38:42 +02:00
if [ "${RETVAL}" -lt 2 ]; then
2016-01-01 14:56:09 +01:00
return ${RESULT}
2017-04-30 17:59:35 +02:00
else
2016-05-04 21:38:42 +02:00
Fatal "ERROR: No result returned from function (TestValue). Incorrect usage?"
#ExitFatal
2016-01-01 14:56:09 +01:00
fi
2016-04-28 12:31:38 +02:00
}
################################################################################
# Name : ViewCategories()
# Description : Show all available categories
#
# Input : <nothing>
# Returns : <nothing>
# Usage : ViewCategories
################################################################################
2016-01-01 14:56:09 +01:00
2016-04-28 12:31:38 +02:00
ViewCategories() {
2016-07-24 17:22:00 +02:00
for CATEGORY in ${TEST_AVAILABLE_CATEGORIES}; do echo "${CATEGORY}"; done
ExitClean
}
################################################################################
# Name : ViewGroups()
# Description : Show what group of tests are available
#
# Input : <nothing>
# Returns : <nothing>
# Usage : ViewGroups
################################################################################
ViewGroups() {
2019-07-16 13:20:30 +02:00
if [ -n "${INCLUDEDIR}" ]; then
2017-03-06 08:41:21 +01:00
for I in $(ls ${INCLUDEDIR}/tests_* | xargs -n 1 basename | sed 's/tests_//' | grep -v "custom.template"); do
2016-07-13 11:12:31 +02:00
echo "${I}"
2014-08-26 17:33:55 +02:00
done
fi
2016-07-13 11:12:31 +02:00
ExitClean
2016-04-27 16:14:22 +02:00
}
2014-08-26 17:33:55 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
# Name : WaitForKeyPress()
# Description : Wait for the user to press [ENTER], unless quickmode is set
#
# Input : <nothing>
# Returns : <nothing>
# Usage : WaitForKeyPress
################################################################################
WaitForKeyPress() {
if [ ${QUICKMODE} -eq 0 ]; then
2017-03-07 20:23:08 +01:00
echo ""; echo "[ Press [ENTER] to continue, or [CTRL]+C to stop ]"
2019-09-17 14:04:30 +02:00
read -r void
2015-12-22 16:02:32 +01:00
fi
2016-04-27 16:14:22 +02:00
}
2014-08-26 17:33:55 +02:00
2015-04-22 00:57:58 +02:00
2016-04-28 12:31:38 +02:00
################################################################################
#
# Legacy functions - Do not use!
#
################################################################################
# For compatibility reasons they are listed here, but will be phased out in
2019-07-12 13:13:39 +02:00
# steps. If they still get used, they will trigger errors on screen.
2016-04-28 12:31:38 +02:00
################################################################################
2019-08-01 14:59:03 +02:00
counttests() {
DisplayWarning "Deprecated function used (counttests)"
if IsDeveloperMode; then Debug "Warning: old counttests function is used. Please replace any reference with CountTests."; fi
CountTests
}
logtext() {
DisplayWarning "Deprecated function used (logtext)"
if IsDeveloperMode; then Debug "Warning: old logtext function is used. Please replace any reference with LogText."; fi
LogText "$1"
}
logtextbreak() {
DisplayWarning "Deprecated function used (logtextbreak)"
if IsDeveloperMode; then Debug "Warning: old logtextbreak function is used. Please replace any reference with LogTextBreak."; fi
LogTextBreak "$1"
}
report() {
DisplayWarning "Deprecated function used (report)"
if IsDeveloperMode; then Debug "Warning: old report function is used. Please replace any reference with Report."; fi
Report "$1"
}
wait_for_keypress() {
DisplayWarning "Deprecated function used (wait_for_keypress)"
if IsDeveloperMode; then Debug "Warning: old wait_for_keypress function is used. Please replace any reference with WaitForKeyPress."; fi
WaitForKeyPress
}
ShowResult() {
DisplayWarning "Deprecated function used (ShowResult)"
if IsDeveloperMode; then Debug "Warning: old ShowResult() function is used. Please replace any reference with WaitForKeyPress."; fi
}
2016-04-28 12:31:38 +02:00
2014-08-26 17:33:55 +02:00
#================================================================================
2014-12-03 23:43:48 +01:00
# Lynis is part of Lynis Enterprise and released under GPLv3 license
2020-03-20 14:50:25 +01:00
# Copyright 2007-2020 - Michael Boelen, CISOfy - https://cisofy.com