Package: keychain Version: 2.8.1-0.1 Severity: normal Tags: patch pending Dear maintainer,
I've prepared an NMU for keychain (versioned as 2.8.2-0.1) and uploaded it to DELAYED/2. Please feel free to tell me if I should delay it longer. Regards. diff -Nru keychain-2.8.1/ChangeLog keychain-2.8.2/ChangeLog --- keychain-2.8.1/ChangeLog 2015-05-29 16:48:32.000000000 +0000 +++ keychain-2.8.2/ChangeLog 2015-11-07 00:11:24.000000000 +0000 @@ -2,7 +2,7 @@ # # Copyright 2002-2006 Gentoo Foundation http://www.gentoo.org/ # Copyright 2007 Aron Griffis <agrif...@n01se.net> -# Copyright 2009-2015 Funtoo Technolgies, LLC. +# Copyright 2009-2015 Funtoo Solutions, Inc. # lockfile() Copyright 2009 Parallels, Inc. # Distributed under the GNU General Public License version 2 @@ -12,6 +12,21 @@ # Maintained and rewritten April 2004 - July 2007 by Aron Griffis <agrif...@n01se.net> # Maintained July 2009 - present by Daniel Robbins <drobb...@funtoo.org> +* keychain 2.8.2 (06 Nov 2015) + + Summary: Support new ssh features, bug fix release. + + Support for new hash algorithms (Ben Boeckel) + + Remove bashisms (Daniel Hertz) + + Various optimizations (Daniel Hahler) + + --timeout option now gets passed to agent, doc fixes (Andrew Bezella, Emil + Lundberg) + + RPM, Makefile fixes (Mike Frysinger) + * keychain 2.8.1 (29 May 2015) Summary: POSIX compatibility and bug fix release. diff -Nru keychain-2.8.1/debian/changelog keychain-2.8.2/debian/changelog --- keychain-2.8.1/debian/changelog 2015-09-05 07:04:43.000000000 +0000 +++ keychain-2.8.2/debian/changelog 2016-12-31 22:35:22.000000000 +0000 @@ -1,3 +1,17 @@ +keychain (2.8.2-0.1) unstable; urgency=medium + + * Non-maintainer upload. + * New upstream release. (Closes: #847445) + - Fixes bashisms causing syntax errors. (Closes: #815510) + - Cleanly separates the --help output for --stop and + --systemd. (Closes: #800555) + * Convert to 3.0 (quilt) source format to avoid making this + a native package again. (see #800555) + * Convert d/rules to dh7-style given that upstream removed + its build system. + + -- Niels Thykier <ni...@thykier.net> Sat, 31 Dec 2016 22:35:22 +0000 + keychain (2.8.1-0.1) unstable; urgency=medium * Non-maintainer upload. diff -Nru keychain-2.8.1/debian/docs keychain-2.8.2/debian/docs --- keychain-2.8.1/debian/docs 1970-01-01 00:00:00.000000000 +0000 +++ keychain-2.8.2/debian/docs 2016-12-31 22:29:05.000000000 +0000 @@ -0,0 +1 @@ +keychain.pod diff -Nru keychain-2.8.1/debian/install keychain-2.8.2/debian/install --- keychain-2.8.1/debian/install 1970-01-01 00:00:00.000000000 +0000 +++ keychain-2.8.2/debian/install 2016-12-31 22:26:40.000000000 +0000 @@ -0,0 +1 @@ +keychain usr/bin/ diff -Nru keychain-2.8.1/debian/keychain.docs keychain-2.8.2/debian/keychain.docs --- keychain-2.8.1/debian/keychain.docs 2015-09-05 06:51:25.000000000 +0000 +++ keychain-2.8.2/debian/keychain.docs 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -README.md diff -Nru keychain-2.8.1/debian/manpages keychain-2.8.2/debian/manpages --- keychain-2.8.1/debian/manpages 1970-01-01 00:00:00.000000000 +0000 +++ keychain-2.8.2/debian/manpages 2016-12-31 22:29:10.000000000 +0000 @@ -0,0 +1 @@ +keychain.1 diff -Nru keychain-2.8.1/debian/rules keychain-2.8.2/debian/rules --- keychain-2.8.1/debian/rules 2015-09-05 06:59:17.000000000 +0000 +++ keychain-2.8.2/debian/rules 2016-12-31 22:26:55.000000000 +0000 @@ -1,90 +1,3 @@ #!/usr/bin/make -f -# Sample debian/rules that uses debhelper. -# GNU copyright 1997 to 1999 by Joey Hess. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -configure: configure-stamp -configure-stamp: - dh_testdir - # Add here commands to configure the package. - - - touch configure-stamp - -build-arch: -# We have nothing to do by default. - -build-indep build: configure-stamp build-stamp -build-stamp: - dh_testdir - - # Add here commands to compile the package. - $(MAKE) keychain keychain.1 - - touch build-stamp - -clean: - dh_testdir - dh_testroot - rm -f build-stamp configure-stamp - - # Add here commands to clean up after the build process. - $(MAKE) clean - - dh_clean - -install: install-indep install-arch - -install-arch: build-arch -# We have nothing to do by default. - -install-indep: build-indep - dh_testdir - dh_testroot - dh_prep - dh_installdirs - - # Add here commands to install the package into debian/keychain. - #$(MAKE) install DESTDIR=$(CURDIR)/debian/keychain - install -m0755 keychain $(CURDIR)/debian/keychain/usr/bin - - -# Build architecture-independent files here. -binary-indep: build-indep install-indep - dh_testdir - dh_testroot -# dh_installdebconf - dh_installdocs keychain.pod - dh_installexamples -# dh_installmenu -# dh_installlogrotate -# dh_installemacsen -# dh_installpam -# dh_installmime -# dh_installinit -# dh_installcron - dh_installman keychain.1 -# dh_installinfo -# dh_undocumented - dh_installchangelogs ChangeLog - dh_link - dh_strip - dh_compress - dh_fixperms -# dh_makeshlibs - dh_installdeb -# dh_perl - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - - -# Build architecture-dependent files here. -binary-arch: build-arch install-arch -# We have nothing to do by default. - -binary: binary-indep binary-arch -.PHONY: build clean build-arch build-indep binary-indep binary-arch binary install configure +%: + dh $@ diff -Nru keychain-2.8.1/debian/source/format keychain-2.8.2/debian/source/format --- keychain-2.8.1/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ keychain-2.8.2/debian/source/format 2016-12-31 22:34:32.000000000 +0000 @@ -0,0 +1 @@ +3.0 (quilt) Binary files /tmp/YpzSyybuvv/keychain-2.8.1/img/keychain-1.png and /tmp/Uo5yHcUAep/keychain-2.8.2/img/keychain-1.png differ Binary files /tmp/YpzSyybuvv/keychain-2.8.1/img/keychain-2.png and /tmp/Uo5yHcUAep/keychain-2.8.2/img/keychain-2.png differ diff -Nru keychain-2.8.1/keychain keychain-2.8.2/keychain --- keychain-2.8.1/keychain 1970-01-01 00:00:00.000000000 +0000 +++ keychain-2.8.2/keychain 2015-11-07 00:11:24.000000000 +0000 @@ -0,0 +1,1659 @@ +#!/bin/sh + +# Copyright 1999-2005 Gentoo Foundation +# Copyright 2007 Aron Griffis <agrif...@n01se.net> +# Copyright 2009-2015 Funtoo Solutions, Inc. +# lockfile() Copyright 2009 Parallels, Inc. + +# Distributed under the terms of the GNU General Public License v2 + +# Originally authored by Daniel Robbins <drobb...@gentoo.org> +# Maintained August 2002 - April 2003 by Seth Chandler <set...@gentoo.org> +# Maintained and rewritten April 2004 - July 2007 by Aron Griffis <agrif...@n01se.net> +# Maintained July 2009 - present by Daniel Robbins <drobb...@funtoo.org> + +version=2.8.2 + +PATH="${PATH:-/usr/bin:/bin:/sbin:/usr/sbin:/usr/ucb}" + +maintainer="drobb...@funtoo.org" +unset mesglog +unset myaction +unset agentsopt +havelock=false +unset hostopt +ignoreopt=false +noaskopt=false +noguiopt=false +nolockopt=false +lockwait=5 +openssh=unknown +sunssh=unknown +confhost=unknown +sshconfig=false +quickopt=false +quietopt=false +clearopt=false +color=true +inheritwhich=local-once +unset stopwhich +unset timeout +unset ssh_timeout +attempts=1 +unset sshavail +unset sshkeys +unset gpgkeys +unset mykeys +keydir="${HOME}/.keychain" +unset envf +evalopt=false +queryopt=false +confirmopt=false +absoluteopt=false +systemdopt=false +unset ssh_confirm +unset GREP_OPTIONS + +BLUE="[34;01m" +CYAN="[36;01m" +CYANN="[36m" +GREEN="[32;01m" +RED="[31;01m" +PURP="[35;01m" +OFF="[0m" + +# GNU awk and sed have regex issues in a multibyte environment. If any locale +# variables are set, then override by setting LC_ALL +unset pinentry_locale +if [ -n "$LANG$LC_ALL" ] || [ -n "`locale 2>/dev/null | egrep -v '="?(|POSIX|C)"?$' 2>/dev/null`" ]; then + # save LC_ALL so that pinentry-curses works right. This has always worked + # correctly for me but peper and kloeri had problems with it. + pinentry_lc_all="$LC_ALL" + LC_ALL=C + export LC_ALL +fi + +# synopsis: qprint "message" +qprint() { + $quietopt || echo "$*" >&2 +} + +# synopsis: mesg "message" +# Prettily print something to stderr, honors quietopt +mesg() { + qprint " ${GREEN}*${OFF} $*" +} + +# synopsis: warn "message" +# Prettily print a warning to stderr +warn() { + echo " ${RED}* Warning${OFF}: $*" >&2 +} + +# synopsis: error "message" +# Prettily print an error +error() { + echo " ${RED}* Error${OFF}: $*" >&2 +} + +# synopsis: die "message" +# Prettily print an error, then abort +die() { + [ -n "$1" ] && error "$*" + qprint + $evalopt && { echo; echo "false;"; } + exit 1 +} + +# synopsis: versinfo +# Display the version information +versinfo() { + qprint + qprint " Copyright ${CYANN}2002-2006${OFF} Gentoo Foundation;" + qprint " Copyright ${CYANN}2007${OFF} Aron Griffis;" + qprint " Copyright ${CYANN}2009-2015${OFF} Funtoo Solutions, Inc;" + qprint " lockfile() Copyright ${CYANN}2009${OFF} Parallels, Inc." + qprint + qprint " Keychain is free software: you can redistribute it and/or modify" + qprint " it under the terms of the ${CYANN}GNU General Public License version 2${OFF} as" + qprint " published by the Free Software Foundation." + qprint +} + +# synopsis: helpinfo +# Display the help information. There's no really good way to use qprint for +# this... +helpinfo() { + cat >&1 <<EOHELP +SYNOPSIS + keychain [ ${GREEN}-hklQqV${OFF} ] [ ${GREEN}--clear${OFF} ${GREEN}--confhost${OFF} ${GREEN}--help${OFF} ${GREEN}--ignore-missing${OFF} ${GREEN}--list${OFF} + ${GREEN}--noask${OFF} ${GREEN}--nocolor${OFF} ${GREEN}--nogui${OFF} ${GREEN}--nolock${OFF} ${GREEN}--quick${OFF} ${GREEN}--quiet${OFF} ${GREEN}--version${OFF} ] + [ ${GREEN}--agents${OFF} ${CYAN}list${OFF} ] [ ${GREEN}--attempts${OFF} ${CYAN}num${OFF} ] [ ${GREEN}--dir${OFF} ${CYAN}dirname${OFF} ] + [ ${GREEN}--host${OFF} ${CYAN}name${OFF} ] [ ${GREEN}--lockwait${OFF} ${CYAN}seconds${OFF} ] + [ ${GREEN}--stop${OFF} ${CYAN}which${OFF} ] [ ${GREEN}--timeout${OFF} ${CYAN}minutes${OFF} ] [ keys... ] + +OPTIONS + ${GREEN}--agents${OFF} ${CYAN}list${OFF} + Start the agents listed. By default keychain will start ssh-agent if + it is found in your path. The list should be comma-separated, for + example "gpg,ssh" + + ${GREEN}--attempts${OFF} ${CYAN}num${OFF} + Try num times to add keys before giving up. The default is 1. + + ${GREEN}--clear${OFF} + Delete all of ssh-agent's keys. Typically this is used in + .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. + + ${GREEN}--confhost${OFF} + By default, keychain will look for key pairs in the ~/.ssh/ + directory. The ${GREEN}--confhost${OFF} option will inform keychain to look in + ~/.ssh/config for IdentityFile settings defined for particular + hosts, and use these paths to locate keys. + + ${GREEN}--confirm${OFF} + Keys are subject to interactive confirmation by the SSH_ASKPASS + program before being used for authentication. See the ${GREEN}-c${OFF} option for + ssh-add(1). + + ${GREEN}--absolute${OFF} + Any arguments to "--dir" are interpreted to be absolute. The default + behavior is to append "/.keychain" to the argument for backwards + compatibility. + + ${GREEN}--dir${OFF} ${CYAN}dirname${OFF} + Keychain will use dirname rather than \$HOME/.keychain + + ${GREEN}--query${OFF} + Keychain will print lines in KEY=value format representing the + values which are set by the agents. + + ${GREEN}--eval${OFF} + Keychain will print lines to be evaluated in the shell on stdout. It + respects the SHELL environment variable to determine if Bourne shell + or C shell output is expected. + + ${GREEN}--env${OFF} ${CYAN}filename${OFF} + After parsing options, keychain will load additional environment + settings from "filename". By default, if "--env" is not given, then + keychain will attempt to load from ~/.keychain/[hostname]-env or + alternatively ~/.keychain/env. The purpose of this file is to + override settings such as PATH, in case ssh is stored in a + non-standard place. + + ${GREEN}-h${OFF} ${GREEN}--help${OFF} + Show help that looks remarkably like this man-page. As of 2.6.10, + help is sent to stdout so it can be easily piped to a pager. + + ${GREEN}--host${OFF} ${CYAN}name${OFF} + Set alternate hostname for creation of pidfiles + + ${GREEN}--ignore-missing${OFF} + Don't warn if some keys on the command-line can't be found. This is + useful for situations where you have a shared .bash_profile, but + your keys might not be available on every machine where keychain is + run. + + ${GREEN}--inherit${OFF} ${CYAN}which${OFF} + Attempt to inherit agent variables from the environment. This can be + useful in a variety of circumstances, for example when ssh-agent is + started by gdm. The following values are valid for "which": + + local Inherit when a pid (e.g. SSH_AGENT_PID) is set in the + environment. This disallows inheriting a forwarded + agent. + + any Inherit when a sock (e.g. SSH_AUTH_SOCK) is set in the + environment. This allows inheriting a forwarded agent. + + local-once Same as "local", but only inherit if keychain isn't + already providing an agent. + + any-once Same as "any", but only inherit if keychain isn't + already providing an agent. + + By default, keychain-2.5.0 and later will behave as if "--inherit + local-once" is specified. You should specify "--noinherit" if you + want the older behavior. + + ${GREEN}-l${OFF} ${GREEN}--list${OFF} + List signatures of all active SSH keys, and exit, similar to + "ssh-add ${GREEN}-l${OFF}". + + ${GREEN}--lockwait${OFF} ${CYAN}seconds${OFF} + How long to wait for the lock to become available. Defaults to 5 + seconds. Specify a value of zero or more. If the lock cannot be + acquired within the specified number of seconds, then this keychain + process will forcefully acquire the lock. + + ${GREEN}--noask${OFF} + 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. + + ${GREEN}--nocolor${OFF} + Disable color hilighting for non ANSI-compatible terms. + + ${GREEN}--nogui${OFF} + Don't honor SSH_ASKPASS, if it is set. This will cause ssh-add to + prompt on the terminal instead of using a graphical program. + + ${GREEN}--noinherit${OFF} + Don't inherit any agent processes, overriding the default "--inherit + local-once" + + ${GREEN}--nolock${OFF} + Don't attempt to use a lockfile while manipulating files, pids and + keys. + + ${GREEN}-k${OFF} ${GREEN}--stop${OFF} ${CYAN}which${OFF} + Kill currently running agent processes. The following values are + valid for "which": + + all Kill all agent processes and quit keychain immediately. + Prior to keychain-2.5.0, this was the behavior of the bare + "--stop" option. + + others Kill agent processes other than the one keychain is + providing. Prior to keychain-2.5.0, keychain would do this + automatically. The new behavior requires that you specify + it explicitly if you want it. + + mine Kill keychain's agent processes, leaving other agents + alone. + + ${GREEN}--systemd${OFF} + Inject environment variables into the systemd ${GREEN}--user${OFF} session. + + ${GREEN}-Q${OFF} ${GREEN}--quick${OFF} + If an ssh-agent process is running then use it. Don't verify the + list of keys, other than making sure it's non-empty. This option + avoids locking when possible so that multiple terminals can be + opened simultaneously without waiting on each other. + + ${GREEN}-q${OFF} ${GREEN}--quiet${OFF} + Only print messages in case of warning, error or required + interactivity. As of version 2.6.10, this also suppresses + "Identities added" messages for ssh-agent. + + ${GREEN}--timeout${OFF} ${CYAN}minutes${OFF} + Allows a timeout to be set for identities added to ssh-agent. When + this option is used with a keychain invocation that starts ssh-agent + itself, then keychain uses the appropriate ssh-agent option to set + the default timeout for ssh-agent. The ${GREEN}--timeout${OFF} option also gets + passed to ssh-add invocations, so any keys added to a running + ssh-agent will be individually configured to have the timeout + specified, overriding any ssh-agent default. + + Most users can simply use the timeout setting they desire and get + the result they want ${GREEN}--${OFF} with all identities having the specified + timeout, whether added by keychain or not. More advanced users can + use one invocation of keychain to set the default timeout, and + optionally set different timeouts for keys added by using a + subsequent invocation of keychain. + + ${GREEN}-V${OFF} ${GREEN}--version${OFF} + Show version information. + +EOHELP +} + +# synopsis: testssh +# Figure out which ssh is in use, set the global boolean $openssh and $sunssh +testssh() { + # Query local host for SSH application, presently supporting + # OpenSSH, Sun SSH, and ssh.com + openssh=false + sunssh=false + case "`ssh -V 2>&1`" in + *OpenSSH*) openssh=true ;; + *Sun?SSH*) sunssh=true ;; + esac +} + +# synopsis: getuser +# Set the global string $me +getuser() { + # whoami gives euid, which might be different from USER or LOGNAME + me=`whoami` || die "Who are you? whoami doesn't know..." +} + +# synopsis: getos +# Set the global string $OSTYPE +getos() { + OSTYPE=`uname` || die 'uname failed' +} + +# synopsis: verifykeydir +# Make sure the key dir is set up correctly. Exits on error. +verifykeydir() { + # Create keydir if it doesn't exist already + if [ -f "${keydir}" ]; then + die "${keydir} is a file (it should be a directory)" + # Solaris 9 doesn't have -e; using -d.... + elif [ ! -d "${keydir}" ]; then + ( umask 0077 && mkdir "${keydir}"; ) || die "can't create ${keydir}" + fi +} + +lockfile() { + # This function originates from Parallels Inc.'s OpenVZ vpsreboot script + + # Description: This function attempts to acquire the lock. If it succeeds, + # it returns 0. If it fails, it returns 1. This function retuns immediately + # and only tries to acquire the lock once. + + local tmpfile="$lockf.$$" + + echo $$ >"$tmpfile" 2>/dev/null || exit + if ln "$tmpfile" "$lockf" 2>/dev/null; then + rm -f "$tmpfile" + havelock=true && return 0 + fi + if kill -0 `cat $lockf 2>/dev/null` 2>/dev/null; then + rm -f "$tmpfile" + return 1 + fi + if ln "$tmpfile" "$lockf" 2>/dev/null; then + rm -f "$tmpfile" + havelock=true && return 0 + fi + rm -f "$tmpfile" "$lockf" && return 1 +} + +takelock() { + # Description: This function calls lockfile() multiple times if necessary + # to try to acquire the lock. It returns 0 on success and 1 on failure. + # Change in behavior: if timeout expires, we will forcefully acquire lock. + + [ "$havelock" = "true" ] && return 0 + [ "$nolockopt" = "true" ] && return 0 + + # First attempt: + lockfile && return 0 + + local counter=0 + mesg "Waiting $lockwait seconds for lock..." + while [ "$counter" -lt "$(( $lockwait * 2 ))" ] + do + lockfile && return 0 + sleep 0.5; counter=$(( $counter + 1 )) + done + rm -f "$lockf" && lockfile && return 0 + return 1 +} + + +# synopsis: droplock +# Drops the lock if we're holding it. +droplock() { + $havelock && [ -n "$lockf" ] && rm -f "$lockf" +} + +# synopsis: findpids [prog] +# Returns a space-separated list of agent pids. +# prog can be ssh or gpg, defaults to ssh. Note that if another prog is ever +# added, need to pay attention to the length for Solaris compatibility. +findpids() { + fp_prog=${1-ssh} + unset fp_psout + + # Different systems require different invocations of ps. Try to generalize + # the best we can. The only requirement is that the agent command name + # appears in the line, and the PID is the first item on the line. + [ -n "$OSTYPE" ] || getos + + # Try systems where we know what to do first + case "$OSTYPE" in + AIX|*bsd*|*BSD*|CYGWIN|darwin*|Linux|linux-gnu|OSF1) + fp_psout=`ps x 2>/dev/null` ;; # BSD syntax + HP-UX) + fp_psout=`ps -u $me 2>/dev/null` ;; # SysV syntax + SunOS) + case `uname -r` in + [56]*) + fp_psout=`ps -u $me 2>/dev/null` ;; # SysV syntax + *) + fp_psout=`ps x 2>/dev/null` ;; # BSD syntax + esac ;; + GNU|gnu) + fp_psout=`ps -g 2>/dev/null` ;; # GNU Hurd syntax + esac + + # If we didn't get a match above, try a list of possibilities... + # The first one will probably fail on systems supporting only BSD syntax. + if [ -z "$fp_psout" ]; then + fp_psout=`UNIX95=1 ps -u $me -o pid,comm 2>/dev/null | grep '^ *[0-9]'` + [ -z "$fp_psout" ] && fp_psout=`ps x 2>/dev/null` + fi + + # Return the list of pids; ignore case for Cygwin. + # Check only 8 characters since Solaris truncates at that length. + # Ignore defunct ssh-agents (bug 28599) + if [ -n "$fp_psout" ]; then + echo "$fp_psout" | \ + awk "BEGIN{IGNORECASE=1} /defunct/{next} + /$fp_prog-[a]gen/{print \$1}" | xargs + return 0 + fi + + # If none worked, we're stuck + error "Unable to use \"ps\" to scan for $fp_prog-agent processes" + error "Please report to $maintainer via http://bugs.gentoo.org" + return 1 +} + +# synopsis: stopagent [prog] +# --stop tells keychain to kill the existing agent(s) +# prog can be ssh or gpg, defaults to ssh. +stopagent() { + stop_prog=${1-ssh} + eval stop_except=\$\{${stop_prog}_agent_pid\} + stop_mypids=`findpids "$stop_prog"` + [ $? = 0 ] || die + + if [ -z "$stop_mypids" ]; then + mesg "No $stop_prog-agent(s) found running" + return 0 + fi + + case "$stopwhich" in + all) + kill $stop_mypids >/dev/null 2>&1 + mesg "All ${CYANN}$me${OFF}'s $stop_prog-agents stopped: ${CYANN}$stop_mypids${OFF}" + ;; + + others) + # Try to handle the case where we *will* inherit a pid + kill -0 $stop_except >/dev/null 2>&1 + if [ -z "$stop_except" -o $? != 0 -o \ + "$inheritwhich" = local -o "$inheritwhich" = any ]; then + if [ "$inheritwhich" != none ]; then + eval stop_except=\$\{inherit_${stop_prog}_agent_pid\} + kill -0 $stop_except >/dev/null 2>&1 + if [ -z "$stop_except" -o $? != 0 ]; then + # Handle ssh2 + eval stop_except=\$\{inherit_${stop_prog}2_agent_pid\} + fi + fi + fi + + # Filter out the running agent pid + unset stop_mynewpids + for stop_x in $stop_mypids; do + [ $stop_x -eq $stop_except ] 2>/dev/null && continue + stop_mynewpids="${stop_mynewpids+$stop_mynewpids }$stop_x" + done + + if [ -n "$stop_mynewpids" ]; then + kill $stop_mynewpids >/dev/null 2>&1 + mesg "Other ${CYANN}$me${OFF}'s $stop_prog-agents stopped: ${CYANN}$stop_mynewpids${OFF}" + else + mesg "No other $stop_prog-agent(s) than keychain's $stop_except found running" + fi + ;; + + mine) + if [ $stop_except -gt 0 ] 2>/dev/null; then + kill $stop_except >/dev/null 2>&1 + mesg "Keychain $stop_prog-agents stopped: ${CYANN}$stop_except${OFF}" + else + mesg "No keychain $stop_prog-agent found running" + fi + ;; + esac + + # remove pid files if keychain-controlled + if [ "$stopwhich" != others ]; then + if [ "$stop_prog" != ssh ]; then + rm -f "${pidf}-$stop_prog" "${cshpidf}-$stop_prog" "${fishpidf}-$stop_prog" 2>/dev/null + else + rm -f "${pidf}" "${cshpidf}" "${fishpidf}" 2>/dev/null + fi + + eval unset ${stop_prog}_agent_pid + fi +} + +# synopsis: inheritagents +# Save agent variables from the environment before they get wiped out +inheritagents() { + # Verify these global vars are null + unset inherit_ssh_auth_sock inherit_ssh_agent_pid + unset inherit_ssh2_auth_sock inherit_ssh2_agent_sock + unset inherit_gpg_agent_info inherit_gpg_agent_pid + + # Save variables so we can inherit a running agent + if [ "$inheritwhich" != none ]; then + if wantagent ssh; then + if [ -n "$SSH_AUTH_SOCK" ]; then + inherit_ssh_auth_sock="$SSH_AUTH_SOCK" + inherit_ssh_agent_pid="$SSH_AGENT_PID" + fi + + if [ -n "$SSH2_AUTH_SOCK" ]; then + inherit_ssh2_auth_sock="$SSH2_AUTH_SOCK" + inherit_ssh2_agent_pid="$SSH2_AGENT_PID" + fi + fi + + if wantagent gpg; then + if [ -n "$GPG_AGENT_INFO" ]; then + inherit_gpg_agent_info="$GPG_AGENT_INFO" + inherit_gpg_agent_pid=`echo "$GPG_AGENT_INFO" | cut -f2 -d:` + # GnuPG v.2.1+ removes $GPG_AGENT_INFO + elif [ -S "${GNUPGHOME:=$HOME/.gnupg}/S.gpg-agent" ]; then + inherit_gpg_agent_pid=$(findpids gpg) + inherit_gpg_agent_info="$GNUPGHOME/S.gpg-agent:${inherit_gpg_agent_pid}:1" + fi + fi + fi +} + +# synopsis: validinherit +# Test inherit_* variables for validity +validinherit() { + vi_agent="$1" + vi_status=0 + + if [ "$vi_agent" = ssh ]; then + if [ -n "$inherit_ssh_auth_sock" ]; then + ls "$inherit_ssh_auth_sock" >/dev/null 2>&1 + if [ $? != 0 ]; then + warn "SSH_AUTH_SOCK in environment is invalid; ignoring it" + unset inherit_ssh_auth_sock inherit_ssh_agent_pid + vi_status=1 + fi + fi + + if [ -n "$inherit_ssh2_auth_sock" ]; then + ls "$inherit_ssh2_auth_sock" >/dev/null 2>&1 + if [ $? != 0 ]; then + warn "SSH2_AUTH_SOCK in environment is invalid; ignoring it" + unset inherit_ssh2_auth_sock inherit_ssh2_agent_pid + vi_status=1 + fi + fi + + elif [ "$vi_agent" = gpg ]; then + if [ -n "$inherit_gpg_agent_pid" ]; then + kill -0 "$inherit_gpg_agent_pid" >/dev/null 2>&1 + if [ $? != 0 ]; then + unset inherit_gpg_agent_pid inherit_gpg_agent_info + warn "GPG_AGENT_INFO in environment is invalid; ignoring it" + vi_status=1 + fi + fi + fi + + return $vi_status +} + +# synopsis: catpidf_shell shell agents... +# cat the pid files for the given agents. This is used by loadagents and also +# for keychain output when --eval is given. +catpidf_shell() { + case "$1" in + */fish|fish) cp_pidf="$fishpidf" ;; + *csh) cp_pidf="$cshpidf" ;; + *) cp_pidf="$pidf" ;; + esac + shift + + for cp_a in "$@"; do + case "${cp_a}" in + ssh) [ -f "$cp_pidf" ] && cat "$cp_pidf" ;; + *) [ -f "${cp_pidf}-$cp_a" ] && cat "${cp_pidf}-$cp_a" ;; + esac + echo + done + + return 0 +} + +# synopsis: catpidf agents... +# cat the pid files for the given agents, appropriate for the current value of +# $SHELL. This is used for keychain output when --eval is given. +catpidf() { + catpidf_shell "$SHELL" "$@" +} + +# synopsis: loadagents agents... +# Load agent variables from $pidf and copy implementation-specific environment +# variables into generic global strings +loadagents() { + for la_a in "$@"; do + case "$la_a" in + ssh) + unset SSH_AUTH_SOCK SSH_AGENT_PID SSH2_AUTH_SOCK SSH2_AGENT_PID + eval "`catpidf_shell sh $la_a`" + if [ -n "$SSH_AUTH_SOCK" ]; then + ssh_auth_sock=$SSH_AUTH_SOCK + ssh_agent_pid=$SSH_AGENT_PID + elif [ -n "$SSH2_AUTH_SOCK" ]; then + ssh_auth_sock=$SSH2_AUTH_SOCK + ssh_agent_pid=$SSH2_AGENT_PID + else + unset ssh_auth_sock ssh_agent_pid + fi + ;; + + gpg) + unset GPG_AGENT_INFO + eval "`catpidf_shell sh $la_a`" + if [ -n "$GPG_AGENT_INFO" ]; then + la_IFS="$IFS" # save current IFS + IFS=':' # set IFS to colon to separate PATH + set -- $GPG_AGENT_INFO + IFS="$la_IFS" # restore IFS + gpg_agent_pid=$2 + fi + ;; + + *) + eval "`catpidf_shell sh $la_a`" + ;; + esac + done + + return 0 +} + +# synopsis: startagent [prog] +# Starts an agent if it isn't already running. +# Requires $ssh_agent_pid +startagent() { + start_prog=${1-ssh} + start_proto=${2-${start_prog}} + unset start_pid + start_inherit_pid=none + start_mypids=`findpids "$start_prog"` + [ $? = 0 ] || die + + # Unfortunately there isn't much way to genericize this without introducing + # a lot more supporting code/structures. + if [ "$start_prog" = ssh ]; then + start_pidf="$pidf" + start_cshpidf="$cshpidf" + start_fishpidf="$fishpidf" + start_pid="$ssh_agent_pid" + if [ -n "$inherit_ssh_auth_sock" -o -n "$inherit_ssh2_auth_sock" ]; then + if [ -n "$inherit_ssh_agent_pid" ]; then + start_inherit_pid="$inherit_ssh_agent_pid" + elif [ -n "$inherit_ssh2_agent_pid" ]; then + start_inherit_pid="$inherit_ssh2_agent_pid" + else + start_inherit_pid="forwarded" + fi + fi + else + start_pidf="${pidf}-$start_prog" + start_cshpidf="${cshpidf}-$start_prog" + start_fishpidf="${fishpidf}-$start_prog" + if [ "$start_prog" = gpg ]; then + start_pid="$gpg_agent_pid" + if [ -n "$inherit_gpg_agent_pid" ]; then + start_inherit_pid="$inherit_gpg_agent_pid" + fi + else + error "I don't know how to start $start_prog-agent (1)" + return 1 + fi + fi + [ "$start_pid" -gt 0 ] 2>/dev/null || start_pid=none + + # This hack makes the case statement easier + if [ "$inheritwhich" = any -o "$inheritwhich" = any-once ]; then + start_fwdflg=forwarded + else + unset start_fwdflg + fi + + # Check for an existing agent + start_tester="$inheritwhich: $start_mypids $start_fwdflg " + case "$start_tester" in + none:*" $start_pid "*|*-once:*" $start_pid "*) + mesg "Found existing ${start_prog}-agent: ${CYANN}$start_pid${OFF}" + return 0 + ;; + + *:*" $start_inherit_pid "*) + # This test was postponed until now to prevent generating warnings + validinherit "$start_prog" + if [ $? != 0 ]; then + # inherit_* vars have been removed from the environment. Try + # again now + startagent "$start_prog" + return $? + fi + mesg "Inheriting ${start_prog}-agent ($start_inherit_pid)" + ;; + + *) + # start_inherit_pid might be "forwarded" which we don't allow with, + # for example, local-once (the default setting) + start_inherit_pid=none + ;; + esac + + # Init the bourne-formatted pidfile + ( umask 0177 && :> "$start_pidf"; ) + if [ $? != 0 ]; then + rm -f "$start_pidf" "$start_cshpidf" "$start_fishpidf" 2>/dev/null + error "can't create $start_pidf" + return 1 + fi + + # Init the csh-formatted pidfile + ( umask 0177 && :> "$start_cshpidf"; ) + if [ $? != 0 ]; then + rm -f "$start_pidf" "$start_cshpidf" "$start_fishpidf" 2>/dev/null + error "can't create $start_cshpidf" + return 1 + fi + + # Init the fish-formatted pidfile + ( umask 0177 && :> "$start_fishpidf"; ) + if [ $? != 0 ]; then + rm -f "$start_pidf" "$start_cshpidf" "$start_fishpidf" 2>/dev/null + error "can't create $start_fishpidf" + return 1 + fi + + # Determine content for files + unset start_out + if [ "$start_inherit_pid" = none ]; then + + # Start the agent. + # Branch again since the agents start differently + mesg "Starting ${start_prog}-agent..." + if [ "$start_prog" = ssh ]; then + start_out=`ssh-agent ${ssh_timeout}` + elif [ "$start_prog" = gpg ]; then + if [ -n "${timeout}" ]; then + start_gpg_timeout="--default-cache-ttl `expr $timeout \* 60`" + else + unset start_gpg_timeout + fi + # the 1.9.x series of gpg spews debug on stderr + start_out=`gpg-agent --daemon --write-env-file $start_gpg_timeout 2>/dev/null` + else + error "I don't know how to start $start_prog-agent (2)" + return 1 + fi + if [ $? != 0 -a $? != 2 ]; then + rm -f "$start_pidf" "$start_cshpidf" "$start_fishpidf" 2>/dev/null + error "Failed to start ${start_prog}-agent" + return 1 + fi + + elif [ "$start_prog" = ssh -a -n "$inherit_ssh_auth_sock" ]; then + start_out="SSH_AUTH_SOCK=$inherit_ssh_auth_sock; export SSH_AUTH_SOCK;" + if [ "$inherit_ssh_agent_pid" -gt 0 ] 2>/dev/null; then + start_out="$start_out +SSH_AGENT_PID=$inherit_ssh_agent_pid; export SSH_AGENT_PID;" + fi + elif [ "$start_prog" = ssh -a -n "$inherit_ssh2_auth_sock" ]; then + start_out="SSH2_AUTH_SOCK=$inherit_ssh2_auth_sock; export SSH2_AUTH_SOCK; +SSH2_AGENT_PID=$inherit_ssh2_agent_pid; export SSH2_AGENT_PID;" + if [ "$inherit_ssh2_agent_pid" -gt 0 ] 2>/dev/null; then + start_out="$start_out +SSH2_AGENT_PID=$inherit_ssh2_agent_pid; export SSH2_AGENT_PID;" + fi + + elif [ "$start_prog" = gpg -a -n "$inherit_gpg_agent_info" ]; then + start_out="GPG_AGENT_INFO=$inherit_gpg_agent_info; export GPG_AGENT_INFO;" + + else + die "something bad happened" # should never be here + fi + + # Add content to pidfiles. + # Some versions of ssh-agent don't understand -s, which means to + # generate Bourne shell syntax. It appears they also ignore SHELL, + # according to http://bugs.gentoo.org/show_bug.cgi?id=52874 + # So make no assumptions. + start_out=`echo "$start_out" | grep -v 'Agent pid'` + case "$start_out" in + setenv*) + echo "$start_out" >"$start_cshpidf" + echo "$start_out" | awk '{print $2"="$3" export "$2";"}' >"$start_pidf" + ;; + *) + echo "$start_out" >"$start_pidf" + echo "$start_out" | sed 's/;.*/;/' | sed 's/=/ /' | sed 's/^/setenv /' >"$start_cshpidf" + echo "$start_out" | sed 's/;.*/;/' | sed 's/^\(.*\)=\(.*\);/set -e \1; set -x -U \1 \2;/' >"$start_fishpidf" + ;; + esac + + # Hey the agent should be started now... load it up! + loadagents "$start_prog" +} + +# synopsis: extract_fingerprints +# Extract the fingerprints from standard input, returns space-separated list. +# Utility routine for ssh_l and ssh_f +extract_fingerprints() { + while read ef_line; do + case "$ef_line" in + *\ *\ [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:*) + # Sun SSH spits out different things depending on the type of + # key. For example: + # md5 1024 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 /home/barney/.ssh/id_dsa(DSA) + # 2048 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 /home/barney/.ssh/id_rsa.pub + echo "$ef_line" | cut -f3 -d' ' + ;; + *\ [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:*) + # The more consistent OpenSSH format, we hope + # 1024 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 /home/barney/.ssh/id_dsa (DSA) + echo "$ef_line" | cut -f2 -d' ' + ;; + *\ [A-Z0-9][A-Z0-9]*:[A-Za-z0-9+/][A-Za-z0-9+/]*) + # The new OpenSSH 6.8+ format, + # 1024 SHA256:mVPwvezndPv/ARoIadVY98vAC0g+P/5633yTC4d/wXE /home/barney/.ssh/id_dsa (DSA) + echo "$ef_line" | cut -f2 -d' ' + ;; + *) + # Fall back to filename. Note that commercial ssh is handled + # explicitly in ssh_l and ssh_f, so hopefully this rule will + # never fire. + warn "Can't determine fingerprint from the following line, falling back to filename" + mesg "$ef_line" + basename "$ef_line" | sed 's/[ (].*//' + ;; + esac + done | xargs +} + +# synopsis: ssh_l +# Return space-separated list of known fingerprints +ssh_l() { + sl_mylist=`ssh-add -l 2>/dev/null` + sl_retval=$? + + if $openssh; then + # Error codes: + # 0 success + # 1 OpenSSH_3.8.1p1 on Linux: no identities (not an error) + # OpenSSH_3.0.2p1 on HP-UX: can't connect to auth agent + # 2 can't connect to auth agent + case $sl_retval in + 0) + echo "$sl_mylist" | extract_fingerprints + ;; + 1) + case "$sl_mylist" in + *"open a connection"*) sl_retval=2 ;; + esac + ;; + esac + return $sl_retval + + elif $sunssh; then + # Error codes (from http://docs.sun.com/db/doc/817-3936/6mjgdbvio?a=view) + # 0 success (even when there are no keys) + # 1 error + case $sl_retval in + 0) + echo "$sl_mylist" | extract_fingerprints + ;; + 1) + case "$sl_mylist" in + *"open a connection"*) sl_retval=2 ;; + esac + ;; + esac + return $sl_retval + + else + # Error codes: + # 0 success - however might say "The authorization agent has no keys." + # 1 can't connect to auth agent + # 2 bad passphrase + # 3 bad identity file + # 4 the agent does not have the requested identity + # 5 unspecified error + if [ $sl_retval = 0 ]; then + # Output of ssh-add -l: + # The authorization agent has one key: + # id_dsa_2048_a: 2048-bit dsa, agrif...@alpha.zk3.dec.com, Fri Jul 25 2003 10:53:49 -0400 + # Since we don't have a fingerprint, just get the filenames *shrug* + echo "$sl_mylist" | sed '2,$s/:.*//' | xargs + fi + return $sl_retval + fi +} + +# synopsis: ssh_f filename +# Return fingerprint for a keyfile +# Requires $openssh and $sunssh +ssh_f() { + sf_filename="$1" + + if $openssh || $sunssh; then + realpath_bin="`command -v realpath`" + # if private key is symlink and symlink to *.pub is missing: + if [ -L "$sf_filename" ] && [ ! -z "$realpath_bin" ]; then + sf_filename="`$realpath_bin $sf_filename`" + fi + lsf_filename="$sf_filename.pub" + if [ ! -f "$lsf_filename" ]; then + # try to remove extension from private key, *then* add .pub, and see if we now find it: + if [ -L "$sf_filename" ] && [ ! -z "$realpath_bin" ]; then + sf_filename="`$realpath_bin $sf_filename`" + fi + lsf_filename=`echo "$sf_filename" | sed 's/\.[^\.]*$//'`.pub + if [ ! -f "$lsf_filename" ]; then + warn "Cannot find public key for $1." + return 1 + fi + fi + sf_fing=`ssh-keygen -l -f "$lsf_filename"` || return 1 + echo "$sf_fing" | extract_fingerprints + else + # can't get fingerprint for ssh2 so use filename *shrug* + basename "$sf_filename" + fi + return 0 +} + +# synopsis: gpg_listmissing +# Uses $gpgkeys +# Returns a newline-separated list of keys found to be missing. +gpg_listmissing() { + unset glm_missing + + GPG_TTY=`tty` + + # Parse $gpgkeys into positional params to preserve spaces in filenames + set -f # disable globbing + glm_IFS="$IFS" # save current IFS + IFS=" +" # set IFS to newline + set -- $gpgkeys + IFS="$glm_IFS" # restore IFS + set +f # re-enable globbing + + for glm_k in "$@"; do + # Check if this key is known to the agent. Don't know another way... + if echo | env -i GPG_TTY="$GPG_TTY" PATH="$PATH" GPG_AGENT_INFO="$GPG_AGENT_INFO" \ + gpg --no-options --use-agent --no-tty --sign --local-user "$glm_k" -o- >/dev/null 2>&1; then + # already know about this key + mesg "Known gpg key: ${CYANN}${glm_k}${OFF}" + continue + else + # need to add this key + if [ -z "$glm_missing" ]; then + glm_missing="$glm_k" + else + glm_missing="$glm_missing +$glm_k" + fi + fi + done + + echo "$glm_missing" +} + +# synopsis: ssh_listmissing +# Uses $sshkeys and $sshavail +# Returns a newline-separated list of keys found to be missing. +ssh_listmissing() { + unset slm_missing + + # Parse $sshkeys into positional params to preserve spaces in filenames + set -f # disable globbing + slm_IFS="$IFS" # save current IFS + IFS=" +" # set IFS to newline + set -- $sshkeys + IFS="$slm_IFS" # restore IFS + set +f # re-enable globbing + + for slm_k in "$@"; do + # Fingerprint current user-specified key + slm_finger=`ssh_f "$slm_k"` || continue + + # Check if it needs to be added + case " $sshavail " in + *" $slm_finger "*) + # already know about this key + mesg "Known ssh key: ${CYANN}${slm_k}${OFF}" + ;; + *) + # need to add this key + if [ -z "$slm_missing" ]; then + slm_missing="$slm_k" + else + slm_missing="$slm_missing +$slm_k" + fi + ;; + esac + done + + echo "$slm_missing" +} + +# synopsis: add_gpgkey +# Adds a key to $gpgkeys +add_gpgkey() { + gpgkeys=${gpgkeys+"$gpgkeys +"}"$1" +} + +# synopsis: add_sshkey +# Adds a key to $sshkeys +add_sshkey() { + sshkeys=${sshkeys+"$sshkeys +"}"$1" +} + +# synopsis: parse_mykeys +# Sets $sshkeys and $gpgkeys based on $mykeys +parse_mykeys() { + # Possible path to the private key: if --confhost variable used. + pkeypath="$1" + + # Parse $mykeys into positional params to preserve spaces in filenames + set -f # disable globbing + pm_IFS="$IFS" # save current IFS + IFS=" +" # set IFS to newline + set -- $mykeys + IFS="$pm_IFS" # restore IFS + set +f # re-enable globbing + + for pm_k in "$@"; do + # Check for ssh + if wantagent ssh; then + if [ -f "$pm_k" ]; then + add_sshkey "$pm_k" ; continue + elif [ -f "$HOME/.ssh/$pm_k" ]; then + add_sshkey "$HOME/.ssh/$pm_k" ; continue + elif [ -f "$HOME/.ssh2/$pm_k" ]; then + add_sshkey "$HOME/.ssh2/$pm_k" ; continue + elif [ -f "$pkeypath" ]; then + add_sshkey "$pkeypath"; continue + fi + fi + + # Check for gpg + if wantagent gpg; then + if [ -z "$pm_gpgsecrets" ]; then + pm_gpgsecrets="`gpg --list-secret-keys 2>/dev/null | cut -d/ -f2 | cut -d' ' -f1 | xargs`" + [ -z "$pm_gpgsecrets" ] && pm_gpgsecrets='/' # arbitrary + fi + case " $pm_gpgsecrets " in *" $pm_k "*) + add_gpgkey "$pm_k" ; continue ;; + esac + fi + + $ignoreopt || warn "can't find $pm_k; skipping" + continue + done + + return 0 +} + +# synopsis: setaction +# Sets $myaction or dies if $myaction is already set +setaction() { + if [ -n "$myaction" ]; then + die "you can't specify --$myaction and $1 at the same time" + else + myaction="$1" + fi +} + +# synopsis: setagents +# Check validity of agentsopt +setagents() { + if [ -n "$agentsopt" ]; then + agentsopt=`echo "$agentsopt" | sed 's/,/ /g'` + unset new_agentsopt + for a in $agentsopt; do + if command -v ${a}-agent >/dev/null; then + new_agentsopt="${new_agentsopt+$new_agentsopt }${a}" + else + warn "can't find ${a}-agent, removing from list" + fi + done + agentsopt="${new_agentsopt}" + else + for a in ssh; do + command -v ${a}-agent >/dev/null || continue + agentsopt="${agentsopt+$agentsopt }${a}" + done + fi + + if [ -z "$agentsopt" ]; then + die "no agents available to start" + fi +} + +# synopsis: confpath +# Return private key path if found in ~/.ssh/config SSH configuration file. +# Input: the name of the host we would like to connect to. +confpath() { + h="" + while IFS= read -r line; do + # get the Host directives + case $line in + *"Host "*) h=$(echo $line | awk '{print $2}') ;; + esac + case $line in + *IdentityFile*) + if [ $h = "$1" ]; then + echo $line | awk '{print $2}' + break + fi + esac + done < ~/.ssh/config +} + +# synopsis: wantagent prog +# Return 0 (true) or 1 (false) depending on whether prog is one of the agents in +# agentsopt +wantagent() { + case "$agentsopt" in + "$1"|"$1 "*|*" $1 "*|*" $1") + return 0 ;; + *) + return 1 ;; + esac +} + +# +# MAIN PROGRAM +# + +# parse the command-line +while [ -n "$1" ]; do + case "$1" in + --help|-h) + setaction help + ;; + --stop|-k) + # As of version 2.5, --stop takes an argument. For the sake of + # backward compatibility, only eat the arg if it's one we recognize. + if [ "$2" = mine ]; then + stopwhich=mine; shift + elif [ "$2" = others ]; then + stopwhich=others; shift + elif [ "$2" = all ]; then + stopwhich=all; shift + else + # backward compat + stopwhich=all-warn + fi + ;; + --version|-V) + setaction version + ;; + --agents) + shift + agentsopt="$1" + ;; + --attempts) + shift + if [ "$1" -gt 0 ] 2>/dev/null; then + attempts=$1 + else + die "--attempts requires a numeric argument greater than zero" + fi + ;; + --clear) + clearopt=true + $quickopt && die "--quick and --clear are not compatible" + ;; + --confirm) + confirmopt=true + ;; + --absolute) + absoluteopt=true + ;; + --dir) + shift + case "$1" in + */.*) keydir="$1" ;; + '') die "--dir requires an argument" ;; + *) + if $absoluteopt; then + keydir="$1" + else + keydir="$1/.keychain" # be backward-compatible + fi + ;; + esac + ;; + --env) + shift + if [ -z "$1" ]; then + die "--env requires an argument" + else + envf="$1" + fi + ;; + --eval) + evalopt=true + ;; + --list|-l) + setaction list + quietopt=true + ;; + --query) + queryopt=true + ;; + --host) + shift + hostopt="$1" + ;; + --ignore-missing) + ignoreopt=true + ;; + --inherit) + shift + case "$1" in + local|any|local-once|any-once) + inheritwhich="$1" + ;; + *) + die "--inherit requires an argument (local, any, local-once or any-once)" + ;; + esac + ;; + --noinherit) + inheritwhich=none + ;; + --noask) + noaskopt=true + ;; + --nogui) + noguiopt=true + ;; + --nolock) + nolockopt=true + ;; + --lockwait) + shift + if [ "$1" -ge 0 ] 2>/dev/null; then + lockwait="$1" + else + die "--lockwait requires an argument zero or greater." + fi + ;; + --quick|-Q) + quickopt=true + $clearopt && die "--quick and --clear are not compatible" + ;; + --quiet|-q) + quietopt=true + ;; + --confhost|-c) + if [ -e ~/.ssh/config ]; then + sshconfig=true + confhost="$2" + else + warn "~/.ssh/config not found; --confhost/-c option ignored." + fi + ;; + --nocolor) + color=false + ;; + --timeout) + shift + if [ "$1" -gt 0 ] 2>/dev/null; then + timeout=$1 + else + die "--timeout requires a numeric argument greater than zero" + fi + ;; + --systemd) + systemdopt=true + ;; + --) + shift + IFS=" +" + mykeys=${mykeys+"$mykeys +"}"$*" + unset IFS + break + ;; + -*) + zero=`basename "$0"` + echo "$zero: unknown option $1" >&2 + $evalopt && { echo; echo "false;"; } + exit 1 + ;; + *) + mykeys=${mykeys+"$mykeys +"}"$1" + ;; + esac + shift +done + +# Set filenames *after* parsing command-line options to allow +# modification of $keydir and/or $hostopt +# +# 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. fishpidf is the .ssh-agent +# file with fish-compatible syntax. lockf is the lockfile, used +# to serialize the execution of multiple ssh-agent processes started +# simultaneously +[ -z "$hostopt" ] && hostopt="${HOSTNAME}" +[ -z "$hostopt" ] && hostopt=`uname -n 2>/dev/null || echo unknown` +pidf="${keydir}/${hostopt}-sh" +cshpidf="${keydir}/${hostopt}-csh" +fishpidf="${keydir}/${hostopt}-fish" +olockf="${keydir}/${hostopt}-lock" +lockf="${keydir}/${hostopt}-lockf" + +# Read the env snippet (especially for things like PATH, but could modify +# basically anything) +if [ -z "$envf" ]; then + envf="${keydir}/${hostopt}-env" + [ -f "$envf" ] || envf="${keydir}/env" + [ -f "$envf" ] || unset envf +fi +if [ -n "$envf" ]; then + . "$envf" +fi + +# Don't use color if there's no terminal on stderr +if [ -n "$OFF" ]; then + tty <&2 >/dev/null 2>&1 || color=false +fi + +#disable color if necessary, right before our initial newline + +$color || unset BLUE CYAN CYANN GREEN PURP OFF RED + +qprint #initial newline +mesg "${PURP}keychain ${OFF}${CYANN}${version}${OFF} ~ ${GREEN}http://www.funtoo.org${OFF}" +[ "$myaction" = version ] && { versinfo; exit 0; } +[ "$myaction" = help ] && { versinfo; helpinfo; exit 0; } + +# Set up traps +# Don't use signal names because they don't work on Cygwin. +if $clearopt; then + trap '' 2 # disallow ^C until we've had a chance to --clear + trap 'droplock; exit 1' 1 15 # drop the lock on signal + trap 'droplock; exit 0' 0 # drop the lock on exit +else + # Don't use signal names because they don't work on Cygwin. + trap 'droplock; exit 1' 1 2 15 # drop the lock on signal + trap 'droplock; exit 0' 0 # drop the lock on exit +fi + +setagents # verify/set $agentsopt +verifykeydir # sets up $keydir +wantagent ssh && testssh # sets $openssh and $sunssh +getuser # sets $me + +# Inherit agent info from the environment before loadagents wipes it out. +# Always call this since it checks $inheritopt and sets variables accordingly. +inheritagents + +# --stop: kill the existing ssh-agent(s) and quit +if [ -n "$stopwhich" ]; then + if [ "$stopwhich" = all-warn ]; then + warn "--stop without an argument is deprecated; see --help" + stopwhich=all + fi + takelock || die + if [ "$stopwhich" = mine -o "$stopwhich" = others ]; then + loadagents $agentsopt + fi + for a in $agentsopt; do + stopagent $a + done + if [ "$stopwhich" != others ]; then + qprint + exit 0 # stopagent is always successful + fi +fi + +# Note regarding locking: if we're trying to be quick, then don't take the lock. +# It will be taken later if we discover we can't be quick. +if $quickopt; then + loadagents $agentsopt # sets ssh_auth_sock, ssh_agent_pid, etc + unset nagentsopt + for a in $agentsopt; do + needstart=true + + # Trying to be quick has a price... If we discover the agent isn't running, + # then we'll have to check things again (in startagent) after taking the + # lock. So don't do the initial check unless --quick was specified. + if [ $a = ssh ]; then + sshavail=`ssh_l` # try to use existing agent + # 0 = found keys, 1 = no keys, 2 = no agent + if [ $? = 0 -o \( $? = 1 -a -z "$mykeys" \) ]; then + mesg "Found existing ssh-agent: ${CYANN}$ssh_agent_pid${OFF}" + needstart=false + fi + elif [ $a = gpg ]; then + # not much way to be quick on this + if [ -n "$gpg_agent_pid" ]; then + case " `findpids gpg` " in + *" $gpg_agent_pid "*) + mesg "Found existing gpg-agent: ${CYANN}$gpg_agent_pid${OFF}" + needstart=false ;; + esac + fi + fi + + if $needstart; then + nagentsopt="$nagentsopt $a" + elif $evalopt; then + catpidf $a + fi + done + agentsopt="$nagentsopt" +fi + +# If there are no agents remaining, then bow out now... +[ -n "$agentsopt" ] || { qprint; exit 0; } + +# --timeout translates almost directly to ssh-add/ssh-agent -t, but ssh.com uses +# minutes and OpenSSH uses seconds +if [ -n "$timeout" ] && wantagent ssh; then + ssh_timeout=$timeout + if $openssh || $sunssh; then + ssh_timeout=`expr $ssh_timeout \* 60` + fi + ssh_timeout="-t $ssh_timeout" +fi + +# There are agents remaining to start, and we now know we can't be quick. Take +# the lock before continuing +takelock || die +loadagents $agentsopt +unset nagentsopt +for a in $agentsopt; do + if $queryopt; then + catpidf_shell sh $a | cut -d\; -f1 + elif startagent $a; then + nagentsopt="${nagentsopt+$nagentsopt }$a" + $evalopt && catpidf $a + fi +done +agentsopt="$nagentsopt" + +# If we are just querying the services, exit. +$queryopt && exit 0 + +# If there are no agents remaining, then duck out now... +[ -n "$agentsopt" ] || { qprint; exit 0; } + +# --confirm translates to ssh-add -c +if $confirmopt && wantagent ssh; then + if $openssh || $sunssh; then + ssh_confirm=-c + else + warn "--confirm only works with OpenSSH" + fi +fi + +# --clear: remove all keys from the agent(s) +if $clearopt; then + for a in ${agentsopt}; do + if [ $a = ssh ]; then + sshout=`ssh-add -D 2>&1` + if [ $? = 0 ]; then + mesg "ssh-agent: $sshout" + else + warn "ssh-agent: $sshout" + fi + elif [ $a = gpg ]; then + kill -1 $gpg_agent_pid 2>/dev/null + mesg "gpg-agent: All identities removed." + else + warn "--clear not supported for ${a}-agent" + fi + done + trap 'droplock' 2 # done clearing, safe to ctrl-c +fi + +if $systemdopt; then + for a in $agentsopt; do + systemctl --user set-environment $( catpidf_shell sh $a | cut -d\; -f1 ) + done +fi + +# --noask: "don't ask for keys", so we're all done +$noaskopt && { qprint; exit 0; } + +# If the --confhost option used, determine the path to the private key as +# written in the ~/.ssh/config and add it to ssh-add. +if $sshconfig; then + pkeypath=$(confpath "$confhost") + eval pkeypath=$pkeypath +fi + +# Parse $mykeys into ssh vs. gpg keys; it may be necessary in the future to +# differentiate on the cmdline +parse_mykeys "$pkeypath" || die + +# Load ssh keys +if wantagent ssh; then + sshavail=`ssh_l` # update sshavail now that we're locked + if [ "$myaction" = "list" ]; then + for key in $sshavail end; do + [ "$key" = "end" ] && continue + echo "$key" + done + else + sshkeys="`ssh_listmissing`" # cache list of missing keys, newline-separated + sshattempts=$attempts + savedisplay="$DISPLAY" + + # Attempt to add the keys + while [ -n "$sshkeys" ]; do + + mesg "Adding ${CYANN}"`echo "$sshkeys" | wc -l`"${OFF} ssh key(s): `echo $sshkeys`" + + # Parse $sshkeys into positional params to preserve spaces in filenames. + # This *must* happen after any calls to subroutines because pure Bourne + # shell doesn't restore "$@" following a call. Eeeeek! + set -f # disable globbing + old_IFS="$IFS" # save current IFS + IFS=" + " # set IFS to newline + set -- $sshkeys + IFS="$old_IFS" # restore IFS + set +f # re-enable globbing + + if $noguiopt || [ -z "$SSH_ASKPASS" -o -z "$DISPLAY" ]; then + unset DISPLAY # DISPLAY="" can cause problems + unset SSH_ASKPASS # make sure ssh-add doesn't try SSH_ASKPASS + sshout=`ssh-add ${ssh_timeout} ${ssh_confirm} "$@" 2>&1` + else + sshout=`ssh-add ${ssh_timeout} ${ssh_confirm} "$@" 2>&1 </dev/null` + fi + if [ $? = 0 ] + then + blurb="" + [ -n "$timeout" ] && blurb="life=${timeout}m" + [ -n "$timeout" ] && $confirmopt && blurb="${blurb}," + $confirmopt && blurb="${blurb}confirm" + [ -n "$blurb" ] && blurb=" (${blurb})" + mesg "ssh-add: Identities added: `echo $sshkeys`${blurb}" + break + fi + if [ $sshattempts = 1 ]; then + die "Problem adding; giving up" + else + warn "Problem adding; trying again" + fi + + # Update the list of missing keys + sshavail=`ssh_l` + [ $? = 0 ] || die "problem running ssh-add -l" + sshkeys="`ssh_listmissing`" # remember, newline-separated + + # Decrement the countdown + sshattempts=`expr $sshattempts - 1` + done + + [ -n "$savedisplay" ] && DISPLAY="$savedisplay" + fi +fi + +# Load gpg keys +if wantagent gpg; then + gpgkeys="`gpg_listmissing`" # cache list of missing keys, newline-separated + gpgattempts=$attempts + + $noguiopt && unset DISPLAY + [ -n "$DISPLAY" ] || unset DISPLAY # DISPLAY="" can cause problems + GPG_TTY=`tty` ; export GPG_TTY # fall back to ncurses pinentry + + # Attempt to add the keys + while [ -n "$gpgkeys" ]; do + tryagain=false + + mesg "Adding ${BLUE}"`echo "$gpgkeys" | wc -l`"${OFF} gpg key(s): `echo $gpgkeys`" + + # Parse $gpgkeys into positional params to preserve spaces in filenames. + # This *must* happen after any calls to subroutines because pure Bourne + # shell doesn't restore "$@" following a call. Eeeeek! + set -f # disable globbing + old_IFS="$IFS" # save current IFS + IFS=" +" # set IFS to newline + set -- $gpgkeys + IFS="$old_IFS" # restore IFS + set +f # re-enable globbing + + for k in "$@"; do + echo | env LC_ALL="$pinentry_lc_all" \ + gpg --no-options --use-agent --no-tty --sign --local-user "$k" -o- >/dev/null 2>&1 + [ $? != 0 ] && tryagain=true + done + $tryagain || break + + if [ $gpgattempts = 1 ]; then + die "Problem adding (is pinentry installed?); giving up" + else + warn "Problem adding; trying again" + fi + + # Update the list of missing keys + gpgkeys="`gpg_listmissing`" # remember, newline-separated + + # Decrement the countdown + gpgattempts=`expr $gpgattempts - 1` + done +fi + +qprint # trailing newline + +# vim:sw=4 noexpandtab tw=120 diff -Nru keychain-2.8.1/keychain.1 keychain-2.8.2/keychain.1 --- keychain-2.8.1/keychain.1 1970-01-01 00:00:00.000000000 +0000 +++ keychain-2.8.2/keychain.1 2015-11-07 00:11:24.000000000 +0000 @@ -0,0 +1,432 @@ +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +.br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +.br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{ +. if \nF \{ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "keychain 1" +.TH keychain 1 "2015-11-07" "2.8.2" "http://www.funtoo.org" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +keychain \- re\-use ssh\-agent and/or gpg\-agent between logins +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +keychain\ [\ \-hklQqV\ ]\ [\ \-\-clear\ \-\-confhost\ \-\-help\ \-\-ignore\-missing\ \-\-list\ \-\-noask +\&\-\-nocolor\ \-\-nogui\ \-\-nolock\ \-\-quick\ \-\-quiet\ \-\-version\ ] +[\ \-\-agents\ \fIlist\fR\ ]\ [\ \-\-attempts\ \fInum\fR\ ]\ [\ \-\-dir\ \fIdirname\fR\ ] +[\ \-\-host\ \fIname\fR\ ]\ [\ \-\-lockwait\ \fIseconds\fR\ ] +[\ \-\-stop\ \fIwhich\fR\ ]\ [\ \-\-timeout\ \fIminutes\fR\ ]\ [\ keys...\ ] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +keychain is a manager for ssh-agent, typically run from ~/.bash_profile. It +allows your shells and cron jobs to easily share a single ssh-agent process. 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 want to change +this behavior, take a look at the \-\-clear and \-\-timeout options, described +below. +.PP +When keychain is run, it checks for a running ssh-agent, otherwise it starts +one. It saves the ssh-agent environment variables to +~/.keychain/${\s-1HOSTNAME\s0}\-sh, so that subsequent logins and non-interactive +shells such as cron jobs can source the file and make passwordless ssh +connections. +.PP +In addition, when keychain runs, it verifies that the key files specified on +the command-line are known to ssh-agent, otherwise it loads them, prompting you +for a password if necessary. Typically, private key files are specified by filename +only, without path, although it is possible to specify an absolute or relative +path to the private key file as well. If just a private key filename is used, +which is typical usage, keychain will look for the specified private key +files in ~/.ssh, ~/.ssh2, or with the \-c/\-\-confhost option, inspect the +~/.ssh/config file and use the IdentityFile option to determine the location of +the private key. Private keys can be symlinks to the actual private key. +.PP +Keychain expects associated public key files to exist in the same directory as +the private key files, with a .pub extension. If the private key is a symlink, +the public key can be found alongside the symlink, or in the same directory as +the symlink target (This capability requires the 'readlink' command to be +available on the system.) +.PP +As an additional feature, if a private key has an extension \*(L".ext\*(R", keychain +will look for privkey.ext.pub first, and if not found, will look for +privkeyname.pub. +.PP +Keychain also supports gpg-agent in the same ways that ssh-agent is +supported. By default keychain attempts to start ssh-agent only. +You can modify this behavior using the \-\-agents +option. +.PP +Keychain supports most UNIX-like operating systems, including Cygwin. +It works with Bourne-compatible, csh-compatible and fish shells. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-\-agents\fR \fIlist\fR" 4 +.IX Item "--agents list" +Start the agents listed. By default keychain will start ssh-agent +if it is found in your path. The list should be comma-separated, +for example \*(L"gpg,ssh\*(R" +.IP "\fB\-\-attempts\fR \fInum\fR" 4 +.IX Item "--attempts num" +Try num times to add keys before giving up. The default is 1. +.IP "\fB\-\-clear\fR" 4 +.IX Item "--clear" +Delete all of ssh-agent's keys. Typically this is used in +\&.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. +.IP "\fB\-\-confhost\fR" 4 +.IX Item "--confhost" +By default, keychain will look for key pairs in the ~/.ssh/ directory. +The \-\-confhost option will inform keychain to look in ~/.ssh/config +for IdentityFile settings defined for particular hosts, and use these +paths to locate keys. +.IP "\fB\-\-confirm\fR" 4 +.IX Item "--confirm" +Keys are subject to interactive confirmation by the \s-1SSH_ASKPASS\s0 +program before being used for authentication. See the \-c option for +\&\fIssh\-add\fR\|(1). +.IP "\fB\-\-absolute\fR" 4 +.IX Item "--absolute" +Any arguments to \*(L"\-\-dir\*(R" are interpreted to be absolute. The default +behavior is to append \*(L"/.keychain\*(R" to the argument for backwards +compatibility. +.IP "\fB\-\-dir\fR \fIdirname\fR" 4 +.IX Item "--dir dirname" +Keychain will use dirname rather than \f(CW$HOME\fR/.keychain +.IP "\fB\-\-query\fR" 4 +.IX Item "--query" +Keychain will print lines in KEY=value format representing the values +which are set by the agents. +.IP "\fB\-\-eval\fR" 4 +.IX Item "--eval" +Keychain will print lines to be evaluated in the shell on stdout. It +respects the \s-1SHELL\s0 environment variable to determine if Bourne shell +or C shell output is expected. +.IP "\fB\-\-env\fR \fIfilename\fR" 4 +.IX Item "--env filename" +After parsing options, keychain will load additional environment +settings from \*(L"filename\*(R". By default, if \*(L"\-\-env\*(R" is not given, then +keychain will attempt to load from ~/.keychain/[hostname]\-env or +alternatively ~/.keychain/env. The purpose of this file is to +override settings such as \s-1PATH,\s0 in case ssh is stored in +a non-standard place. +.IP "\fB\-h \-\-help\fR" 4 +.IX Item "-h --help" +Show help that looks remarkably like this man-page. As of 2.6.10, +help is sent to stdout so it can be easily piped to a pager. +.IP "\fB\-\-host\fR \fIname\fR" 4 +.IX Item "--host name" +Set alternate hostname for creation of pidfiles +.IP "\fB\-\-ignore\-missing\fR" 4 +.IX Item "--ignore-missing" +Don't warn if some keys on the command-line can't be found. This is +useful for situations where you have a shared .bash_profile, but your +keys might not be available on every machine where keychain is run. +.IP "\fB\-\-inherit\fR \fIwhich\fR" 4 +.IX Item "--inherit which" +Attempt to inherit agent variables from the environment. This can be +useful in a variety of circumstances, for example when ssh-agent is +started by gdm. The following values are valid for \*(L"which\*(R": +.RS 4 +.IP "\fBlocal\fR" 12 +.IX Item "local" +Inherit when a pid (e.g. \s-1SSH_AGENT_PID\s0) is set in the environment. +This disallows inheriting a forwarded agent. +.IP "\fBany\fR" 12 +.IX Item "any" +Inherit when a sock (e.g. \s-1SSH_AUTH_SOCK\s0) is set in the environment. +This allows inheriting a forwarded agent. +.IP "\fBlocal-once\fR" 12 +.IX Item "local-once" +Same as \*(L"local\*(R", but only inherit if keychain isn't already providing +an agent. +.IP "\fBany-once\fR" 12 +.IX Item "any-once" +Same as \*(L"any\*(R", but only inherit if keychain isn't already providing an +agent. +.RE +.RS 4 +.Sp +By default, keychain\-2.5.0 and later will behave as if \*(L"\-\-inherit +local-once\*(R" is specified. You should specify \*(L"\-\-noinherit\*(R" if you +want the older behavior. +.RE +.IP "\fB\-l \-\-list\fR" 4 +.IX Item "-l --list" +List signatures of all active \s-1SSH\s0 keys, and exit, similar to \*(L"ssh-add \-l\*(R". +.IP "\fB\-\-lockwait\fR \fIseconds\fR" 4 +.IX Item "--lockwait seconds" +How long to wait for the lock to become available. Defaults to 5 +seconds. Specify a value of zero or more. If the lock cannot be +acquired within the specified number of seconds, then this keychain +process will forcefully acquire the lock. +.IP "\fB\-\-noask\fR" 4 +.IX Item "--noask" +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. +.IP "\fB\-\-nocolor\fR" 4 +.IX Item "--nocolor" +Disable color hilighting for non ANSI-compatible terms. +.IP "\fB\-\-nogui\fR" 4 +.IX Item "--nogui" +Don't honor \s-1SSH_ASKPASS,\s0 if it is set. This will cause ssh-add to +prompt on the terminal instead of using a graphical program. +.IP "\fB\-\-noinherit\fR" 4 +.IX Item "--noinherit" +Don't inherit any agent processes, overriding the default +\&\*(L"\-\-inherit local-once\*(R" +.IP "\fB\-\-nolock\fR" 4 +.IX Item "--nolock" +Don't attempt to use a lockfile while manipulating files, pids and +keys. +.IP "\fB\-k \-\-stop\fR \fIwhich\fR" 4 +.IX Item "-k --stop which" +Kill currently running agent processes. The following values are +valid for \*(L"which\*(R": +.RS 4 +.IP "all" 9 +.IX Item "all" +Kill all agent processes and quit keychain immediately. Prior to +keychain\-2.5.0, this was the behavior of the bare \*(L"\-\-stop\*(R" option. +.IP "others" 9 +.IX Item "others" +Kill agent processes other than the one keychain is providing. Prior +to keychain\-2.5.0, keychain would do this automatically. The new +behavior requires that you specify it explicitly if you want it. +.IP "mine" 9 +.IX Item "mine" +Kill keychain's agent processes, leaving other agents alone. +.RE +.RS 4 +.RE +.IP "\fB\-\-systemd\fR" 4 +.IX Item "--systemd" +Inject environment variables into the systemd \-\-user session. +.IP "\fB\-Q \-\-quick\fR" 4 +.IX Item "-Q --quick" +If an ssh-agent process is running then use it. Don't verify the list +of keys, other than making sure it's non-empty. This option avoids +locking when possible so that multiple terminals can be opened +simultaneously without waiting on each other. +.IP "\fB\-q \-\-quiet\fR" 4 +.IX Item "-q --quiet" +Only print messages in case of warning, error or required interactivity. As of +version 2.6.10, this also suppresses \*(L"Identities added\*(R" messages for ssh-agent. +.IP "\fB\-\-timeout\fR \fIminutes\fR" 4 +.IX Item "--timeout minutes" +Allows a timeout to be set for identities added to ssh-agent. When this option +is used with a keychain invocation that starts ssh-agent itself, then keychain +uses the appropriate ssh-agent option to set the default timeout for ssh-agent. +The \-\-timeout option also gets passed to ssh-add invocations, so any keys added +to a running ssh-agent will be individually configured to have the timeout +specified, overriding any ssh-agent default. +.Sp +Most users can simply use the timeout setting they desire and get the result +they want \*(-- with all identities having the specified timeout, whether added by +keychain or not. More advanced users can use one invocation of keychain to set +the default timeout, and optionally set different timeouts for keys added by +using a subsequent invocation of keychain. +.IP "\fB\-V \-\-version\fR" 4 +.IX Item "-V --version" +Show version information. +.SH "EXAMPLES" +.IX Header "EXAMPLES" +This snippet should work in most shells to load two ssh keys and one gpg +key: +.PP +.Vb 1 +\& eval \`keychain \-\-eval id_rsa id_dsa 0123ABCD\` +.Ve +.PP +For the fish shell, use the following format: +.PP +.Vb 3 +\& if status \-\-is\-interactive +\& keychain \-\-eval \-\-quiet \-Q id_rsa | source +\& end +.Ve +.PP +If you have trouble with that in csh: +.PP +.Vb 2 +\& setenv SHELL /bin/csh +\& eval \`keychain \-\-eval id_rsa id_dsa 0123ABCD\` +.Ve +.PP +This is equivalent for Bourne shells (including bash and zsh) but +doesn't use keychain's \-\-eval feature: +.PP +.Vb 6 +\& keychain id_rsa id_dsa 0123ABCD +\& [ \-z "$HOSTNAME" ] && HOSTNAME=\`uname \-n\` +\& [ \-f $HOME/.keychain/$HOSTNAME\-sh ] && \e +\& . $HOME/.keychain/$HOSTNAME\-sh +\& [ \-f $HOME/.keychain/$HOSTNAME\-sh\-gpg ] && \e +\& . $HOME/.keychain/$HOSTNAME\-sh\-gpg +.Ve +.PP +This is equivalent for C shell (including tcsh): +.PP +.Vb 8 +\& keychain id_rsa id_dsa 0123ABCD +\& host=\`uname \-n\` +\& if (\-f $HOME/.keychain/$host\-csh) then +\& source $HOME/.keychain/$host\-csh +\& endif +\& if (\-f $HOME/.keychain/$host\-csh\-gpg) then +\& source $HOME/.keychain/$host\-csh\-gpg +\& endif +.Ve +.PP +To load keychain variables from a script (for example from cron) and +abort unless id_dsa is available: +.PP +.Vb 4 +\& # Load keychain variables and check for id_dsa +\& [ \-z "$HOSTNAME" ] && HOSTNAME=\`uname \-n\` +\& . $HOME/.keychain/$HOSTNAME\-sh 2>/dev/null +\& ssh\-add \-l 2>/dev/null | grep \-q id_dsa || exit 1 +.Ve +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\fIssh\-agent\fR\|(1) +.SH "NOTES" +.IX Header "NOTES" +Keychain was created and is currently maintained by Daniel Robbins. If you need +to report a bug or request an enhancement, please post to the Funtoo Linux +bug tracker <http://bugs.funtoo.org>. For more information +about keychain, please visit <http://www.funtoo.org/Keychain>. diff -Nru keychain-2.8.1/keychain.pod keychain-2.8.2/keychain.pod --- keychain-2.8.1/keychain.pod 2015-05-29 16:48:32.000000000 +0000 +++ keychain-2.8.2/keychain.pod 2015-11-07 00:11:24.000000000 +0000 @@ -209,10 +209,6 @@ Kill currently running agent processes. The following values are valid for "which": -=item B<--systemd> - -Inject environment variables into the systemd --user session. - =over 9 =item all @@ -232,6 +228,10 @@ =back +=item B<--systemd> + +Inject environment variables into the systemd --user session. + =item B<-Q --quick> If an ssh-agent process is running then use it. Don't verify the list @@ -246,9 +246,18 @@ =item B<--timeout> I<minutes> -Set a timeout in minutes on your keys. This is conveyed to ssh-agent -which does the actual timing out of keys since keychain doesn't run -continuously. +Allows a timeout to be set for identities added to ssh-agent. When this option +is used with a keychain invocation that starts ssh-agent itself, then keychain +uses the appropriate ssh-agent option to set the default timeout for ssh-agent. +The --timeout option also gets passed to ssh-add invocations, so any keys added +to a running ssh-agent will be individually configured to have the timeout +specified, overriding any ssh-agent default. + +Most users can simply use the timeout setting they desire and get the result +they want -- with all identities having the specified timeout, whether added by +keychain or not. More advanced users can use one invocation of keychain to set +the default timeout, and optionally set different timeouts for keys added by +using a subsequent invocation of keychain. =item B<-V --version> diff -Nru keychain-2.8.1/keychain.spec keychain-2.8.2/keychain.spec --- keychain-2.8.1/keychain.spec 1970-01-01 00:00:00.000000000 +0000 +++ keychain-2.8.2/keychain.spec 2015-11-07 00:11:24.000000000 +0000 @@ -0,0 +1,41 @@ +Name: keychain +Version: 2.8.2 +Release: 1 +Summary: agent manager for OpenSSH, ssh.com, Sun SSH, and GnuPG +Packager: Daniel Robbins <drobb...@funtoo.org> +URL: http://www.funtoo.org +Source0: %{name}-%{version}.tar.bz2 +License: GPL v2 +Group: Applications/Internet +BuildArch: noarch +Requires: /bin/sh sh-utils +Prefix: /usr/bin +BuildRoot: %{_tmppath}/%{name}-root + +%description +Keychain is a manager for OpenSSH, ssh.com, Sun SSH and GnuPG agents. +It acts as a front-end to the agents, allowing you to easily have one +long-running agent process per system, rather than per login session. +This reduces the number of times you need to enter your passphrase +from once per new login session to once every time your local machine +is rebooted. + +%prep +%setup -q + +%build + +%install +[ $RPM_BUILD_ROOT != / ] && rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/%{_bindir} $RPM_BUILD_ROOT/%{_mandir}/man1 +install -m0755 keychain $RPM_BUILD_ROOT/%{_bindir}/keychain +install -m0644 keychain.1 $RPM_BUILD_ROOT/%{_mandir}/man1 + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) + %{_bindir}/* +%doc %{_mandir}/*/* +%doc ChangeLog COPYING.txt keychain.pod README.md diff -Nru keychain-2.8.1/keychain.spec.in keychain-2.8.2/keychain.spec.in --- keychain-2.8.1/keychain.spec.in 2015-05-29 16:48:32.000000000 +0000 +++ keychain-2.8.2/keychain.spec.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -Name: keychain -Version: KEYCHAIN_VERSION -Release: 1 -Summary: agent manager for OpenSSH, ssh.com, Sun SSH, and GnuPG -Packager: Daniel Robbins <drobb...@funtoo.org> -URL: http://www.funtoo.org -Source0: %{name}-%{version}.tar.bz2 -License: GPL v2 -Group: Applications/Internet -BuildArch: noarch -Requires: /bin/sh sh-utils -Prefix: /usr/bin -BuildRoot: %{_tmppath}/%{name}-root - -%description -Keychain is a manager for OpenSSH, ssh.com, Sun SSH and GnuPG agents. -It acts as a front-end to the agents, allowing you to easily have one -long-running agent process per system, rather than per login session. -This reduces the number of times you need to enter your passphrase -from once per new login session to once every time your local machine -is rebooted. - -%prep -%setup -q - -%build - -%install -[ $RPM_BUILD_ROOT != / ] && rm -rf $RPM_BUILD_ROOT -mkdir -p $RPM_BUILD_ROOT/%{_bindir} $RPM_BUILD_ROOT/%{_mandir}/man1 -install -m0755 keychain $RPM_BUILD_ROOT/%{_bindir}/keychain -install -m0644 keychain.1 $RPM_BUILD_ROOT/%{_mandir}/man1 - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root) - %{_bindir}/* -%doc %{_mandir}/*/* -%doc ChangeLog COPYING.txt keychain.pod README.md diff -Nru keychain-2.8.1/Makefile keychain-2.8.2/Makefile --- keychain-2.8.1/Makefile 2015-05-29 16:48:32.000000000 +0000 +++ keychain-2.8.2/Makefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -V:=$(shell cat VERSION) -D:=$(shell date +'%d %b %Y') -RPMDIR:=$(shell rpmbuild -E '%_rpmdir') -SRPMDIR:=$(shell rpmbuild -E '%_srcrpmdir') -TARBALL_CONTENTS=keychain README.md ChangeLog COPYING.txt keychain.pod keychain.1 \ - keychain.spec - -all: keychain.1 keychain keychain.spec - -.PHONY : tmpclean -tmpclean: - rm -rf dist keychain.1.orig keychain.txt - -.PHONY : clean -clean: tmpclean - rm -rf keychain.1 keychain keychain.spec - -keychain.spec: keychain.spec.in keychain.sh - sed 's/KEYCHAIN_VERSION/$V/' keychain.spec.in > keychain.spec - -keychain.1: keychain.pod keychain.sh - pod2man --name=keychain --release=$V \ - --center='http://www.funtoo.org' \ - keychain.pod keychain.1 - sed -i.orig -e "s/^'br/.br/" keychain.1 - -keychain.1.gz: keychain.1 - gzip -9 keychain.1 - -GENKEYCHAINPL = open P, "keychain.txt" or die "cant open keychain.txt"; \ - while (<P>) { \ - $$printing = 0 if /^\w/; \ - $$printing = 1 if /^(SYNOPSIS|OPTIONS)/; \ - $$printing || next; \ - s/\$$/\\\$$/g; \ - s/\`/\\\`/g; \ - s/\\$$/\\\\/g; \ - s/\*(\w+)\*/\$${CYAN}$$1\$${OFF}/g; \ - s/(^|\s)(-+[-\w]+)/$$1\$${GREEN}$$2\$${OFF}/g; \ - $$pod .= $$_; \ - }; \ - open B, "keychain.sh" or die "cant open keychain.sh"; \ - $$/ = undef; \ - $$_ = <B>; \ - s/INSERT_POD_OUTPUT_HERE[\r\n]/$$pod/ || die; \ - s/\#\#VERSION\#\#/$V/g || die; \ - print - -keychain: keychain.sh keychain.txt - perl -e '$(GENKEYCHAINPL)' >keychain || rm -f keychain - chmod +x keychain - -keychain.txt: keychain.pod - pod2text keychain.pod keychain.txt - -keychain-$V.tar.gz: $(TARBALL_CONTENTS) - @case $V in *-test*) \ - echo "**** Version is $V, please remove -test"; \ - exit 1 ;; \ - esac - @if ! grep -qF '* keychain $V ' ChangeLog; then \ - echo "**** Need to update the ChangeLog for version $V"; \ - exit 1; \ - fi - mkdir keychain-$V - cp $(TARBALL_CONTENTS) keychain-$V - /bin/tar cjvf keychain-$V.tar.bz2 keychain-$V - rm -rf keychain-$V - ls -l keychain-$V.tar.bz2 - -# Building noarch.rpm builds src.rpm at the same time. I haven't -# found an elegant way yet to prevent parallel builds from messing -# this up, so all deps in the Makefile refer only to noarch.rpm -keychain-$V-1.noarch.rpm-unsigned: keychain-$V.tar.gz - rpmbuild -ta keychain-$V.tar.bz2 - mv $(RPMDIR)/noarch/keychain-$V-1.noarch.rpm \ - $(SRPMDIR)/keychain-$V-1.src.rpm . -keychain-$V-1.noarch.rpm: keychain-$V-1.noarch.rpm-unsigned - rpm --addsign keychain-$V-1.noarch.rpm keychain-$V-1.src.rpm diff -Nru keychain-2.8.1/misc/macos-security.sh keychain-2.8.2/misc/macos-security.sh --- keychain-2.8.1/misc/macos-security.sh 2015-05-29 16:48:32.000000000 +0000 +++ keychain-2.8.2/misc/macos-security.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -security find-generic-password -s SSH | grep "\"acct\"<blob>" | sed -e 's/^.*"acct"<blob>=\(".*"\)$/\1/' diff -Nru keychain-2.8.1/VERSION keychain-2.8.2/VERSION --- keychain-2.8.1/VERSION 2015-05-29 16:48:32.000000000 +0000 +++ keychain-2.8.2/VERSION 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -2.8.1