OpenSSH's IdentityFile directive only ever adds identity files (as of 7.4)

March 13, 2017

In some complicated scenarios (especially with 2FA devices), even IdentitiesOnly can potentially give you too many identities between relatively generic Host ... entries and host-specific ones. Since there is only so far it's sensible to push Host ... entries with negated hostnames before you wind up with a terrible mess, there are situations where it would be nice to be able to say something like:

Host *.ourdomain
  IdentityFile ...
  IdentityFile ...
  [...]

Host something-picky.ourdomain
  IdentityFile NONE
  IdentityFile /u/cks/.ssh/identities/specific
  IdentitiesOnly yes
  [...]

Here, you want to offer a collection of identities from various sources to most hosts, but there are some hosts that both require very specific identities and will cut your connection off if you offer too many identities (as mentioned back here).

I have in the past said that 'as far as I knew' IdentityFile directives were purely cumulative (eg in comments on this entry). This held out a small sliver of hope that there was some way of doing this that I either couldn't see in the manpages or that just wasn't documented. As it happens, I recently decided to look at the OpenSSH source code for 7.4 (the latest officially released version) to put this to rest once and for all, and the bad news is that I have to stop qualifying my words. As far as I can tell from the source code, there is absolutely no way of wiping out existing IdentityFile directives that have been added by various matching Host stanzas. There's an array of identities (up to the maximum 100 that's allowed), and the code only ever adds identities to it. Nothing removes entries or resets the number of valid entries in the array.

Oh well. It would have been nice, and maybe someday the OpenSSH people will add some sort of feature for this.

In the process of reading bits of the OpenSSH code, I ran across an interesting comment in sshconnect2.c's pubkey_prepare():

/*
 * try keys in the following order:
 * 	1. certificates listed in the config file
 * 	2. other input certificates
 *	3. agent keys that are found in the config file
 *	4. other agent keys
 *	5. keys that are only listed in the config file
 */

(IdentitiesOnly does not appear to affect this order, it merely causes some keys to be excluded.)

To add to an earlier entry of mine, keys supplied with -i fall into the 'in the config file' case, because what that actually means is 'keys from -i, from the user's configuration file, and from the system configuration file, in that order'. They all get added to the list of keys with the same function, add_identity_file(), but -i is processed first.

(This means that my earlier writeup of the SSH identity offering order is a bit incomplete, but at this point I'm sufficiently tired of wrestling with this particular undocumented SSH mess that I'm not going to carefully do a whole bunch of tests to verify what the code comment says here. Having skimmed the code, I believe the comment.)

Written on 13 March 2017.
« What should it mean for a system call to time out?
Sorting out Python generator functions and yield from in my head »

Page tools: View Source.
Search:
Login: Password:

Last modified: Mon Mar 13 23:05:53 2017
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.