Hi all,
I'm implementing an ssh client using the ssh package;
my program checks the server's public key using ClientConfig.HostKeyCallback
Unfortunately, it fails login to some servers if the server has multiple keys
(e.g., ssh_host_ecdsa_key, ssh_host_rsa_key, and ssh_host_dsa_key)
and the client has a public key other than ECDSA.
SSH client in Google Go always lists the host key algorithms in the SSH_MSG_KEXINIT message
in this order:
* ECDSA256
* ECDSA384
* ECDSA521
* RSA
* DSA
See the source code:
If the server has both ECDSA and RSA keys, and the client knows only the RSA public key,
the implementation in Google Go will always use ECDSA, so the SSH handshake will fail.
Only the ECDSA public key will be passed to ClientConfig.HostKeyCallback, then the SSH handshake will fail.
In order_hostkeyalgs function (file sshconnect2.c), they find all public keys in known_hosts
for this host and place the corresponding algorithms at the beginning of the list of host key
algorithms in SSH_MSG_KEXINIT. For example, if the client has an RSA key for this host,
the list of algorithms passed to the server will be:
* ssh-rsa (we have a key for it in known_hosts)
* ECDSA
* ... (other algorithms supported by the client)
RFC 4253, chapter 7.1 says:
"The first algorithm on the client's name-list that satisfies the requirements and
is also supported by the server MUST be chosen. If there is no such algorithm, both
sides MUST disconnect."
So, the implementation in Google Go seems to be incorrect.
What do you think about it? How do you check server's public key when using the ssh package?
Thanks.
Peter.