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.
This commit is contained in:
hlein 2017-03-08 09:24:24 -07:00 committed by Michael Boelen
parent e054e9757c
commit 62d9a18861
13 changed files with 71 additions and 35 deletions

View File

@ -151,7 +151,11 @@
else
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)
sed -i -e '/^'"${SETTING}"';/d' ${SETTINGS_FILE}
CreateTempFile
TEMP_SETTINGS_FILE="${TEMP_FILE}"
cat ${SETTINGS_FILE} > ${TEMP_SETTINGS_FILE}
sed -e '/^'"${SETTING}"';/d' ${TEMP_SETTINGS_FILE} > ${SETTINGS_FILE}
rm ${TEMP_SETTINGS_FILE}
echo "${SETTING};${VALUE};${DESCRIPTION};" >> ${SETTINGS_FILE}
fi
else
@ -250,16 +254,16 @@
PROGRAM_LV="0000000000"; DB_MALWARE_LV="0000000000"; DB_FILEPERMS_LV="0000000000"
if [ ${RUN_UPDATE_CHECK} -eq 1 ]; then
LYNIS_LV_RECORD="lynis-latest-version.cisofy.com."
FIND=$(which dig 2> /dev/null)
FIND=$(which dig 2> /dev/null | grep -v "no [^ ]* in")
if [ ! -z "${FIND}" ]; then
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
FIND=$(which host 2> /dev/null)
FIND=$(which host 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! -z "${FIND}" ]; then
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]$")
if [ "${PROGRAM_LV}" = "" ]; then PROGRAM_LV=0; fi
else
FIND=$(which drill 2> /dev/null)
FIND=$(which drill 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! -z "${FIND}" ]; then
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
@ -778,14 +782,24 @@
# Avoid some hashes (empty, only zeros)
BLACKLISTED_HASHES="6ef1338f520d075957424741d7ed35ab5966ae97 adc83b19e793491b1c6ea0fd8b46cd9f32e592fc"
# Check which utilities we can use (e.g. lynis show hostids). Normally these are detected during binaries collecting.
if [ "${SHA1SUMBINARY}" = "" ]; then SHA1SUMBINARY=$(which sha1sum 2> /dev/null); fi
if [ "${SHA1SUMBINARY}" = "" ]; then SHA1SUMBINARY=$(which sha1 2> /dev/null); fi
if [ "${SHA256SUMBINARY}" = "" ]; then SHA256SUMBINARY=$(which sha256sum 2> /dev/null); fi
if [ "${SHA256SUMBINARY}" = "" ]; then SHA256SUMBINARY=$(which sha256 2> /dev/null); fi
if [ "${CSUMBINARY}" = "" ]; then CSUMBINARY=$(which csum 2> /dev/null); fi
if [ "${OPENSSLBINARY}" = "" ]; then OPENSSLBINARY=$(which openssl 2> /dev/null); fi
if [ "${IFCONFIGBINARY}" = "" ]; then IFCONFIGBINARY=$(which ifconfig 2> /dev/null); fi
if [ "${IPBINARY}" = "" ]; then IPBINARY=$(which ip 2> /dev/null); fi
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
if [ ! "${SHA1SUMBINARY}" = "" -o ! "${OPENSSLBINARY}" = "" -o ! "${CSUMBINARY}" = "" ]; then
@ -1033,8 +1047,8 @@
HASH2=$(echo ${STRING_TO_HASH} | ${SHA256SUMBINARY} | awk '{ print $1 }')
HASH_HOSTNAME=$(echo ${HOSTNAME} | ${SHA256SUMBINARY} | awk '{ print $1 }')
elif [ ! "${OPENSSLBINARY}" = "" ]; then
HASH2=$(echo ${STRING_TO_HASH} | ${OPENSSLBINARY} sha -sha256 | awk '{ print $2 }')
HASH_HOSTNAME=$(echo ${HOSTNAME} | ${OPENSSLBINARY} sha -sha256 | awk '{ print $2 }')
HASH2=$(echo ${STRING_TO_HASH} | ${OPENSSLBINARY} dgst -${OPENSSL_HASHTYPE} | awk '{ print $2 }')
HASH_HOSTNAME=$(echo ${HOSTNAME} | ${OPENSSLBINARY} dgst -${OPENSSL_HASHTYPE} | awk '{ print $2 }')
fi
LogText "Hash (hostname): ${HASH_HOSTNAME}"
LogText "Hash (ssh or machineid): ${HASH2}"
@ -1178,7 +1192,7 @@
################################################################################
IsNotebook() {
FIND=$(which laptop-detect 2> /dev/null)
FIND=$(which laptop-detect 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! -z "${FIND}" ]; then
Debug "Testing if we are a notebook"
laptop-detect
@ -2547,7 +2561,7 @@
if [ "${OS}" = "macOS" ]; then
# If a Python binary is found, use the one in path
if [ ${BINARY_SCAN_FINISHED} -eq 0 -a "${PYTHONBINARY}" = "" ]; then
FIND=$(which python 2> /dev/null)
FIND=$(which python 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! "${FIND}" = "" ]; then LogText "Setting temporary pythonbinary variable"; PYTHONBINARY="${FIND}"; fi
fi
@ -2558,7 +2572,7 @@
fi
else
if [ ${BINARY_SCAN_FINISHED} -eq 0 -a "${READLINKBINARY}" = "" ]; then
FIND=$(which readlink 2> /dev/null)
FIND=$(which readlink 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! "${FIND}" = "" ]; then LogText "Setting temporary readlinkbinary variable"; READLINKBINARY="${FIND}"; fi
fi

View File

@ -138,7 +138,7 @@ if [ $# -gt 0 ]; then
CHANGELOG="${FILEPATH}/CHANGELOG.md"
# Check also for gzipped changelog
elif [ -f ${FILEPATH}/changelog.gz ]; then
ZCAT=$(which zcat 2> /dev/null)
ZCAT=$(which zcat 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! -z "${ZCAT}" ]; then
CreateTempFile
CHANGELOG="${TEMP_FILE}"

View File

@ -49,8 +49,8 @@
# Enable screen output again
QUIET=0
SCP_BINARY=$(which scp 2> /dev/null)
SSH_BINARY=$(which ssh 2> /dev/null)
SCP_BINARY=$(which scp 2> /dev/null | grep -v "no [^ ]* in ")
SSH_BINARY=$(which ssh 2> /dev/null | grep -v "no [^ ]* in ")
if [ "${SCP_BINARY}" = "" ]; then echo "Could not find scp binary"; ExitFatal; fi
if [ "${SSH_BINARY}" = "" ]; then echo "Could not find ssh binary"; ExitFatal; fi

View File

@ -38,9 +38,9 @@ SERVER_VERSION=""
PERFORM_UPGRADE=0
QUIET=0
WGET_EXISTS=$(which wget 2> /dev/null)
CURL_EXISTS=$(which curl 2> /dev/null)
FETCH_EXISTS=$(which fetch 2> /dev/null)
WGET_EXISTS=$(which wget 2> /dev/null | grep -v "no [^ ]* in ")
CURL_EXISTS=$(which curl 2> /dev/null | grep -v "no [^ ]* in ")
FETCH_EXISTS=$(which fetch 2> /dev/null | grep -v "no [^ ]* in ")
# Update version
if [ "$1" = "release" ]; then

View File

@ -412,7 +412,7 @@
OS_FULLNAME=$(cat /etc/vmware-release)
OS_VERSION=$(uname -r)
fi
HAS_VMWARE_UTIL=$(which vmware 2> /dev/null)
HAS_VMWARE_UTIL=$(which vmware 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! "${HAS_VMWARE_UTIL}" = "" ]; then
IS_VMWARE_ESXI=$(vmware -vl | grep VMware ESXi)
if [ ! "${IS_VMWARE_ESXI}" = "" ]; then
@ -440,7 +440,7 @@
"AIX") ECHOCMD="echo" ;;
"DragonFly"|"FreeBSD"|"NetBSD") ECHOCMD="echo -e"; ECHONB="echo -n" ;;
"macOS" | "Mac OS X") ECHOCMD="echo"; ECHONB="/bin/echo -n" ;;
"Solaris") ECHOCMD="echo" ;;
"Solaris") ECHOCMD="echo" ; test -f /usr/ucb/echo && ECHONB="/usr/ucb/echo -n" ;;
"Linux")
# Check if dash is used (Debian/Ubuntu)
DEFAULT_SHELL=$(ls -l /bin/sh | awk -F'>' '{print $2}')

View File

@ -650,7 +650,12 @@
if [ -d ${DIR} -a ! -L ${DIR} ]; then
LogText "Result: directory ${DIR} exists"
# Search in the specified directory
FIND=$(find ${DIR} -maxdepth 1 -type f -name "pam_*.so" -print | sort)
if [ "${OS}" = "Solaris" ]; then
# Solaris doesn't support -maxdepth
FIND=$(find ${DIR} -type f -name "pam_*.so" -print | sort)
else
FIND=$(find ${DIR} -maxdepth 1 -type f -name "pam_*.so" -print | sort)
fi
if [ ! "${FIND}" = "" ]; then FOUND=1; fi
for FILE in ${FIND}; do
LogText "Found file: ${FILE}"
@ -809,7 +814,14 @@
Register --test-no AUTH-9288 --preqs-met ${PREQS_MET} --weight L --network NO --root-only YES --category security --description "Checking for expired passwords"
if [ ${SKIPTEST} -eq 0 ]; then
if FileIsReadable /etc/shadow; then
DAYS_SINCE_EPOCH=$(($(date --utc +%s)/86400))
if [ "$OS" = "Solaris" ]; then
NOW=$(nawk 'BEGIN{print srand()}')
else
NOW=$(date "+%s")
fi
DAYS_SINCE_EPOCH=$((${NOW}/86400))
LogText "Data: Days since epoch is ${DAYS_SINCE_EPOCH}"
LogText "Test: collecting accounts which have an expired password (last day changed + maximum change time)"
# Skip fields with a !, *, or x, or !* (field $3 is last changed, $5 is maximum changed)

View File

@ -350,7 +350,7 @@
Register --test-no KRNL-5770 --os Solaris --weight L --network NO --category security --description "Checking active kernel modules"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: searching loaded kernel modules"
FIND=$(modinfo -c -w | ${GREPBINARY} -v "UNLOADED" | ${GREPBINARY} LOADED | ${AWKBINARY} '{ print $3 }' | sort)
FIND=$(/usr/sbin/modinfo -c -w | ${GREPBINARY} -v "UNLOADED" | ${GREPBINARY} LOADED | ${AWKBINARY} '{ print $3 }' | sort)
if [ ! "${FIND}" = "" ]; then
for I in ${FIND}; do
LogText "Found module: ${I}"

View File

@ -267,7 +267,7 @@
if [ ${UNBOUND_RUNNING} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no NAME-4036 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check Unbound configuration file"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(which unbound-checkconf)
FIND=$(which unbound-checkconf | grep -v "no [^ ]* in ")
if [ ! "${FIND}" = "" ]; then
LogText "Test: running unbound-checkconf"
# Don't capture any output, just gather exit code (0 is fine, otherwise bad)

View File

@ -87,7 +87,7 @@
#
# Test : PKGS-7303
# Description : Query brew package manager
FIND=$(which brew 2> /dev/null)
FIND=$(which brew 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! "${FIND}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no PKGS-7303 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Query brew package manager"
if [ ${SKIPTEST} -eq 0 ]; then
@ -223,7 +223,7 @@
Register --test-no PKGS-7312 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Checking available updates for pacman based system"
if [ ${SKIPTEST} -eq 0 ]; then
FOUND=0
FIND=$(which checkupdates 2> /dev/null)
FIND=$(which checkupdates 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! -z "${FIND}" ]; then
FIND=$(checkupdates)
for I in ${FIND}; do

View File

@ -35,7 +35,7 @@
# Description : Check cron daemon
Register --test-no SCHD-7702 --weight L --network NO --category security --description "Check status of cron daemon"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(ps aux | ${EGREPBINARY} "( cron$|/cron(d)? )")
FIND=$(${PSBINARY} aux | ${EGREPBINARY} "( cron$|/cron(d)? )")
if [ "${FIND}" = "" ]; then
LogText "Result: no cron daemon found"
else

View File

@ -283,7 +283,7 @@
FIND=$(${EGREPBINARY} '(/usr)?(/local)?/bin/bash' /etc/shells | ${GREPBINARY} -v "^#" | head -1)
else
LogText "Test: checking if bash is available via which command"
FIND=$(which bash 2> /dev/null | head -1)
FIND=$(which bash 2> /dev/null | grep -v "no [^ ]* in " | head -1)
fi
LogText "Result: command revealed ${FIND} as output"

View File

@ -183,7 +183,7 @@
# Continue if tooling is available and configuration file found
if [ ${FAIL2BAN_FOUND} -eq 1 -a ! "${FAIL2BAN_CONFIG}" = "" ]; then
Report "fail2ban_config=${FAIL2BAN_CONFIG}"
FAIL2BANCLIENT=$(which fail2ban-client 2> /dev/null)
FAIL2BANCLIENT=$(which fail2ban-client 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! -z "${FAIL2BANCLIENT}" ]; then PERFORM_FAIL2BAN_TESTS=1; fi
fi
fi

12
lynis
View File

@ -1,5 +1,10 @@
#!/bin/sh
# In Solaris /bin/sh is not POSIX, but /usr/xpg4/bin/sh is.
# Switch to /usr/xpg4/bin/sh if it exists and we are not already running it.
test "$_" != "/usr/xpg4/bin/sh" && test -f /usr/xpg4/bin/sh && \
exec /usr/xpg4/bin/sh "$0" "$@"
#################################################################################
#
# Lynis
@ -698,7 +703,12 @@ ${NORMAL}
fi
# Test for older releases, without testing via update mechanism
NOW=$(date "+%s")
if [ "$OS" = "Solaris" ]; then
NOW=$(nawk 'BEGIN{print srand()}')
else
NOW=$(date "+%s")
fi
OLD_RELEASE=0
TIME_DIFFERENCE_CHECK=10368000 # 4 months
RELEASE_PLUS_TIMEDIFF=$((${PROGRAM_RELEASE_TIMESTAMP} + ${TIME_DIFFERENCE_CHECK}))