File selinux-ready of Package libselinux

#!/bin/bash

KERNEL="unknown"
INITRD="unknown"
TD=""


# init needs /selinux to be there
check_dir()
{
	SLDIRS="/selinux /sys/fs/selinux"
	FOUND="no"

	for DIR in $SLDIRS; do
		if [ -d $DIR ]; then
			printf "\tcheck_dir: OK. $DIR exists.\n"
			FOUND="yes"
		fi
	done

	if [ $FOUND == "yes" ]; then
		return 0
	else
		printf "\tcheck_dir: ERR. Neither of $SLDIRS does exist. Please execute 'mkdir /sys/fs/selinux' as root\n"
		return 1
	fi
}

check_filesystem()
{
	FSPATH="/proc/filesystems"
	FSNAMES="securityfs selinuxfs"
	OK="O"

	for FSNAME in $FSNAMES; do
		grep -w $FSNAME $FSPATH 1>&2 >/dev/null

		if [ $? == 0 ]; then
			printf "\tcheck_filesystem: OK. Filesystem '$FSNAME' exists.\n"
		else
			printf "\tcheck_filesystem: ERR. Filesystem '$FSNAME' is missing. Please enable SELinux while compiling the kernel.\n"
			OK="1"
		fi
	done
	if [ "$OK" == "0" ]; then
		return 0;
	else
		return 1;
	fi
}

check_boot()
{
	BPARAM1="security=selinux"
	BPARAM2="selinux=1"

	printf "\tcheck_boot: Assuming GRUB2 as bootloader.\n"

	# look for parameters of the current kernel
	CURRENT_KERNEL=$(uname -r)
	OTHERS=""
	RETVAL="FAIL"
	while read BLINE
	do
		K=$(echo $BLINE | awk -F' ' '{print $2}')
		KERNEL=$(basename $K)
		K=$(echo $KERNEL | sed s/vmlinuz-//)

		if [ "$K" == "$CURRENT_KERNEL" ]; then
			INITRD=initrd-$K
			RETVAL="OK"
		else
			OTHERS="$KERNEL $OTHERS"
		fi
	done < <(grep -- $BPARAM1 /boot/grub2/grub.cfg 2>/dev/null | grep -- $BPARAM2)

	if [ "$RETVAL" == OK ]; then
		printf "\tcheck_boot: OK. Current kernel '$KERNEL' has boot-parameters '$BPARAM1 $BPARAM2'\n"
		printf "\tcheck_boot: OK. Other kernels with correct parameters: $OTHERS\n"
		return 0
	else
		printf "\tcheck_boot: ERR. Boot-parameter missing for booting the kernel.\n"
		printf "\t            Please use YaST2 to add 'security=selinux selinux=1' to the kernel boot-parameter list.\n"
		return 1
	fi
}

check_mkinitrd()
{
	if [ "$INITRD" == "unknown" ]; then
		return 1
	fi
	MCMD="mount.*/root/proc.*"

	if ! [ -f "/boot/$INITRD" ];then
		printf "\tcheck_mkinitrd: ERR. Unable to locate '/boot/$INITRD'\n"
		return 2
	fi

	cp /boot/$INITRD $TD/ 2>/dev/null

	if ! [ -f "$TD/$INITRD" ];then
		printf "\tcheck_mkinitrd: ERR. Error while copying initrd file.'\n"
		return 2
	fi


	pushd . 2>&1>/dev/null
	cd $TD
	mkdir initrd-extracted
	cd initrd-extracted
	INITRD_FORMAT=$(file $TD/$INITRD | awk -F' ' '{print $2}')
  case $INITRD_FORMAT in
  'XZ' )
    xz -d -c $TD/$INITRD | cpio -i --force-local --no-absolute-filenames 2>/dev/null ;;
  'ASCII' )
    /usr/lib/dracut/skipcpio $TD/$INITRD | xz -d | cpio -i --force-local --no-absolute-filenames 2>/dev/null ;;
  'gzip' )
    gzip -d -c $TD/$INITRD | cpio -i --force-local --no-absolute-filenames 2>/dev/null ;;
  * )
		printf "\tcheck_mkinitrd: ERR. Error while extracting initrd file.'\n"
    return 2
  esac
  if [ -d boot ]; then 
    grep -E -- $MCMD boot/* 2>&1 >/dev/null
    FLG1=$?
    grep -E -- load_policy boot/* 2>&1 >/dev/null
    FLG2=$?
  else
    # looks like we're using dracut/systemd. We can only check if libselinux1
    # exists
    if [ -f lib64/libselinux.so.1 ]; then
      # if this exists 
      FLG1=0
      FLG2=0
    fi
  fi
	popd 2>&1>/dev/null

	if [ $FLG1 == 0 -a $FLG2 == 0 ];then
		printf "\tcheck_mkinitrd: OK. Your initrd seems to be correct.\n"
		return 0
	else
		printf "\tcheck_mkinitrd: ERR. Your initrd seems not to mount /proc of\n"
		printf "\t                the root filesystem during boot and/or load_policy\n"
		printf "\t                is missing,\n"
		printf "\t                this may be a reason for SELinux not working.\n"
		return 1
	fi
}

check_pam()
{
	AA_PAM=0
	SE_PAM=0

	# test for AA pam module
	grep apparmor /etc/pam.d/* 2>&1 >/dev/null
	FLG=$?
	if [ $FLG == 0 ]; then
		AA_PAM=1
	fi

	# test for SELinux pam module
	grep selinux /etc/pam.d/* 2>&1 >/dev/null
	FLG=$?
	if [ $FLG == 0 ]; then
		SE_PAM=1
	fi

	# suggest config
	if [ $SE_PAM == 1 ] && [ $AA_PAM == 0 ]; then
		printf "\tcheck_pam: OK. Your PAM configuration seems to be correct.\n"
		return 0
	fi
		printf "\tcheck_pam: ERR. Your PAM configuration seems to be incorrect.\n"
	if [ $AA_PAM == 1 ]; then
		printf "             execute 'pam-config -d --apparmor' as root\n"
	fi
	if [ $SE_PAM == 0 ]; then
		printf "             execute 'pam-config -a --selinux' as root\n"
	fi

	return 1
}

check_initupstart()
{
	CFGFILE="/etc/selinux/config"

	if ! [ -f $CFGFILE ]; then
		printf "\tcheck_initupstart: ERR. $CFGFILE does not exist.\n"
		return 1;
	fi
}

check_runlevel()
{
	if [ "$(systemctl is-enabled restorecond.service)" == "enabled" ]; then
		printf "\tcheck_runlevel: OK. restorecond is enabled on your system\n"
		return 0;
	fi
	printf "\tcheck_runlevel: ERR. please execute 'yast2 runlevel' and enable restorecond.\n"
	return 1
}

check_packages()
{
	PKGLST="checkpolicy policycoreutils selinux-tools libselinux1 libsepol1 libsemanage1 selinux-policy"
	FAIL=0

	for i in $PKGLST
	do
		rpm -q $i 1>&2 >/dev/null
		if [ $? == 1 ];then
			printf "\tcheck_packages: ERR. Package '$i' not installed, please run 'zypper in $i' as root\n"
			FAIL=1
		fi
	done

	if [ $FAIL == 0 ]; then
		printf "\tcheck_packages: OK. All essential packages are installed\n"
		return 0
	else
		return 1
	fi
}

check_config()
{
	CF="/etc/selinux/config"

	if [ -f $CF ];then
		printf "\tcheck_config: OK. Config file seems to be there.\n"
		# with -L because /etc/selinux/config is now a link to /etc/sysconfig/selinux-policy
		if ! [ $(stat -L --printf=%a $CF) -eq "644" ]; then
			printf "\tcheck_config: ERR. Config file '$CF' has wrong permissions.\n"
			return 1
		fi

		# check that SELINUX is not disabled there
	        SELINUX_MODE=$(grep "^\s*SELINUX\s*=" $CF | sed "s/SELINUX\s*=\(\S*\)\s*"/\\1/)
		case "$SELINUX_MODE" in
			permissive | enforcing )
				printf "\tcheck_config: OK. SELINUX is set to '$SELINUX_MODE'.\n"
				return 0
				;;
			* )
				printf "\tcheck_config: ERR. SELINUX is set to '$SELINUX_MODE' in '$CF'. Should be either 'permissive' or 'enforcing'\n"
				return 1
				;;
		esac
	else
		printf "\tcheck_config: ERR. Config file '$CF' is missing.\n"
		return 1
	fi
}

TD=$(mktemp -q -d /tmp/selinux-ready.XXXXXX)

echo "Start checking your system if it is selinux-ready or not:"
check_dir
check_filesystem
check_boot
check_mkinitrd
check_packages
check_config
check_initupstart
check_pam
check_runlevel

rm -rf $TD
openSUSE Build Service is sponsored by