Micah Cowan
2014-Oct-09 18:38 UTC
Feature rqst/Patch: Attempted key's fp in env to AuthorizedKeysCommand
Hello. My employer (Akamai Technologies) had a case where they wanted to manage a large number (tens of thousands) of authorized keys for a single user. I'm sure there may be alternatives to that sort of use case, but at any rate it was decided that the simplest way to proceed would be to use OpenSSH's AuthorizedKeysCommand config option, with the extension that the attempted key's fingerprint would be placed in the environment of the command, so that it could use it as an index, and limit its output to only the relevant key, so that OpenSSH wouldn't spin around, linearly processing large number of keys to be thrown away in a moment. It was thought that it might be worth providing the patch in case it was thought to be useful to a wider audience. NOTES: - The patch below is similar to, but not quite the same, as the patch that was actually created for Akamai's use. Our patch uses a different name for the env var, and was written against Ubuntu's openssh source package, with a variety of other custom in-house patches atop it. - It is thus UNTESTED. It didn't seem worthwhile to me to set up a proper testing environment, as I suspect there's a strong chance it won't be applied upstream unchanged, and that at any rate you folks probably test more thoroughly than I would know to. (And the patch is trivial in any case.) - Are the results from this command cached in any way, and then reused if the user is trying multiple keys (say, from ssh-agent)? That won't be the way we're using it, so probably doesn't matter for us; but it'd be reasonable for a general-audience implementation to take that into account. This patch assumes no, and expects subsequent key attempts would result in additional invocations of user_key_command_allowed2 for each attempted key, but I hadn't actually confirmed this to be the case. - We're just using the SHA256 fingerprint, but it doesn't seem like it'd be a bad idea just to get all three sum-types, and throw them all into the environment, so users could use whichever they preferred for the index lookup (or whatever use they're putting it to). I originally wrote the patch to use MD5, but was then asked to use a stronger hash instead. But when the purpose is indexing, and not verification or direct authentication, I don't see much harm in using "weak" hashes. Patch follows. Thanks for your attention/feedback! -mjc diff -urNp openssh-6.7.orig/auth2-pubkey.c openssh-6.7/auth2-pubkey.c --- openssh-6.7.orig/auth2-pubkey.c 2014-07-15 08:54:14.000000000 -0700 +++ openssh-6.7/auth2-pubkey.c 2014-10-09 11:07:02.620077981 -0700 @@ -507,6 +507,7 @@ user_key_command_allowed2(struct passwd int status, devnull, p[2], i; pid_t pid; char *username, errmsg[512]; + char *envsha256; if (options.authorized_keys_command == NULL || options.authorized_keys_command[0] != '/') @@ -595,6 +596,20 @@ user_key_command_allowed2(struct passwd _exit(1); } + /* + * Put attempted key's fingerprint in environment, so + * users with many authorized keys can use indexing and + * return only the single relevant key for processing. + */ + envsha256 = key_fingerprint(key, SSH_FP_SHA256, + SSH_FP_HEX); + if (setenv(SSH_ATTEMPT_KEY_SHA256_ENV_NAME, envsha256, 1) + == -1) { + error("%s: setenv: %s", __func__, strerror(errno)); + _exit(1); + } + free(envsha256); /* Key has been copied into env. */ + execl(options.authorized_keys_command, options.authorized_keys_command, user_pw->pw_name, NULL); diff -urNp openssh-6.7.orig/ssh.h openssh-6.7/ssh.h --- openssh-6.7.orig/ssh.h 2010-06-25 00:14:46.000000000 -0700 +++ openssh-6.7/ssh.h 2014-10-09 11:04:28.720082528 -0700 @@ -69,6 +69,12 @@ #define SSH_ASKPASS_ENV "SSH_ASKPASS" /* + * Name of the environment variable used to pass the key fingerprint to the + * command named by the AuthorizedKeyCommand configuration setting. + */ +#define SSH_ATTEMPT_KEY_SHA256_ENV_NAME "SSH_ATTEMPT_KEY_SHA256" + +/* * Force host key length and server key length to differ by at least this * many bits. This is to make double encryption with rsaref work. */ (End of message.)
Daniel Kahn Gillmor
2014-Oct-09 18:55 UTC
Feature rqst/Patch: Attempted key's fp in env to AuthorizedKeysCommand
On 10/09/2014 02:38 PM, Micah Cowan wrote:> Hello. My employer (Akamai Technologies) had a case where they wanted to > manage a large number (tens of thousands) of authorized keys for a > single user. > > I'm sure there may be alternatives to that sort of use case, but at any > rate it was decided that the simplest way to proceed would be to use > OpenSSH's AuthorizedKeysCommand config option, with the extension that > the attempted key's fingerprint would be placed in the environment of > the command, so that it could use it as an index, and limit its output > to only the relevant key, so that OpenSSH wouldn't spin around, > linearly processing large number of keys to be thrown away in a moment.Thanks for working on this, Micah, and for publishing your patch. are you aware of: https://bugzilla.mindrot.org/show_bug.cgi?id=2081 This feedback should probably go to that bug report. fwiw, i think if we're supplying the key, there's no sense in supplying just the fingerprint -- go ahead and supply the whole key, and let the authorizedkeyscommand do whatever digesting it wants to do. --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 949 bytes Desc: OpenPGP digital signature URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20141009/e0f724f8/attachment.bin>
Nico Kadel-Garcia
2014-Oct-11 15:02 UTC
Feature rqst/Patch: Attempted key's fp in env to AuthorizedKeysCommand
On Thu, Oct 9, 2014 at 2:38 PM, Micah Cowan <micah at addictivecode.org> wrote:> Hello. My employer (Akamai Technologies) had a case where they wanted to > manage a large number (tens of thousands) of authorized keys for a > single user.Did you talk to Andy or Brian over in the security group before publishing this? Feel free to tell them I said "Hi". I worked with them back when I was in the old Systems Engineering group, there over 10 years ago. And I did the tools to switch them from a commercial to the available OpenSSH based server back then. I was *very, very glad* that restarting sshd did not kill the SSH session you were currently using, but as a belt and suspenders move I'd start up the old sshd on a separate port before switching to the new one, just in case things got interrupted. And when you deal with that many hosts, some interruptions are *inevitable*.> I'm sure there may be alternatives to that sort of use case, but at any > rate it was decided that the simplest way to proceed would be to use > OpenSSH's AuthorizedKeysCommand config option, with the extension that > the attempted key's fingerprint would be placed in the environment of > the command, so that it could use it as an index, and limit its output > to only the relevant key, so that OpenSSH wouldn't spin around, > linearly processing large number of keys to be thrown away in a moment.That... sounds workable, and might scale well for other quite large environments. I'm particularly thinking of github and Sourceforge and other large 'git' or 'svn+ssh' environments. I also see that you've not included any documentation whatsoever for the user. Can I encourage you to add documentation in the relevant man pages along with your patch?> It was thought that it might be worth providing the patch in case it was > thought to be useful to a wider audience. > > NOTES: > - The patch below is similar to, but not quite the same, as the patch > that was actually created for Akamai's use. Our patch uses a > different name for the env var, and was written against Ubuntu's > openssh source package, with a variety of other custom in-house > patches atop it.Heh-heh-heh-heh. Oh, I could guess at some of them, including one I ripped out by the roots way back when. That was the old 'turn off reverse DNS lookups' patch, which is better handled by using 'sshd -u0' in the init scripts.> - It is thus UNTESTED. It didn't seem worthwhile to me to set up a > proper testing environment, as I suspect there's a strong chance it > won't be applied upstream unchanged, and that at any rate you folks > probably test more thoroughly than I would know to. (And the patch is > trivial in any case.)OK, now I'm laughing *really* hard. I used to do hardware evaluations there, as well as OS image building, and completely rebuilt the tools used to build test environments and new hosts. I certainly hope they still have that flexibile "rebuild at whim" capability. I'm afraid I've not personally been testing 6.7 yet. I tend to test in personal VM's on my laptop these days, so if I can find time to test it on an RHEL environment, I'll do so. No promises right now.> - Are the results from this command cached in any way, and then reused > if the user is trying multiple keys (say, from ssh-agent)? That > won't be the way we're using it, so probably doesn't matter for us; > but it'd be reasonable for a general-audience implementation to take > that into account. This patch assumes no, and expects subsequent > key attempts would result in additional invocations of > user_key_command_allowed2 for each attempted key, but I hadn't > actually confirmed this to be the case. > - We're just using the SHA256 fingerprint, but it doesn't seem like > it'd be a bad idea just to get all three sum-types, and throw them > all into the environment, so users could use whichever they > preferred for the index lookup (or whatever use they're putting it > to). I originally wrote the patch to use MD5, but was then asked to > use a stronger hash instead. But when the purpose is indexing, and > not verification or direct authentication, I don't see much harm in > using "weak" hashes.I personally agree with your risk assessment.> Patch follows. Thanks for your attention/feedback! > -mjc > > diff -urNp openssh-6.7.orig/auth2-pubkey.c openssh-6.7/auth2-pubkey.c > --- openssh-6.7.orig/auth2-pubkey.c 2014-07-15 08:54:14.000000000 -0700 > +++ openssh-6.7/auth2-pubkey.c 2014-10-09 11:07:02.620077981 -0700 > @@ -507,6 +507,7 @@ user_key_command_allowed2(struct passwd > int status, devnull, p[2], i; > pid_t pid; > char *username, errmsg[512]; > + char *envsha256; > > if (options.authorized_keys_command == NULL || > options.authorized_keys_command[0] != '/') > @@ -595,6 +596,20 @@ user_key_command_allowed2(struct passwd > _exit(1); > } > > + /* > + * Put attempted key's fingerprint in environment, so > + * users with many authorized keys can use indexing and > + * return only the single relevant key for processing. > + */ > + envsha256 = key_fingerprint(key, SSH_FP_SHA256, > + SSH_FP_HEX); > + if (setenv(SSH_ATTEMPT_KEY_SHA256_ENV_NAME, envsha256, 1) > + == -1) { > + error("%s: setenv: %s", __func__, strerror(errno)); > + _exit(1); > + } > + free(envsha256); /* Key has been copied into env. */ > + > execl(options.authorized_keys_command, > options.authorized_keys_command, user_pw->pw_name, NULL); > > diff -urNp openssh-6.7.orig/ssh.h openssh-6.7/ssh.h > --- openssh-6.7.orig/ssh.h 2010-06-25 00:14:46.000000000 -0700 > +++ openssh-6.7/ssh.h 2014-10-09 11:04:28.720082528 -0700 > @@ -69,6 +69,12 @@ > #define SSH_ASKPASS_ENV "SSH_ASKPASS" > > /* > + * Name of the environment variable used to pass the key fingerprint to the > + * command named by the AuthorizedKeyCommand configuration setting. > + */ > +#define SSH_ATTEMPT_KEY_SHA256_ENV_NAME "SSH_ATTEMPT_KEY_SHA256" > + > +/* > * Force host key length and server key length to differ by at least this > * many bits. This is to make double encryption with rsaref work. > */ > > (End of message.) > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev