From time to time during the last couple of months, I've been
reorganizing the lsh code. At the moment, I've got far enough to be confident that it will work well, even though there still are several important pieces missing. The most important change is a split into several processes. On the server side, responsibility is split into three programs, with cuts between the layers in the ssh protocol:
* lshd: Accepts new connections, speaks the ssh transport protocol (i.e. key exchange, encryptioon, authentication, compression), authenticates the server. Userauth and channel related messages (i.e. ssh packets with first byte >= 50) are not processed, just past on via a pipe to a "service" process. Normally runs as root.
* lshd-userauth: Implements the ssh userauth protocol, and is started by lshd when the client requests the "ssh-userauth" service. Usually started as root, and changes uid to that of the logged in user before it exec:s the next program.
* lshd-connection: Implements the ssh connection protocol, with multiple channels, forwardings, etc. Always runs as the logged in user.
The idea is to make the components that need root privileges smaller and simpler. lshd-transport doesn't need to know anything of the more commplex parts of the ssh protocol. Since lshd-userauth runs as a separate process, it can use ordinary blocking i/o, and it can freely use blocking api:s to talk to other systems, e.g., kerberos and pam.
On the client side, I also split functionality into two programs, although this is of less importance:
* lsh-transport: Implements the client side of the transport and userauth protocols.
* lsh: Implements the connection protocol, channels, forwardings etc. Should also take over the gateway/connection sharing functionality. lshg should no longer be a separate program.
A side effect of this split is that I hope it should make it easier for people to reuse the ssh transport protocol for other applications. It should be reasonably straight forward to write glue to make an arbitrary network service fit as an ssh "service", with or without ssh userauthentication. The current transport protocol implementation is also much closer to being an "ssh library" than the old code was.
A related change is that the fairly complex i/o abstractions used by lsh have been ripped out. The parts that still need non-blocking i/o, i.e. everything but lshd-userauth, now use the liboop library directly to install the appropriate i/o callbacks.
At the moment, basic session channels and port forwarding works. Missing pieces:
* Since the server functionality is split in several processes, it's no longer practical to have all configuration via command line options. Configuration files are necessary. This is not yet implemented. The plan is to have one file per program, stored under /etc/lsh. All features should be off by default, but each program should have a command line option that exports a reasonable and commented sample file.
* utmp/wtmp logging. This actually the only issue I found so far that's fundamentally difficult to get right. The problem is that the logging is tightly coupled to pty allocation. And the pty allocation is done by lshd-connection, which doesn't have sufficient privileges to manipulate the system log files. I don't know how to best solve this, it seems like some daemon or setuid program is needed that can be made responsible for both pty allocation and proper logging.
* gateway/connection sharing functionality. Not yet implemented, but it should be fairly straight-forward.
* assorted missing features, like x11 forwarding and pty allocation. Also no big deal, but it's not currently working.
* in some places, the code relies on modern unix features, such as getaddrinfo. Work is needed to make the code portable to a wider variety of systems.
If anybody is curious, check out the branch "experimental_BRANCH_20050201" from CVS.
Happy hacking, /Niels