Skip to content

Commit

Permalink
Reformat Markdown files
Browse files Browse the repository at this point in the history
Split long sentences.
Use a line per a sentence.
Use a backquote instead of * e.g. `~/.ssh/id_rsa` instead of *~/.ssh/id_rsa*.
Add more details about ./dropbearkey -y
  • Loading branch information
stokito authored and mkj committed Dec 17, 2023
1 parent c269c83 commit f5883e3
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 66 deletions.
32 changes: 22 additions & 10 deletions DEVELOPING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 \<target\>: \<generator\>(\<source\>)
Following are generated files in the format `<target>: <generator>(<source>)`
```
- configure: autoconf(configure.ac)
- config.h.in: autoheader(configure.ac)
Expand All @@ -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

Expand All @@ -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.
50 changes: 30 additions & 20 deletions FUZZER-NOTES.md
Original file line number Diff line number Diff line change
@@ -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.
37 changes: 24 additions & 13 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -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
```
Expand Down Expand Up @@ -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.

Expand All @@ -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`.

Expand All @@ -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

Expand All @@ -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.
8 changes: 5 additions & 3 deletions MULTI.md
Original file line number Diff line number Diff line change
@@ -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
```
Expand Down
Loading

0 comments on commit f5883e3

Please sign in to comment.