#!/bin/sh
# 
# Installs tnetd jumbo patch on system in single-user mode.
# 	Installs the following files:
#		/vmunix
# 		/usr/etc/mkdb 
#		/usr/etc/tnetd
#		/usr/etc/tnetd_ctl
#		/usr/etc/tnet_kstats
#		/usr/etc/halt
#		/usr/etc/reboot
#		/usr/include/cmw/secpolicy.h
#		/usr/kvm/sys/`arch -k`/OBJ/raw_usrreq.o
#		/usr/kvm/sys/`arch -k`/OBJ/sec_tnet.o
#		/usr/kvm/sys/`arch -k`/OBJ/sec_driver.o
# 

#
# basename is a System V'ism.  We define it here just in case...
#
basename()
{
	echo $1 |  awk -F'/' '{print $NF}'
}

#
# install_new_files
# $1 is regular files, $2 is kernel objects in /usr/kvm/sys/`arch`/
# $3 is the kernel architecture of the target host.
#
install_new_files()
{
	echo "Installing new files..."
	for i in $1
	do
		FILENAME=`basename $i`
		cp ${FILENAME} $i
		echo "  $i"
		# Are we a diskless server?
		# If so, check our client's filesystems.
		if [ $IM_SERVER -eq "yes" ]; then
			for client in $MY_CLIENTS
			do
				client_arch=`grep /usr/kvm \
					/export/root/${client}/etc/fstab | \
					awk -F'/' '{print $5}' | \
					awk -F'.' '{print $1}' `
				if [ -f /export/root/${client}${i}.FCS ]; then
					cp ${FILENAME} \
					  /export/root/${client}$i
					echo "  /export/root/${client}${i}"
				fi
			done
		fi
	done

	for i in sun4 sun4c sun4m
	do
			for j in $2
			do
				ARCHNAME=$i
				if [ -d /usr/kvm/sys/$i ]; then
					cp ${ARCHNAME}/${j} \
						/usr/kvm/sys/$i/OBJ/${j}
					echo  "  /usr/kvm/sys/$i/OBJ/$j"
				fi
			# This only happens if we're a server...
	SFILN="/export/exec/kvm/${i}.${MYOS}.${MYOSVER}/sys/${i}/OBJ/${j}"
	if [ -d /export/exec/kvm/${i}.${MYOS}.${MYOSVER}/sys/${i} ]; then
				cp ${i}/${j} ${SFILN}
				echo "  ${SFILN}"
			fi
			done
	done
	echo "Done."
}

#
# keep_FCS_versions()
#
# Keeps the original versions of the listed files.
# $1 is regular files, $2 is kernel objects in /usr/kvm/sys/`arch`/
keep_FCS_versions()
{
	echo "Saving FCS versions of files..."
	for i in $1
	do
		echo -n "  $i..."
		if [ -f $i.${3} ]; then
			echo "already saved.  Skipping."
		else
			mv $i $i.${3}
			echo " to $i.${3}"
		fi
		# Are we a diskless server?
		# If so, check our client's filesystems.
		if [ $IM_SERVER -eq "yes" ]; then
			for client in $MY_CLIENTS
			do
			if [ -f /export/root/${client}${i} ]; then
				echo -n "  /export/root/${client}${i}..."
				if [ -f /export/root/${client}${i}.${3} ]; then
					echo "already saved.  Skipping."
				else
					mv /export/root/${client}$i \
						/export/root/${client}${i}.${3}
				      echo " to /export/root/${client}${i}.${3}"
				fi
			fi
			done
		fi
	done

	for i in sun4 sun4c sun4m
	do
		for j in $2
		do
			if [ -f /usr/kvm/sys/$i/OBJ/$j ]; then
				echo "  /usr/kvm/sys/$i/OBJ/$j..."
				if [ -f $i.${3} ]; then
					echo "already saved.  Skipping."
				else
					mv /usr/kvm/sys/$i/OBJ/$j \
				   	/usr/kvm/sys/${i}/OBJ/$j.${3}
					echo \
					"      to /usr/kvm/sys/${i}/OBJ/${j}.${3}"
				fi
			fi

			# This only happens if we're a server...
	SFILN="/export/exec/kvm/${i}.${MYOS}.${MYOSVER}/sys/${i}/OBJ/${j}"
			if [ -f $SFILN ]; then
				echo "  ${SFILN}..."
				if [ -f ${SFILN}.${3} ]; then
					echo "already saved.  Skipping."
				else
					mv ${SFILN} ${SFILN}.${3}
					echo "    to ${SFILN}.${3}"
				fi
			fi
		done
	done
	echo "Done."
}

#
# cleanup_patch()
#
# herein we find any cleanup work which needs to be done, such as
# the generation of new databases and so forth.
# $1 is the list of tcb_static files outside the kernel trees.
# $2 is the list of tcb_static files inside the kernel trees.
# $3 is the list of tcb_dynamic files outside the kernel trees.
# $4 is the list of tcb_dynamic files inside the kernel trees.
cleanup()
{
	echo "Setting priviliges on executables..."

	echo -n "  /usr/etc/mkdb"
	chmod go-rwx /usr/etc/mkdb
	chown root.staff /usr/etc/mkdb
	chpriv a+all /usr/etc/mkdb
	chpriv f-all /usr/etc/mkdb

	echo -n "  /usr/etc/tnetd"
	chmod go-rwx /usr/etc/tnetd
	chmod u+rwx /usr/etc/tnetd
	chown root.staff /usr/etc/tnetd
	chpriv a+all /usr/etc/tnetd
	chpriv f+net_allowaccess,proc_setclr,proc_setid,proc_setil,proc_setsl /usr/etc/tnetd

	echo -n "  /usr/etc/tnetd_ctl"
	chmod go-rwx /usr/etc/tnetd_ctl
	chown root.staff /usr/etc/tnetd_ctl
	chpriv a+all /usr/etc/tnetd_ctl
	chpriv f+net_allowaccess /usr/etc/tnetd_ctl

	echo -n "  /usr/etc/halt"
	chown root.staff /usr/etc/halt
	chpriv a+all /usr/etc/halt
	chpriv f+file_mac_read,net_allowaccess,proc_audit_tcb,sys_audit /usr/etc/halt

	echo "  /usr/etc/reboot"
	chown root.staff /usr/etc/reboot
	chpriv a+all /usr/etc/reboot
	chpriv f+file_mac_read,net_allowaccess,proc_audit_tcb,sys_audit /usr/etc/reboot
	echo "  /usr/include/cmw/secpolicy.h"
	chmod ugo+r /usr/include/cmw/secpolicy.h
	echo "  /usr/man/man8/tnetd_ctl.8t"
	chmod ugo+r /usr/man/man8/tnetd_ctl.8t
	echo "Done."


	if [ $IM_SERVER -eq "yes" ]; then
		echo "Making new TNET_LOG's..."
	else
		echo "Making a new TNET_LOG..."
	fi
	mv /var/adm/TNET_LOG /var/adm/TNET_LOG.FCS
	touch /var/adm/TNET_LOG
	setlabel "system_high[system_high]" /var/adm/TNET_LOG
	chmod go-rwx /var/adm/TNET_LOG
	/usr/etc/mkdb /etc/security/TNETDB 4096 80
	if [ $IM_SERVER -eq "yes" ]; then
		for cl in $MY_CLIENTS
		do
		mv /export/root/${cl}/var/adm/TNET_LOG /var/adm/TNET_LOG.patch
		touch /export/root/${cl}/var/adm/TNET_LOG
		setlabel "system_low[system_high]" \
			/export/root/${cl}/var/adm/TNET_LOG 
		chmod go-rwx /export/root/${cl}/var/adm/TNET_LOG
		done
	fi
	echo "Done."

	if [ $IM_SERVER -eq "yes" ]; then
		echo "Making new TNETDB's..."
	else
		echo "Making a new TNETDB..."
	fi
	rm -rf /etc/security/TNETDB
	/usr/etc/mkdb /etc/security/TNETDB 4096 80
	if [ $IM_SERVER -eq "yes" ]; then
		for cl in $MY_CLIENTS
		do
			rm -rf /export/root/${cl}/etc/security/TNETDB
			/usr/etc/mkdb /export/root/${cl}/etc/security/TNETDB \
				4096 80
		done
	fi
	echo "Done."

	echo -n "Updating consistency databases for patched files... "
	if [ $IM_SERVER -eq "yes" ]; then
		echo "(this may take a while) "
	else
		echo
	fi
	touch /etc/tfm/home/sync_ctab.log
	#
	# Static databases
	#
	echo "  Static databases..."
	if [ -n "$1" ]; then
	for i in $1
	do
		echo "     $i"
		sync_ctab /etc/security/tcb_static -o $i \
			>> /etc/tfm/home/sync_ctab.log
		if [ $IM_SERVER -eq "yes" ]; then
			for client in $MY_CLIENTS
			do
				sync_ctab /etc/security/tcb_static \
					-c ${client} \
					-o $i \
					>> /etc/tfm/home/sync_ctab.log
			done
		fi
	done
	fi
	if [ -n "$2" ]; then
	for i in sun4 sun4c sun4m
	do
		for j in $2
		do
				echo "       /usr/kvm/sys/${i}/OBJ/${j}"
				sync_ctab /etc/security/tcb_static -o \
					/usr/kvm/sys/$i/OBJ/$j \
					>> /etc/tfm/home/sync_ctab.log
		if [ $IM_SERVER -eq "yes" ]; then
			for client in $MY_CLIENTS
			do
			sync_ctab /etc/security/tcb_static \
				-c ${client} \
				-o /usr/kvm/sys/$i/OBJ/$j \
				>> /etc/tfm/home/sync_ctab.log
			done
	echo "   /export/exec/kvm/${i}.${MYOS}.${MYOSVER}/sys/${i}.${j}"
			sync_ctab /etc/security/tcb_static -o \
			/export/exec/kvm/${i}.${MYOS}.${MYOSVER}/sys/${i}.${j}\
				>> /etc/tfm/home/sync_ctab.log
		fi
		done
	done
	fi
	#
	# tcb_dynamic databases
	#
	echo "  Dynamic databases..."
	if [ -n "$3" ]; then
	for i in $3
	do
		echo "     $i"
		sync_ctab /etc/security/tcb_static -o $i \
			>> /etc/tfm/home/sync_ctab.log
		if [ $IM_SERVER -eq "yes" ]; then
			for client in $MY_CLIENTS
			do
				sync_ctab /etc/security/tcb_static \
					-c ${client} \
					-o $i \
					>> /etc/tfm/home/sync_ctab.log
			done
		fi
	done
	fi

	if [ -n "$4" ]; then
	for i in sun4 sun4c sun4m
	do
		for j in $4
		do
				echo "     /usr/kvm/sys/${i}/OBJ/${j}"
				sync_ctab /etc/security/tcb_static \
					-o /usr/kvm/sys/$i/OBJ/$j \
					>> /etc/tfm/home/sync_ctab.log
		if [ $IM_SERVER -eq "yes" ]; then
			for client in $MY_CLIENTS
			do
			sync_ctab /etc/security/tcb_static  \
				-c ${client} \
				-o /usr/kvm/sys/$i/OBJ/$j \
				>> /etc/tfm/home/sync_ctab.log
			done
	echo "   /export/exec/kvm/${i}.${MYOS}.${MYOSVER}/sys/${i}.${j}"
			sync_ctab /etc/security/tcb_static  \
	-o /export/exec/kvm/${i}.${MYOS}.${MYOSVER}/sys/${i}.${j}\
				>> /etc/tfm/home/sync_ctab.log
		fi
		done
	done
	fi
	echo " Done."
	echo -n "Syncing disks"
	sync
	echo -n "."
	sleep 1
	sync
	echo -n "."
	sleep 1
	sync
	echo -n "."
	echo " done"
	echo
	echo -n "You must now configure "
	if [ $IM_SERVER -eq "yes" ]; then
		echo -n "new kernels "
	else
		echo -n "a new kernel "
	fi
	echo " and sync your disks"
	echo "with /bin/sync before rebooting."
	echo "Check /usr/kvm/`arch -k`/config/README and your Systems and"
	echo "Networking manual for details."
}
#
# make_client_list()
# Makes a list of the diskless clients of this host to stdout.
# Checks in /export/root for the name, and then looks in /etc/ethers.
make_client_list() {
	CL_LIST=`/bin/ls -1 /export/root | grep -v lost+found`
	for i in $CL_LIST
	do
		echo -n `grep $i /etc/ethers | awk '{print $2}'`
		echo -n " "
	done
}


#
# The main thing.
#
FCSEXT="FCS"
FILESTOPATCH="\
		/usr/etc/mkdb\
		/usr/etc/tnetd\
		/usr/etc/tnetd_ctl\
		/usr/etc/tnet_kstats\
		/usr/etc/halt\
		/usr/etc/reboot\
		/usr/man/man8/tnetd_ctl.8t\
		/usr/include/cmw/secpolicy.h"
OBJTOPATCH="raw_usrreq.o sec_tnet.o sec_driver.o"
PATH=/bin:/usr/bin:/usr/etc
MYKARCH=`arch -k`
MYOS="trusted_solaris"
MYOSVER="1.1"
MYTITLE='   * * * Trusted Solaris 1.1 Trusted Network Jumbo Patch Installation * * *'

#
# Tell the user about this.
#
echo "$MYTITLE"
echo

# Find out if we're a server for diskless clients.  If so, this is going
# to take a bit longer than we thought...
#
if [ -d /export ]; then
	IM_SERVER="yes"
	echo "Hmmm... This machine is a diskless server.  This installation "
	echo "will take a little longer than I'd thought."
	MY_CLIENTS="`make_client_list`"
else
	IM_SERVER="no"
fi

# We'll put the FCS versions aside, because we like to be safe.
keep_FCS_versions "$FILESTOPATCH" "$OBJTOPATCH" $FCSEXT
# And install the new files...
install_new_files "$FILESTOPATCH" "$OBJTOPATCH" $MYKARCH

#
# Do a little clean-up.
cleanup "$FILESTOPATCH" "$OBJTOPATCH" "/usr/etc/TNETDB" ""
