There are some machines I trust very little, but I still need my agent to authenticate a connection from it, e.g., to checkout something from a revision control system or copy a file. Currently I ssh into those machines with the -A option, overriding the "ForwardAgent no" in my config file as it applies to that machine, do my checkout or whatever, and then exit and resume work in a session without agent forwarding. This exposes me more than I would like. I would like the ability to set "ForwardAgent ask" in my config file (or on the command line), which would cause that ssh to forward the request to the agent only if approved via the standard SSH_ASKPASS mechanism.
I think it would be nicer to ask the agent to require explict confirmation of all private key operations make over specific connections; i.e. rather than asking whether the agent should be forwards, ask each time the key is used.
This seems fairly straightforward to implement: 1) Add a new flag to SSH2_AGENTC_SIGN_REQUEST, SSH_AGENT_NONLOCAL. 2) Add a new key constraint flag, SSH_AGENT_CONSTRAIN_CONFIRM_NONLOCAL. (Either as a separate flag, or by defining a two-bit field including SSH_AGENT_CONSTRAIN_CONFIRM and this; doing the latter would allow a fourth constraint possibility rather than the useless combination of the two.) 3) If the connection has "ForwardAgent ask" (or some other sensible configuration option) set, the local SSH will proxy the agent protocol and add SSH_AGENT_NONLOCAL to all SSH2_AGENTC_SIGN_REQUEST messages. 4) The SSH agent, given a key with SSH_AGENT_CONSTRAIN_CONFIRM_NONLOCAL set, will prompt iff the SSH_AGENT_NONLOCAL flag appears. Note that this approach covers SSH2 key operations only. Adding support for SSH1 key operations would require a new protocol message, since SSH_AGENTC_RSA_CHALLENGE has no flags field to extend. This doesn't seem necessary, though; just don't forward agents to hosts you need SSH1 keys to log into.
I had something more simple in mind: have ssh(1) send a magic request (SSH_AGENTC_CONSTRAIN_CHANNEL / SSH2_AGENTC_CONSTRAIN_CHANNEL) that marks the entire listen socket as "untrusted" rather than doing it on a per-request basis. This has a couple of advantages: 1) no need to extend the per-request agent protocol. Presently unknown requests are refused without killing the protocol, so ssh(1) can make up its mind on whether to drop the connection if the agent refused the constraint (e.g. to be determined by the ExitOnForwardingFailure option) 2) a compromised ssh(1) can't like and get use of the keys after connection. Since the agent connection is established before much interaction with the server, there isn't much opportunity for a hostile server to corrupt the client. Even if a ssh(1) is owned later, the CONSTRAIN_CHANNEL message is irrevocable so the user has at least some chance to see if something is awry. This might matter in some configurations where ssh(1) is sandboxed in some way. There are some caveats though: 1) ssh needs to learn to interpret (a subset of) the agent protocol. Right now the agent is pretty much a dumb pipe. 2) We need to find some weasel wording for the manpage to explain the trust relationship between the agent and the ssh client. Right now there isn't much of one, but with this change ssh(1) will be trusted to correctly label connections. To go further than this, it might be possible to sign agent requests with the host keys (or some derivative thereof) of each intervening host that the agent is forwarded through, but this would need careful design and analysis. It wouldn't be trivially backwards compatible like this proposal either.
Would be great to have some kind of "ask every time" in instead of having to set it to a blind "yes" for the whole connection.
I have gpg-agent set up to ask me to confirm each use of the key for authentication so that each act of forwarding by a remote host is confirmed. This gets extremely annoying when I make lots of connections from my local host as I already have to trust my own "ssh" command so it should not need to prompt for this. (In reply to Damien Miller from comment #3) > I had something more simple in mind: have ssh(1) send a magic > request (SSH_AGENTC_CONSTRAIN_CHANNEL / > SSH2_AGENTC_CONSTRAIN_CHANNEL) that marks the entire listen socket > as "untrusted" rather than doing it on a per-request basis. I'd like this because it'd solve my problem by allowing gpg-agent to only request confirmation on subsequent authentication requests. It would be helpful if ssh could include a "user@host" in the constrain message, so that this could also be displayed, providing some context as requested by bug 1876. (In reply to Damien Miller from comment #3) > To go further than this, it might be possible to sign agent requests > with the host keys (or some derivative thereof) of each intervening > host that the agent is forwarded through, but this would need careful > design and analysis. It wouldn't be trivially backwards compatible > like this proposal either. If you wanted to provide context for different remote hosts, you could have each agent forwarding socket create a new connection all the way back to the original ssh client, and use multiple "constraint channel" messages to indicate the path. When you're using a forwarded agent and ssh elsewhere, a new agent connection would be made and each ssh client up the path to the original host could add its own constrain message indicating where it had connected to. You'd have to trust each host in the path to tell you where it's connecting to but this is already the case. Even if the agent requests were signed, or you could prove that you were connecting to a known remote host and the key data would only work on that one authentication, you can't necessarily trust the remote host not to do something malicious with your connection. Knowing the path you (appear to) take to reach the new remote host is the one you expect would be enough.