Matt,
Answers embedded...
Ed
Hi,
I'm pretty sure there'd be interest in such a port, even if
there are no immediate takers. I guess it depends how much
effort you want to put in - a separate tarball (or hg
branch ease of merging future versions) might be enough for other
people to get going. It doesn't sound like the changes would
be _too_ intrusive, so could probably live in the main tree.
One concern would be avoiding it breaking from other changes
- would it be easy enough to build the embedded variant
targetting a normal Linux-type platform?
Yea, that shouldn't be too hard to do. The first level of change would
be to
use threads instead of fork, and also not spawn a shell, just interface to a
dumb command interpreter that users could replace with something
project specific. My plan is to use this in my uCon tool, so I'll have to
go down this path anyway, so maybe that would be the first step toward
integrating.
A few comments inline below.
no fork(), no exec(), no pipes, etc.. This includes no use of
fprintf(...) as well.
Missing fprintf() might make the code a bit messier - did
you encounter other uses than for logging/error messages?
No, mostly just error messages...
- I loosely base this on the "no-inetd" option; and I
heavily chopped away at things in options.h (hopefully
without breaking anything).
- Since there is no shell, this simply hooks to an internal command
line processor.
- Currently the server is built to run as if the following command
line were invoked:
./dropbear -s -F -b "yada yada" -r dropbear_rsa_host_key
and since I do have an FS, I created the dropbear_rsa_host_key
file using dropbearkey on my host machine, and simply
copied it to my embedded system's FS for now. The need
for the FS could easily be eliminated.
A good source of random values is pretty important for
SSH security. If there are say 16 bytes of good random
values written at "manufacturing", that could be read in as
input then saved out at Dropbear startup and occassionally
during operation (reusing the same seed twice would be very
bad). The write_urandom() would work for writing a value
back. A flash write per boot isn't great, but hard to see a
better way without random number generation hardware.
Yea I have a few system-specific ways to get a reasonably random value
out of my hardware, so that's not a problem; however, its also not portable.
DETAILS:
My build puts the two math directories into a library, and
then builds the server using portions of ~25 of the ~65 .c
files that are in the main dropbear directory.
Did you have to change much in the libtom libraries? I'm
planning to merge in tomsfastmath support (using the ltc_mp
descriptor to keep libtommath working as a fallback), that
might help performance as well by reducing malloc()s.
I don't think I changed anything there except for the malloc defines.
For all the dropbear code (I include libtom stuff in this) I replaced
all uses
of malloc (m_malloc, malloc, XMALLOC) with DB_MALLOC (same applies
to calloc/realloc/free) throughout. I had to do this so that I could easily
redefine all calls to malloc to pass __FILE__ and __LINE__ for debugging.
The point here is that it would be nice if ALL use of malloc used the same
name.
I simulate interaction with a shell by intercepting incoming
characters in common_recv_msg_channel_data(). Each line
of text is simply passed to a command line parser. While
that command line is being processed, all output from that
embedded command is sent through the function
ssh_putchar():
static void
ssh_putcharc(struct Channel *channel,char c)
{
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_DATA);
buf_putint(ses.writepayload, channel->remotechan);
buf_putint(ses.writepayload, 1);
buf_putbyte(ses.writepayload, c);
encrypt_packet();
}
You may as well write out at least 12 bytes at once (I
think), since encrypt_packet pads out to MIN_PACKET_LEN (=16)
with at least 4 bytes of padding.
Yea, understood, I buffer up when I know I can. This is just worst case.
and one other important thing...
At the bottom of encrypt_packet(), I call write_packet() so that the data
is immediately pushed out the socket.
That sounds fine.
SUMMARY:
Thats about it in the nutshell. The two big gotchas with this were
issues that
would not necessarily be important in a process-based environment:
1. The use of dropbear_exit() for errors requires the use of
setjmp/longjmp because
its in a thread that needs to cleanup properly.
2. The heap is clean when exits are clean; but things get messy in a lot of
exception cases; hence, the need for a dropbear-specific heap which
allows me to force a clean heap when the session ends (simulating
the cleanup that
is automatically done when the process exits).
It'd need a close look over releasing any resources other
than memory allocations, though there probably aren't many
things. libtom* might make use of some static variables.
Dropbear has a small number that can be fixed.
Cheers,
Matt