#!/bin/sh

#
# (c) spd_at_daphne.cps.unizar.es
# Mon Apr 18 11:47:53 MEST 2005
# Thu Oct  5 13:33:49 MEST 2006 /root/ -> $TMPDIR
# Thu Oct 16 13:43:57 MEST 2008 - speed up, better cred checking
# License: Cantoware - Si te gusta ya te puedes dar con un canto en los dientes
#
# This script will check for sanity and consistency of NIS+ databases.
# Needs: root privileges
# Use: run without arguments
#


DOMAIN=`domainname`


trap "onexit" 0 1 2 3 15

TMPDIR=/tmp/nischk.$$

umask 077
set -e
mkdir $TMPDIR
set +e

ECHO=/usr/bin/echo
DO=

usage()
{
	echo "Use: `basename $0` [-hq]"
	echo "-q: quiet"
}


set -- `getopt hqn $*`
for i in $*
do
	case $i in
	-q) ECHO=:; shift;;
	-n) DO=echo; shift;;
	-h)
		usage
		exit 0
		;;
	esac
done


onexit()
{
	rm -f $TMPDIR/passwd
	rm -f $TMPDIR/shadow
	rm -f $TMPDIR/group
	rm -f $TMPDIR/uids
	rm -f $TMPDIR/uids_u
	rm -f $TMPDIR/unames
	rm -f $TMPDIR/unames-uids
	rm -f $TMPDIR/cred_local
	rm -f $TMPDIR/cred_des
	rm -f $TMPDIR/cred_des_in
	rm -f $TMPDIR/hosts
	rm -f $TMPDIR/home
	test -d $TMPDIR && rmdir $TMPDIR
}
###########################################################################
if egrep -s '^passwd.*ldap' /etc/nsswitch.conf
then
    [ ! "$LDAP_PASSWD" ] && \
    ( echo "LDAP Credentials must be provided" ; exit 1)
    LDAP=true
    NISPLUS=false
    USE_FILES=false
    HPREFIX=/home
    $ECHO "\\n#####" Using LDAP database
    if [ -f /etc/krb5/krb5.conf ]
    then
        USE_KERBEROS=true
        $ECHO "\\n#####" Using Kerberos
    fi
elif egrep -s '^passwd.*nisplus' /etc/nsswitch.conf
then
    LDAP=false
    NISPLUS=true
    USE_FILES=false
    HPREFIX=/home
    $ECHO "\\n#####" Using NIS+ database
elif test -f /var/run/lookupd.pid
then
    LDAP=false
    NISPLUS=false
    NETINFO=true
    USE_FILES=false
    HPREFIX=/Users
    $ECHO "\\n#####" Using NetINFO on MacOS X
else
    LDAP=false
    NISPLUS=false
    $ECHO "\\n#####" Using files database
fi
###########################################################################
if $NISPLUS
then
	echo "####"
	echo "# check for NIS+ entries with excessive permissions..."

	niscat -o '[]passwd.org_dir' | nawk '

	function readNlines(n)
	{
		for (i = n; i > 0; i--)
		getline
	}

	/Access.+ ....rmcd/ {
		readNlines(6)
		print substr($5, 2, length($5) - 2)
	}

	' D=$DOMAIN

	echo "# done"
fi

echo "####"
echo "# check for incorrect passwd.org_dir entries"

: > $TMPDIR/passwd
: > $TMPDIR/shadow
: > $TMPDIR/group
chmod 600 $TMPDIR/passwd $TMPDIR/group $TMPDIR/shadow

if $NISPLUS
then
    nisaddent -d passwd > $TMPDIR/passwd
    nisaddent -d shadow > $TMPDIR/shadow
    niscat group.org_dir > $TMPDIR/group
elif $LDAP
then
	echo "WARNING: half implemented"
	ldapaddent -d passwd > $TMPDIR/passwd
	ldapaddent -d shadow > $TMPDIR/shadow
	ldapaddent -d group > $TMPDIR/passwd
else
    cat /etc/passwd > $TMPDIR/passwd
    cat /etc/shadow > $TMPDIR/shadow
    cat /etc/group > $TMPDIR/group
fi


#cat $TMPDIR/passwd | egrep -v -e \
#'^[a-z][a-z0-9]*:.[^:]*:[0-9][0-9]*:[0-9][0-9]*:.[^:]*:/.[^:]*:/bin/[^:]*sh:[-]*[0-9]*:[-]*[0-9]*:[-]*[0-9]*:[-]*[0-9]*:[-]*[0-9]*:[-]*[0-9]*:[0-9]*'
#
echo "# check for incorrect passwd entries"
cat $TMPDIR/passwd | egrep -v -e \
'^[a-z][a-z0-9_-]*:.[^:]*:[0-9][0-9]*:[0-9][0-9]*:.[^:]*:/.[^:]*:/([s]*bin|dev)/[^:]*(sh|false|null)$'

echo "# check for incorrect shadow entries"
cat $TMPDIR/shadow | egrep -v -e \
'^[a-z][a-z0-9_-]*:.[^:]*:[-]*[0-9]*:[-]*[0-9]*:[-]*[0-9]*:[-]*[0-9]*:[-]*[0-9]*:[-]*[0-9]*:[0-9]*$'


echo "# done"
echo "####"
echo "# check duplicated uids"

awk -F: '{print $3}' $TMPDIR/passwd | sort | tee $TMPDIR/uids | uniq > $TMPDIR/uids_u

for uid in `comm -3 $TMPDIR/uids $TMPDIR/uids_u`
do
	egrep "^[^:]*:[^:]*:${uid}:" $TMPDIR/passwd
done


echo "# done"
echo "####"
echo "# check duplicated gids"

awk -F: '{print $3}' $TMPDIR/group | sort | tee $TMPDIR/uids | uniq > $TMPDIR/uids_u

for uid in `comm -3 $TMPDIR/uids $TMPDIR/uids_u`
do
	egrep "^[^:]*:[^:]*:${uid}:" $TMPDIR/group
done

echo "# done"
echo "####"
echo "# check inexistent gids"

awk -F: '{print $4}' $TMPDIR/passwd | sort -u > $TMPDIR/uids
awk -F: '{print $3}' $TMPDIR/group | sort -u > $TMPDIR/uids_u

for gid in `comm -23 $TMPDIR/uids $TMPDIR/uids_u`
do
	egrep "^[^:]*:[^:]*:[^:]*:${gid}:" $TMPDIR/passwd
done

echo "# done"
echo "####"

echo "# check inexistent home dir or bad shell"

if $NISPLUS
then

	awk -F: '{print $8}' $TMPDIR/passwd | sort -u | while read shell
	do
		if [ "_$shell" != "_" ]
		then
		[ -x "$shell" ] || ( echo  SHELL":"\"$shell\"
			nisgrep -v shell="$shell" passwd.org_dir  )
		fi
	done

	niscat auto_home.org_dir |awk -F":" "/^$uname /"'{print $NF}' |\
	while read home
	do
		[ -d $realhome/. ] || echo HOME":"$realhome
	done

else
	OIFS=""
	IFS=:
	while read uname pass uid gid gcos home shell
	do
		if egrep '^[^#].*auto_home' /etc/auto*master > /dev/null 2>&1
		then
			if $LDAP
			then
				realhome=`ldapaddent -d auto_home |awk -F":" "/^$uname  /"'{print $NF}'`
			else
				realhome=`awk -F":" "/^$uname[  ]/"'{print $NF}' /etc/auto_home`
			fi
		else
			realhome=$home
		fi
		if [ "_$realhome" = "_" ]
		then
			realhome=/export/home/robot/$uname
		fi
		[ -d $realhome/. ] || echo HOME  $uname":"$home":"$realhome
		[ -x "$shell" ] || echo  SHELL $uname":"$shell
	done < $TMPDIR/passwd
	
	IFS="$OIFS"
fi

echo "# done"

if $NISPLUS
then
	echo "####"
	echo "# check LOCAL credentials"

	niscat cred.org_dir | awk -F: '/:LOCAL:/ {print $1,$3}' |\
			sort > $TMPDIR/cred_local
	awk -F: '{print $1".'$DOMAIN'.",$3}' $TMPDIR/passwd |\
			sort > $TMPDIR/unames-uids
	diff $TMPDIR/unames-uids $TMPDIR/cred_local

	sed -e 's/\..*//' < $TMPDIR/unames-uids > $TMPDIR/unames

	echo "# done"
	echo "####"
	echo "# check DES credentials"


	niscat cred.org_dir | awk -F: '/:DES:unix\.[0-9][0-9]*/ {print $1,$3}'|\
	sed -e 's/unix\.//' -e 's/@.*//' | sort > $TMPDIR/cred_des

	diff $TMPDIR/unames-uids $TMPDIR/cred_des

	echo "# done"
	echo "####"
	echo "# check auto_home"
	niscat auto_home.org_dir | awk '{print $1}' | sort > $TMPDIR/home

	diff $TMPDIR/home $TMPDIR/unames

	echo "# done"

fi

onexit

