EXCEPTIONS

When using exceptions in commands like do_request_service, when should
we use the passed in exception handler, and when should we use the
handler in the connection struct? Perhaps we should not have any
connection->e handler at all?

What about A_WRITE()? Perhaps it would make things simpler if this
method doesn't get any exception handler argument? If the destination
is dead, the function should either call fatal() or ignore the data.
If the data is somehow bogus, an error could be signalled to
connection->e or something like that.

Non-trivial handlers to write:

* The connection-error handler, which should recognize protocol errors,
  send a disconnect message, and close the fd for reading.

* The channel-exception handler, which should take care of channel
  close events, instead of the channel_process_status function.

Perhaps io.c should install its own exception handler on the fd:s, to
make sure that they are closed automaticalle on i/o errors? That would
simplify programs like sexp_conv.

  
KEYS

Code is needed to generate, store and read dss keys. Preferably in a
SPKI/s-expression form.

Fix compliance with the (next) SPKI draft. In particular, the order of
fields and the encoding of numbers needs updating.


S-EXPRESSIONS

Add newlines and pretty printing to the sexp formatter.
Rewrite the sexp parser so that the scanner class inherits
read_handler.


USERS

Functions to lookup users, their passwords and .lsh/authorized_keys.
Also have a look at 'Pluggable Non Interactive Authentication Modules'
at http://www.msu.ru/pniam/pniam.html.


CHARSETS

The conversion from UTF8->unicode->latin1 doesn't handle accented
characters properly. Probably needs a complete rewrite.


CONFIGURATION

Read configuration files. Better command line options. In particular
lsh.c needs a cleanup of argument parsing, probably using argp.


LOGGING

Use syslog to log server startup, shutdown, and user authentication.
Update utmp (users currently logged in), wtmp (record of logins) and lastlog
(last login time).
Use tcpwrapper's libwrap to log connections and perform access control.


ALLOCATION

Not all packet consumers free processed packets properly.

Have the allocator initialize all objects automatically.

Better typechecking of non-heap objects. To do this one would also
need valid isa-pointers in classes (as classes are statically
allocated). If this is done properly, the meta feature could also be
cleaned up a little.

Fix gc_kill to deallocate objects immediately.

Consider adding reference counts to strings.


CHANNELS

Create some generic methods for connecting a channel to one or more
files. The data shuffling and error handling should be very similar
for most channel types. 

Fix the handling of EOF on fd:s associated with channels. Related
stuff functions: make_channel_read_data,
make_exc_read_eof_channel_handler, consuming_read.

Consider which errors can occur in the channel callback functions;
they are probably somewhat different from errors in higher levels. For
instance, a writing to a file associated with a channel may fail. In
that case, the channel should be closed, but the connection should not
die. Handle the LSH_CHANNEL_FINISHED code properly.

Should channels be resources, or get some other kind of notification
if the connection they are associated with disappears?


CHANNEL CLOSE

Channels may need some live-ness status. For instance, a remote
process may close its stdout and stderr, but still keep on running. In
this case, the local process should close it's stdout and stderr, but
not close the channel until it has received a close message and
possibly an exit status.


USER INFO

Where should the user information (name, home directory, login shell,
etc), be stored? Is there any reasonable place but the connection
structure? Perhaps the channel_open handler for the session is a
reasonable place? Then we only have to figure out when to install that
information.


PROCESSES

Dying children must be handled. For example like this: Use a signal
handler to set a flag when a child dies. Let the backend loop (io.c)
look at this flag, wait() to get status from dying children. Use an
alist pid->callback to report children's exit status back to the remote
end. Another issue are process groups... Are they relevant? 

Kill child processes if its channel or its connection is closed
unexpectedly. 


FREENESS

It might be safer to remove patent-encumbered code like IDEA code from the
regular lsh distribution, and make it available separately (this approach is
taken with GnuPG).

scsh is not free software. Olin Shivers (one of the scsh copyright owners)
has indicated he is willing to free it, but currently he has no time to
handle the paperwork. We need scsh to be freed, or we need to rewrite the
Scheme scripts so that they are as portable between Scheme implementations
as possible, or switch to a free Scheme implementation, like Guile. This is
not urgent however.


CONTROL LANGUAGE

Implement some kind of tracing in the command language (the current
attempt is broken). Implement and use exceptions.

Improve the tail recursiveness of builtin functions.


FORWARDING

Perhaps split tcpforward.c into two files, tcpforward.c and
tcpforward_commands.c. Implement other types of forwarding; X,
ssh-agent, UDP, etc.

Review the naming of functions in tcpforward.c; it appears a little
inconsistent. 


MISC

Try to find out why read() sometimes returns -1 and sets errno==EPIPE,
on sparc-linux, 2.0.33, redhat-5.1, glibc.
Note: Debian's sparc port uses glibc2.1, rather than 2.0; maybe Red Hat does
too? Quite a lot of things have changed between 2.0 and 2.1; this might well
be a documented feature of 2.1.

"lsh" is already used as the name of a shell (included in Debian;
Description: Baby Shell for Novices with DOS compatible commands). Perhaps
we need to change our name?

Get a decent source of random (the current version will fall back to a
really poorly seeded generator if /dev/urandom is not available). Two
main alternatives are Werner Koch's code in GnuPG, and Peter Gutmann's
libcrypt. 

Make it cleaner wrt. more gcc warnings.

Fix desTest.c to use proper declarations of its function pointers, and
have autoconf check for rusage().

Use argp instead of getopt_long (but we must first find out how to use
argp on non-glibc systems).

It seems that it is a little difficult to detect that an asyncronous
connect() failed; poll() indicates that both reading and writing is
possible, but write failes (with EPIPE/SIGPIPE) later. Perhaps a
linux-problem?

Extract handling of hex and base 64 encodings into a separate file.

Include length fields when hashing in
publickey_crypto.c:init_diffie_hellman_instance() (Done now). Perhaps
some of this code should be moved to keyexchange.c? Similar
considerations apply also to other hashes.

Fix so that lsh compiles in the absense of zlib.

Fix configure script to add appropriate -R options when linking.
Currently, using a shared libz.so doesn't work.

Fix the src/symmetric/desTest program. It doesn't complain if the
desCode is compiled with empty keymap.h, parity.h and rotors.h files.

About POLLHUP:

  I've found something that can either be an io.c or a linux kernel bug.
  This time it is the poll() system call, which causes troubles. If an
  AF_UNIX connection is closed by the client, the kernel doesn't set
  POLLIN in revents, instead it sets only POLLHUP. (and therefore the io
  backend doesn't read the last zero length packet) The following patch
  solves the problem for me:
  
  -        if (fds[i].revents & POLLIN)
  -          READ_FD(fd);
  +        if (fds[i].revents & (POLLIN | POLLHUP))
  +          READ_FD(fd);
  
  jpoll.h doesn't define POLLHUP, so I added a
  
  #define POLLHUP         0
  
  line there. I seldom use poll() so I don't know what the correct
  behaviour should be, but I am afraid this is a kernel bug again.
  
  --
  Bazsi

Find out why opening /dev/ptmx failes occasionally (errno = 19, no
such device).

Add some workaround for the poll()-bug in linux/glibc-2.07 reported by
Bazsi. Hmm, this is probably not a bug. I have to find out what the
right way is to handle the poll conditions POLLERR, POLLHUP and
POLLERR. For a start, the fd-list passed to poll should include only
fd:s that we are actually interested in.

Implement some limit on the amount of data that may be buffered for
write on a connection. When the limit is exceeded, the connection
should be dropped. The problem: if a client connects and sends a lot
of packets, without ever reading anything from its socket, the server
will eventually run out of memory.

Consider removing the write-attribute from ssh_channel.

Let init_channel take enough arguments to initialize the window- and
packet-size fields properly. It's too easy to forget them.

It would be nice also to be able to see what encryption and compression
algorithms were negotiated, if these are chosen at connect time, when
verbose mode is on. (David C Niemi <niemi@niemi.erols.com>).

Remove the EXC_IO_EOF exception, and let the read handler get a NULL
argument instead. This is already done for buffered_read, should we do
it for consuming_read as well?

Add const to arguments of type struct exception_handler *?

Do something reasonable in do_buffered_read() when self->handler is
NULL?

Figure out why -nt doesn't work.

In channel_eof() and channel_close(), don't assert() that close or eof
have not been sent already, but instead check the appropriate flags
and do the right thing.
