Mailing List Archive

ForwardAgent without IdentityAgent?
[.running on
OpenSSH_9.0, LibreSSL 3.6.0
OpenBSD 7.1-current (GENERIC.MP) #630: Mon Jul 18 09:28:20 MDT 2022
deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP]

Hi,

I usually use distinct IdentityFile values for distinct sites without
IdentityAgent set or ssh-agent(1) running, so site A never sees login
attempts with !A keys.

Now I want to forward an agent containing keys for site B onto site A.
Logging into A shall only use its respective key and from A I want to
to be able to connect to B using the forwarded agent.

Having read ssh_config(5)'s ForwardAgent description, my impression was
that setting this option to a socket path should be enough, i.e.
$ ssh -oForwardAgent=/path/to/B.sock A

Testing however shows that ForwardAgent has no effect unless
IdentityAgent is set whatever yields the same socket.

This in turn causes SSH to use the identity agent for authentication
against A (explicitly undesired) and adding both A and B keys to the
agent forwarded would result in using both keys A and B for
authentication against B (explicitly undesired).


It is not obvious to me from the manual that ForwardAgent requires
IdentityAgent, neither does it make sense to me.

What is the benefit of overwriting IdentityAgent's socket path with
ForwardAgent=/path/to/sock?

Using IdentityAgent=yes|SSH_AUTH_SOCK|/path/to/sock together with
ForwardAgent=yes is clear, as that's simply how to use a single agent
for site A and whatever follows on site A.

Is this behaviour intended and thus possibly underdocumented?

Should the relatively new SSH agent restriction functionality be used
for usecases like mine?

Or can/should ForwardAgent work without IdentityAgent, i.e. can I simply
forward an agent without using it for the initial connection?


FWIW, here is how I tested against a default /etc/ssh/sshd_config config
on my local OpenBSD system:

1. create dummy site A (aka. localhost):
$ doas rcctl -f start sshd
$ cd `mktemp -d`
$ ssh-keygen -q -N '' -f ./A.key
$ cat ./A.key.pub >> ~/.ssh/authorized_keys
$ ssh -F none -i ./A.key localhost -- 'env | grep ^SSH'
SSH_CLIENT=127.0.0.1 41399 22
SSH_CONNECTION=127.0.0.1 41399 127.0.0.1 22

3. create dummy key and agent for site B:
$ ssh-keygen -q -N '' -f ./B.key
$ SSH_AUTH_SOCK=./B.sock ssh-add ./B.key
Identity added: ./B.key (./B.key)

4. login to A with key alone and forward agent B:
$ ssh -F none -i ./A.key -o IdentityAgent=none \
-o ForwardAgent=./B.sock localhost -- \
'env | grep ^SSH ; ssh-add -l'
SSH_CLIENT=127.0.0.1 19770 22
SSH_CONNECTION=127.0.0.1 19770 127.0.0.1 22
Could not open a connection to your authentication agent.

Adding `-vvv' here shows no debug log about IdentityAgent or
ForwardAgent whatsoever.

Neither does "enabling" IdentityAgent, i.e. using "yes" or "/dev/null"
(whilst having SSH_AUTH_SOCK unset in, of course) work.

5. login to A with key and wrong agent B and forward agent B:
$ ssh -F none -i ./A.key -o IdentityAgent=./B.sock \
-o ForwardAgent=./B.sock localhost -- \
'env | grep ^SSH ; ssh-add -l'
SSH_AUTH_SOCK=/tmp/ssh-vaPtauEZPt/agent.80209
SSH_CLIENT=127.0.0.1 5081 22
SSH_CONNECTION=127.0.0.1 5081 127.0.0.1 22
3072 SHA256:mgkO5o+UnLNER2rh3uNkAJr0Zbbz0YKNBpBzawfuVBQ ./B.key (RSA)

Adding `-vvv' here shows how B.key is tried against A (undesired) and
A.key is used to login to A (as intended):

debug1: Will attempt key: ./B.key RSA SHA256:mgkO5o+UnLNER2rh3uNkAJr0Zbbz0YKNBpBzawfuVBQ agent
debug1: Offering public key: ./B.key RSA SHA256:mgkO5o+UnLNER2rh3uNkAJr0Zbbz0YKNBpBzawfuVBQ agent
...
debug1: Offering public key: ./A.key RSA SHA256:dH9k2cvncTBOFjv+KWOqThAbZ6troMdfZuiW/Qp1aDs explicit
debug1: Server accepts key: ./A.key RSA SHA256:dH9k2cvncTBOFjv+KWOqThAbZ6troMdfZuiW/Qp1aDs explicit

So this logging into B from A would now be possible, but not without
disclosing B.key to A.


I see https://www.openssh.com/agent-restrict.html describes host rules
to limit keys in a single agent.

In theory, I could probably use a single agent and implement my
desired separation between distinct sites with such rules, but that
seems a) more error prone to me and b) requires more duplication, e.g.
hostnames and their relation now have to be manually entered into
ssh-agent(1) with ssh-add(1)'s `-h'.

With ForwardAgent working independently of IdentityAgent, I can leave
all that to existing Host/Match blocks which would conditionally set
ForwardAgent.
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Re: ForwardAgent without IdentityAgent? [ In reply to ]
Klemens Nanni wrote:
> In theory, I could probably use a single agent and implement my
> desired separation between distinct sites with such rules, but that
> seems a) more error prone to me and b) requires more duplication, e.g.
> hostnames and their relation now have to be manually entered into
> ssh-agent(1) with ssh-add(1)'s `-h'.

I'm not sure even that will accomplish what you want.

Once an agent socket is forwarded to A, A can communicate with that
agent at will.

If the agent can know to respond differently based on extra
information (e.g. that a request is coming from B through A) then it
could implement the rules you want, but AFAIK the agent can only know
*for sure* that a request arrived from A, nothing more.

The agent can't know whether A is truthful about a request originating
from B or from A itself.


I think you have to combine ProxyJump with a potentially complex
local agent setup/rules, and *never* forward any agent socket in
order to limit visibility of specific keys to specific hosts.


Kind regards

//Peter
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Re: ForwardAgent without IdentityAgent? [ In reply to ]
On Sun, 24 Jul 2022, Klemens Nanni wrote:

> Hi,
>
> I usually use distinct IdentityFile values for distinct sites without
> IdentityAgent set or ssh-agent(1) running, so site A never sees login
> attempts with !A keys.
>
> Now I want to forward an agent containing keys for site B onto site A.
> Logging into A shall only use its respective key and from A I want to
> to be able to connect to B using the forwarded agent.

You might also be able to use https://www.openssh.com/agent-restrict.html
for this.

> Having read ssh_config(5)'s ForwardAgent description, my impression was
> that setting this option to a socket path should be enough, i.e.
> $ ssh -oForwardAgent=/path/to/B.sock A
>
> Testing however shows that ForwardAgent has no effect unless
> IdentityAgent is set whatever yields the same socket.
>
> This in turn causes SSH to use the identity agent for authentication
> against A (explicitly undesired) and adding both A and B keys to the
> agent forwarded would result in using both keys A and B for
> authentication against B (explicitly undesired).
>
> It is not obvious to me from the manual that ForwardAgent requires
> IdentityAgent, neither does it make sense to me.
>
> What is the benefit of overwriting IdentityAgent's socket path with
> ForwardAgent=/path/to/sock?

I think this is likely to be an implementation detail that leaked out,
from not plumbing the IdentityAgent path through to
sshconnect2.c:ssh_get_authentication_socket() and it should probably
be cleaned up to allow fully separate Identity/ForwardAgent.

-d
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev