#!/bin/bash
# vim: cindent:shiftwidth=4:tabstop=4:smarttab:textwidth=100

#$title$ file security
#$check$ verify ownership and permissions of inodes on system volumes
#$ref$ https://wiki.debian.org/Permissions
#$author$ Rafal Rzeczkowski
#$version$ 0.8.0

level_check long

#CHANGELOG
#0.50	initial
#0.51	UID_MAX=299 to accommodate SOE4 applications
#0.52	exclude temporary editor files for $AGE_MAX days
#0.53	keep the list of bad files in $TMP file
#0.54	metadata headers
#0.55	list of non-compliant files placed directly in the help message
#0.56	exclude git files and directory from tracking
#0.57	permit non-privileged ownership of temporary mount points
#0.58	exclude active mount points
#0.59	use is_element_of() from syscheck 0.68
#0.60	exclude Perl Storable index containers used by dirtrack
#0.61	exclude .gitignore and .gitattribute
#0.62	exclude Clearcable tmp directory
#0.63	detect files where no user or group corresponds to file's numeric group ID
#0.64	detect files writable by others
#0.65	exclude /opt (non-Debian software) from permission checks
#0.66	allow /srv/tftp directory itself to also be writable by others
#0.67	exclude .gitkeep
#0.68	downgrade failure report level to caution
#0.69	ignore stats VM users during checks
#0.70	reverse broken update 0.69
#0.71	restrict spurious file search to SOE4 CLI users
#0.72	exclude /usr/local/src
#0.8.0	look for unmanaged SSL certificates

declare -r -a PROBLEMS=(INSECURE_FILE SSL_OBSOLETE_FILE)

# http://www.debian.org/doc/debian-policy/ch-opersys.html
# 0-99: Globally allocated by the Debian project
# 100-199: (SOE4) dynamically allocated system users and groups (Debian packages)
# 200-499: (SOE4) reserved
# 500-599: (SOE4) system administrators
# 600-899: (SOE4) reserved
# 900-999: (SOE4) dynamically allocated system users and groups (other packages)
declare -r -i ADM_UID_MIN=500
declare -r -i ADM_UID_MAX=599

declare -r -a FILESYSTEMs=(/ /var/log)

declare -r -a SSL_FILES=(
/etc/ssl/certs/local_CAcert.pem
/etc/ssl/certs/local_cert.pem
/etc/ssl/certs/local_combined.pem
/etc/ssl/certs/local_combined_cacert.pem
/etc/ssl/private/local_key.pem
)

MOUNTs=($(awk '{print $2}' '/proc/mounts'))

FILEs=()
while IFS= read -r -d $'\0' FILE; do
	if ! is_element_of "$FILE" ${FILESYSTEMs[*]}; then
		is_element_of "$FILE" ${MOUNTs[*]} && continue
	fi
	FILEs+=($FILE)
done < <(find ${FILESYSTEMs[*]} -xdev \( \
	\( -nogroup -o -nouser \) -o \
	\( \! -type l -perm -o=w \! \( -path '/srv/tftp' -o -path '/srv/tftp/*' -o -path '/opt/*' \) \) -o \
	\( \
	\( -uid +$(( ADM_UID_MIN - 1 )) -a -uid -$(( ADM_UID_MAX + 1 )) \) \
	-not \( -type d -a \( -path /media -o -path /mnt \) \) \
	-not \( -name '.*.swp' -a -mtime -3 \) \
	-not \( -path '*/.git' -o -path '*/.git/*' \) \
	-not \( -name '.gitignore' -o -name '.gitattributes' -o -name '.gitkeep' \) \
	-not \( -path '*/Clearcable/tmp/*' \) \
	-not \( -path '*.dirtrack.Storable' \) \
	-not \( -path '/usr/local/src/*' \) \
	\) \
\) -print0)

if [[ ${#FILEs[@]} -gt 0 ]]; then
	FILE_PLURAL=$(plural_text ${#FILEs[@]} 'file')
	fail caution "${#FILEs[@]} $FILE_PLURAL found with faulty permissions or ownership"
	helpmsg "${FILEs[@]}"
	problem INSECURE_FILE $(printf '%s;' ${FILEs[@]})
	exit
fi

if [[ ! -d '/usr/share/ssl-cert' ]]; then
	FILEs=()
	for FILE in ${SSL_FILES[@]}; do
		if [[ -f "$FILE" ]]; then
			FILEs+=($FILE)
		fi
	done

	if [[ ${#FILEs[@]} -gt 0 ]]; then
		FILE_PLURAL=$(plural_text ${#FILEs[@]} 'file')
		fail caution "${#FILEs[@]} obsolete SSL certificate $FILE_PLURAL found"
		helpmsg "${FILEs[@]}"
		problem SSL_OBSOLETE_FILE $(printf '%s;' ${FILEs[@]})
		exit
	fi
fi

ok
