#!/bin/sh

if [ "$1" = "-d" ]
then
    set -x
    debugflag=x
    shift
else
    debugflag=
fi

if [ $# -lt 1 ]
then
    echo "usage: $0 [-d] [-c cycletime] [-f file] [[user@]host ...]" >&2
    echo "to push kerberos tickets from here to sessions on host1 host2 ..." >&2
    echo "-d turns on debugging" >&2
    echo "-c check for updated ticket every cycletime seconds" >&2
    echo "-f specify file containing [user@]host list" >&2
    exit 1
fi

listfile=""
repeatflag=0
while :
do
    case "x$1" in 
    x-f) listfile=$2; shift; shift;;
    x-c) repeatflag=1; delay=$2; shift; shift;;
    *)   break;;
    esac
done

if [ "$repeatflag" = 1 ]
then
    output="`klist -f | head -5`"
fi

firsttime=1

while [ $firsttime = 1 -o $repeatflag = 1 ]
do

    firsttime=0
    if [ $repeatflag = 1 ]
    then
	# wait for ticket cache to be updated   
        newoutput="`klist -f | head -5`"
	while [ "$newoutput" = "$output" ]
	do
	    sleep $delay
            newoutput="`klist -f | head -5`"
	done
        output="$newoutput"
    fi

    if [ "x$listfile" != "x" ] && [ -r "$listfile" ]
    then
	set : `cat $listfile`
	shift
    fi

    for host_user in "$@"
    do
	case "$host_user" in
	*@*)cmd="`echo $host_user | sed -e 's/\(.*\)@\(.*\)/host=\2;user=\1/'`"
	    eval "$cmd"
	    uargs="-l $user"
	    ;;
	*)  host=$host_user; 
	    user=$USER
	    uargs=""
	esac
	#
	# the block we rsh is a little convoluted:
	#	Get the list of pid-cache-file candidates
	#	     keep any belonging to us with right modes
	#	     skip our current credential file
	#	loop through results each as $file
	#	    default principals must match
	#		continue otherwise
	#	    check what sort of file
	#	    /tmp/krb5cc_uid_pid -> valid if pid matches an sshd pid
	#		continue otheriwse
	#	    /tmp/krb5cc_p<pid>* -> valid if pid is a kshd
	#		continue otheriwse
	#	    /tmp/krb5cc_<tty> -> valid if tty exists and USER's
	#		continue otheriwse
	#	    print a message
	#	    copy the current creds to that file
	#	
	(((${K5PUSH_RSH:-/usr/bin/ssh} $uargs $host /bin/sh -${debugflag} 2>&1) ||
	  (/usr/krb5/bin/ssh $uargs $host /bin/sh -${debugflag} 2>&1) ||
	  (/usr/krb5/bin/rsh -F $uargs $host /bin/sh -${debugflag} 2>&1) ||
	  (/usr/kerberos/bin/rsh -F $uargs $host /bin/sh -${debugflag} 2>&1) ||
	  (/usr/bin/ssh $uargs $host /bin/sh -${debugflag} 2>&1) ||
	  false
	 ) | cat) << 'EOF'
	    PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/bsd:/usr/ucb:/usr/krb5/bin:/usr/kerberos/bin
	    export PATH
	    USER=`echo $USER | sed -e 's/ .*//'`
	    cd /tmp
	    if ls -ld . | grep -v '^drwxrwxrwt' > /dev/null
	    then
		echo "Skipping `hostname` due to bad modes on /tmp"
		exit
	    fi
	    echo Updating keys for $USER on `hostname`
	    uid=${UID:-`/usr/xpg4/bin/id -u 2>/dev/null || id -u`}
	    curcred=`echo $KRB5CCNAME | sed -e sxFILE:xx -e sx/tmp/xx`
	    principal=`klist | grep 'Default'| sed -e 's/.* //'`
 
	    find krb5cc_* \! -name $curcred -user $USER -type f -perm 0600 -print 2>/dev/null |
	    while read file 
	    do 
		if klist $file  |
 			grep -i Default.*$principal
		then
		    echo "checking $file"
		    case $file in 
		    *_[0-9]*_*)# new ssh format 
			    echo updating $file
			    cp ./$curcred ./$file
			  ;;
			  
		    *_p*) pid=`echo $file | sed -e sx.*krb5cc_pxx` 
			  if (ps $pid 2>/dev/null || ps -p $pid 2>/dev/null) | 
			      sed -e "s/^/found: $file => /" |
			      egrep 'bash|sh|csh|tcsh|kshd|klogind|telnetd|sshd' 
			  then
				echo updating $file
				cp ./$curcred ./$file
			  fi
			  ;;
		    *)    tty=`echo $file | sed -e sx.*krb5cc_xx` 
			  if ls -Ll /dev/$tty /dev/pts/$tty 2>/dev/null | 
			      sed -e "s/^/found: $file => /" |
			      grep "$USER" 
			  then
				echo updating $file
				cp ./$curcred ./$file
			  fi
			  ;;
		    esac
		fi
	    done
	    /usr/krb5/bin/kdestroy
EOF
    done
done
