#!/bin/sh

#################################################################################
#
#   Lynis
# ------------------
#
# Copyright 2007-2008, 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.
#
#################################################################################
#
# User, Group and authentication tests
#
#################################################################################
#
    # Possible locations of sudoers file
    SUDOERS_LOCATIONS="/etc/sudoers /usr/local/etc/sudoers"
#
#################################################################################
#
    InsertSection "Users, Groups and Authentication"

    # Test        : AUTH-9204
    # Description : Check users with UID zero (0)
    Register --test-no AUTH-9204 --weight L --network NO --description "Check users with an UID of zero"
    if [ ${SKIPTEST} -eq 0 ]; then
        # Search accounts with UID 0
        logtext "Test: Searching accounts with UID 0"
	FIND=`grep ':0:' /etc/passwd | egrep -v '^#|^root:|^:0:0:::' | cut -d ":" -f1,3 | grep ':0'`
        if [ ! "${FIND}" = "" ]; then
	    Display --indent 2 --text "- Search administrator accounts..." --result WARNING --color RED
	    logtext "Result: Found more than one administrator accounts"
	    ReportWarning "${TEST_NO}" "H" "Multiple users with UID 0 found in passwd file"
	    for I in ${FIND}; do
	      logtext "Administrator account: ${I}"
	    done
	    if [ "${OS}" = "FreeBSD" ]; then
	        logtext "FreeBSD note: default there is a user 'toor' installed. This account is considered useless unless it"
		logtext "is assigned a password and used for daily operations or emergencies. ie: bad shell for root user."
		ReportSuggestion ${TEST_NO} "Use vipw to delete the 'toor' user if not used."
    	    fi
          else
	    Display --indent 2 --text "- Search administrator accounts..." --result OK --color GREEN
	    logtext "Result: No accounts found with UID 0 other than root."
        fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9208
    # Description : Check non unique accounts
    Register --test-no AUTH-9208 --os FreeBSD --weight L --network NO --description "Check non unique accounts"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: ${USER_PASSWD_DOUBLEUID_AUDIT_TITLE}"
        logtext "Description: ${USER_PASSWD_DOUBLEUID_AUDIT_DESCRIPTION}"
        logtext "Action: Checking for non unique accounts"
    
        # Check master.passwd
        if [ -f /etc/master.passwd ]; then
	    FIND=`cat /etc/master.passwd | grep -v '^#' | cut -d ':' -f3 | uniq -d`
	    if [ "${FIND}" = "" ]; then
		Display --indent 2 --text "- Checking UIDs... " --result OK --color GREEN
		logtext "Result: all accounts found in /etc/master.passwd are unique"
	      else
	        Display --indent 2 --text "- Checking UIDs... " --result WARNING --color RED
		logtext "Result: found multiple accounts with same UID"
    	        logtext "Output (non unique UIDs): ${FIND}"
	        logtext "Impact: HIGH"
	        ReportWarning ${TEST_NO} "H" "Multiple accounts found with same UID"
            fi
	  else
	    Display --indent 2 --text "- Checking UIDs... " --result SKIPPED --color WHITE
	    logtext "Result: test skipped, /etc/master.passwd file not available"
        fi
        logtext "Remarks: ${USER_PASSWD_DOUBLEUID_AUDIT_TEXT}"
    fi
#
#################################################################################
#
    # Test        : AUTH-9212
    # Description : Test group file with chkgrp tool (ie FreeBSD)
    if [ -f /usr/sbin/chkgrp ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no AUTH-9212 --preqs-met ${PREQS_MET} --weight L --network NO --description "Test group file"
    if [ ${SKIPTEST} -eq 0 ]; then
    	Display --indent 2 --text "- Checking chkgrp tool..." --result FOUND --color GREEN
	logtext "Result: /usr/sbin/chkgrp binary found. Using this to perform next test(s)."
	logtext "Test: Testing consistency of /etc/group file... "
	FIND=`/usr/sbin/chkgrp | grep -v 'is fine'`
	if [ "${FIND}" = "" ]; then
	    Display --indent 4 --text "- Consistency check /etc/group file..." --result OK --color GREEN
	    logtext "Result: chkgrp test performed, Group file seems to be ok."
	  else
	    Display --indent 4 --text "- Consistency check /etc/group file..." --result WARNING --color RED
	    logtext "Result: chkgrp found some errors. Run the tool manually to see details."
	    logtext "chkgrp output: ${FIND}"
	    ReportWarning ${TEST_NO} "M" "chkgrp reported inconsistencies in /etc/group file"
	fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9216
    # Description : Check /etc/group and shadow group files
    if [ ! "${GRPCKBINARY}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no AUTH-9216 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check group and shadow group files"
    if [ ${SKIPTEST} -eq 0 ]; then
	# Test            : run grpck to test group files (most likely /etc/group and shadow group files)
        # Expected result : 0 (exit code)
        logtext "Test: Checking for grpck binary..."

	if [ "${OS}" = "Linux" ]; then
	    # Read only mode
	    FIND=`${GRPCKBINARY} -r 2> /dev/null ; echo $?`
	  elif [ "${OS}" = "AIX" ]; then
	    FIND=`${GRPCKBINARY} -n 2> /dev/null ; echo $?`
	  else
	    FIND=`${GRPCKBINARY} 2> /dev/null ; echo $?`
	fi
	
	# Overrule for SuSE
	if [ "${LINUX_VERSION}" = "SuSE" ]; then
	    FIND=`${GRPCKBINARY} -q -r > /dev/null ; echo $?`	
	fi
	
	# Check exit-code
	if [ "${FIND}" = "0" ]; then
	    Display --indent 2 --text "- Test group files (grpck)..." --result OK --color GREEN
	    logtext "Result: grpck binary didn't find any errors in the group files"
	  else
	    Display --indent 2 --text "- Test group files (grpck)..." --result WARNING --color RED
	    ReportWarning ${TEST_NO} "M" "grpck binary found errors in one or more group files"
	    ReportSuggestion ${TEST_NO} "Run grpck manually and check your group files"
	fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9218
    # Description : Check login shells
    Register --test-no AUTH-9218 --os FreeBSD --weight L --network NO --description "Check harmful login shells"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking login shells"
	if [ -f /etc/master.passwd ]; then
	    # Check for all shells, except: /sbin/nologin
	    FIND=`cat /etc/master.passwd | grep "[a-z]:\*:" | egrep -v '^#|/sbin/nologin|/nonexistent'`
	    if [ "${FIND}" = "" ]; then
	        Display --indent 2 --text "- Checking login shells..." --result OK --color GREEN
	      else
    		Display --indent 2 --text "- Checking login shells..." --result WARNING --color RED
		logtext "Output: ${FIND}"
		ReportWarning ${TEST_NO} "H" "Possible harmful shell found (for passwordless account!)"
             fi
          else
	    Display --indent 2 --text "- Checking login shells..." --result SKIPPED --color WHITE
	    logtext "Result: No /etc/master.passwd file found"
	fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9222
    # Description : Check for non unique groups
    Register --test-no AUTH-9222 --weight L --network NO --description "Check for non unique groups"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking for non unique group ID's in /etc/group"
	FIND=`awk -F: '{ print $3 }' /etc/group | grep -v '^#' | sort | uniq -d`
        if [ "${FIND}" = "" ]; then	
	    Display --indent 2 --text "- Checking non unique group ID's..." --result OK --color GREEN
	    logtext "Result: All group ID's are unique"
	  else
	    Display --indent 2 --text "- Checking non unique group ID's..." --result WARNING --color WARNING
	    logtext "Result: Found the same group ID multiple times"
	    logtext "Output: ${FIND}"
	    ReportSuggestion ${TEST_NO} "Check your /etc/group file and correct inconsistencies"
	    ReportWarning ${TEST_NO} "H" "Found multiple groups with same group ID"
        fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9226
    # Description : Check non unique group names
    if [ -f /etc/group ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no AUTH-9226 --preqs-met ${PREQS_MET} --weight L --network NO --description "Check non unique group names"
    if [ ${SKIPTEST} -eq 0 ]; then
        logtext "Test: Checking for non unique group names in /etc/group"
	FIND=`awk -F: '{ print $1 }' /etc/group | grep -v '^#' | sort | uniq -d`
	if [ "${FIND}" = "" ]; then
	    Display --indent 2 --text "- Checking non unique group names..." --result OK --color GREEN
	    logtext "Result: All group names are unique"
          else
      	    Display --indent 2 --text "- Checking non unique group names..." --result WARNING --color WARNING
	    logtext "Result: Found the same group name multiple times"
    	    logtext "Output: ${FIND}"
	    ReportWarning ${TEST_NO} "M" "Found inconsistencies in group file (multiple occurences of a single group)"
	    ReportSuggestion ${TEST_NO} "Check your /etc/group file and correct inconsistencies"
        fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9230
    # Description : Check password file consistency
    if [ -x /usr/sbin/pwck ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no AUTH-9230 --os SunOS --preqs-met ${PREQS_MET} --weight L --network NO --description "Check password file consistency"
    if [ ${SKIPTEST} -eq 0 ]; then
	logtext "Test: Checking password file consistency (pwck)"
	FIND=`/usr/sbin/pwck 2> /dev/null; echo $?`
	if [ "${FIND}" = "0" ]; then
	    Display --indent 2 --text "- Checking password file consistency..." --result OK --color GREEN
	    logtext "Result: pwck finished didn't find problems"
	  else
	    Display --indent 2 --text "- Checking password file consistency..." --result WARNING --color RED
            logtext "Result: pwck found one or more errors/warnings in the password file."
	    ReportWarning ${TEST_NO} "M" "pwck found one or more errors/warnings in the password file"
	    ReportSuggestion ${TEST_NO} "Run pwck manually and correct found issues."
	fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9234
    # Description : Query user accounts
    # More info   : HPUX > 100
    #               MacOS: need to be improved (just reading passwd file is not enough)
    #               OpenBSD/NetBSD: unknown
    Register --test-no AUTH-9234 --os Linux --weight L --network NO --description "Query user accounts"
    if [ ${SKIPTEST} -eq 0 ]; then
	Display --indent 2 --text "- Query system users (non daemons)..."
        logtext "Test: Read real system users from /etc/passwd..."
        FIND=""
    
        if [ "${OS}" = "FreeBSD" ]; then
          logtext "FreeBSD real users output (ID > 1000, but not 65534):"
          FIND=`awk -F: '($3 > 1000) && ($3 != 65534) || ($3 == 0) { print $1","$3 }' /etc/passwd`
        fi

        if [ "${OS}" = "Linux" ]; then
          logtext "Linux real users output (ID > 500, but not 65534):"
          FIND=`awk -F: '($3 > 500) && ($3 != 65534) || ($3 == 0) { print $1","$3 }' /etc/passwd`
        fi

        if [ "${OS}" = "SunOS" ]; then
          logtext "Solaris real users output (ID > 100, but not 60001/65534):"
          FIND=`awk -F: '($3 > 100 && $3 != 60001 && $3 != 65534) || ($3 == 0) { print $1","$3 }' /etc/passwd`
        fi

        # Check if we got any output
        if [ "${FIND}" = "" ]; then
            Display --indent 4 --text "Result: No users found/unknown result"
            logtext "Result: Querying of system users skipped"
          else
            for I in ${FIND}; do
              logtext "Real user: ${I}"
              report "real_user[]=${I}"
            done
        fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9238
    # Description : Query LDAP authentication support
    if [ -f /etc/nsswitch.conf ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no AUTH-9238 --preqs-met ${PREQS_MET} --weight L --network NO --description "Query LDAP authentication support"
    if [ ${SKIPTEST} -eq 0 ]; then
	FIND=`egrep "^passwd" /etc/nsswitch.conf | grep "ldap"`
	if [ "${FIND}" = "" ]; then
	    logtext "Result: LDAP authentication not enabled"
	    Display --indent 2 --text "- Checking LDAP authentication support" --result "NOT ENABLED" --color WHITE
	  else
	    Display --indent 2 --text "- Checking LDAP authentication support" --result "ENABLED" --color GREEN
	    logtext "Result: LDAP authentication enabled"
	    logtext "Test: checking /etc/ldap/ldap.conf"
	    if [ -f /etc/ldap/ldap.conf ]; then
	        logtext "Result: /etc/ldap/ldap.conf exists"
		FIND2=`egrep "^host " /etc/ldap/ldap.conf | awk '{ print $2 }'`
		for I in ${FIND2}; do
		    Display --indent 6 --text "LDAP server: ${I}"
		    logtext "Result: found LDAP server ${I}"
		    # YYY check if host(s) are reachable/respond to queries
		done
	      else
	        logtext "Result: /etc/ldap/ldap.conf does NOT exist"
	    fi
	fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9240
    # Description : Query NIS+ authentication support
    Register --test-no AUTH-9240 --weight L --network NO --description "Query NIS+ authentication support"
    if [ ${SKIPTEST} -eq 0 ]; then
	FIND=`egrep "^passwd" /etc/nsswitch.conf | egrep "compat|nisplus"`
	if [ "${FIND}" = "" ]; then
	    logtext "Result: NIS+ authentication not enabled"
	    Display --indent 2 --text "- Checking NIS+ authentication support" --result "NOT ENABLED" --color WHITE
	  else
	    FIND2=`egrep "^passwd_compat" /etc/nsswitch.conf | grep "nisplus"`
	    FIND3=`egrep "^passwd" /etc/nsswitch.conf | grep "nisplus"`
	    if [ ! "${FIND2}" = "" -o ! "${FIND3}" = "" ]; then
	        logtext "Result: NIS+ authentication enabled"
		Display --indent 2 --text "- Checking NIS+ authentication support" --result "ENABLED" --color GREEN
	      else
	        logtext "Result: NIS+ authentication not enabled"
	        Display --indent 2 --text "- Checking NIS+ authentication support" --result "NOT ENABLED" --color WHITE
	    fi
	fi      
    fi
#
#################################################################################
#
    # Test        : AUTH-9242
    # Description : Query NIS authentication support
    Register --test-no AUTH-9242 --weight L --network NO --description "Query NIS authentication support"
    if [ ${SKIPTEST} -eq 0 ]; then
	FIND=`egrep "^passwd" /etc/nsswitch.conf | egrep "compat|nis" | grep -v "nisplus"`
	if [ "${FIND}" = "" ]; then
	    logtext "Result: NIS authentication not enabled"
	    Display --indent 2 --text "- Checking NIS authentication support" --result "NOT ENABLED" --color WHITE
	  else
	    FIND2=`egrep "^passwd_compat" /etc/nsswitch.conf | grep "nis" | grep -v "nisplus"`
	    FIND3=`egrep "^passwd" /etc/nsswitch.conf | grep "nis" | grep -v "nisplus"`
	    if [ ! "${FIND2}" = "" -o ! "${FIND3}" = "" ]; then
	        logtext "Result: NIS authentication enabled"
		Display --indent 2 --text "- Checking NIS authentication support" --result "ENABLED" --color GREEN
	      else
	        logtext "Result: NIS authentication not enabled"
	        Display --indent 2 --text "- Checking NIS authentication support" --result "NOT ENABLED" --color WHITE
	    fi
	fi      
    fi
#
#################################################################################
#
    # Test        : AUTH-9244
    # Description : Query NIS servers
    #Register --test-no AUTH-9244 --weight L --network NO --description "Query NIS servers"
    #if [ ${SKIPTEST} -eq 0 ]; then
    #fi
#
#################################################################################
#
    # Test        : AUTH-9246
    # Description : Query NIS active
    #Register --test-no AUTH-9246 --weight L --network NO --description "Query active NIS servers"
    #if [ ${SKIPTEST} -eq 0 ]; then
    #if
    #grep '^+' /etc/passwd /etc/group
#
#################################################################################
#
    # Test        : AUTH-9250
    # Description : Check for sudoers file
    Register --test-no AUTH-9250 --weight L --network NO --description "Check sudoers file"
    if [ ${SKIPTEST} -eq 0 ]; then
        FOUND=0
        for I in ${SUDOERS_LOCATIONS}; do
	    logtext "Test: checking presence ${I}"
	    if [ -f ${I} ]; then FOUND=1; fi
	done
	if [ ${FOUND} -eq 1 ]; then
	    logtext "Result: sudoers file found (${I})"
	    Display --indent 2 --text "- Check sudoers file" --result FOUND --color GREEN
	    # YYY add more tests to audit sudoers file
	  else
	    logtext "Result: sudoers file NOT found"
	    Display --indent 2 --text "- Check sudoers file" --result "NOT FOUND" --color YELLOW
        fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9254
    # Description : Solaris test to check passwordless accounts
    Register --test-no AUTH-9254 --os SunOS --weight L --network NO --description "Solaris passwordless accounts"
    if [ ${SKIPTEST} -eq 0 ]; then
	FIND=`logins -p | awk '{ print $1 }'`
	if [ "${FIND}" = "" ]; then
	    logtext "Result: no passwordless accounts found"
	    Display --indent 2 --text "- Checking passwordless accounts on Solaris" --result OK --color GREEN
	  else	    	
	    for I in ${FIND}; do
		warning ${TEST_NO} "H" "Found passwordless account (${I})"
	    done
	fi
    fi
#
#################################################################################
#
    # Test        : AUTH-9258
    # Description : login.access checks
    #Register --test-no AUTH-9258 --weight L --network NO --description "login.access checks"
#
#################################################################################
#
    # Test        : AUTH-9262
    # Description : Search for PAM password strength testing libraries
    if [ -d /lib/security ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
    Register --test-no AUTH-9262 --preqs-met ${PREQS_MET} --weight L --network NO --description "Checking presence password strength testing tools (PAM)"
    if [ ${SKIPTEST} -eq 0 ]; then
        FOUND=0
	logtext "Result: /lib/security exists"	
	if [ -f /lib/security/pam_cracklib.so ]; then
	    FOUND=1
	    logtext "Result: found pam_cracklib.so (crack library PAM)"
	  else
	    logtext "Result: pam_cracklib.so NOT found (crack library PAM)"
	fi	

	if [ -f /lib/security/pam_passwdqc.so ]; then
	    FOUND=1
	    logtext "Result: found pam_passwdqc.so (passwd quality control PAM)"
	  else
	    logtext "Result: pam_passwdqc.so NOT found (passwd quality control PAM)"
	fi	
	
	if [ ${FOUND} -eq 0 ]; then
	    Display --indent 2 --text "- Checking PAM password strength tools" --result "SUGGESTION" --color YELLOW
	    logtext "Result: no PAM modules for password strength testing found"
	    ReportSuggestion ${TEST_NO} "Install a PAM module for password strength testing like pam_cracklib"
	  else	    	
	    Display --indent 2 --text "- Checking PAM password strength tools" --result OK --color GREEN
	    logtext "Result: found at least one PAM module for password strength testing"
	fi
      else
        logtext "Result: /lib/security not found, tests skipped"
    fi
#
#################################################################################
#
    # Test        : AUTH-9282
    # Description : Search password protected accounts without expire (Linux)
    Register --test-no AUTH-9282 --os Linux --weight L --network NO --description "Checking password protected account without expire date"
    if [ ${SKIPTEST} -eq 0 ]; then
	FIND=`passwd --all --status | awk '{ if ($2=="P" && $5=="99999") print $1 }'`
	if [ "${FIND}" = "" ]; then
	    Display --indent 2 --text "- Checking accounts without expire date" --result OK --color GREEN
	    logtext "Result: no accounts found without an expire date"
	  else
	    for I in ${FIND}; do
	      logtext "Account without expire date: ${I}"
	    done
	    Display --indent 2 --text "- Checking accounts without expire date" --result SUGGESTION --color YELLOW
	    ReportSuggestion ${TEST_NO} "When possible set expire dates for all password protected accounts"
	fi
    fi
#
#################################################################################
#

wait_for_keypress

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