ssh-agent: perform AGENTC_REMOVE_ALL_IDENTITIES on SIGUSR1

Steffen Nurpmeso steffen at sdaoden.eu
Wed Sep 8 21:46:59 AEST 2021


Hello.

A long time ago i asked for the possibility to remove all
identities from a running agent by sending a signal.

The use case i have in mind is that upon LID close or another
thinkable event all identities can be removed from all running
agents simply by calling "pkill -USR1 ssh-agent".

Another option would be automatic locking as via "ssh-add -x", but
extending ssh-agent to simply require the user's password for
unlocking seemed very complicated or even impossible the way that
the according code is organized and usable in OpenSSH.

For example, what i am currently doing upon LID close is

   if command -v ssh-add >/dev/null 2>&1; then
      for a in /tmp/ssh-*/agent.*; do
         [ -e "$a" ] || continue
         act 'SSH_AUTH_SOCK="$a" ssh-add -D </dev/null >/dev/null 2>&1 &'
         : > /run/.zzz_act
      done
   fi

which works nicely here, but would not work in environments with
private home directories, or any other complication.
"pkill -USR1 ssh-agent", on the other hand, would work just fine.

The necessary code addition to ssh-agent is minimal, and builds
upon existing code.  The work is done in a signal handler, because
ssh_signal() sets SA_RESTART and thus the loop would not wake up
to tick.  On the other hand ssh_signal() fills the signal mask, so
signal recursion of any form cannot happen, therefore processing
the list in the signal handler seems safe.

I have compiled the diff below, but have not tried it out yet.
(Oh the grief if it could not be upstreamed, then.)

It would be nice if that would be considered.
Thank you.

Ciao from Germany already here,

diff --git a/ssh-agent.1 b/ssh-agent.1
index ed8c870969..dd2b0e8af1 100644
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -178,6 +178,9 @@ will automatically use them if present.
 is also used to remove keys from
 .Nm
 and to query the keys that are held in one.
+.Nm
+will remove all keys when it receives the user signal
+.Dv SIGUSR1 .
 .Pp
 Connections to
 .Nm
diff --git a/ssh-agent.c b/ssh-agent.c
index 48a47d45a9..96c3ed77c2 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -529,11 +529,10 @@ process_remove_identity(SocketEntry *e)
 }
 
 static void
-process_remove_all_identities(SocketEntry *e)
+remove_all_identities(void)
 {
 	Identity *id;
 
-	debug2_f("entering");
 	/* Loop over all identities and clear the keys. */
 	for (id = TAILQ_FIRST(&idtab->idlist); id;
 	    id = TAILQ_FIRST(&idtab->idlist)) {
@@ -543,6 +542,13 @@ process_remove_all_identities(SocketEntry *e)
 
 	/* Mark that there are no identities. */
 	idtab->nentries = 0;
+}
+
+static void
+process_remove_all_identities(SocketEntry *e)
+{
+	debug2_f("entering");
+	remove_all_identities();
 
 	/* Send success. */
 	send_status(e, 1);
@@ -1342,6 +1348,13 @@ cleanup_handler(int sig)
 	_exit(2);
 }
 
+/*ARGSUSED*/
+static void
+remove_all_handler(int sig)
+{
+	remove_all_identities();
+}
+
 static void
 check_parent_exists(void)
 {
@@ -1619,6 +1632,7 @@ skip:
 	ssh_signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN);
 	ssh_signal(SIGHUP, cleanup_handler);
 	ssh_signal(SIGTERM, cleanup_handler);
+	ssh_signal(SIGUSR1, remove_all_handler);
 
 	if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1)
 		fatal("%s: pledge: %s", __progname, strerror(errno));

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)


More information about the openssh-unix-dev mailing list