#! /bin/bash
# Make old ssh connections that forward the AUTH_SOCK work by
# symbolically linking old ssh auth sockets used by ssh clients to the
# currently active socket.

# Usage:
#   ssh host 'ssh_auth_shuffle && screen -d -r; rm ~/.ssh_auth_sock/$$'
# to clean up pid file immediately or
#   ssh host 'ssh_auth_shuffle && exec screen -d -r'

# Useful aliases/functions for Bourne like shells are:
#     auth '. ~/.auth_ssh' -- refreshes SSH variables to current settings
#     ssh '. ~/.auth_ssh; ssh ' -- refreshes SSH variables and invokes ssh
#     scp '. ~/.auth_ssh; ssh ' -- refreshes SSH variables and invokes scp
# at the end of your shell startup script put:
# . ~/.auth_ssh # for bourne like shells

# Support for multiple screen sessions not yet complete, but that is
# why there are independent files to store the SSH auth vars in.

# require globbing for non-existant files to be null.
shopt -s nullglob

# make files/directories created below private
umask 077

# make directory
[ -d ~/.ssh/auth_sock_info ] || mkdir -p ~/.ssh/auth_sock_info

# clean up old links to sockets we have done in the past
if [ -f ~/.ssh/auth_sock_info/old ]; then
    for i in `cat ~/.ssh/auth_sock_info/old`
    do
      rm -rf `dirname $i`
    done
    rm -f ~/.ssh/auth_sock_info/old
fi

# clean up socket info for old shells
for i in ~/.ssh/auth_sock_info/[0-9]*
do
  # use ps -p to see if process exists.
  # exit 1 if not and 0 if it does.
  # it's ok if it's not our process at some point the process will
  # not exist and the pid file will be reaped.
  /bin/ps -p `basename $i` > /dev/null || rm -f $i
done

# make sure we have an active sshd process to link to.
pid=`echo $SSH_AUTH_SOCK | sed -e 's/.*\.\([0-9]*\)$/\1/'`
if ps -p $pid -f  | grep "$USER.*sshd.*@.*[0-9]" > /dev/null; then
  # store the current SSH variables
    set | sed -ne '/[S]SH/s/^/export /p' > ~/.ssh/auth_sock_info/$PPID
  # store the current DISPLAY variable
    set | sed -ne '/DISPLAY/s/^/export /p' >> ~/.ssh/auth_sock_info/$PPID

  # Create a statically named link that points to the current
  # info
    rm -f ~/.auth_ssh;
    ln -s ~/.ssh/auth_sock_info/$PPID ~/.auth_ssh
else
  echo "Current SSH_AUTH_SOCK is invalid. Pid $pid not a valid sshd."
  exit 2
fi

# run through processes for this user looking for ssh processes
# with SSH_AUTH_SOCK set in their environments.

USER=`whoami`
for i in `pgrep -u $USER 'ssh$'`
do
  SOCK=`ps ewwp $i | sed -ne 's/.*SSH_AUTH_SOCK=\([^ ]*\).*/\1/p'`
  OLD_SOCK="$OLD_SOCK $SOCK" 
done

if [ -n "$OLD_SOCK" ]; then
    for i in $OLD_SOCK
    do
      # see if the old sshd process is running and if it is not
      # connected to a tty it's orphaned. Kill it and set up to
      # forward the socket.
      pid=`echo $i | sed -e 's/.*\.\([0-9]*\)$/\1/'`
      if ps -p $pid -f  | grep "$USER.*sshd.*@.*[0-9]" > /dev/null; then
      echo "Prior sshd process $pid still connected to tty not resetting socket"
      else
        # make sure it is orphaned. It could be reused by another
        # non-sshd process.
	  if ps -p $pid -f  | grep "$USER.*sshd.*notty" > /dev/null ; then
	      kill $pid
	  fi
        # remove the old socket in case ssh didn't clean up
	  rm -f $i

	  OLD_DEAD_SOCK="$OLD_DEAD_SOCK $i"
      fi
    done
fi

if [ -n "$OLD_DEAD_SOCK" ]; then
    for i in $OLD_DEAD_SOCK
    do
        # in case ssh exited on it's own it might have cleaned up and
        # removed the socket and the directory, so we need to check
        # and remake directory.

        [ -d "`dirname $i`" ] || mkdir "`dirname $i`"

        # link old location to new active socket.
        ln -s  "$SSH_AUTH_SOCK" "$i"

	# record for later cleanup
	echo "$i" >> ~/.ssh/auth_sock_info/old
    done
fi

exit 0
