#!/bin/sh
#
#    Copyright (c) 2002-2007 Brocade Communications Systems, Inc.
#    All rights reserved.
#
#    File name:   logout
#    Module name: fabos/src/security/utils.c
#
#    This script will logout all sessions of specified particular users.
#    It's called by the in a number of situtaions in secure mode
#    by the FABOS code such as when passwords change or FCS role
#    change.
#
PATH=/fabos/sbin:/fabos/bin:/bin:/usr/bin:/sbin

# A common function to logout all the sessions in case of AAA config change
# or ssh session termination on zeroization

logout_all_sessions()
{

        mytty=`tty | /bin/sed  -e 's/\/dev\///g'`
        killown=0
        if [ "$1" == "user" ]; then
                session_list=`/usr/bin/who | /bin/grep -w "$2"|  /bin/sed -e 's/   / /g' | /bin/sed -e 's/  / /g' | /bin/sed -e 's/  / /g' \
                                | /usr/bin/cut -d' ' -f2`
        else
                session_list=`/usr/bin/who | /bin/sed -e 's/   / /g' | /bin/sed -e 's/  / /g' | /bin/sed -e 's/  / /g' | /usr/bin/cut -d' ' -f2`
        fi

        for tty in $session_list
        do
                /bin/echo "*tty - $tty*" >> /var/log/user.log
                #kill all other shells first
                if [ "$tty" != "$mytty" ]; then
                        pid=`fuser /dev/$tty 2>/dev/null | /bin/sed -e "s,^/dev/[[:alnum:]/]*:[[:space:]]*,,g" | /bin/sed "s/^ *//;s/ *$//"`
                        #   echo Killing PID $pid
                        if [ "$pid" != "" ]; then
                                pidarray=$(/bin/echo $pid | /usr/bin/tr " " "\n")
                                for eachpid in $pidarray
                                do
                                        if [ "$1" == "AAA" ] || [ "$1" == "saveown" ]; then
                                                ppid=`ps -o ppid= $eachpid`
                                        elif [ "$1" == "user" ]; then

						# Kill only local user sessions
                                                if [ -f /proc/$eachpid/environ ]; then
                                                        ret=$(/bin/grep -cw "AUTH_TYPE=1" /proc/$eachpid/environ)
                                                        /bin/echo "*ret - $ret" >> /var/log/user.log
                                                        if [ $ret -ne 1 ]; then
                                                                ppid=`ps -o ppid= $eachpid`
                                                        fi
                                                fi
						elif [ "$1" == "ssh" ] || [ "$1" == "sftp" ]; then
                                                	ppid=`/bin/ps -o ppid= $eachpid`
                                                	process_name=`/bin/ps -p $ppid -o comm= 2> /dev/null`
                                                	if [ "$process_name" != "sshd" ] && [ "$process_name" != "sftp" ]; then
								ppid=""
								eachpid=""
							fi
                                        	fi
					        if [[ ! -z $eachpid ]] && [ "$tty" == "ttyS0" ]; then
							/bin/kill -9 $eachpid 2> /dev/null
					        elif [[ ! -z $ppid ]] && [ $ppid != 1 ] && [ $ppid != $PPID ]; then
							/bin/kill -9 $ppid 2> /dev/null
						fi
                                done
                        fi
                else
                    /bin/sleep 1
                    killown=1
                fi
        done

	#Check for chassis/pizzabox
	# Terminate standby sessions in case of ssh/sftp
	pizzabox=$(/fabos/cliexec/hashow | /bin/grep -c "Not supported on this platform")
	if [[ $pizzabox -eq 0 ]]; then
		# Chassis
		if [ "$1" == "ssh" ]; then
			terminate_process_standby "sshd:"
		elif [ "$1" == "sftp" ]; then
			terminate_process_standby "sftp"
		fi
	fi

#Kill ssh session without pts/tty associated with them
if [ "$1" == "ssh" ];then
	ssh_pid_without_terminal=`/bin/ps -eaf | /bin/grep sshd: | /bin/grep -v "grep\|pts\|tty" |  /bin/sed -e 's/  */ /g' |  /usr/bin/cut -d' ' -f2`
	for eachpid in $ssh_pid_without_terminal
	do	
		/bin/kill -9 $eachpid 2>/dev/null
	done

fi 
    	
	#kill own shell
if [ $killown == 1 ]; then
	if [ "$1" != "saveown" ] && [ "$1" != "sftp" ]; then
		# FOS-818951: Fix to address passwddefault not kicking root user out
		if [ "$2" == "root" ] && [ "$mytty" == "ttyS0" ]; then
			pid=`/bin/ps | /bin/grep ttyS0 | /bin/grep sh | /bin/awk '{ print $1 }'`
		else
			pid=`/sbin/fuser /dev/$mytty 2>/dev/null | /bin/sed -e "s,^/dev/[[:alnum:]/]*:[[:space:]]*,,g" | /bin/sed "s/^ *//;s/ *$//"`
		fi
		# End of Fix for FOS-818951
		/bin/echo "All PID's associated with Shell = $pid" >> /var/log/user.log
		if [ "$1" == "AAA" ]; then
			ret=0
		else
			ret=1
		fi
        	if [ "$pid" != "" ]; then
			pidarray=$(/bin/echo $pid | /usr/bin/tr " " "\n")
			for eachpid in $pidarray
			do	
				if [ "$eachpid" != "" ]; then
					ppid=`/bin/ps -o ppid= $eachpid`
					if [ "$1" == "user" ]; then
						# Kill only local user sessions
						if [ -f /proc/$eachpid/environ ]; then
							ret=$(/bin/grep -cw "AUTH_TYPE=1" /proc/$eachpid/environ)
							/bin/echo "*ret - $ret" >> /var/log/user.log
						fi
					elif [ "$1" == "ssh" ]; then
						process_name=`/bin/ps -p $ppid -o comm= 2> /dev/null`
						if [ "$process_name" == "sshd" ]; then
							ret=0
						fi
					fi
					if [ $ret -ne 1 ]; then
						shell=`/bin/ps -p $eachpid -o comm= 2> /dev/null`
						if [ "$shell" == "sh" ] || [ "$shell" == "rbash" ]; then
							/bin/echo "shell PID = $eachpid" >> /var/log/user.log
							/bin/sleep 1
							if [ "$mytty" == "ttyS0" ]; then
								/bin/kill -9 $eachpid 2> /dev/null
							elif [[ ! -z $ppid ]] && [ $ppid != 1 ]; then
								/bin/kill -9 $ppid 2> /dev/null
							fi
						fi
					fi
				fi
			done
		fi
	fi
fi
}

terminate_process_standby() {
	otherhost=`/fabos/rbin/cipherutil get_otherhost 2>/dev/null`
	if  /bin/ping -c 2 $otherhost >& /dev/null ; then
		/usr/bin/rsh -n $otherhost "for ssh_sess_pid in \`/bin/ps -aef| /bin/grep "$1" |/bin/grep -v grep|/bin/sed -e 's/  */ /g'|/usr/bin/cut -d' ' -f2\`;
		do
			/bin/kill -9 \$ssh_sess_pid 2> /dev/null;
                done" >& /dev/null
	fi
}

terminate_service_sessions()
{
        msg="Service session will be logged out"
        killown=0

        pidlist=`/bin/ps -aef | /bin/grep maintenance | /bin/grep "\-\-init-file /fabos/users/maintenance/.service"| /bin/sed -e 's/  */ /g' | /usr/bin/cut -d' ' -f2`
        #Self sesion kill will only be invoked in --reset from service shell
        #PPID will denote --reset, parent of ppid will denote bash
        mysesspid=`ps -o ppid= $PPID | /bin/sed 's/^[ \t]*//'`
        for pid in $pidlist
        do
                if [ "$pid" != "$mysesspid" ]; then
                        tty=`/bin/ps -o tty= -p $pid`
                        if [ "$tty" != "" ]; then
                                /bin/echo -e "\n$msg" > /dev/$tty
                                sleep 1
                        fi
                        /bin/kill -15 $pid 2> /dev/null
                else
                        killown=1
                fi
        done

        if [ "$killown" != "0" ]; then
                tty=`/bin/ps -o tty= -p $mysesspid`
                if [ "$tty" != "" ]; then
                        /bin/echo -e "\n$msg" > /dev/$tty
                        sleep 1
                fi
                /bin/kill -9 $mysesspid 2> /dev/null
        fi
}

terminate_factory_sessions()
{
        msg="Factory session will be logged out"
        killown=0

        pidlist=`/bin/ps -aef | /bin/grep maintenance | /bin/grep "\-\-init-file /fabos/users/maintenance/.factory"| /bin/sed -e 's/  */ /g' | /usr/bin/cut -d' ' -f2`
        #Self sesion kill will only be invoked in --reset from factory shell
        #PPID will denote --reset, parent of ppid will denote bash
        mysesspid=`ps -o ppid= $PPID | /bin/sed 's/^[ \t]*//'`
        for pid in $pidlist
        do
                if [ "$pid" != "$mysesspid" ]; then
                        tty=`/bin/ps -o tty= -p $pid`
                        if [ "$tty" != "" ]; then
                                /bin/echo -e "\n$msg" > /dev/$tty
                                sleep 1
                        fi
                        /bin/kill -15 $pid 2> /dev/null
                else
                        killown=1
                fi
        done

        if [ "$killown" != "0" ]; then
                tty=`/bin/ps -o tty= -p $mysesspid`
                if [ "$tty" != "" ]; then
                        /bin/echo -e "\n$msg" > /dev/$tty
                        sleep 1
                fi
                /bin/kill -9 $mysesspid 2> /dev/null
        fi
}

if [ $# -ge 1 ]; then
# Logout Multiple Users
if [ $# -ge 2 ]; then
# Information for User
#echo Will logout user: $1
line="$*"
sw=`/bin/echo $line | /usr/bin/cut -d' ' -f 1`
accts=`/bin/echo $line | /usr/bin/cut -d' ' -f 2-`

if [ $1 == "-user" ]; then
	if [ "$3" == "genericmsg" ]; then
		msg="Security Policy, Password or Account Attribute Change: "
		accts=$2
		/bin/sleep 1
	elif [ "$3" == "timeout" ]; then
		msg="Time of Day Expired: "
		accts="$2"
	else
	msg="Security Policy, Password or Account Attribute Change: "
	fi
else
	msg="Security Policy, Password or Account Attribute Change: "
fi
msg=$msg$accts" will be logged out"
chassis_info=`getchassisconfig`
num_switches=`/bin/echo $chassis_info | \
	/bin/sed -n -e 's/Number of switches: //gp' | \
	/bin/sed -n -e 's/ .*//gp'`

fi

if [ $# -eq 1 ]; then

# Logout Invalid Users
if [ $1 == "-invalid" ]; then
/bin/echo "Finding invalid users" >> /var/log/user.log
for logged_user in `/usr/bin/who | /usr/bin/cut -d' ' -f1`
do
/bin/echo "*logged_user - $logged_user* " >> /var/log/user.log
	kill_user=1
	# Check if the user is valid by searching the /etc/passwd file
	for valid_user in `/bin/grep "$logged_user" < /etc/passwd | /usr/bin/cut -d':' -f1`
	do
		if [ "$logged_user" == "$valid_user" ]
		then
			kill_user=0
			break
		fi
	done
	# If user is invalid, add it to the list of accounts
	if [ $kill_user -eq 1 ]
	then
		accts="$logged_user $accts"
	fi
done
if [ "$accts" != "" ]; then
	/usr/bin/wall "Active CP : Invalid users \"$accts\" will be logged out."
fi
accts=`/bin/echo $accts | /usr/bin/cut -d' ' -f1-`

# matador fips rel v7.0, need to terminate all SSH sessions
# after zeroizing ssh public/private keys. 
elif [ $1 == "-ssh" ]; then

	msg="All SSH accounts will be logged out"
	/usr/bin/wall "$msg"
        /bin/sleep 1
	logout_all_sessions "ssh"
elif [ $1 == "-sftp" ]; then
	msg="SSH public/private Keys are Zeroized. SFTP sessions will be terminated"
	/usr/bin/wall "$msg"
	logout_all_sessions "sftp"
elif [ $1 == "-saveown" ]; then
        msg="Security Policy, Password or Account Attribute Change: all accounts will be logged out"
        /usr/bin/wall "$msg"
        logout_all_sessions "saveown"
        /bin/sleep 1
elif [ "$1" == "-service" ]; then
        terminate_service_sessions
        exit 0
elif [ "$1" == "-factory" ]; then
        terminate_factory_sessions
        exit 0
elif [ "$1" == "-factreset" ]; then
	msg="Factory reset: all accounts will be logged out"
	/usr/bin/wall "$msg"
	logout_all_sessions "AAA"
	/bin/sleep 1

else

	/bin/echo "Invalid Arguments/Options for usrlogout"
fi

elif [ $1 == "-user" ]; then
	msg="Logging out all the sessions of user $2"
	# Only display message to user being logged out
	for user_sess in `/usr/bin/who | /bin/grep -w $2 | /bin/awk '{print $2}'`
	do
	        /bin/echo "$msg" > /dev/$user_sess
	        /bin/sleep 1
	done
	logout_all_sessions "user" "$2"
	/bin/sleep 1 
	exit 0

fi

/bin/echo "logged_users : $accts" >> /var/log/user.log
/bin/echo "" >> /var/log/user.log
/bin/echo "looping through all accounts" >> /var/log/user.log
# Loop through all accounts
for name in $accts; do
/bin/echo "$name" >> /var/log/user.log
	msg="Logging out all the sessions of user $name"
	# Only display message to user being logged out
	for user_sess in `/usr/bin/who | /bin/grep -w $name | /bin/awk '{print $2}'`
	do
	        /bin/echo "$msg" > /dev/$user_sess
	        /bin/sleep 1
	done
	logout_all_sessions "user" "$name"
done


# no argument, logout all
elif [ $# -eq 0 ]; then

	msg="AAA Server Configuration Change: all accounts will be logged out"
	/usr/bin/wall "$msg"
	pizzabox=$(/fabos/cliexec/hashow | /bin/grep -c "Not supported on this platform")
	act_standby=$(/fabos/cliexec/hashow | /bin/grep "Local CP" | /bin/awk '{print $6}')
	if [ "${act_standby:0:6}" == "Active" ] || [ $pizzabox -eq 1 ]; then
        	/bin/echo " Logging out all the sessions"
	else
        	/bin/echo " Logging out all the sessions on Standby"
	fi
	logout_all_sessions "AAA"
	/bin/sleep 1
fi
