[RFC PATCH 4/4] pam-ssh-agent: Add authenticating the SSH agent

Domenico Andreoli cavokz at gmail.com
Tue Jul 21 11:06:17 AEST 2020


The two key sets, agent and auth, are compared. The matching keys are
used to challenge the agent in signing some random data. The first
positive proof immediately ends the verification with a success.

Tests verify the correct behavior with different auth files. A full
round with all the supported key types is also performed.

Signed-off-by: Domenico Andreoli <domenico.andreoli at linux.com>

---
 pam-ssh-agent.c          |   33 ++++++++++++++++++++++++++++++++-
 regress/pam-ssh-agent.sh |   23 +++++++++++++++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)

Index: b/pam-ssh-agent.c
===================================================================
--- a/pam-ssh-agent.c
+++ b/pam-ssh-agent.c
@@ -38,6 +38,7 @@
 #include "authfile.h"
 #include "authfd.h"
 #include "ssherr.h"
+#include "sshkey.h"
 #include "ssh.h"
 
 static int pam_debug;
@@ -95,6 +96,36 @@ out:
 	return r;
 }
 
+static int
+challenge_agent(int agent_fd, const struct sshkey *agent_key, const struct sshkey *auth_key)
+{
+	u_char *sig = NULL;
+	size_t slen = 0;
+	char data[1024];
+	int ret;
+
+	arc4random_buf(data, sizeof(data));
+	ret = ssh_agent_sign(agent_fd, agent_key, &sig, &slen, data, sizeof(data), NULL, 0) ||
+	      sshkey_verify(auth_key, sig, slen, data, sizeof(data), NULL, 0, NULL);
+
+	if (sig != NULL)
+		free(sig);
+	return !ret;
+}
+
+static int
+authenticate_agent(int agent_fd, const struct ssh_identitylist *agent_ids,
+	const struct ssh_identitylist *auth_ids)
+{
+	unsigned i, j;
+	for (i=0; i!=agent_ids->nkeys; i++)
+		for (j=0; j!=auth_ids->nkeys; j++)
+			if (sshkey_equal(agent_ids->keys[i], auth_ids->keys[j]))
+				if (challenge_agent(agent_fd, agent_ids->keys[i], auth_ids->keys[j]))
+					return PAM_SUCCESS;
+	return PAM_AUTH_ERR;
+}
+
 int
 pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
 {
@@ -161,7 +192,7 @@ pam_sm_authenticate(pam_handle_t *pamh,
 			syslog(LOG_DEBUG, "  %d) %s", i, agent_ids->comments[i]);
 	}
 
-	ret = PAM_SUCCESS;
+	ret = authenticate_agent(agent_fd, agent_ids, auth_ids);
 
 out:
 	if (agent_fd != -1)
Index: b/regress/pam-ssh-agent.sh
===================================================================
--- a/regress/pam-ssh-agent.sh
+++ b/regress/pam-ssh-agent.sh
@@ -20,7 +20,9 @@ PAM_AUTHINFO_UNAVAIL=9
 . $OBJ/keytype_gen.sh
 
 first_kt=`echo $ktypes | cut -d" " -f1`
+second_kt=`echo $ktypes | cut -d" " -f2`
 AUTH_FILE=$OBJ/key.$first_kt.pub
+AUTH_FILE2=$OBJ/key.$second_kt.pub
 
 pam_agent_test()
 {
@@ -73,6 +75,27 @@ expect=$PAM_SUCCESS           pam_agent_
 trace "authenticate agent (non-debug)"
 expect=$PAM_SUCCESS           pam_agent_test file=$AUTH_FILE
 
+trace "change of auth file (debug)"
+expect=$PAM_AUTH_ERR          pam_agent_test file=$AUTH_FILE2 debug
+
+trace "change of auth file (non-debug)"
+expect=$PAM_AUTH_ERR          pam_agent_test file=$AUTH_FILE2
+
+for kt in $ktypes; do
+	trace "load key $kt into the agent"
+	${SSHADD} -q $OBJ/key.$kt
+	r=$?
+	if [ $r -ne 0 ]; then
+		fatal "could not add the key: exit code $r"
+	fi
+
+	trace "authenticate agent with $kt (debug)"
+	expect=$PAM_SUCCESS       pam_agent_test file=$OBJ/key.$kt.pub debug
+
+	trace "authenticate agent with $kt (non-debug)"
+	expect=$PAM_SUCCESS       pam_agent_test file=$OBJ/key.$kt.pub
+done
+
 trace "kill agent"
 ${SSHAGENT} -k > /dev/null
 



More information about the openssh-unix-dev mailing list