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