PATCH] ssh-agent: Add key usage logging for unconstrained keys with session bindings

Manon Goo manon.goo at dg-i.net
Mon Dec 15 10:13:52 AEDT 2025


Hi,

I'd like to propose a patch (60 lines in a single location in ssh-agent.c ) that adds debug logging for signature requests made with unconstrained keys when session bindings are present.

Motivation:

Currently, when a key is loaded with destination constraints (ssh-add -h), the agent logs information about signing operations via debug_f("user=%s") and the detailed session binding
chain via identity_permitted(). However, for unconstrained keys, this information is not logged even though the session bindings exist 

This creates a gap for users who want visibility into which hosts their keys are being used to authenticate to, without necessarily wanting to enforce restrictions. The use case is
monitoring - being able to see in debug logs where keys are being used.

In my case, I am writing a wrapper application that keeps a log of key usage. Having this debug output available for unconstrained keys would allow tracking authentication events.

What the patch does:

For unconstrained keys (ndest_constraints == 0) with active session bindings (nsession_ids > 0), the patch:

1. Attempts to parse the userauth request (same as done for constrained keys)
2. Logs debug_f("signing for user \"%s\" with unconstrained key " "%s %s", user, sshkey_type(id->key), fp) 
3. Logs session binding details via debug3_f() - matching the style in identity_permitted()

The patch does not change any behavior - it only adds logging. The existing constrained key code path remains unchanged.

Example output (with -d):

debug1: process_sign_request2: signing for user "tester" with unconstrained key RSA SHA256: XXXX
debug3: process_sign_request2: session binding 0 AUTH, hostkey ED25519 SHA256:XXXX
debug3: process_sign_request2: hostkey in signature: ED25519 SHA256:XXXX


Thanks for considering,
Manon Goo

diff --git a/ssh-agent.c b/ssh-agent.c
index cd569c33a..b3a736083 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -831,7 +831,7 @@ static void
 process_sign_request2(SocketEntry *e)
 {
 	u_char *signature = NULL;
-	size_t slen = 0;
+	size_t slen = 0, i;
 	u_int compat = 0, flags;
 	int r, ok = -1, retried = 0;
 	char *fp = NULL, *pin = NULL, *prompt = NULL;
@@ -861,6 +861,46 @@ process_sign_request2(SocketEntry *e)
 	    SSH_FP_DEFAULT)) == NULL)
 		fatal_f("fingerprint failed");

+	/* Audit logging for unconstrained keys with session bindings */
+	if (id->ndest_constraints == 0 && e->nsession_ids > 0) {
+		if (parse_userauth_request(data, key, &user, &sid,
+		    &hostkey) == 0) {
+			struct hostkey_sid *hks;
+			char *fp2;
+
+			debug_f("signing for user \"%s\" with unconstrained key "
+			    "%s %s", user, sshkey_type(id->key), fp);
+			for (i = 0; i < e->nsession_ids; i++) {
+				hks = e->session_ids + i;
+				if ((fp2 = sshkey_fingerprint(hks->key,
+				    SSH_FP_HASH_DEFAULT,
+				    SSH_FP_DEFAULT)) == NULL)
+					fatal_f("fingerprint failed");
+				debug3_f("session binding %zu %s, "
+				    "hostkey %s %s", i,
+				    hks->forwarded ? "FORWARD" : "AUTH",
+				    sshkey_type(hks->key), fp2);
+				free(fp2);
+			}
+			if (hostkey != NULL) {
+				if ((fp2 = sshkey_fingerprint(hostkey,
+				    SSH_FP_HASH_DEFAULT,
+				    SSH_FP_DEFAULT)) == NULL)
+					fatal_f("fingerprint failed");
+				debug3_f("hostkey in signature: %s %s",
+				    sshkey_type(hostkey), fp2);
+				free(fp2);
+			}
+		}
+		/* Reset for potential reuse by constrained key path */
+		free(user);
+		user = NULL;
+		sshbuf_free(sid);
+		sid = NULL;
+		sshkey_free(hostkey);
+		hostkey = NULL;
+	}
+
 	if (id->ndest_constraints != 0) {
 		if (e->nsession_ids == 0) {
 			logit_f("refusing use of destination-constrained key "













More information about the openssh-unix-dev mailing list