Boston Linux & Unix (BLU) Home | Calendar | Mail Lists | List Archives | Desktop SIG | Hardware Hacking SIG
Wiki | Flickr | PicasaWeb | Video | Maps & Directions | Installfests | Keysignings
Linux Cafe | Meeting Notes | Blog | Linux Links | Bling | About BLU

BLU Discuss list archive


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Keychain



No, this keychain is an open source shell script available from Gentoo that
utilizes ssh-agent in such a manner that it is possible to start mutiple shells
with out multiple instances of ssh-agent being generated each time.

My earlier post was inaccurate as far as the symptoms I am experiencing. I have
been experimenting with both keychain and ssh-agent over the past week but not
every day, so I unfortunately described the behavior of ssh-agent in my post. And
that behavior is what you should experience with ssh-agent. Keychain is not
working yet for me it gives me the following output when I first start a cygwin
bash shell:

KeyChain 2.0.1; http://www.gentoo.org/projects/keychain
 Copyright 2002 Gentoo Technologies, Inc.; Distributed under the GPL
 * All previously running ssh-agent(s) have been stopped.
 * Initializing /home/jim/.keychain/KELLY-RAND-sh file...
 * Initializing /home/jim/.keychain/KELLY-RAND-csh file...
 * Starting new ssh-agent
 * 1 more keys to add...
Enter passphrase for /home/jim/.ssh/id_dsa:
Identity added: /home/jim/.ssh/id_dsa (/home/jim/.ssh/id_dsa)

bash: /home/jim/.ssh-agent: No such file or directory

##############################################
below is the script keychain

#############################################
#!/bin/sh
# Copyright 1999-2002 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2
# Author: Daniel Robbins <drobbins at gentoo.org>
# $Header: /home/cvsroot/gentoo-src/keychain/keychain,v 1.25 2002/08/26 20:25:24
drobbins Exp $

version=2.0.1

PATH="/sbin:/usr/sbin:${PATH}:/usr/ucb"; export PATH;

myaction=""
myactionarg=""
noaskopt=""
quietopt=""
nocolopt=""
clearopt=""
mykeys=""
keydir="${HOME}/.keychain"
while [ -n "$1" ]
do
 case $1 in
  -h|--help|--stop|-k)
   #action specified
   if [ -z "$myaction" ]
   then
    case $1 in
     -h|--help)
      myaction="help"
      ;;
     --stop|-k)
      myaction="stop"
      ;;
    esac
    myactionarg="$1"
   else
    echo "$0: you can't specify $myactionarg and $1 at the same time; exiting."
    exit 1
   fi
   ;;
  --dir)
   shift
   keydir="${1}/.keychain"
   ;;
  --clear)
   clearopt="yes"
   ;;
  --noask)
   noaskopt="yes"
   ;;
  -q|--quiet)
   quietopt="yes"
   ;;
  --nocolor)
   nocolopt="yes"
   ;;
  *)
   mykeys="${mykeys} $1"
   ;;
 esac
 shift
done
#first, handle help.
if [ "$myaction" = "help" ]
then
 echo $E Usage: ${CYAN}${0}${OFF} [ ${GREEN}options${OFF} ] ${CYAN}sshkey${OFF}
...
 cat <<EOHELP

Description:

 Keychain is an OpenSSH key manager, typically run from ~/.bash_profile.  When
 run, it will make sure ssh-agent is running; if not, it will start ssh-agent.
 It will redirect ssh-agent's output to ~/.keychain/[hostname]-sh, so that cron
 jobs that need to use ssh-agent keys can simply source this file and make the
 necessary passwordless ssh connections.  In addition, when keychain runs, it
 will check with ssh-agent and make sure that the ssh RSA/DSA keys that you
 specified on the keychain command line have actually been added to ssh-agent.
 If not, you are prompted for the appropriate passphrases so that they can be
 added by keychain.

 Typically, one uses keychain by adding the following to the top of their
 ~/.bash_profile (or ~/.zlogin, in case of zsh):

EOHELP
 echo $E "  ${CYAN}keychain ~/.ssh/id_rsa ~/.ssh/id_dsa"
 echo $E "  . ~/.keychain/\${HOSTNAME}-sh${OFF}"
 echo
 echo $E "  # alt. syntax: . ~/.keychain/\`uname -n\`-sh"
 echo $E "  # note the use of back-quotes (\`) rather than single-quotes (')
above."
 echo $E "  # We now include the hostname (\`uname -n\`) in the keychain filename"

 echo $E "  # for NFS-compatibility."
 echo
 echo " You can make keychain work with your csh-compatible shell by adding the"
 echo " following to your .cshrc:"
 echo
 echo $E "  ${CYAN}keychain ~/.ssh/id_rsa ~/.ssh/id_dsa"
 echo $E "  source ~/.keychain/\${HOSTNAME}-csh${OFF}"
 echo
 cat <<EOHELP
 Keychain allows all your apps and cron jobs to use a single ssh-agent process
 as an authentication agent.  By default, the ssh-agent started by keychain is
 long-running and will continue to run, even after you have logged out from the
 system.  If you'd like to tighten up security a bit, take a look at the
EOHELP
 echo $E " ${GREEN}--clear${OFF} option, described below."
 echo
 echo Options:
 echo
 echo $E " ${GREEN}--clear${OFF}"
 echo
 cat <<EOHELP
 Tells keychain to delete all of ssh-agent's host keys.  Typically, This is
 used in the ~/.bash_profile.  The theory behind this is that keychain should
 assume that you are an intruder until proven otherwise.  However, while this
 option increases security, it still allows your cron jobs to use your ssh keys
 when you're logged out.
EOHELP
 echo
 echo $E " ${GREEN}--dir [directoryname]${OFF}"
 echo
 cat <<EOHELP
 Keychain will look in [directoryname] for the .keychain file, rather than your
 home directory.
EOHELP

 echo
 echo $E " ${GREEN}--noask${OFF}"
 echo
 cat <<EOHELP
 This option tells keychain do everything it normally does (ensure ssh-agent is
 running, set up the ~/.keychain/[hostname]-{c}sh files) except that it will not
 prompt you to add any of the keys you specified if they haven't yet been added
 to ssh-agent.
EOHELP
 echo
 echo $E " ${GREEN}--nocolor${OFF}"
 echo
 echo " This option disables color highlighting for non vt-100-compatible terms."
 echo
 echo $E " ${GREEN}--stop | -k${OFF}"
 echo
 cat <<EOHELP
 This option tells keychain to stop all running ssh-agent processes, and then
 exit.
EOHELP
 echo
 echo $E " ${GREEN}--quiet | -q${OFF}"
 echo
 cat <<EOHELP
 This option tells keychain to turn off verbose mode and only print error
 messages and interactive messages. This is useful for login scripts etc.
EOHELP
 echo
#' this line is a simple fix for vim syntax highlighting
 rm -f "$lockf" 2> /dev/null
 exit 1
fi

# Query local host for operating system.
cygwin="no"
hpux="no"
myuname=`uname -s`
if [ -n "`echo $myuname | grep CYGWIN`" ]
then
 cygwin="yes"
elif [ -n "`echo $myuname | grep HP-UX`" ]
then
 hpux="yes"
fi

# Query local host for SSH application, presently supporting only
# OpenSSH (see http://www.openssh.org) when openssh="yes" and
# SSH2 (see http://www.ssh.com) when openssh="no".
openssh="no"
if [ -n "`ssh -V 2>&1 | grep OpenSSH`" ]
then
 openssh="yes"
fi

# Avoid trapping on signal names with Cygwin.
trapint="INT"
if [ "$cygwin" = "yes" ]
then
 trapint=2
fi

# Disallow ^C abortion, since keys may be in interim, unsafe states.
trap "" $trapint

# pidf holds the specific name of the keychain .ssh-agent-myhostname file.
# We use the new hostname extension for NFS compatibility. cshpidf is the
# .ssh-agent file with csh-compatible syntax. lockf is the lockfile, used
# to serialize the execution of multiple ssh-agent processes started
# simultaneously (only works if lockfile from the procmail package is
# available.

hostname=`uname -n`
pidf="${keydir}/${hostname}-sh"
cshpidf="${keydir}/${hostname}-csh"
lockf="${keydir}/${hostname}-lock"

if [ -f ${keydir} ]
then
 echo "$0: ${keydir} is a file (it should be a directory;) please fix."
 exit 1
#Solaris 9 doesn't have -e; using -d....
elif [ ! -d ${keydir} ]
then
 mkdir ${keydir} || exit 1
 chmod 0700 ${keydir}
fi

# perform lock if we have lockfile available
if type lockfile >/dev/null 2>&1; then
 lockfile -1 -r 30 -l 35 -s 2 "$lockf"
 if [ $? != 0 ]; then
  echo "$0: Couldn't get lock" >&2
  exit 1
 fi
fi

#auto-detect whether echo -e works.
unset BLUE GREEN OFF CYAN E
if [ -z "`echo -e`" ]
then
 E="-e"
 # color variables won't be defined if --nocolor is present
fi
if [ -z "$nocolopt" ]
then
 BLUE="\033[34;01m"
 GREEN="\033[32;01m"
 OFF="\033[0m"
 CYAN="\033[36;01m"
fi

if [ -z "$quietopt" ]
then
 echo
 echo $E "${GREEN}KeyChain ${version};
${BLUE}http://www.gentoo.org/projects/keychain${OFF}";
 echo $E " Copyright 2002 Gentoo Technologies, Inc.; Distributed under the GPL"
fi

me=`whoami`
if [ "$cygwin" = "yes" ]
then
 #for cygwin
 psopts="-e -u $me -f"
elif [ "$hpux" = "yes" ]
then
 #for hp-ux
 psopts="-u $me -f"
else
 psopts="FAIL"
 #-x option needed on MacOS X, but just in case it doesn't work on other arches we
have a "-u $me -f"
 #at the end. "-uxw" works on modern Linux systems.
 for x in "-x -u $me -f" "-uxw" "-u $me -f"
 do
  ps $x >/dev/null 2>&1
  if [ $? -eq 0 ]
  then
   psopts="$x"
   break
  fi
 done
 if [ "$psopts" = "FAIL" ]
 then
  echo "$0: unable to use \"ps\" to scan for ssh-agent processes.  Report keychain
version and"
  echo "system configuration to drobbins at gentoo.org."
  rm -f "${lockf}" 2> /dev/null
  exit 1
 fi
fi

mypids=`ps $psopts 2>/dev/null | grep "[s]sh-agent"` > /dev/null 2>&1
#extract the second item from mypids:
if [ -n "$mypids" ]
then
 set $mypids
 mypids=$2
fi

if [ "$myaction" = "stop" ]
then
 # --stop tells keychain to kill the existing ssh-agent(s), then exit
 kill $mypids > /dev/null 2>&1
 rm -f "${pidf}" "${cshpidf}" "$lockf" 2> /dev/null
 #`whoami` (rather than the $LOGNAME var) gives us the euid rather than the uid
(what we want)
 if [ -z "$quietopt" ]
 then
  echo $E " ${GREEN}*${OFF} All ssh-agent(s) started by" `whoami` "are now
stopped."
  echo
 fi
 exit 0
fi

SSH_AGENT_PID="NULL"
if [ -f $pidf ]
then
 . $pidf
fi

# Copy application-specific environment variables into generic local variables.
SSH_AUTH_SOCK_NAME="SSH_AUTH_SOCK"
SSH_AGENT_PID_NAME="SSH_AGENT_PID"
if [ "$openssh" = "no" ]
then
 SSH_AUTH_SOCK=${SSH2_AUTH_SOCK}
 SSH_AGENT_PID=${SSH2_AGENT_PID}

 SSH_AUTH_SOCK_NAME="SSH2_AUTH_SOCK"
 SSH_AGENT_PID_NAME="SSH2_AGENT_PID"
fi

match="no"
for x in $mypids
do
 if [ "$x" = "$SSH_AGENT_PID" ]
 then
  if [ -z "$quietopt" ]
  then
   echo $E " ${GREEN}*${OFF} Found existing ssh-agent at PID ${x}"
  fi
  match="yes"
  break
 fi
done

if [ "$match" = "no" ]
then
 if [ -n "$mypids" ]
 then
  kill $mypids > /dev/null 2>&1
 fi
 if [ -z "$quietopt" ]
 then
  echo $E " ${GREEN}*${OFF} All previously running ssh-agent(s) have been
stopped."
  echo $E " ${GREEN}*${OFF} Initializing ${pidf} file..."
 fi

 # "> pidf" doesn't work ash.  But it should work with any sh-compatible shell
 > "$pidf" || { echo "$0: Cannot create ${pidf}; exiting." 1>&2; rm -f "$pidf"
"$cshpidf" "$lockf" 2> /dev/null; exit 1; }
 [ -z "$quietopt" ] && echo $E " ${GREEN}*${OFF} Initializing ${cshpidf} file..."
 > "$cshpidf" || { echo "$0: Cannot create ${cshpidf}; exiting." 1>&2; rm -f
"$pidf" "$cshpidf" "$lockf" 2> /dev/null; exit 1; }
 chmod 0600 "$pidf" "$cshpidf"
 [ -z "$quietopt" ] && echo $E " ${GREEN}*${OFF} Starting new ssh-agent"
 nohup ssh-agent -s | grep -v 'Agent pid' > "$pidf"
 . "$pidf"
 echo "setenv $SSH_AUTH_SOCK_NAME $SSH_AUTH_SOCK;" > "$cshpidf"
 echo "setenv $SSH_AGENT_PID_NAME $SSH_AGENT_PID;" >> "$cshpidf"
fi

if [ -n "$clearopt" ]
then
 echo $E " ${GREEN}*${OFF} \c"
 ssh-add -D
fi

#now that keys are potentially cleared, it's safe to be aborted by ^C
trap - $trapint

if [ -n "$noaskopt" ]
then
 # --noask means "don't ask for keys", so skip this next part
 echo
 rm -f "$lockf" 2> /dev/null
 exit 0
fi

# hook in to existing agent
. "$pidf"

missingkeys="START"
#below, previous count of missing keys, and count of missing keys, respectively.
#when the difference between these two numbers does not abort after three tries,
#we abort the loop (using $countdown)
pmcount=0
mcount=0
countdown=3
while [ $countdown -gt 1 ] && [ "$missingkeys" != "" ]
do
 pmcount=$mcount
 mcount=0
 myfail=0
 missingkeys=""

 # Generate and parse verbose listing of already added keys.
 if [ "$openssh" = "no" ]
 then
  myavail=`ssh-add -l 2>&1 | tail +2 | awk '{ sub(/:.*/, ""); print }'`
 else
  myavail=`ssh-add -l 2>&1 | cut -f2 -d " "`
 fi

 if [ $? -ne 0 ]
 then
  echo $E " ${CYAN}*${OFF} Problems listing keys; exiting..."
  exit 1
 fi
 for x in $mykeys
 do
  if [ ! -f "$x" ]
  then
   echo $E " ${CYAN}*${OFF} Can't find ${x}; skipping..."
   continue
  fi

  # Extract relevant metadata from current user-specified key.
  if [ "$openssh" = "no" ]
  then
   myfing=`basename ${x} 2>&1 | cut -f2 -d " "`
  else
   if [ -f "${x}.pub" ]
   then
    myfing=`ssh-keygen -l -f ${x}.pub 2>&1`
   else
    myfing=`ssh-keygen -l -f ${x} 2>&1`
    if [ $? -ne 0 ]
    then
     echo $E " ${CYAN}*${OFF} Warning: ${x}.pub missing; can't tell if key ${x}
already loaded."
     myfail=3
    fi
   fi
   myfing=`echo ${myfing} | cut -f2 -d " "`
  fi

  skip=0
  for y in $myavail
  do
   if [ "$y" = "$myfing" ]
   then
    skip=1
    break
   fi
  done
  if [ $skip -ne 1 ]
  then
   missingkeys="$missingkeys $x"
   mcount=`expr $mcount + 1`
  fi
 done
 if [ "$missingkeys" = "" ]
 then
  break
 fi
 if [ `expr $pmcount - $mcount` -eq 0 ]
 then
  countdown=`expr $countdown - 1`
 else
  countdown=3
 fi
 if [ -z "$quietopt" ]
 then
  echo $E " ${GREEN}*${OFF} ${BLUE}${mcount}${OFF} more keys to add..."
 fi
 if [ -n "$SSH_ASKPASS" ]
 then
  ssh-add ${missingkeys} < /dev/null
 else
  ssh-add ${missingkeys}
 fi
 if [ $? -ne 0 ]
 then
  myfail=`expr $myfail + 1`
  echo $E " ${CYAN}*${OFF} Problem adding key${OFF}..."
 fi
done
if [ -z "$quietopt" ]
then
 echo
fi
#remove lockfile if it exists
rm -f "$lockf" 2> /dev/null

#end of keychain

till next
    Jim Kelly-Rand





BLU is a member of BostonUserGroups
BLU is a member of BostonUserGroups
We also thank MIT for the use of their facilities.

Valid HTML 4.01! Valid CSS!



Boston Linux & Unix / webmaster@blu.org