You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Much of OpenSSH appears to me to largely have the assumption that there will only ever be a single SSH agent in use at a time. I see no place in the ssh agent protocol for multiplexing over multiple agents, agent forwarding using -A appears to only support a single agent, IdentityAgent specifies the agent to use (not an agent to use), the SSH_AUTH_SOCK environment variable is a single path to a single agent, command line flags override the environment variables, etc. Since trezor-agent is not a full drop-in replacement for ssh-agent, it would be nice if there was a way to mix usage of ssh-agent and trezor-agent, because ssh-agent provides support for temporary keys and certificates that can be added and removed, whereas trezor-agent cannot do this (it refuses SSH_AGENTC_ADD_IDENTITY as noted below).
As a little use case to think about, suppose the user has a SSH key A stored in their local ssh-agent instance and also an SSH key B derived from the locally attached hardware key provided by trezor-agent. Perhaps A is an SSH certificate issued by a certificate authority, or else it can be any other key that is able to be provided by ssh-agent. In that case, since the user can only select one agent to forward, they must either choose to forward either trezor-agent or ssh-agent, but not both, so that the user when connected to the server now only has the single agent (and thus only key A or B) rather than their local machine which has access to both.
SSH configuration files can solve this by allowing the user to select at the time of invoking SSH which agent using the matching primitives like Host, User, Match exec, etc. which appears to be what is commonly used (e.g. #75), but this only works on the first hop that has access to both agents to select among. I believe the closest you could get is that one could write a script that could answer the Match exec directive, i.e.:
#!/bin/bash# trezor-agent-check-ident## Usage: trezor-agent-check-ident [user] [host]## Exits with status code 0 if 'user@host' is a key that `trezor-agent` can provide, 1 otherwiseset -euo pipefail
user=$1
host=$2
grep ".* <ssh://$user@$host|.*>\$"$HOME/.ssh/trezor.conf
exit$?
However this still only works on the local host and not with agent forwarding to a remote server. Perhaps some hack can be used to forward the trezor-agent socket as well, or some crazy socatnc magic, but perhaps a better solution is transparently proxying commands to/from the standard OpenSSH agent.
trezor-agent would basically wrap an existing agent. When called to sign for an identity it would first check if the identity could be provided by the local hardware key, and if so then it would handle that, otherwise it would pass through the command to the chosen agent.
trezor-agent currently only responds to four messages and really only implements two:
SSH_AGENTC_REQUEST_RSA_IDENTITIES (legacy SSH protocol 1 reserved message number 1), trezor-agent constructs a "successful" response containing an empty list
SSH_AGENTC_REQUEST_IDENTITIES (message 11), trezor-agent replies with key list from local hardware key
SSH_AGENTC_SIGN_REQUEST (message 13), trezor-agent replies with signature
SSH_AGENTC_EXTENSION (message 27), trezor-agent constructs a protocol error response compliant with Section 3.8, namely SSH_AGENT_EXTENSION_FAILURE.
For SSH_AGENTC_REQUEST_IDENTITIES, trezor-agent could simply union the keys from the hardware key as well as the chosen passthrough agent.
For SSH_AGENTC_SIGN_REQUEST, trezor-agent uses the key identity to decide whether to sign or not. If the key identity is one it has on the local hardware key, it passes through to the local hardware key, and if not, passes through to the chosen agent.
For all the other messages, it appears to me that trezor-agent could simply forward the messages as-is to the chosen agent. Perhaps SSH_AGENTC_LOCK and SSH_AGENTC_UNLOCK could be implemented by revoking any cached session and then also forwarding the message to the chosen agent so as to lock both agents, and unlocking could be done specially, but I don't think agent locking is commonly used anyway, so it seems to me that it would be permissible to simply refuse the messages as well as it does today.
If this set of changes is too large in scope, I'd be happy to move this into a separate tool that could be composed with trezor-agent, however I think from my initial browsing of the code it would be largely contained to the SSH server implementation in
, basically a little proxy in front that decides "which SSH agent server to send it to" as well as the plumbing for the user to provide the passthrough agent socket path with defaults to the default OpenSSH agent.
The text was updated successfully, but these errors were encountered:
jacobgreenleaf
changed the title
SSH: Passthrough to native OpenSSH agent
SSH: Passthrough to native OpenSSH agent for better forwarding support
Mar 30, 2024
Much of OpenSSH appears to me to largely have the assumption that there will only ever be a single SSH agent in use at a time. I see no place in the ssh agent protocol for multiplexing over multiple agents, agent forwarding using
-A
appears to only support a single agent,IdentityAgent
specifies the agent to use (not an agent to use), theSSH_AUTH_SOCK
environment variable is a single path to a single agent, command line flags override the environment variables, etc. Sincetrezor-agent
is not a full drop-in replacement forssh-agent
, it would be nice if there was a way to mix usage of ssh-agent and trezor-agent, becausessh-agent
provides support for temporary keys and certificates that can be added and removed, whereastrezor-agent
cannot do this (it refusesSSH_AGENTC_ADD_IDENTITY
as noted below).As a little use case to think about, suppose the user has a SSH key
A
stored in their localssh-agent
instance and also an SSH keyB
derived from the locally attached hardware key provided bytrezor-agent
. PerhapsA
is an SSH certificate issued by a certificate authority, or else it can be any other key that is able to be provided byssh-agent
. In that case, since the user can only select one agent to forward, they must either choose to forward eithertrezor-agent
orssh-agent
, but not both, so that the user when connected to the server now only has the single agent (and thus only keyA
orB
) rather than their local machine which has access to both.SSH configuration files can solve this by allowing the user to select at the time of invoking SSH which agent using the matching primitives like
Host
,User
,Match exec
, etc. which appears to be what is commonly used (e.g. #75), but this only works on the first hop that has access to both agents to select among. I believe the closest you could get is that one could write a script that could answer theMatch exec
directive, i.e.:However this still only works on the local host and not with agent forwarding to a remote server. Perhaps some hack can be used to forward the trezor-agent socket as well, or some crazy
socat
nc
magic, but perhaps a better solution is transparently proxying commands to/from the standard OpenSSH agent.trezor-agent
would basically wrap an existing agent. When called to sign for an identity it would first check if the identity could be provided by the local hardware key, and if so then it would handle that, otherwise it would pass through the command to the chosen agent.As I read the SSH agent protocol, here are the messages, by number:
trezor-agent
currently only responds to four messages and really only implements two:SSH_AGENTC_REQUEST_RSA_IDENTITIES
(legacy SSH protocol 1 reserved message number 1),trezor-agent
constructs a "successful" response containing an empty listSSH_AGENTC_REQUEST_IDENTITIES
(message 11),trezor-agent
replies with key list from local hardware keySSH_AGENTC_SIGN_REQUEST
(message 13),trezor-agent
replies with signatureSSH_AGENTC_EXTENSION
(message 27),trezor-agent
constructs a protocol error response compliant with Section 3.8, namelySSH_AGENT_EXTENSION_FAILURE
.For
SSH_AGENTC_REQUEST_IDENTITIES
, trezor-agent could simply union the keys from the hardware key as well as the chosen passthrough agent.For
SSH_AGENTC_SIGN_REQUEST
, trezor-agent uses the key identity to decide whether to sign or not. If the key identity is one it has on the local hardware key, it passes through to the local hardware key, and if not, passes through to the chosen agent.For all the other messages, it appears to me that trezor-agent could simply forward the messages as-is to the chosen agent. Perhaps
SSH_AGENTC_LOCK
andSSH_AGENTC_UNLOCK
could be implemented by revoking any cached session and then also forwarding the message to the chosen agent so as to lock both agents, and unlocking could be done specially, but I don't think agent locking is commonly used anyway, so it seems to me that it would be permissible to simply refuse the messages as well as it does today.If this set of changes is too large in scope, I'd be happy to move this into a separate tool that could be composed with
trezor-agent
, however I think from my initial browsing of the code it would be largely contained to the SSH server implementation intrezor-agent/libagent/ssh/protocol.py
Lines 75 to 76 in dace3eb
The text was updated successfully, but these errors were encountered: