diff --git a/DEVELOPING.md b/DEVELOPING.md index 20af2c38..bbe67246 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -5,15 +5,16 @@ See [INSTALL.md](INSTALL.md) for build instructions. [SMALL.md](SMALL.md) has hints for building smaller binaries, also see comments in [default_options.h](./src/default_options.h). -To be able to debug add `-g` compiler option to the `CFLAGS` environment variable. This will generate debug symbols. +To be able to debug add `-g` compiler option to the `CFLAGS` environment variable to generate debug symbols. ``` export CFLAGS="$CFLAGS -g" ``` #### File dependencies -The GitHub [test build script](./.github/workflows/build.yml) requires the [default_options.h](./src/default_options.h) be at the top of the repository tree. The script uses the file to generate localoptions.h with various features enabled/disabled. +The GitHub [test build script](./.github/workflows/build.yml) requires the [default_options.h](./src/default_options.h) be at the top of the repository tree. +The script uses the file to generate `localoptions.h` with various features enabled/disabled. -Following are generated files in the format \: \(\) +Following are generated files in the format `: ()` ``` - configure: autoconf(configure.ac) - config.h.in: autoheader(configure.ac) @@ -25,11 +26,16 @@ Although generated, the first two files are checked in as they change very infre #### Debug printing -Set `#define DEBUG_TRACE 1` in [localoptions.h](./localoptions.h) to enable a `-v` option for dropbear and dbclient. That prints various details of the session. For development running `dropbear -F -E` is useful to run in the foreground. You can set `#define DEBUG_NOFORK 1` to make dropbear a one-shot server, easy to run under a debugger. +Set `#define DEBUG_TRACE 1` in [localoptions.h](./localoptions.h) to enable a `-v` option for dropbear and dbclient to print various details of the session. +For development running `dropbear -F -E` is useful to run in the foreground. +You can set `#define DEBUG_NOFORK 1` to make dropbear a one-shot server, easy to run under a debugger. #### Random sources -Most cryptography requires a good random entropy source, both to generate secret keys and in the course of a session. Dropbear uses the Linux kernel's `getrandom()` syscall to ensure that the system RNG has been initialised before using it. On some systems there is insufficient entropy gathered during early boot - generating hostkeys then will block for some amount of time. Dropbear has a `-R` option to generate hostkeys upon the first connection as required - that will allow the system more time to gather entropy. +Most cryptography requires a good random entropy source, both to generate secret keys and in the course of a session. +Dropbear uses the Linux kernel's `getrandom()` syscall to ensure that the system RNG has been initialised before using it. +On some systems there is insufficient entropy gathered during early boot - generating hostkeys then will block for some amount of time. +Dropbear has a `-R` option to generate hostkeys upon the first connection as required - that will allow the system more time to gather entropy. #### Algorithms @@ -39,24 +45,30 @@ Enabling/disabling algorithms is done in [localoptions.h](./localoptions.h), see #### Style -Source code is indented with tabs, width set to 4 (though width shouldn't matter much). Braces are on the same line as functions/loops/if - try to keep consistency with existing code. +Source code is indented with tabs, width set to 4 (though width shouldn't matter much). +Braces are on the same line as functions/loops/if - try to keep consistency with existing code. All `if` statements should have braces, no exceptions. Avoid using pointer arithmetic, instead the functions in [buffer.h](./src/buffer.h) should be used. -Some Dropbear platforms have old compilers. Variable declarations must be at the top of a scope and comments must be `/* */` rather than `//`. +Some Dropbear platforms have old compilers. +Variable declarations must be at the top of a scope and comments must be `/* */` rather than `//`. Pointer variables should be initialised to NULL - it can reduce the severity of bugs. #### Third party code -Libtomcrypt and libtommath are periodically synced from upstream, so avoid making changes to that code which will need to be maintained. Improvements can be sent upstream to the libtom project. +Libtomcrypt and libtommath are periodically synced from upstream, so avoid making changes to that code which will need to be maintained. +Improvements can be sent upstream to the libtom project. #### Non-root user -Dropbear server will run fine as a non-root user, allowing logins only for that user. Password authentication probably won't work (can't read shadow passwords). You will need to create hostkeys that are readable. +Dropbear server will run fine as a non-root user, allowing logins only for that user. +Password authentication probably won't work (can't read shadow passwords). You will need to create hostkeys that are readable. #### Connection setup -Dropbear implements `first_kex_packet_follows` to reduce handshake latency [RFC 4253 7.1](https://www.rfc-editor.org/rfc/rfc4253.html#section-7.1). Some less common implementations don't handle that - it can be a cause of problems connecting. Note also that Dropbear may send several ssh packets within a single TCP packet - it's just a stream. +Dropbear implements `first_kex_packet_follows` to reduce handshake latency [RFC 4253 7.1](https://www.rfc-editor.org/rfc/rfc4253.html#section-7.1). +Some less common implementations don't handle that - it can be a cause of problems connecting. +Note also that Dropbear may send several ssh packets within a single TCP packet - it's just a stream. diff --git a/FUZZER-NOTES.md b/FUZZER-NOTES.md index 078fbc5f..703fb24d 100644 --- a/FUZZER-NOTES.md +++ b/FUZZER-NOTES.md @@ -1,45 +1,55 @@ ## Fuzzing Dropbear -Dropbear is process-per-session so it assumes calling `dropbear_exit()` is fine at any point to clean up. This makes fuzzing a bit trickier. A few pieces of wrapping infrastructure are used to work around this. +Dropbear is process-per-session so it assumes calling `dropbear_exit()` is fine at any point to clean up. +This makes fuzzing a bit trickier. A few pieces of wrapping infrastructure are used to work around this. -The [libfuzzer](http://llvm.org/docs/LibFuzzer.html#fuzz-target) harness expects a long running process to continually run a test function with a string of crafted input. That process should not leak resources or exit. +The [libfuzzer](http://llvm.org/docs/LibFuzzer.html#fuzz-target) harness expects a long running process to continually run a test function with a string of crafted input. +That process should not leak resources or exit. #### longjmp -When dropbear runs in fuzz mode it sets up a [`setjmp()`](http://man7.org/linux/man-pages/man3/setjmp.3.html) target prior to launching the code to be fuzzed, and then [`dropbear_exit()`](./src/dbutil.c#L125) calls `longjmp()` back there. This avoids exiting though it doesn't free memory or other resources. +When dropbear runs in fuzz mode it sets up a [`setjmp()`](http://man7.org/linux/man-pages/man3/setjmp.3.html) target prior to launching the code to be fuzzed, and then [`dropbear_exit()`](./src/dbutil.c#L125) calls `longjmp()` back there. +This avoids exiting though it doesn't free memory or other resources. #### malloc Wrapper -Dropbear normally uses a [`m_malloc()`](./src/dbmalloc.c) function that is the same as `malloc()` but exits if allocation fails. In fuzzing mode this is replaced with a tracking allocator that stores all allocations in a linked list. After the `longjmp()` occurs the fuzzer target calls [`m_malloc_free_epoch(1, 1)`](./src/dbmalloc.c#L80) to clean up any unreleased memory. +Dropbear normally uses a [`m_malloc()`](./src/dbmalloc.c) function that is the same as `malloc()` but exits if allocation fails. +In fuzzing mode this is replaced with a tracking allocator that stores all allocations in a linked list. +After the `longjmp()` occurs the fuzzer target calls [`m_malloc_free_epoch(1, 1)`](./src/dbmalloc.c#L80) to clean up any unreleased memory. -If the fuzz target runs to completion it calls `m_malloc_free_epoch(1, 0)` which will reset the tracked allocations but will not free memory - that allows libfuzzer's leak checking to detect leaks in normal operation. +If the fuzz target runs to completion it calls `m_malloc_free_epoch(1, 0)` which will reset the tracked allocations but will not free memory. +That allows libfuzzer's leak checking to detect leaks in normal operation. #### File Descriptor Input -As a network process Dropbear reads and writes from a socket. The wrappers for `read()`/`write()`/`select()` in [fuzz-wrapfd.c](./fuzz/fuzz-wrapfd.c) will read from the fuzzer input that has been set up with `wrapfd_add()`. `write()` output is currently discarded. These also test error paths such as EINTR and short reads with certain probabilities. +As a network process Dropbear reads and writes from a socket. +The wrappers for `read()`/`write()`/`select()` in [fuzz-wrapfd.c](./fuzz/fuzz-wrapfd.c) will read from the fuzzer input that has been set up with `wrapfd_add()`. `write()` output is currently discarded. +These also test error paths such as EINTR and short reads with certain probabilities. -This allows running the entire dropbear server process with network input provided by the fuzzer, without many modifications to the main code. At the time of writing this only runs the pre-authentication stages, though post-authentication could be run similarly. +This allows running the entire dropbear server process with network input provided by the fuzzer, without many modifications to the main code. +At the time of writing this only runs the pre-authentication stages, though post-authentication could be run similarly. #### Encryption and Randomness When running in fuzzing mode Dropbear uses a [fixed seed](./src/dbrandom.c#L185) every time so that failures can be reproduced. -Since the fuzzer cannot generate valid encrypted input the packet decryption and message authentication calls are disabled, see [packet.c](./src/packet.c). MAC failures are set to occur with a low probability to test that error path. +Since the fuzzer cannot generate valid encrypted input the packet decryption and message authentication calls are disabled, see [packet.c](./src/packet.c). +MAC failures are set to occur with a low probability to test that error path. #### Fuzzers Current fuzzers are: -* [fuzzer-preauth](./fuzz/fuzzer-preauth.c) - the fuzzer input is treated as a stream of session input. This will test key exchange, packet ordering, authentication attempts etc. - -* [fuzzer-preauth_nomaths](./fuzz/fuzzer-preauth_nomaths.c) - the same as fuzzer-preauth but with asymmetric crypto routines replaced with dummies for faster runtime. corpora are shared between fuzzers by [oss-fuzz](https://github.com/google/oss-fuzz) so this will help fuzzer-preauth too. - -* [fuzzer-verify](./fuzz/fuzzer-verify.c) - read a key and signature from fuzzer input and verify that signature. It would not be expected to pass, though some keys with bad parameters are able to validate with a trivial signature - extra checks are added for that. - +* [fuzzer-preauth](./fuzz/fuzzer-preauth.c) - the fuzzer input is treated as a stream of session input. + This will test key exchange, packet ordering, authentication attempts etc. +* [fuzzer-preauth_nomaths](./fuzz/fuzzer-preauth_nomaths.c) - the same as fuzzer-preauth but with asymmetric crypto routines replaced with dummies for faster runtime. + corpora are shared between fuzzers by [oss-fuzz](https://github.com/google/oss-fuzz) so this will help fuzzer-preauth too. +* [fuzzer-verify](./fuzz/fuzzer-verify.c) - read a key and signature from fuzzer input and verify that signature. + It would not be expected to pass, though some keys with bad parameters are able to validate with a trivial signature - extra checks are added for that. * [fuzzer-pubkey](./fuzz/fuzzer-pubkey.c) - test parsing of an `authorized_keys` line. - -* [fuzzer-kexdh](./fuzz/fuzzer-kexdh.c) - test Diffie-Hellman key exchange where the fuzz input is the ephemeral public key that would be received over the network. This is testing `mp_expt_mod()` and and other libtommath routines. - -* [fuzzer-kexecdh](./fuzz/fuzzer-kexecdh.c) - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh. This is testing libtommath ECC routines. - -* [fuzzer-kexcurve25519](./fuzz/fuzzer-kexcurve25519.c) - test Curve25519 Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexecdh. This is testing `dropbear_curve25519_scalarmult()` and other libtommath routines. +* [fuzzer-kexdh](./fuzz/fuzzer-kexdh.c) - test Diffie-Hellman key exchange where the fuzz input is the ephemeral public key that would be received over the network. + This is testing `mp_expt_mod()` and and other libtommath routines. +* [fuzzer-kexecdh](./fuzz/fuzzer-kexecdh.c) - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh. + This is testing libtommath ECC routines. +* [fuzzer-kexcurve25519](./fuzz/fuzzer-kexcurve25519.c) - test Curve25519 Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexecdh. + This is testing `dropbear_curve25519_scalarmult()` and other libtommath routines. diff --git a/INSTALL.md b/INSTALL.md index 9dd65f9b..af1d5875 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,7 +1,9 @@ ## Basic Dropbear Build Instructions -Edit [localoptions.h](./localoptions.h) to set which features you want. Available options are described in default_options.h, these will be overridden by anything set in [localoptions.h](./localoptions.h) should be located in the build directory if you are building out of tree. -Note that the file is not tracked ([*.gitignore*](.gitignore)-d) and you may need to create it. +Edit [localoptions.h](./localoptions.h) to set which features you want. +Available options are described in default_options.h. +They will be overridden by anything set in [localoptions.h](./localoptions.h) should be located in the build directory if you are building out of tree. +Note that the file is not tracked ([.gitignore](.gitignore)-d) and you may need to create it. #### Configure for your system ``` @@ -36,7 +38,8 @@ To test the installation targeting a temporary forder set `DESTDIR`: make install DESTDIR=/same/temp/location ``` -You can leave items out of the `PROGRAMS` list to avoid compiling them. If you recompile after changing the `PROGRAMS` list, you **MUST** `make clean` before recompiling - bad things will happen otherwise. +You can leave items out of the `PROGRAMS` list to avoid compiling them. +If you recompile after changing the `PROGRAMS` list, you **MUST** `make clean` before recompiling - bad things will happen otherwise. [DEVELOPING.md](DEVELOPING.md) has some notes on other developer topics, including debugging. @@ -47,7 +50,8 @@ If you want to compile statically use ./configure --enable-static ``` -By default Dropbear adds various build flags that improve robustness against programming bugs (good for security). If these cause problems they can be disabled with `./configure --disable-harden`. +By default Dropbear adds various build flags that improve robustness against programming bugs (good for security). +If these cause problems they can be disabled with `./configure --disable-harden`. Binaries can be stripped with `make strip`. @@ -56,9 +60,13 @@ Binaries can be stripped with `make strip`. ## Compiling with uClibc -Firstly, make sure you have at least uclibc 0.9.17, as `getusershell()` in prior versions is broken. Also note that you may get strange issues if your uClibc headers don't match the library you are running with, ie the headers might say that shadow password support exists, but the libraries don't have it. +Firstly, make sure you have at least uclibc 0.9.17, as `getusershell()` in prior versions is broken. +Also note that you may get strange issues if your uClibc headers don't match the library you are running with. +I.e. the headers might say that shadow password support exists, but the libraries don't have it. -Compiling for uClibc should be the same as normal, just set CC to the magic uClibc toolchain compiler (ie `export CC=i386-uclibc-gcc` or whatever). You can use `make STATIC=1` to make statically linked binaries, and it is advisable to strip the binaries too. If you're looking to make a small binary, you should remove unneeded ciphers and algorithms, by editing [localoptions.h](./localoptions.h). +Compiling for uClibc should be the same as normal, just set CC to the magic uClibc toolchain compiler (ie `export CC=i386-uclibc-gcc` or whatever). +You can use `make STATIC=1` to make statically linked binaries, and it is advisable to strip the binaries too. +If you're looking to make a small binary, you should remove unneeded ciphers and algorithms, by editing [localoptions.h](./localoptions.h). It is possible to compile zlib in, by copying zlib.h and zconf.h into a subdirectory (ie zlibincludes), and @@ -68,15 +76,18 @@ export LDFLAGS=/usr/lib/libz.a ``` before `./configure` and `make`. -If you disable zlib, you must explicitly disable compression for the client - OpenSSH is possibly buggy in this regard, it seems you need to disable it globally in *~/.ssh/config*, not just in the host entry in that file. +If you disable zlib, you must explicitly disable compression for the client. +OpenSSH is possibly buggy in this regard, it seems you need to disable it globally in `~/.ssh/config`, not just in the host entry in that file. You may want to manually disable lastlog recording when using uClibc, configure with `--disable-lastlog`. -One common problem is pty allocation. There are a number of types of pty allocation which can be used -- if they work properly, the end result is the same for each type. Running configure should detect the best type to use automatically, however for some systems, this may be incorrect. Some -things to note: - -* If your system expects */dev/pts* to be mounted (this is a uClibc option), make sure that it is. +One common problem is pty allocation. +There are a number of types of pty allocation which can be used -- if they work properly, the end result is the same for each type. +Running configure should detect the best type to use automatically, however for some systems, this may be incorrect. +Some things to note: +* If your system expects `/dev/pts` to be mounted (this is a uClibc option), make sure that it is. * Make sure that your libc headers match the library version you are using. - -* If `openpty()` is being used (`HAVE_OPENPTY` defined in *config.h*) and it fails, you can try compiling with `--disable-openpty`. You will probably then need to create all the */dev/pty??* and */dev/tty??* devices, which can be problematic for devfs. In general, `openpty()` is the best way to allocate PTYs, so it's best to try and get it working. +* If `openpty()` is being used (`HAVE_OPENPTY` defined in `config.h`) and it fails, you can try compiling with `--disable-openpty`. + You will probably then need to create all the `/dev/pty??` and `/dev/tty??` devices, which can be problematic for `devfs`. + In general, `openpty()` is the best way to allocate PTYs, so it's best to try and get it working. diff --git a/MULTI.md b/MULTI.md index 01f9bc1b..0c2290d3 100644 --- a/MULTI.md +++ b/MULTI.md @@ -1,16 +1,18 @@ ## Multi-Binary Compilation -To compile for systems without much space (floppy distributions etc), you can create a single binary. This will save disk space by avoiding repeated code between the various parts. If you are familiar with "busybox", it's the same principle. +To compile for systems without much space (floppy distributions etc), you can create a single binary. +This will save disk space by avoiding repeated code between the various parts. +If you are familiar with BusyBox, it's the same principle. To compile the multi-binary, first `make clean` (if you've compiled previously), then -``` +```sh make PROGRAMS="programs you want here" MULTI=1 ``` To use the binary, symlink it from the desired executable: -``` +```sh ln -s dropbearmulti dropbear ln -s dropbearmulti dbclient ``` diff --git a/README.md b/README.md index 560b34f2..7d964270 100644 --- a/README.md +++ b/README.md @@ -22,24 +22,25 @@ matt@ucc.asn.au ---- #### Server public key auth -You can use *~/.ssh/authorized_keys* in the same way as with OpenSSH, just put the key entries in that file. They should be of the form: +You can use `~/.ssh/authorized_keys` in the same way as with OpenSSH, just put the key entries in that file. +They should be of the form: -``` -ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwVa6M6cGVmUcLl2cFzkxEoJd06Ub4bVDsYrWvXhvUV+ZAM9uGuewZBDoAqNKJxoIn0Hyd0NkyU99UVv6NWV/5YSHtnf35LKds56j7cuzoQpFIdjNwdxAN0PCET/MG8qyskG/2IE2DPNIaJ3Wy+Ws4IZEgdJgPlTYUBWWtCWOGc= someone@hostname -``` + ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwVa6M6cGVmUcLl2cFzkxEoJd06Ub4bVDsYrWvXhvUV+ZAM9uGuewZBDoAqNKJxoIn0Hyd0NkyU99UVv6NWV/5YSHtnf35LKds56j7cuzoQpFIdjNwdxAN0PCET/MG8qyskG/2IE2DPNIaJ3Wy+Ws4IZEgdJgPlTYUBWWtCWOGc= someone@hostname -You must make sure that *~/.ssh*, and the key file, are only writable by the user. Beware of editors that split the key into multiple lines. +You must make sure that `~/.ssh`, and the key file, are only writable by the user. +Beware of editors that split the key into multiple lines. Dropbear supports some options for authorized_keys entries, see the manpage. ---- #### Client public key auth -Dropbear can do public key auth as a client, but you will have to convert OpenSSH style keys to Dropbear format, or use dropbearkey to create them. +Dropbear can do public key auth as a client. +But you will have to convert OpenSSH style keys to Dropbear format, or use dropbearkey to create them. -If you have an OpenSSH-style private key *~/.ssh/id_rsa*, you need to do: +If you have an OpenSSH-style private key `~/.ssh/id_rsa`, you need to do: -``` +```sh dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_rsa.db dbclient -i ~/.ssh/id_rsa.db ``` @@ -48,11 +49,15 @@ Dropbear does not support encrypted hostkeys though can connect to ssh-agent. ---- If you want to get the public-key portion of a Dropbear private key, look at dropbearkey's `-y` option. +It will print both public key and fingerprint. If you need the pub key only you can grep by a prefix `ssh-`: +```sh +./dropbearkey -y -f ~/.ssh/id_ed25519 | grep "^ssh-" > ~/.ssh/id_ed25519.pub +``` ---- To run the server, you need to generate server keys, this is one-off: -``` +```sh ./dropbearkey -t rsa -f dropbear_rsa_host_key ./dropbearkey -t dss -f dropbear_dss_host_key ./dropbearkey -t ecdsa -f dropbear_ecdsa_host_key @@ -61,15 +66,19 @@ To run the server, you need to generate server keys, this is one-off: Or alternatively convert OpenSSH keys to Dropbear: -``` +```sh ./dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key dropbear_dss_host_key ``` -You can also get Dropbear to create keys when the first connection is made - this is preferable to generating keys when the system boots. Make sure */etc/dropbear/* exists and then pass `-R` to the dropbear server. +You can also get Dropbear to create keys when the first connection is made - this is preferable to generating keys when the system boots. +Make sure `/etc/dropbear/` exists and then pass `-R` to the dropbear server. ---- -If the server is run as non-root, you most likely won't be able to allocate a pty, and you cannot login as any user other than that running the daemon (obviously). Shadow passwords will also be unusable as non-root. +If the server is run as non-root, you most likely won't be able to allocate a pty, and you cannot login as any user other than that running the daemon (obviously). +Shadow passwords will also be unusable as non-root. ---- -The Dropbear distribution includes a standalone version of OpenSSH's `scp` program. You can compile it with `make scp`. You may want to change the path of the ssh binary, specified by `_PATH_SSH_PROGRAM` in *options.h*. By default -the progress meter isn't compiled in to save space, you can enable it by adding `SCPPROGRESS=1` to the `make` commandline. +The Dropbear distribution includes a standalone version of OpenSSH's `scp` program. +You can compile it with `make scp`. +You may want to change the path of the ssh binary, specified by `_PATH_SSH_PROGRAM` in `options.h`. +By default the progress meter isn't compiled in to save space, you can enable it by adding `SCPPROGRESS=1` to the `make` commandline. diff --git a/SMALL.md b/SMALL.md index 3fba838f..7fa7b9c7 100644 --- a/SMALL.md +++ b/SMALL.md @@ -12,17 +12,19 @@ rather than just make dropbear ``` -so that client functionality in shared portions of Dropbear won't be included. The same applies for `PROGRAMS=dbclient`. +so that client functionality in shared portions of Dropbear won't be included. +The same applies for `PROGRAMS=dbclient`. --- -The following are set in *localoptions.h*. See *default_options.h* for possibilities. +The following are set in `localoptions.h`. See `default_options.h` for possibilities. -* You can disable either password or public-key authentication. +You can disable either password or public-key authentication. -* Various algorithms can be disabled if they are not required by any connecting SSH clients/servers. Disabling many is fine for a local install, though +Various algorithms can be disabled if they are not required by any connecting SSH clients/servers. +Disabling many is fine for a local install, though builds for public consumption require more consideration. -* You can disable x11, tcp and agent forwarding as desired. None of these are essential (depending on use cases) +You can disable x11, tcp and agent forwarding as desired. None of these are essential (depending on use cases). --- If you are compiling statically, you may want to disable zlib, as it will use a few tens of kB of binary size @@ -32,7 +34,8 @@ If you are compiling statically, you may want to disable zlib, as it will use a You can create a combined binary, see the file [MULTI.md](MULTI.md), which will put all the functions into one binary, avoiding repeated code. -If you're compiling with gcc, you might want to look at gcc's options for stripping unused code. The relevant vars to set before configure are: +If you're compiling with gcc, you might want to look at gcc's options for stripping unused code. +The relevant vars to set before configure are: ``` LDFLAGS=-Wl,--gc-sections