#!/bin/sh

#################################################################################
#
#   Lynis
# ------------------
#
# Copyright 2007-2014, Michael Boelen (michael@rootkit.nl), The Netherlands
# Web site: http://www.rootkit.nl
#
# 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.
#
#################################################################################
#
# Time
#
#################################################################################
#
    InsertSection "Time and Synchronization"
#
#################################################################################
#
    NTP_DAEMON=""
    NTP_DAEMON_RUNNING=0
    NTP_CONFIG_FOUND=0
    NTP_CONFIG_TYPE_DAEMON=0
    NTP_CONFIG_TYPE_SCHEDULED=0
    NTP_CONFIG_TYPE_EVENTBASED=0
    NTP_CONFIG_TYPE_STARTUP=0
    # Specific for ntpd
    NTPD_RUNNING=0
    CRON_DIRS="/etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly /var/spool/crontabs"
#
#################################################################################
#
    # Test        : TIME-3104
    # Description : Check for a running NTP daemon
    if [ -f /sys/hypervisor/type ]; then
          # Skip NTP tests if we are in a DomU xen instance YYY
          FIND=`cat /sys/hypervisor/type`
          if [ "${FIND}" = "xen" ]; then PREQS_MET="NO"; else PREQS_MET="YES"; fi
        else
          PREQS_MET="YES"
    fi
    Register --test-no TIME-3104 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check for running NTP daemon or client"
    if [ ${SKIPTEST} -eq 0 ]; then
        # Linux/FreeBSD (ntpdate), OpenBSD (ntpd, rdate)
        logtext "Test: Searching for a running NTP daemon or available client... "
        FOUND=0

        # Check running processes
        FIND=`${PSBINARY} ax | grep "ntpd" | grep -v "dntpd" | grep -v "grep"`
        if [ ! "${FIND}" = "" ]; then
            FOUND=1; NTPD_RUNNING=1; NTP_DAEMON_RUNNING=1; NTP_CONFIG_TYPE_DAEMON=1
            NTP_DAEMON="ntpd"
            logtext "Result: found running NTP daemon in process list"
            Display --indent 2 --text "- Checking running NTP daemon (ntpd)..." --result FOUND --color GREEN
          else
            logtext "Result: NTP daemon not found in process list"
            Display --indent 2 --text "- Checking running NTP daemon (ntpd)..." --result "NOT FOUND" --color WHITE
        fi

        # Check time daemon (eg NetBSD)
        IsRunning timed
        if [ ${RUNNING} -eq 1 ]; then
            FOUND=1; NTP_DAEMON_RUNNING=1; NTP_CONFIG_TYPE_DAEMON=1; NTP_DAEMON="timed"
            Display --indent 2 --text "- Checking running NTP daemon (timed)..." --result FOUND --color GREEN
          else
            Display --indent 2 --text "- Checking running NTP daemon (timed)..." --result "NOT FOUND" --color WHITE
        fi

        # Check time daemon (eg DragonFly BSD)
        IsRunning dntpd
        if [ ${RUNNING} -eq 1 ]; then
            FOUND=1; NTP_DAEMON_RUNNING=1; NTP_CONFIG_TYPE_DAEMON=1; NTP_DAEMON="dntpd"
            Display --indent 2 --text "- Checking running NTP daemon (dntpd)..." --result FOUND --color GREEN
          else
            Display --indent 2 --text "- Checking running NTP daemon (dntpd)..." --result "NOT FOUND" --color WHITE
        fi

        # Check crontab for OpenBSD/FreeBSD
        # Check anacrontab for Linux
        CRONTAB_FILES="/etc/anacrontab /etc/crontab"
        for I in ${CRONTAB_FILES}; do
            if [ -f ${I} ]; then
                logtext "Test: checking for ntpdate or rdate in crontab file ${I}"
                FIND=`cat ${I} | egrep "ntpdate|rdate" | grep -v '^#'`
                if [ ! "${FIND}" = "" ]; then
                    FOUND=1;
                    NTP_CONFIG_TYPE_SCHEDULED=1
                    Display --indent 2 --text "- Checking NTP client in crontab file (${I})..." --result FOUND --color GREEN
                    logtext "Result: found ntpdate or rdate reference in crontab file ${I}"
                  else
                    Display --indent 2 --text "- Checking NTP client in crontab file (${I})..." --result "NOT FOUND" --color WHITE
                    logtext "Result: no ntpdate or rdate reference found in crontab file ${I}"
                fi
              else
                logtext "Result: crontab file ${I} not found"
          fi
        done

        ##########################
        # To do: test on Solaris #
        ##########################

        # Don't run check in cron job directory on Solaris
        # /etc/cron.d/FIFO is a special file and test get stuck at this file
        FOUND_IN_CRON=0

        # Check cron jobs
        for I in ${CRON_DIRS}; do
            if [ -d ${I} ]; then
                FIND=`ls ${I}`
                if [ ! "${FIND}" = "" ]; then
                    logtext "Test: checking for ntpdate or rdate in ${I} directory"
                    FIND2=`egrep "rdate|ntpdate" ${I}/* --exclude="FIFO" | grep -v "^#"`
                    if [ ! "${FIND2}" = "" ]; then
                        logtext "Output: ${FIND2}"
                        FOUND=1; FOUND_IN_CRON=1; NTP_CONFIG_TYPE_SCHEDULED=1
                      else
                        logtext "Result: No ntpdate/rdate found in ${I}"
                    fi
                  else
                    logtext "Result: ${I} is empty, skipping search in directory"
                fi
            fi
        done

        if [ ${FOUND_IN_CRON} -eq 1 ]; then
            Display --indent 2 --text "- Checking NTP client in cron files..." --result FOUND --color GREEN
            logtext "Result: found ntpdate or rdate in cron directory"
          else
            Display --indent 2 --text "- Checking NTP client in cron.d files..." --result "NOT FOUND" --color WHITE
            logtext "Result: no ntpdate or rdate found in cron directories"
        fi


        # Checking if ntpdate is performed by event
        logtext "Test: checking for file /etc/network/if-up.d/ntpdate"
        if [ -f /etc/network/if-up.d/ntpdate ]; then
            logtext "Result: found ntpdate action when network interface comes up"
            FOUND=1
            NTP_CONFIG_TYPE_EVENTBASED=1
            Display --indent 2 --text "- Checking event based ntpdate (if-up)..." --result FOUND --color GREEN
          else
            logtext "Result: file /etc/network/if-up.d/ntpdate does not exist"
        fi

        if [ "${OS}" = "FreeBSD" ]; then
            logtext "Test: Checking if ntpdate is enabled at startup in FreeBSD"
            if [ -f /etc/rc.conf ]; then
                FIND=`grep 'ntpdate_enable="YES"' /etc/rc.conf`
                if [ ! "${FIND}" = "" ]; then
                    logtext "Result: ntpdate is enabled in rc.conf"
                    # Mark system having a NTP client, but remind user to improve it
                    FOUND=1
                    NTP_CONFIG_TYPE_STARTUP=1
                    ReportSuggestion ${TEST_NO} "Although ntpdate is enabled in rc.conf, it is adviced to run it at least daily or use a NTP daemon"
                  else
                    logtext "Result: ntpdate is not enabled in rc.conf"
                fi
            fi
        fi

        if [ ${FOUND} -eq 0 ]; then
            Display --indent 2 --text "- Checking for a running NTP daemon or client..." --result WARNING --color RED
            logtext "Result: Could not find a NTP daemon or client"
            ReportSuggestion ${TEST_NO} "Check if any NTP daemon is running or a NTP client gets executed daily, to prevent big time differences and avoid problems with services like kerberos, authentication or logging differences."
            ReportWarning ${TEST_NO} "M" "No running NTP daemon or available client found"
            AddHP 0 2
          else
            Display --indent 2 --text "- Checking for a running NTP daemon or client..." --result OK --color GREEN
            logtext "Result: Found a time syncing daemon/client."
            AddHP 3 3
        fi
    fi
#
#################################################################################
#
    # Test        : TIME-3112
    # Description : Check for valid associations from ntpq peers list
    if [ ${NTPD_RUNNING} -eq 1 -a ! "${NTPQBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no TIME-3112 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check active NTP associations ID's"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking for NTP association ID's from ntpq peers list"
        FIND=`${NTPQBINARY} -p -n | grep "No association ID's returned"`
        if [ "${FIND}" = "" ]; then
            Display --indent 2 --text "- Checking valid association ID's..." --result FOUND --color GREEN
            logtext "Result: Found one or more association ID's"
          else
            Display --indent 2 --text "- Checking valid association ID's..." --result WARNING --color RED
            ReportSuggestion ${TEST_NO} "Check ntp.conf for properly configured NTP servers and a correctly functioning name service."
            ReportWarning ${TEST_NO} "L" "No ntp peers found"
        fi
    fi
#
#################################################################################
#
    # Test        : TIME-3116
    # Description : Check for stratum 16 peers
    if [ ${NTPD_RUNNING} -eq 1 -a ! "${NTPQBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no TIME-3116 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check peers with stratum value of 16"
    if [ ${SKIPTEST} -eq 0 ]; then
        N=0
        logtext "Test: Checking stratum 16 sources from ntpq peers list"
        FIND=`${NTPQBINARY} -p -n | awk '{ if ($3=="16") { print $1 } }'`
        if [ "${FIND}" = "" ]; then
            Display --indent 2 --text "- Checking high stratum ntp peers..." --result OK --color GREEN
            logtext "Result: All peers are lower than stratum 16"
          else
            for I in ${FIND}; do
                logtext "Found stratum 16 peer: ${I}"
                FIND2=`egrep "^ntp:ignore_stratum_16_peer:${I}:" ${PROFILE}`
                if [ "${FIND2}" = "" ]; then
                    N=`expr ${N} + 1`
                  else
                    logtext "Output: host ${I} ignored by profile"
                fi
            done
            # Check if one or more high stratum time servers are found
            if [ ${N} -eq 0 ]; then
                Display --indent 2 --text "- Checking high stratum ntp peers..." --result OK --color GREEN
                logtext "Result: all non local servers are lower than stratum 16, or whitelisted within the scan profile"
              else
                Display --indent 2 --text "- Checking high stratum ntp peers..." --result WARNING --color RED
                logtext "Result: Found one or more high stratum (16) peers)"
                ReportSuggestion ${TEST_NO} "Check ntpq peers output"
                ReportWarning ${TEST_NO} "L" "Found one or more stratum 16 peers"
            fi
        fi
    fi
#
#################################################################################
#
    # Test        : TIME-3120
    # Description : Check unreliable peers from peer list
    # Notes       : Items with # are too far away (network distance)
    #               Items with - are not chosing due clustering algoritm
    if [ ${NTPD_RUNNING} -eq 1 -a ! "${NTPQBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no TIME-3120 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check unreliable NTP peers"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking unreliable ntp peers"
        FIND=`${NTPQBINARY} -p -n | egrep "^(-|#)" | awk '{ print $1 }' | sed 's/^-//g'`
        if [ "${FIND}" = "" ]; then
            Display --indent 2 --text "- Checking unreliable ntp peers..." --result FOUND --color GREEN
            logtext "Result: No unreliable peers found"
          else
            Display --indent 2 --text "- Checking unreliable ntp peers..." --result NOTICE --color YELLOW
            logtext "Result: Found one or more unreliable peers (marked with a minus or dash sign)"
            for I in ${FIND}; do
                logtext "Unreliable peer: ${I}"
            done
            ReportSuggestion ${TEST_NO} "Check ntpq peers output for unreliable ntp peers and correct/replace them"
            #ReportWarning ${TEST_NO} "L" "Found one or more unreliable ntp peers"
        fi
    fi
#
#################################################################################
#
    # Test        : TIME-3124
    # Description : Check selected time source
    if [ ${NTPD_RUNNING} -eq 1 -a ! "${NTPQBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no TIME-3124 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check selected time source"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking selected time source"
        FIND=`${NTPQBINARY} -p -n | grep '^*' | awk '{ if ($4=="l") { print $1 } }'`
        FIND2=`${NTPQBINARY} -p -n | grep '^*' | awk '{ print $1 }'`
        if [ "${FIND}" = "" ]; then
            Display --indent 2 --text "- Checking selected time source..." --result OK --color GREEN
            FIND2=`echo ${FIND2} | sed 's/*//g'`
            logtext "Result: Found selected time source (value: ${FIND2})"
          else
            Display --indent 2 --text "- Checking selected time source..." --result WARNING --color RED
            logtext "Result: Found local source as selected time source. This could indicate that no external sources are available to sync with."
            logtext "Local source: ${FIND}"
            ReportSuggestion ${TEST_NO} "Check ntpq peers output"
            ReportWarning ${TEST_NO} "L" "Found local source as selected time source"
        fi
    fi
#
#################################################################################
#
    # Test        : TIME-3128
    # Description : Check time source candidates
    if [ ${NTPD_RUNNING} -eq 1 -a ! "${NTPQBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no TIME-3128 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check preffered time source"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking preferred time source"
        FIND=`${NTPQBINARY} -p -n | grep '^+' | awk '{ print $1 }'`
        if [ "${FIND}" = "" ]; then
            Display --indent 2 --text "- Checking time source candidates..." --result NONE --color YELLOW
            logtext "Result: No other time source candidates found"
            ReportSuggestion ${TEST_NO} "Check ntpq peers output for time source candidates"
          else
            Display --indent 2 --text "- Checking time source candidates..." --result OK --color GREEN
            logtext "Result: Found one or more candidates to synchronize time with."
                for I in ${FIND}; do
                I=`echo ${I} | sed 's/+//g'`
                logtext "Candidate found: ${I}"
            done
        fi
    fi
#
#################################################################################
#
    # Test        : TIME-3132
    # Description : Check ntpq falsetickers
    if [ ${NTPD_RUNNING} -eq 1 -a ! "${NTPQBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no TIME-3132 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check NTP falsetickers"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking preferred time source"
        FIND=`${NTPQBINARY} -p -n | grep '^x'`
        if [ "${FIND}" = "" ]; then
            Display --indent 2 --text "- Checking falsetickers..." --result OK --color GREEN
            logtext "Result: No falsetickers found (items preceeding with an 'x')"
          else
            Display --indent 2 --text "- Checking falsetickers..." --result NONE --color YELLOW
            logtext "Result: Found one or more falsetickers  (items preceeding with an 'x')"
            for I in ${FIND}; do
                I=`echo ${I} | sed 's/x//g'`
                echo "Falseticker found: ${I}"
            done
            ReportSuggestion ${TEST_NO} "Check ntpq peers output for falsetickers"
            ReportWarning ${TEST_NO} "L" "Found one or more falsetickers in NTP peers list"
        fi
    fi
#
#################################################################################
#
    # Test        : TIME-3136
    # Description : Check ntpq reported ntp version (Linux)
    # Notes       : Test could be improved by checking every host (YYY)
    if [ ${NTPD_RUNNING} -eq 1 -a ! "${NTPQBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no TIME-3136 --os Linux --preqs-met ${PREQS_MET} --weight L --network NO --description "Check NTP protocol version"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking NTP protocol version (ntpq -c ntpversion)"
        FIND=`${NTPQBINARY} -c ntpversion | awk '{ if ($1=="NTP" && $2=="version" && $5=="is") { print $6 } }'`
        if [ "${FIND}" = "" ]; then
            Display --indent 2 --text "- Checking NTP version..." --result UNKNOWN --color YELLOW
            logtext "Result: No NTP version found"
          else
            Display --indent 2 --text "- Checking NTP version..." --result FOUND --color GREEN
            logtext "Result: Found NTP version ${FIND}"
            report "ntp_version=${FIND}"
        fi
    fi
#
#################################################################################
#
    # Test        : TIME-3146
    # Description : Check /etc/default/ntpdate (Linux)
    # Notes       : ntpdate-debian binary
    #if [ ${NTPD_RUNNING} -eq 1 -a ! "${NTPQBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    #Register --test-no TIME-3146 --os Linux --preqs-met ${PREQS_MET} --weight L --network NO --description "Check /etc/default/ntpdate"
    #if [ ${SKIPTEST} -eq 0 ]; then
#
#################################################################################
#

wait_for_keypress

#
#################################################################################
#


report "ntp_config_found=${NTP_CONFIG_FOUND}"
report "ntp_config_type_daemon=${NTP_CONFIG_TYPE_DAEMON}"
report "ntp_config_type_eventbased=${NTP_CONFIG_TYPE_EVENTBASED}"
report "ntp_config_type_scheduled=${NTP_CONFIG_TYPE_SCHEDULED}"
report "ntp_config_type_startup=${NTP_CONFIG_TYPE_STARTUP}"
report "ntp_daemon=${NTP_DAEMON}"
report "ntp_daemon_running=${NTP_DAEMON_RUNNING}"




    # OS        Time daemons  Configuration file
    # --------------------------------------------
    # AIX       xntpd         /etc/ntp.conf
    # HP
    # Linux     ntpd          /etc/ntp.conf
    # OpenBSD   ntpd          /etc/ntpd.conf
    # Solaris   xntpd         /etc/inet/ntp.conf

#
#================================================================================
# Lynis - Copyright 2007-2014, Michael Boelen - www.rootkit.nl - The Netherlands
