Before we negotiate a HostKey with the server, libssh should check the known_hosts file if there is an entry and prefer the key in the hosts file. This will avoid that keys in the hosts file are not accepted if newer host keys get supported.
This is actually implemented by the function ssh_known_hosts_get_algorithms(), but behaves a bit differently than a similar function in OpenSSH client:
- This function limits the offered list to only key types found in known_hosts. The OpenSSH counterpart takes the default and puts the known in front and the supported to the end of the list.
- This function does not consult the global known hosts file if I am right
- In my local setup, I noticed that the libssh selects only the ed25519 key, while openssh finds also the ecdsa, which I have stored in my known hosts.
From ./examples/ssh-client -vvvvv localhost:
[2018/10/18 11:46:38.912159, 3] ssh_client_select_hostkeys: Changing host key method to "ssh-ed25519" [...] [2018/10/18 11:46:38.912229, 4] ssh_list_kex: server host key algo: ssh-ed25519
From OpenSSH 7.8 ssh -vvv localhost:
debug3: hostkeys_foreach: reading file "/home/jjelen/.ssh/known_hosts" debug3: record_hostkey: found key type ED25519 in file /home/jjelen/.ssh/known_hosts:3 debug3: record_hostkey: found key type ECDSA in file /home/jjelen/.ssh/known_hosts:8 debug3: load_hostkeys: loaded 2 keys from localhost debug3: order_hostkeyalgs: prefer hostkeyalgs: email@example.com,firstname.lastname@example.org,email@example.com,firstname.lastname@example.org,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519 [...] debug2: host key algorithms: email@example.com,firstname.lastname@example.org,email@example.com,firstname.lastname@example.org,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,email@example.com,firstname.lastname@example.org,email@example.com,rsa-sha2-512,rsa-sha2-256,ssh-rsa
Do you happen to remember what was the exact use case that was broken by this? I will indeed work on the above issues, but I would like not to miss the original issue.
a) We what the same what OpenSSH does. I think the function ssh_known_hosts_get_algorithms() just gets the one from known_hosts but dosn't deal with the supported defaults.
b) The global hosts file is not supported in the new known_hosts API I totally forgot to impelment that. See T107
The following changes should settle the behavior to more sane that follows openssh and does not cause problems if there are more host keys stored in the known_hosts files:
It also updates tests to make sure this use case is validated.
I am still running the CI and memcheck, but this should resolve this issue.