#!/bin/sh

#################################################################################
#
#   Lynis
# ------------------
#
# Copyright (c) Michael Boelen, CISOfy, and many contributors.
#
# Website  : https://cisofy.com
# Blog     : https://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.
#
#################################################################################
#
# Category: Boot and services
#
#################################################################################
#
    InsertSection "${SECTION_BOOT_AND_SERVICES}"
#
#################################################################################
#
    BOOT_LOADER="unknown"
    BOOT_LOADER_FOUND=0
    BOOT_LOADER_SEARCHED=0
    GRUB_VERSION=0
    if [ -z "${SERVICE_MANAGER}" ]; then
        SERVICE_MANAGER="unknown"
    fi
#
#################################################################################
#
    # Test        : BOOT-5102
    # Description : Check for AIX boot device
    # Notes       : The AIX bootstrap is called as software ROS. Bootstrap contains IPL (Initial Program loader)
    #               TODO - binary detection of bootinfo and replace with variable
    Register --test-no BOOT-5102 --os AIX --weight L --network NO --root-only YES --category security --description "Check for AIX boot device"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        LogText "Test: Query bootinfo for AIX boot device"
        if [ -x /usr/sbin/bootinfo ]; then
            FIND=$(/usr/sbin/bootinfo -b)
            if [ -n "${FIND}" ]; then
                LogText "Result: found boot device ${FIND}"
                Display --indent 2 --text "- Checking boot device (bootinfo)" --result "${STATUS_FOUND}" --color GREEN
                BOOT_LOADER="ROS"
                BOOT_LOADER_FOUND=1
            else
                LogText "Result: no data received from bootinfo, most likely boot device not found"
            fi
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5104
    # Description : Determine service manager
    # Notes       :
    # initscripts     - Used by Arch before
    # runit           - Used by Artix, Devuan, Dragora and Void
    # systemd         - Common option with more Linux distros implementing it
    # upstart         - Used by Debian/Ubuntu
    Register --test-no BOOT-5104 --weight L --network NO --category security --description "Determine service manager"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        case ${OS} in
            "Linux")
                if [ -f /proc/1/cmdline ]; then
                    OUTPUT=$(${AWKBINARY} '/(^\/|init|runit)/ { print $1 }' /proc/1/cmdline | ${TRBINARY} '\0' ' ' | ${SEDBINARY} 's/ $//')
                    LogText "Result: cmdline found = ${OUTPUT}"
                    FILENAME=$(echo "${OUTPUT}" | ${AWKBINARY} '{print $1}')
                    LogText "Result: file on disk = ${FILENAME}"
                    ISFILE=$(echo ${FILENAME} | ${GREPBINARY} "^/")
                    if [ -n "${ISFILE}" ]; then
                        if [ -L ${ISFILE} ]; then
                            ShowSymlinkPath ${ISFILE}
                            FILENAME="${SYMLINK}"
                        elif [ -f ${ISFILE} ]; then
                            FILENAME="${ISFILE}"
                        else
                            LogText "Result: cmdline of PID 1 is not a file"
                        fi
                    fi
                    if [ -n "${FILENAME}" ]; then
                        SHORTNAME=$(echo ${FILENAME} | ${AWKBINARY} -F/ '{ print $NF }')
                        LogText "Found: ${SHORTNAME}"
                        if [ "${SERVICE_MANAGER}" = "unknown" ]; then
                            case ${SHORTNAME} in
                                busybox)
                                    SERVICE_MANAGER="busybox"
                                ;;

                                "init" | "initsplash")
                                    if [ -d ${ROOTDIR}etc/rc.d ]; then
                                        SERVICE_MANAGER="bsdrc.d"
                                    else
                                        SERVICE_MANAGER="SysV Init"
                                    fi
                                ;;
                                systemd)
                                    SERVICE_MANAGER="systemd"
                                ;;
                                upstart)
                                    SERVICE_MANAGER="upstart"
                                ;;
                                runit)
                                    SERVICE_MANAGER="runit"
                                ;;
				openrc-init)
                                    SERVICE_MANAGER="openrc"
                                ;;
                                *)
                                    CONTAINS_SYSTEMD=$(echo ${SHORTNAME} | ${GREPBINARY} "systemd")
                                    if [ -n "${CONTAINS_SYSTEMD}" ]; then
                                        SERVICE_MANAGER="systemd"
                                    else
                                        LogText "Found ${SHORTNAME}. Unclear what service manager this is"
                                        ReportException "${TEST_NO}:001" "Unknown service manager"
                                    fi
                                ;;
                            esac
                        fi
                    else
                        LogText "Result: /proc/1/cmdline seems to be empty"
                        ReportException "${TEST_NO}:002" "No data found in /proc/1/cmdline"
                    fi
                fi
                # Continue testing if we didn't find it yet
                if [ "${SERVICE_MANAGER}" = "unknown" ]; then
                    if [ -f /usr/bin/init-openrc ]; then SERVICE_MANAGER="openrc"; fi
                fi
            ;;
            "DragonFly" | "NetBSD" | "FreeBSD" | "OpenBSD")
                if [ -x /sbin/init -a -d ${ROOTDIR}etc/rc.d -a -f ${ROOTDIR}etc/rc ]; then
                    SERVICE_MANAGER="bsdrc"
                fi
            ;;
            "macOS")
                if [ -x ${ROOTDIR}sbin/launchd ]; then
                    SERVICE_MANAGER="launchd"
                fi
            ;;
            "Solaris")
                if [ -x "${ROOTDIR}usr/bin/svcs" ]; then
                    SERVICE_MANAGER="SMF (svcs)"
                elif [ -d "${ROOTDIR}etc/init.d" ]; then
                    SERVICE_MANAGER="SysV Init"
                fi
            ;;
            *)
                LogText "Result: unknown service manager"
            ;;
        esac
        LogText "Result: service manager found = ${SERVICE_MANAGER}"
        if [ "${SERVICE_MANAGER}" = "" -o "${SERVICE_MANAGER}" = "unknown" ]; then
            Display --indent 2 --text "- Service Manager" --result "${STATUS_UNKNOWN}" --color YELLOW
        else
            Display --indent 2 --text "- Service Manager" --result "${SERVICE_MANAGER}" --color GREEN
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5106
    # Description : Check if boot.efi is found on macOS/macOS
    Register --test-no BOOT-5106 --os "macOS" --weight L --network NO --root-only YES --category security --description "Check EFI boot file on Mac OS X/macOS"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        FileExists ${ROOTDIR}System/Library/CoreServices/boot.efi
        if [ ${FILE_FOUND} -eq 1 ]; then
            LogText "Result: found macOS/Mac OS X boot.efi file"
            BOOT_LOADER="macOS-boot-EFI"
            BOOT_LOADER_FOUND=1
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5108
    # Description : Check for Syslinux
    Register --test-no BOOT-5108 --os "Linux" --weight L --network NO --root-only YES --category security --description "Check Syslinux as bootloader"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        FileExists ${ROOTDIR}boot/syslinux/syslinux.cfg
        if [ ${FILE_FOUND} -eq 1 ]; then
            LogText "Result: found Syslinux"
            BOOT_LOADER="Syslinux"
            BOOT_LOADER_FOUND=1
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5109
    # Description : Check for rEFInd
    Register --test-no BOOT-5109 --os "Linux" --weight L --network NO --root-only YES --category security --description "Check rEFInd as bootloader"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        FileExists ${ROOTDIR}boot/refind_linux.conf
        if [ ${FILE_FOUND} -eq 1 ]; then
            LogText "Result: found rEFInd"
            BOOT_LOADER="rEFInd"
            BOOT_LOADER_FOUND=1
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5116
    # Description : Check if system is booted in UEFI mode
    Register --test-no BOOT-5116 --weight L --network NO --root-only YES --category security --description "Check if system is booted in UEFI mode"
    if [ ${SKIPTEST} -eq 0 ]; then
        UEFI_TESTS_PERFORMED=0
        case ${OS} in
            Linux)
                UEFI_TESTS_PERFORMED=1
                # Check if UEFI is available in this boot
                LogText "Test: checking if UEFI is used"
                if [ -d ${ROOTDIR}sys/firmware/efi ]; then
                    LogText "Result: system booted in UEFI mode"
                    UEFI_BOOTED=1
                else
                    LogText "Result: UEFI not used, can't find /sys/firmware/efi directory"
                fi

                # Test if Secure Boot is enabled
                LogText "Test: determine if Secure Boot is used"
                if [ -d ${ROOTDIR}sys/firmware/efi/efivars ]; then
                    FIND=$(${LSBINARY} ${ROOTDIR}sys/firmware/efi/efivars/SecureBoot-* 2> /dev/null)
                    if [ -n "${FIND}" ]; then
                        for FILE in ${FIND}; do
                            LogText "Test: checking file ${FILE}"
                            # TODO: add detection for od
                            J=$(od -An -t u1 ${FILE} | ${AWKBINARY} '{ print $5 }')
                            if [ "${J}" = "1" ]; then
                                LogText "Result: found SecureBoot file with enabled status"
                                UEFI_BOOTED_SECURE=1
                            else
                                LogText "Result: system not booted with Secure Boot (status 0 in file ${FILE})"
                            fi
                        done
                    fi
                else
                    LogText "Result: system not booted with Secure Boot (no SecureBoot file found)"
                fi
            ;;
            #macOS)
            # TODO: macOS ioreg -l -p IODeviceTree | ${GREPBINARY} firmware-abi
            #;;
            *)
                LogText "Result: no test implemented yet to test for UEFI on this platform"
            ;;
        esac
        if [ ${UEFI_BOOTED} -eq 1 ]; then
            Display --indent 2 --text "- Checking UEFI boot" --result "${STATUS_ENABLED}" --color GREEN
            if [ ${UEFI_BOOTED_SECURE} -eq 1 ]; then
                Display --indent 2 --text "- Checking Secure Boot" --result "${STATUS_ENABLED}" --color GREEN
            else
                Display --indent 2 --text "- Checking Secure Boot" --result "${STATUS_DISABLED}" --color YELLOW
            fi
        else
            if [ ${UEFI_TESTS_PERFORMED} -eq 1 ]; then
                Display --indent 2 --text "- Checking UEFI boot" --result "${STATUS_DISABLED}" --color WHITE
            fi
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5117
    # Description : Check for systemd-boot boot loader
    if [ ! "${BOOTCTLBINARY}" = "" -a ${HAS_SYSTEMD} -eq 1 -a ${UEFI_BOOTED} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no BOOT-5117 --preqs-met ${PREQS_MET} --os "Linux" --weight L --network NO --category security --description "Check for systemd-boot bootloader presence"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        CURRENT_BOOT_LOADER=$(${BOOTCTLBINARY} status --no-pager 2>/dev/null | ${AWKBINARY} '/Current Boot Loader/{ getline; print $2 }')
        if [ "${CURRENT_BOOT_LOADER}" = "systemd-boot" ]; then
	    Display --indent 2 --text "- Checking systemd-boot presence" --result "${STATUS_FOUND}" --color GREEN
            LogText "Result: found systemd-boot"
            BOOT_LOADER="systemd-boot"
            BOOT_LOADER_FOUND=1
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5121
    # Description : Check for GRUB boot loader
    Register --test-no BOOT-5121 --weight L --network NO --category security --description "Check for GRUB boot loader presence"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        FOUND=0
        LogText "Test: Checking for presence GRUB conf file (/boot/grub/grub.conf or /boot/grub/menu.lst)"
        if [ -f /boot/grub/grub.conf -o -f /boot/grub/menu.lst ]; then
            FOUND=1
            BOOT_LOADER="GRUB"
            BOOT_LOADER_FOUND=1
            GRUB_VERSION=1
            Display --indent 2 --text "- Checking presence GRUB" --result "${STATUS_OK}" --color GREEN
            if [ -f /boot/grub/grub.conf ]; then GRUBCONFFILE="/boot/grub/grub.conf"; else GRUBCONFFILE="/boot/grub/menu.lst"; fi
        fi

        # GRUB2 configuration file
        if [ -f /boot/grub/grub.cfg -o -f /boot/grub2/grub.cfg ]; then
            FOUND=1
            BOOT_LOADER="GRUB2"
            BOOT_LOADER_FOUND=1
            GRUB_VERSION=2
            Display --indent 2 --text "- Checking presence GRUB2" --result "${STATUS_FOUND}" --color GREEN
            if [ -f /boot/grub/grub.cfg ]; then
                GRUBCONFFILE="/boot/grub/grub.cfg"
            elif [ -f /boot/grub2/grub.cfg ]; then
                GRUBCONFFILE="/boot/grub2/grub.cfg"
            fi
            LogText "Result: found GRUB2 configuration file (${GRUBCONFFILE})"
        fi

        # Some OSes like Gentoo do not have /boot mounted by default
        # TODO: root directory and rewrite ls statement
        if [ -d /boot ]; then
            if [ "$(ls /boot/* 2> /dev/null)" = "" -a -n "${GRUB2INSTALLBINARY}" ]; then
                BOOT_LOADER_FOUND=1
                LogText "Result: found empty /boot, however with GRUB2 binary installed. Best guess is that GRUB2 is actually installed, but /boot not mounted"
                Display --indent 2 --text "- Checking presence GRUB2" --result "POSSIBLE MATCH" --color YELLOW
                ReportManual "${TEST_NO}:01"
            fi
        fi

        if [ ${FOUND} -eq 0 ]; then
            LogText "Result: no GRUB configuration file found."
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5122
    # Description : Check for GRUB boot loader configuration
    if [ -n "${GRUBCONFFILE}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no BOOT-5122 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for GRUB boot password"
    if [ ${SKIPTEST} -eq 0 ]; then
        FOUND=0

        if [ -d "${ROOTDIR}etc/grub.d" ]; then
            CONF_FILES=$(${FINDBINARY} -L "${ROOTDIR}etc/grub.d" -type f -name "[0-9][0-9]*" -print0 | ${TRBINARY} '\0' ' ' | ${TRBINARY} -d '[:cntrl:]')
            CONF_FILES="${GRUBCONFFILE} ${ROOTDIR}boot/grub/custom.cfg ${CONF_FILES}"
        else
            CONF_FILES="${GRUBCONFFILE} ${ROOTDIR}boot/grub/custom.cfg"
        fi

        for FILE in ${CONF_FILES}; do
            if [ -f "${FILE}" ]; then
                LogText "Found file ${FILE}, proceeding with tests."
                if FileIsReadable "${FILE}"; then
                    FIND=$(${GREPBINARY} 'password --md5' ${FILE} | ${GREPBINARY} -v '^#')
                    FIND2=$(${GREPBINARY} 'password --encrypted' ${FILE} | ${GREPBINARY} -v '^#')
                    FIND3=$(${GREPBINARY} 'set superusers' ${FILE} | ${GREPBINARY} -v '^#')
                    FIND4=$(${GREPBINARY} 'password_pbkdf2' ${FILE} | ${GREPBINARY} -v '^#')
                    FIND5=$(${GREPBINARY} 'grub.pbkdf2' ${FILE} | ${GREPBINARY} -v '^#')
                    # GRUB1: Password should be set (MD5 or SHA1)
                    if [ -n "${FIND}" -o -n "${FIND2}" ]; then
                        FOUND=1
                    # GRUB2: Superusers AND password should be defined
                    elif [ -n "${FIND3}" ]; then
                        if [ -n "${FIND4}" -o -n "${FIND5}" ]; then FOUND=1; fi
                    else
                        LogText "Result: did not find hashed password line in this file"
                    fi
                else
                    LogText "Result: Can not read '${FILE}' (no permission?)"
                fi
            else
                LogText "Result: File '${FILE}' does not exist"
            fi
        done
        if [ ${FOUND} -eq 1 ]; then
                Display --indent 4 --text "- Checking for password protection" --result "${STATUS_OK}" --color GREEN
                LogText "Result: GRUB has password protection."
                AddHP 4 4
        else
                Display --indent 4 --text "- Checking for password protection" --result "${STATUS_NONE}" --color RED
                LogText "Result: Didn't find hashed password line in GRUB configuration"
                ReportSuggestion "${TEST_NO}" "Set a password on GRUB boot loader to prevent altering boot configuration (e.g. boot in single user mode without password)"
                AddHP 0 2
        fi
        unset CONF_FILES FILE FIND FIND2 FIND3 FIND4 FIND5 FOUND
    fi
#
#################################################################################
#
    # Test        : BOOT-5124
    # Description : Check for FreeBSD boot loader
    Register --test-no BOOT-5124 --os FreeBSD --weight L --network NO --category security --description "Check for FreeBSD boot loader presence"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        if [ -f ${ROOTDIR}boot/boot1 -a -f ${ROOTDIR}boot/boot2 -a -f ${ROOTDIR}boot/loader ]; then
            LogText "Result: found boot1, boot2 and loader files in ${ROOTDIR}boot"
            Display --indent 2 --text "- Checking presence FreeBSD loader" --result "${STATUS_FOUND}" --color GREEN
            BOOT_LOADER="FreeBSD"
            BOOT_LOADER_FOUND=1
        else
            LogText "Result: Not all expected files found in ${ROOTDIR}boot"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5261
    # Description : Check for DragonFly boot loader
    Register --test-no BOOT-5261 --os DragonFly --weight L --network NO --category security --description "Check for DragonFly boot loader presence"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        if [ -f ${ROOTDIR}boot/boot1 -a -f ${ROOTDIR}boot/boot2 -a -f ${ROOTDIR}boot/loader ]; then
            LogText "Result: found boot1, boot2 and loader files in ${ROOTDIR}boot"
            Display --indent 2 --text "- Checking presence DragonFly loader" --result "${STATUS_FOUND}" --color GREEN
            BOOT_LOADER="DragonFly"
            BOOT_LOADER_FOUND=1
        else
            LogText "Result: Not all expected files found in ${ROOTDIR}boot"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5126
    # Description : Check for NetBSD boot loader
    Register --test-no BOOT-5126 --os NetBSD --weight L --network NO --category security --description "Check for NetBSD boot loader presence"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        if [ -f ${ROOTDIR}boot.${HARDWARE} -o -f ${ROOTDIR}boot -o -f ${ROOTDIR}ofwboot ]; then
            LogText "Result: found NetBSD secondary bootstrap"
            Display --indent 2 --text "- Checking presence NetBSD loader" --result "${STATUS_FOUND}" --color GREEN
            BOOT_LOADER="NetBSD"
            BOOT_LOADER_FOUND=1
        else
            LogText "Result: NetBSD secondary bootstrap not found"
            ReportException "${TEST_NO}:1" "No boot loader found on NetBSD"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5139
    # Description : Check for LILO boot loader
    # Notes       : password= or password =
    Register --test-no BOOT-5139 --weight L --network NO --category security --description "Check for LILO boot loader presence"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        LILOCONFFILE="${ROOTDIR}etc/lilo.conf"
        LogText "Test: checking for presence LILO configuration file"
        if [ -f ${LILOCONFFILE} ]; then
            FileIsReadable ${LILOCONFFILE}
            if [ ${CANREAD} -eq 1 ]; then
                BOOT_LOADER="LILO"
                BOOT_LOADER_FOUND=1
                Display --indent 2 --text "- Checking presence LILO" --result "${STATUS_OK}" --color GREEN
                LogText "Checking password option LILO"
                FIND=$(${GREPBINARY} -E 'password[[:space:]]?=' ${LILOCONFFILE} | ${GREPBINARY} -v "^#")
                if [ -z "${FIND}" ]; then
                    if [ "${MACHINE_ROLE}" = "server" -o "${MACHINE_ROLE}" = "workstation" ]; then
                        Display --indent 4 --text "- Password option presence " --result "${STATUS_WARNING}" --color RED
                        LogText "Result: no password set for LILO. Bootloader is unprotected to dropping to single user mode or unauthorized access to devices/data."
                        ReportSuggestion "${TEST_NO}" "Add a password to LILO, by adding a line to the lilo.conf file, above the first line saying 'image=<name>': password=<password>"
                        ReportWarning "${TEST_NO}" "No password set on LILO bootloader"
                        AddHP 0 2
                    elif [ "${MACHINE_ROLE}" = "personal" ]; then
                        Display --indent 4 --text "- Password option presence " --result "${STATUS_WARNING}" --color yellow
                        LogText "Result: no password set for LILO. Bootloader is unprotected to dropping to single user mode or unauthorized access to devices/data."
                        ReportSuggestion "${TEST_NO}" "No password set on LILO bootloader. Add a password to LILO, by adding a line to the lilo.conf file, above the first line saying 'image=<name>': password=<password>"
                        AddHP 1 2
                    else
                        LogText "Result: no password set for LILO, with unknown machine role"
                    fi
                else
                    Display --indent 4 --text "- Password option presence " --result "${STATUS_OK}" --color GREEN
                    LogText "Result: LILO password option set"
                    AddHP 4 4
                fi
            else
                LogText "Result: can not read ${LILOCONFFILE} (no permission)"
            fi
        else
            LogText "Result: LILO configuration file not found"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5140
    # Description : Check for ELILO boot loader
    Register --test-no BOOT-5140 --os "Linux" --weight L --network NO --root-only YES --category security --description "Check for ELILO boot loader presence"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        CONF_FILES="${ROOTDIR}etc/elilo.conf ${ROOTDIR}boot/efi/EFI/${LINUX_VERSION}/elilo.conf"
        for FILE in ${CONF_FILES}; do
            FileExists ${FILE}
            if [ ${FILE_FOUND} -eq 1 ]; then
                Display --indent 2 --text "- Checking boot loader ELILO" --result "${STATUS_FOUND}" --color GREEN
                LogText "Result: found ELILO boot loader"
                BOOT_LOADER="ELILO"
                BOOT_LOADER_FOUND=1
            fi
        done
    fi
#
#################################################################################
#
    # Test        : BOOT-5142
    # Description : Check for SILO boot loader
    Register --test-no BOOT-5142 --weight L --network NO --category security --description "Check SPARC Improved boot loader (SILO)"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        if [ -f ${ROOTDIR}etc/silo.conf ]; then
            LogText "Result: Found SILO configuration file (/etc/silo.conf)"
            Display --indent 2 --text "- Checking boot loader SILO" --result "${STATUS_FOUND}" --color GREEN
            BOOT_LOADER="SILO"
            BOOT_LOADER_FOUND=1
        else
            LogText "Result: no SILO configuration file found."
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5155
    # Description : Check for YABOOT boot loader
    Register --test-no BOOT-5155 --weight L --network NO --category security --description "Check for YABOOT boot loader configuration file"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        LogText "Test: Check for /etc/yaboot.conf"
        if [ -f /etc/yaboot.conf ]; then
            LogText "Result: Found YABOOT configuration file (/etc/yaboot.conf)"
            Display --indent 4 --text "- Checking boot loader YABOOT" --result "${STATUS_FOUND}" --color GREEN
            BOOT_LOADER="YABOOT"
            BOOT_LOADER_FOUND=1
        else
            LogText "Result: no YABOOT configuration file found."
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5159
    # Description : Check for OpenBSD boot loader
    # More info   : Only OpenBSD
    Register --test-no BOOT-5159 --os OpenBSD --weight L --network NO --category security --description "Check for OpenBSD boot loader presence"
    if [ ${SKIPTEST} -eq 0 ]; then
        BOOT_LOADER_SEARCHED=1
        FOUND=0
        # Boot files
        # /usr/mdec/biosboot: first stage bootstrap
        # /boot             : second stage bootstrap
        if [ -f ${ROOTDIR}usr/mdec/biosboot -a -f ${ROOTDIR}boot ]; then
            FOUND=1
        fi
        # Configuration file
        if [ -f ${ROOTDIR}etc/boot.conf ]; then
            FOUND=1
            Display --indent 2 --text "- Checking ${ROOTDIR}etc/boot.conf" --result "${STATUS_FOUND}" --color GREEN
            FIND=$(${GREPBINARY} '^boot' ${ROOTDIR}etc/boot.conf)
            if [ -z "${FIND}" ]; then
                Display --indent 4 --text "- Checking boot option" --result "${STATUS_WARNING}" --color RED
                #ReportSuggestion "${TEST_NO}" "Add 'boot' to the ${ROOTDIR}etc/boot.conf file to disable the default 5 seconds waiting time, to disallow booting into single user mode."
                ReportWarning "${TEST_NO}" "System can be booted into single user mode without password"
            else
                Display --indent 4 --text "- Checking boot option" --result "${STATUS_OK}" --color GREEN
                LogText "Ok, boot option is enabled."
            fi
        else
            Display --indent 2 --text "- Checking ${ROOTDIR}etc/boot.conf" --result "${STATUS_NOT_FOUND}" --color YELLOW
            LogText "Result: no ${ROOTDIR}etc/boot.conf found. When using the default boot loader, physical"
            LogText "access to the server can be used to possibly enter single user mode."
            ReportSuggestion "${TEST_NO}" "Add 'boot' to the ${ROOTDIR}etc/boot.conf file to disable the default 5 seconds waiting time."
        fi
        if [ ${FOUND} -eq 1 ]; then
            LogText "Result: found OpenBSD boot loader"
            BOOT_LOADER="OpenBSD"
            BOOT_LOADER_FOUND=1
        fi
    fi
#
#################################################################################
#
    if [ ${BOOT_LOADER_FOUND} -eq 0 -a ${BOOT_LOADER_SEARCHED} -eq 1 ]; then
        # Your boot loader is not detected. Want to help supporting it, see the README
        # ReportException "BOOTLOADER" "No boot loader found"
        Display --indent 4 --text "- Boot loader" --result "NONE FOUND" --color YELLOW
    fi
#
#################################################################################
#
    # Test        : BOOT-5165
    # Description : Check for FreeBSD boot services
    Register --test-no BOOT-5165 --os FreeBSD --weight L --network NO --category security --description "Check for FreeBSD boot services"
    if [ ${SKIPTEST} -eq 0 ]; then
        if HasData "${SERVICEBINARY}"; then
            # FreeBSD (Ask services(8) for enabled services)
            LogText "Searching for services at startup (service)"
            FIND=$(${SERVICEBINARY} -e | ${SEDBINARY} 's|^.*\/||' | ${SORTBINARY})
        else
            # FreeBSD (Read /etc/rc.conf file for enabled services)
            LogText "Searching for services at startup (rc.conf)"
            FIND=$(${GREPBINARY} -E -v -i '^#|none' ${ROOTDIR}etc/rc.conf | ${GREPBINARY} -E -i '_enable.*(yes|on|1)' | ${SORTBINARY} | ${AWKBINARY} -F= '{ print $1 }' | ${SEDBINARY} 's/_enable//')
        fi
        COUNT=0
        for ITEM in ${FIND}; do
            LogText "Found service (service/rc.conf): ${ITEM}"
            Report "boottask[]=${ITEM}"
            COUNT=$((COUNT + 1))
        done
        Display --indent 2 --text "- Checking services at startup (service/rc.conf)" --result "${STATUS_DONE}" --color GREEN
        Display --indent 6 --text "Result: found ${COUNT} services/options set"
        LogText "Found ${COUNT} services/options to run at startup"
    fi
#
#################################################################################
#
    # Test        : BOOT-5170
    # Description : Check for Solaris boot daemons
    Register --test-no BOOT-5170 --os Solaris --weight L --network NO --category security --description "Check for Solaris boot daemons"
    if [ ${SKIPTEST} -eq 0 ]; then
        if [ -n "${SVCSBINARY}" ]; then
            LogText "Result: Using svcs binary to check for daemons"
            LogText "SysV style services may be incorrectly counted as running."

            Report "running_service_tool=svcs"

            # For the documentation of the states (field $1) see
            # "Managing System Services in Oracle Solaris 11.4" pp. 24, available
            # at https://docs.oracle.com/cd/E37838_01/pdf/E60998.pdf

            FIND=$("${SVCSBINARY}" -Ha | ${AWKBINARY} '{ if ($1 == "online" || $1 == "legacy_run") print $3 }')
            COUNT=0
            for ITEM in ${FIND}; do
                LogText "Found running daemon: ${ITEM}"
                Report "running_service[]=${ITEM}"
                COUNT=$((COUNT + 1 ))
            done
            Display --indent 2 --text "- Check running daemons (svcs)" --result "${STATUS_DONE}" --color GREEN
            Display --indent 8 --text "Result: found ${COUNT} running daemons"
            LogText "Result: Found ${COUNT} running daemons"

            LogText "Searching for enabled daemons (svcs)"
            Report "boot_service_tool=svcs"

            FIND=$("${SVCSBINARY}" -Ha | ${AWKBINARY} '{ if ($1 != "disabled" && $1 != "uninitialized") print $3 }')
            COUNT=0
            for ITEM in ${FIND}; do
                LogText "Found enabled daemon at boot: ${ITEM}"
                Report "boot_service[]=${ITEM}"
                COUNT=$((COUNT + 1 ))
            done
            LogText "Note: Run svcs -a see all services"
            Display --indent 2 --text "- Check enabled daemons at boot (svcs)" --result "${STATUS_DONE}" --color GREEN
            Display --indent 8 --text "Result: found ${COUNT} enabled daemons at boot"
            LogText "Result: Found ${COUNT} enabled daemons at boot"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5171
    # Description : Check for services with errors on solaris
#
#################################################################################
#
    # Test        : BOOT-5177
    # Description : Check for Linux boot services (systemd and chkconfig)
    # Notes       : We skip using chkconfig if systemd is being used.
    Register --test-no BOOT-5177 --os Linux --weight L --network NO --category security --description "Check for Linux boot and running services"
    if [ ${SKIPTEST} -eq 0 ]; then
        CHECKED=0
        LogText "Test: checking presence systemctl binary"
        # Determine if we have systemctl on board
        if HasData "${SYSTEMCTLBINARY}"; then
            LogText "Result: systemctl binary found, trying that to discover information"
            # Running services
            LogText "Searching for running services (systemctl services only)"
            FIND=$(${SYSTEMCTLBINARY} --no-legend --full --type=service --state=running | ${AWKBINARY} -F.service '{ print $1 }')
            COUNT=0
            Report "running_service_tool=systemctl"
            for ITEM in ${FIND}; do
                LogText "Found running service: ${ITEM}"
                Report "running_service[]=${ITEM}"
                COUNT=$((COUNT + 1))
            done
            LogText "Hint: Run systemctl --full --type=service to see all services"
            Display --indent 2 --text "- Check running services (systemctl)" --result "${STATUS_DONE}" --color GREEN
            Display --indent 8 --text "Result: found ${COUNT} running services"
            LogText "Result: Found ${COUNT} running services"

            # Services at boot
            LogText "Searching for enabled services (systemctl services only)"
            FIND=$(${SYSTEMCTLBINARY} list-unit-files --no-legend --type=service --state=enabled | ${SORTBINARY} -u | ${AWKBINARY} -F.service '{ print $1 }')
            COUNT=0
            Report "boot_service_tool=systemctl"
            for ITEM in ${FIND}; do
                LogText "Found enabled service at boot: ${ITEM}"
                Report "boot_service[]=${ITEM}"
                COUNT=$((COUNT + 1))
            done
            LogText "Hint: Run systemctl list-unit-files --type=service to see all services"
            Display --indent 2 --text "- Check enabled services at boot (systemctl)" --result "${STATUS_DONE}" --color GREEN
            Display --indent 8 --text "Result: found ${COUNT} enabled services"
            LogText "Result: Found ${COUNT} enabled services"

        else

            LogText "Result: systemctl binary not found, checking chkconfig binary"
            if [ -n "${CHKCONFIGBINARY}" ]; then
                LogText "Result: chkconfig binary found, trying that to discover information"
                LogText "Searching for services at startup (chkconfig, runlevel 3 and 5)"
                FIND=$(${CHKCONFIGBINARY} --list | ${GREPBINARY} -E '3:on|5:on' | ${AWKBINARY} '{ print $1 }')
                COUNT=0
                Report "boot_service_tool=chkconfig"
                for ITEM in ${FIND}; do
                    LogText "Found service (at boot, runlevel 3 or 5): ${ITEM}"
                    Report "boot_service[]=${ITEM}"
                    COUNT=$((COUNT + 1))
                done
                LogText "Hint: Run chkconfig --list to see all services and disable unneeded services"
                Display --indent 2 --text "- Check services at startup (chkconfig)" --result "${STATUS_DONE}" --color GREEN
                Display --indent 8 --text "Result: found ${COUNT} services"
                LogText "Result: Found ${COUNT} services at startup"
            else
                LogText "Result: both systemctl and chkconfig not found. Skipping this test"
            fi
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5180
    # Description : Check for Linux boot services (Debian style)
    # Notes       : Debian 8+ shows runlevel 5
    if [ "${LINUX_VERSION}" = "Debian" ] || [ "${LINUX_VERSION}" = "Ubuntu" ] ||
           [ "${LINUX_VERSION_LIKE}" = "Debian" ] || [ "${LINUX_VERSION_LIKE}" = "Ubuntu" ]; then
        PREQS_MET="YES"
    else
        PREQS_MET="NO"
    fi

    Register --test-no BOOT-5180 --os Linux --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for Linux boot services (Debian style)"
    if [ ${SKIPTEST} -eq 0 ]; then
        # Runlevel check
        sRUNLEVEL=$(${RUNLEVELBINARY} | ${GREPBINARY} "N [0-9]" | ${AWKBINARY} '{ print $2} ')
        LogText "Result: found runlevel ${sRUNLEVEL}"
        if [ "${sRUNLEVEL}" = "2" ]; then
            LogText "Result: performing find in /etc/rc2.d as runlevel 2 is found"
            FIND=$(${FINDBINARY} ${ROOTDIR}etc/rc2.d -type l -print | ${CUTBINARY} -d '/' -f4 | ${SEDBINARY} "s/S[0-9][0-9]//g" | sort)
            if [ -n "${FIND}" ]; then
                COUNT=0
                for SERVICE in ${FIND}; do
                    LogText "Found service (at boot, runlevel 2): ${SERVICE}"
                    COUNT=$((COUNT + 1))
                done
                Display --indent 2 --text "- Check services at startup (rc2.d)" --result "${STATUS_DONE}" --color WHITE
                Display --indent 4 --text "Result: found ${COUNT} services"
                LogText "Result: found ${COUNT} services"
            fi
        elif [ -z "${sRUNLEVEL}" ]; then
            ReportSuggestion "${TEST_NO}" "Determine runlevel and services at startup"
        else
            LogText "Result: skipping further actions"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5184
    # Description : Check world writable startup scripts
    Register --test-no BOOT-5184 --os "Linux Solaris" --weight L --network NO --category security --description "Check permissions for boot files/scripts"
    if [ ${SKIPTEST} -eq 0 ]; then
        FOUND=0
        CHECKDIRS="${ROOTDIR}etc/init.d ${ROOTDIR}etc/rc.d ${ROOTDIR}etc/rcS.d"

        LogText "Result: checking ${ROOTDIR}etc/init.d scripts for writable bit"
        for DIR in ${CHECKDIRS}; do
            LogText "Test: checking if directory ${DIR} exists"
            if [ -d ${DIR} ]; then
                LogText "Result: directory ${DIR} found"
                LogText "Test: checking for available files in directory"
                FIND=$(${FINDBINARY} -L ${DIR} -type f -print | ${SORTBINARY})
                if [ -n "${FIND}" ]; then
                    LogText "Result: found files in directory, checking permissions now"
                    for FILE in ${FIND}; do
                        LogText "Test: checking permissions of file ${FILE}"
                        if IsWorldWritable ${FILE}; then
                            FOUND=1
                            LogText "Result: warning, file ${FILE} is world writable"
                        else
                            LogText "Result: good, file ${FILE} not world writable"
                        fi
                    done
                else
                    LogText "Result: found no files in directory."
                fi
            else
                LogText "Result: directory ${DIR} not found. Skipping.."
            fi
        done

        # /etc/rc[0-6].d
        for NO in 0 1 2 3 4 5 6; do
            LogText "Test: Checking ${ROOTDIR}etc/rc${NO}.d scripts for writable bit"
            if [ -d ${ROOTDIR}etc/rc${NO}.d ]; then
                FIND=$(${FINDBINARY} -L ${ROOTDIR}etc/rc${NO}.d -type f -print | ${SORTBINARY})
                for I in ${FIND}; do
                    if IsWorldWritable ${I}; then
                        FOUND=1
                        LogText "Result: warning, file ${I} is world writable"
                    else
                        LogText "Result: good, file ${I} not world writable"
                    fi
                done
            fi
        done

        # Other files
        CHECKFILES="${ROOTDIR}etc/rc ${ROOTDIR}etc/rc.local ${ROOTDIR}etc/rc.d/rc.sysinit"
        for I in ${CHECKFILES}; do
            if [ -f ${I} ]; then
                ShowSymlinkPath "${I}"
                if [ ${FOUNDPATH} -eq 1 ]; then
                    CHECKFILE="${SYMLINK}"
                    LogText "Result: found the path behind this symlink (${CHECKFILE} --> ${I})"
                else
                    CHECKFILE="${I}"
                fi
                LogText "Test: Checking ${CHECKFILE} file for writable bit"
                if IsWorldWritable ${CHECKFILE}; then
                    FOUND=1
                    ReportWarning "${TEST_NO}" "Found writable startup script ${CHECKFILE}"
                    LogText "Result: warning, file ${CHECKFILE} is world writable"
                else
                    LogText "Result: good, file ${CHECKFILE} not world writable"
                fi
            fi
        done

        # Check results
        if [ ${FOUND} -eq 1 ]; then
            Display --indent 2 --text "- Check startup files (permissions)" --result "${STATUS_WARNING}" --color RED
            ReportWarning "${TEST_NO}" "Found world writable startup scripts" "-" "-"
            LogText "Result: found one or more scripts which are possibly writable by other users"
            AddHP 0 3
        else
            Display --indent 2 --text "- Check startup files (permissions)" --result "${STATUS_OK}" --color GREEN
            AddHP 3 3
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5202
    # Description : Check uptime of system
    Register --test-no BOOT-5202 --weight L --network NO --category security --description "Check uptime of system"
    if [ ${SKIPTEST} -eq 0 ]; then
        FOUND=0
        FIND=""
        UPTIME_IN_SECS=""
        case "${OS}" in
            Linux)
                # Idle time, not real uptime
                if [ -f /proc/uptime ]; then
                    UPTIME_IN_SECS=$(${CUTBINARY} -d ' ' -f1 /proc/uptime | ${CUTBINARY} -d '.' -f1)
                else
                    Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
                    ReportException "${TEST_NO}:1" "No uptime test available for this operating system (/proc/uptime missing)"
                fi
            ;;

            DragonFly | FreeBSD | macOS)
                if [ -n "${SYSCTLBINARY}" ]; then
                    TIME_BOOT=$(${SYSCTLBINARY} kern.boottime | ${AWKBINARY} '{ print $5 }' | ${SEDBINARY} -e 's/,//' | ${GREPBINARY} "[0-9]")
                    TIME_NOW=$(date "+%s")
                    LogText "Boot time: ${TIME_BOOT}"
                    LogText "Current time: ${TIME_NOW}"
                    if [ -n "${TIME_BOOT}" -a -n "${TIME_NOW}" ]; then
                        UPTIME_IN_SECS=$((TIME_NOW - TIME_BOOT))
                    else
                        ReportException "${TEST_NO}:5" "Most likely kern.boottime empty, unable to determine uptime"
                    fi
                else
                    Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
                    ReportException "${TEST_NO}:4" "No uptime test available for this operating system (sysctl missing)"
                fi
            ;;

            NetBSD | OpenBSD)
                if [ -n "${SYSCTLBINARY}" ]; then
                    TIME_BOOT=$(${SYSCTLBINARY} -n kern.boottime)
                    TIME_NOW=$(date "+%s")
                    LogText "Boot time: ${TIME_BOOT}"
                    LogText "Current time: ${TIME_NOW}"
                    if [ -n "${TIME_BOOT}" -a -n "${TIME_NOW}" ]; then
                        UPTIME_IN_SECS=$((TIME_NOW - TIME_BOOT))
                    else
                        ReportException "${TEST_NO}:5" "Most likely kern.boottime empty, unable to determine uptime"
                    fi
                else
                    Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
                    ReportException "${TEST_NO}:4" "No uptime test available for this operating system (sysctl missing)"
                fi
            ;;

            Solaris)
                if [ -n "${KSTATBINARY}" ]; then
                    UPTIME_IN_SECS=$(${KSTATBINARY} -p unix:0:system_misc:snaptime | ${GREPBINARY} "^unix" | ${AWKBINARY} '{print $2}' | ${CUTBINARY} -d "." -f1)
                else
                    Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
                    ReportException "${TEST_NO}:2" "No uptime test available for this operating system (kstat missing)"
                fi
            ;;

            *)
                Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW

                # Want to help improving Lynis? Share your operating system and a way to determine the uptime (in seconds)
                ReportException "${TEST_NO}:3" "No uptime test available yet for this operating system"
            ;;
        esac

        if [ -n "${UPTIME_IN_SECS}" ]; then
            UPTIME_IN_DAYS=$((UPTIME_IN_SECS / 60 / 60 / 24))
            LogText "Uptime (in seconds): ${UPTIME_IN_SECS}"
            LogText "Uptime (in days): ${UPTIME_IN_DAYS}"
            Report "uptime_in_seconds=${UPTIME_IN_SECS}"
            Report "uptime_in_days=${UPTIME_IN_DAYS}"
        else
            LogText "Result: no uptime information available"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5260
    # Description : Check single user mode for systemd
    Register --test-no BOOT-5260 --os Linux --weight L --network NO --category security --description "Check single user mode for systemd"
    if [ ${SKIPTEST} -eq 0 ]; then
        LogText "Test: Searching /usr/lib/systemd/system/rescue.service"
        if [ -f ${ROOTDIR}usr/lib/systemd/system/rescue.service ]; then
            LogText "Result: file /usr/lib/systemd/system/rescue.service"
            LogText "Test: checking presence sulogin for single user mode"
            FIND=$(${GREPBINARY} -E "^ExecStart=.*sulogin" ${ROOTDIR}usr/lib/systemd/system/rescue.service)
            if [ -n "${FIND}" ]; then
                FOUND=1
                LogText "Result: found sulogin, so single user is protected"
                AddHP 3 3
            else
                LogText "Result: did not find sulogin in rescue.service"
                AddHP 1 3
                Display --indent 2 --text "- Checking sulogin in rescue.service" --result "${STATUS_NOT_FOUND}" --color YELLOW
                ReportSuggestion "${TEST_NO}" "Protect rescue.service by using sulogin"
            fi
        else
            LogText "Result: file ${ROOTDIR}usr/lib/systemd/system/rescue.service does not exist"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5262
    # Description : Check for OpenBSD boot daemons
    Register --test-no BOOT-5262 --os OpenBSD --weight L --network NO --category security --description "Check for OpenBSD boot daemons"
    if [ ${SKIPTEST} -eq 0 ]; then
        if HasData "${RCCTLBINARY}"; then
            LogText "Result: rcctl binary found, trying that to discover information"
            # OpenBSD (Ask rcctl(8) for running daemons)
            LogText "Searching for running daemons (rcctl)"
            FIND=$(${RCCTLBINARY} ls started)
            COUNT=0
            Report "running_service_tool=rcctl"
            for ITEM in ${FIND}; do
                LogText "Found running daemon: ${ITEM}"
                Report "running_service[]=${ITEM}"
                COUNT=$((COUNT + 1 ))
            done
            LogText "Note: Run rcctl ls all | grep -E '^(pf|check_quotas|library_aslr)$' to see all daemons"
            Display --indent 2 --text "- Check running daemons (rcctl)" --result "${STATUS_DONE}" --color GREEN
            Display --indent 8 --text "Result: found ${COUNT} running daemons"
            LogText "Result: Found ${COUNT} running daemons"

            # OpenBSD (Ask rcctl(8) for enabled daemons)
            LogText "Searching for enabled daemons (rcctl)"
            FIND=$(${RCCTLBINARY} ls on | ${GREPBINARY} -E -v '^(pf|check_quotas|library_aslr)$')
            COUNT=0
            Report "boot_service_tool=rcctl"
            for ITEM in ${FIND}; do
                LogText "Found enabled daemon at boot: ${ITEM}"
                Report "boot_service[]=${ITEM}"
                COUNT=$((COUNT + 1 ))
            done
            LogText "Note: Run rcctl ls all | grep -E  '^(pf|check_quotas|library_aslr)$' to see all daemons"
            Display --indent 2 --text "- Check enabled daemons at boot (rcctl)" --result "${STATUS_DONE}" --color GREEN
            Display --indent 8 --text "Result: found ${COUNT} enabled daemons at boot"
            LogText "Result: Found ${COUNT} enabled daemons at boot"
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5263
    # Description : Check OpenBSD world writable startup scripts
    Register --test-no BOOT-5263 --os OpenBSD --weight L --network NO --category security --description "Check permissions for boot files/scripts"
    if [ ${SKIPTEST} -eq 0 ]; then
        FOUND=0
        CHECKDIR="${ROOTDIR}etc/rc.d"
        LogText "Result: checking ${ROOTDIR}etc/rc.d scripts for writable bit"
        LogText "Test: checking if directory ${DIR} exists"
        if [ -d ${CHECKDIR} ]; then
            LogText "Result: directory ${DIR} found"
            LogText "Test: checking for available files in directory"
            # OpenBSD uses symlinks to create another instance of daemons
            FIND=$(${FINDBINARY} -L ${CHECKDIR} -type f -print | ${SORTBINARY})
            if [ -n "${FIND}" ]; then
                LogText "Result: found files in directory, checking permissions now"
                for FILE in ${FIND}; do
                    LogText "Test: checking permissions of file ${FILE}"
                    ShowSymlinkPath "${FILE}"
                    if [ ${FOUNDPATH} -eq 1 ]; then
                        CHECKFILE="${SYMLINK}"
                        LogText "Result: found the path behind this symlink (${CHECKFILE} --> ${FILE})"
                    else
                        CHECKFILE="${FILE}"
                    fi
                    if IsWorldWritable ${CHECKFILE}; then
                        FOUND=1
                        LogText "Result: warning, file ${CHECKFILE} is world writable"
                    else
                        LogText "Result: good, file ${CHECKFILE} not world writable"
                    fi
                done
            else
                LogText "Result: found no files in directory."
            fi
        else
            LogText "Result: directory ${CHECKDIR} not found. Skipping.."
        fi

        # Other files
        CHECKFILES="${ROOTDIR}etc/rc ${ROOT}etc/rc.conf ${ROOT}etc/rc.conf.local ${ROOTDIR}etc/rc.local"
        for I in ${CHECKFILES}; do
            if [ -f ${I} ]; then
                ShowSymlinkPath "${I}"
                if [ ${FOUNDPATH} -eq 1 ]; then
                    CHECKFILE="${SYMLINK}"
                    LogText "Result: found the path behind this symlink (${CHECKFILE} --> ${I})"
                else
                    CHECKFILE="${I}"
                fi
                LogText "Test: Checking ${CHECKFILE} file for writable bit"
                if IsWorldWritable ${CHECKFILE}; then
                    FOUND=1
                    ReportWarning "${TEST_NO}" "Found writable startup script ${CHECKFILE}"
                    LogText "Result: warning, file ${CHECKFILE} is world writable"
                else
                    LogText "Result: good, file ${CHECKFILE} not world writable"
                fi
            fi
        done

        # Check results
        if [ ${FOUND} -eq 1 ]; then
            Display --indent 2 --text "- Check startup files (permissions)" --result "${STATUS_WARNING}" --color RED
            ReportWarning "${TEST_NO}" "Found world writable startup scripts" "-" "-"
            LogText "Result: found one or more scripts which are possibly writable by other users"
            AddHP 0 3
        else
            Display --indent 2 --text "- Check startup files (permissions)" --result "${STATUS_OK}" --color GREEN
            AddHP 3 3
        fi
    fi
#
#################################################################################
#
    # Test        : BOOT-5264
    # Description : Run systemd-analyze security
    if [ -z "${SYSTEMDANALYZEBINARY}" ]; then SKIPREASON="systemd-analyze not available"; PREQS_MET="NO";
    else
        SYSTEMD_VERSION=$("${SYSTEMDANALYZEBINARY}" --version | ${AWKBINARY} '/^systemd / {print $2}')
        if [ "${SYSTEMD_VERSION}" -ge 240 ]; then PREQS_MET="YES"; else SKIPREASON="systemd-analyze too old (v${SYSTEMD_VERSION}), need at least v240"; PREQS_MET="NO"; fi
    fi
    Register --test-no BOOT-5264 --preqs-met ${PREQS_MET} --skip-reason "${SKIPREASON}" --os Linux --weight L --network NO --category security --description "Run systemd-analyze security"
    if [ ${SKIPTEST} -eq 0 ]; then
        LogText "Test: Run systemd-analyze security"
        Display --indent 2 --text "- Running 'systemd-analyze security'"
        Display --indent 6 --text "Unit name (exposure value) and predicate"
        Display --indent 6 --text "--------------------------------"
        ${SYSTEMDANALYZEBINARY} security | while read UNIT EXPOSURE PREDICATE HAPPY; do
            if [ "${UNIT}" = "UNIT" ]; then
                continue
            fi
            STATUS="UNKNOWN"
            COLOR="BLACK"
            case ${PREDICATE} in
                PERFECT | SAFE | OK)
                    STATUS="${STATUS_PROTECTED}"
                    COLOR=GREEN
                ;;
                MEDIUM)
                    STATUS="${STATUS_MEDIUM}"
                    COLOR=WHITE
                ;;
                EXPOSED)
                    STATUS="${STATUS_EXPOSED}"
                    COLOR=YELLOW
                ;;
                UNSAFE | DANGEROUS)
                    STATUS="${STATUS_UNSAFE}"
                    COLOR=YELLOW
                ;;
            esac
            Display --indent 4 --text "- ${UNIT} (value=${EXPOSURE})" --result "${STATUS}" --color "${COLOR}"
            LogText "Result: ${UNIT} has exposure value ${EXPOSURE} with predicate '${STATUS}'"
        done
        ReportSuggestion "${TEST_NO}" "Consider hardening system services" "Run '${SYSTEMDANALYZEBINARY} security SERVICE' for each service"
    fi
#
#################################################################################
#

Report "boot_loader=${BOOT_LOADER}"
Report "boot_uefi_booted=${UEFI_BOOTED}"
Report "boot_uefi_booted_secure=${UEFI_BOOTED_SECURE}"
Report "service_manager=${SERVICE_MANAGER}"

WaitForKeyPress

#
#================================================================================
# Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com
