Authenticating users from proprietary user databases

Yaniv Aknin yaniv at aknin.name
Tue Oct 6 05:27:09 EST 2009


Hi,

I work for a company which develops a rather complicated Linux-based
grid-technology appliance. The appliance is made of several Linux hosts,
exposing its functionality over a proprietary CLI-like protocol. This
protocol currently works by running a proprietary client executable on a
host, sending the command via TCP/IP to one of the appliance's hosts and
receiving the response. The client handles authentication, compression, etc.
In addition, it is possible to access the various hosts of the clustered
appliance as a regular Linux host using plain SSH for technician maintenance
(not exposed to customers).

I'm a big proponent of exposing our CLI over SSH as well and doing away with
the proprietary "cli executable". Already the CLI executable can run inside
the appliance itself, and I'd very much like it to be possible to run a
single CLI command by running:
$ ssh user at appliance command parameter=value
...and also to make it possible to run a readline based appliance-CLI
interactive "shell" (we already have something like that) by running:
$ ssh user at appliance

We can easily separate (at least, at the transport layer) between the
"maintenance" SSH shell and the "CLI" SSH shell by running two sshd
instances and binding them to different ports (or addresses). I'm thinking
that the CLI-SSH instance have a sshd_config global ForceCommand that will
read SSH_ORIGINAL_COMMAND and run the CLI command or the 'CLI interactive
shell' accordingly. Also, I think I realize the security implications
insofar as our CLI executable is concerned, as well as the importance of
sanitizing the SSH connection (no sftp, no forwarding, etc). I'd much rather
not direct the discussion in that direction, unless you think this is
totally imperative and I missed something gargantuan. I know exploiting our
CLI can easily mean exploiting our box and I'll take that into account as
best I can (I'm not sure the current implementation is any better, either).

The issue I'm not sure how to tackle is how to make SSH 'natively'
authenticate the appliance's built-in users. Our appliance has its own user
directory with credentials, unrelated to the passwd/shadow directory of
nsswitch. The 'obvious' solution is to write an nsswitch module which will
fake all users from the appliance's proprietary directory as passwd:shadow
entries (we store the passwords in a way that is shadow compatible), and
give all users a uniform passwd entry with only the username/shadow hash
changing. This entry will have a fixed UID, GID, shell and homedir, and this
fixed homedir will contain an authorized_keys file that will dynamically
contain keys as set for our appliance's users (I'll add the CLI command
"user_add_ssh_key" or something).

While the above solution is, like I said, obvious, it has a very severe
drawback I'm not sure how to tackle, and that's the fact that nsswitch
modules are system global. I don't want our hosts' Linux users (root,
nobody, daemon, etc) to collide with the appliance's users and vice versa,
and I'd definitely not want to jeopardize the stability of core Linux
services in any way by adding something as complex as looking up our
clustered database for users from within all processes in the system.

I'm not sure how to further handle this. Should I patch OpenSSH itself (oh
god, please, no...)? Should I use some dynamic LD_PRELOAD concoction to
'rewrite' nsswitch.conf only for this sshd instance? Should I give up on
OpenSSH entirely and use an SSH implementation which is less focused on
letting system-users run shell-commands (like twisted.conch, or maybe
others)? All these options are... well, doable, but all seem like a lot of
(fragile) work. I'd appreciate comments and ideas.

Sincerely,
 - Yaniv


More information about the openssh-unix-dev mailing list