14

I'm having a hard time finding proper docs on the order in which the OpenSSH client tries private keys for authenticating against a server, given that all of the following are present:

  • key files with default names in ~/.ssh, e.g. ~/.ssh/id_rsa,
  • key files with non-default names that are configured to be used with a specific host via ~/.ssh/config,
  • keys managed by ssh-agent.

Are all of these locations always tried (provided that the host matches an entry in ~/.ssh/config), and in which order?

Background: I have ~/.ssh/id_rsa which can only be used to authenticate against server A, and I have another key managed by ssh-agent that can only be used to authenticate against server B. When trying to ssh to B, authentications fails, apparently because only ~/.ssh/id_rsa is tried. There does not seem to be a fallback to try the key managed by ssh-agent.

sschuberth
  • 243
  • 2
  • 7

2 Answers2

13

I know about the -v, -vv etc. options, but I'd like to know before I try how ssh is going to behave. There must be a saner method to find out than trial and error.

Use the source, Luke!

OpenSSH is open source so instead of trial-error, you can read the code to get better understanding what is going on there. ssh.c is a good place to start. It has a function load_public_identity_files(void), which takes care of this. In the first place, the keys from PKCS#11 (Smartcard, HSM) are used:

(nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,

and then the keys provided by options.identity_files:

for (i = 0; i < options.num_identity_files; i++) {

This variable is set in readconf.c:

if (options->num_identity_files == 0) {
    add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
    add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
#ifdef OPENSSL_HAS_ECC
    add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
#endif
    add_identity_file(options, "~/",
        _PATH_SSH_CLIENT_ID_ED25519, 0);
}

The real paths of the files are defined in pathnames.h:

#define _PATH_SSH_USER_DIR  ".ssh"
[...]
#define _PATH_SSH_CLIENT_ID_DSA     _PATH_SSH_USER_DIR "/id_dsa"
#define _PATH_SSH_CLIENT_ID_ECDSA   _PATH_SSH_USER_DIR "/id_ecdsa"
#define _PATH_SSH_CLIENT_ID_RSA     _PATH_SSH_USER_DIR "/id_rsa"
#define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519"

To the background question:

This is exactly why the IdentitiesOnly option exists and why you should use it in the ~/.ssh/config if you have more than one key to manage. The ssh-agent identities are used after the default ones.

Jakuje
  • 9,145
  • 2
  • 40
  • 44
  • 1
    While I appreciate you digging into the source code for me, that's not much saner (regarding the amount of work) than trial & error. I mean, this *must* be documented somewhere, as it's essential for configuring SSH correctly. – sschuberth May 12 '17 at 09:53
  • 1
    I don't think it *must* ... it is quite implementation detail. Manual pages (for `ssh` and `ssh_config`) specify that these paths are used by default and it is enough for basic user. If you want to know the order, debug log is where you find it quite easily. If it is not enough, source is here for you. – Jakuje May 12 '17 at 10:09
  • 1
    "The `ssh-agent` identities are used after the default ones", that does not match my observation from my OP. `ssh` seems to only try the first applicable key, and as by default `~/.ssh/id_rsa` etc. are always applicable, it does not try `ssh-agent` provided keys but fails immediately. – sschuberth Apr 25 '19 at 06:52
2

If you want to see how SSH client tries private keys for authenticating against a server, you can run it with -v option.

In my case it looks like:

debug1: Trying private key: /Users/atolkachev/.ssh/id_rsa
debug1: Trying private key: /Users/atolkachev/.ssh/id_dsa
debug1: Trying private key: /Users/atolkachev/.ssh/id_ecdsa
debug1: Trying private key: /Users/atolkachev/.ssh/id_ed25519
Alexander Tolkachev
  • 4,513
  • 3
  • 14
  • 23