/[gentoo-src]/keychain/keychain
Gentoo

Contents of /keychain/keychain

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.28 - (show annotations) (download)
Wed Apr 21 22:41:13 2004 UTC (16 years, 5 months ago) by agriffis
Branch: MAIN
CVS Tags: HEAD
Changes since 1.27: +1 -1 lines
FILE REMOVED
finally commit my keychain changes... version 2.2.0

1 #!/bin/sh
2 # Copyright 1999-2003 Gentoo Technologies, Inc.
3 # Distributed under the terms of the GNU General Public License v2
4 # Author: Daniel Robbins <drobbins@gentoo.org>
5 # Current Maintainer: Seth Chandler <sethbc@gentoo.org>
6 # $Header: /home/cvsroot/gentoo-src/keychain/keychain,v 1.27 2003/04/17 18:40:59 sethbc Exp $
7
8 version=2.0.3
9
10 PATH="/sbin:/usr/sbin:${PATH}:/usr/ucb"; export PATH;
11
12 myaction=""
13 myactionarg=""
14 noaskopt=""
15 quietopt=""
16 nocolopt=""
17 clearopt=""
18 mykeys=""
19 keydir="${HOME}/.keychain"
20 while [ -n "$1" ]
21 do
22 case $1 in
23 -h|--help|--stop|-k)
24 #action specified
25 if [ -z "$myaction" ]
26 then
27 case $1 in
28 -h|--help)
29 myaction="help"
30 ;;
31 --stop|-k)
32 myaction="stop"
33 ;;
34 esac
35 myactionarg="$1"
36 else
37 echo "$0: you can't specify $myactionarg and $1 at the same time; exiting."
38 exit 1
39 fi
40 ;;
41 --dir)
42 shift
43 keydir="${1}/.keychain"
44 ;;
45 --clear)
46 clearopt="yes"
47 ;;
48 --noask)
49 noaskopt="yes"
50 ;;
51 -q|--quiet)
52 quietopt="yes"
53 ;;
54 --nocolor)
55 nocolopt="yes"
56 ;;
57 *)
58 mykeys="${mykeys} $1"
59 ;;
60 esac
61 shift
62 done
63
64 #auto-detect whether echo -e works.
65 unset E
66 if [ -z "`echo -e`" ]
67 then
68 E="-e"
69 fi
70
71 BLUE="\033[34;01m"
72 GREEN="\033[32;01m"
73 OFF="\033[0m"
74 CYAN="\033[36;01m"
75
76 # color variables won't be defined if --nocolor is present
77 if [ "$nocolopt" = "yes" ]
78 then
79 unset BLUE GREEN OFF CYAN
80 fi
81
82
83 #first, handle help.
84 if [ "$myaction" = "help" ]
85 then
86 echo $E Usage: ${CYAN}${0}${OFF} [ ${GREEN}options${OFF} ] ${CYAN}sshkey${OFF} ...
87 cat <<EOHELP
88
89 Description:
90
91 Keychain is an OpenSSH key manager, typically run from ~/.bash_profile. When
92 run, it will make sure ssh-agent is running; if not, it will start ssh-agent.
93 It will redirect ssh-agent's output to ~/.keychain/[hostname]-sh, so that cron
94 jobs that need to use ssh-agent keys can simply source this file and make the
95 necessary passwordless ssh connections. In addition, when keychain runs, it
96 will check with ssh-agent and make sure that the ssh RSA/DSA keys that you
97 specified on the keychain command line have actually been added to ssh-agent.
98 If not, you are prompted for the appropriate passphrases so that they can be
99 added by keychain.
100
101 Typically, one uses keychain by adding the following to the top of their
102 ~/.bash_profile (or ~/.zlogin, in case of zsh):
103
104 EOHELP
105 echo $E " ${CYAN}keychain ~/.ssh/id_rsa ~/.ssh/id_dsa"
106 echo $E " . ~/.keychain/\${HOSTNAME}-sh${OFF}"
107 echo
108 echo $E " # alt. syntax: . ~/.keychain/\`uname -n\`-sh"
109 echo $E " # note the use of back-quotes (\`) rather than single-quotes (') above."
110 echo $E " # We now include the hostname (\`uname -n\`) in the keychain filename"
111 echo $E " # for NFS-compatibility."
112 echo
113 echo " You can make keychain work with your csh-compatible shell by adding the"
114 echo " following to your .cshrc:"
115 echo
116 echo $E " ${CYAN}keychain ~/.ssh/id_rsa ~/.ssh/id_dsa"
117 echo $E " source ~/.keychain/\${HOSTNAME}-csh${OFF}"
118 echo
119 cat <<EOHELP
120 Keychain allows all your apps and cron jobs to use a single ssh-agent process
121 as an authentication agent. By default, the ssh-agent started by keychain is
122 long-running and will continue to run, even after you have logged out from the
123 system. If you'd like to tighten up security a bit, take a look at the
124 EOHELP
125 echo $E " ${GREEN}--clear${OFF} option, described below."
126 echo
127 echo Options:
128 echo
129 echo $E " ${GREEN}--clear${OFF}"
130 echo
131 cat <<EOHELP
132 Tells keychain to delete all of ssh-agent's host keys. Typically, This is
133 used in the ~/.bash_profile. The theory behind this is that keychain should
134 assume that you are an intruder until proven otherwise. However, while this
135 option increases security, it still allows your cron jobs to use your ssh keys
136 when you're logged out.
137 EOHELP
138 echo
139 echo $E " ${GREEN}--dir [directoryname]${OFF}"
140 echo
141 cat <<EOHELP
142 Keychain will look in [directoryname] for the .keychain file, rather than your
143 home directory.
144 EOHELP
145
146 echo
147 echo $E " ${GREEN}--noask${OFF}"
148 echo
149 cat <<EOHELP
150 This option tells keychain do everything it normally does (ensure ssh-agent is
151 running, set up the ~/.keychain/[hostname]-{c}sh files) except that it will not
152 prompt you to add any of the keys you specified if they haven't yet been added
153 to ssh-agent.
154 EOHELP
155 echo
156 echo $E " ${GREEN}--nocolor${OFF}"
157 echo
158 echo " This option disables color highlighting for non vt-100-compatible terms."
159 echo
160 echo $E " ${GREEN}--stop | -k${OFF}"
161 echo
162 cat <<EOHELP
163 This option tells keychain to stop all running ssh-agent processes, and then
164 exit.
165 EOHELP
166 echo
167 echo $E " ${GREEN}--quiet | -q${OFF}"
168 echo
169 cat <<EOHELP
170 This option tells keychain to turn off verbose mode and only print error
171 messages and interactive messages. This is useful for login scripts etc.
172 EOHELP
173 echo
174 #' this line is a simple fix for vim syntax highlighting
175 rm -f "$lockf" 2> /dev/null
176 exit 1
177 fi
178
179 # Query local host for operating system.
180 cygwin="no"
181 hpux="no"
182 myuname=`uname -s`
183 if [ -n "`echo $myuname | grep CYGWIN`" ]
184 then
185 cygwin="yes"
186 elif [ -n "`echo $myuname | grep HP-UX`" ]
187 then
188 hpux="yes"
189 fi
190
191 # Query local host for SSH application, presently supporting only
192 # OpenSSH (see http://www.openssh.org) when openssh="yes" and
193 # SSH2 (see http://www.ssh.com) when openssh="no".
194 openssh="no"
195 if [ -n "`ssh -V 2>&1 | grep OpenSSH`" ]
196 then
197 openssh="yes"
198 fi
199
200 # Avoid trapping on signal names with Cygwin.
201 trapint="INT"
202 if [ "$cygwin" = "yes" ]
203 then
204 trapint=2
205 fi
206
207 # Disallow ^C abortion, since keys may be in interim, unsafe states.
208 trap "" $trapint
209
210 # pidf holds the specific name of the keychain .ssh-agent-myhostname file.
211 # We use the new hostname extension for NFS compatibility. cshpidf is the
212 # .ssh-agent file with csh-compatible syntax. lockf is the lockfile, used
213 # to serialize the execution of multiple ssh-agent processes started
214 # simultaneously (only works if lockfile from the procmail package is
215 # available.
216
217 hostname=`uname -n`
218 pidf="${keydir}/${hostname}-sh"
219 cshpidf="${keydir}/${hostname}-csh"
220 lockf="${keydir}/${hostname}-lock"
221
222 if [ -f ${keydir} ]
223 then
224 echo "$0: ${keydir} is a file (it should be a directory;) please fix."
225 exit 1
226 #Solaris 9 doesn't have -e; using -d....
227 elif [ ! -d ${keydir} ]
228 then
229 mkdir ${keydir} || exit 1
230 chmod 0700 ${keydir}
231 fi
232
233 # perform lock if we have lockfile available
234 if type lockfile >/dev/null 2>&1; then
235 lockfile -1 -r 30 -l 35 -s 2 "$lockf"
236 if [ $? != 0 ]; then
237 echo "$0: Couldn't get lock" >&2
238 exit 1
239 fi
240 fi
241
242 if [ -z "$quietopt" ]
243 then
244 echo
245 echo $E "${GREEN}KeyChain ${version}; ${BLUE}http://www.gentoo.org/projects/keychain${OFF}"
246 echo $E " Copyright 2002 Gentoo Technologies, Inc.; Distributed under the GPL"
247 fi
248
249 me=`whoami`
250 if [ "$cygwin" = "yes" ]
251 then
252 #for cygwin
253 psopts="-e -u $me -f"
254 grepopts="-i"
255 elif [ "$hpux" = "yes" ]
256 then
257 #for hp-ux
258 psopts="-u $me -f"
259 else
260 psopts="FAIL"
261 #-x option needed on MacOS X, but just in case it doesn't work on other arches we have a "-u $me -f"
262 #at the end. "-uxw" works on modern Linux systems.
263 for x in "-x -u $me -f" "-uxw" "-u $me -f"
264 do
265 ps $x >/dev/null 2>&1
266 if [ $? -eq 0 ]
267 then
268 psopts="$x"
269 break
270 fi
271 done
272 if [ "$psopts" = "FAIL" ]
273 then
274 echo "$0: unable to use \"ps\" to scan for ssh-agent processes. Report keychain version and"
275 echo "system configuration to sethbc@gentoo.org."
276 rm -f "${lockf}" 2> /dev/null
277 exit 1
278 fi
279 fi
280
281 mypids=`ps $psopts 2>/dev/null | grep $grepopts "[s]sh-agent"` > /dev/null 2>&1
282 #extract the second item from mypids:
283 if [ -n "$mypids" ]
284 then
285 set $mypids
286 mypids=$2
287 fi
288
289 if [ "$myaction" = "stop" ]
290 then
291 # --stop tells keychain to kill the existing ssh-agent(s), then exit
292 kill $mypids > /dev/null 2>&1
293 rm -f "${pidf}" "${cshpidf}" "$lockf" 2> /dev/null
294 #`whoami` (rather than the $LOGNAME var) gives us the euid rather than the uid (what we want)
295 if [ -z "$quietopt" ]
296 then
297 echo $E " ${GREEN}*${OFF} All ssh-agent(s) started by" `whoami` "are now stopped."
298 echo
299 fi
300 exit 0
301 fi
302
303 SSH_AGENT_PID="NULL"
304 if [ -f $pidf ]
305 then
306 . $pidf
307 fi
308
309 # Copy application-specific environment variables into generic local variables.
310 SSH_AUTH_SOCK_NAME="SSH_AUTH_SOCK"
311 SSH_AGENT_PID_NAME="SSH_AGENT_PID"
312 if [ "$openssh" = "no" ]
313 then
314 SSH_AUTH_SOCK=${SSH2_AUTH_SOCK}
315 SSH_AGENT_PID=${SSH2_AGENT_PID}
316
317 SSH_AUTH_SOCK_NAME="SSH2_AUTH_SOCK"
318 SSH_AGENT_PID_NAME="SSH2_AGENT_PID"
319 fi
320
321 match="no"
322 for x in $mypids
323 do
324 if [ "$x" = "$SSH_AGENT_PID" ]
325 then
326 if [ -z "$quietopt" ]
327 then
328 echo $E " ${GREEN}*${OFF} Found existing ssh-agent at PID ${x}"
329 fi
330 match="yes"
331 break
332 fi
333 done
334
335 if [ "$match" = "no" ]
336 then
337 if [ -n "$mypids" ]
338 then
339 kill $mypids > /dev/null 2>&1
340 fi
341 if [ -z "$quietopt" ]
342 then
343 echo $E " ${GREEN}*${OFF} All previously running ssh-agent(s) have been stopped."
344 echo $E " ${GREEN}*${OFF} Initializing ${pidf} file..."
345 fi
346
347 # "> pidf" doesn't work ash. But it should work with any sh-compatible shell
348 > "$pidf" || { echo "$0: Cannot create ${pidf}; exiting." 1>&2; rm -f "$pidf" "$cshpidf" "$lockf" 2> /dev/null; exit 1; }
349 [ -z "$quietopt" ] && echo $E " ${GREEN}*${OFF} Initializing ${cshpidf} file..."
350 > "$cshpidf" || { echo "$0: Cannot create ${cshpidf}; exiting." 1>&2; rm -f "$pidf" "$cshpidf" "$lockf" 2> /dev/null; exit 1; }
351 chmod 0600 "$pidf" "$cshpidf"
352 [ -z "$quietopt" ] && echo $E " ${GREEN}*${OFF} Starting new ssh-agent"
353 nohup ssh-agent -s | grep -v 'Agent pid' > "$pidf"
354 . "$pidf"
355 echo "setenv $SSH_AUTH_SOCK_NAME $SSH_AUTH_SOCK;" > "$cshpidf"
356 echo "setenv $SSH_AGENT_PID_NAME $SSH_AGENT_PID;" >> "$cshpidf"
357 fi
358
359 if [ -n "$clearopt" ]
360 then
361 echo $E " ${GREEN}*${OFF} \c"
362 ssh-add -D
363 fi
364
365 #now that keys are potentially cleared, it's safe to be aborted by ^C
366 trap - $trapint
367
368 if [ -n "$noaskopt" ]
369 then
370 # --noask means "don't ask for keys", so skip this next part
371 echo
372 rm -f "$lockf" 2> /dev/null
373 exit 0
374 fi
375
376 # hook in to existing agent
377 . "$pidf"
378
379 missingkeys="START"
380 #below, previous count of missing keys, and count of missing keys, respectively.
381 #when the difference between these two numbers does not abort after three tries,
382 #we abort the loop (using $countdown)
383 pmcount=0
384 mcount=0
385 countdown=3
386 while [ $countdown -gt 1 ] && [ "$missingkeys" != "" ]
387 do
388 pmcount=$mcount
389 mcount=0
390 myfail=0
391 missingkeys=""
392
393 # Generate and parse verbose listing of already added keys.
394 if [ "$openssh" = "no" ]
395 then
396 myavail=`ssh-add -l 2>&1 | tail +2 | awk '{ sub(/:.*/, ""); print }'`
397 else
398 myavail=`ssh-add -l 2>&1 | cut -f2 -d " "`
399 fi
400
401 if [ $? -ne 0 ]
402 then
403 echo $E " ${CYAN}*${OFF} Problems listing keys; exiting..."
404 exit 1
405 fi
406 for x in $mykeys
407 do
408 if [ ! -f "$x" ]
409 then
410 echo $E " ${CYAN}*${OFF} Can't find ${x}; skipping..."
411 continue
412 fi
413
414 # Extract relevant metadata from current user-specified key.
415 if [ "$openssh" = "no" ]
416 then
417 myfing=`basename ${x} 2>&1 | cut -f2 -d " "`
418 else
419 if [ -f "${x}.pub" ]
420 then
421 myfing=`ssh-keygen -l -f ${x}.pub 2>&1`
422 else
423 myfing=`ssh-keygen -l -f ${x} 2>&1`
424 if [ $? -ne 0 ]
425 then
426 echo $E " ${CYAN}*${OFF} Warning: ${x}.pub missing; can't tell if key ${x} already loaded."
427 myfail=3
428 fi
429 fi
430 myfing=`echo ${myfing} | cut -f2 -d " "`
431 fi
432
433 skip=0
434 for y in $myavail
435 do
436 if [ "$y" = "$myfing" ]
437 then
438 skip=1
439 break
440 fi
441 done
442 if [ $skip -ne 1 ]
443 then
444 missingkeys="$missingkeys $x"
445 mcount=`expr $mcount + 1`
446 fi
447 done
448 if [ "$missingkeys" = "" ]
449 then
450 break
451 fi
452 if [ `expr $pmcount - $mcount` -eq 0 ]
453 then
454 countdown=`expr $countdown - 1`
455 else
456 countdown=3
457 fi
458 if [ -z "$quietopt" ]
459 then
460 echo $E " ${GREEN}*${OFF} ${BLUE}${mcount}${OFF} more keys to add..."
461 fi
462 if [ -n "$SSH_ASKPASS" ]
463 then
464 ssh-add ${missingkeys} < /dev/null
465 else
466 ssh-add ${missingkeys}
467 fi
468 if [ $? -ne 0 ]
469 then
470 myfail=`expr $myfail + 1`
471 echo $E " ${CYAN}*${OFF} Problem adding key${OFF}..."
472 fi
473 done
474 if [ -z "$quietopt" ]
475 then
476 echo
477 fi
478 #remove lockfile if it exists
479 rm -f "$lockf" 2> /dev/null

  ViewVC Help
Powered by ViewVC 1.1.20