mirror of
http://galexander.org/git/simplesshd.git
synced 2024-12-29 09:28:07 +00:00
133 lines
5.0 KiB
Plaintext
133 lines
5.0 KiB
Plaintext
December 6, 2014.
|
|
|
|
The idea is to make a proper ssh implementation for Android. Important
|
|
features:
|
|
|
|
* it should run happily without root (on a non-root port)
|
|
|
|
* it should be a regular android app requiring no special permissions,
|
|
and not requiring any 'magic' executable files
|
|
|
|
* should not rely on busybox
|
|
|
|
* preferably support sftp
|
|
|
|
* open source
|
|
|
|
The existing apps are either expensive, don't work, need root, or too
|
|
complicated, or a mix of all of the above. And none of them are open
|
|
source.
|
|
|
|
I figure I'll start with dropbear, which I will run through JNI instead
|
|
of putting it in its own binary (because making such a binary executable
|
|
is a bit of a hack).
|
|
|
|
So that's the plan........
|
|
|
|
|
|
December 14, 2014.
|
|
|
|
I got dropbear to compile under the Android NDK, so now it's time to work
|
|
on the Android side of it.
|
|
|
|
I need:
|
|
* a Service that can be started, stopped, and queried for whether it's
|
|
running or not
|
|
* a Thread to implement the Service's work (by calling into dropbear's
|
|
main()), which can also be stopped.
|
|
* a config UI with at least these choices:
|
|
- bool: start on boot (def: false)
|
|
- number: port number (def: 2222)
|
|
- string: path to authorized_keys file (def: /sdcard/ssh)
|
|
- string: name of default shell (def: /system/bin/sh -l)
|
|
- string: default path for HOME (def: /sdcard/ssh)
|
|
- button: start or (if it's running) stop
|
|
|
|
|
|
December 15, 2014.
|
|
|
|
Getting to the fun part. Process management...
|
|
|
|
To start sshd, it seems like I can startService(). Then in the Service's
|
|
onStartCommand(), call startForeground() so it won't be killed (return
|
|
START_STICKY too?).
|
|
|
|
The question is if dropbear's main() should run under a separate Thread,
|
|
or a separate Process. The trouble with a Thread is that it might be
|
|
hard to kill. The trouble with a process is that there is no way to
|
|
report back status (such as a failure to start sshd).
|
|
|
|
Connectbot starts a new process for its shell -- it really doesn't have a
|
|
choice because the shell binary isn't linked with Connectbot, and exec()
|
|
in a thread stinks. To stop it, it just closes stdin/stdout!!! So
|
|
zombies can (and do) linger.
|
|
|
|
I suppose dropbear could be in its own process if it had something like
|
|
stdin/stdout to communicate failure? Or it could just write error
|
|
messages to (i.e.) /sdcard/ssh/log. To stop the service, it would just
|
|
use kill().
|
|
|
|
I am curious how the main waiting-for-connections loop looks, but even if
|
|
it uses select(), I'm not sure how I would honor Thread.interrupt() or
|
|
whatever. It's not guaranteed to interrupt select(), and I'm not keen on
|
|
adding an arbitrary timeout/polling feature to it.
|
|
|
|
|
|
December 20, 2014.
|
|
|
|
So, I added a builtin scp endpoint. It was pretty straight forward,
|
|
except dropbear defaults to vfork(), which blocks the parent until the
|
|
child runs execve()!!
|
|
|
|
Anyways, I noticed that scp doesn't quote its arguments to the remote
|
|
scp. That means you can't conveniently copy a remote file with a space in
|
|
its name (it becomes two files). But the upside is that this is where
|
|
wildcards are handled -- by the shell!
|
|
|
|
So I need to either run it as a separate executable launched through the
|
|
shell, or make my own implementation of wildcards.
|
|
|
|
It is easy, using a $(BUILD_EXECUTABLE) script, to get ndk to build an
|
|
executable. But it is only packaged up if it is named "gdbserver" (and
|
|
debug apk), or "libfoo.so". The good news is that libfoo.so can be
|
|
executed in /data/data/org.galexander.sshd/lib/libfoo.so, so that is a
|
|
viable option.
|
|
|
|
Doing the expansion myself is not necessarily hard either, though. I
|
|
need a library function called glob(), which is apparently not part of
|
|
bionic. But I have the idea some cut and paste would resolve that with
|
|
very little extra work on my part.
|
|
|
|
|
|
December 21, 2014.
|
|
|
|
Well, bionic libc *does* provide fnmatch(), and even scandir() (a
|
|
shortcut for readdir). In the best case, though, that still leaves me
|
|
with a bit of a path parsing conundrum (I have to tell scandir which
|
|
directory to operate on). And also a bit of an escape character
|
|
conundrum -- \* and "*" should not act like wildcards.
|
|
|
|
Those are not insurmountable but I think I've talked myself out of it.
|
|
So then the question is, do I figure out how to ship an executable, or
|
|
do I do some hack like open a pipe to "/system/bin/sh echo filespec" and
|
|
use the shell solely for expansion?
|
|
|
|
I'm developing the idea that it's actually pretty easy to ship an
|
|
executable, I just need to find some -pre-package step where I can do
|
|
"mv scp libscp.so" and then it will ship. ndk-build will not let me make
|
|
a target with a "." in it directly.
|
|
|
|
...
|
|
|
|
Now scp, sftp-server, and rsync work as separate executables... rsync
|
|
does fail at -z because it needs it's own custom zlib...The stock
|
|
"external" one seems to lack the "old-style compress" method. There is
|
|
another commandline option for the new (deflate?) technique, but I think
|
|
the normal -z ought to work too. But that is literally the last feature!
|
|
Then just release details.
|
|
|
|
XXX - rsync should use its builtin zlib...
|
|
|
|
XXX - document (ga.org/software/simplesshd/)
|
|
XXX - upload
|