[PATCH v2] ssh-add: support external parsing of key listing

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

 



From: Corey Hickey <chickey@xxxxxxxxxx>

When ssh-add is used in a script like:

    if ! KEY_LISTING=$(ssh-add -l 2>&1) ; then
        echo "SSH agent error" >&2
        exit 2
    fi

...the operation fails when there is an agent but there are no keys in
the agent. This is because ssh-add exits with status of 1. If the
intent is to examine the keys in the agent, then this behavior is
undesired and not easily distinguishable from an error (e.g. no agent
running).

To address this, modify ssh-add to:
* print "The agent has no identities." to stderr instead of stdout
* exit with a status of 0 instead of 1

Also modify tests accordingly, so `make tests` passes.
---
 regress/agent-restrict.sh |  4 ++--
 regress/agent-timeout.sh  |  5 +----
 regress/agent.sh          | 47 +++++++++++++++++----------------------
 regress/test-exec.sh      | 22 ++++++++++++++++++
 ssh-add.c                 | 10 +++++----
 5 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/regress/agent-restrict.sh b/regress/agent-restrict.sh
index 62cea8522..9d3fd71ac 100644
--- a/regress/agent-restrict.sh
+++ b/regress/agent-restrict.sh
@@ -204,8 +204,8 @@ trap "kill $AGENT_PID" EXIT
 sleep 4 # Give it a chance to start
 # Check that it's running.
 ${SSHADD} -l > /dev/null 2>&1
-if [ $? -ne 1 ]; then
-	fail "ssh-add -l did not fail with exit code 1"
+if [ $? -ne 0 ]; then
+	fail "ssh-add -l did not fail with exit code 0"
 fi
 
 verbose "authentication with agent (no restrict)"
diff --git a/regress/agent-timeout.sh b/regress/agent-timeout.sh
index 6dec09285..1c11c5da6 100644
--- a/regress/agent-timeout.sh
+++ b/regress/agent-timeout.sh
@@ -28,10 +28,7 @@ else
 	trace "sleeping 2*${SSHAGENT_TIMEOUT} seconds"
 	sleep ${SSHAGENT_TIMEOUT}
 	sleep ${SSHAGENT_TIMEOUT}
-	${SSHADD} -l 2> /dev/null | grep 'The agent has no identities.' >/dev/null
-	if [ $? -ne 0 ]; then
-		fail "ssh-add -l still returns keys after timeout"
-	fi
+	check_keys_absent "after timeout"
 
 	trace "kill agent"
 	${SSHAGENT} -k > /dev/null
diff --git a/regress/agent.sh b/regress/agent.sh
index f0022aca5..c33e8407e 100644
--- a/regress/agent.sh
+++ b/regress/agent.sh
@@ -22,8 +22,9 @@ if [ $r -ne 0 ]; then
 fi
 
 ${SSHADD} -l > /dev/null 2>&1
-if [ $? -ne 1 ]; then
-	fail "ssh-add -l did not fail with exit code 1"
+r=$?
+if [ $r -ne 0 ]; then
+	fail "with no keys, ssh-add -l failed: exit code $r"
 fi
 
 rm -f $OBJ/user_ca_key $OBJ/user_ca_key.pub
@@ -99,11 +100,15 @@ for t in ${SSH_KEYTYPES}; do
 done
 
 trace "agent forwarding"
-${SSH} -A -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
+AGENT_LISTING=$(${SSH} -A -F $OBJ/ssh_proxy somehost ${SSHADD} -l 2> /dev/null)
 r=$?
 if [ $r -ne 0 ]; then
 	fail "ssh-add -l via agent fwd failed (exit code $r)"
 fi
+NUM_LINES=$(printf "%s" "$AGENT_LISTING" | wc -l)
+if [ "$NUM_LINES" -eq 0 ]; then
+	fail "ssh-add -l via agent fwd has no keys"
+fi
 ${SSH} "-oForwardAgent=$SSH_AUTH_SOCK" -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
 r=$?
 if [ $r -ne 0 ]; then
@@ -128,16 +133,20 @@ if [ $r -ne 0 ]; then
 	fail "ssh-add -l via agent path env fwd of different agent failed (exit code $r)"
 fi
 
-# Remove keys from forwarded agent, ssh-add on remote machine should now fail.
+# Remove keys from forwarded agent, then test for keys on remote machine.
 SSH_AUTH_SOCK=$FW_SSH_AUTH_SOCK ${SSHADD} -D > /dev/null 2>&1
 r=$?
 if [ $r -ne 0 ]; then
 	fail "ssh-add -D failed: exit code $r"
 fi
-${SSH} '-oForwardAgent=$FW_SSH_AUTH_SOCK' -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
+AGENT_LISTING=$(${SSH} '-oForwardAgent=$FW_SSH_AUTH_SOCK' -F $OBJ/ssh_proxy somehost ${SSHADD} -l 2> /dev/null)
 r=$?
-if [ $r -ne 1 ]; then
-	fail "ssh-add -l with different agent did not fail with exit code 1 (exit code $r)"
+if [ $r -ne 0 ]; then
+	fail "ssh-add -l via agent fwd failed (exit code $r)"
+fi
+NUM_LINES=$(printf "%s" "$AGENT_LISTING" | wc -l)
+if [ "$NUM_LINES" -ne 0 ]; then
+	fail "ssh-add -l via agent fwd still has keys"
 fi
 
 (printf 'cert-authority,principals="estragon" '; cat $OBJ/user_ca_key.pub) \
@@ -164,11 +173,7 @@ if [ $r -ne 0 ]; then
 	fail "ssh-add -D failed: exit code $r"
 fi
 # make sure they're gone
-${SSHADD} -l > /dev/null 2>&1
-r=$?
-if [ $r -ne 1 ]; then
-	fail "ssh-add -l returned unexpected exit code: $r"
-fi
+check_keys_absent "after delete"
 trace "readd keys"
 # re-add keys/certs to agent
 for t in ${SSH_KEYTYPES}; do
@@ -176,11 +181,7 @@ for t in ${SSH_KEYTYPES}; do
 		fail "ssh-add failed exit code $?"
 done
 # make sure they are there
-${SSHADD} -l > /dev/null 2>&1
-r=$?
-if [ $r -ne 0 ]; then
-	fail "ssh-add -l failed: exit code $r"
-fi
+check_keys_present "after readd"
 trace "delete all agent keys using SIGUSR1"
 kill -s USR1 $SSH_AGENT_PID
 r=$?
@@ -188,22 +189,14 @@ if [ $r -ne 0 ]; then
 	fail "kill -s USR1 failed: exit code $r"
 fi
 # make sure they're gone
-${SSHADD} -l > /dev/null 2>&1
-r=$?
-if [ $r -ne 1 ]; then
-	fail "ssh-add -l returned unexpected exit code: $r"
-fi
+check_keys_absent "after USR1"
 # re-add keys/certs to agent
 for t in ${SSH_KEYTYPES}; do
 	${SSHADD} $OBJ/$t-agent-private >/dev/null 2>&1 || \
 		fail "ssh-add failed exit code $?"
 done
 # make sure they are there
-${SSHADD} -l > /dev/null 2>&1
-r=$?
-if [ $r -ne 0 ]; then
-	fail "ssh-add -l failed: exit code $r"
-fi
+check_keys_present "after readd again"
 
 check_key_absent() {
 	${SSHADD} -L | grep "^$1 " >/dev/null
diff --git a/regress/test-exec.sh b/regress/test-exec.sh
index 62c00fd8c..89170657e 100644
--- a/regress/test-exec.sh
+++ b/regress/test-exec.sh
@@ -495,6 +495,28 @@ stop_sshd ()
 	PIDFILE=""
 }
 
+_check_keys_present() {
+	AGENT_LISTING=$(${SSHADD} -l 2> /dev/null)
+	r=$?
+	if [ $r -ne 0 ]; then
+		fail "$1: ssh-add -l returned unexpected exit code: $r"
+	fi
+	NUM_LINES=$(printf "%s" "$AGENT_LISTING" | wc -l)
+	[ "$NUM_LINES" -ne 0 ]
+}
+
+check_keys_absent() {
+	if _check_keys_present "$1" ; then
+		fail "$1: keys unexpectedly present"
+	fi
+}
+
+check_keys_present() {
+	if ! _check_keys_present "$1" ; then
+		fail "$1: keys unexpectedly absent"
+	fi
+}
+
 # helper
 cleanup ()
 {
diff --git a/ssh-add.c b/ssh-add.c
index 0035cb84a..8194a1649 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -538,12 +538,14 @@ list_identities(int agent_fd, int do_fp)
 	size_t i;
 
 	if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
-		if (r != SSH_ERR_AGENT_NO_IDENTITIES)
+		if (r == SSH_ERR_AGENT_NO_IDENTITIES) {
+			fprintf(stderr, "The agent has no identities.\n");
+			return 0;
+		} else {
 			fprintf(stderr, "error fetching identities: %s\n",
 			    ssh_err(r));
-		else
-			printf("The agent has no identities.\n");
-		return -1;
+			return -1;
+		}
 	}
 	for (i = 0; i < idlist->nkeys; i++) {
 		if (do_fp) {
-- 
2.47.1

_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev



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

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux