Compare commits

...

309 Commits

Author SHA1 Message Date
clearrml
09bc32d7f8 improve build.sh 2024-12-26 00:26:02 +02:00
clearrml
07f1f1d5f9 sync_git_2024.86 tag/DROPBEAR_2024.86 2024-12-22 17:07:35 +02:00
clearrml
af3488e293 Merge branch 'sync_git_2024.85' 2024-12-22 17:02:08 +02:00
allegroai
9452f11bf9 Add build.sh to build dropbearmulti inside a docker 2024-07-24 03:54:33 +03:00
allegroai
ed8f0da039 Add SFTPSERVER_PATH to override the default location of /usr/libexec/sftp-server 2024-07-24 03:53:55 +03:00
allegroai
d8900abd95 Add DROPBEAR_CLEARML_FIXED_PASSWORD environment variable to allow simple pass auth for non-root user inside containers 2024-07-24 03:52:52 +03:00
allegroai
b63e8d8694 sync github July 2024 2024-07-24 03:31:27 +03:00
allegroai
35427a2d0b Add DROPBEAR_CLEARML_FIXED_PASSWORD environement variable to allow simple pass auth for non-root user inside containers 2023-02-09 00:10:16 +02:00
allegroai
78576360f6 Switch to Alpine:3.17.1 base docker for build. Build single multi file 2023-02-09 00:03:39 +02:00
allegroai
31e3a973c1 Add build static release inside container 2023-02-08 16:58:34 +02:00
Matt Johnston
9defeb477a Fix CI for dbclient/dropbear only 2023-01-04 20:36:58 +08:00
Matt Johnston
7a53c7f0f4 Fix building only client or server
Regressed when -Wundef was added

Fixes #210
2023-01-04 20:32:23 +08:00
Matt Johnston
febb805742 Add test building only dropbear or dbclient
Expected to fail, fix pending
2023-01-04 20:31:40 +08:00
Matt Johnston
923a65ea0d Merge remote-tracking branch 'refs/remotes/origin/master' 2023-01-03 22:07:07 +08:00
Matt Johnston
39d955c49f Add missing break in switch
Has no effect on execution, the fallthrough does nothing
Closes #208
2023-01-03 22:05:14 +08:00
Matt Johnston
f7b1ba6aad Merge pull request #206 from fperrad/20221222_lint
some linting
2022-12-22 22:56:34 +08:00
Francois Perrad
01415ef826 const parameter mp_int 2022-12-22 10:19:54 +01:00
Matt Johnston
6fa49f98c5 Merge pull request #201 from mkj/test-pty-gid
Allow users's own gid in pty permission check
2022-12-12 22:34:06 +08:00
Matt Johnston
8607215588 Allow users's own gid in pty permission check
This allows non-root Dropbear to work even without devpts gid=5 mount
option on Linux.
2022-12-07 13:04:10 +08:00
Matt Johnston
c043efb47c Fix so DROPBEAR_DSS is only forced for fuzzing
Regression from 787391ea3b,
was missing fuzzing conditional
2022-12-06 22:34:11 +08:00
Matt Johnston
ec2215726c Fix y2038 issues with time_t conversion
These changes were identified by building with and without
-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64
on 32-bit arm, logging warnings to files.
-Wconversion was added to CFLAGS in both builds.

Then a "diff -I Wconversion log1 log2" shows new warnings that appear
with the 64-bit time_t. There are a few false positives that have been
fixed for quietness.

struct logininfo and struct wtmp are still problematic, those will
need to be handled by libc.
2022-12-01 13:40:13 +08:00
Matt Johnston
bd94cb712c Another attempt to make CI work 2022-11-28 21:40:09 +08:00
Matt Johnston
cf7f9350b8 CI: don't run dropbearkey for disabled types 2022-11-28 21:32:10 +08:00
Matt Johnston
5a07edfa2b Actually disable werror, and more --disable flags 2022-11-28 21:29:36 +08:00
Matt Johnston
a7659fb581 No werror for options disabled CI 2022-11-28 21:24:53 +08:00
Matt Johnston
1034024029 Add CI for disabled options 2022-11-28 21:20:44 +08:00
Matt Johnston
36a0313263 Add #if DROPBEAR_RSA guards
Fixes building with DROPBEAR_RSA disabled.
Closes #197
2022-11-28 21:12:23 +08:00
Matt Johnston
a4689e25ec Update config.guess and config.sub
Updated to 2022-09-17 with
wget -O config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
wget -O config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'
2022-11-14 11:15:12 +08:00
Matt Johnston
e360dffff2 Fix typo for LTM_CFLAGS 2022-11-14 10:55:44 +08:00
Matt Johnston
5a3bc9fa9c Update version to 2022.83, finish CHANGES 2022-11-14 10:37:15 +08:00
Matt Johnston
aa6559db66 Add a single DROPBEAR_SK_KEYS config option
Replaces DROPBEAR_SK_ECDSA and DROPBEAR_SK_ED25519
2022-11-11 16:23:07 +08:00
Matt Johnston
b2b94acc97 Better docs for DisableTrivialAuth 2022-11-11 11:25:50 +08:00
Matt Johnston
960d374e65 Fix test for !DROPBEAR_DSS
Fixes: 0e70732 ("Use faster primality testing in libtomcrypt")
2022-11-10 18:54:16 +08:00
Matt Johnston
fd234018a4 Add draft CHANGES 2022-11-10 18:39:08 +08:00
Matt Johnston
54a90ddac5 Add LTM_CFLAGS configure argument 2022-11-10 17:39:27 +08:00
Matt Johnston
cda8070898 Remove hmac-md5 entirely 2022-11-10 17:10:16 +08:00
Matt Johnston
b5e941c0b1 Revert "Add CI build with more options enabled"
This reverts commit e85f329e5c.

I'd forgotten there's already the automatic "nondefault options"
2022-11-10 16:59:11 +08:00
Matt Johnston
e87a222ce7 Avoid hitting dropbear_lint.sh 2022-11-10 16:57:28 +08:00
Matt Johnston
e85f329e5c Add CI build with more options enabled 2022-11-10 16:54:12 +08:00
Matt Johnston
1d22801101 Fix accientally removed variable for DSS 2022-11-10 16:52:42 +08:00
Matt Johnston
787391ea3b Force DROPBEAR_DSS when fuzzing 2022-11-10 14:49:26 +08:00
Matt Johnston
c9a16e661a Enable DSS in CI so the tests still work 2022-11-10 14:44:54 +08:00
Matt Johnston
b966cce3ae Fix warnings when DROPBEAR_DSS is disabled 2022-11-10 14:37:44 +08:00
Matt Johnston
e5e6b6c1b8 Add DROPBEAR_RSA_SHA1 as a visible config option 2022-11-10 14:29:08 +08:00
Matt Johnston
c29c4e1024 Disable DSS by default 2022-11-10 14:28:43 +08:00
Matt Johnston
1cdd95f997 Fix dropbearkey to disallow 512 bit keys
The key loading code rejected <1024 bit keys already
2022-11-10 13:20:09 +08:00
Matt Johnston
86ac8411a0 Add manpage entry for -z, change help text
Fixes #193 on github (with previous patch)
2022-11-10 12:26:25 +08:00
Petr Štetiar
2864c3d154 Make IP Type-Of-Service feature optional
Add new -z commandline option which when set, disables new IP TOS
feature.

References: https://github.com/openwrt/openwrt/issues/10405
Signed-off-by: Petr Štetiar <ynezz@true.cz>
2022-11-10 11:58:43 +08:00
Matt Johnston
0e70732e1e Use faster primality testing in libtomcrypt
This can only be used if DSS is disabled
2022-11-10 11:52:55 +08:00
Matt Johnston
cdaf52aead Update github builders to ubuntu 22.04 default 2022-11-10 11:16:19 +08:00
Matt Johnston
cdc83ad98a Update github action to macos-12
10.15 is being removed on github soon
2022-11-10 11:13:00 +08:00
Matt Johnston
80fa169cb9 Move ./configure CFLAGS to the end of the list
This allows overriding configure-script provided arguments
such as -Wundef with the user provided CFLAGS
2022-11-10 11:08:26 +08:00
Matt Johnston
50a07a4889 Just disable -Wundef for macos runners instead
The previous change to set TARGET_OS_EMBEDDED=0 didn't work
for libtommath which doesn't include Dropbear headers
2022-11-10 10:53:59 +08:00
Matt Johnston
dacc10a8cf Work around macos broken TARGET_OS_EMBEDDED
Their headers test TARGET_OS_EMBEDDED without
testing if it's defined which breaks Wundef.

Might be fixed in more recent macos, but it broke the github action.
2022-11-10 10:45:32 +08:00
Matt Johnston
0058cc69c8 Update autoconf workflow to Ubuntu 22.04
This should let it succeed with autoconf 2.71
2022-11-10 10:29:03 +08:00
Matt Johnston
963b9eafaa Add -Wundef and fix missing definitions 2022-11-10 10:19:12 +08:00
Matt Johnston
7c9bd09af6 Fix typo in DROPEAR_DSS
Fixes #195 issue in github
2022-11-10 10:18:19 +08:00
Matt Johnston
72b28448a1 Fix missing end quote in comment example 2022-11-10 10:07:41 +08:00
Matt Johnston
dc3c1a30cf Allow overriding shells for compat getusershell() 2022-11-09 18:40:10 +08:00
Matt Johnston
71d78653c7 Merge pull request #160 from Jackkal/two-factor-authentication
Two-factor authentication support (pubkey and password)
2022-11-09 17:33:48 +08:00
Matt Johnston
9f55ff216b Add check for -t -s clash
multiauthmethod with noauthpass isn't allowed
2022-11-09 17:33:04 +08:00
Matt Johnston
b4c30b5e7e Ignore all-zero ed25519 keys in fuzzer-verify 2022-11-09 17:00:18 +08:00
Matt Johnston
561ef41230 Merge egor-duda:sk-authkey-options
Github pull request #172
2022-11-09 16:14:59 +08:00
Matt Johnston
ab6ea4d697 Fix plugin argument
This broke in the re-exec changes, it was altering the argv
argument in-place, but argv was re-used later.

Fixes #194 github issue
2022-11-09 13:14:22 +08:00
Matt Johnston
9d320a73be Merge remote-tracking branch 'refs/remotes/origin/master' 2022-10-31 09:51:00 +08:00
Matt Johnston
f19a0494d7 Merge pull request #190 from mgiacomoli/fix-dbclient-keyboard-interactive-login
Dbclient: keyboard_interactive login method never used
2022-10-27 15:52:02 +08:00
Matt Johnston
ab70167534 Merge pull request #189 from mgiacomoli/utx-typo
Fix utx var typo
2022-10-25 23:48:49 +08:00
Matt Johnston
d1fed8b451 Merge pull request #191 from mgiacomoli/ask-fingerprint-flush-stdin
Dbclient: Flush stdin after fingerprint confirmation
2022-10-25 23:47:45 +08:00
Matt Johnston
5284a3da56 Merge pull request #182 from tuoha/permitopen_authorized_keys
Added permitopen option to authorized_keys
2022-10-25 23:42:41 +08:00
Matt Johnston
f7d306e963 Fix decompression size check
Dropbear's decompression could erroneously exit with
"bad packet, oversized decompressed"
for a valid 32768 byte decompressed payload (an off-by-one error).
It could be triggered particularly with larger SSH window sizes.

This change also simplifies the function by allocating a
single 32kB buffer rather than incrementally increasing the size.
2022-10-25 21:17:56 +08:00
Matt Johnston
86efbae708 Add flags so libtommath builds with -O3
This was the default prior to 2022.82 and makes a significant
difference to performance. Perhaps at a later time
this could be made more configurable.

Discussion in https://github.com/mkj/dropbear/issues/174
2022-10-25 21:12:08 +08:00
Matt Johnston
64e270b6f2 dropbear_lint.sh: Use grep -- 2022-10-24 11:28:47 +08:00
Michele Giacomoli
b36707ba46 Fix comment style 2022-09-19 18:25:26 +02:00
Michele Giacomoli
acf50a4f98 Flush stdin after fingerprint confirmation 2022-09-19 18:09:38 +02:00
Michele Giacomoli
b734e5a423 Resort cli auth method tries 2022-09-19 17:45:55 +02:00
Michele Giacomoli
4c67d03656 Fix utx var typo 2022-09-19 16:50:43 +02:00
Matt Johnston
17e02fe614 Link to dropbear.nl in README 2022-08-04 21:39:28 +08:00
Matt Johnston
e520d035e7 Merge pull request #184 from wulei-student/patch-1
Update dropbear.init
2022-07-22 15:19:51 +08:00
lwu
d48a2ba8b7 Update dropbear.init
need \ ,at the end of the line.
2022-07-22 15:14:27 +08:00
Matt Johnston
7de29c2686 Re-add missing setsid(), missed #ifdef conversion
Fixes: 2a81289 ("Make DEBUG_NOFORK a #if not #ifdef")
Fixes #180 github issue
2022-07-18 15:01:51 +08:00
Tuomas Haikarainen
1e4d64d300 Added permitopen option to authorized_keys
It is now possible to limit local port forwarding to specified
destination(s) by using the permitopen option in authorized_keys.

Resolves #181
2022-07-12 10:35:00 +03:00
Matt Johnston
a7e3b06b04 Remove unused MAX_IP_LEN 2022-06-27 14:36:04 +08:00
Jackkal
427e49003a make comments consistent and fix typo 2022-06-21 22:48:56 +02:00
Matt Johnston
808bc392a0 Merge pull request #175 from k-kurematsu/fix_errmsg
Fix misleading error message
2022-06-21 17:18:06 +08:00
k-kurematsu
e03abf0d1a Fix misleading error message
As per the message, even if I deleted the write permission(chmod -007), but an error occurred.
It's a source of confusion, so fix the message.
2022-06-21 17:58:12 +09:00
Egor Duda
62ea53c1e5 Implement no-touch-required and verify-requred for authorized_keys file 2022-06-11 19:17:40 +03:00
Matt Johnston
544f28a051 Fix MAX_UNAUTH_CLIENTS regression
Since re-exec change in 2022.82 Dropbear count
treat authenticated sessions towards the unauthenticated
session limit. This is fixed by passing the childpipe FD
through to the re-execed process.
2022-06-08 21:26:20 +08:00
Matt Johnston
f2318d831b Merge github #169
Fix compilation when disabling pubkey authentication (DROPBEAR_SVR_PUBKEY_AUTH)
2022-05-31 09:48:17 +08:00
MaxMougg
1622c80be4 Fix indentations 2022-05-30 11:28:17 -04:00
MaxMougg
c77d02bb11 Update svr-chansession for build issue
Following issue "Compilation error when disabling pubkey authentication (DROPBEAR_SVR_PUBKEY_AUTH)" from davidbernard04, code is modified to take in account that requesting information from method "ses.authstate.pubkey_info" isn't possible since the method is disabled when DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT value is 0.
2022-05-30 11:01:16 -04:00
Matt Johnston
50c6e8d3c3 Remove codeql 2022-05-24 09:49:10 +08:00
Matt Johnston
258f6127b4 Remove flawfinder.
It's too noisy, lacks context
2022-05-24 09:36:44 +08:00
Matt Johnston
b81c81c047 Add flawfinder action 2022-05-23 16:32:11 +08:00
Matt Johnston
3c3e4f6e6b Create codeql-analysis.yml
Experiment whether codeql works
2022-05-23 16:31:13 +08:00
Jackkal
d8d1db2cf8 Two-factor auth - Fix missing include 2022-04-29 16:54:01 +02:00
Jackkal
0c9318a0b2 Two-factor authentication support (pubkey and password) 2022-04-29 15:43:15 +02:00
Matt Johnston
46654cda85 Increase build.yml DEFAULT_IDLE_TIMEOUT 2022-04-28 10:43:56 +08:00
Matt Johnston
72d8cae7a4 Test linking for hardening options
Some options depend on correct library support.
2022-04-26 22:04:38 +08:00
Matt Johnston
2e0a16c334 Avoid UNAUTH_CLOSE_DELAY when testing
Seeing if this fixes test failures
2022-04-26 17:12:15 +08:00
Matt Johnston
c4a0304b3f Add a test for off-by-default compile options
This would have caught broken x11 (gh #156)
2022-04-23 22:54:39 +08:00
Matt Johnston
46106f71ab Fix build warning with DEBUG_TRACE
TRACE() code only gets used above DROPBEAR_VERBOSE_LEVEL
2022-04-23 22:44:23 +08:00
Matt Johnston
0292aacdf0 Fix X11 build failure, use DROPBEAR_PRIO_LOWDELAY 2022-04-23 22:33:31 +08:00
Matt Johnston
b8669b063b Bump version to 2022.82 2022-04-01 14:43:27 +08:00
Matt Johnston
c6e2d50310 Fix -q to hide the banner
Got lost merging the DEBUG/TRACE level patch
2022-04-01 14:33:27 +08:00
Matt Johnston
dd305c1533 Fix IPv6 address parsing for dbclient -b
Now can correctly handle '-b [ipv6address]:port'

Code is shared with dropbear -p, though they handle colon-less arguments
differently
2022-04-01 14:13:52 +08:00
Matt Johnston
7894254afa Allow dbclient -J to be used with multihop
Based on a patch from Hans Harder.

This also tidies formatting and un-needed parts
2022-04-01 12:17:02 +08:00
Matt Johnston
ac2433cb8d Add m_snprintf() that won't return negative 2022-04-01 12:10:48 +08:00
Matt Johnston
552385280a Fix extra default -i arguments for multihop
When multihop executes dbclient it should only add -i arguments
from the original commandline, not the default id_dropbear key.
Otherwise multiple -i arguments keep getting added which
results in servers disconnecting with too many auth attempts
2022-04-01 11:56:10 +08:00
Matt Johnston
c93103746e dbclient print remote fingerprint with -v 2022-04-01 11:21:34 +08:00
Matt Johnston
abb577fcba Write CHANGES since last release 2022-03-30 23:18:00 +08:00
Raphael Hertzog
0e042476a0 Add /usr/sbin and /sbin to default root PATH
When dropbear is used in a very restricted environment (such as in a
initrd), the default user shell is often also very restricted
and doesn't take care of setting the PATH so the user ends up
with the PATH set by dropbear. Unfortunately, dropbear always
sets "/usr/bin:/bin" as default PATH even for the root user
which should have /usr/sbin and /sbin too.

For a concrete instance of this problem, see the "Remote Unlocking"
section in this tutorial: https://paxswill.com/blog/2013/11/04/encrypted-raspberry-pi/

It speaks of a bug in the initramfs script because it's written "blkid"
instead of "/sbin/blkid"... this is just because the scripts from the
initramfs do not expect to have a PATH without the sbin directories and
because dropbear is not setting the PATH appropriately for the root user.

I'm thus suggesting to use the attached patch to fix this misbehaviour (I
did not test it, but it's easy enough). It might seem anecdotic but
multiple Kali users have been bitten by this.

From https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=903403
2022-03-30 23:13:34 +08:00
Matt Johnston
0fc4e35c94 Update to latest config.guess and config.sub 2022-03-30 21:42:23 +08:00
Matt Johnston
9007a80616 Handle ecdsa-sk flags, reject no-touch
For the time being Dropbear will only allow SK auth with default
parameters, user-presence needs to be set.
In future handling of authorized_keys option "no-touch-required" can be
added.
This code would also be refactored to share between ecdsa and ed25519
once I get hardware/emulation to test ed25519.
2022-03-30 21:06:15 +08:00
Matt Johnston
ecc85f91e6 Fix declaration after statement
Caught by just-added c89 build
2022-03-30 14:32:49 +08:00
Matt Johnston
82bff01242 Add c89 build test 2022-03-30 14:29:18 +08:00
Matt Johnston
02a8c6cadd Fix C99 comment 2022-03-30 14:28:59 +08:00
Matt Johnston
85f56f438a Fix tilde expansion of paths
(Part was missed from previous series of commits)
2022-03-30 14:08:15 +08:00
Begley Brothers Inc
0de8d44297 Expand home path for MOTD file
Patch modified by Matt Johnston

Signed-off-by: Begley Brothers Inc <begleybrothers@gmail.com>
2022-03-30 13:52:09 +08:00
Begley Brothers Inc
8b202f86e2 Default options comments, ignore localoptions.h
Also trim whitespaces.

Signed-off-by: Begley Brothers Inc <begleybrothers@gmail.com>
2022-03-30 13:52:04 +08:00
Begley Brothers Inc
f4be5a3c8b Allow user space file locations (rootless support)
Why:
Running dropbear as a user (rootless) is aided if
files and programs can be saved/removed without
needing sudo.

What:
Use the same convention as DROPBEAR_DEFAULT_CLI_AUTHKEY;
if not starting with '/', then is relative to hedge's /home/hedge:
*_PRIV_FILENAME
DROPBEAR_PIDFILE
SFTPSERVER_PATH

default_options.h commentary added.

Changes kept to a minimum, so log entry in svr_kex.c#163
is refactored.
From:
    Generated hostkey is <path> ... <finger-print>
to:
    Generated hostkey path is <path>
    Generated hostkey fingerprint is <fp>
Otherwise the unexpanded path was reported.

Patch modified by Matt Johnston

Signed-off-by: Begley Brothers Inc <begleybrothers@gmail.com>
2022-03-30 13:51:57 +08:00
Matt Johnston
2f68f6693f Check authorized_keys permissions as the user
This is necessary on NFS with squash root.
Based on work from Chris Dragan
This commit also tidies some trailing whitespace.

Fixes github pull #107
2022-03-30 12:56:09 +08:00
Matt Johnston
6f793d42d0 Disable dh-group1 KEX by default
Add comments for SK keys
2022-03-30 12:51:32 +08:00
Matt Johnston
04a4548ba2 Document supported formats for dropbearconvert 2022-03-30 12:03:50 +08:00
Matt Johnston
6ad6210901 Print the key type in "Pubkey auth succeeded" 2022-03-30 11:51:56 +08:00
Matt Johnston
8b68eb55d9 Make SHA1 optional, implement SHA256 fingerprints
SHA256 is always compiled and only enable SHA1 when needed. Fingerprints
are always SHA256: base64 format, md5 and sha1 are removed. dbrandom now
uses sha256 its hash function.
2022-03-30 11:44:04 +08:00
Matt Johnston
6dc029f2cb Remove twofish and remnants of blowfish
Twofish CTR was never enabled by default and CBC modes are
deprecated
2022-03-30 10:23:39 +08:00
Matt Johnston
9d36e94deb Remove commented ssh.com code from keyimport 2022-03-30 10:10:15 +08:00
Matt Johnston
6ac92cf606 Fix dropbearconvert ecdsa parsing error typo
Simplify handling for different key types
2022-03-29 23:55:35 +08:00
Matt Johnston
cb9a00951f Use buf_burn_free() instead of two calls 2022-03-29 23:47:30 +08:00
Matt Johnston
81e3977360 Add ecdsa OpenSSH format for dropbearconvert 2022-03-29 23:27:55 +08:00
Matt Johnston
bcbae1f4ba Fix dropbearconvert for dropbearmulti test 2022-03-29 22:36:30 +08:00
Matt Johnston
ee3828b3f8 Add tests for dropbearconvert 2022-03-29 22:29:17 +08:00
Matt Johnston
81425365de Support RSA OpenSSH new format in dropbearconvert
Added support for reading and writing. PEM writing support
has been removed.

OpenSSH file format routines have been moved to signkey_ossh.c
2022-03-29 22:27:55 +08:00
Matt Johnston
3189d12c9f Fix ed25519 dropbear to openssh conversion
This introduces buf_put_ed25519_priv_ossh and buf_get_ed25519_priv_ossh
to handle OpenSSH internal private key format. Previously writing
OpenSSH format keys didn't write the private part correctly.
2022-03-29 16:46:06 +08:00
Matt Johnston
a70b9e34c8 Fix act matrix workaround which broke real actions 2022-03-24 16:50:42 +08:00
Matt Johnston
ce745e98c0 Add build test with DEBUG_TRACE 5 2022-03-24 16:47:20 +08:00
Matt Johnston
d142639e38 Add -v variable debug levels for server too
-vvvv is equivalent to the old -v
2022-03-24 14:44:13 +08:00
Matt Johnston
bceba1f2ed Only set soft core limit not hard limit
Otherwise child shells can't enable coredumps if desired.

Fixes #145 on github
2022-03-24 14:18:45 +08:00
Matt Johnston
3521b58690 Revert "Don't include sk keys at all in KEX list"
This reverts git commit f972813ecd.
The sk algorithms need to remain in the sigalgs list so that they
are included in the server-sig-algs ext-info message sent by
the server. RFC8308 for server-sig-algs requires that all algorithms are
listed (though OpenSSH client 8.4p1 tested doesn't require that)
2022-03-24 13:42:08 +08:00
Matt Johnston
635ae3d500 Fix tarball retention-days 2022-03-24 12:26:09 +08:00
Matt Johnston
02eb74fbec Add release.sh --testrel, github action
This makes github actions create a tarball sha256sum for comparison.
The release.sh script now works in a git repository too.
2022-03-24 12:22:07 +08:00
Matt Johnston
515db2d706 Merge pull request #152 from HansH111/tracelevel2 2022-03-23 21:55:33 +08:00
Matt Johnston
9411bc21a8 Fix building with DEBUG_TRACE = 0
Also try a less repetitive way of specifying macros
2022-03-22 23:29:38 +08:00
Matt Johnston
0d4ab4fc09 Use signature type not key type for debug message 2022-03-22 23:28:24 +08:00
Matt Johnston
be4f9ce8e7 merge 2022-03-22 16:17:47 +08:00
Matt Johnston
f030618543 Split CPPFLAGS and CFLAGS more carefully
This has no change to the build, but makes it easier to try
other build tools that only want CPPFLAGS
2022-03-22 16:17:05 +08:00
HansH111
193d967123 changed TRACE to DEBUG3 for dbclient 2022-03-19 09:04:18 +00:00
HansH111
94b693b43c changed TRACE to DEBUG2 for dbclient 2022-03-19 09:03:51 +00:00
HansH111
1f169dafa8 changed TRACE to DEBUG1 for dbclient 2022-03-19 09:02:55 +00:00
HansH111
9ea30b8932 Added DEBUG1,DEBUG2,DEBUG3 to separate functions while keeping TRACE and TRACE2. 2022-03-19 09:01:05 +00:00
HansH111
098263950f increase verboseness by allowing multiple -v 2022-03-19 08:55:31 +00:00
HansH111
d597b66571 Allow for DEBUG_TRACE value 0 - 5 2022-03-19 08:54:25 +00:00
Matt Johnston
98ef42a856 Don't set pubkey_info directly in checkpubkey_line
This makes it safe to use from fuzzer-pubkey without leaking
the value since the cleanup isn't called
2022-03-16 18:35:23 +08:00
Matt Johnston
678cc6fcc0 Fix pytest incorrect skip "reason" string
No change to functionality
2022-03-16 17:32:43 +08:00
Matt Johnston
b58f96526a Disable aslr pytest for fsanitize test platforms 2022-03-16 17:25:03 +08:00
Matt Johnston
10875e8524 Fix SSH_PUBKEYINFO, limit characters, add tests
We fix a bad_bufptr() failure from a previous commit. We now limit
the allowed characters to those that will definitely be safe
in a shell. Some scripts/programs may use arbitrary environment
variables without escaping correctly - that could be a problem
in a restricted environment.

The current allowed set is a-z A-Z 0-9 .,_-+@

This also adds a test for SSH_PUBKEYINFO, by default it only runs
under github actions (or "act -j build").
2022-03-16 17:23:58 +08:00
Matt Johnston
355b248318 Merge pull request #151 from HansH111/pubkeyinfo 2022-03-16 10:43:24 +08:00
HansH111
212583544a use buf_getptr and m_free on every iteration before m_malloc to insure no memory leaks are happening 2022-03-15 18:57:21 +00:00
Matt Johnston
ae8a0abc34 test: Set allow_reuse_addr
This avoids intermittent "Address already in use" failure
2022-03-15 15:38:46 +08:00
HansH111
488ffce133 only show banner when cli_opts.quiet is not set 2022-03-14 09:50:07 +08:00
HansH111
360d60fb34 use option -q for suppression remote banner output, pass option also for proxy command 2022-03-14 09:50:07 +08:00
HansH111
fa4a1ab435 added quiet variable in cli_opts 2022-03-14 09:50:07 +08:00
HansH111
35631a21a2 set envvar SSH_PUBKEYINFO if authstate.pubkey_info contains information 2022-03-13 17:38:38 +00:00
HansH111
80e7143fd2 extract pubkey_info when seuccesfully auth with a key and free it in the cleanup function 2022-03-13 17:38:13 +00:00
HansH111
19cfb22d30 add pubkey_info field to authstate structure 2022-03-13 17:37:44 +00:00
Matt Johnston
8d11116dcb Make missing homedir non-fatal, instead use /
Fixes github #146
2022-02-24 11:51:51 +08:00
Matt Johnston
26feb8f13e Handle /proc/.../maps being reordered
We now search for the first r-xp line in the file
2022-02-03 22:13:06 +08:00
Matt Johnston
9124997602 Avoid unused argument warning when reexec is unused 2022-02-03 22:12:11 +08:00
Matt Johnston
12b094f0bf Fix regression in non-symlink dropbearmulti
Introduced in recent commit for re-exec
2022-02-01 23:15:53 +08:00
Matt Johnston
5334d58a15 Fix accidentally commented out test matrix items 2022-02-01 22:25:51 +08:00
Matt Johnston
3939321750 Make re-exec work with "dropbearmulti dropbear"
The re-exec needs to know to use the dropbearmulti binary instead.
Add a test for this case.
2022-02-01 22:19:49 +08:00
Matt Johnston
a95ca34a10 Fix incorrect algolist TRACE print 2022-02-01 22:12:25 +08:00
Matt Johnston
4c2d2fc3ac merge 2022-02-01 15:51:01 +08:00
Matt Johnston
e93b03cb00 Fix missing NULL terminator for re-exec
Also fixes fallback, sockets were not kept open
2022-01-31 11:12:58 +08:00
Matt Johnston
2b0238706a Add test for up-to-date configure script 2022-01-30 14:15:37 +08:00
Matt Johnston
3fb2406717 Fix testing with dropbearmulti 2022-01-30 13:46:52 +08:00
Matt Johnston
d367503fb0 Remove extraneous print 2022-01-30 13:46:20 +08:00
Matt Johnston
2a6dac19b5 Use venv for test_aslr
Otherwise we can't find the psutil dependency
2022-01-30 13:37:20 +08:00
Matt Johnston
da7f77a50d Fix -Wexpansion-to-defined failure on clang
(failure introduced in previous re-exec commit)
2022-01-30 10:23:06 +08:00
Matt Johnston
c7b7c9a99d Add re-exec for server
This allows ASLR to re-randomize the address
space for every connection, preventing some
vulnerabilities from being exploitable by
repeated probing.

Overhead (memory and time) is yet to be confirmed.

At present this is only enabled on Linux. Other BSD platforms
with fexecve() would probably also work though have not been tested.
2022-01-30 10:14:56 +08:00
Matt Johnston
ebb4018889 Merge netio changes 2022-01-27 15:09:29 +08:00
Matt Johnston
1c8f00bd59 Leave non-interactive at default QoS class
Lower class levels are less well defined, and non-interactive
SSH can carry various different types of applications.

This change also sets lowdelay class (AF21) earlier in an an outbound
dbclient session
2022-01-27 14:34:10 +08:00
Matt Johnston
a4362d3019 Test for IP_TOS and hardcode DSCP values
This allows it to work on macos too
2022-01-25 17:57:05 +08:00
Matt Johnston
14bdd5a8ae Use DSCP for IP QoS traffic classes
The previous TOS values are deprecated and not used by modern traffic
classifiers. This sets AF21 for "interactive" traffic (with a tty).
Non-tty traffic sets AF11 - that indicates high throughput but is not
lowest priority (which would be CS1 or LE).

This differs from the CS1 used by OpenSSH, it lets interactive git over SSH
have higher priority than background least effort traffic. Dropbear's settings
here should be suitable with the diffservs used by CAKE qdisc.
2022-01-25 17:32:20 +08:00
Matt Johnston
f3a4ea511b Use DSCP for IP QoS traffic classes
The previous TOS values are deprecated and not used by modern traffic
classifiers. This sets AF21 for "interactive" traffic (with a tty).
Non-tty traffic sets AF11 - that indicates high throughput but is not
lowest priority (which would be CS1 or LE).

This differs from the CS1 used by OpenSSH, it lets interactive git over SSH
have higher priority than background least effort traffic. Dropbear's settings
here should be suitable with the diffservs used by CAKE qdisc.
2022-01-25 17:32:20 +08:00
Matt Johnston
f972813ecd Don't include sk keys at all in KEX list 2022-01-23 17:29:39 +08:00
Matt Johnston
8727f49dec Don't include sk keys at all in KEX list 2022-01-23 17:29:39 +08:00
egor-duda
5edd2ce32e Implement server-side support for sk-ecdsa U2F-backed keys (#142)
* Implement server-side support for sk-ecdsa U2F-backed keys

* Fix out-of-bounds read on normal ecdsa-sha2-[identifier] keys

* Fix one more potential out-of-bounds read

* Check if nistp256 curve is used in sk-ecdsa-sha2- key

It's the only allowed curve per PROTOCOL.u2f specification

* Implement server-side support for sk-ed25519 FIDO2-backed keys

* Keys with type sk-* make no sense as host keys, so they should be
disabled

* fix typo

* Make sk-ecdsa call buf_ecdsa_verify

This reduces code duplication, the SK code just handles the
different message format.

* Reduce sk specific code

The application id can be stored in signkey, then we don't need
to call sk-specific functions from svr-authpubkey

* Remove debugging output, which causes compilation errors with DEBUG_TRACE disabled

* Proper cleanup of sk_app

Co-authored-by: Matt Johnston <matt@codeconstruct.com.au>
2022-01-22 21:53:04 +08:00
egor-duda
c06d8254d8 Implement server-side support for sk-ecdsa U2F-backed keys (#142)
* Implement server-side support for sk-ecdsa U2F-backed keys

* Fix out-of-bounds read on normal ecdsa-sha2-[identifier] keys

* Fix one more potential out-of-bounds read

* Check if nistp256 curve is used in sk-ecdsa-sha2- key

It's the only allowed curve per PROTOCOL.u2f specification

* Implement server-side support for sk-ed25519 FIDO2-backed keys

* Keys with type sk-* make no sense as host keys, so they should be
disabled

* fix typo

* Make sk-ecdsa call buf_ecdsa_verify

This reduces code duplication, the SK code just handles the
different message format.

* Reduce sk specific code

The application id can be stored in signkey, then we don't need
to call sk-specific functions from svr-authpubkey

* Remove debugging output, which causes compilation errors with DEBUG_TRACE disabled

* Proper cleanup of sk_app

Co-authored-by: Matt Johnston <matt@codeconstruct.com.au>
2022-01-22 21:53:04 +08:00
Matt Johnston
18be2a6509 Fix accidentally committed debug message
Was added Oct 18 2021
"Only redirect stderr after the session login."
2022-01-22 12:46:08 +08:00
Matt Johnston
483b427335 debugging test runner authorized_keys perms 2021-10-19 13:45:59 +08:00
Matt Johnston
27ffea3223 Debug pytest password auth failing 2021-10-19 13:30:58 +08:00
Matt Robinson
742e296115 Use HOME before /etc/passwd to find id_dropbear (#137)
Currently dbclient uses the value of HOME by default when looking for
~/.ssh/known_hosts, falling back to /etc/passwd if HOME is not set (so
that people can work around broken values in /etc/passwd).

However, when locating the default authentication key (defaults to
~/.ssh/id_dropbear), paths not starting with / are always prefixed with
the value from /etc/passwd.

Make the behaviour consistent by adjusting expand_homedir_path to use
the value of HOME, falling back to /etc/passwd if HOME is not set.
2021-10-19 13:02:47 +08:00
Matt Johnston
0e43d68d81 Remove caching and socat from build.yml
socat isn't needed and it consumes exit codes

Caching seems impossible to invalidate
2021-10-19 12:49:19 +08:00
Matt Johnston
bcb9d78d83 Add configure --enable-werror argument
This should be used instead of putting -Werror in CFLAGS
before configure, as -Werror interferes with conftests.

Update github actions to use that.
2021-10-19 12:16:20 +08:00
Matt Johnston
8da9646c83 Upload config.log on failure
Change tests to avoid double-negative for skipcheck

Skip some actions when running under act
2021-10-19 11:50:12 +08:00
Matt Johnston
da482ede60 github action workaround macos ranlib 2021-10-18 23:45:09 +08:00
Matt Johnston
f0495697e5 disable fuzzstandalone github action for now, needs debugging 2021-10-18 23:36:23 +08:00
Matt Johnston
f9ced2c880 fix github actions arguments
If only we could test this locally with the same setup....
2021-10-18 23:33:41 +08:00
Matt Johnston
17e0c7e76f github action, don't try apt or python on macos 2021-10-18 23:31:23 +08:00
Matt Johnston
30adc15860 Use sudo for the real github action job
(Wasn't required by act's runner)
2021-10-18 23:25:20 +08:00
Matt Johnston
6138bdc62f Add github actions build workflow, remove travis CI 2021-10-18 23:21:52 +08:00
Matt Johnston
e05945f67a Add a default 10 second timeout for tests 2021-10-18 23:20:32 +08:00
Matt Johnston
3e640acd17 Only redirect stderr after the session login. That lets errors
get recorded on the server parent side, rather than being sent
over a SSH connection.
2021-10-18 23:20:08 +08:00
Matt Johnston
ae25761c7c Rename "make test" to "make check". Also run lint 2021-10-18 15:17:14 +08:00
Matt Johnston
e6152ccd7d Update .hgignore and .gitignore with tests 2021-10-18 14:26:59 +08:00
Matt Johnston
8b0d31ab20 Add "make test" target to run pytest
This will create a virtualenv if required.

There is a bit of churn here reverting to autoconf 2.59 in generated
config.h.in and configure
2021-10-18 14:24:32 +08:00
Matt Johnston
65f6e48a06 Add first channel tests
These initial tests are checking various edge cases of channel handling
that have cropped up over the years.
2021-10-18 14:22:37 +08:00
Matt Johnston
a7ef149463 Bring back recently removed channel->flushing
This resolves the "sleep 10&echo hello" case which should
return immediately
2021-10-14 20:55:15 +08:00
Matt Johnston
043b0fbd1b Increase max window size to 10MB, fallback rather than
exiting if an invalid value is given.
2021-10-12 23:32:10 +08:00
Matt Johnston
110b55214b Partial strings from strtoul should return error 2021-10-12 23:31:09 +08:00
Matt Johnston
c08177a3af Banner size should account for newlines 2021-10-12 21:29:42 +08:00
Matt Johnston
3c2436cd05 Comment on reason for DROPBEAR_MAX_PASSWORD_LEN limit 2021-10-12 21:29:25 +08:00
Matt Johnston
f3b72bfd18 Merge 2021-10-11 15:46:49 +08:00
Matt Johnston
f17400e738 Replace ChanType.sepfds with Channel.bidir_fd
This handles the case where a svrchansess has separate FDs
for nopty, but a single FD for pty mode.

The use of sepfds was also previously incorrect for X11 and
agent forwarding
2021-10-11 15:42:14 +08:00
Matt Johnston
8e6f73e879 - Remove "flushing" handling for exited processes, it should be
handled by normal file descriptor reads.

- Fix sesscheckclose() handling if a channel was closed before a
  process was ever launched
2021-10-11 15:16:54 +08:00
Matt Johnston
7c2470ba3a Fix some outdated comments 2021-10-11 15:14:46 +08:00
Matt Johnston
cc59c08605 Move comment to svr_chansess_checksignal() where it belongs 2021-10-11 15:13:42 +08:00
Matt Johnston
661d8ca225 Add a comment about sending initial auth request 2021-10-11 15:12:22 +08:00
fidomax
41d4b4e7f7 keep LANG env variable for child process (#111) 2021-08-19 23:49:52 +08:00
Anton Bershanskiy
dc016f900b Remove unused argument of do_cmd() in scp.c (#125) 2021-08-19 23:40:58 +08:00
Sven Roederer
4c8c879b38 signkey: remove !! from SHA1 digest (#130)
Remove the "!!" chars from message when printing the key-fingerprint, as it's
confusing users. They have been added when switching from MD5, but SHA1 can be
considered as standard today.

Signed-off-by: Sven Roederer <devel-sven@geroedel.de>
2021-08-19 23:39:31 +08:00
Manfred Kaiser
210a983349 added option to disable trivial auth methods (#128)
* added option to disable trivial auth methods

* rename argument to match with other ssh clients

* fixed trivial auth detection for pubkeys
2021-08-19 23:37:14 +08:00
Matt Johnston
69e5709f75 Clarify help text for dropbear -e environment option 2021-08-19 23:17:34 +08:00
Roland Vollgraf
2157d52352 pass on sever process environment to child processes (option -e) (#118) 2021-08-19 23:13:41 +08:00
Matt Johnston
846d38fe43 Add "restrict" authorized_keys option 2021-05-01 20:47:15 +08:00
Matt Johnston
a8d6dac2c5 Don't include .hg_archival.txt in tarballs. They're now reproducible. 2021-03-31 23:31:26 +08:00
Matt Johnston
ee49a1b16d merge 2021-03-31 23:24:55 +08:00
Matt Johnston
325d0c1d02 Add configure script to version control. Set timezone for release tarball 2021-03-31 23:23:14 +08:00
Matt Johnston
17f209f9b7 Update config.sub and config.guess to latest 2021-03-31 23:21:30 +08:00
Matt Johnston
924d5a06a6 Make releases tarballs more deterministic
Not fully tested on different systems yet
2021-03-30 22:08:14 +08:00
Matt Johnston
1bf7acc5bd Remove some obselete autoconf bits.
Keeps autoconf 2.71 happy, though we leave the prereq version at 2.59
2021-03-30 20:42:04 +08:00
ValdikSS
8d0013bbe0 Use MAX_HOST_LEN for TCP forwarding requests (#121)
tcpip-forward request can include hostname, which is later resolved by getaddrinfo() call.
Dropbear incorrectly assumes tcpip-forward includes only IP(v4) address. Fix this.
2021-03-18 21:16:17 +08:00
Matt Johnston
9262ffe861 fuzz: don't push wrapfd descriptors larger than needed 2021-03-08 21:59:10 +08:00
Matt Johnston
1eb369272b fuzz: add -q quiet argument for standalone fuzzers.
travis has a log length limit
2021-03-07 21:26:34 +08:00
Matt Johnston
c0ed29ea02 fuzz: split long argument list with xargs 2021-03-07 16:30:33 +08:00
Matt Johnston
91ca561d7a fuzz: cifuzz fix syntax 2021-03-06 23:44:16 +08:00
Matt Johnston
ba260bd67b fuzz: try run cifuzz on push as well 2021-03-06 23:42:59 +08:00
Matt Johnston
898bff3d4e fuzz: add cifuzz for github pull requests 2021-03-06 23:34:39 +08:00
Matt Johnston
67a8de30b7 Prevent multiple shells being spawned
Existing shells would be leaked.
The old check only caught multiple commands, not shells.
2021-03-06 23:06:43 +08:00
Matt Johnston
6c571c54e5 small tidy of "signal" while loop 2021-03-06 23:05:17 +08:00
Matt Johnston
d2bfa6aedc fuzz: handle errors from wrapfd_new_dummy() 2021-03-06 22:58:57 +08:00
Matt Johnston
d0d1ede191 fuzz: fix crash in newtcpdirect(), don't close the channel too early 2021-03-05 22:51:11 +08:00
Matt Johnston
3c2f113a78 Return errstring on connect failure 2021-03-05 21:13:20 +08:00
Matt Johnston
f193e95a3e fuzz: avoid extraneous printing 2021-03-04 23:57:12 +08:00
Matt Johnston
03481aba06 Define _GNU_SOURCE properly, other header fixes
This lets -std=c89 build for gcc 8.4.0
2021-03-04 21:03:02 +08:00
Matt Johnston
8b0fdf8010 Small cleanups of netio allocated port 2021-03-04 21:02:16 +08:00
Guillaume Picquet
934cc87db3 Update netio.c (#115)
Moved allocated_lport_p and allocated_lport at begin of block to buld in C89
2021-03-04 20:50:13 +08:00
Guillaume Picquet
ae94f64145 Update cli-main.c (#114)
Moved pid_t proxy_cmd_pid declaration at begin of block to allow build in c89 (gcc-2.95)
2021-03-04 20:46:46 +08:00
Matt Johnston
8552a0e9eb Disable UNAUTH_CLOSE_DELAY by default 2021-03-02 22:20:14 +08:00
Matt Johnston
d20420e709 merge 2021-01-29 21:59:12 +08:00
Matt Johnston
e8640bdca3 fuzz: wrap kill() 2021-01-29 21:47:56 +08:00
Xenhat
e4edbf2e57 Update INSTALL (#113)
Make Git/Mercurial instructions easier to understand
2020-12-17 17:35:48 +08:00
Matt Johnston
5d60e5f312 Use buf_eatstring instead 2020-12-10 23:18:48 +08:00
Dirkjan Bussink
38d7da5fe5 Fix handling of replies to global requests (#112)
The current code assumes that all global requests want / need a reply.
This isn't always true and the request itself indicates if it wants a
reply or not.

It causes a specific problem with hostkeys-00@openssh.com messages.
These are sent by OpenSSH after authentication to inform the client of
potential other host keys for the host. This can be used to add a new
type of host key or to rotate host keys.

The initial information message from the server is sent as a global
request, but with want_reply set to false. This means that the server
doesn't expect an answer to this message. Instead the client needs to
send a prove request as a reply if it wants to receive proof of
ownership for the host keys.

The bug doesn't cause any current problems with due to how OpenSSH
treats receiving the failure message. It instead treats it as a
keepalive message and further ignores it.

Arguably this is a protocol violation though of Dropbear and it is only
accidental that it doesn't cause a problem with OpenSSH.

The bug was found when adding host keys support to libssh, which is more
strict protocol wise and treats the unexpected failure message an error,
also see https://gitlab.com/libssh/libssh-mirror/-/merge_requests/145
for more information.

The fix here is to honor the want_reply flag in the global request and
to only send a reply if the other side expects a reply.
2020-12-10 23:13:13 +08:00
Matt Johnston
a6b2eeb190 Fix null pointer dereference removing listeners 2020-12-07 20:03:24 +08:00
Matt Johnston
e12ff23e7d fuzz: add an always-failing dropbear_listen() replacement 2020-12-06 21:54:01 +08:00
Matt Johnston
007a5925dc fuzz: work around fuzz_connect_remote() limitations 2020-12-06 21:27:25 +08:00
Matt Johnston
d439ed26e4 Some minor manpage improvements 2020-12-05 14:56:53 +08:00
Matt Johnston
f9ff3fa23d fuzz: skip custom mutators with -fsanitize=memory 2020-12-05 11:54:53 +08:00
Matt Johnston
2c64335d9c fuzz: make postauth set authdone properly 2020-12-03 22:18:51 +08:00
Matt Johnston
286b6b9f80 Remove unused cli_authinitialise 2020-12-03 21:19:19 +08:00
Matt Johnston
220ba993a2 fuzzing - Set postauth user to root since that's what it runs as 2020-11-17 19:28:11 +08:00
Matt Johnston
3c88d6536a fuzzing: add workaround getpwuid/getpwnam 2020-11-16 22:44:30 +08:00
Matt Johnston
f49b576e93 Fix fuzzing build 2020-11-15 21:22:08 +08:00
Matt Johnston
8ec9016585 Add server postauth fuzzer, wrap connect_remote() 2020-11-13 23:18:05 +08:00
Matt Johnston
15ea6d1106 Remove accidentally committed abort() 2020-11-13 23:16:50 +08:00
Matt Johnston
24cfda9e3c fuzzing - fix some wrong types and -lcrypt on macos 2020-11-02 20:33:48 +08:00
Matt Johnston
121e6e6202 Fuzzing - get rid of "prefix" for streams
Improved packet generation with sshpacketmutator
2020-11-01 23:44:58 +08:00
Matt Johnston
1b6e16ae7c fuzzing - avoid sha1 for random seed every iteration 2020-11-01 14:01:37 +08:00
Matt Johnston
b8352f8164 Move fuzzer-kex initialisation into a constructor function
Hopefully this can avoid hitting AFL timeouts
https://github.com/google/oss-fuzz/pull/2474
2020-10-29 23:00:52 +08:00
Matt Johnston
6aa065b1b4 Use SSH packet mutator for preauth too
Get rid of separate client mutator.
Have 0.1% chance of llvm random mutation
Add comments
2020-10-29 22:41:37 +08:00
Matt Johnston
6cf29061c2 Fix FUZZ_NO_REPLACE_STDERR for fuzz.c 2020-10-29 22:14:38 +08:00
Matt Johnston
f92f0777de Merge from main 2020-10-29 21:51:41 +08:00
Matt Johnston
9c70e4bed1 Added signature for changeset 5879c5829e85 2020-10-29 21:40:34 +08:00
Matt Johnston
a51833c51a Added tag DROPBEAR_2020.81 for changeset 4b984c42372d 2020-10-29 21:40:27 +08:00
Matt Johnston
d852d69b50 Changelog for 2020.81 2020-10-29 21:35:50 +08:00
Matt Johnston
1b603069db Fix fuzzing stderr override on os x 2020-10-26 23:44:43 +08:00
Matt Johnston
bf4058d1df Preallocate memory for sshpacketmutator. Add fuzzer-client_mutator_nomaths 2020-10-26 23:31:24 +08:00
Matt Johnston
4d716b6302 crossover works 2020-10-26 23:06:41 +08:00
Matt Johnston
1260fbc5cd Fix fuzz-sshpacketmutator to work 2020-10-26 22:52:07 +08:00
Matt Johnston
acd6a22a0c Print ascii in printhex too 2020-10-26 22:51:44 +08:00
Matt Johnston
4e8a1da551 Add first try at fuzzing custom mutator 2020-10-25 22:52:36 +08:00
Matt Johnston
754dc50b93 merge from main 2020-10-25 21:47:42 +08:00
Matt Johnston
c7cfa75e92 Disable stderr output for fuzzer by default 2020-10-24 22:40:08 +08:00
Matt Johnston
b070bcd570 Make "Too many remote algorithms" exit rather than log
It's fatal anyway, makes logs more concise.
2020-10-24 19:28:29 +08:00
Matt Johnston
037d26f055 Add buf_decrpos() 2020-10-24 18:56:45 +08:00
Matt Johnston
cb252296c5 Add some more variation to fuzzer random number generation 2020-10-23 23:32:44 +08:00
Matt Johnston
f37def57b0 Move fuzzing code to fuzz/ subdirectory, improve Makefile.in 2020-10-23 23:10:20 +08:00
Matt Johnston
1a208c460b Increase MAX_PROPOSED_ALGO to 50, warn if exceeded 2020-10-23 20:53:58 +08:00
Matt Johnston
34f24b1841 Fix #ifdef DROPBEAR_FUZZ (caught by linter) 2020-10-21 20:49:22 +08:00
Matt Johnston
1a7b944917 Load password and key for client fuzzer.
Add fuzz_dump()
2020-10-20 23:34:38 +08:00
Matt Johnston
3b400bd64e Don't sort objects, it breaks -lcrypt ordering 2020-10-20 23:33:45 +08:00
Matt Johnston
f74baa5830 Add ubsan fuzz run to Travis CI too 2020-10-19 23:38:11 +08:00
Matt Johnston
4c5b8fb6d6 Use Dropbear's random source rather than libtommath's platform 2020-10-19 22:49:19 +08:00
Matt Johnston
d5cc5eb25c Avoid passing NULL to memcpy 2020-10-19 21:38:20 +08:00
Matt Johnston
9f642e2bd4 Fix fuzzer build 2020-10-18 23:32:39 +08:00
Matt Johnston
6ca24af24a Merge fuzz branch 2020-10-18 22:53:44 +08:00
Matt Johnston
400c7c161f Allocate real file descriptors for fuzz input with dup()
--HG--
branch : fuzz
2020-10-18 22:52:24 +08:00
Matt Johnston
5567c238a7 Disallow extra kexinit messages
--HG--
branch : fuzz
2020-10-18 22:17:54 +08:00
Matt Johnston
33eba22966 Add fuzzer-client_nomaths, fix client fuzzer
--HG--
branch : fuzz
2020-10-18 15:08:54 +08:00
Matt Johnston
282fc81981 Get client fuzzer building and starting (fails straight away)
--HG--
branch : fuzz
2020-10-18 12:17:39 +08:00
Matt Johnston
cc1b07dcf1 Make wrapfd share a common buffer for all FDs
--HG--
branch : fuzz
2020-10-15 22:46:24 +08:00
Matt Johnston
0e3e8db5bf merge from main
--HG--
branch : fuzz
2020-10-15 19:55:15 +08:00
Matt Johnston
17873e8c92 Avoid gnu extension conditional operator 2020-10-08 11:00:04 +08:00
Matt Johnston
80e9281701 Change secure.ucc.asn.au/hg to hg.ucc.asn.au 2020-07-28 18:53:48 +08:00
Matt Johnston
926c477188 Added signature for changeset 88f63b8b0f13 2020-06-26 21:57:20 +08:00
Matt Johnston
d999575e34 Added tag DROPBEAR_2020.80 for changeset 73646de50f13 2020-06-26 21:57:18 +08:00
Thomas De Schampheleire
49177312fb Introduce extra delay before closing unauthenticated sessions
To make it harder for attackers, introduce a delay to keep an
unauthenticated session open a bit longer, thus blocking a connection
slot until after the delay.

Without this, while there is a limit on the amount of attempts an attacker
can make at the same time (MAX_UNAUTH_PER_IP), the time taken by dropbear to
handle one attempt is still short and thus for each of the allowed parallel
attempts many attempts can be chained one after the other. The attempt rate
is then:
    "MAX_UNAUTH_PER_IP / <process time of one attempt>".

With the delay, this rate becomes:
    "MAX_UNAUTH_PER_IP / UNAUTH_CLOSE_DELAY".
2017-02-15 13:53:04 +01:00
227 changed files with 19418 additions and 5362 deletions

9
.github/multiwrapper vendored Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
# symlink this to dropbear/dbclient/dropbearkey next to dropbearmulti
# good enough for testing purposes.
DIR=$(dirname $0)
PROG=$(basename $0)
exec $DIR/dropbearmulti $PROG "$@"

25
.github/workflows/autoconf.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
# Checks that autoconf has been run if configure.ac was updated
# Assumes that autoconf 2.71 was run, the same as ubuntu 22.04
name: Autoconf Up To Date
on:
pull_request:
push:
branches:
- master
jobs:
autoconf:
runs-on: 'ubuntu-22.04'
steps:
- name: deps
run: |
sudo apt-get -y update
sudo apt-get -y install autoconf
- uses: actions/checkout@v4
- name: run autoconf
run: autoconf && autoheader
- name: check no difference
run: git diff --exit-code

290
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,290 @@
# Can be used locally with https://github.com/nektos/act
# Note the XXX line below.
name: BuildTest
on:
pull_request:
push:
branches:
- master
jobs:
build:
runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
strategy:
matrix:
# XXX uncomment the line below to work with act, see https://github.com/nektos/act/issues/996
# name: []
# Rather than a boolean False we use eg
# runcheck: 'no'
# Otherwise GH expressions will make a None var
# compare with False. We want an undefined default of True.
# MULTI and NOWRITEV are passed as integers to the build
include:
- name: plain linux
- name: multi binary
multi: 1
multilink: 1
- name: multi binary, dropbearmulti argv0
multi: 1
multiwrapper: 1
- name: client only
runcheck: 'no'
make_target: PROGRAMS=dbclient
- name: server only
runcheck: 'no'
make_target: PROGRAMS=dropbear
- name: bundled libtom, bionic , no writev()
# test can use an older distro with bundled libtommath
os: ubuntu-20.04
configure_flags: --enable-bundled-libtom --enable-werror
# NOWRITEV is unrelated, test here to save a job
nowritev: 1
# our tests expect >= python3.7
runcheck: 'no'
- name: linux clang
cc: clang
# Some platforms only have old compilers, we try to keep
# compatibilty. For some reason -std=c89 doesn't enforce
# early declarations so we specify it anyway.
- name: c89
extracflags: -std=c89 -Wdeclaration-after-statement
# enable all options
nondefault: 1
configure_flags: --enable-pam
- name: macos 14
os: macos-14
cc: clang
# OS X says daemon() and utmp are deprecated.
# OS X tests for undefined TARGET_OS_EMBEDDED in libc headers
extracflags: -Wno-deprecated-declarations -Wno-undef
runcheck: 'no'
apt: 'no'
# fails with:
# .../ranlib: file: libtomcrypt.a(cbc_setiv.o) has no symbols
ranlib: ranlib -no_warning_for_no_symbols
- name: macos 12
os: macos-12
cc: clang
# OS X says daemon() and utmp are deprecated.
# OS X tests for undefined TARGET_OS_EMBEDDED in libc headers
extracflags: -Wno-deprecated-declarations -Wno-undef
runcheck: 'no'
apt: 'no'
# fails with:
# .../ranlib: file: libtomcrypt.a(cbc_setiv.o) has no symbols
ranlib: ranlib -no_warning_for_no_symbols
# Check that debug code doesn't bitrot
- name: DEBUG_TRACE
nondefault: 1
configure_flags: --enable-pam
localoptions: |
#define DEBUG_TRACE 5
# Check off-by-default options don't bitrot
- name: nondefault options
nondefault: 1
configure_flags: --enable-pam
- name: most options disabled
configure_flags: --disable-harden --disable-zlib --disable-openpty --disable-lastlog
runcheck: 'no'
localoptions: |
#define DROPBEAR_RSA 0
#define INETD_MODE 0
#define DROPBEAR_REEXEC 0
#define DROPBEAR_SMALL_CODE 0
#define DROPBEAR_CLI_LOCALTCPFWD 0
#define DROPBEAR_CLI_REMOTETCPFWD 0
#define DROPBEAR_SVR_LOCALTCPFWD 0
#define DROPBEAR_SVR_REMOTETCPFWD 0
#define DROPBEAR_SVR_AGENTFWD 0
#define DROPBEAR_CLI_AGENTFWD 0
#define DROPBEAR_CLI_PROXYCMD 0
#define DROPBEAR_USER_ALGO_LIST 0
#define DROPBEAR_AES128 0
#define DROPBEAR_AES256 0
#define DROPBEAR_ENABLE_CTR_MODE 0
#define DROPBEAR_SHA1_HMAC 0
#define DROPBEAR_SHA2_256_HMAC 0
#define DROPBEAR_RSA 0
#define DROPBEAR_ECDSA 0
#define DROPBEAR_SK_KEYS 0
#define DROPBEAR_DELAY_HOSTKEY 0
#define DROPBEAR_DH_GROUP14_SHA1 0
#define DROPBEAR_DH_GROUP14_SHA256 0
#define DROPBEAR_ECDH 0
#define DROPBEAR_DH_GROUP1_CLIENTONLY 0
#define DO_MOTD 0
#define DROPBEAR_SVR_PUBKEY_AUTH 0
#define DROPBEAR_CLI_PASSWORD_AUTH 0
#define DROPBEAR_CLI_PUBKEY_AUTH 0
#define DROPBEAR_USE_PASSWORD_ENV 0
#define DROPBEAR_SFTPSERVER 0
- name: other algo combos
runcheck: 'no'
# disables all sha1
localoptions: |
#define DROPBEAR_SHA1_HMAC 0
#define DROPBEAR_RSA_SHA1 0
#define DROPBEAR_DH_GROUP14_SHA1 0
#define DROPBEAR_ECDSA 0
#define DROPBEAR_ED25519 0
#define DROPBEAR_SK_KEYS 0
#define DROPBEAR_ENABLE_GCM_MODE 1
#define DROPBEAR_3DES 1
#define DROPBEAR_DH_GROUP16 1
#define DROPBEAR_SHA2_512_HMAC 1
#define DROPBEAR_CLI_PUBKEY_AUTH 0
# # Fuzzers run standalone. A bit superfluous with cifuzz, but
# # good to run the whole corpus to keep it working.
# - name: fuzzing with address sanitizer
# configure_flags: --enable-fuzz --disable-harden --enable-bundled-libtom --enable-werror
# ldflags: -fsanitize=address
# extracflags: -fsanitize=address
# # -fsanitize=address prevents aslr, don't test it
# pytest_addopts: -k "not aslr"
# fuzz: True
# cc: clang
# # Undefined Behaviour sanitizer
# - name: fuzzing with undefined behaviour sanitizer
# configure_flags: --enable-fuzz --disable-harden --enable-bundled-libtom --enable-werror
# ldflags: -fsanitize=undefined
# # don't fail with alignment due to https://github.com/libtom/libtomcrypt/issues/549
# extracflags: -fsanitize=undefined -fno-sanitize-recover=undefined -fsanitize-recover=alignment
# pytest_addopts: -k "not aslr"
# fuzz: True
# cc: clang
env:
MULTI: ${{ matrix.multi }}
CC: ${{ matrix.cc || 'gcc' }}
LDFLAGS: ${{ matrix.ldflags }}
EXTRACFLAGS: ${{ matrix.extracflags }}
CONFIGURE_FLAGS: ${{ matrix.configure_flags || '--enable-werror' }}
MAKE_TARGET: ${{ matrix.make_target }}
# for fuzzing
CXX: clang++
RANLIB: ${{ matrix.ranlib || 'ranlib' }}
# pytest in "make check" recognises this for extra arguments
PYTEST_ADDOPTS: ${{ matrix.pytest_addopts }}
# some pytests depend on special setup from this file. see authorized_keys below.
DBTEST_IN_ACTION: true
LOCALOPTIONS: ${{ matrix.localoptions }}
steps:
- name: deps
if: ${{ matrix.apt != 'no' }}
run: |
sudo apt-get -y update
sudo apt-get -y install zlib1g-dev libtomcrypt-dev libtommath-dev mercurial python3-venv libpam0g-dev $CC
- uses: actions/checkout@v4
- name: configure
run: ./configure $CONFIGURE_FLAGS CFLAGS="-O2 -Wall -Wno-pointer-sign $EXTRACFLAGS" --prefix="$HOME/inst" || (cat config.log; exit 1)
- name: nowritev
if: ${{ matrix.nowritev }}
run: sed -i -e s/HAVE_WRITEV/DONT_HAVE_WRITEV/ config.h
- name: localoptions
run: |
echo "$LOCALOPTIONS" | tee localoptions.h
- name: nondefault
if: ${{ matrix.nondefault }}
run: |
# Turn on anything that's off by default. Rough but seems sufficient
grep ' 0$' src/default_options.h | sed 's/0$/1/' > localoptions.h
# PAM clashes with password
echo "#define DROPBEAR_SVR_PASSWORD_AUTH 0" >> localoptions.h
# 1 second timeout is too short
sed -i "s/DEFAULT_IDLE_TIMEOUT 1/DEFAULT_IDLE_TIMEOUT 99/" localoptions.h
- name: make
run: |
cat localoptions.h
make -j3 $MAKE_TARGET
- name: multilink
if: ${{ matrix.multilink }}
run: make multilink
- name: multi wrapper script
if: ${{ matrix.multiwrapper }}
run: |
cp .github/multiwrapper dropbear
cp .github/multiwrapper dbclient
cp .github/multiwrapper dropbearkey
cp .github/multiwrapper dropbearconvert
- name: makefuzz
run: make fuzzstandalone
if: ${{ matrix.fuzz }}
# avoid concurrent install, osx/freebsd is racey (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208093)
- name: make install
run: make install
- name: keys
if: ${{ matrix.runcheck != 'no' }}
run: |
mkdir -p ~/.ssh
# remove old files so we can rerun in-place with "act -r" during test development
rm -vf ~/.ssh/id_dropbear*
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear | grep ^ecdsa > ~/.ssh/authorized_keys
# to test setting SSH_PUBKEYINFO, replace the trailing comment
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key2 | grep ^ecdsa | sed 's/[^ ]*$/key2 extra/' >> ~/.ssh/authorized_keys
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key3 | grep ^ecdsa | sed 's/[^ ]*$/key3%char/' >> ~/.ssh/authorized_keys
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key4 | grep ^ecdsa | sed 's/[^ ]*$/key4,char/' >> ~/.ssh/authorized_keys
chmod 700 ~ ~/.ssh ~/.ssh/authorized_keys
ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
# upload config.log if something has failed
- name: config.log
if: ${{ !env.ACT && (failure() || cancelled()) }}
uses: actions/upload-artifact@v2
with:
name: config.log
path: config.log
- name: check
if: ${{ matrix.runcheck != 'no' }}
run: make check
# Sanity check that the binary runs
- name: genrsa
if: ${{ matrix.runcheck != 'no' }}
run: ~/inst/bin/dropbearkey -t rsa -f testrsa
- name: genecdsa256
if: ${{ matrix.runcheck != 'no' }}
run: ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256
- name: genecdsa384
if: ${{ matrix.runcheck != 'no' }}
run: ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384
- name: genecdsa521
if: ${{ matrix.runcheck != 'no' }}
run: ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521
- name: gened25519
if: ${{ matrix.runcheck != 'no' }}
run: ~/inst/bin/dropbearkey -t ed25519 -f tested25519
- name: fuzz
if: ${{ matrix.fuzz }}
run: ./fuzzers_test.sh

30
.github/workflows/cifuzz.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
# Runs fuzzers for a little while on pull requests.
# From https://google.github.io/oss-fuzz/getting-started/continuous-integration/
name: CIFuzz
on:
pull_request:
push:
branches:
- master
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'dropbear'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'dropbear'
fuzz-seconds: 1200
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

25
.github/workflows/outoftree.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
# Can be used locally with https://github.com/nektos/act
name: Out of tree build
on:
pull_request:
push:
branches:
- master
jobs:
outoftree:
runs-on: 'ubuntu-22.04'
steps:
- uses: actions/checkout@v4
- name: build
run: |
mkdir build
cd build
../configure --enable-fuzz --enable-bundled-libtom --prefix=$PWD/inst
make -j3
make -j3 fuzzstandalone
make install
test -x inst/bin/dbclient
test -f inst/share/man/man8/dropbear.8

36
.github/workflows/tarball.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: tarball sha256sum
on:
push:
branches:
- master
jobs:
tarball:
runs-on: 'ubuntu-22.04'
steps:
- uses: actions/checkout@v4
- name: release.sh
run: ./release.sh --testrel | tee log1.txt
- name: extract output
run: |
grep ^SHA256 log1.txt | tee sha256sum.txt
sed 's/.*= *//' < sha256sum.txt > hash.txt
mv `tail -n1 log1.txt` rel.tar.bz2
- name: sha256sum
uses: actions/upload-artifact@v4
with:
name: sha256sum
path: |
sha256sum.txt
hash.txt
- name: tarball
uses: actions/upload-artifact@v4
with:
name: tarball
# only keep for debugging
retention-days: 3
path: rel.tar.bz2

12
.gitignore vendored
View File

@@ -6,6 +6,7 @@
*.bbg
*.prof
.*.swp
/obj
/autom4te.cache
/config.log
/config.status
@@ -19,9 +20,14 @@
/fuzzer-*.options
/scp
/scp-progress
Makefile
config.h
config.h.in
configure
default_options_guard.h
localoptions.h
Makefile
tags
.pytest*
*.pyc
/test/venv/
/test/init/
/test/fakekey
.vscode/

View File

@@ -1,2 +0,0 @@
.*\.o
.*~

29
.hgsigs
View File

@@ -1,29 +0,0 @@
aa2f51a6b81d33de5e9898a7f27c792a173d9b26 0 iD8DBQBOuADmjPn4sExkf7wRAv/fAJ9FJFvjDoF+wd1ipDx1wkzdeBQNqgCgykUrSbXv76FBbxKntVbk9oS3GjI=
3f12086c2ef2b9ffe36a822fdb3ff647fcec1831 0 iD8DBQBOuSlQjPn4sExkf7wRAvkbAKCgE1e8xEMQ16CGeoywhIQ0QR4eNgCfZdYYlzjb/+521Uvh5/7FRYEmrho=
85f835f2fe0ac2c503c50a414de127222fb0a57c 0 iD8DBQBPRkMUjPn4sExkf7wRAvM4AJ9mw2OAkyjhSbamM1MizlEJUX18HACgoFKQkYf6BnYxN34Nv2HhM0cmzUc=
9b80981212fe6c01b7c16b3ca7c4e66af56f12f1 0 iEYEABECAAYFAlFLKKcACgkQjPn4sExkf7xK7wCfcioCmJPsysSbQO6+4qZMVe0mmLwAn2/o+wRf4MrUXlohrr7aXEF9vdSB
095b46180bbc412b029420587736a6185afc17e1 0 iEYEABECAAYFAlFsCnkACgkQjPn4sExkf7xLrwCfeMWjUaSmfU/fvseT5TdrYRqBEVQAoLz5SFLEA40C5f8zE8Ma/vgVJVIC
f168962bab857ca030829e4cd73d9b32c868c874 0 iEYEABECAAYFAlFwDNwACgkQjPn4sExkf7wJ6QCePVovn/avKXUyNwNBYCcov6JLYqkAnRCPQdkXgv20N3t10r6PRMBBo1/S
deb211f75ca194e2fcf0d2e5f71c60474e42ec95 0 iEYEABECAAYFAlJO01cACgkQjPn4sExkf7yDqACaA/P+Yl/K2Cv3OC5G0b7ck2Kb75EAoIeW7qpCyclzJLWwk95koED+4lxD
025237c9f0a1a60a616f984d82fb2a9270d3b0ea 0 iEYEABECAAYFAlJeqDYACgkQjPn4sExkf7y5nQCfW6t+TJySBTTo+gCfDUBPRVxvNe8AoIn/15aWfqH/A2G9uikfoVtWK3pd
a50a1dc743317fad9b3737bc68fbca640659bb6d 0 iEYEABECAAYFAlJeqL0ACgkQjPn4sExkf7yVqACg6IP0fU29+Feh/TDeemDA+2XAzrIAoIdZfMDvVYlDoWotZD8ACFnf5H1P
9ec083a21adfcb099f21eb03704b66d14a4ba800 0 iEYEABECAAYFAlKE4JoACgkQjPn4sExkf7wLDgCghkVGwMjI138bEv+ORVzN7zIH7cEAoLckaxZc1k1aXlmlSCRlP8cuKH3o
3d1d7d151c0ce3a79da62e86463f5632fa2b144a 0 iEYEABECAAYFAlKd5AEACgkQjPn4sExkf7wzWgCfdvPEEIdlMPqcbOQMJ7b+eAyy164An2ip1lPh1eS5g26/gSfruvWBVym4
277429102f1337bd10c89107d3e01de509cc1a7e 0 iEYEABECAAYFAlMEvF4ACgkQjPn4sExkf7xeVQCgtbxJ4G3hsFwUOM0K1WGr1J2vsbEAoMM8dEyr1mdrbgO1tzNLfD1nxbyn
96584b934d04ebab443f603e78d38fe692d36313 0 iEYEABECAAYFAlPVFrQACgkQjPn4sExkf7xr6ACglRiLE21vRrS1rJ809o2yMADIKtwAn1f5SyZUngSde8eE55JxCMwtMC5m
caac692b366c153cea0e9cd59aa2d79a7d843d4e 0 iEYEABECAAYFAlPk1mcACgkQjPn4sExkf7wLpgCeOqMYqpkf4lYUuyrn9VYThNpc7PkAn3JOSNgIqkKUcmSy6FstrI8jwJzq
2d421bc0545d1be6d59a4ebfe61606d94b124b0c 0 iEYEABECAAYFAlRJDCQACgkQjPn4sExkf7xUYACcCwVJkYWXJn5x/D5A+qMupy778lEAn0rg1oNiq96YU/4jOPsS5IMItihu
1d2d81b1b7c1b100e9c369e40b9fa5b2d491eea9 0 iEYEABECAAYFAlTKOKUACgkQjPn4sExkf7xWMACfYFozyHiRk5GaocTa5z6Ws1uyB4kAoLubxoxcnM3E7AA9mHAzc3OB5M0Y
a687f835236c7025b5cb2968fe9c4ebc4a49f0ea 0 iQIcBAABCgAGBQJVxg62AAoJEPSYMBLCC7qsC+EQAKw8YWogrVHhIFct2fx/nqybSPVrhFyKFKHhq7K/lZeVm0MGIWdSyVcQgP+Hs2jWNBWzG4AJ1BtifHWQH6IDh7W5RuwOXu5KobgPW9BsN3EVE9KIR+xe9jCAmFl9rIw0tNpy1q6R0TpYXx/sWlMilxecyEGyr2Ias2Sm19aY2mOEv8PLfh9BLfrJEKtt2NxL7TX8ScPwJXJMmVIQjN9WK4Ptx3tjcGNRivEVR/dftP5sJx2DBJx9avyDqrfloMW7Q7sPgJ88MPruCDxedOkbzH7JdHe3Humr2G4LsI0KPU7pNN6EBDjhJ+SVXuOyAgu5j/C0R+0ggGfjSrjDu8WjHyclFlwwu2MSGuHf111I1qkLtaRY3H1FZO5Y2gbLwBLQ82svA4klcBIxtP5jKAZDTh1jQMYsfKotvZdawOWrPDkNmKoUg2JXLHAtj9Dd0uGIhqfspZY3qlpzxw9uCkljWclUBD097ygotwAb2XdLoAWZ3KdvoPM+k448vIAQ7Q/aqcnm/dLQJr3Le029gpkOKoWKaQTlk0itrRGpgETHAhE2LnmWxYSKp6NYSKMgEONbfDiVNLyDTOlvpPiEb20RsOP64xA4wVDGmPenCURmMYoepQK6oJdtkNtCdth2S49KxPQAC+Dem4YZ7b+5b+cXrK5Nz7elBxZzRQWdjmZ4JDQK
ef4b26364b0cdda1084751d7de3d76c589e2d9cb 0 iQIcBAABCgAGBQJVxg7BAAoJEESTFJTynGdz9Q4P/A0Kq4H52rQqxq42PoEMFbVQIUfkFzyWjAz8eEGLmP5x5/sdpyxZDEyBSUG55uyNvOPTHE+Sd3t2h2Iieq749qwYgqggXC0P+C0zGzW3hB5Rv6dTUrKN1yCyaWE2tY488RsyVlcAs4vrp1Cum5Gv8/BUVKjzZmkZ1iq/3RyrvbLEiLoMrcLnQ+sUdaYHvfEwxDbzpOEvepg8iDJBitTrfG9xHp9otX6ucahwn1EumFvC5mvUxbiQ9jv76t4FJztjMoB24hPCH9T1FjB8uNsoM+j2Z67r81eJrGgNpJzjX0S3lY/AADZGhfGnfybTM9gFuQayIJuCJqduQibVwYkAAnPi17NmbdwPu0Rdz55oU+ft09XLVm/qkQcD1EP5bxYWnLIEMkkZQnFx7WdMpjKK9oGxZHeFYAKEgPgePCkk4TQ4PxNa+3854H19AUssQlaueGcbDLyPIRiSyqhleXawGfaJi+1jBt0DM7CNbAHAUWUE07VhQzNGWjabdEk4eXKTmDL+mZJFdHGBhyCve8sPmZBYJvM2PRgcXe8fwFh+R7gVj6kFbZJvgM9kG7EeF+4ZMEXG4yKpV/SKfMMeEPBCZjFxZhlJJ0fsZbB1Y/iLw8LXnJ0fa/5xFYv6k+iytfom/rqS4iUD7NWTjcEYHjd4EO4QlPD2Ef/AWOO8YBUBv8kA
af074dbcb68ff8670b3818e0d66d5dc6f1bd5877 0 iQIcBAABCgAGBQJWVdQfAAoJEPSYMBLCC7qs+n4P/RgZU3GsLFJN7v7Cn6NOdKdfjJBmlbCtK9KwlZZaj8fW4noqnLDcDd6a2xT4mDV3rCE6+QYialGXjNkkNCBwD9Z+gFc8spOtThrpQ54dgWzbgDlYB1y7Hp7DoWoJQIlU6Od9nWBemcSrAviOFNAX8+S6poRdEhrHgMcv2xJoqHjvT7X8gob0RnJcYxW5nLWzDaJV58QnX6QlXg4ClSB6IoCeEawdW6WzXlZ9MGsRycTtx1ool7Uo6Vo2xg48n9TaJqM/lbSsMAjHxO/fdTJMWzTId1fuZxJGFVeJbkhjSwlf7fkVXxrgDxjvIAmFDR8TSTfJo50CD82j5rPcd7KSEpQ12ImBUsntPDgOtt/mJZ3HcFds86OZ7NkPpqoJGVFFQ8yUpe//DNSB2Ovg1FrwhSKOq/9N61BBwk1INVFDp1hMq45PIa9gI9zW/99inGDeSSQlxa4iafEUEjXZTRYuX7mFjnWm5q7r134J7kyWQtN/jNUZ71F0mvhnemufgpNY/I/D7K6qkONpbDZ2nuzkhfoqugzhHYp467UePM0qmLTLdXGPPMukoGorpWeiSb2T25AEKm7N4A9NwPmdAnoFjAibjF9FAuU03sl+pu9MqFb+1ldsqjNfxhcJmoAUR5vy3pED9ailCb/OCBVTHkDPfTEhGU3waO9tPM+5x2rGB5fe
5bb5976e6902a0c9fba974a880c68c9487ee1e77 0 iQIcBAABCgAGBQJWVyIKAAoJEESTFJTynGdzQosP/0k5bVTerpUKZLjyNuMU8o0eyc7njkX8EyMOyGbtcArKpzO2opSBTRsuCT9Zsk1iiQ1GMTY1quKD7aNr86Hipqo4th/+ZXmLe9mmaCDukKjD0ZYC4dBVUy6RSUAMvdkDP9sZs7CMTO/22a9SqOsKTv3s2NN6XnsBGnmNbvVx5hkAk5hMVNFrjKIaexzI/7bWQIDRo2HQCaWaL06JvWEDSEQd2mynGSXxT/+m4hBnuGg6qxn2pd4XfG0g10tDAFx64HQkWgZqSB+F8z71Cvfjondy1zjJYgtABqNlwCKQJZhRUW2+PblqQnz08TUy83XN2vtisOju4avGcHSaBgBbMvg8Wx4ZtM7sPP9pLrhhOTd5ceERHeTceTJy+iI1SQFvccjrRfs5aJ0zAQX5q6f4bV0zp5SmxkvnZUEkZIoetkM8VrPOYugqx31LtHAWfVT9NM+VkV/rrxLhk6J0giIQvC9MPWxRDileFVDszPiOgTLcxWjOziOLT+xijcj7dtx1b/f2bNCduN5G7i+icjjTlCNtyRPRqhBqn705W7F+xESP2gsscM/1BjQ7TGidU5m1njdkUjbrqm3+Qic6iqkG7SfETHmQB9mHqpJ0hACRPvZlhwB7oimNHllkrlw8UJw9f0SiuLjfERIgVS2EOp+mAia0RU7MlTt19o017M1ffEYL
926e7275cef4f4f2a4251597ee4814748394824c 0 iQIcBAABCgAGBQJWYES4AAoJEESTFJTynGdzdT0P/0O/1frevtr698DwMe6kmJx35P6Bqq8szntMxYucv0HROTfr85JRcCCSvl/2SflDS215QmOxdvYLGLUWPJNz/gURCLpzsT88KLF68Y1tC72nl4Fj+LGIOlsWsvwEqQqw0v4iQkHIfcxI6q7g1r9Hfldf/ju4bzQ4HnKLxm6KNcLLoAsuehVpQ+njHpLmlLAGHU5a84B7xeXHFR+U/EBPxSdm637rNhmpLpkuK2Mym/Mzv7BThKDstpB8lhFHIwAVNqi3Cy4nGYxFZOJpooUN9pDornqAwuzHmOAMs9+49L8GZ1de5PBRGyFKibzjBIUWPEU9EIkfJVaVwTlqYK8Q/IRi9HjITPx6GpE8cZhdSvAibrQdb6BbIDrZ8eCvD9vnod6Uk0Jb9/ui6nCF9x+CN/3Qez4epV5+JCMYsqCiXFkVPm9Lab6L2eGZis7Q2TXImA/sSV+E4BGfH2urpkKlnuXTTtDp4XRG+lOISkIBXgjVY+uy8soVKNdx1gv+LeY8hu/oQ2NyOlaOeL47aSQ3who4Pk6pVRUOl6zfcKo9Vs6xDWm35A3Z6x/mrAENaXasB0JrfY5nIbefJUpbeSmi76fYldU98HdQNHPHCSeiKVYl7v/B6gi2JXp5xngLZz/5VVAurago7sRmpIp7G/AqU6LNE85IUzG8aQz8AfR0d1dW
fd1981f41c626a969f07b4823848deaefef3c8aa 0 iQIcBAABCgAGBQJW4W2TAAoJEESTFJTynGdzuOcP/j6tvB2WRwSj39KoJuRcRebFWWv4ZHiQXYMXWa3X0Ppzz52r9W0cXDjjlp5FyGdovCQsK+IXmjPo5cCvWBrZJYA6usFr9ssnUtTC+45lvPxPYwj47ZGPngCXDt7LD+v08XhqCu4LsctXIP/zejd30KVS1eR2RHI+tnEyaIKC0Xaa0igcv74MZX7Q8/U+B730QMX5adfYAHoeyRhoctRWaxVV3To7Vadd9jNXP45MRY5auhRcK7XyQcS85vJeCRoysfDUas4ERRQWYkX+68GyzO9GrkYFle931Akw2K6ZZfUuiC2TrF5xv1eRP1Zm2GX481U4ZGFTI8IzZL8sVQ6tvzq2Mxsecu589JNui9aB2d8Gp2Su/E2zn0h0ShIRmviGzf2HiBt+Bnji5X2h/fJKWbLaWge0MdOU5Jidfyh9k0YT7xo4piJLJYSaZ3nv+j4jTYnTfL7uYvuWbYkJ1T32aQVCan7Eup3BFAgQjzbWYi1XQVg6fvu8uHPpS3tNNA9EAMeeyTyg1l6zI2EIU5gPfd/dKmdyotY2lZBkFZNJqFkKRZuzjWekcw7hAxS+Bd68GKklt/DGrQiVycAgimqwXrfkzzQagawq2fXL2uXB8ghlsyxKLSQPnAtBF2Jcn5FH2z7HOQ+e18ZrFfNy0cYa/4OdH6K5aK1igTzhZZP2Urn0
70705edee9dd29cd3d410f19fbd15cc3489313e2 0 iQIcBAABCgAGBQJW7CQRAAoJEESTFJTynGdzTj0QAJL38CKSZthBAeI9c6B+IlwIeT6kPZaPqk1pkycCTWOe87NiNU9abrsF+JrjTuRQiO1EpM2IvfQEIXTijUcMxvld3PnzrZDDv6UvBLtOkn3i++HSVRO0MOuTKI8gFDEPUxRtcaCKXEbqYnf1OTK25FT09Vb//qP9mK1thvlLJmbV+D2a9MkMK66rom1d1h+347IsuwsM+ycHjB80VVAQLA7VYLC5YIwmL17dSmcQLvetfikAMwwmUE+KES4qiLSaqOcAWcKcU67RZzgMMv5o0rESlQmv1nj0mHZtHoUR71sd21emPaRXLOr0oT5YogWUphKq2qVthRn2B06+vd3hPdtn92CmJw9j7zT2jl4OeSjNm9qfAajsRzHIANssFxkGAb7w/LxcMoO29JC+01iUUJMdOVm+4Ns6wGI7qxssWPKdB+VbQUDlHrXLR+sopO524uhkYoWB6DVfTj4R6tImaHtj5/VXON0lsYaLGj8cSH60emL6nNQ0lYV/bSlk6l0s+0x3uXGZnp9oKA+vqMzHfG3vJeMm6KUqtFVjUsYx+q8nHm5/SlWxj1EwnkH8s8ELKZAUXjd76nWEwJ7JFRNRSQWvjOUh3/rsOo4JopzZXPsjCjm+Vql9TG0X6hB21noai32oD5RvfhtR/NX6sXNS5TKZz/j/cMsMnAAsSKb6W7Jm
9030ffdbe5625e35ed7189ab84a41dfc8d413e9c 0 iQIcBAABCgAGBQJXkOg0AAoJEESTFJTynGdzc1kP/3vSKCnhOOvjCjnpTQadYcCUq8vTNnfLHYVu0R4ItPa/jT6RmxoaYP+lZnLnnBx9+aX7kzwHsa9BUX3MbMEyLrOzX2I+bDJbNPhQyupyCuPYlf5Q9KVcO9YlpbsC4q5XBzCn3j2+pT8kSfi9uD8fgY3TgE4w9meINrfQAealfjwMLT8S/I49/ni0r+usSfk/dnSShJYDUO7Ja0VWbJea/GkkZTu30bCnMUZPjRApipU3hPP63WFjkSMT1rp2mAXbWqyr9lf8z32yxzM9nMSjq4ViRFzFlkGtE3EVRJ4PwkO7JuiWAMPJpiQcEr+r52cCsmWhiGyHuINo01MwoMO9/n6uL1WVa3mJcE9se3xBOvfgDu2FRFGCAdm1tef+AGVo9EG1uJXi0sX2yUc6DMeuYaRWrXMMlZh7zp9cuNU9Y/lLui9RFmq66yeXG3Z2B72doju3Ig5QGrNNw2AOsSzeHdAtOp6ychqPcl9QfIeJQG18KyPSefZKM3G8YRKBRIwXFEH6iZJe5ZIP4iXrHDMn2JqtTRtDqKR8VNDAgb9z4Ffx8QRxFyj5JzTTMM1GddHb9udLvTQlO0ULYG7hCSMRNzvUBE2aTw8frjLRyfyyg3QpDu/hz8op8s1ecE8rTCD8RuX9DiiylNozypPtGNS+UDbAmkc1PCWaRpPVl+9K6787
5c9207ceedaea794f958224c19214d66af6e2d56 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlkdtooACgkQRJMUlPKcZ3P6ZxAAmLy/buZB/d96DJF/pViRWt/fWdjQFC4MqWfeSLW02OZ8Qkm1vPL3ln6WPHC2thy3xZWVg2uan3pLk/XXnsIFu8Q7r1EAfFFpvlMUmdl7asE8V6ilaeqmiI7bIvGMFbf4cZkQliLjiFkJX56tFHRCNi+rb7WgRuru3/GzPXUq2AvXZvFpFJgik0B72TxVlmCKeBRZq1FvP0UhAH48RJWYJksdEyzh2paMfjX9ZO5Q2SFFrmPw6k2ArdJFC1AYcgceZC84y06RKJ0WiSntUPlEUXgQbQVVWbtQDhjfJXMr/beuroNdT/vsRraLVkAzvhaDXNnHlAJNLQxci+AcLpnzZhxMW+ax7RRtrpXGxRN4cs0lBGUcSkaDybFqMYXwEjXAE8w6fdJRWCIlxctkAW/iNEO4kAG97hI2Qwcw5oU2Ymnv09zyGR+XJE35pJqPulJHExdwanJHvmjH0QF7TNFS82yxS5dKnP954cj3Lu9SWGYWjxQJRmLtOwb+lqqol4VTxG7Ois4uef9/Tpp9skeMZXVeNlpn2wrp6iFcX3uiiVDg9VKkl3ig6UqCiqQSuiIN87RXwUOeHXlCnW3adz3Xei0ziBrwLSql7lBIHGEAlUUNmJ3CrR8IwQtcynGEMKfNIeZ/XK+uNlm9cJIqZf1fzqc8KexlyS9AS0i/kiYZTr4=
2f0c3f3361d3ea4eb9129ed8810699fda7e7a8ee 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlqVb+IACgkQRJMUlPKcZ3OENA//R9HsOUJQB2QZjRgAvqgLn2AMLUvmWb2etTZEc3Nps957Fw1F4kjh6VGfIpWuytfsDx1W8qRx09ikTdb3YteMWCuX8/aFreSPrioYmzrAEcxkZdA7B/jciqU0iXuHiJ9saKk5TR70aNp+iRy0hjAgiYEsVMF9YKHzULOJcHr70x9XVKquubQkwNqJA+/b2JbK2j46wM5nVK/alGSI2kMmEzXmAHQxsvf1OLMvgH8ou/l0xsg/CuFEK299XKfZAbsFEXrjuoWZ1aSa6rTeOWsWli5T+czyyJHI4Eu0Sz/gaR8+MPhJSYes8YjvzEdv32rRMDVOdBq4e+HoTgFt/THYABP6/R1H5fX3Lm4K8u9F9SwJbb/YKRAIrfWDob8ApnGFHk2dyYO20Fskbbg6b1pC7ulDWsufu8lYkQyMlTc3dR6P4eTB6mKO4x+gMG6tIYZ60fiULoEnMJCgegPtevmz+TG1rzdjh3ljiw9Dxz5lNtL+W7sBKKHwhyG0u+bavgmvBMKNL/rdHEM+0yCIz1U6Lb8sVaST1E4zbdm7cWHbSozBij3G0GBSkLFEq7ZLlh8wco9rELRh0Y9fFsWY9j6H/PTOu0GfHrYluFb9WGywHAquQY8j2croRx+MrvTbR1wZrbevPNm9gqk3vgOiDWu7KwxLLqcj+dEQ7tccptVYtbM=
07b0d56d186d7eeef4106137a3eba554959ba0e3 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlyWOo8ACgkQRJMUlPKcZ3O+MQ//c5oeDUvZuFiI4FHZqfIK/59YAciTP+9TQmoWDVSuOdkd9ZYJA7b7DCusqP2TWFEIl9M7i5hTLTMD21xuEQQtfOSP6EXpUw6JNdh/lsJs7EDlFANtwkdEozAQozFKnXbJEV3y9WldEWUlmPFjt4fJQIuG10SU7MTJHcSaQddJCh3I1//F4EvgRe+OqyrFwKekGiFdvfjcIFN3lQmk6K1Sc0MgyIO/VVZm/AQpBi0Dlg0yOl+EDcxxlmeSInbvLceWSP6op35I4dE5YWH1UetjzIsr5AIM15/k3viAKDDefY1EMAzK9b7YAF4BLw0a6XoQu0apvcWaALE/bJzWNSg/QbCm2JAZzk21WLLvR+AELzPfKXrHX3o0h51lpQ4rs7EWKUm43dJPoWkcFNOU+BDsNzffcJgChbRs48ut89DYLiGmSxhRxE77VPbA+klgTGdctOTLd8psseRlGYCuGe8zeota80bV9fUZ9WJZHwNgEWGowKUoTjy6l5k9OH3iQuQX3OXoy78ufRgWDulE7noVTMhXurQ8a0Jf2k/MW9dcnqGVkWitCFKPEvZwVmWyW2AWsdMcBJnFFGzDsNSxWTtCF9XcxieDO1IB8vGwYcb1TwEVuVzvR/wwvc3PgVikF+4Qv2NqdoQc1yn2PkocY2hwXyIZUAwz7erNumlTbeC/JK8=
ebcdb893992d286d363e60f5353d6e1401e7084b 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlybhXAACgkQRJMUlPKcZ3O7pQ//QuNJfBVa7ROaOJOR2H/xr6PRn1Fnc6rr/GCF9cqWrbGP6wNo24dRjcu5LxviqPvzfwRXIMXwVz8L/y61/sm6XcA7VFP4+MBoltfeUOdMbfBdtwEUo3WMBdP1w2q5GgYj8ZY6MawiLEqFba5aua7dokTNBOQM3Yebj+9I16MiWEaRSnuwYPoieHW2Fo6oftcIgs/GCXwT2xYzc0n3FpYAbK7u6sEkpL16EstV0Y/G70+X1/4Mg3GM96S5fl9Zbun47W7/+gT4AQVQjE+UnPNDudObAe+2BaOZLFvEbd7iJBBcqtjpBktuP58IEAb3A3srUCy49LNLWk43lj+PtoslK/U6TShKQ2vAgfd//bbn6ieXFJY8N+wYPpJo1m7zpTiEtS7J7wu6vkGGZlqUAj6MHXZj223CgazhSAlg/XFPs9oz3Y96c33Tnd4jB9iEXNNt5jzCAMImx2huSGgnP0JFAbcniq/ug5tl1VWaracvSuJl7fmf17DbmehsLbvtZBoMlePY7Ssfb5IokfVvptt4zRpRZnjtWfHCjtC6zYhtvXTmXH/bqWwx9MMjOf5WPfZoCMvXfMqdVI15FVbxU15WnqjvdvKUCkdz1aMFzxqc4MXgyvjtB9CvO/8WwBOJ2m2nDdiZfh8/H8SawYqEHgB61FX5xA5aXecgXcjQnqWDDxw=
4877afd51e041eca7749cc46b57fd80aa23815b4 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl7nmREACgkQRJMUlPKcZ3PG1BAAnUl0/nTnQ3CMM3S72DT1JQ1eDxZa14r6r1xEPngU83hNNzmPcnfiMDts+Vz1M3PLxNNOXVVt/MTw04+V9joPhhSWEe8O1pd3lAqTPswL7hhIEbVwZwyFCuAV4iAm+tHKzKLjtjgZfMgij6XylOmw18VBw5R+suoOMclJqeHlJ5m0Mq2wRLDE+RdVCAkulTqhGYjJNQUXMMNPx/cxUo3NHsto9pWL3d1285vBByP6BQSaeYlO012InvJRlQuEkK3lnIyzq6voIc6+tMli0q9iyBz+2GIloBQNAnb6EGaXxqAOBW5NRc+/Oauiu8Yf/6JoFlkAIcPXmGRtxiAiynJImhiTaCFdgdxaXLFzjBvq+tcwVXvvNM52fOZ4Z3QgMDu6EgNWfma0lsg4T3ar2ml2/evuWeLVut5ZmYFHarTFX+/pTVy9nAZK/F5ROJM1prTNYI18PZV4qvULta8spGV2Be0rCkQQubp9RWdKHNGZE70lrX5OnNIwE/D3g2QE04243i0IGBwhlDEpYjqujLyHk8W6XE1CORx0hQ0fUjzKZsRvOB7XyMAFpQUVOhoMFcnk5XHDW6B/U7NAxzqNqO+gbHO/UIeuy/KOVlMNJCmtRL/HYNGZ6SCZbRpyX3d8Ow0sasNfJkZrT6a0Tf6lZktWOxtPkoEDLfuCzudzn4JxGQM=

61
.hgtags
View File

@@ -1,61 +0,0 @@
03f65e461915a940939e4cc689fc89721ffc40de DROPBEAR_0.48.1
0f967bfef5cd0056b7ec60e2305d917e51cbf30d DROPBEAR_0.44
170329dc8ce5dfcf6298e1ad6699f109bf78e73d DROPBEAR_0.51
1dbd2473482f320ea59f76ce961385cb3a0150a9 DROPBEAR_0.46
2098857ab826dd42ae05a9a22c3ce2cc835b9844 DROPBEAR_0.45
36160290a1b27451178be36752ed038840f59cdd LTC_DB_0.46
39d5d58461d6e93337636e69d4cdf184a09c8d24 LTC_1.05
55a99934db873be2e63b5968fb6532e5d9bd02e4 DROPBEAR_0.48
59400faa4b44708c5d0b595e81193bc621e752d3 libtomcrypt-1.05
66087d87c3555c78b47cf01f32bb5a32054c3ceb DROPBEAR_0.44test4
677843bfa734238a67636b461a02c110c462ffaf DROPBEAR_0.44test1
7faae8f46238e23975430876547b8950b4e75481 t:ltc-0.95-orig
8220862baae829ebc762587b99c662480d57bb23 DROPBEAR_0.53
86e0b50a9b588239c3fc9cc9cfe255ef586df17b ltm-0.30-orig
88e0a1ad951add46b795511dc2698e36b4aee922 DROPBEAR_0.44test3
8e94663164c6e106ccc5c9e997dedf6e04d77dd2 LTM_DB_0.44
91fbc376f01084037cd5f6a5bf2e2db4903e8e99 libtommath-0.35
97db060d0ef5f8cf8e67eb602ef037055a185ca9 libtommath-0.40
aa2f51a6b81d33de5e9898a7f27c792a173d9b26 DROPBEAR_0.53.1
ab370c629d363f8c9a3eca512bfa86e362034654 DROPBEAR_0.49
c2ac796b130eeb6fa840873d8c230544c8ec7e4b DROPBEAR_0.44test2
cd1143579f00b0248c79f63ca70efee4a35a57e8 LTC_DB_0.44
ce104c8b0be1ff3f2c2590b7cdc3fd6870c865cd DROPBEAR_0.52
d5faf4814ddbc5abd9e209409bb9e7a4686c8cd7 libtomcrypt-1.16
d7da3b1e15401eb234ec866d5eac992fc4cd5878 t:ltc-0.95-db-merge1
d8254fc979e99560c93ca2cece77a6df31927ea5 LTM_0.35
e109027b9edfb02f0bdf96ec45bb1cd9ad41e7da LTM_DB_0.46
e109027b9edfb02f0bdf96ec45bb1cd9ad41e7da LTM_DB_0.47
e37b160c414cab6466622f63b0c4dcbf6ebc47a9 DROPBEAR_0.47
e430a26064ee86ab79aef372118d6d03b2441996 DROPBEAR_0.50
e5d119ea4c63656bc54ecfd865d04591ac2ed225 LTC_DB_0.47
3f12086c2ef2b9ffe36a822fdb3ff647fcec1831 DROPBEAR_2011.54
d354464b2aa6f6ba0bf44d43bcae5aa798435393 DROPBEAR_2012.55
7faae8f46238e23975430876547b8950b4e75481 t:ltc-0.95-orig
0000000000000000000000000000000000000000 t:ltc-0.95-orig
d7da3b1e15401eb234ec866d5eac992fc4cd5878 t:ltc-0.95-db-merge1
0000000000000000000000000000000000000000 t:ltc-0.95-db-merge1
1b8b2b9d6e94bc3cc5e61b620476ea36cc466e1b DROPBEAR_2013.56
96b8bcb88017815040949a417caa55686271e8a9 DROPBEAR_2013.57
e76614145aea67f66e4a4257685c771efba21aa1 DROPBEAR_2013.58
7b68e581985fd4ea50869f8608ab95cda5d17876 DROPBEAR_2013.59
a50a1dc743317fad9b3737bc68fbca640659bb6d DROPBEAR_2013.60
e894dbc015ba7ff4c3bf897ee20e28ca90c55a16 DROPBEAR_2013.61test
3d1d7d151c0ce3a79da62e86463f5632fa2b144a DROPBEAR_2013.62
2351b2da8e0d08dcc6e64fcc328b53b9630bda68 DROPBEAR_2014.63
0d2d39957c029adb7f4327d37fe6b4900f0736d9 DROPBEAR_2014.64
e9579816f20ea85affc6135e87f8477992808948 DROPBEAR_2014.65
735511a4c761141416ad0e6728989d2dafa55bc2 DROPBEAR_2014.66
cbd674d63cd4f3781464a8d4056a5506c8ae926f DROPBEAR_2015.67
809feaa9408f036734129c77f2b3c7e779d4f099 DROPBEAR_2015.68
1637dbd262124d113e52967df46afd6c715e4fad DROPBEAR_2015.69
79a6ef02307d05cb9dda10465cb5b807baa8f62e DROPBEAR_2015.70
9a944a243f08be6b22d32f166a0690eb4872462b DROPBEAR_2015.71
78b12b6549be08b0bea3da329b2578060a76ca31 DROPBEAR_2016.72
309e1c4a87682b6ca7d80b8555a1db416c3cb7ac DROPBEAR_2016.73
0ed3d2bbf956cb8a9bf0f4b5a86b7dd9688205cb DROPBEAR_2016.74
c31276613181c5cff7854e7ef586ace03424e55e DROPBEAR_2017.75
1c66ca4f3791c82501c88e7637312182c7294978 DROPBEAR_2018.76
6d1bbe7d5fa5827c7eae28bca044d691f7efa785 DROPBEAR_2019.77
009d52ae26d35f3381c801e02318fa9be34be93c DROPBEAR_2019.78
e2e4929d057b09422f2ea4556fb64209aff58161 DROPBEAR_2020.79

View File

@@ -1,72 +0,0 @@
language: c
git:
depth: 3
# use focal which provides libtommath 1.20
dist: focal
matrix:
include:
- name: "plain linux"
compiler: gcc
env: WEXTRAFLAGS=-Werror
- name: "multi binary"
env: MULTI=1 WEXTRAFLAGS=-Werror
- name: "bundled libtom, xenial, no writev()"
# NOWRITEV is unrelated to libtom/xenial, test here to save a job
env: CONFIGURE_FLAGS=--enable-bundled-libtom WEXTRAFLAGS=-Werror NOWRITEV=1
# can use an older distro with bundled libtom
dist: xenial
- name: "linux clang"
os: linux
compiler: clang
env: WEXTRAFLAGS=-Werror
- name: "osx"
os: osx
compiler: clang
# OS X says daemon() and utmp are deprecated
env: WEXTRAFLAGS="-Wno-deprecated-declarations -Werror"
# Note: the fuzzing malloc wrapper doesn't replace free() in system libtomcrypt, so need bundled.
- name: "fuzzing"
env: DO_FUZZ=1 CONFIGURE_FLAGS="--enable-fuzz --disable-harden --enable-bundled-libtom" WEXTRAFLAGS=-Werror LDFLAGS=-fsanitize=address EXTRACFLAGS=-fsanitize=address CXX=clang++
compiler: clang
# container-based builds
addons:
apt:
packages:
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
- zlib1g-dev
- libtomcrypt-dev
- libtommath-dev
- mercurial
before_install:
- if [ "$CC" = "clang" ]; then WEXTRAFLAGS="$WEXTRAFLAGS -Wno-error=incompatible-library-redeclaration" ; fi # workaround
install:
- autoconf
- autoheader
- ./configure $CONFIGURE_FLAGS CFLAGS="-O2 -Wall -Wno-pointer-sign $WEXTRAFLAGS $EXTRACFLAGS" --prefix="$HOME/inst" || (cat config.log; exit 1)
- if [ "$NOWRITEV" = "1" ]; then sed -i -e s/HAVE_WRITEV/DONT_HAVE_WRITEV/ config.h ; fi
- make lint
- make -j3
- test -z $DO_FUZZ || make fuzzstandalone
# avoid concurrent install, osx/freebsd is racey (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208093)
- make install
script:
- ~/inst/bin/dropbearkey -t rsa -f testrsa
- ~/inst/bin/dropbearkey -t dss -f testdss
- ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256
- ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384
- ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521
- ~/inst/bin/dropbearkey -t ed25519 -f tested25519
- test -z $DO_FUZZ || ./fuzzers_test.sh
branches:
only:
- master
- coverity

389
CHANGES
View File

@@ -1,3 +1,370 @@
2024.85 - 25 April 2024
This release fixes build regressions in 2024.84
- Fix build failure when SHA1 is disabled, thanks to Peter Krefting
- Fix build failure when DROPBEAR_CLI_PUBKEY_AUTH disabled, thanks to
Sergey Ponomarev
- Update debian/ directory with changed paths
2024.84 - 4 April 2024
Features and Changes:
Note >> for compatibility/configuration changes
- >> Only use /etc/shadow when a user has :x: as the crypt in /etc/passwd.
This is the documented behaviour of passwd(5) so should be consistent with
other programs. Thanks to Paulo Cabral for the report.
Note that any users without x as the crypt will not be able
to log in with /etc/shadow, in cases were the existing configuration
differs.
- Support -o StrictHostKeyChecking, patch from Sergey Ponomarev
- Support -o BatchMode, from Sergey Ponomarev and Hans Harder
- Support various other -o options compatible with OpenSSH, from
Sergey Ponomarev. Includes -o PasswordAuthentication
- Add dbclient config file support, ~/.ssh/dropbear_config
Thanks to tjkolev
Disabled by default, set #define DROPBEAR_USE_SSH_CONFIG 1
- Add support for unix socket forwarding (destination) on
the server, thanks to WangYi for the implementation
- Add option to bind to interface, from Diederik De Coninck
- Ignore unsupported arguments in dropbearkey, allow running
binary as 'ssh-key'. From Sergey Ponomarev
- Save a public key file on generation with dropbearkey.
-C can be used for a comment, and choose a default key
type (ed25519 first preference).
Thanks to Sergey Ponomarev
- Allow inetd to run in non-syslog modes. Thanks to Laurent Bercot
for the report
- Allow user's own gid in PTY permissions, lets Dropbear work as non-root
even if /dev/pts isn't mounted with gid=5
- src/distrooptions.h can now be used as another config file.
This can be used by distributions for customisations (separate
to the build directory's localoptions.h)
Fixes:
- "dbclient host >> output" would previously overwrite "output", instead of
appending. Thanks for the report from eSotoIoT
- Add "Strict KEX" support. This mitigates a SSH protocol flaw which lets
a MITM attacker silently remove packets immediately after the
first key exchange. At present the flaw does not seem to reduce Dropbear's
security (the only packet affected would be a server-sig-algs extension,
which is used for compatibility not security).
For Dropbear, chacha20-poly1305 is the only affected cipher.
Both sides of the connection must support Strict KEX for it to be used.
The protocol flaw is tracked as CVE-2023-48795, details
at https://terrapin-attack.com . Thanks to the researchers Fabian Bäumer,
Marcus Brinkmann, and Jörg Schwenk. Thanks to OpenSSH for specifying
strict KEX mode.
- Fix blocking while closing forwarded TCP sessions. Noticable
when many connections are being forwarded. Reported and
tested by GektorUA. Github #230
- Don't offer RSA (then fail) if there is no RSA key. Regression in 2020.79
Github #219
- Fix missing response to remote TCP requests when it is disabled.
Patch from Justin Chen. Github #254
- Fix building with DROPBEAR_RSA disabled
- /proc/timer_list is no longer used for entropy, it was a bottleneck.
Thanks to Aleksei Plotnikov for the report.
- Don't unconditionally enable DROPBEAR_DSS
- Make banner reading failure non-fatal
- Fix DROPBEAR_SVR_MULTIUSER. This appears to have been broken since when it
was added in 2019. If you're using this let me know (it might be removed
if I don't hear otherwise). Thanks to davidatrsp
- Fix Y2038 issues
Infrastructure:
- Move source files to src/ subdirectory. Thanks to tjkolev
- Remove more files with "make distclean"
- Add tests for disabled options
2022.83 - 14 November 2022
Features and Changes:
Note >> for compatibility/configuration changes
- >> Disable DROPBEAR_DSS by default
It is only 1024 bit and uses sha1, most distros disable it by default already.
- Added DROPBEAR_RSA_SHA1 option to allow disabling sha1 rsa signatures.
>> RSA with sha1 will be disabled in a future release (rsa keys will continue
to work OK, with sha256 signatures used instead).
- Add option for requiring both password and pubkey (-t)
Patch from Jackkal
- Add 'no-touch-required' and 'verify-required' options for sk keys
Patch from Egor Duda
- >> DROPBEAR_SK_KEYS config option now replaces separate DROPBEAR_SK_ECDSA
and DROPBEAR_SK_ED25519 options.
- Add 'permitopen' option for authorized_keys to restrict forwarded ports
Patch from Tuomas Haikarainen
- >> Added LTM_CFLAGS configure argument to set flags for building
bundled libtommath. This also restores the previous arguments used
in 2020.81 (-O3 -funroll-loops). That gives a big speedup for RSA
key generation, which regressed in 2022.82.
There is a tradeoff with code size, so -Os can be used if required.
https://github.com/mkj/dropbear/issues/174
Reported by David Bernard
- Add '-z' flag to disable setting QoS traffic class. This may be necessary
to work with broken networks or network drivers, exposed after changes to use
AF21 in 2022.82
https://github.com/mkj/dropbear/issues/193
Reported by yuhongwei380, patch from Petr Štetiar
- Allow overriding user shells with COMPAT_USER_SHELLS
Based on a patch from Matt Robinson
- Improve permission error message
Patch from k-kurematsu
- >> Remove HMAC_MD5 entirely
Regression fixes from 2022.82:
- Fix X11 build
- Fix build warning
- Fix compilation when disabling pubkey authentication
Patch from MaxMougg
- Fix MAX_UNAUTH_CLIENTS regression
Reported by ptpt52
- Avoid using slower prime testing in bundled libtomcrypt when DSS is disabled
https://github.com/mkj/dropbear/issues/174
Suggested by Steffen Jaeckel
- Fix Dropbear plugin support
https://github.com/mkj/dropbear/issues/194
Reported by Struan Bartlett
Other fixes:
- Fix long standing incorrect compression size check. Dropbear
(client or server) would erroneously exit with
"bad packet, oversized decompressed"
when receiving a compressed packet of exactly the maximum size.
- Fix missing setsid() removed in 2020.79
https://github.com/mkj/dropbear/issues/180
Reported and debugged by m5jt and David Bernard
- Try keyboard-interactive auth before password, in dbclient.
This was unintentionally changed back in 2013
https://github.com/mkj/dropbear/pull/190
Patch from Michele Giacomoli
- Drain the terminal when reading the fingerprint confirmation response
https://github.com/mkj/dropbear/pull/191
Patch from Michele Giacomoli
- Fix utx wtmp variable typo. This has been wrong for a long time but
only recently became a problem when wtmp was detected.
https://github.com/mkj/dropbear/pull/189
Patch from Michele Giacomoli
- Improve configure test for hardening options.
Fixes building on AIX
https://github.com/mkj/dropbear/issues/158
- Fix debian/dropbear.init newline
From wulei-student
Infrastructure:
- Test off-by-default compile options
- Set -Wundef to catch typos in #if statements
2022.82 - 1 April 2022
Features and Changes:
Note >> for compatibility/configuration changes
- Implemented OpenSSH format private key handling for dropbearconvert.
Keys can be read in OpenSSH format or the old PEM format.
>> Keys are now written in OpenSSH format rather than PEM.
ED25519 support is now correct. DSS keys are still PEM format.
- Use SHA256 for key fingerprints
- >> Reworked -v verbose printing, specifying multiple times will increase
verbosity. -vvvv is equivalent to the old DEBUG_TRACE -v level, it
can be configured at compile time in localoptions.h (see default_options.h)
Lower -v options can be used to check connection progress or algorithm
negotiation.
Thanks to Hans Harder for the implementation
localoptions.h DEBUG_TRACE should be set to 4 for the same result as the
previous DEBUG_TRACE 1.
- Added server support for U2F/FIDO keys (ecdsa-sk and ed25519-sk) in
authorized_keys. no-touch-required option isn't allowed yet.
Thanks to Egor Duda for the implementation
- autoconf output (configure script etc) is now committed to version control.
>> It isn't necessary to run "autoconf" any more on a checkout.
- sha1 will be omitted from the build if KEX/signing/MAC algorithms don't
require it. Instead sha256 is used for random number generation.
See sysoptions.h to see which algorithms require which hashes.
- Set SSH_PUBKEYINFO environment variable based on the authorized_keys
entry used for auth. The first word of the comment after the key is used
(must only have characters a-z A-Z 0-9 .,_-+@)
Patch from Hans Harder, modified by Matt Johnston
- Let dbclient multihop mode be used with '-J'.
Patch from Hans Harder
- Allow home-directory relative paths ~/path for various settings
and command line options.
*_PRIV_FILENAME DROPBEAR_PIDFILE SFTPSERVER_PATH MOTD_FILENAME
Thanks to Begley Brothers Inc
>> The default DROPBEAR_DEFAULT_CLI_AUTHKEY has now changed, it now needs
a tilde prefix.
- LANG environment variable is carried over from the Dropbear server process
From Maxim Kochetkov
- Add /usr/sbin and /sbin to $PATH when logging in as root.
Patch from Raphaël Hertzog
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=903403
- Added client option "-o DisableTrivialAuth". It disallows a server immediately
giving successful authentication (without presenting any password/pubkey prompt).
This avoids a UI confusion issue where it may appear that the user is accepting
a SSH agent prompt from their local machine, but are actually accepting a prompt
sent immediately by the remote server.
CVE-2021-36369 though the description there is a bit confused. It only applies
to Dropbear as a client.
Thanks to Manfred Kaiser from Austrian MilCERT
- Add -q client option to hide remote banner, from Hans Harder
- Add -e option to pass all server environment variables to child processes.
This should be used with caution.
Patch from Roland Vollgraf (github #118)
- >> Use DSCP for QoS traffic classes. Priority (tty) traffic is now set to
AF21 "interactive". Previously TOS classes were used, they are not used by
modern traffic classifiers. Non-tty traffic is left at default priority.
- >> Disable dh-group1 key exchange by default. It has been disabled server
side by default since 2018.
- >> Removed Twofish cipher
Fixes:
- Fix flushing channel data when pty was allocated (github #85)
Data wasn't completely transmitted at channel close.
Reported and initial patch thanks to Yousong Zhou
- Dropbear now re-executes itself rather than just forking for each connection
(only on Linux). This allows ASLR to randomise address space for each
connection as a security mitigation. It should not have any visible impact
- if there are any performance impacts in the wild please report it.
- Check authorized_keys permissions as the user, fixes NFS squash root.
Patch from Chris Dragan (github #107)
- A missing home directory is now non-fatal, starting in / instead
- Fixed IPv6 [address]:port parsing for dbclient -b
Reported by Fabio Molinari
- Improve error logging so that they are logged on the server rather than being
sent to the client over the connection
- Max window size is increased to 10MB, more graceful fallback if it's invalid.
- Fix correctness of Dropbear's handling of global requests.
Patch from Dirkjan Bussink
- Fix some small bugs found by fuzzers, null pointer dereference crash and leaks
(post authentication)
- $HOME variable is used before /etc/passwd when expanding paths such as
~/.ssh/id_dropbear (for the client). Patch from Matt Robinson
- C89 build fixes from Guillaume Picquet
Infrastructure:
- Improvements to fuzzers. Added post-auth fuzzer, and a mutator that can
handle the structure of SSH packet streams. Added cifuzz to run on commits
and pull requests.
Thanks to OSS-Fuzz for the tools/clusters and reward funding.
- Dropbear source tarballs generated by release.sh are now reproducible from a
Git or Mercurial checkout, they will be identical on any system. Tested
on ubuntu and macos.
- Added some integration testing using pytest. Currently this has tests
for various channel handling edge cases, ASLR fork randomisation,
dropbearconvert, and SSH_PUBKEYINFO
- Set up github actions. This runs the pytest suite and other checks.
- build matrix includes c89, dropbearmulti, bundled libtom, macos, DEBUG_TRACE
- test for configure script regeneration
- build a tarball for external reproducibility
2020.81 - 29 October 2020
- Fix regression in 2020.79 which prevented connecting with some SSH
implementations. Increase MAX_PROPOSED_ALGO to 50, and print a log
message if the limit is hit. This fixes interoperability with sshj
library (used by PyCharm), and GoAnywhere.
Reported by Pirmin Walthert and Piotr Jurkiewicz
- Fix building with non-GCC compilers, reported by Kazuo Kuroi
- Fix potential long delay in dbclient, found by OSS Fuzz
- Fix null pointer dereference crash, found by OSS Fuzz
- libtommath now uses the same random source as Dropbear (in 2020.79
and 2020.80 used getrandom() separately)
- Some fuzzing improvements, start of a dbclient fuzzer
2020.80 - 26 June 2020
- Don't block authorized_keys logins with no-X11-forwarding or no-agent-forwarding
@@ -215,7 +582,7 @@
dropbear is running with -a (Allow connections to forwarded ports from any host)
This could potentially allow arbitrary code execution as root by an authenticated user.
Affects versions 2013.56 to 2016.74. Thanks to Mark Shepard for reporting the crash.
CVE-2017-9078 https://secure.ucc.asn.au/hg/dropbear/rev/c8114a48837c
CVE-2017-9078 https://hg.ucc.asn.au/dropbear/rev/c8114a48837c
- Security: Fix information disclosure with ~/.ssh/authorized_keys symlink.
Dropbear parsed authorized_keys as root, even if it were a symlink. The fix
@@ -227,7 +594,7 @@
contents of that file.
This information disclosure is to an already authenticated user.
Thanks to Jann Horn of Google Project Zero for reporting this.
CVE-2017-9079 https://secure.ucc.asn.au/hg/dropbear/rev/0d889b068123
CVE-2017-9079 https://hg.ucc.asn.au/dropbear/rev/0d889b068123
- Generate hostkeys with dropbearkey atomically and flush to disk with fsync
Thanks to Andrei Gherzan for a patch
@@ -247,23 +614,23 @@
run arbitrary code as the dbclient user. This could be a problem if scripts
or webpages pass untrusted input to the dbclient program.
CVE-2016-7406
https://secure.ucc.asn.au/hg/dropbear/rev/b66a483f3dcb
https://hg.ucc.asn.au/dropbear/rev/b66a483f3dcb
- Security: dropbearconvert import of OpenSSH keys could run arbitrary code as
the local dropbearconvert user when parsing malicious key files
CVE-2016-7407
https://secure.ucc.asn.au/hg/dropbear/rev/34e6127ef02e
https://hg.ucc.asn.au/dropbear/rev/34e6127ef02e
- Security: dbclient could run arbitrary code as the local dbclient user if
particular -m or -c arguments are provided. This could be an issue where
dbclient is used in scripts.
CVE-2016-7408
https://secure.ucc.asn.au/hg/dropbear/rev/eed9376a4ad6
https://hg.ucc.asn.au/dropbear/rev/eed9376a4ad6
- Security: dbclient or dropbear server could expose process memory to the
running user if compiled with DEBUG_TRACE and running with -v
CVE-2016-7409
https://secure.ucc.asn.au/hg/dropbear/rev/6a14b1f6dc04
https://hg.ucc.asn.au/dropbear/rev/6a14b1f6dc04
The security issues were reported by an anonymous researcher working with
Beyond Security's SecuriTeam Secure Disclosure www.beyondsecurity.com/ssd.html
@@ -309,7 +676,7 @@
- Validate X11 forwarding input. Could allow bypass of authorized_keys command= restrictions,
found by github.com/tintinweb. Thanks for Damien Miller for a patch. CVE-2016-3116
https://secure.ucc.asn.au/hg/dropbear/rev/a3e8389e01ff
https://hg.ucc.asn.au/dropbear/rev/a3e8389e01ff
2015.71 - 3 December 2015
@@ -590,11 +957,11 @@ kernels, from Steve Dover
- Limit the size of decompressed payloads, avoids memory exhaustion denial
of service
Thanks to Logan Lamb for reporting and investigating it. CVE-2013-4421
https://secure.ucc.asn.au/hg/dropbear/rev/0bf76f54de6f
https://hg.ucc.asn.au/dropbear/rev/0bf76f54de6f
- Avoid disclosing existence of valid users through inconsistent delays
Thanks to Logan Lamb for reporting. CVE-2013-4434
https://secure.ucc.asn.au/hg/dropbear/rev/d7784616409a
https://hg.ucc.asn.au/dropbear/rev/d7784616409a
- Update config.guess and config.sub for newer architectures
@@ -697,7 +1064,7 @@ though probably will be soon
This bug affects releases 0.52 onwards. Ref CVE-2012-0920.
Thanks to Danny Fullerton of Mantor Organization for reporting
the bug.
https://secure.ucc.asn.au/hg/dropbear/rev/818108bf7749
https://hg.ucc.asn.au/dropbear/rev/818108bf7749
- Compile fix, only apply IPV6 socket options if they are available in headers
Thanks to Gustavo Zacarias for the patch
@@ -741,7 +1108,7 @@ though probably will be soon
- New version numbering scheme.
Source repository has now migrated to Mercurial at
https://secure.ucc.asn.au/hg/dropbear/graph/default
https://hg.ucc.asn.au/dropbear/graph/default
0.53.1 - Wednesday 2 March 2011

View File

@@ -1,75 +1,88 @@
# Developer Notes
## Developer Notes
## Building
#### Building
See [INSTALL](INSTALL) for build instructions.
[SMALL](SMALL) has hints for building smaller binaries, also see comments
in default_options.h.
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).
## Debug printing
Debug symbols can be generated by adding `-g` to `CFLAGS` environment variable.
```
export CFLAGS="$CFLAGS -g"
```
Set `#define DEBUG_TRACE 1` in 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.
#### 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.
## Random sources
Following are generated files in the format `<target>: <generator>(<source>)`
```
- configure: autoconf(configure.ac)
- src/config.h.in: autoheader(configure.ac)
- src/config.h: configure(src/config.h.in)
- Makefile: configure(Makefile.in)
- default_options_guard.h: make(default_options.h)
```
Although generated, the first two files are checked in as they change very infrequently.
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.
#### Debug printing
## Algorithms
Set `#define DEBUG_TRACE 1` in [localoptions.h](./localoptions.h) to enable a `-v` verbose option for dropbear and dbclient.
Higher numbers can be used to allow increased debug levels, with `-v` argument repeated.
Default algorithm lists are specified in [common-algo.c](common-algo.c).
They are in priority order, the client's first matching choice is used
(see rfc4253).
Dropbear client has `-c` and `-m` arguments to choose which are enabled at
runtime (doesn't work for server as of June 2020).
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.
Enabling/disabling algorithms is done in [localoptions.h](localoptions.h),
see [default_options.h](default_options.h).
#### Random sources
## Style
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.
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.
#### Algorithms
Default algorithm lists are specified in [common-algo.c](./src/common-algo.c). They are in priority order, the client's first matching choice is used (see [rfc4253](https://www.rfc-editor.org/rfc/rfc4253.html)). Dropbear client has `-c` and `-m` arguments to choose which are enabled at runtime (doesn't work for server as of June 2020).
Enabling/disabling algorithms is done in [localoptions.h](./localoptions.h), see [default_options.h](./src/default_options.h).
#### Style
In general please conform to the current style of the file you are editing.
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](buffer.h) should be used.
Add a single space between flow control statements and their open parenthesis:
```
if (...
for (...
switch (...
etc.
```
Use `snake_case` for variable and function names.
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 `//`.
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.
Pointer variables should be initialised to NULL - it can reduce the severity of bugs.
## Third party code
#### Third party code
Libtomcrypt and libtommath are periodically synced from upstream, so
avoid making changes to that code which will need to be maintained.
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
#### 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). 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.
#### 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.

14
Dockerfile Normal file
View File

@@ -0,0 +1,14 @@
FROM alpine:3.17.1 AS builder
RUN apk add --no-cache alpine-sdk
RUN apk add --no-cache \
musl-dev \
zlib-dev \
tar \
bzip2 \
bash
RUN mkdir -p /root/dropbear/
WORKDIR /root/dropbear/
ENTRYPOINT ["bash"]

View File

@@ -1,77 +1,55 @@
# Fuzzing Dropbear
## 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
#### 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()`](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
#### malloc Wrapper
Dropbear normally uses a [`m_malloc()`](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)`](dbmalloc.c) 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
#### 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-wrapfd.c) will read from the
fuzzer input that has been set up with `wrapfd_add()`. `write()` output is
currently discarded.
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
#### Encryption and Randomness
When running in fuzzing mode Dropbear uses a [fixed seed](dbrandom.c#L185)
every time so that failures can be reproduced.
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](packet.c).
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
#### Fuzzers
Current fuzzers are
Current fuzzers are:
- [fuzzer-preauth](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](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](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](fuzzer-pubkey.c) - test parsing of an `authorized_keys` line.
- [fuzzer-kexdh](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](fuzzer-kexecdh.c) - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh.
* [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](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-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.

93
INSTALL
View File

@@ -1,93 +0,0 @@
Basic Dropbear build instructions:
- Edit 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.
- If using a Mercurial or Git checkout, "autoconf; autoheader"
- Configure for your system:
./configure (optionally with --disable-zlib or --disable-syslog,
or --help for other options)
- Compile:
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
- Optionally install, or copy the binaries another way
make install (/usr/local/bin is usual default):
or
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
(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 has some notes on other developer topics, including debugging.
See MULTI for instructions on making all-in-one binaries.
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
Binaries can be stripped with "make strip"
============================================================================
If you're compiling for a 386-class CPU, you will probably need to add
CFLAGS=-DLTC_NO_BSWAP so that libtomcrypt doesn't use 486+ instructions.
============================================================================
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.
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 MD5, by editing localoptions.h
It is possible to compile zlib in, by copying zlib.h and zconf.h into a
subdirectory (ie zlibincludes), and
export CFLAGS="-Izlibincludes -I../zlibincludes"
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.
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.
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.

97
INSTALL.md Normal file
View File

@@ -0,0 +1,97 @@
## Basic Dropbear Build Instructions
### Build Options
Custom build options can be configured in `localoptions.h` in the build directory. This is a local file, not checked in to git.
Available options are described in [`src/default_options.h`](src/default_options.h)
Options include available cryptographic algorithms, SSH features, and file paths.
In addition, a `src/distrooptions.h` file will be used if it exists, for distributions to set configuration options.
### Configure for your system
```
./configure
```
Optionally with `--disable-zlib` or `--disable-syslog`.
Or `--help` for other options.
You'll need to first run `autoconf; autoheader` if you edit `configure.ac`.
### Compile:
```
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
```
Optionally install, or copy the binaries another way:
```
make install
```
`/usr/local/bin` is usual default.
or
```
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
```
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.
[DEVELOPING.md](DEVELOPING.md) has some notes on other developer topics, including debugging.
See [MULTI.md](MULTI.md) for instructions on making all-in-one binaries.
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`.
Binaries can be stripped with `make strip`.
> **Note**
> If you're compiling for a 386-class CPU, you will probably need to add CFLAGS=-DLTC_NO_BSWAP so that libtomcrypt doesn't use 486+ instructions.
## 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.
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).
It is possible to compile zlib in, by copying zlib.h and zconf.h into a subdirectory (ie zlibincludes), and
```
export CFLAGS="-Izlibincludes -I../zlibincludes"
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.
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.
* 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.

22
MULTI
View File

@@ -1,22 +0,0 @@
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 the multi-binary, first "make clean" (if you've compiled
previously), then
make PROGRAMS="programs you want here" MULTI=1
To use the binary, symlink it from the desired executable:
ln -s dropbearmulti dropbear
ln -s dropbearmulti dbclient
etc
then execute as normal:
./dropbear <options here>

25
MULTI.md Normal file
View File

@@ -0,0 +1,25 @@
## 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 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
```
etc.
Then execute as normal:
```
./dropbear <options here>
```

View File

@@ -12,67 +12,81 @@ ifndef PROGRAMS
PROGRAMS=dropbear dbclient dropbearkey dropbearconvert
endif
srcdir=@srcdir@/src
VPATH=@srcdir@/src
STATIC_LTC=libtomcrypt/libtomcrypt.a
STATIC_LTM=libtommath/libtommath.a
LIBTOM_LIBS=@LIBTOM_LIBS@
ifeq (@BUNDLED_LIBTOM@, 1)
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_CLEAN=ltc-clean ltm-clean
CFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_CLEAN=ltc-clean ltm-clean
CPPFLAGS+=-I$(srcdir)/../libtomcrypt/src/headers/
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
endif
OPTION_HEADERS = default_options_guard.h sysoptions.h
ifneq ($(wildcard localoptions.h),)
CFLAGS+=-DLOCALOPTIONS_H_EXISTS
OPTION_HEADERS += localoptions.h
ifneq ($(wildcard ./localoptions.h),)
CPPFLAGS+=-DLOCALOPTIONS_H_EXISTS
endif
ifneq ($(wildcard $(srcdir)/distrooptions.h),)
CPPFLAGS+=-DDISTROOPTIONS_H_EXISTS
endif
COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
OBJ_DIR=./obj
MAN_DIR=@srcdir@/manpages
_COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
dss.o bignum.o \
signkey.o rsa.o dbrandom.o \
queue.o \
atomicio.o compat.o fake-rfc2553.o \
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
curve25519.o ed25519.o \
ltc_prng.o ecc.o ecdsa.o sk-ecdsa.o crypto_desc.o \
curve25519.o ed25519.o sk-ed25519.o \
dbmalloc.o \
gensignkey.o gendss.o genrsa.o gened25519.o
COMMONOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_COMMONOBJS))
SVROBJS=svr-kex.o svr-auth.o sshpty.o \
_SVROBJS=svr-kex.o svr-auth.o sshpty.o \
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\
svr-tcpfwd.o svr-authpam.o
SVROBJS = $(patsubst %,$(OBJ_DIR)/%,$(_SVROBJS))
CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
_CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
cli-session.o cli-runopts.o cli-chansession.o \
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \
cli-agentfwd.o
cli-agentfwd.o cli-readconf.o
CLIOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_CLIOBJS))
CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
common-channel.o common-chansession.o termcodes.o loginrec.o \
tcp-accept.o listener.o process-packet.o dh_groups.o \
common-runopts.o circbuffer.o list.o netio.o chachapoly.o gcm.o
_CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
common-channel.o common-chansession.o termcodes.o loginrec.o \
tcp-accept.o listener.o process-packet.o dh_groups.o \
common-runopts.o circbuffer.o list.o netio.o chachapoly.o gcm.o
CLISVROBJS = $(patsubst %,$(OBJ_DIR)/%,$(_CLISVROBJS))
KEYOBJS=dropbearkey.o
_KEYOBJS=dropbearkey.o
KEYOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_KEYOBJS))
CONVERTOBJS=dropbearconvert.o keyimport.o
_CONVERTOBJS=dropbearconvert.o keyimport.o signkey_ossh.o
CONVERTOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_CONVERTOBJS))
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
_SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
SCPOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_SCPOBJS))
ifeq (@DROPBEAR_FUZZ@, 1)
allobjs = $(COMMONOBJS) fuzz-common.o fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@
allobjs:=$(subst svr-main.o, ,$(allobjs))
allobjs:=$(subst cli-main.o, ,$(allobjs))
allobjs:=$(sort $(allobjs))
allobjs = $(COMMONOBJS) fuzz/fuzz-common.o fuzz/fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@
allobjs:=$(subst $(OBJ_DIR)/svr-main.o, ,$(allobjs))
allobjs:=$(subst $(OBJ_DIR)/cli-main.o, ,$(allobjs))
dropbearobjs=$(allobjs) svr-main.o
dbclientobjs=$(allobjs) cli-main.o
dropbearobjs=$(allobjs) $(OBJ_DIR)/svr-main.o
dbclientobjs=$(allobjs) $(OBJ_DIR)/cli-main.o
dropbearkeyobjs=$(allobjs) $(KEYOBJS)
dropbearconvertobjs=$(allobjs) $(CONVERTOBJS)
# CXX only set when fuzzing
CXX=@CXX@
FUZZ_CLEAN=fuzz-clean
else
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
@@ -82,17 +96,14 @@ else
endif
ifeq (@DROPBEAR_PLUGIN@, 1)
# rdynamic makes all the global symbols of dropbear available to all the loaded shared libraries
# this allow a plugin to reuse existing crypto/utilities like base64_decode/base64_encode without
# the need to rewrite them.
PLUGIN_LIBS=-ldl -rdynamic
# rdynamic makes all the global symbols of dropbear available to all the loaded shared libraries
# this allow a plugin to reuse existing crypto/utilities like base64_decode/base64_encode without
# the need to rewrite them.
PLUGIN_LIBS=-ldl -rdynamic
else
PLUGIN_LIBS=
PLUGIN_LIBS=
endif
VPATH=@srcdir@
srcdir=@srcdir@
prefix=@prefix@
exec_prefix=@exec_prefix@
datarootdir = @datarootdir@
@@ -107,8 +118,8 @@ AR=@AR@
RANLIB=@RANLIB@
STRIP=@STRIP@
INSTALL=@INSTALL@
CPPFLAGS=@CPPFLAGS@
CFLAGS+=-I. -I$(srcdir) $(CPPFLAGS) @CFLAGS@
CPPFLAGS+=@CPPFLAGS@ -I. -I$(srcdir)
CFLAGS+=@CFLAGS@
LIBS+=@LIBS@
LDFLAGS=@LDFLAGS@
@@ -119,15 +130,16 @@ STATIC=@STATIC@
# whether we're building client, server, or both for the common objects.
# evilness so we detect 'dropbear' by itself as a word
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdropbearZ, Z$(prog)Z))))
CFLAGS+= -DDROPBEAR_SERVER
CPPFLAGS+= -DDROPBEAR_SERVER
endif
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdbclientZ, Z$(prog)Z))))
CFLAGS+= -DDROPBEAR_CLIENT
CPPFLAGS+= -DDROPBEAR_CLIENT
endif
# these are exported so that libtomcrypt's makefile will use them
export CC
export CFLAGS
export CPPFLAGS
export RANLIB AR STRIP
ifeq ($(STATIC), 1)
@@ -142,21 +154,30 @@ endif
# for the scp progress meter. The -D doesn't affect anything else.
ifeq ($(SCPPROGRESS), 1)
CFLAGS+=-DPROGRESS_METER
CPPFLAGS+=-DPROGRESS_METER
endif
all: $(TARGETS)
# for simplicity assume all source depends on all headers
HEADERS=$(wildcard $(srcdir)/*.h *.h) $(OPTION_HEADERS)
%.o : %.c $(HEADERS)
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
HEADERS=$(wildcard $(srcdir)/*.h *.h) default_options_guard.h
default_options_guard.h: default_options.h
$(OBJ_DIR):
mkdir -p $@
$(OBJ_DIR)/%.o: $(srcdir)/%.c $(HEADERS) | $(OBJ_DIR)
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ -c
fuzz/%.o: $(srcdir)/../fuzz/%.c $(HEADERS)
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ -c
default_options_guard.h: $(srcdir)/default_options.h
@echo Creating $@
@printf "/*\n > > > Do not edit this file (default_options_guard.h) < < <\nGenerated from "$^"\nLocal customisation goes in localoptions.h\n*/\n\n" > $@.tmp
@$(srcdir)/ifndef_wrapper.sh < $^ >> $@.tmp
@mv $@.tmp $@
mv -v $@.tmp $@
pwd
ls -l $@
strip: $(TARGETS)
$(STRIP) $(addsuffix $(EXEEXT), $(TARGETS))
@@ -166,31 +187,31 @@ install: $(addprefix inst_, $(TARGETS))
insmultidropbear: dropbearmulti$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(sbindir)
-rm -f $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
$(INSTALL) -m 644 $(MAN_DIR)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
insmulti%: dropbearmulti$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(bindir)
-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
if test -e $(MAN_DIR)/$*.1; then $(INSTALL) -m 644 $(MAN_DIR)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
# dropbear should go in sbin, so it needs a separate rule
inst_dropbear: dropbear
$(INSTALL) -d $(DESTDIR)$(sbindir)
$(INSTALL) dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
$(INSTALL) -m 644 $(MAN_DIR)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
inst_%: %
$(INSTALL) -d $(DESTDIR)$(bindir)
$(INSTALL) $*$(EXEEXT) $(DESTDIR)$(bindir)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
if test -e $(MAN_DIR)/$*.1; then $(INSTALL) -m 644 $(MAN_DIR)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
inst_dropbearmulti: $(addprefix insmulti, $(PROGRAMS))
inst_dropbearmulti: $(addprefix insmulti, $(PROGRAMS))
# for some reason the rule further down doesn't like $($@objs) as a prereq.
dropbear: $(dropbearobjs)
@@ -215,8 +236,8 @@ scp: $(SCPOBJS) $(HEADERS) Makefile
# multi-binary compilation.
MULTIOBJS=
ifeq ($(MULTI),1)
MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
MULTIOBJS=$(OBJ_DIR)/dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
CPPFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
endif
dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile
@@ -230,13 +251,13 @@ link%:
-rm -f $*$(EXEEXT)
-ln -s dropbearmulti$(EXEEXT) $*$(EXEEXT)
$(STATIC_LTC): $(OPTION_HEADERS)
$(STATIC_LTC): $(HEADERS)
$(MAKE) -C libtomcrypt
$(STATIC_LTM): $(OPTION_HEADERS)
$(STATIC_LTM): $(HEADERS)
$(MAKE) -C libtommath
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint check
ltc-clean:
$(MAKE) -C libtomcrypt clean
@@ -247,16 +268,17 @@ ltm-clean:
sizes: dropbear
objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn
clean: $(LIBTOM_CLEAN) thisclean
clean: $(LIBTOM_CLEAN) $(FUZZ_CLEAN) thisclean
thisclean:
-rm -f dropbear$(EXEEXT) dbclient$(EXEEXT) dropbearkey$(EXEEXT) \
dropbearconvert$(EXEEXT) scp$(EXEEXT) scp-progress$(EXEEXT) \
dropbearmulti$(EXEEXT) *.o *.da *.bb *.bbg *.prof
dropbearmulti$(EXEEXT) *.o *.da *.bb *.bbg *.prof \
$(OBJ_DIR)/*
distclean: clean tidy
-rm -f config.h
-rm -f Makefile
-rm -f src/config.h config.status config.log
-rm -f Makefile test/Makefile
-rm -f default_options_guard.h
tidy:
@@ -265,56 +287,52 @@ tidy:
lint:
cd $(srcdir); ./dropbear_lint.sh
check: lint
make -C test
## Fuzzing targets
# list of fuzz targets
FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519
FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths \
fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths \
fuzzer-postauth_nomaths fuzzer-cliconf
FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \
fuzz/fuzz-sshpacketmutator.o
list-fuzz-targets:
@echo $(FUZZ_TARGETS)
# fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs
fuzzstandalone: FUZZLIB=fuzz-harness.o
fuzzstandalone: fuzz-harness.o fuzz-targets
fuzzstandalone: FUZZLIB=fuzz/fuzz-harness.o
fuzzstandalone: fuzz/fuzz-harness.o fuzz-targets
# exclude svr-main.o to avoid duplicate main
svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs))
fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) fuzz-common.o
# build all the fuzzers. This will require fail to link unless built with
# make fuzz-targets FUZZLIB=-lFuzzer.a
# or similar - the library provides main().
# Build all the fuzzers. Usually like
# make fuzz-targets FUZZLIB=-lFuzzer.a
# the library provides main(). Otherwise
# make fuzzstandalone
# provides a main in fuzz-harness.c
fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
fuzzer-preauth: fuzzer-preauth.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
$(FUZZ_TARGETS): $(LIBTOM_DEPS) $(allobjs) $(FUZZ_OBJS)
$(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
# fuzzers that use the custom mutator - these expect a SSH network stream
MUTATOR_FUZZERS=fuzzer-client fuzzer-client_nomaths \
fuzzer-preauth fuzzer-preauth_nomaths fuzzer-postauth_nomaths
fuzzer-pubkey: fuzzer-pubkey.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-verify: fuzzer-verify.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-kexdh: fuzzer-kexdh.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-kexecdh: fuzzer-kexecdh.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-kexcurve25519: fuzzer-kexcurve25519.o fuzz-harness.o
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
# Skip custom mutators for -fsanitize-memory since libfuzzer doesn't initialise memory
# Pending fix for it https://github.com/google/oss-fuzz/issues/4605
ifeq (,$(findstring fsanitize=memory, $(CFLAGS)))
$(MUTATOR_FUZZERS): allobjs += fuzz/fuzz-sshpacketmutator.o
endif
fuzzer-%.options: Makefile
echo "[libfuzzer]" > $@
echo "max_len = 50000" >> $@
# run this to update hardcoded hostkeys for for fuzzing.
# run this to update hardcoded hostkeys for for fuzzing.
# hostkeys.c is checked in to hg.
fuzz-hostkeys:
dropbearkey -t rsa -f keyr
@@ -326,3 +344,6 @@ fuzz-hostkeys:
/usr/bin/xxd -i -a keye >> hostkeys.c
/usr/bin/xxd -i -a keyd >> hostkeys.c
/usr/bin/xxd -i -a keyed25519 >> hostkeys.c
fuzz-clean:
-rm -f fuzz/*.o $(FUZZ_TARGETS) $(FUZZER_OPTIONS)

79
README
View File

@@ -1,79 +0,0 @@
This is Dropbear, a smallish SSH server and client.
https://matt.ucc.asn.au/dropbear/dropbear.html
INSTALL has compilation instructions.
MULTI has instructions on making a multi-purpose binary (ie a single binary
which performs multiple tasks, to save disk space)
SMALL has some tips on creating small binaries.
Please contact me if you have any questions/bugs found/features/ideas/comments etc :)
There is also a mailing list http://lists.ucc.gu.uwa.edu.au/mailman/listinfo/dropbear
Matt Johnston
matt@ucc.asn.au
In the absence of detailed documentation, some notes follow:
============================================================================
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:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwVa6M6cGVmUcLl2cFzkxEoJd06Ub4bVDsYrWvXhvUV+ZAM9uGuewZBDoAqNKJxoIn0Hyd0Nk/yU99UVv6NWV/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.
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.
If you have an OpenSSH-style private key ~/.ssh/id_rsa, you need to do:
dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_rsa.db
dbclient -i ~/.ssh/id_rsa.db <hostname>
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.
============================================================================
To run the server, you need to generate server keys, this is one-off:
./dropbearkey -t rsa -f dropbear_rsa_host_key
./dropbearkey -t dss -f dropbear_dss_host_key
./dropbearkey -t ecdsa -f dropbear_ecdsa_host_key
./dropbearkey -t ed25519 -f dropbear_ed25519_host_key
or alternatively convert OpenSSH keys to Dropbear:
./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.
============================================================================
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.

84
README.md Normal file
View File

@@ -0,0 +1,84 @@
## Dropbear SSH
A smallish SSH server and client
https://matt.ucc.asn.au/dropbear/dropbear.html
[INSTALL.md](INSTALL.md) has compilation instructions.
[MULTI.md](MULTI.md) has instructions on making a multi-purpose binary (ie a single binary which performs multiple tasks, to save disk space).
[SMALL.md](SMALL.md) has some tips on creating small binaries.
A mirror of the Dropbear website and tarballs is available at https://dropbear.nl/mirror/.
Please contact me if you have any questions/bugs found/features/ideas/comments etc
There is also a mailing list https://lists.ucc.asn.au/mailman/listinfo/dropbear
Matt Johnston
matt@ucc.asn.au
### In the absence of detailed documentation, some notes follow
----
#### 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:
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.
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.
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 <hostname>
```
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
./dropbearkey -t ed25519 -f dropbear_ed25519_host_key
```
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.
----
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.

53
SMALL
View File

@@ -1,53 +0,0 @@
Tips for a small system:
If you only want server functionality (for example), compile with
make PROGRAMS=dropbear
rather than just
make dropbear
so that client functionality in shared portions of Dropbear won't be included.
The same applies if you are compiling just a client.
---
The following are set in options.h:
- You can safely disable blowfish and twofish ciphers, and MD5 hmac, without
affecting interoperability
- If you're compiling statically, you can turn off host lookups
- You can disable either password or public-key authentication, though note
that the IETF draft states that pubkey authentication is required.
- Similarly with DSS and RSA, you can disable one of these if you know that
all clients will be able to support a particular one. The IETF draft
states that DSS is required, however you may prefer to use RSA.
DON'T disable either of these on systems where you aren't 100% sure about
who will be connecting and what clients they will be using.
- Disabling the MOTD code and SFTP-SERVER may save a small amount of codesize
- You can disable x11, tcp and agent forwarding as desired. None of these are
essential, although agent-forwarding is often useful even on firewall boxes.
---
If you are compiling statically, you may want to disable zlib, as it will use
a few tens of kB of binary-size (./configure --disable-zlib).
You can create a combined binary, see the file MULTI, 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:
LDFLAGS=-Wl,--gc-sections
CFLAGS="-ffunction-sections -fdata-sections"
You can also experiment with optimisation flags such as -Os, note that in some
cases these flags actually seem to increase size, so experiment before
deciding.
Of course using small C libraries such as uClibc and dietlibc can also help.
If you have any queries, mail me and I'll see if I can help.

59
SMALL.md Normal file
View File

@@ -0,0 +1,59 @@
## Tips for a small system
If you only want server functionality, compile with
```
make PROGRAMS=dropbear
```
rather than just
```
make dropbear
```
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.
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
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).
---
If you are compiling statically, you may want to disable zlib, as it will use a few tens of kB of binary size
```
./configure --disable-zlib
```
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:
```
LDFLAGS=-Wl,--gc-sections
CFLAGS="-ffunction-sections -fdata-sections"
```
You can also experiment with optimisation flags such as `-Os`. Note that in some cases these flags actually seem to increase size, so experiment before
deciding.
Of course using small C libraries such as musl can also help.
---
Libtommath has its own default `CFLAGS` to improve speed. You can use
```
./configure LTM_CFLAGS=-Os
```
to reduce size at the expense of speed.
If you have any queries, mail me and I'll see if I can help.

View File

@@ -0,0 +1,21 @@
FROM nvidia/cuda:11.1.1-cudnn8-devel-ubuntu18.04
# use an older system (18.04) to avoid opencv incompatibility (issue#3524)
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y \
python3-opencv ca-certificates python3-dev git wget sudo ninja-build
RUN ln -sv /usr/bin/python3 /usr/bin/python
# create a non-root user
ARG USER_ID=1000
RUN useradd -m --no-log-init --system --uid ${USER_ID} appuser -g sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER appuser
WORKDIR /home/appuser
ENV PATH="/home/appuser/.local/bin:${PATH}"
RUN wget https://bootstrap.pypa.io/pip/3.6/get-pip.py && \
python3 get-pip.py --user && \
rm get-pip.py

10
build.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/bash
docker build -t dropbearbuild -f Dockerfile .
docker run --rm -t -v $(pwd):/root/dropbear dropbearbuild -c "./configure --disable-utmp --disable-wtmp --disable-lastlog --disable-zlib --disable-syslog --enable-static --disable-harden && make clean && make -j4 MULTI=1 PROGRAMS=\"dropbear dropbearconvert dropbearkey\" && mv dropbearmulti dropbearmulti_ && make clean && mv dropbearmulti_ dropbearmulti"
docker image rm dropbearbuild
mkdir build
cp dropbearmulti ./build

10009
configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -5,9 +5,8 @@
# of the platform checks have been taken straight from OpenSSH's configure.ac
# Huge thanks to them for dealing with the horrible platform-specifics :)
AC_PREREQ(2.59)
AC_PREREQ([2.59])
AC_INIT
AC_CONFIG_SRCDIR(buffer.c)
# Record which revision is being built
if test -s "`which hg`" && test -d "$srcdir/.hg"; then
@@ -16,21 +15,22 @@ if test -s "`which hg`" && test -d "$srcdir/.hg"; then
fi
ORIGCFLAGS="$CFLAGS"
LATE_CFLAGS=""
# Checks for programs.
AC_PROG_CC
if test -z "$LD" ; then
LD=$CC
fi
AC_SUBST(LD)
AC_SUBST(LD)
AC_DEFUN(DB_TRYADDCFLAGS,
AC_DEFUN(DB_TRYADDCFLAGS,
[{
OLDFLAGS="$CFLAGS"
TESTFLAGS="$1"
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
CFLAGS="$TESTFLAGS $CFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDFLAGS" ]
)
}])
@@ -41,12 +41,28 @@ if test -z "$ORIGCFLAGS" && test "$GCC" = "yes"; then
CFLAGS="-Os -W -Wall"
fi
# LTM_CFLAGS is given to ./configure by the user,
# DROPBEAR_LTM_CFLAGS is substituted in the LTM Makefile.in
DROPBEAR_LTM_CFLAGS="$LTM_CFLAGS"
if test -z "$DROPBEAR_LTM_CFLAGS"; then
DROPBEAR_LTM_CFLAGS="-O3 -funroll-loops -fomit-frame-pointer"
fi
AC_MSG_NOTICE(Setting LTM_CFLAGS to $DROPBEAR_LTM_CFLAGS)
AC_ARG_VAR(LTM_CFLAGS, CFLAGS for bundled libtommath. Default -O3 -funroll-loops -fomit-frame-pointer)
AC_SUBST(DROPBEAR_LTM_CFLAGS)
AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wno-pointer-sign])
DB_TRYADDCFLAGS([-Wno-pointer-sign])
AC_MSG_NOTICE([Checking if compiler '$CC' supports -fno-strict-overflow])
DB_TRYADDCFLAGS([-fno-strict-overflow])
AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wundef])
DB_TRYADDCFLAGS([-Wundef])
# needed for various extensions. define early before autoconf tests
AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions if glibc])
STATIC=0
AC_ARG_ENABLE(static,
[ --enable-static Build static binaries],
@@ -77,15 +93,15 @@ if test "$hardenbuild" -eq 1; then
OLDLDFLAGS="$LDFLAGS"
TESTFLAGS="-Wl,-pie"
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
LDFLAGS="$TESTFLAGS $LDFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[
LDFLAGS="$OLDLDFLAGS"
TESTFLAGS="-pie"
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
LDFLAGS="$TESTFLAGS $LDFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
)
]
@@ -93,24 +109,24 @@ if test "$hardenbuild" -eq 1; then
# readonly elf relocation sections (relro)
OLDLDFLAGS="$LDFLAGS"
TESTFLAGS="-Wl,-z,now -Wl,-z,relro"
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
LDFLAGS="$TESTFLAGS $LDFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
)
fi # non-static
# stack protector. -strong is good but only in gcc 4.9 or later
OLDCFLAGS="$CFLAGS"
TESTFLAGS="-fstack-protector-strong"
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
CFLAGS="$TESTFLAGS $CFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[
CFLAGS="$OLDCFLAGS"
TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4"
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
CFLAGS="$TESTFLAGS $CFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDCFLAGS" ]
)
]
@@ -124,6 +140,17 @@ if test "$hardenbuild" -eq 1; then
fi
AC_ARG_ENABLE(werror,
[ --enable-werror Set -Werror when building],
[
if test "x$enableval" = "xyes"; then
# -Werror shouldn't be set when configure runs tests.
# We add it to the Makefile's CFLAGS
LATE_CFLAGS+="$LATE_CFLAGS -Werror"
AC_MSG_NOTICE(Enabling -Werror)
fi
], [])
# large file support is useful for scp
AC_SYS_LARGEFILE
@@ -159,7 +186,7 @@ case "$host" in
# OpenSSH thinks it's broken. If it isn't, let me know.
AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
;;
*-*-hpux*)
LIBS="$LIBS -lsec"
# It's probably broken.
@@ -173,10 +200,10 @@ esac
AC_CHECK_TOOL(AR, ar, :)
AC_CHECK_TOOL(RANLIB, ranlib, :)
AC_CHECK_TOOL(STRIP, strip, :)
AC_CHECK_TOOL(INSTALL, install, :)
AC_PROG_INSTALL
dnl Can't use login() or logout() with uclibc
AC_CHECK_DECL(__UCLIBC__,
AC_CHECK_DECL(__UCLIBC__,
[
no_loginfunc_check=1
AC_MSG_NOTICE([Using uClibc - login() and logout() probably don't work, so we won't use them.])
@@ -184,14 +211,14 @@ AC_CHECK_DECL(__UCLIBC__,
dnl We test for crypt() specially. On Linux (and others?) it resides in libcrypt
dnl but we don't want link all binaries to -lcrypt, just dropbear server.
dnl OS X doesn't need -lcrypt
dnl OS X doesn't need -lcrypt
AC_CHECK_FUNC(crypt, found_crypt_func=here)
AC_CHECK_LIB(crypt, crypt,
AC_CHECK_LIB(crypt, crypt,
[
CRYPTLIB="-lcrypt"
found_crypt_func=here
])
AC_SUBST(CRYPTLIB)
AC_SUBST(CRYPTLIB)
if test "t$found_crypt_func" = there; then
AC_DEFINE(HAVE_CRYPT, 1, [crypt() function])
fi
@@ -347,6 +374,7 @@ AC_ARG_ENABLE(fuzz,
DROPBEAR_FUZZ=1
# libfuzzer needs linking with c++ libraries
AC_PROG_CXX
mkdir -pv fuzz
else
AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing)
AC_MSG_NOTICE(Disabling fuzzing)
@@ -364,14 +392,13 @@ AC_SUBST(DROPBEAR_FUZZ)
AC_SUBST(CXX)
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \
crypt.h \
pty.h libutil.h libgen.h inttypes.h stropts.h utmp.h \
utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h \
pam/pam_appl.h netinet/in_systm.h sys/uio.h linux/pkt_sched.h \
sys/random.h])
sys/random.h sys/prctl.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -379,7 +406,6 @@ AC_TYPE_UID_T
AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_CHECK_TYPES([uint8_t, u_int8_t, uint16_t, u_int16_t, uint32_t, u_int32_t])
AC_CHECK_TYPES([struct sockaddr_storage])
@@ -554,7 +580,7 @@ AC_ARG_ENABLE(bundled-libtom,
)
if test $BUNDLED_LIBTOM = 1 ; then
AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom)
AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom)
fi
AC_SUBST(LIBTOM_LIBS)
@@ -627,7 +653,7 @@ AC_ARG_ENABLE(pututxline,
AC_ARG_WITH(lastlog,
[ --with-lastlog=FILE|DIR specify lastlog location [common locations]],
[
if test "x$withval" = "xno" ; then
if test "x$withval" = "xno" ; then
AC_DEFINE(DISABLE_LASTLOG)
else
conf_lastlog_location=$withval
@@ -702,7 +728,7 @@ fi
if test -n "$conf_lastlog_location"; then
AC_DEFINE_UNQUOTED(CONF_LASTLOG_FILE, "$conf_lastlog_location", lastlog file location)
fi
fi
dnl utmp detection
AC_MSG_CHECKING([if your system defines UTMP_FILE])
@@ -732,7 +758,7 @@ if test -z "$conf_utmp_location"; then
fi
if test -n "$conf_utmp_location"; then
AC_DEFINE_UNQUOTED(CONF_UTMP_FILE, "$conf_utmp_location", utmp file location)
fi
fi
dnl wtmp detection
AC_MSG_CHECKING([if your system defines WTMP_FILE])
@@ -764,7 +790,7 @@ if test -z "$conf_wtmp_location"; then
fi
if test -n "$conf_wtmp_location"; then
AC_DEFINE_UNQUOTED(CONF_WTMP_FILE, "$conf_wtmp_location", wtmp file location)
fi
fi
dnl utmpx detection - I don't know any system so perverse as to require
@@ -792,7 +818,7 @@ if test -z "$conf_utmpx_location"; then
fi
else
AC_DEFINE_UNQUOTED(CONF_UTMPX_FILE, "$conf_utmpx_location", utmpx file location)
fi
fi
dnl wtmpx detection
AC_MSG_CHECKING([if your system defines WTMPX_FILE])
@@ -819,7 +845,7 @@ if test -z "$conf_wtmpx_location"; then
fi
else
AC_DEFINE_UNQUOTED(CONF_WTMPX_FILE, "$conf_wtmpx_location", wtmpx file location)
fi
fi
# Checks for library functions.
AC_PROG_GCC_TRADITIONAL
@@ -827,7 +853,7 @@ AC_FUNC_MEMCMP
AC_FUNC_SELECT_ARGTYPES
AC_CHECK_FUNCS([getpass getspnam getusershell putenv])
AC_CHECK_FUNCS([clearenv strlcpy strlcat daemon basename _getpty getaddrinfo ])
AC_CHECK_FUNCS([freeaddrinfo getnameinfo fork writev getgrouplist])
AC_CHECK_FUNCS([freeaddrinfo getnameinfo fork writev getgrouplist fexecve])
AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
@@ -855,12 +881,17 @@ fi
AC_EXEEXT
if test $BUNDLED_LIBTOM = 1 ; then
(cd $srcdir; find libtomcrypt -type d) | xargs mkdir -pv
(cd $srcdir; find libtomcrypt -type d) | xargs mkdir -pv
LIBTOM_FILES="libtomcrypt/Makefile libtommath/Makefile"
fi
AC_CONFIG_HEADER(config.h)
AC_CONFIG_FILES(Makefile $LIBTOM_FILES)
# flags that should be set in Makefile but not for configure tests
CFLAGS="$CFLAGS $LATE_CFLAGS"
AC_CONFIG_AUX_DIR([src])
AC_CONFIG_HEADERS([config.h:src/config.h.in])
AC_CONFIG_FILES(Makefile $LIBTOM_FILES test/Makefile)
AC_OUTPUT
AC_MSG_NOTICE()

30
debian/changelog vendored
View File

@@ -1,3 +1,33 @@
dropbear (2024.85-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 25 Apr 2024 22:51:57 +0800
dropbear (2024.84-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 4 Apr 2024 22:51:57 +0800
dropbear (2022.83-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Mon, 14 Nov 2022 22:51:57 +0800
dropbear (2022.82-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Fri, 1 Apr 2022 22:51:57 +0800
dropbear (2020.81-0.1) unstable; urgency=low
* New upstream release.
-- Matt Johnston <matt@ucc.asn.au> Thu, 29 Oct 2020 22:51:57 +0800
dropbear (2020.80-0.1) unstable; urgency=low
* New upstream release.

View File

@@ -1,3 +1,3 @@
README
README.md
debian/README.runit
debian/README.Debian.diet

View File

@@ -25,7 +25,7 @@ set -e
cancel() { echo "$1" >&2; exit 0; };
test ! -r /etc/default/dropbear || . /etc/default/dropbear
test -x "$DAEMON" || cancel "$DAEMON does not exist or is not executable."
test ! -x /usr/sbin/update-service || ! update-service --check dropbear ||
test ! -x /usr/sbin/update-service || ! update-service --check dropbear || \
cancel 'The dropbear service is controlled through runit, use the sv(8) program'
test -z "$DROPBEAR_BANNER" || \

4
debian/rules vendored
View File

@@ -77,9 +77,9 @@ install: deb-checkdir deb-checkuid build-stamp
# man pages
install -d -m0755 '$(DIR)'/usr/share/man/man8
install -d -m0755 '$(DIR)'/usr/share/man/man1
install -m644 dropbear.8 '$(DIR)'/usr/share/man/man8/
install -m644 manpages/dropbear.8 '$(DIR)'/usr/share/man/man8/
for i in dbclient.1 dropbearkey.1 dropbearconvert.1; do \
install -m644 $$i '$(DIR)'/usr/share/man/man1/ || exit 1; \
install -m644 manpages/$$i '$(DIR)'/usr/share/man/man1/ || exit 1; \
done
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
gzip -9 '$(DIR)'/usr/share/man/man1/*.1

View File

@@ -1,209 +0,0 @@
#include "includes.h"
#include "includes.h"
#include "fuzz.h"
#include "dbutil.h"
#include "runopts.h"
#include "crypto_desc.h"
#include "session.h"
#include "dbrandom.h"
#include "bignum.h"
#include "fuzz-wrapfd.h"
struct dropbear_fuzz_options fuzz;
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param);
static void load_fixed_hostkeys(void);
void fuzz_common_setup(void) {
fuzz.fuzzing = 1;
fuzz.wrapfds = 1;
fuzz.do_jmp = 1;
fuzz.input = m_malloc(sizeof(buffer));
_dropbear_log = fuzz_dropbear_log;
crypto_init();
fuzz_seed();
/* let any messages get flushed */
setlinebuf(stdout);
}
int fuzz_set_input(const uint8_t *Data, size_t Size) {
fuzz.input->data = (unsigned char*)Data;
fuzz.input->size = Size;
fuzz.input->len = Size;
fuzz.input->pos = 0;
memset(&ses, 0x0, sizeof(ses));
memset(&svr_ses, 0x0, sizeof(svr_ses));
wrapfd_setup();
fuzz_seed();
return DROPBEAR_SUCCESS;
}
#if DEBUG_TRACE
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param) {
if (debug_trace) {
char printbuf[1024];
vsnprintf(printbuf, sizeof(printbuf), format, param);
fprintf(stderr, "%s\n", printbuf);
}
}
#else
static void fuzz_dropbear_log(int UNUSED(priority), const char* UNUSED(format), va_list UNUSED(param)) {
/* No print */
}
#endif /* DEBUG_TRACE */
void fuzz_svr_setup(void) {
fuzz_common_setup();
_dropbear_exit = svr_dropbear_exit;
char *argv[] = {
"-E",
};
int argc = sizeof(argv) / sizeof(*argv);
svr_getopts(argc, argv);
/* user lookups might be slow, cache it */
fuzz.pw_name = m_strdup("person");
fuzz.pw_dir = m_strdup("/tmp");
fuzz.pw_shell = m_strdup("/bin/zsh");
fuzz.pw_passwd = m_strdup("!!zzznope");
load_fixed_hostkeys();
}
static void load_fixed_hostkeys(void) {
#include "fuzz-hostkeys.c"
buffer *b = buf_new(3000);
enum signkey_type type;
TRACE(("load fixed hostkeys"))
svr_opts.hostkey = new_sign_key();
buf_setlen(b, 0);
buf_putbytes(b, keyr, keyr_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_RSA;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed rsa hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keyd, keyd_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_DSS;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed dss hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keye, keye_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed ecdsa hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keyed25519, keyed25519_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_ED25519;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed ed25519 hostkey");
}
buf_free(b);
}
void fuzz_kex_fakealgos(void) {
ses.newkeys->recv.crypt_mode = &dropbear_mode_none;
}
void fuzz_get_socket_address(int UNUSED(fd), char **local_host, char **local_port,
char **remote_host, char **remote_port, int UNUSED(host_lookup)) {
if (local_host) {
*local_host = m_strdup("fuzzlocalhost");
}
if (local_port) {
*local_port = m_strdup("1234");
}
if (remote_host) {
*remote_host = m_strdup("fuzzremotehost");
}
if (remote_port) {
*remote_port = m_strdup("9876");
}
}
/* cut down version of svr_send_msg_kexdh_reply() that skips slow maths. Still populates structures */
void fuzz_fake_send_kexdh_reply(void) {
assert(!ses.dh_K);
m_mp_alloc_init_multi(&ses.dh_K, NULL);
mp_set_ul(ses.dh_K, 12345678uL);
finish_kexhashbuf();
}
int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) {
static int once = 0;
if (!once) {
fuzz_svr_setup();
fuzz.skip_kexmaths = skip_kexmaths;
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
/*
get prefix. input format is
string prefix
uint32 wrapfd seed
... to be extended later
[bytes] ssh input stream
*/
/* be careful to avoid triggering buffer.c assertions */
if (fuzz.input->len < 8) {
return 0;
}
size_t prefix_size = buf_getint(fuzz.input);
if (prefix_size != 4) {
return 0;
}
uint32_t wrapseed = buf_getint(fuzz.input);
wrapfd_setseed(wrapseed);
int fakesock = 20;
wrapfd_add(fakesock, fuzz.input, PLAIN);
m_malloc_set_epoch(1);
if (setjmp(fuzz.jmp) == 0) {
svr_session(fakesock, fakesock);
m_malloc_free_epoch(1, 0);
} else {
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}
const void* fuzz_get_algo(const algo_type *algos, const char* name) {
const algo_type *t;
for (t = algos; t->name; t++) {
if (strcmp(t->name, name) == 0) {
return t->data;
}
}
assert(0);
}

72
fuzz.h
View File

@@ -1,72 +0,0 @@
#ifndef DROPBEAR_FUZZ_H
#define DROPBEAR_FUZZ_H
#include "config.h"
#if DROPBEAR_FUZZ
#include "includes.h"
#include "buffer.h"
#include "algo.h"
#include "fuzz-wrapfd.h"
// once per process
void fuzz_common_setup(void);
void fuzz_svr_setup(void);
// must be called once per fuzz iteration.
// returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
int fuzz_set_input(const uint8_t *Data, size_t Size);
int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths);
const void* fuzz_get_algo(const algo_type *algos, const char* name);
// fuzzer functions that intrude into general code
void fuzz_kex_fakealgos(void);
int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename,
const char* algo, unsigned int algolen,
const unsigned char* keyblob, unsigned int keybloblen);
extern const char * const * fuzz_signkey_names;
void fuzz_seed(void);
void fuzz_get_socket_address(int fd, char **local_host, char **local_port,
char **remote_host, char **remote_port, int host_lookup);
void fuzz_fake_send_kexdh_reply(void);
// fake IO wrappers
#ifndef FUZZ_SKIP_WRAP
#define select(nfds, readfds, writefds, exceptfds, timeout) \
wrapfd_select(nfds, readfds, writefds, exceptfds, timeout)
#define write(fd, buf, count) wrapfd_write(fd, buf, count)
#define read(fd, buf, count) wrapfd_read(fd, buf, count)
#define close(fd) wrapfd_close(fd)
#endif // FUZZ_SKIP_WRAP
struct dropbear_fuzz_options {
int fuzzing;
// fuzzing input
buffer *input;
struct dropbear_cipher recv_cipher;
struct dropbear_hash recv_mac;
int wrapfds;
// whether to skip slow bignum maths
int skip_kexmaths;
// dropbear_exit() jumps back
int do_jmp;
sigjmp_buf jmp;
uid_t pw_uid;
gid_t pw_gid;
char* pw_name;
char* pw_dir;
char* pw_shell;
char* pw_passwd;
};
extern struct dropbear_fuzz_options fuzz;
#endif // DROPBEAR_FUZZ
#endif /* DROPBEAR_FUZZ_H */

398
fuzz/fuzz-common.c Normal file
View File

@@ -0,0 +1,398 @@
#define FUZZ_NO_REPLACE_STDERR
#define FUZZ_NO_REPLACE_GETPW
#include "includes.h"
#include "includes.h"
#include "dbutil.h"
#include "runopts.h"
#include "crypto_desc.h"
#include "session.h"
#include "dbrandom.h"
#include "bignum.h"
#include "atomicio.h"
#include "fuzz-wrapfd.h"
#include "fuzz.h"
struct dropbear_fuzz_options fuzz;
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param);
static void load_fixed_hostkeys(void);
static void load_fixed_client_key(void);
// This runs automatically before main, due to contructor attribute in fuzz.h
void fuzz_early_setup(void) {
/* Set stderr to point to normal stderr by default */
fuzz.fake_stderr = stderr;
}
void fuzz_common_setup(void) {
disallow_core();
fuzz.fuzzing = 1;
fuzz.wrapfds = 1;
fuzz.do_jmp = 1;
fuzz.input = m_malloc(sizeof(buffer));
_dropbear_log = fuzz_dropbear_log;
crypto_init();
fuzz_seed("start", 5);
/* let any messages get flushed */
setlinebuf(stdout);
#if DEBUG_TRACE
if (debug_trace)
{
fprintf(stderr, "Dropbear fuzzer: -v specified, not disabling stderr output\n");
}
else
#endif
if (getenv("DROPBEAR_KEEP_STDERR")) {
fprintf(stderr, "Dropbear fuzzer: DROPBEAR_KEEP_STDERR, not disabling stderr output\n");
}
else
{
fprintf(stderr, "Dropbear fuzzer: Disabling stderr output\n");
fuzz.fake_stderr = fopen("/dev/null", "w");
assert(fuzz.fake_stderr);
}
}
int fuzz_set_input(const uint8_t *Data, size_t Size) {
fuzz.input->data = (unsigned char*)Data;
fuzz.input->size = Size;
fuzz.input->len = Size;
fuzz.input->pos = 0;
memset(&ses, 0x0, sizeof(ses));
memset(&svr_ses, 0x0, sizeof(svr_ses));
memset(&cli_ses, 0x0, sizeof(cli_ses));
wrapfd_setup(fuzz.input);
// printhex("input", fuzz.input->data, fuzz.input->len);
fuzz_seed(fuzz.input->data, MIN(fuzz.input->len, 16));
return DROPBEAR_SUCCESS;
}
#if DEBUG_TRACE
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param) {
if (debug_trace) {
char printbuf[1024];
vsnprintf(printbuf, sizeof(printbuf), format, param);
fprintf(stderr, "%s\n", printbuf);
}
}
#else
static void fuzz_dropbear_log(int UNUSED(priority), const char* UNUSED(format), va_list UNUSED(param)) {
/* No print */
}
#endif /* DEBUG_TRACE */
void fuzz_svr_setup(void) {
fuzz_common_setup();
_dropbear_exit = svr_dropbear_exit;
char *argv[] = {
"dropbear",
"-E",
};
int argc = sizeof(argv) / sizeof(*argv);
svr_getopts(argc, argv);
load_fixed_hostkeys();
}
void fuzz_svr_hook_preloop() {
if (fuzz.svr_postauth) {
ses.authstate.authdone = 1;
fill_passwd("root");
}
}
void fuzz_cli_setup(void) {
fuzz_common_setup();
_dropbear_exit = cli_dropbear_exit;
_dropbear_log = cli_dropbear_log;
char *argv[] = {
"dbclient",
"-y",
"localhost",
"uptime"
};
int argc = sizeof(argv) / sizeof(*argv);
cli_getopts(argc, argv);
load_fixed_client_key();
/* Avoid password prompt */
setenv(DROPBEAR_PASSWORD_ENV, "password", 1);
}
#include "fuzz-hostkeys.c"
static void load_fixed_client_key(void) {
buffer *b = buf_new(3000);
sign_key *key;
enum signkey_type keytype;
key = new_sign_key();
keytype = DROPBEAR_SIGNKEY_ANY;
buf_putbytes(b, keyed25519, keyed25519_len);
buf_setpos(b, 0);
if (buf_get_priv_key(b, key, &keytype) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed ed25519 hostkey");
}
list_append(cli_opts.privkeys, key);
buf_free(b);
}
static void load_fixed_hostkeys(void) {
buffer *b = buf_new(3000);
enum signkey_type type;
TRACE(("load fixed hostkeys"))
svr_opts.hostkey = new_sign_key();
buf_setlen(b, 0);
buf_putbytes(b, keyr, keyr_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_RSA;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed rsa hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keyd, keyd_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_DSS;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed dss hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keye, keye_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed ecdsa hostkey");
}
buf_setlen(b, 0);
buf_putbytes(b, keyed25519, keyed25519_len);
buf_setpos(b, 0);
type = DROPBEAR_SIGNKEY_ED25519;
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
dropbear_exit("failed fixed ed25519 hostkey");
}
buf_free(b);
}
void fuzz_kex_fakealgos(void) {
ses.newkeys->recv.crypt_mode = &dropbear_mode_none;
ses.newkeys->recv.algo_mac = &dropbear_nohash;
}
void fuzz_get_socket_address(int UNUSED(fd), char **local_host, char **local_port,
char **remote_host, char **remote_port, int UNUSED(host_lookup)) {
if (local_host) {
*local_host = m_strdup("fuzzlocalhost");
}
if (local_port) {
*local_port = m_strdup("1234");
}
if (remote_host) {
*remote_host = m_strdup("fuzzremotehost");
}
if (remote_port) {
*remote_port = m_strdup("9876");
}
}
/* cut down version of svr_send_msg_kexdh_reply() that skips slow maths. Still populates structures */
void fuzz_fake_send_kexdh_reply(void) {
assert(!ses.dh_K);
m_mp_alloc_init_multi(&ses.dh_K, NULL);
mp_set_ul(ses.dh_K, 12345678uL);
finish_kexhashbuf();
}
/* fake version of spawn_command() */
int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
*ret_writefd = wrapfd_new_dummy();
*ret_readfd = wrapfd_new_dummy();
if (ret_errfd) {
*ret_errfd = wrapfd_new_dummy();
}
if (*ret_writefd == -1 || *ret_readfd == -1 || (ret_errfd && *ret_errfd == -1)) {
m_close(*ret_writefd);
m_close(*ret_readfd);
if (ret_errfd) {
m_close(*ret_errfd);
}
return DROPBEAR_FAILURE;
} else {
*ret_pid = 999;
return DROPBEAR_SUCCESS;
}
}
/* Fake dropbear_listen, always returns failure for now.
TODO make it sometimes return success with wrapfd_new_dummy() sockets.
Making the listeners fake a new incoming connection will be harder. */
/* Listen on address:port.
* Special cases are address of "" listening on everything,
* and address of NULL listening on localhost only.
* Returns the number of sockets bound on success, or -1 on failure. On
* failure, if errstring wasn't NULL, it'll be a newly malloced error
* string.*/
int fuzz_dropbear_listen(const char* UNUSED(address), const char* UNUSED(port),
int *UNUSED(socks), unsigned int UNUSED(sockcount), char **errstring, int *UNUSED(maxfd)) {
if (errstring) {
*errstring = m_strdup("fuzzing can't listen (yet)");
}
return -1;
}
int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int postauth) {
static int once = 0;
if (!once) {
fuzz_svr_setup();
fuzz.skip_kexmaths = skip_kexmaths;
once = 1;
}
fuzz.svr_postauth = postauth;
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
uint32_t wrapseed;
genrandom((void*)&wrapseed, sizeof(wrapseed));
wrapfd_setseed(wrapseed);
int fakesock = wrapfd_new_fuzzinput();
m_malloc_set_epoch(1);
fuzz.do_jmp = 1;
if (setjmp(fuzz.jmp) == 0) {
svr_session(fakesock, fakesock);
m_malloc_free_epoch(1, 0);
} else {
fuzz.do_jmp = 0;
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}
int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths) {
static int once = 0;
if (!once) {
fuzz_cli_setup();
fuzz.skip_kexmaths = skip_kexmaths;
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
// Allow to proceed sooner
ses.kexstate.donefirstkex = 1;
uint32_t wrapseed;
genrandom((void*)&wrapseed, sizeof(wrapseed));
wrapfd_setseed(wrapseed);
int fakesock = wrapfd_new_fuzzinput();
m_malloc_set_epoch(1);
fuzz.do_jmp = 1;
if (setjmp(fuzz.jmp) == 0) {
cli_session(fakesock, fakesock, NULL, 0);
m_malloc_free_epoch(1, 0);
} else {
fuzz.do_jmp = 0;
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}
const void* fuzz_get_algo(const algo_type *algos, const char* name) {
const algo_type *t;
for (t = algos; t->name; t++) {
if (strcmp(t->name, name) == 0) {
return t->data;
}
}
assert(0);
}
void fuzz_dump(const unsigned char* data, size_t len) {
if (fuzz.dumping) {
TRACE(("dump %zu", len))
assert(atomicio(vwrite, fuzz.recv_dumpfd, (void*)data, len) == len);
}
}
static struct passwd pwd_root = {
.pw_name = "root",
.pw_passwd = "!",
.pw_uid = 0,
.pw_gid = 0,
.pw_dir = "/root",
.pw_shell = "/bin/sh",
};
static struct passwd pwd_other = {
.pw_name = "other",
.pw_passwd = "!",
.pw_uid = 100,
.pw_gid = 100,
.pw_dir = "/home/other",
.pw_shell = "/bin/sh",
};
/* oss-fuzz runs fuzzers under minijail, without /etc/passwd.
We provide sufficient values for the fuzzers to run */
struct passwd* fuzz_getpwnam(const char *login) {
if (!fuzz.fuzzing) {
return getpwnam(login);
}
if (strcmp(login, pwd_other.pw_name) == 0) {
return &pwd_other;
}
if (strcmp(login, pwd_root.pw_name) == 0) {
return &pwd_root;
}
return NULL;
}
struct passwd* fuzz_getpwuid(uid_t uid) {
if (!fuzz.fuzzing) {
return getpwuid(uid);
}
if (uid == pwd_other.pw_uid) {
return &pwd_other;
}
if (uid == pwd_root.pw_uid) {
return &pwd_root;
}
return NULL;
}

View File

@@ -7,15 +7,19 @@ extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
int main(int argc, char ** argv) {
int i;
buffer *input = buf_new(100000);
int quiet = 0;
for (i = 1; i < argc; i++) {
printf("arg %s\n", argv[i]);
#if DEBUG_TRACE
if (strcmp(argv[i], "-v") == 0) {
debug_trace = 1;
TRACE(("debug printing on"))
debug_trace++;
fprintf(stderr, "debug level -> %d\n", debug_trace);
}
#endif
if (strcmp(argv[i], "-q") == 0) {
printf("Running quiet\n");
quiet = 1;
}
}
int old_fuzz_wrapfds = 0;
@@ -30,12 +34,19 @@ int main(int argc, char ** argv) {
buf_readfile(input, fn);
buf_setpos(input, 0);
/* Run twice to catch problems with statefulness */
fuzz.wrapfds = old_fuzz_wrapfds;
printf("Running %s once \n", fn);
if (!quiet) {
printf("Running %s once \n", fn);
}
LLVMFuzzerTestOneInput(input->data, input->len);
printf("Running %s twice \n", fn);
if (!quiet) {
printf("Running %s twice \n", fn);
}
LLVMFuzzerTestOneInput(input->data, input->len);
printf("Done %s\n", fn);
if (!quiet) {
printf("Done %s\n", fn);
}
/* Disable wrapfd so it won't interfere with buf_readfile() above */
old_fuzz_wrapfds = fuzz.wrapfds;
@@ -46,3 +57,10 @@ int main(int argc, char ** argv) {
return 0;
}
// Just to let it link
size_t LLVMFuzzerMutate(uint8_t *UNUSED(Data), size_t UNUSED(Size), size_t UNUSED(MaxSize)) {
printf("standalone fuzzer harness shouldn't call LLVMFuzzerMutate");
abort();
return 0;
}

View File

@@ -1,5 +1,6 @@
/* To be included in fuzz-common.c */
unsigned char keyr[] = {
static unsigned char keyr[] = {
0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00,
0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xb1,
0x06, 0x95, 0xc9, 0xa8, 0x38, 0xb9, 0x99, 0x91, 0xb5, 0x17, 0x39, 0xb9,
@@ -69,8 +70,8 @@ unsigned char keyr[] = {
0xb0, 0x9b, 0xea, 0x18, 0x77, 0xf6, 0x25, 0x02, 0xb4, 0x5e, 0x71, 0xea,
0xa3
};
unsigned int keyr_len = 805;
unsigned char keye[] = {
static unsigned int keyr_len = 805;
static unsigned char keye[] = {
0x00, 0x00, 0x00, 0x13, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x73, 0x68,
0x61, 0x32, 0x2d, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00,
0x00, 0x00, 0x08, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00,
@@ -84,8 +85,8 @@ unsigned char keye[] = {
0x3c, 0x58, 0x28, 0x70, 0x9b, 0x23, 0x39, 0x51, 0xd7, 0xbc, 0xa7, 0x1a,
0xf5, 0xb4, 0x23, 0xd3, 0xf6, 0x17, 0xa6, 0x9c, 0x02
};
unsigned int keye_len = 141;
unsigned char keyd[] = {
static unsigned int keye_len = 141;
static unsigned char keyd[] = {
0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00,
0x00, 0x00, 0x81, 0x00, 0xb0, 0x02, 0x19, 0x8b, 0xf3, 0x46, 0xf9, 0xc5,
0x47, 0x78, 0x3d, 0x7f, 0x04, 0x10, 0x0a, 0x43, 0x8e, 0x00, 0x9e, 0xa4,
@@ -126,8 +127,8 @@ unsigned char keyd[] = {
0x7b, 0xac, 0xaa, 0x0c, 0xa2, 0xca, 0x7b, 0xa8, 0xd4, 0xdf, 0x68, 0x56,
0xf9, 0x39
};
unsigned int keyd_len = 458;
unsigned char keyed25519[] = {
static unsigned int keyd_len = 458;
static unsigned char keyed25519[] = {
0x00, 0x00, 0x00, 0x0b, 0x73, 0x73, 0x68, 0x2d, 0x65, 0x64, 0x32, 0x35,
0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb3, 0x79, 0x06, 0xe5,
0x9b, 0xe7, 0xe4, 0x6e, 0xec, 0xfe, 0xa5, 0x39, 0x21, 0x7c, 0xf6, 0x66,
@@ -136,4 +137,4 @@ unsigned char keyed25519[] = {
0xa4, 0xd5, 0xe9, 0x23, 0xfe, 0x8e, 0xd6, 0xd4, 0xf9, 0xb1, 0x11, 0x69,
0x7c, 0x57, 0x52, 0x0e, 0x41, 0xdb, 0x1b, 0x12, 0x87, 0xfa, 0xc9
};
unsigned int keyed25519_len = 83;
static unsigned int keyed25519_len = 83;

View File

@@ -0,0 +1,306 @@
/* A mutator/crossover for SSH protocol streams.
Attempts to mutate each SSH packet individually, keeping
lengths intact.
It will prepend a SSH-2.0-dbfuzz\r\n version string.
Linking this file to a binary will make libfuzzer pick up the custom mutator.
Care is taken to avoid memory allocation which would otherwise
slow exec/s substantially */
#include "fuzz.h"
#include "dbutil.h"
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
static const char* FIXED_VERSION = "SSH-2.0-dbfuzz\r\n";
static const char* FIXED_IGNORE_MSG =
"\x00\x00\x00\x10\x06\x02\x00\x00\x00\x00\x11\x22\x33\x44\x55\x66";
static const unsigned int FIXED_IGNORE_MSG_LEN = 16;
#define MAX_FUZZ_PACKETS 500
/* XXX This might need tuning */
static const size_t MAX_OUT_SIZE = 50000;
/* Splits packets from an input stream buffer "inp".
The initial SSH version identifier is discarded.
If packets are not recognised it will increment until an uint32 of valid
packet length is found. */
/* out_packets an array of num_out_packets*buffer, each of size RECV_MAX_PACKET_LEN */
static void fuzz_get_packets(buffer *inp, buffer **out_packets, unsigned int *num_out_packets) {
/* Skip any existing banner. Format is
SSH-protoversion-softwareversion SP comments CR LF
so we look for SSH-2. then a subsequent LF */
unsigned char* version = memmem(inp->data, inp->len, "SSH-2.", strlen("SSH-2."));
if (version) {
buf_incrpos(inp, version - inp->data);
unsigned char* newline = memchr(&inp->data[inp->pos], '\n', inp->len - inp->pos);
if (newline) {
buf_incrpos(inp, newline - &inp->data[inp->pos]+1);
} else {
/* Give up on any version string */
buf_setpos(inp, 0);
}
}
const unsigned int max_out_packets = *num_out_packets;
*num_out_packets = 0;
while (1) {
if (inp->pos + 4 > inp->len) {
/* End of input */
break;
}
if (*num_out_packets >= max_out_packets) {
/* End of output */
break;
}
/* Read packet */
unsigned int packet_len = buf_getint(inp);
if (packet_len > RECV_MAX_PACKET_LEN-4) {
/* Bad length, try skipping a single byte */
buf_decrpos(inp, 3);
continue;
}
packet_len = MIN(packet_len, inp->len - inp->pos);
/* Check the packet length makes sense */
if (packet_len >= MIN_PACKET_LEN-4) {
/* Copy to output buffer. We're reusing buffers */
buffer* new_packet = out_packets[*num_out_packets];
(*num_out_packets)++;
buf_setlen(new_packet, 0);
// packet_len doesn't include itself
buf_putint(new_packet, packet_len);
buf_putbytes(new_packet, buf_getptr(inp, packet_len), packet_len);
}
buf_incrpos(inp, packet_len);
}
}
/* Mutate a packet buffer in-place.
Returns DROPBEAR_FAILURE if it's too short */
static int buf_llvm_mutate(buffer *buf) {
int ret;
/* Position it after packet_length and padding_length */
const unsigned int offset = 5;
buf_setpos(buf, 0);
buf_incrwritepos(buf, offset);
size_t max_size = buf->size - buf->pos;
size_t new_size = LLVMFuzzerMutate(buf_getwriteptr(buf, max_size),
buf->len - buf->pos, max_size);
size_t new_total = new_size + 1 + 4;
// Round down to a block size
new_total = new_total - (new_total % dropbear_nocipher.blocksize);
if (new_total >= 16) {
buf_setlen(buf, new_total);
// Fix up the length fields
buf_setpos(buf, 0);
// packet_length doesn't include itself, does include padding_length byte
buf_putint(buf, new_size+1);
// always just put minimum padding length = 4
buf_putbyte(buf, 4);
ret = DROPBEAR_SUCCESS;
} else {
// instead put a fake packet
buf_setlen(buf, 0);
buf_putbytes(buf, FIXED_IGNORE_MSG, FIXED_IGNORE_MSG_LEN);
ret = DROPBEAR_FAILURE;
}
return ret;
}
/* Persistent buffers to avoid constant allocations */
static buffer *oup;
static buffer *alloc_packetA;
static buffer *alloc_packetB;
static buffer* packets1[MAX_FUZZ_PACKETS];
static buffer* packets2[MAX_FUZZ_PACKETS];
/* Allocate buffers once at startup.
'constructor' here so it runs before dbmalloc's interceptor */
static void alloc_static_buffers() __attribute__((constructor));
static void alloc_static_buffers() {
int i;
oup = buf_new(MAX_OUT_SIZE);
alloc_packetA = buf_new(RECV_MAX_PACKET_LEN);
alloc_packetB = buf_new(RECV_MAX_PACKET_LEN);
for (i = 0; i < MAX_FUZZ_PACKETS; i++) {
packets1[i] = buf_new(RECV_MAX_PACKET_LEN);
}
for (i = 0; i < MAX_FUZZ_PACKETS; i++) {
packets2[i] = buf_new(RECV_MAX_PACKET_LEN);
}
}
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
size_t MaxSize, unsigned int Seed) {
buf_setlen(alloc_packetA, 0);
buf_setlen(alloc_packetB, 0);
buf_setlen(oup, 0);
unsigned int i;
size_t ret_len;
unsigned short randstate[3] = {0,0,0};
memcpy(randstate, &Seed, sizeof(Seed));
// printhex("mutator input", Data, Size);
/* 0.1% chance straight llvm mutate */
// if (nrand48(randstate) % 1000 == 0) {
// ret_len = LLVMFuzzerMutate(Data, Size, MaxSize);
// // printhex("mutator straight llvm", Data, ret_len);
// return ret_len;
// }
buffer inp_buf = {.data = Data, .size = Size, .len = Size, .pos = 0};
buffer *inp = &inp_buf;
/* Parse packets */
unsigned int num_packets = MAX_FUZZ_PACKETS;
buffer **packets = packets1;
fuzz_get_packets(inp, packets, &num_packets);
if (num_packets == 0) {
// Make up a packet, writing direct to the buffer
inp->size = MaxSize;
buf_setlen(inp, 0);
buf_putbytes(inp, FIXED_VERSION, strlen(FIXED_VERSION));
buf_putbytes(inp, FIXED_IGNORE_MSG, FIXED_IGNORE_MSG_LEN);
// printhex("mutator no input", Data, inp->len);
return inp->len;
}
/* Start output */
/* Put a new banner to output */
buf_putbytes(oup, FIXED_VERSION, strlen(FIXED_VERSION));
/* Iterate output */
for (i = 0; i < num_packets+1; i++) {
// These are pointers to output
buffer *out_packetA = NULL, *out_packetB = NULL;
buf_setlen(alloc_packetA, 0);
buf_setlen(alloc_packetB, 0);
/* 2% chance each */
const int optA = nrand48(randstate) % 50;
if (optA == 0) {
/* Copy another */
unsigned int other = nrand48(randstate) % num_packets;
out_packetA = packets[other];
// printf("copy another %d / %d len %u\n", other, num_packets, out_packetA->len);
}
if (optA == 1) {
/* Mutate another */
unsigned int other = nrand48(randstate) % num_packets;
out_packetA = alloc_packetA;
buffer *from = packets[other];
buf_putbytes(out_packetA, from->data, from->len);
if (buf_llvm_mutate(out_packetA) == DROPBEAR_FAILURE) {
out_packetA = NULL;
}
// printf("mutate another %d / %d len %u -> %u\n", other, num_packets, from->len, out_packetA->len);
}
if (i < num_packets) {
int optB = nrand48(randstate) % 100;
if (optB == 1) {
/* small chance of drop */
/* Drop it */
//printf("%d drop\n", i);
} else {
/* Odds of modification are proportional to packet position.
First packet has 20% chance, last has 100% chance */
int optC = nrand48(randstate) % 1000;
int mutate_cutoff = MAX(200, (1000 * (i+1) / num_packets));
if (optC < mutate_cutoff) {
// // printf("%d mutate\n", i);
out_packetB = alloc_packetB;
buffer *from = packets[i];
buf_putbytes(out_packetB, from->data, from->len);
if (buf_llvm_mutate(out_packetB) == DROPBEAR_FAILURE) {
out_packetB = from;
}
// printf("mutate self %d / %d len %u -> %u\n", i, num_packets, from->len, out_packetB->len);
} else {
/* Copy as-is */
out_packetB = packets[i];
// printf("%d as-is len %u\n", i, out_packetB->len);
}
}
}
if (out_packetA && oup->len + out_packetA->len <= oup->size) {
buf_putbytes(oup, out_packetA->data, out_packetA->len);
}
if (out_packetB && oup->len + out_packetB->len <= oup->size) {
buf_putbytes(oup, out_packetB->data, out_packetB->len);
}
}
ret_len = MIN(MaxSize, oup->len);
memcpy(Data, oup->data, ret_len);
// printhex("mutator done", Data, ret_len);
return ret_len;
}
size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
const uint8_t *Data2, size_t Size2,
uint8_t *Out, size_t MaxOutSize,
unsigned int Seed) {
unsigned short randstate[3] = {0,0,0};
memcpy(randstate, &Seed, sizeof(Seed));
unsigned int i;
buffer inp_buf1 = {.data = (void*)Data1, .size = Size1, .len = Size1, .pos = 0};
buffer *inp1 = &inp_buf1;
buffer inp_buf2 = {.data = (void*)Data2, .size = Size2, .len = Size2, .pos = 0};
buffer *inp2 = &inp_buf2;
unsigned int num_packets1 = MAX_FUZZ_PACKETS;
fuzz_get_packets(inp1, packets1, &num_packets1);
unsigned int num_packets2 = MAX_FUZZ_PACKETS;
fuzz_get_packets(inp2, packets2, &num_packets2);
// fprintf(stderr, "input 1 %u packets\n", num_packets1);
// printhex("crossover input1", Data1, Size1);
// fprintf(stderr, "input 2 %u packets\n", num_packets2);
// printhex("crossover input2", Data2, Size2);
buf_setlen(oup, 0);
/* Put a new banner to output */
buf_putbytes(oup, FIXED_VERSION, strlen(FIXED_VERSION));
if (num_packets1 == 0 && num_packets2 == 0) {
buf_putbytes(oup, FIXED_IGNORE_MSG, FIXED_IGNORE_MSG_LEN);
} else {
unsigned int min_out = MIN(num_packets1, num_packets2);
unsigned int max_out = num_packets1 + num_packets2;
unsigned int num_out = min_out + nrand48(randstate) % (max_out-min_out+1);
for (i = 0; i < num_out; i++) {
unsigned int choose = nrand48(randstate) % (num_packets1 + num_packets2);
buffer *p = NULL;
if (choose < num_packets1) {
p = packets1[choose];
} else {
p = packets2[choose-num_packets1];
}
if (oup->len + p->len <= oup->size) {
buf_putbytes(oup, p->data, p->len);
}
}
}
size_t ret_len = MIN(MaxOutSize, oup->len);
memcpy(Out, oup->data, ret_len);
// printhex("crossover output", Out, ret_len);
return ret_len;
}

View File

@@ -17,25 +17,33 @@ static const double CHANCE_WRITE2 = 0.5;
struct fdwrap {
enum wrapfd_mode mode;
buffer *buf;
int closein;
int closeout;
};
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
/* for quick selection of in-use descriptors */
static int wrap_used[IOWRAP_MAXFD+1];
static unsigned int nused;
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1] = {{UNUSED, 0, 0}};
static int wrapfd_maxfd = -1;
static unsigned short rand_state[3];
static buffer *input_buf;
static int devnull_fd = -1;
void wrapfd_setup(void) {
static void wrapfd_remove(int fd);
void wrapfd_setup(buffer *buf) {
TRACE(("wrapfd_setup"))
nused = 0;
memset(wrap_fds, 0x0, sizeof(wrap_fds));
memset(wrap_used, 0x0, sizeof(wrap_used));
// clean old ones
int i;
for (i = 0; i <= wrapfd_maxfd; i++) {
if (wrap_fds[i].mode != UNUSED) {
wrapfd_remove(i);
}
}
wrapfd_maxfd = -1;
memset(rand_state, 0x0, sizeof(rand_state));
wrapfd_setseed(50);
input_buf = buf;
}
void wrapfd_setseed(uint32_t seed) {
@@ -43,39 +51,55 @@ void wrapfd_setseed(uint32_t seed) {
nrand48(rand_state);
}
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
assert(fd >= 0);
assert(fd <= IOWRAP_MAXFD);
assert(wrap_fds[fd].mode == UNUSED);
assert(buf || mode == RANDOMIN);
int wrapfd_new_fuzzinput() {
if (devnull_fd == -1) {
devnull_fd = open("/dev/null", O_RDONLY);
assert(devnull_fd != -1);
}
wrap_fds[fd].mode = mode;
wrap_fds[fd].buf = buf;
int fd = dup(devnull_fd);
assert(fd != -1);
assert(wrap_fds[fd].mode == UNUSED);
wrap_fds[fd].mode = COMMONBUF;
wrap_fds[fd].closein = 0;
wrap_fds[fd].closeout = 0;
wrap_used[nused] = fd;
wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
nused++;
return fd;
}
void wrapfd_remove(int fd) {
unsigned int i, j;
int wrapfd_new_dummy() {
if (devnull_fd == -1) {
devnull_fd = open("/dev/null", O_RDONLY);
assert(devnull_fd != -1);
}
int fd = dup(devnull_fd);
if (fd == -1) {
return -1;
}
if (fd > IOWRAP_MAXFD) {
close(fd);
errno = EMFILE;
return -1;
}
assert(wrap_fds[fd].mode == UNUSED);
wrap_fds[fd].mode = DUMMY;
wrap_fds[fd].closein = 0;
wrap_fds[fd].closeout = 0;
wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
return fd;
}
static void wrapfd_remove(int fd) {
TRACE(("wrapfd_remove %d", fd))
assert(fd >= 0);
assert(fd <= IOWRAP_MAXFD);
assert(wrap_fds[fd].mode != UNUSED);
wrap_fds[fd].mode = UNUSED;
/* remove from used list */
for (i = 0, j = 0; i < nused; i++) {
if (wrap_used[i] != fd) {
wrap_used[j] = wrap_used[i];
j++;
}
}
nused--;
close(fd);
}
int wrapfd_close(int fd) {
@@ -89,7 +113,6 @@ int wrapfd_close(int fd) {
int wrapfd_read(int fd, void *out, size_t count) {
size_t maxread;
buffer *buf;
if (!fuzz.wrapfds) {
return read(fd, out, count);
@@ -115,18 +138,18 @@ int wrapfd_read(int fd, void *out, size_t count) {
return -1;
}
buf = wrap_fds[fd].buf;
if (buf) {
maxread = MIN(buf->len - buf->pos, count);
if (input_buf && wrap_fds[fd].mode == COMMONBUF) {
maxread = MIN(input_buf->len - input_buf->pos, count);
/* returns 0 if buf is EOF, as intended */
if (maxread > 0) {
maxread = nrand48(rand_state) % maxread + 1;
}
memcpy(out, buf_getptr(buf, maxread), maxread);
buf_incrpos(buf, maxread);
memcpy(out, buf_getptr(input_buf, maxread), maxread);
buf_incrpos(input_buf, maxread);
return maxread;
}
// return fixed output, of random length
maxread = MIN(MAX_RANDOM_IN, count);
maxread = nrand48(rand_state) % maxread + 1;
memset(out, 0xef, maxread);
@@ -175,8 +198,6 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
int ret = 0;
int fdlist[IOWRAP_MAXFD+1];
memset(fdlist, 0x0, sizeof(fdlist));
if (!fuzz.wrapfds) {
return select(nfds, readfds, writefds, exceptfds, timeout);
}
@@ -244,3 +265,15 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
return ret;
}
int fuzz_kill(pid_t pid, int sig) {
if (fuzz.fuzzing) {
TRACE(("fuzz_kill ignoring pid %d signal %d", (pid), sig))
if (sig >= 0) {
return 0;
} else {
errno = EINVAL;
return -1;
}
}
return kill(pid, sig);
}

79
fuzz/fuzzer-cliconf.c Normal file
View File

@@ -0,0 +1,79 @@
/* fuzz target for cli-readconf.c */
#include "fuzz.h"
#include "fuzz-wrapfd.h"
#include "debug.h"
#include "runopts.h"
static void setup_fuzzer(void) {
fuzz_common_setup();
/* Set up commandline args */
char* args[2] = { "dbclient", "far" };
cli_getopts(2, args);
}
// Needs to be outside so it doesn't get optimised away for the setjmp().
// volatile doesn't seem to work, unsure why.
static FILE *conf_file = NULL;
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
if (!once) {
setup_fuzzer();
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}
m_malloc_set_epoch(1);
if (setjmp(fuzz.jmp) == 0) {
/* remotehost most be set before config parsing */
m_free(cli_opts.remotehost);
cli_opts.remotehost = m_strdup("far");
/* optional arguments */
if (buf_getbool(fuzz.input)) {
m_free(cli_opts.username);
cli_opts.username = m_strdup("someone");
}
if (buf_getbool(fuzz.input)) {
m_free(cli_opts.remoteport);
cli_opts.remoteport = m_strdup("999");
}
buffer *conf_buf = buf_getstringbuf(fuzz.input);
if (conf_buf->len > 0)
{
conf_file = fmemopen(conf_buf->data, conf_buf->len, "r");
read_config_file("fuzz", conf_file, &cli_opts);
fclose(conf_file);
conf_file = NULL;
}
buf_free(conf_buf);
m_free(cli_opts.remotehost);
m_free(cli_opts.remoteport);
m_free(cli_opts.username);
m_malloc_free_epoch(1, 0);
} else {
// Cleanup
if (conf_file) {
fclose(conf_file);
conf_file = NULL;
}
m_free(cli_opts.remotehost);
m_free(cli_opts.remoteport);
m_free(cli_opts.username);
m_malloc_free_epoch(1, 1);
TRACE(("dropbear_exit longjmped"))
/* dropbear_exit jumped here */
}
return 0;
}

View File

@@ -1,6 +1,6 @@
#include "fuzz.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return fuzz_run_preauth(Data, Size, 0);
return fuzz_run_client(Data, Size, 0);
}

View File

@@ -1,6 +1,6 @@
#include "fuzz.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return fuzz_run_preauth(Data, Size, 1);
return fuzz_run_client(Data, Size, 1);
}

View File

@@ -6,33 +6,30 @@
#include "algo.h"
#include "bignum.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
static struct key_context* keep_newkeys = NULL;
/* number of generated parameters is limited by the timeout for the first run.
TODO move this to the libfuzzer initialiser function instead if the timeout
doesn't apply there */
#define NUM_PARAMS 20
static struct kex_curve25519_param *curve25519_params[NUM_PARAMS];
static struct key_context* keep_newkeys = NULL;
/* An arbitrary limit */
#define NUM_PARAMS 80
static struct kex_curve25519_param *curve25519_params[NUM_PARAMS];
if (!once) {
fuzz_common_setup();
fuzz_svr_setup();
static void setup() __attribute__((constructor));
// Perform initial setup here to avoid hitting timeouts on first run
static void setup() {
fuzz_common_setup();
fuzz_svr_setup();
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "curve25519-sha256");
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ED25519;
ses.newkeys = keep_newkeys;
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "curve25519-sha256");
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ED25519;
ses.newkeys = keep_newkeys;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
curve25519_params[i] = gen_kexcurve25519_param();
}
once = 1;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
curve25519_params[i] = gen_kexcurve25519_param();
}
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}

View File

@@ -6,33 +6,29 @@
#include "algo.h"
#include "bignum.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
static struct key_context* keep_newkeys = NULL;
/* number of generated parameters is limited by the timeout for the first run.
TODO move this to the libfuzzer initialiser function instead if the timeout
doesn't apply there */
#define NUM_PARAMS 20
static struct kex_dh_param *dh_params[NUM_PARAMS];
static struct key_context* keep_newkeys = NULL;
#define NUM_PARAMS 80
static struct kex_dh_param *dh_params[NUM_PARAMS];
if (!once) {
fuzz_common_setup();
fuzz_svr_setup();
static void setup() __attribute__((constructor));
// Perform initial setup here to avoid hitting timeouts on first run
static void setup() {
fuzz_common_setup();
fuzz_svr_setup();
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "diffie-hellman-group14-sha256");
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
ses.newkeys = keep_newkeys;
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "diffie-hellman-group14-sha256");
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
ses.newkeys = keep_newkeys;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
dh_params[i] = gen_kexdh_param();
}
once = 1;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
dh_params[i] = gen_kexdh_param();
}
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;
}

View File

@@ -6,38 +6,38 @@
#include "algo.h"
#include "bignum.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
static const struct dropbear_kex *ecdh[3]; /* 256, 384, 521 */
static struct key_context* keep_newkeys = NULL;
/* number of generated parameters is limited by the timeout for the first run */
#define NUM_PARAMS 80
static struct kex_ecdh_param *ecdh_params[NUM_PARAMS];
static const struct dropbear_kex *ecdh[3]; /* 256, 384, 521 */
static struct key_context* keep_newkeys = NULL;
/* number of generated parameters. An arbitrary limit, but will delay startup */
#define NUM_PARAMS 80
static struct kex_ecdh_param *ecdh_params[NUM_PARAMS];
if (!once) {
fuzz_common_setup();
fuzz_svr_setup();
static void setup() __attribute__((constructor));
// Perform initial setup here to avoid hitting timeouts on first run
static void setup() {
fuzz_common_setup();
fuzz_svr_setup();
/* ses gets zeroed by fuzz_set_input */
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
ecdh[0] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp256");
ecdh[1] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp384");
ecdh[2] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp521");
assert(ecdh[0]);
assert(ecdh[1]);
assert(ecdh[2]);
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
ses.newkeys = keep_newkeys;
/* ses gets zeroed by fuzz_set_input */
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
ecdh[0] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp256");
ecdh[1] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp384");
ecdh[2] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp521");
assert(ecdh[0]);
assert(ecdh[1]);
assert(ecdh[2]);
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
ses.newkeys = keep_newkeys;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
ses.newkeys->algo_kex = ecdh[i % 3];
ecdh_params[i] = gen_kexecdh_param();
}
once = 1;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
ses.newkeys->algo_kex = ecdh[i % 3];
ecdh_params[i] = gen_kexecdh_param();
}
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0;

View File

@@ -0,0 +1,6 @@
#include "fuzz.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return fuzz_run_server(Data, Size, 1, 1);
}

6
fuzz/fuzzer-preauth.c Normal file
View File

@@ -0,0 +1,6 @@
#include "fuzz.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return fuzz_run_server(Data, Size, 0, 0);
}

View File

@@ -0,0 +1,6 @@
#include "fuzz.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return fuzz_run_server(Data, Size, 1, 0);
}

View File

@@ -27,7 +27,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
unsigned int algolen;
char* algoname = buf_getstring(keyblob, &algolen);
if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNKEY_NONE) {
if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNATURE_NONE) {
dropbear_exit("fuzzer imagined a bogus algorithm");
}

View File

@@ -3,6 +3,7 @@
#include "fuzz-wrapfd.h"
#include "debug.h"
#include "dss.h"
#include "ed25519.h"
static void setup_fuzzer(void) {
fuzz_common_setup();
@@ -59,6 +60,21 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
/* Could also check g**q mod p == 1 */
}
if (keytype == DROPBEAR_SIGNKEY_SK_ED25519 || keytype == DROPBEAR_SIGNKEY_ED25519) {
dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype);
if (eck && *eck) {
int i;
/* we've seen all-zero keys validate */
boguskey = 1;
for (i = 0; i < CURVE25519_LEN; i++) {
if ((*eck)->priv[i] != 0x00 || (*eck)->pub[i] != 0x00) {
boguskey = 0;
}
}
}
}
if (!boguskey) {
printf("Random key/signature managed to verify!\n");
abort();

View File

@@ -4,9 +4,11 @@
result=0
test -d fuzzcorpus && hg --repository fuzzcorpus/ pull || hg clone https://secure.ucc.asn.au/hg/dropbear-fuzzcorpus fuzzcorpus || exit 1
test -d fuzzcorpus && hg --repository fuzzcorpus/ pull || hg clone https://hg.ucc.asn.au/dropbear-fuzzcorpus fuzzcorpus || exit 1
for f in `make list-fuzz-targets`; do
./$f fuzzcorpus/$f/* || result=1
# use xargs to split the too-long argument list
# -q quiet because travis has a logfile limit
echo fuzzcorpus/$f/* | xargs -n 1000 ./$f -q || result=1
done
exit $result

File diff suppressed because it is too large Load Diff

View File

@@ -42,7 +42,7 @@ ARFLAGS = r
EXTRALIBS = ../libtommath/libtommath.a
#Compilation flags
LTC_CFLAGS = -Isrc/headers/ -I$(srcdir)/src/headers/ -I../ -I$(srcdir)/../ -DLTC_SOURCE -I../libtommath/ -I$(srcdir)/../libtommath/ $(CFLAGS)
LTC_CFLAGS = -Isrc/headers/ -I$(srcdir)/src/headers/ -I../ -I$(srcdir)/../src -DLTC_SOURCE -I../libtommath/ -I$(srcdir)/../libtommath/ $(CFLAGS) $(CPPFLAGS)
LTC_LDFLAGS = $(LDFLAGS) $(EXTRALIBS)
VERSION=1.18.1

View File

@@ -16,12 +16,6 @@
#if DROPBEAR_AES
#define LTC_RIJNDAEL
#endif
/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
* (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
#if DROPBEAR_TWOFISH
#define LTC_TWOFISH
#define LTC_TWOFISH_SMALL
#endif
#if DROPBEAR_3DES
#define LTC_DES
@@ -56,10 +50,8 @@
#define LTC_SHA256
#endif
#if DROPBEAR_SHA1
#define LTC_SHA1
#if DROPBEAR_MD5
#define LTC_MD5
#endif
/* ECC */

View File

@@ -6,8 +6,9 @@ VPATH=@srcdir@
srcdir=@srcdir@
# So that libtommath can include Dropbear headers for options and m_burn()
CFLAGS += -I$(srcdir) -I../libtomcrypt/src/headers/ -I$(srcdir)/../libtomcrypt/src/headers/ -I../ -I$(srcdir)/../
CFLAGS += -I$(srcdir) -I../libtomcrypt/src/headers/ -I$(srcdir)/../libtomcrypt/src/headers/ -I../ -I$(srcdir)/../src
CFLAGS += -Wno-deprecated
CFLAGS += $(CPPFLAGS)
V = 1
@@ -24,8 +25,14 @@ endif
coverage: LIBNAME:=-Wl,--whole-archive $(LIBNAME) -Wl,--no-whole-archive
# Dropbear sets its own flags below
IGNORE_SPEED=1
include $(srcdir)/makefile_include.mk
# override makefile_include.mk flags
LTM_CFLAGS += @DROPBEAR_LTM_CFLAGS@
%.o: %.c $(HEADERS)
ifneq ($V,1)
@echo " * ${CC} $@"

View File

@@ -12,6 +12,10 @@ mp_err mp_2expt(mp_int *a, int b)
{
mp_err err;
if (b < 0) {
return MP_VAL;
}
/* zero a as per default */
mp_zero(a);

View File

@@ -9,6 +9,10 @@ mp_err mp_grow(mp_int *a, int size)
int i;
mp_digit *tmp;
if (size < 0) {
return MP_VAL;
}
/* if the alloc size is smaller alloc more ram */
if (a->alloc < size) {
/* reallocate the array a->dp

View File

@@ -6,6 +6,11 @@
/* init an mp_init for a given size */
mp_err mp_init_size(mp_int *a, int size)
{
if (size < 0) {
return MP_VAL;
}
size = MP_MAX(MP_MIN_PREC, size);
/* alloc mem */

View File

@@ -9,6 +9,10 @@ mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c)
mp_digit d;
mp_err err;
if (b < 0) {
return MP_VAL;
}
/* copy */
if (a != c) {
if ((err = mp_copy(a, c)) != MP_OKAY) {

View File

@@ -3,11 +3,13 @@
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
mp_err(*s_mp_rand_source)(void *out, size_t size) = s_mp_rand_platform;
/* Dropbear sets this separately, avoid platform code */
mp_err(*s_mp_rand_source)(void *out, size_t size) = NULL;
void mp_rand_source(mp_err(*source)(void *out, size_t size))
{
s_mp_rand_source = (source == NULL) ? s_mp_rand_platform : source;
/* Dropbear, don't reset to platform if source==NULL */
s_mp_rand_source = source;
}
mp_err mp_rand(mp_int *a, int digits)

View File

@@ -16,6 +16,10 @@ mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
mp_word r;
mp_digit tmpx, *tmpt, *tmpy;
if (digs < 0) {
return MP_VAL;
}
/* can we use the fast multiplier? */
if ((digs < MP_WARRAY) &&
(MP_MIN(a->used, b->used) < MP_MAXFAST)) {

View File

@@ -26,6 +26,10 @@ mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs)
mp_digit W[MP_WARRAY];
mp_word _W;
if (digs < 0) {
return MP_VAL;
}
/* grow the destination as required */
if (c->alloc < digs) {
if ((err = mp_grow(c, digs)) != MP_OKAY) {

View File

@@ -15,6 +15,10 @@ mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
mp_word r;
mp_digit tmpx, *tmpt, *tmpy;
if (digs < 0) {
return MP_VAL;
}
/* can we use the fast multiplier? */
if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST)
&& ((a->used + b->used + 1) < MP_WARRAY)

View File

@@ -19,6 +19,10 @@ mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int
mp_digit W[MP_WARRAY];
mp_word _W;
if (digs < 0) {
return MP_VAL;
}
/* grow the destination as required */
pa = a->used + b->used;
if (c->alloc < pa) {

View File

@@ -104,7 +104,7 @@ LIBTOOLFLAGS += -no-undefined
endif
# add in the standard FLAGS
LTM_CFLAGS += $(CFLAGS)
LTM_CFLAGS := $(CFLAGS) $(LTM_CFLAGS)
LTM_LFLAGS += $(LFLAGS)
LTM_LDFLAGS += $(LDFLAGS)
LTM_LIBTOOLFLAGS += $(LIBTOOLFLAGS)

View File

@@ -1316,6 +1316,8 @@
#undef BN_S_MP_KARATSUBA_SQR_C
#undef BN_S_MP_TOOM_MUL_C
#undef BN_S_MP_TOOM_SQR_C
/* Dropbear uses its own random source */
#undef BN_S_MP_RAND_PLATFORM_C
#include "dbmalloc.h"
#define MP_MALLOC m_malloc

View File

@@ -1,4 +1,4 @@
.TH dbclient 1
.TH dbclient 1 2023-02-01
.SH NAME
dbclient \- lightweight SSH client
.SH SYNOPSIS
@@ -19,10 +19,9 @@ dbclient \- lightweight SSH client
.SH DESCRIPTION
.B dbclient
is a small SSH client
is the client part of Dropbear SSH
.SH OPTIONS
.TP
.TP
.B command
A command to run on the remote host. This will normally be run by the remote host
using the user's shell. The command begins at the first hyphen argument after the
@@ -44,27 +43,27 @@ from OpenSSH with dropbearconvert(1). The default path ~/.ssh/id_dropbear is use
.TP
.B \-L\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
Local port forwarding.
Forward the port
Forward
.I listenport
on the local host through the SSH connection to port
on the local host through the SSH connection to
.I port
on the host
on
.IR host .
.TP
.B \-R\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
Remote port forwarding.
Forward the port
Forward
.I listenport
on the remote host through the SSH connection to port
on the remote host through the SSH connection to
.I port
on the host
on
.IR host .
.TP
.B \-l \fIuser
Username.
Login as
.I user
on the remote host.
on the remote host. An alternative is to specify user@host.
.TP
.B \-t
Allocate a PTY. This is the default when no command is given, it gives a full
@@ -72,7 +71,7 @@ interactive remote session. The main effect is that keystrokes are sent remotely
immediately as opposed to local line-based editing.
.TP
.B \-T
Don't allocate a PTY. This is the default a command is given. See -t.
Don't allocate a PTY. This is the default when a command is given. See -t.
.TP
.B \-N
Don't request a remote shell or run any commands. Any command arguments are ignored.
@@ -94,7 +93,18 @@ is performed at all, this is usually undesirable.
.B \-A
Forward agent connections to the remote host. dbclient will use any
OpenSSH-style agent program if available ($SSH_AUTH_SOCK will be set) for
public key authentication. Forwarding is only enabled if -A is specified.
public key authentication. Forwarding is only enabled if \fI-A\fR is specified.
Beware that a forwarded agent connection will allow the remote server to have
the same authentication credentials as you have used locally. A compromised
remote server could use that to log in to other servers.
In many situations Dropbear's multi-hop mode is a better and more secure alternative
to agent forwarding, avoiding having to trust the intermediate server.
If the SSH agent program is set to prompt when a key is used, the
\fI-o DisableTrivialAuth\fR option can prevent UI confusion.
.TP
.B \-W \fIwindowsize
Specify the per-channel receive window buffer size. Increasing this
@@ -111,6 +121,9 @@ if 0 disables keepalives. If no response is received for 3 consecutive keepalive
.B \-I \fIidle_timeout
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
.TP
.B \-z
By default Dropbear will send network traffic with the \fBAF21\fR setting for QoS, letting network devices give it higher priority. Some devices may have problems with that, \fI-z\fR can be used to disable it.
.TP
.\" TODO: how to avoid a line break between these two -J arguments?
.B \-J \fIproxy_command
@@ -148,8 +161,54 @@ The following options have currently been implemented:
.RS
.TP
.B BatchMode
Disable interactive prompts e.g. password prompts and host key confirmation. The argument must be "yes" or "no" (the default).
.TP
.B BindAddress
Specify address and port on the local machine as the source address of the connection.
.TP
.B DisableTrivialAuth
Disallow a server immediately
giving successful authentication (without presenting any password/pubkey prompt).
This avoids a UI confusion issue where it may appear that the user is accepting
a SSH agent prompt from their local machine, but are actually accepting a prompt
sent immediately by the remote server.
.TP
.B ExitOnForwardFailure
Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be yes or no”. The default is “no”.
Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be "yes" or "no" (the default).
.TP
.B ForwardAgent
Forward the authentication agent to the remote machine. The argument must be "yes" or "no" (the default).
.TP
.B GatewayPorts
Allow to remote host to connect to local forwarded ports. The argument must be "yes" or "no" (the default).
.TP
.B IdentityFile
Specify an authentication identity file path.
.TP
.B PasswordAuthentication
Allow to prompt a user for a password. If the DROPBEAR_PASSWORD env is specified then it still will be used. The argument must be "yes" (the default) or "no".
.TP
.B Port
Specify a listening port, like the \fI-p\fR argument.
.TP
.B ProxyCommand
Specify the proxy command to use to connect to the server.
.TP
.B ServerAliveInterval
Sets a timeout interval in seconds between keep-alive messages through the encrypted channel. The default is 0 e.g. disabled.
.TP
.B StrictHostKeyChecking
Use "yes" to refuse connection to hosts where the host key is not already
correct in known_hosts. Entries must be added to known_hosts manually.
Use "no" to skip the known_hosts key checking.
Use "accept-new" to add new host keys to the known_hosts and
refuse to connect if the host key has changed.
"ask" is the default.
.TP
.B UseSyslog
Send dbclient log messages to syslog in addition to stderr.
@@ -198,6 +257,52 @@ SSH_ASKPASS should be set to the path of a program that will return a password
on standard output. This program will only be used if either DISPLAY is set and
standard input is not a TTY, or the environment variable SSH_ASKPASS_ALWAYS is
set.
.SH FILES
.B ~/.ssh/dropbear_config
This is the per user configuration file. A very limited subset of the keywords for
ssh_config(5) is supported, and none of the advanced features. The file contains
key value pairs on a single line separated with space or '='. Empty lines are ignored.
Text starting with '#' is a comment, and also ignored.
The file is not considered if multi-hop connection is used. Values on the command line
override the respective values in the file.
The recognized keywords are as follows. Keywords are case insensitive and values are
case insensitive.
.TP
.B Host
Defines the options that would be applied if this value matches the host specified
on the command line. The next Host entry or EOF determine the list of applicable
options.
.TP
.B HostName
Specifies the actual host name to connect to. Can be DNS name or IP address.
.TP
.B Port
Specifies the port number to use to connect to the remote host.
.TP
.B
User
Specifies the user name to login in as.
.TP
.B
IdentityFile
Specifies the file with the private key used for public key authentication with the remote
host. The file must be in the Dropbear format. See dropbearkey(1) to generate one. A '~/' at
the start of the path will expanded to the executing user's home directory. A path that
does not start with '/' will be treated relative to this configuration file's directory. Otherwise
the path will be used as is.
Because this file contains a secret it must have strict permissions to prevent abuse
attempts - read/write for the executing user, and no access to anyone else.
.SH NOTES
If compiled with zlib support and if the server supports it, dbclient will
always use compression.

View File

@@ -35,6 +35,12 @@ Don't fork into background.
.B \-E
Log to standard error rather than syslog.
.TP
.B \-e
Pass on the server environment to all child processes. This is required, for example,
if Dropbear is launched on the fly from a SLURM workload manager. The environment is not
passed by default. Note that this could expose secrets in environment variables from
the calling process - use with caution.
.TP
.B \-m
Don't display the message of the day on login.
.TP
@@ -47,8 +53,12 @@ Disable password logins.
.B \-g
Disable password logins for root.
.TP
.B \-t
Enable two-factor authentication. Both password login and public key authentication are
required. Should not be used with the '-s' option.
.TP
.B \-j
Disable local port forwarding.
Disable local port forwarding. This includes unix stream forwards.
.TP
.B \-k
Disable remote port forwarding.
@@ -60,7 +70,11 @@ and TCP
.I port.
If just a port is given listen
on all addresses.
up to 10 can be specified (default 22 if none specified).
Up to 10 can be specified (default 22 if none specified).
.TP
.B \-l \fIinterface
Listen on the specified
.I interface
.TP
.B \-i
Service program mode.
@@ -86,17 +100,21 @@ Ensure that traffic is transmitted at a certain interval in seconds. This is
useful for working around firewalls or routers that drop connections after
a certain period of inactivity. The trade-off is that a session may be
closed if there is a temporary lapse of network connectivity. A setting
if 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
of 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
.TP
.B \-I \fIidle_timeout
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
.TP
.B \-z
By default Dropbear will send network traffic with the \fBAF21\fR setting for QoS, letting network devices give it higher priority. Some devices may have problems with that, \fI-z\fR can be used to disable it.
.TP
.B \-T \fImax_authentication_attempts
Set the number of authentication attempts allowed per connection. If unspecified the default is 10 (MAX_AUTH_TRIES)
.TP
.B \-c \fIforced_command
Disregard the command provided by the user and always run \fIforced_command\fR. This also
overrides any authorized_keys command= option.
overrides any authorized_keys command= option. The original command is saved in the
SSH_ORIGINAL_COMMAND environment variable (see below).
.TP
.B \-V
Print the version
@@ -118,7 +136,7 @@ Available restrictions are:
.TP
.B no-port-forwarding
Don't allow port forwarding for this connection
Don't allow port forwarding for this connection, including unix streams.
.TP
.B no-agent-forwarding
@@ -133,6 +151,18 @@ Don't allow X11 forwarding for this connection
Disable PTY allocation. Note that a user can still obtain most of the
same functionality with other means even if no-pty is set.
.TP
.B restrict
Applies all the no- restrictions listed above.
.TP
.B permitopen=\fR"\fIhost:port\fR"
Restrict local port forwarding so that connection is allowed only to the
specified host and port. Multiple permitopen options separated by commas
can be set in authorized_keys. Wildcard character ('*') may be used in
port specification for matching any port. Hosts must be literal domain names or
IP addresses.
.TP
.B command=\fR"\fIforced_command\fR"
Disregard the command provided by the user and always run \fIforced_command\fR.

View File

@@ -9,7 +9,7 @@ dropbearconvert \- convert between Dropbear and OpenSSH private key formats
.I output_file
.SH DESCRIPTION
.B Dropbear
and
and
.B OpenSSH
SSH implementations have different private key formats.
.B dropbearconvert
@@ -24,15 +24,15 @@ first.
.SH ARGUMENTS
.TP
.I input_type
Either
Either
.I dropbear
or
or
.I openssh
.TP
.I output_type
Either
Either
.I dropbear
or
or
.I openssh
.TP
.I input_file
@@ -40,6 +40,15 @@ An existing Dropbear or OpenSSH private key file
.TP
.I output_file
The path to write the converted private key file. For client authentication ~/.ssh/id_dropbear is loaded by default
.SH SUPPORTED FORMATS
.B dropbearconvert
can read OpenSSH format files, and older PEM format files (
.B ssh-keygen
.I -m PEM
).
.B dropbearconvert
will write OpenSSH format files, usable with OpenSSH 6.5 and later.
Reading OpenSSH format DSS files or PKCS8 files is not currently supported.
.SH EXAMPLE
# dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_dropbear
.SH AUTHOR

View File

@@ -1,22 +1,52 @@
#!/bin/sh
VERSION=$(echo '#include "sysoptions.h"\necho DROPBEAR_VERSION' | cpp - | sh)
echo Releasing version "$VERSION" ...
if ! head -n1 CHANGES | grep -q $VERSION ; then
echo "CHANGES needs updating"
exit 1
set -e
if [ "$1" = '--testrel' ]; then
# --testrel won't check changelog version correctness and will build in a temporary dir
TESTREL=1
else
TESTREL=0
fi
if ! head -n1 debian/changelog | grep -q $VERSION ; then
echo "debian/changelog needs updating"
exit 1
VERSION=$(echo '#include "src/default_options.h"\n#include "src/sysoptions.h"\necho DROPBEAR_VERSION' | cpp -DHAVE_CRYPT - | sh)
if [ $TESTREL -eq 1 ]; then
echo Making test tarball for "$VERSION" ...
echo Not checking version mismatches.
WORKDIR=$(mktemp -d)
TARSUFFIX="-testrel"
else
if ! git diff -s --exit-code; then
echo "Git isn't clean"
exit 1
fi
echo Releasing version "$VERSION" ...
if ! head -n1 CHANGES | grep -q $VERSION ; then
echo "CHANGES needs updating"
exit 1
fi
if ! head -n1 debian/changelog | grep -q $VERSION ; then
echo "debian/changelog needs updating"
exit 1
fi
WORKDIR=$PWD/..
TARSUFFIX=""
fi
RELDIR=$WORKDIR/dropbear-$VERSION
ARCHIVE=${RELDIR}${TARSUFFIX}.tar.bz2
head -n1 CHANGES
#sleep 3
if tar --version | grep -q 'GNU tar'; then
TAR=tar
else
TAR=gtar
fi
RELDIR=$PWD/../dropbear-$VERSION
ARCHIVE=${RELDIR}.tar.bz2
if test -e $RELDIR; then
echo "$RELDIR exists"
exit 1
@@ -27,19 +57,24 @@ if test -e $ARCHIVE; then
exit 1
fi
hg archive "$RELDIR" || exit 2
git -c tar.umask=0022 archive --format tar -o /dev/stdout --prefix=dropbear-$VERSION/ HEAD | tar xf - -C $WORKDIR || exit 2
(cd "$RELDIR" && autoconf && autoheader) || exit 2
chmod -R a+rX $RELDIR
rm -r "$RELDIR/autom4te.cache" || exit 2
RELDATE=$(head -n1 CHANGES | cut -d - -f 2)
# timezone keeps it consistent, choose a plausible release time
RELTIME="22:30:00 +0800"
rm "$RELDIR/.hgtags"
(cd "$RELDIR/.." && tar cjf $ARCHIVE `basename "$RELDIR"`) || exit 2
# from https://reproducible-builds.org/docs/archives/
TAROPTS="--sort=name --owner=0 --group=0 --numeric-owner"
(cd "$RELDIR/.." && $TAR cjf $ARCHIVE $TAROPTS --mtime="$RELDATE $RELTIME" `basename "$RELDIR"`) || exit 2
ls -l $ARCHIVE
openssl sha256 $ARCHIVE
echo Done to
echo "$ARCHIVE"
echo Sign it with
echo gpg2 --detach-sign -a -u F29C6773 "$ARCHIVE"
if [ $TESTREL -eq 0 ]; then
echo Sign it with
echo gpg --detach-sign -a -u F29C6773 "$ARCHIVE"
fi

View File

View File

@@ -28,9 +28,9 @@
#include "includes.h"
#include "signkey.h"
#include "chansession.h"
#include "list.h"
void svr_authinitialise(void);
void cli_authinitialise(void);
/* Server functions */
void recv_msg_userauth_request(void);
@@ -46,6 +46,7 @@ int svr_pubkey_allows_agentfwd(void);
int svr_pubkey_allows_tcpfwd(void);
int svr_pubkey_allows_x11fwd(void);
int svr_pubkey_allows_pty(void);
int svr_pubkey_allows_local_tcpfwd(const char *host, unsigned int port);
void svr_pubkey_set_forced_command(struct ChanSess *chansess);
void svr_pubkey_options_cleanup(void);
int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filename);
@@ -55,6 +56,9 @@ int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filena
#define svr_pubkey_allows_tcpfwd() 1
#define svr_pubkey_allows_x11fwd() 1
#define svr_pubkey_allows_pty() 1
static inline int svr_pubkey_allows_local_tcpfwd(const char *host, unsigned int port)
{ (void)host; (void)port; return 1; }
static inline void svr_pubkey_set_forced_command(struct ChanSess *chansess) { }
static inline void svr_pubkey_options_cleanup(void) { }
#define svr_add_pubkey_options(x,y,z) DROPBEAR_SUCCESS
@@ -94,6 +98,7 @@ void cli_auth_pubkey_cleanup(void);
#define AUTH_METHOD_INTERACT "keyboard-interactive"
#define AUTH_METHOD_INTERACT_LEN 20
#define PUBKEY_OPTIONS_ANY_PORT UINT_MAX
/* This structure is shared between server and client - it contains
@@ -126,6 +131,7 @@ struct AuthState {
char *pw_passwd;
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
struct PubKeyOptions* pubkey_options;
char *pubkey_info;
#endif
};
@@ -139,6 +145,18 @@ struct PubKeyOptions {
int no_pty_flag;
/* "command=" option. */
char * forced_command;
/* "permitopen=" option */
m_list *permit_open_destinations;
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
int no_touch_required_flag;
int verify_required_flag;
#endif
};
struct PermitTCPFwdEntry {
char *host;
unsigned int port;
};
#endif

View File

@@ -93,12 +93,12 @@ void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len) {
/* hash the ssh representation of the mp_int mp */
void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
hash_state *hs, mp_int *mp) {
hash_state *hs, const mp_int *mp) {
buffer * buf;
buf = buf_new(512 + 20); /* max buffer is a 4096 bit key,
plus header + some leeway*/
buf_putmpint(buf, mp);
hash_desc->process(hs, buf->data, buf->len);
buf_free(buf);
buf_burn_free(buf);
}

View File

@@ -33,6 +33,6 @@ void m_mp_alloc_init_multi(mp_int **mp, ...) ATTRIB_SENTINEL;
void m_mp_free_multi(mp_int **mp, ...) ATTRIB_SENTINEL;
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len);
void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
hash_state *hs, mp_int *mp);
hash_state *hs, const mp_int *mp);
#endif /* DROPBEAR_BIGNUM_H_ */

View File

@@ -39,44 +39,32 @@
/* Create (malloc) a new buffer of size */
buffer* buf_new(unsigned int size) {
buffer* buf;
if (size > BUF_MAX_SIZE) {
dropbear_exit("buf->size too big");
}
buf = (buffer*)m_malloc(sizeof(buffer)+size);
if (size > 0) {
buf->data = (unsigned char*)buf + sizeof(buffer);
} else {
buf->data = NULL;
}
buf->data = (unsigned char*)buf + sizeof(buffer);
buf->size = size;
return buf;
}
/* free the buffer's data and the buffer itself */
void buf_free(buffer* buf) {
m_free(buf);
}
/* overwrite the contents of the buffer to clear it */
void buf_burn(const buffer* buf) {
/* overwrite the contents of the buffer then free it */
void buf_burn_free(buffer* buf) {
m_burn(buf->data, buf->size);
m_free(buf);
}
/* resize a buffer, pos and len will be repositioned if required when
* downsizing */
buffer* buf_resize(buffer *buf, unsigned int newsize) {
if (newsize > BUF_MAX_SIZE) {
dropbear_exit("buf->size too big");
}
@@ -139,18 +127,23 @@ void buf_incrwritepos(buffer* buf, unsigned int incr) {
}
}
/* increment the position by incr, negative values are allowed, to
* decrement the pos*/
void buf_incrpos(buffer* buf, int incr) {
/* increment the position by incr */
void buf_incrpos(buffer* buf, unsigned int incr) {
if (incr > BUF_MAX_INCR
|| incr < -BUF_MAX_INCR
|| (unsigned int)((int)buf->pos + incr) > buf->len
|| ((int)buf->pos + incr) < 0) {
|| (buf->pos + incr) > buf->len) {
dropbear_exit("Bad buf_incrpos");
}
buf->pos += incr;
}
/* decrement the position by decr */
void buf_decrpos(buffer* buf, unsigned int decr) {
if (decr > buf->pos) {
dropbear_exit("Bad buf_decrpos");
}
buf->pos -= decr;
}
/* Get a byte from the buffer and increment the pos */
unsigned char buf_getbyte(buffer* buf) {
@@ -306,7 +299,7 @@ void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
/* for our purposes we only need positive (or 0) numbers, so will
* fail if we get negative numbers */
void buf_putmpint(buffer* buf, mp_int * mp) {
void buf_putmpint(buffer* buf, const mp_int * mp) {
size_t written;
unsigned int len, pad = 0;
TRACE2(("enter buf_putmpint"))

View File

@@ -44,12 +44,13 @@ buffer * buf_new(unsigned int size);
/* Possibly returns a new buffer*, like realloc() */
buffer * buf_resize(buffer *buf, unsigned int newsize);
void buf_free(buffer* buf);
void buf_burn(const buffer* buf);
void buf_burn_free(buffer* buf);
buffer* buf_newcopy(const buffer* buf);
void buf_setlen(buffer* buf, unsigned int len);
void buf_incrlen(buffer* buf, unsigned int incr);
void buf_setpos(buffer* buf, unsigned int pos);
void buf_incrpos(buffer* buf, int incr); /* -ve is ok, to go backwards */
void buf_incrpos(buffer* buf, unsigned int incr);
void buf_decrpos(buffer* buf, unsigned int decr);
void buf_incrwritepos(buffer* buf, unsigned int incr);
unsigned char buf_getbyte(buffer* buf);
unsigned char buf_getbool(buffer* buf);
@@ -64,7 +65,7 @@ void buf_putint(buffer* buf, unsigned int val);
void buf_putstring(buffer* buf, const char* str, unsigned int len);
void buf_putbufstring(buffer *buf, const buffer* buf_str);
void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len);
void buf_putmpint(buffer* buf, mp_int * mp);
void buf_putmpint(buffer* buf, const mp_int * mp);
int buf_getmpint(buffer* buf, mp_int* mp);
unsigned int buf_getint(buffer* buf);

View File

@@ -28,6 +28,7 @@
#include "includes.h"
#include "buffer.h"
#include "circbuffer.h"
#include "netio.h"
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
#define SSH_OPEN_CONNECT_FAILED 2
@@ -41,13 +42,6 @@
struct ChanType;
enum dropbear_channel_prio {
DROPBEAR_CHANNEL_PRIO_INTERACTIVE, /* pty shell, x11 */
DROPBEAR_CHANNEL_PRIO_UNKNOWABLE, /* tcp - can't know what's being forwarded */
DROPBEAR_CHANNEL_PRIO_BULK, /* the rest - probably scp or something */
DROPBEAR_CHANNEL_PRIO_EARLY, /* channel is still being set up */
};
struct Channel {
unsigned int index; /* the local channel index */
@@ -60,6 +54,10 @@ struct Channel {
int readfd; /* read from insecure side, written to wire */
int errfd; /* used like writefd or readfd, depending if it's client or server.
Doesn't exactly belong here, but is cleaner here */
int bidir_fd; /* a boolean indicating that writefd/readfd are the same
file descriptor (bidirectional), such as a network sockets.
That is handled differently when closing FDs. Is only
applicable to sockets (which can be used with shutdown()) */
circbuffer *writebuf; /* data from the wire, for local consumption. Can be
initially NULL */
circbuffer *extrabuf; /* extended-data for the program - used like writebuf
@@ -68,6 +66,9 @@ struct Channel {
/* whether close/eof messages have been exchanged */
int sent_close, recv_close;
int recv_eof, sent_eof;
/* once flushing is set, readfd will close once no more data is available
(not waiting for EOF) */
int flushing;
struct dropbear_progress_connection *conn_pending;
int initconn; /* used for TCP forwarding, whether the channel has been
@@ -77,25 +78,22 @@ struct Channel {
for this channel (and are awaiting a confirmation
or failure). */
int flushing;
/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
void (*read_mangler)(const struct Channel*, const unsigned char* bytes, int *len);
const struct ChanType* type;
enum dropbear_channel_prio prio;
enum dropbear_prio prio;
};
struct ChanType {
int sepfds; /* Whether this channel has separate pipes for in/out or not */
const char *name;
/* Sets up the channel */
int (*inithandler)(struct Channel*);
/* Called to check whether a channel should close, separately from the FD being closed.
/* Called to check whether a channel should close, separately from the FD being EOF.
Used for noticing process exiting */
int (*check_close)(const struct Channel*);
int (*check_close)(struct Channel*);
/* Handler for ssh_msg_channel_request */
void (*reqhandler)(struct Channel*);
/* Called prior to sending ssh_msg_channel_close, used for sending exit status */
@@ -104,7 +102,7 @@ struct ChanType {
void (*cleanup)(const struct Channel*);
};
/* Callback for connect_remote */
/* Callback for connect_remote/connect_streamlocal. errstring may be NULL if result == DROPBEAR_SUCCESS */
void channel_connect_done(int result, int sock, void* user_data, const char* errstring);
void chaninitialise(const struct ChanType *chantypes[]);

View File

@@ -47,7 +47,6 @@
static int new_agent_chan(struct Channel * channel);
const struct ChanType cli_chan_agent = {
0, /* sepfds */
"auth-agent@openssh.com",
new_agent_chan,
NULL,
@@ -94,6 +93,7 @@ static int new_agent_chan(struct Channel * channel) {
channel->readfd = fd;
channel->writefd = fd;
channel->bidir_fd = 1;
return 0;
}

View File

@@ -32,12 +32,6 @@
#include "packet.h"
#include "runopts.h"
void cli_authinitialise() {
memset(&ses.authstate, 0, sizeof(ses.authstate));
}
/* Send a "none" auth request to get available methods */
void cli_auth_getmethods() {
TRACE(("enter cli_auth_getmethods"))
@@ -88,6 +82,11 @@ void recv_msg_userauth_banner() {
return;
}
if (cli_opts.quiet) {
TRACE(("not showing banner"))
return;
}
banner = buf_getstring(ses.payload, &bannerlen);
buf_eatstring(ses.payload); /* The language string */
@@ -162,6 +161,7 @@ void recv_msg_userauth_failure() {
unsigned int methlen = 0;
unsigned int partial = 0;
unsigned int i = 0;
int allow_pw_auth = 1;
TRACE(("<- MSG_USERAUTH_FAILURE"))
TRACE(("enter recv_msg_userauth_failure"))
@@ -176,6 +176,13 @@ void recv_msg_userauth_failure() {
dropbear_exit("Unexpected userauth failure");
}
/* Password authentication is only allowed in batch mode
* when a password can be provided non-interactively */
if (cli_opts.batch_mode && !getenv(DROPBEAR_PASSWORD_ENV)) {
allow_pw_auth = 0;
}
allow_pw_auth &= cli_opts.password_authentication;
/* When DROPBEAR_CLI_IMMEDIATE_AUTH is set there will be an initial response for
the "none" auth request, and then a response to the immediate auth request.
We need to be careful handling them. */
@@ -240,14 +247,14 @@ void recv_msg_userauth_failure() {
}
#endif
#if DROPBEAR_CLI_INTERACT_AUTH
if (strncmp(AUTH_METHOD_INTERACT, tok,
AUTH_METHOD_INTERACT_LEN) == 0) {
if (allow_pw_auth
&& strncmp(AUTH_METHOD_INTERACT, tok, AUTH_METHOD_INTERACT_LEN) == 0) {
ses.authstate.authtypes |= AUTH_TYPE_INTERACT;
}
#endif
#if DROPBEAR_CLI_PASSWORD_AUTH
if (strncmp(AUTH_METHOD_PASSWORD, tok,
AUTH_METHOD_PASSWORD_LEN) == 0) {
if (allow_pw_auth
&& strncmp(AUTH_METHOD_PASSWORD, tok, AUTH_METHOD_PASSWORD_LEN) == 0) {
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
}
#endif
@@ -266,7 +273,10 @@ void recv_msg_userauth_success() {
/* This function can validly get called multiple times
if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
TRACE(("received msg_userauth_success"))
DEBUG1(("received msg_userauth_success"))
if (cli_opts.disable_trivial_auth && cli_ses.is_trivial_auth) {
dropbear_exit("trivial authentication not allowed");
}
/* Note: in delayed-zlib mode, setting authdone here
* will enable compression in the transport layer */
ses.authstate.authdone = 1;
@@ -294,20 +304,8 @@ int cli_auth_try() {
}
#endif
#if DROPBEAR_CLI_PASSWORD_AUTH
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_PASSWORD)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
} else {
cli_auth_password();
finished = 1;
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
}
}
#endif
#if DROPBEAR_CLI_INTERACT_AUTH
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) {
if (!finished && cli_opts.password_authentication && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
fprintf(stderr, "Sorry, I won't let you use interactive auth unencrypted.\n");
} else {
@@ -320,6 +318,18 @@ int cli_auth_try() {
}
#endif
#if DROPBEAR_CLI_PASSWORD_AUTH
if (!finished && cli_opts.password_authentication && (ses.authstate.authtypes & AUTH_TYPE_PASSWORD)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
} else {
cli_auth_password();
finished = 1;
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
}
}
#endif
TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype))
if (finished) {
@@ -345,8 +355,13 @@ char* getpass_or_cancel(const char* prompt)
return password;
}
#endif
if (cli_opts.batch_mode) {
dropbear_close("BatchMode active, no interactive session possible.");
}
password = getpass(prompt);
if (!cli_opts.batch_mode) {
password = getpass(prompt);
}
/* 0x03 is a ctrl-c character in the buffer. */
if (password == NULL || strchr(password, '\3') != NULL) {

View File

@@ -115,6 +115,7 @@ void recv_msg_userauth_info_request() {
for (i = 0; i < num_prompts; i++) {
unsigned int response_len = 0;
cli_ses.is_trivial_auth = 0;
prompt = buf_getstring(ses.payload, NULL);
cleantext(prompt);

View File

@@ -120,7 +120,7 @@ void cli_auth_password() {
char* password = NULL;
char prompt[80];
TRACE(("enter cli_auth_password"))
DEBUG1(("enter cli_auth_password"))
CHECKCLEARTOWRITE();
snprintf(prompt, sizeof(prompt), "%s@%s's password: ",
@@ -155,7 +155,7 @@ void cli_auth_password() {
encrypt_packet();
m_burn(password, strlen(password));
cli_ses.is_trivial_auth = 0;
TRACE(("leave cli_auth_password"))
}
#endif /* DROPBEAR_CLI_PASSWORD_AUTH */

View File

@@ -66,6 +66,10 @@ void recv_msg_userauth_pk_ok() {
algotype = buf_getstring(ses.payload, &algolen);
sigtype = signature_type_from_name(algotype, algolen);
if (sigtype == DROPBEAR_SIGNATURE_NONE) {
/* Server replied with an algorithm that we didn't send */
dropbear_exit("Bad pk_ok");
}
keytype = signkey_type_from_signature(sigtype);
TRACE(("recv_msg_userauth_pk_ok: type %d", sigtype))
m_free(algotype);
@@ -125,7 +129,7 @@ void recv_msg_userauth_pk_ok() {
static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
const buffer *data_buf) {
#if DROPBEAR_CLI_AGENTFWD
// TODO: rsa-sha256 agent
/* TODO: rsa-sha256 agent */
if (key->source == SIGNKEY_SOURCE_AGENT) {
/* Format the agent signature ourselves, as buf_put_sign would. */
buffer *sigblob;
@@ -147,7 +151,7 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype,
buffer* sigbuf = NULL;
enum signkey_type keytype = signkey_type_from_signature(sigtype);
TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype))
DEBUG1(("enter send_msg_userauth_pubkey %s", signature_name_from_type(sigtype, NULL)))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
@@ -176,6 +180,7 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype,
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf);
buf_free(sigbuf); /* Nothing confidential in the buffer */
cli_ses.is_trivial_auth = 0;
}
encrypt_packet();

View File

@@ -46,7 +46,6 @@ static int cli_init_netcat(struct Channel *channel);
static void cli_tty_setup(void);
const struct ChanType clichansess = {
0, /* sepfds */
"session", /* name */
cli_initchansess, /* inithandler */
NULL, /* checkclosehandler */
@@ -344,11 +343,11 @@ static int cli_init_stdpipe_sess(struct Channel *channel) {
setnonblocking(STDERR_FILENO);
channel->extrabuf = cbuf_new(opts.recv_window);
channel->bidir_fd = 0;
return 0;
}
static int cli_init_netcat(struct Channel *channel) {
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
return cli_init_stdpipe_sess(channel);
}
@@ -361,12 +360,9 @@ static int cli_initchansess(struct Channel *channel) {
cli_setup_agent(channel);
}
#endif
if (cli_opts.wantpty) {
send_chansess_pty_req(channel);
channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
} else {
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
channel->prio = DROPBEAR_PRIO_LOWDELAY;
}
send_chansess_shell_req(channel);
@@ -375,7 +371,7 @@ static int cli_initchansess(struct Channel *channel) {
cli_tty_setup();
channel->read_mangler = cli_escape_handler;
cli_ses.last_char = '\r';
}
}
return 0; /* Success */
}
@@ -383,7 +379,6 @@ static int cli_initchansess(struct Channel *channel) {
#if DROPBEAR_CLI_NETCAT
static const struct ChanType cli_chan_netcat = {
0, /* sepfds */
"direct-tcpip",
cli_init_netcat, /* inithandler */
NULL,

View File

@@ -46,6 +46,13 @@ void send_msg_kexdh_init() {
TRACE(("send_msg_kexdh_init()"))
CHECKCLEARTOWRITE();
#if DROPBEAR_FUZZ
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
return;
}
#endif
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
switch (ses.newkeys->algo_kex->mode) {
#if DROPBEAR_NORMAL_DH
@@ -98,6 +105,12 @@ void recv_msg_kexdh_reply() {
unsigned char* keyblob = NULL;
TRACE(("enter recv_msg_kexdh_reply"))
#if DROPBEAR_FUZZ
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
return;
}
#endif
if (cli_ses.kex_state != KEXDH_INIT_SENT) {
dropbear_exit("Received out-of-order kexdhreply");
@@ -196,6 +209,15 @@ static void ask_to_confirm(const unsigned char* keyblob, unsigned int keybloblen
int response = 'z';
fp = sign_key_fingerprint(keyblob, keybloblen);
if (!cli_opts.ask_hostkey) {
dropbear_log(LOG_INFO, "\nHost '%s' key unknown.\n(%s fingerprint %s)",
cli_opts.remotehost,
algoname,
fp);
dropbear_exit("Not accepted automatically");
}
if (cli_opts.always_accept_key) {
dropbear_log(LOG_INFO, "\nHost '%s' key accepted unconditionally.\n(%s fingerprint %s)\n",
cli_opts.remotehost,
@@ -204,18 +226,25 @@ static void ask_to_confirm(const unsigned char* keyblob, unsigned int keybloblen
m_free(fp);
return;
}
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\nDo you want to continue connecting? (y/n) ",
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\n",
cli_opts.remotehost,
algoname,
fp);
m_free(fp);
if (cli_opts.batch_mode) {
dropbear_exit("Didn't validate host key");
}
fprintf(stderr, "Do you want to continue connecting? (y/n) ");
tty = fopen(_PATH_TTY, "r");
if (tty) {
response = getc(tty);
fclose(tty);
} else {
response = getc(stdin);
/* flush stdin buffer */
while ((getchar()) != '\n');
}
if (response == 'y') {
@@ -358,7 +387,7 @@ static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen)
if (ret == DROPBEAR_SUCCESS) {
/* Good matching key */
TRACE(("good matching key"))
DEBUG1(("server match %s", fingerprint))
goto out;
}
@@ -384,7 +413,7 @@ static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen)
goto out;
}
if (!cli_opts.always_accept_key) {
if (!cli_opts.no_hostkey_check) {
/* put the new entry in the file */
fseek(hostsfile, 0, SEEK_END); /* In case it wasn't opened append */
buf_setpos(line, 0);

View File

@@ -31,9 +31,7 @@
#include "dbrandom.h"
#include "crypto_desc.h"
#include "netio.h"
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
static void cli_dropbear_log(int priority, const char* format, va_list param);
#include "fuzz.h"
#if DROPBEAR_CLI_PROXYCMD
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out);
@@ -49,6 +47,7 @@ int main(int argc, char ** argv) {
int sock_in, sock_out;
struct dropbear_progress_connection *progress = NULL;
pid_t proxy_cmd_pid = 0;
_dropbear_exit = cli_dropbear_exit;
_dropbear_log = cli_dropbear_log;
@@ -66,14 +65,17 @@ int main(int argc, char ** argv) {
}
#endif
TRACE(("user='%s' host='%s' port='%s' bind_address='%s' bind_port='%s'", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport, cli_opts.bind_address, cli_opts.bind_port))
if (cli_opts.bind_address) {
DEBUG1(("connect to: user=%s host=%s/%s bind_address=%s:%s", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport, cli_opts.bind_address, cli_opts.bind_port))
} else {
DEBUG1(("connect to: user=%s host=%s/%s",cli_opts.username,cli_opts.remotehost,cli_opts.remoteport))
}
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
dropbear_exit("signal() error");
}
pid_t proxy_cmd_pid = 0;
#if DROPBEAR_CLI_PROXYCMD
if (cli_opts.proxycmd) {
cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid);
@@ -86,8 +88,9 @@ int main(int argc, char ** argv) {
} else
#endif
{
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port);
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port,
DROPBEAR_PRIO_LOWDELAY);
sock_in = sock_out = -1;
}
@@ -98,58 +101,6 @@ int main(int argc, char ** argv) {
}
#endif /* DBMULTI stuff */
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
char exitmsg[150];
char fullmsg[300];
/* Note that exit message must be rendered before session cleanup */
/* Render the formatted exit message */
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
TRACE(("Exited, cleaning up: %s", exitmsg))
/* Add the prefix depending on session/auth state */
if (!ses.init_done) {
snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
} else {
snprintf(fullmsg, sizeof(fullmsg),
"Connection to %s@%s:%s exited: %s",
cli_opts.username, cli_opts.remotehost,
cli_opts.remoteport, exitmsg);
}
/* Do the cleanup first, since then the terminal will be reset */
session_cleanup();
/* Avoid printing onwards from terminal cruft */
fprintf(stderr, "\n");
dropbear_log(LOG_INFO, "%s", fullmsg);
exit(exitcode);
}
static void cli_dropbear_log(int priority,
const char* format, va_list param) {
char printbuf[1024];
const char *name;
name = cli_opts.progname;
if (!name) {
name = "dbclient";
}
vsnprintf(printbuf, sizeof(printbuf), format, param);
#ifndef DISABLE_SYSLOG
if (opts.usingsyslog) {
syslog(priority, "%s", printbuf);
}
#endif
fprintf(stderr, "%s: %s\n", name, printbuf);
fflush(stderr);
}
static void exec_proxy_cmd(const void *user_data_cmd) {
const char *cmd = user_data_cmd;
char *usershell;
@@ -188,6 +139,7 @@ static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out) {
ret = spawn_command(exec_proxy_cmd, ex_cmd,
sock_out, sock_in, NULL, pid_out);
DEBUG1(("cmd: %s pid=%d", ex_cmd,*pid_out))
m_free(ex_cmd);
if (ret == DROPBEAR_FAILURE) {
dropbear_exit("Failed running proxy command");
@@ -199,4 +151,5 @@ static void kill_proxy_sighandler(int UNUSED(signo)) {
kill_proxy_command();
_exit(1);
}
#endif /* DROPBEAR_CLI_PROXYCMD */

177
src/cli-readconf.c Normal file
View File

@@ -0,0 +1,177 @@
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2023 TJ Kolev
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#include "dbutil.h"
#include "runopts.h"
#if DROPBEAR_USE_SSH_CONFIG
#define TOKEN_CHARS " =\t\n"
static const size_t MAX_CONF_LINE = 200;
typedef enum {
opHost,
opHostName,
opHostPort,
opLoginUser,
opIdentityFile,
} cfg_option;
static const struct {
const char *name;
cfg_option option;
}
config_options[] = {
/* Start of config section. */
{ "host", opHost },
{ "hostname", opHostName },
{ "port", opHostPort },
{ "user", opLoginUser },
{ "identityfile", opIdentityFile },
};
void read_config_file(char* filename, FILE* config_file, cli_runopts* options) {
char *line = NULL;
int linenum = 0;
buffer *buf = NULL;
char* cfg_key;
char* cfg_val;
char* saveptr;
int in_host_section = 0;
DEBUG1(("Reading '%.200s'", filename));
buf = buf_new(MAX_CONF_LINE);
line = buf->data;
while (buf_getline(buf, config_file) == DROPBEAR_SUCCESS) {
char* commentStart = NULL;
cfg_option cfg_opt;
int found;
size_t i;
/* Update line number counter. */
linenum++;
/* Add nul terminator */
if (buf->len == buf->size) {
dropbear_exit("Long line %s:%d", filename, linenum);
}
buf_setpos(buf, buf->len);
buf_putbyte(buf, '\0');
buf_setpos(buf, 0);
commentStart = strchr(line, '#');
if (NULL != commentStart) {
*commentStart = '\0'; /* Drop the comments. */
}
cfg_key = strtok_r(line, TOKEN_CHARS, &saveptr);
if (NULL == cfg_key) {
continue;
}
found = 0;
for (i = 0; i < ARRAY_SIZE(config_options); i++) {
if (0 == strcasecmp(cfg_key, config_options[i].name)) {
cfg_opt = config_options[i].option;
found = 1;
break;
}
}
if (!found) {
dropbear_exit("Unsupported option %s at %s:%d", cfg_key, filename, linenum);
}
cfg_val = strtok_r(NULL, TOKEN_CHARS, &saveptr);
if (NULL == cfg_val) {
dropbear_exit("Missing value for %s at %s:%d", cfg_key, filename, linenum);
}
if (in_host_section) {
switch (cfg_opt) {
case opHost: {
/* Hit the next host section. Done reading config. */
goto outloop;
}
case opHostName: {
/* The host name is the alias given on the command line.
* Set the actual remote host specified in the config.
*/
m_free(options->remotehost);
options->remotehost = m_strdup(cfg_val);
options->remotehostfixed = 1; /* Subsequent command line parsing should leave it alone. */
break;
}
case opHostPort: {
m_free(options->remoteport);
options->remoteport = m_strdup(cfg_val);
break;
}
case opLoginUser: {
m_free(options->username);
options->username = m_strdup(cfg_val);
break;
}
case opIdentityFile: {
#if DROPBEAR_CLI_PUBKEY_AUTH
char* key_file_path;
if (strncmp(cfg_val, "~/", 2) == 0) {
key_file_path = expand_homedir_path(cfg_val);
} else if (cfg_val[0] != '/') {
char* config_dir = dirname(filename);
int path_len = strlen(config_dir) + strlen(cfg_val) + 10;
key_file_path = m_malloc(path_len);
snprintf(key_file_path, path_len, "%s/%s", config_dir, cfg_val);
} else {
key_file_path = m_strdup(cfg_val);
}
loadidentityfile(key_file_path, 1);
m_free(key_file_path);
#else
dropbear_exit("identityfile isn't supported in %s", filename);
#endif
break;
}
}
}
else
{
if (opHost != cfg_opt || 0 != strcmp(cfg_val, options->remotehost)) {
/* Not our host section. */
continue;
}
in_host_section = 1;
}
}
outloop:
buf_free(buf);
}
#endif /* DROPBEAR_USE_SSH_CONFIG */

View File

@@ -1,19 +1,19 @@
/*
* Dropbear - a SSH2 server
*
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -37,9 +37,6 @@ static void printhelp(void);
static void parse_hostname(const char* orighostarg);
static void parse_multihop_hostname(const char* orighostarg, const char* argv0);
static void fill_own_user(void);
#if DROPBEAR_CLI_PUBKEY_AUTH
static void loadidentityfile(const char* filename, int warnfail);
#endif
#if DROPBEAR_CLI_ANYTCPFWD
static void addforward(const char* str, m_list *fwdlist);
#endif
@@ -48,6 +45,10 @@ static void add_netcat(const char *str);
#endif
static void add_extendedopt(const char *str);
#if DROPBEAR_USE_SSH_CONFIG
static void apply_config_settings(const char* cli_host_arg);
#endif
static void printhelp() {
fprintf(stderr, "Dropbear SSH client v%s https://matt.ucc.asn.au/dropbear/dropbear.html\n"
@@ -62,6 +63,7 @@ static void printhelp() {
"-T Don't allocate a pty\n"
"-N Don't run a remote command\n"
"-f Run in background after auth\n"
"-q quiet, don't show remote banner\n"
"-y Always accept remote host key if unknown\n"
"-y -y Don't perform any remote host key checking (caution)\n"
"-s Request a subsystem (use by external sftp)\n"
@@ -79,12 +81,13 @@ static void printhelp() {
#if DROPBEAR_CLI_REMOTETCPFWD
"-R <[listenaddress:]listenport:remotehost:remoteport> Remote port forwarding\n"
#endif
"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
"-W <receive_window_buffer> (default %d, larger may be faster, max 10MB)\n"
"-K <keepalive> (0 is never, default %d)\n"
"-I <idle_timeout> (0 is never, default %d)\n"
"-z disable QoS\n"
#if DROPBEAR_CLI_NETCAT
"-B <endhost:endport> Netcat-alike forwarding\n"
#endif
#endif
#if DROPBEAR_CLI_PROXYCMD
"-J <proxy_program> Use program pipe rather than TCP connection\n"
#endif
@@ -95,19 +98,19 @@ static void printhelp() {
"-b [bind_address][:bind_port]\n"
"-V Version\n"
#if DEBUG_TRACE
"-v verbose (compiled with DEBUG_TRACE)\n"
"-v verbose (repeat for more verbose)\n"
#endif
,DROPBEAR_VERSION, cli_opts.progname,
#if DROPBEAR_CLI_PUBKEY_AUTH
DROPBEAR_DEFAULT_CLI_AUTHKEY,
#endif
DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
}
void cli_getopts(int argc, char ** argv) {
unsigned int i, j;
char ** next = NULL;
const char ** next = NULL;
enum {
OPT_EXTENDED_OPTIONS,
#if DROPBEAR_CLI_PUBKEY_AUTH
@@ -127,23 +130,27 @@ void cli_getopts(int argc, char ** argv) {
} opt;
unsigned int cmdlen;
char* recv_window_arg = NULL;
char* keepalive_arg = NULL;
char* idle_timeout_arg = NULL;
char *host_arg = NULL;
char *bind_arg = NULL;
const char* recv_window_arg = NULL;
const char* idle_timeout_arg = NULL;
const char *host_arg = NULL;
const char *proxycmd_arg = NULL;
const char *remoteport_arg = NULL;
const char *username_arg = NULL;
char c;
/* see printhelp() for options */
cli_opts.progname = argv[0];
cli_opts.remotehost = NULL;
cli_opts.remotehostfixed = 0;
cli_opts.remoteport = NULL;
cli_opts.username = NULL;
cli_opts.cmd = NULL;
cli_opts.no_cmd = 0;
cli_opts.quiet = 0;
cli_opts.backgrounded = 0;
cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
cli_opts.always_accept_key = 0;
cli_opts.ask_hostkey = 1;
cli_opts.no_hostkey_check = 0;
cli_opts.is_subsystem = 0;
#if DROPBEAR_CLI_PUBKEY_AUTH
@@ -152,6 +159,9 @@ void cli_getopts(int argc, char ** argv) {
#if DROPBEAR_CLI_ANYTCPFWD
cli_opts.exit_on_fwd_failure = 0;
#endif
cli_opts.disable_trivial_auth = 0;
cli_opts.password_authentication = 1;
cli_opts.batch_mode = 0;
#if DROPBEAR_CLI_LOCALTCPFWD
cli_opts.localfwds = list_new();
opts.listen_fwd_all = 0;
@@ -167,8 +177,10 @@ void cli_getopts(int argc, char ** argv) {
#if DROPBEAR_CLI_PROXYCMD
cli_opts.proxycmd = NULL;
#endif
cli_opts.bind_arg = NULL;
cli_opts.bind_address = NULL;
cli_opts.bind_port = NULL;
cli_opts.keepalive_arg = NULL;
#ifndef DISABLE_ZLIB
opts.compress_mode = DROPBEAR_COMPRESS_ON;
#endif
@@ -206,15 +218,21 @@ void cli_getopts(int argc, char ** argv) {
opt = OPT_OTHER;
for (j = 1; (c = argv[i][j]) != '\0' && !next && opt == OPT_OTHER; j++) {
switch (c) {
case 'y': /* always accept the remote hostkey */
case 'y':
/* once is always accept the remote hostkey,
* the same as stricthostkeychecking=accept-new */
if (cli_opts.always_accept_key) {
/* twice means no checking at all */
/* twice means no checking at all
* (stricthostkeychecking=no) */
cli_opts.no_hostkey_check = 1;
}
cli_opts.always_accept_key = 1;
break;
case 'q': /* quiet */
cli_opts.quiet = 1;
break;
case 'p': /* remoteport */
next = (char**)&cli_opts.remoteport;
next = &remoteport_arg;
break;
#if DROPBEAR_CLI_PUBKEY_AUTH
case 'i': /* an identityfile */
@@ -259,11 +277,11 @@ void cli_getopts(int argc, char ** argv) {
#endif
#if DROPBEAR_CLI_PROXYCMD
case 'J':
next = &cli_opts.proxycmd;
next = &proxycmd_arg;
break;
#endif
case 'l':
next = &cli_opts.username;
next = &username_arg;
break;
case 'h':
printhelp();
@@ -276,7 +294,7 @@ void cli_getopts(int argc, char ** argv) {
next = &recv_window_arg;
break;
case 'K':
next = &keepalive_arg;
next = &cli_opts.keepalive_arg;
break;
case 'I':
next = &idle_timeout_arg;
@@ -296,7 +314,7 @@ void cli_getopts(int argc, char ** argv) {
#endif
#if DEBUG_TRACE
case 'v':
debug_trace = 1;
debug_trace++;
break;
#endif
case 'F':
@@ -317,7 +335,10 @@ void cli_getopts(int argc, char ** argv) {
exit(EXIT_SUCCESS);
break;
case 'b':
next = &bind_arg;
next = &cli_opts.bind_arg;
break;
case 'z':
opts.disable_ip_tos = 1;
break;
default:
fprintf(stderr,
@@ -383,15 +404,34 @@ void cli_getopts(int argc, char ** argv) {
parse_ciphers_macs();
#endif
/* Done with options/flags; now handle the hostname (which may not
* start with a hyphen) and optional command */
if (host_arg == NULL) { /* missing hostname */
printhelp();
exit(EXIT_FAILURE);
dropbear_exit("Remote host needs to provided.");
}
TRACE(("host is: %s", host_arg))
#if DROPBEAR_USE_SSH_CONFIG
apply_config_settings(host_arg);
#endif
/* Apply needed defaults if missing from command line or config file. */
if (remoteport_arg) {
m_free(cli_opts.remoteport);
cli_opts.remoteport = m_strdup(remoteport_arg);
} else if (!cli_opts.remoteport) {
cli_opts.remoteport = m_strdup("22");
}
if (username_arg) {
m_free(cli_opts.username);
cli_opts.username = m_strdup(username_arg);
} else if(!cli_opts.username) {
cli_opts.username = m_strdup(cli_opts.own_user);
}
/* Done with options/flags; now handle the hostname (which may not
* start with a hyphen) and optional command */
if (i < (unsigned int)argc) {
/* Build the command to send */
cmdlen = 0;
@@ -413,26 +453,18 @@ void cli_getopts(int argc, char ** argv) {
/* And now a few sanity checks and setup */
#if DROPBEAR_CLI_PROXYCMD
if (cli_opts.proxycmd) {
#if DROPBEAR_CLI_PROXYCMD
if (proxycmd_arg) {
/* To match the common path of m_freeing it */
cli_opts.proxycmd = m_strdup(cli_opts.proxycmd);
cli_opts.proxycmd = m_strdup(proxycmd_arg);
}
#endif
if (cli_opts.remoteport == NULL) {
cli_opts.remoteport = "22";
}
if (bind_arg) {
/* split [host][:port] */
char *port = strrchr(bind_arg, ':');
if (port) {
cli_opts.bind_port = m_strdup(port+1);
*port = '\0';
}
if (strlen(bind_arg) > 0) {
cli_opts.bind_address = m_strdup(bind_arg);
if (cli_opts.bind_arg) {
if (split_address_port(cli_opts.bind_arg,
&cli_opts.bind_address, &cli_opts.bind_port)
== DROPBEAR_FAILURE) {
dropbear_exit("Bad -b argument");
}
}
@@ -450,17 +482,14 @@ void cli_getopts(int argc, char ** argv) {
&& cli_opts.no_cmd == 0) {
dropbear_exit("Command required for -f");
}
if (recv_window_arg) {
opts.recv_window = atol(recv_window_arg);
if (opts.recv_window == 0 || opts.recv_window > MAX_RECV_WINDOW) {
dropbear_exit("Bad recv window '%s'", recv_window_arg);
}
parse_recv_window(recv_window_arg);
}
if (keepalive_arg) {
if (cli_opts.keepalive_arg) {
unsigned int val;
if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) {
dropbear_exit("Bad keepalive '%s'", keepalive_arg);
if (m_str_to_uint(cli_opts.keepalive_arg, &val) == DROPBEAR_FAILURE) {
dropbear_exit("Bad keepalive '%s'", cli_opts.keepalive_arg);
}
opts.keepalive_secs = val;
}
@@ -479,14 +508,6 @@ void cli_getopts(int argc, char ** argv) {
}
#endif
#if (DROPBEAR_CLI_PUBKEY_AUTH)
{
char *expand_path = expand_homedir_path(DROPBEAR_DEFAULT_CLI_AUTHKEY);
loadidentityfile(expand_path, 0);
m_free(expand_path);
}
#endif
/* The hostname gets set up last, since
* in multi-hop mode it will require knowledge
* of other flags such as -i */
@@ -495,26 +516,37 @@ void cli_getopts(int argc, char ** argv) {
#else
parse_hostname(host_arg);
#endif
/* We don't want to include default id_dropbear as a
-i argument for multihop, so handle it later. */
#if (DROPBEAR_CLI_PUBKEY_AUTH)
{
loadidentityfile(DROPBEAR_DEFAULT_CLI_AUTHKEY, 0);
}
#endif
}
#if DROPBEAR_CLI_PUBKEY_AUTH
static void loadidentityfile(const char* filename, int warnfail) {
void loadidentityfile(const char* filename, int warnfail) {
sign_key *key;
enum signkey_type keytype;
TRACE(("loadidentityfile %s", filename))
char *id_key_path = expand_homedir_path(filename);
TRACE(("loadidentityfile %s", id_key_path))
key = new_sign_key();
keytype = DROPBEAR_SIGNKEY_ANY;
if ( readhostkey(filename, key, &keytype) != DROPBEAR_SUCCESS ) {
if ( readhostkey(id_key_path, key, &keytype) != DROPBEAR_SUCCESS ) {
if (warnfail) {
dropbear_log(LOG_WARNING, "Failed loading keyfile '%s'\n", filename);
dropbear_log(LOG_WARNING, "Failed loading keyfile '%s'\n", id_key_path);
}
sign_key_free(key);
m_free(id_key_path);
} else {
key->type = keytype;
key->source = SIGNKEY_SOURCE_RAW_FILE;
key->filename = m_strdup(filename);
key->filename = id_key_path;
list_append(cli_opts.privkeys, key);
}
}
@@ -522,61 +554,65 @@ static void loadidentityfile(const char* filename, int warnfail) {
#if DROPBEAR_CLI_MULTIHOP
static char*
multihop_passthrough_args() {
char *ret;
int total;
unsigned int len = 0;
/* Fill out -i, -y, -W options that make sense for all
* the intermediate processes */
static char* multihop_passthrough_args(void) {
char *args = NULL;
unsigned int len, total;
#if DROPBEAR_CLI_PUBKEY_AUTH
m_list_elem *iter;
/* Fill out -i, -y, -W options that make sense for all
* the intermediate processes */
#endif
/* Sufficient space for non-string args */
len = 100;
/* String arguments have arbitrary length, so determine space required */
if (cli_opts.proxycmd) {
len += strlen(cli_opts.proxycmd);
}
#if DROPBEAR_CLI_PUBKEY_AUTH
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{
sign_key * key = (sign_key*)iter->item;
len += 3 + strlen(key->filename);
len += 4 + strlen(key->filename);
}
#endif /* DROPBEAR_CLI_PUBKEY_AUTH */
#endif
len += 30; /* space for -W <size>, terminator. */
ret = m_malloc(len);
args = m_malloc(len);
total = 0;
if (cli_opts.no_hostkey_check)
{
int written = snprintf(ret+total, len-total, "-y -y ");
total += written;
}
else if (cli_opts.always_accept_key)
{
int written = snprintf(ret+total, len-total, "-y ");
total += written;
/* Create new argument string */
if (cli_opts.quiet) {
total += m_snprintf(args+total, len-total, "-q ");
}
if (opts.recv_window != DEFAULT_RECV_WINDOW)
{
int written = snprintf(ret+total, len-total, "-W %u ", opts.recv_window);
total += written;
if (cli_opts.no_hostkey_check) {
total += m_snprintf(args+total, len-total, "-y -y ");
} else if (cli_opts.always_accept_key) {
total += m_snprintf(args+total, len-total, "-y ");
}
if (cli_opts.batch_mode) {
total += m_snprintf(args+total, len-total, "-o BatchMode=yes ");
}
if (cli_opts.proxycmd) {
total += m_snprintf(args+total, len-total, "-J '%s' ", cli_opts.proxycmd);
}
if (opts.recv_window != DEFAULT_RECV_WINDOW) {
total += m_snprintf(args+total, len-total, "-W %u ", opts.recv_window);
}
#if DROPBEAR_CLI_PUBKEY_AUTH
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{
sign_key * key = (sign_key*)iter->item;
const size_t size = len - total;
int written = snprintf(ret+total, size, "-i %s ", key->filename);
dropbear_assert((unsigned int)written < size);
total += written;
total += m_snprintf(args+total, len-total, "-i %s ", key->filename);
}
#endif /* DROPBEAR_CLI_PUBKEY_AUTH */
/* if args were passed, total will be not zero, and it will have a space at the end, so remove that */
if (total > 0)
{
total--;
}
return ret;
return args;
}
/* Sets up 'onion-forwarding' connections. This will spawn
@@ -589,6 +625,9 @@ multihop_passthrough_args() {
* dbclient -J "dbclient -B madako:22 wrt" madako
* etc for as many hosts as we want.
*
* Note that "-J" arguments aren't actually used, instead
* below sets cli_opts.proxycmd directly.
*
* Ports for hosts can be specified as host/port.
*/
static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
@@ -602,12 +641,12 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
* for our multihop syntax, so we suture it back together.
* This will break usernames that have both '@' and ',' in them,
* though that should be fairly uncommon. */
if (cli_opts.username
&& strchr(cli_opts.username, ',')
if (cli_opts.username
&& strchr(cli_opts.username, ',')
&& strchr(cli_opts.username, '@')) {
unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
hostbuf = m_malloc(len);
snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
m_snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
} else {
hostbuf = m_strdup(orighostarg);
}
@@ -630,19 +669,15 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
/* Set up the proxycmd */
unsigned int cmd_len = 0;
char *passthrough_args = multihop_passthrough_args();
if (cli_opts.proxycmd) {
dropbear_exit("-J can't be used with multihop mode");
}
if (cli_opts.remoteport == NULL) {
cli_opts.remoteport = "22";
}
cmd_len = strlen(argv0) + strlen(remainder)
cmd_len = strlen(argv0) + strlen(remainder)
+ strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport)
+ strlen(passthrough_args)
+ 30;
cli_opts.proxycmd = m_malloc(cmd_len);
snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s",
argv0, cli_opts.remotehost, cli_opts.remoteport,
/* replace proxycmd. old -J arguments have been copied
to passthrough_args */
cli_opts.proxycmd = m_realloc(cli_opts.proxycmd, cmd_len);
m_snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s",
argv0, cli_opts.remotehost, cli_opts.remoteport,
passthrough_args, remainder);
#ifndef DISABLE_ZLIB
/* The stream will be incompressible since it's encrypted. */
@@ -652,51 +687,53 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
}
m_free(hostbuf);
}
#endif /* !DROPBEAR_CLI_MULTIHOP */
#endif /* DROPBEAR_CLI_MULTIHOP */
/* Parses a [user@]hostname[/port] argument. */
static void parse_hostname(const char* orighostarg) {
char *userhostarg = NULL;
char *port = NULL;
char* remotehost = NULL;
userhostarg = m_strdup(orighostarg);
cli_opts.remotehost = strchr(userhostarg, '@');
if (cli_opts.remotehost == NULL) {
remotehost = strchr(userhostarg, '@');
if (remotehost == NULL) {
/* no username portion, the cli-auth.c code can figure the
* local user's name */
cli_opts.remotehost = userhostarg;
remotehost = userhostarg;
} else {
cli_opts.remotehost[0] = '\0'; /* Split the user/host */
cli_opts.remotehost++;
cli_opts.username = userhostarg;
remotehost[0] = '\0'; /* Split the user/host */
remotehost++;
cli_opts.username = m_strdup(userhostarg);
}
if (cli_opts.username == NULL) {
cli_opts.username = m_strdup(cli_opts.own_user);
}
port = strchr(cli_opts.remotehost, '^');
port = strchr(remotehost, '^');
if (!port) {
/* legacy separator */
port = strchr(cli_opts.remotehost, '/');
port = strchr(remotehost, '/');
}
if (port) {
*port = '\0';
cli_opts.remoteport = port+1;
cli_opts.remoteport = m_strdup(port+1);
}
if (cli_opts.remotehost[0] == '\0') {
dropbear_exit("Bad hostname");
if (remotehost[0] == '\0') {
dropbear_exit("Bad hostname.");
}
if (!cli_opts.remotehostfixed) {
cli_opts.remotehost = m_strdup(remotehost);
}
m_free(userhostarg);
}
#if DROPBEAR_CLI_NETCAT
static void add_netcat(const char* origstr) {
char *portstr = NULL;
char * str = m_strdup(origstr);
portstr = strchr(str, ':');
if (portstr == NULL) {
TRACE(("No netcat port"))
@@ -704,25 +741,25 @@ static void add_netcat(const char* origstr) {
}
*portstr = '\0';
portstr++;
if (strchr(portstr, ':')) {
TRACE(("Multiple netcat colons"))
goto fail;
}
if (m_str_to_uint(portstr, &cli_opts.netcat_port) == DROPBEAR_FAILURE) {
TRACE(("bad netcat port"))
goto fail;
}
if (cli_opts.netcat_port > 65535) {
TRACE(("too large netcat port"))
goto fail;
}
cli_opts.netcat_host = str;
return;
fail:
dropbear_exit("Bad netcat endpoint '%s'", origstr);
}
@@ -730,7 +767,7 @@ fail:
static void fill_own_user() {
uid_t uid;
struct passwd *pw = NULL;
struct passwd *pw = NULL;
uid = getuid();
@@ -760,7 +797,7 @@ static void addforward(const char* origstr, m_list *fwdlist) {
TRACE(("enter addforward"))
/* We need to split the original argument up. This var
is never free()d. */
is never free()d. */
str = m_strdup(origstr);
part1 = str;
@@ -820,7 +857,7 @@ static void addforward(const char* origstr, m_list *fwdlist) {
TRACE(("listenport > 65535"))
goto badport;
}
if (newfwd->connectport > 65535) {
TRACE(("connectport > 65535"))
goto badport;
@@ -886,17 +923,50 @@ static void add_extendedopt(const char* origstr) {
if (strcmp(origstr, "help") == 0) {
dropbear_log(LOG_INFO, "Available options:\n"
"\tBatchMode\n"
"\tBindAddress\n"
"\tDisableTrivialAuth\n"
#if DROPBEAR_CLI_ANYTCPFWD
"\tExitOnForwardFailure\n"
#endif
#if DROPBEAR_CLI_AGENTFWD
"\tForwardAgent\n"
#endif
#if DROPBEAR_CLI_LOCALTCPFWD
"\tGatewayPorts\n"
#endif
#if DROPBEAR_CLI_PUBKEY_AUTH
"\tIdentityFile\n"
#endif
"\tPasswordAuthentication\n"
"\tPort\n"
#if DROPBEAR_CLI_PROXYCMD
"\tProxyCommand\n"
#endif
"\tServerAliveInterval\n"
"\tStrictHostKeyChecking\n"
#ifndef DISABLE_SYSLOG
"\tUseSyslog\n"
#endif
"\tPort\n"
);
exit(EXIT_SUCCESS);
}
if (match_extendedopt(&optstr, "BatchMode") == DROPBEAR_SUCCESS) {
cli_opts.batch_mode = parse_flag_value(optstr);
return;
}
if (match_extendedopt(&optstr, "BindAddress") == DROPBEAR_SUCCESS) {
cli_opts.bind_arg = optstr;
return;
}
if (match_extendedopt(&optstr, "DisableTrivialAuth") == DROPBEAR_SUCCESS) {
cli_opts.disable_trivial_auth = parse_flag_value(optstr);
return;
}
#if DROPBEAR_CLI_ANYTCPFWD
if (match_extendedopt(&optstr, "ExitOnForwardFailure") == DROPBEAR_SUCCESS) {
cli_opts.exit_on_fwd_failure = parse_flag_value(optstr);
@@ -904,6 +974,75 @@ static void add_extendedopt(const char* origstr) {
}
#endif
#if DROPBEAR_CLI_AGENTFWD
if (match_extendedopt(&optstr, "ForwardAgent") == DROPBEAR_SUCCESS) {
cli_opts.agent_fwd = parse_flag_value(optstr);
return;
}
#endif
#if DROPBEAR_CLI_LOCALTCPFWD
if (match_extendedopt(&optstr, "GatewayPorts") == DROPBEAR_SUCCESS) {
opts.listen_fwd_all = 1;
return;
}
#endif
#if DROPBEAR_CLI_PUBKEY_AUTH
if (match_extendedopt(&optstr, "IdentityFile") == DROPBEAR_SUCCESS) {
loadidentityfile(optstr, 1);
return;
}
#endif
#if DROPBEAR_CLI_PASSWORD_AUTH
if (match_extendedopt(&optstr, "PasswordAuthentication") == DROPBEAR_SUCCESS) {
cli_opts.password_authentication = parse_flag_value(optstr);
return;
}
#endif
if (match_extendedopt(&optstr, "BatchMode") == DROPBEAR_SUCCESS) {
cli_opts.batch_mode = parse_flag_value(optstr);
return;
}
if (match_extendedopt(&optstr, "Port") == DROPBEAR_SUCCESS) {
cli_opts.remoteport = m_strdup(optstr);
return;
}
#if DROPBEAR_CLI_PROXYCMD
if (match_extendedopt(&optstr, "ProxyCommand") == DROPBEAR_SUCCESS) {
cli_opts.proxycmd = m_strdup(optstr);
return;
}
#endif
if (match_extendedopt(&optstr, "ServerAliveInterval") == DROPBEAR_SUCCESS) {
cli_opts.keepalive_arg = optstr;
return;
}
if (match_extendedopt(&optstr, "StrictHostKeyChecking") == DROPBEAR_SUCCESS) {
if (strcmp(optstr, "accept-new") == 0) {
cli_opts.always_accept_key = 1;
} else if (strcmp(optstr, "ask") == 0) {
/* the default */
} else {
int opt = parse_flag_value(optstr);
if (opt) {
/* "yes" means entry must already exist in
* known_hosts for success. */
cli_opts.ask_hostkey = 0;
} else {
/* "no" means no check at all */
cli_opts.no_hostkey_check = 1;
}
}
return;
}
#ifndef DISABLE_SYSLOG
if (match_extendedopt(&optstr, "UseSyslog") == DROPBEAR_SUCCESS) {
opts.usingsyslog = parse_flag_value(optstr);
@@ -911,10 +1050,24 @@ static void add_extendedopt(const char* origstr) {
}
#endif
if (match_extendedopt(&optstr, "Port") == DROPBEAR_SUCCESS) {
cli_opts.remoteport = optstr;
return;
}
dropbear_log(LOG_WARNING, "Ignoring unknown configuration option '%s'", origstr);
}
#if DROPBEAR_USE_SSH_CONFIG
static void apply_config_settings(const char* cli_host_arg) {
char* is_multi_hop_host_target = strchr(cli_host_arg, ',');
if (!is_multi_hop_host_target) {
char* config_path = expand_homedir_path(DROPBEAR_DEFAULT_SSH_CONFIG);
FILE* f;
if ((f = fopen(config_path, "r")) == NULL) {
DEBUG1(("Configuration file '%.200s' not found.", config_path));
}
else {
parse_hostname(cli_host_arg); /* Needed as key into the config. */
read_config_file(config_path, f, &cli_opts);
fclose(f);
}
m_free(config_path);
}
}
#endif

View File

@@ -46,6 +46,7 @@ static void cli_finished(void) ATTRIB_NORETURN;
static void recv_msg_service_accept(void);
static void cli_session_cleanup(void);
static void recv_msg_global_request_cli(void);
static void cli_algos_initialise(void);
struct clientsession cli_ses; /* GLOBAL */
@@ -102,6 +103,9 @@ void cli_connected(int result, int sock, void* userdata, const char *errstring)
dropbear_exit("Connect failed: %s", errstring);
}
myses->sock_in = myses->sock_out = sock;
DEBUG1(("cli_connected"))
ses.socket_prio = DROPBEAR_PRIO_NORMAL;
/* switches to lowdelay */
update_channel_prio();
}
@@ -114,6 +118,7 @@ void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection
}
chaninitialise(cli_chantypes);
cli_algos_initialise();
/* Set up cli_ses vars */
cli_session_init(proxy_cmd_pid);
@@ -165,6 +170,7 @@ static void cli_session_init(pid_t proxy_cmd_pid) {
/* Auth */
cli_ses.lastprivkey = NULL;
cli_ses.lastauthtype = 0;
cli_ses.is_trivial_auth = 1;
/* For printing "remote host closed" for the user */
ses.remoteclosed = cli_remoteclosed;
@@ -245,6 +251,9 @@ static void cli_sessionloop() {
/* We've got the transport layer sorted, we now need to request
* userauth */
send_msg_service_request(SSH_SERVICE_USERAUTH);
/* We aren't using any "implicit server authentication" methods,
so don't need to wait for a response for SSH_SERVICE_USERAUTH
before sending the auth messages (rfc4253 10) */
cli_auth_getmethods();
cli_ses.state = USERAUTH_REQ_SENT;
TRACE(("leave cli_sessionloop: sent userauth methods req"))
@@ -352,6 +361,11 @@ static void cli_session_cleanup(void) {
(void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
/* Don't leak */
m_close(cli_ses.stdincopy);
m_close(cli_ses.stdoutcopy);
m_close(cli_ses.stderrcopy);
cli_tty_cleanup();
if (cli_ses.server_sig_algs) {
buf_free(cli_ses.server_sig_algs);
@@ -403,7 +417,84 @@ void cleantext(char* dirtytext) {
}
static void recv_msg_global_request_cli(void) {
TRACE(("recv_msg_global_request_cli"))
/* Send a proper rejection */
send_msg_request_failure();
unsigned int wantreply = 0;
buf_eatstring(ses.payload);
wantreply = buf_getbool(ses.payload);
TRACE(("recv_msg_global_request_cli: want_reply: %u", wantreply));
if (wantreply) {
/* Send a proper rejection */
send_msg_request_failure();
}
}
void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
char exitmsg[150];
char fullmsg[300];
/* Note that exit message must be rendered before session cleanup */
/* Render the formatted exit message */
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
TRACE(("Exited, cleaning up: %s", exitmsg))
/* Add the prefix depending on session/auth state */
if (!ses.init_done) {
snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
} else {
snprintf(fullmsg, sizeof(fullmsg),
"Connection to %s@%s:%s exited: %s",
cli_opts.username, cli_opts.remotehost,
cli_opts.remoteport, exitmsg);
}
/* Do the cleanup first, since then the terminal will be reset */
session_cleanup();
#if DROPBEAR_FUZZ
if (fuzz.do_jmp) {
longjmp(fuzz.jmp, 1);
}
#endif
/* Avoid printing onwards from terminal cruft */
fprintf(stderr, "\n");
dropbear_log(LOG_INFO, "%s", fullmsg);
exit(exitcode);
}
void cli_dropbear_log(int priority, const char* format, va_list param) {
char printbuf[1024];
const char *name;
name = cli_opts.progname;
if (!name) {
name = "dbclient";
}
vsnprintf(printbuf, sizeof(printbuf), format, param);
#ifndef DISABLE_SYSLOG
if (opts.usingsyslog) {
syslog(priority, "%s", printbuf);
}
#endif
fprintf(stderr, "%s: %s\n", name, printbuf);
fflush(stderr);
}
static void cli_algos_initialise(void) {
algo_type *algo;
for (algo = sshkex; algo->name; algo++) {
if (strcmp(algo->name, SSH_STRICT_KEX_S) == 0) {
algo->usable = 0;
}
}
}

View File

@@ -35,7 +35,6 @@
static int newtcpforwarded(struct Channel * channel);
const struct ChanType cli_chan_tcpremote = {
1, /* sepfds */
"forwarded-tcpip",
newtcpforwarded,
NULL,
@@ -51,9 +50,8 @@ static int cli_localtcp(const char* listenaddr,
const char* remoteaddr,
unsigned int remoteport);
static const struct ChanType cli_chan_tcplocal = {
1, /* sepfds */
"direct-tcpip",
tcp_prio_inithandler,
NULL,
NULL,
NULL,
NULL,
@@ -273,12 +271,11 @@ static int newtcpforwarded(struct Channel * channel) {
origaddr, origport);
goto out;
}
snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel, NULL, NULL);
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done,
channel, NULL, NULL, DROPBEAR_PRIO_NORMAL);
err = SSH_OPEN_IN_PROGRESS;
out:

View File

@@ -64,14 +64,6 @@ static const struct dropbear_cipher dropbear_aes256 =
static const struct dropbear_cipher dropbear_aes128 =
{&aes_desc, 16, 16};
#endif
#if DROPBEAR_TWOFISH256
static const struct dropbear_cipher dropbear_twofish256 =
{&twofish_desc, 32, 16};
#endif
#if DROPBEAR_TWOFISH128
static const struct dropbear_cipher dropbear_twofish128 =
{&twofish_desc, 16, 16};
#endif
#if DROPBEAR_3DES
static const struct dropbear_cipher dropbear_3des =
{&des3_desc, 24, 8};
@@ -122,10 +114,6 @@ static const struct dropbear_hash dropbear_sha2_256 =
static const struct dropbear_hash dropbear_sha2_512 =
{&sha512_desc, 64, 64};
#endif
#if DROPBEAR_MD5_HMAC
static const struct dropbear_hash dropbear_md5 =
{&md5_desc, 16, 16};
#endif
const struct dropbear_hash dropbear_nohash =
{NULL, 16, 0}; /* used initially */
@@ -156,15 +144,6 @@ algo_type sshciphers[] = {
#if DROPBEAR_AES256
{"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
#endif
#if DROPBEAR_TWOFISH_CTR
/* twofish ctr is conditional as it hasn't been tested for interoperability, see options.h */
#if DROPBEAR_TWOFISH256
{"twofish256-ctr", 0, &dropbear_twofish256, 1, &dropbear_mode_ctr},
#endif
#if DROPBEAR_TWOFISH128
{"twofish128-ctr", 0, &dropbear_twofish128, 1, &dropbear_mode_ctr},
#endif
#endif /* DROPBEAR_TWOFISH_CTR */
#endif /* DROPBEAR_ENABLE_CTR_MODE */
#if DROPBEAR_ENABLE_CBC_MODE
@@ -174,13 +153,6 @@ algo_type sshciphers[] = {
#if DROPBEAR_AES256
{"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
#endif
#if DROPBEAR_TWOFISH256
{"twofish256-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
{"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
#endif
#if DROPBEAR_TWOFISH128
{"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc},
#endif
#endif /* DROPBEAR_ENABLE_CBC_MODE */
#if DROPBEAR_3DES
@@ -209,9 +181,6 @@ algo_type sshhashes[] = {
#endif
#if DROPBEAR_SHA2_512_HMAC
{"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL},
#endif
#if DROPBEAR_MD5_HMAC
{"hmac-md5", 0, (void*)&dropbear_md5, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -239,6 +208,9 @@ algo_type ssh_nocompress[] = {
algo_type sigalgs[] = {
#if DROPBEAR_ED25519
{"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL},
#if DROPBEAR_SK_ED25519
{"sk-ssh-ed25519@openssh.com", DROPBEAR_SIGNATURE_SK_ED25519, NULL, 1, NULL},
#endif
#endif
#if DROPBEAR_ECDSA
#if DROPBEAR_ECC_256
@@ -250,6 +222,9 @@ algo_type sigalgs[] = {
#if DROPBEAR_ECC_521
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
#endif
#if DROPBEAR_SK_ECDSA
{"sk-ecdsa-sha2-nistp256@openssh.com", DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256, NULL, 1, NULL},
#endif
#endif
#if DROPBEAR_RSA
#if DROPBEAR_RSA_SHA256
@@ -332,6 +307,12 @@ algo_type sshkex[] = {
/* Set unusable by svr_algos_initialise() */
{SSH_EXT_INFO_C, 0, NULL, 1, NULL},
#endif
#endif
#if DROPBEAR_CLIENT
{SSH_STRICT_KEX_C, 0, NULL, 1, NULL},
#endif
#if DROPBEAR_SERVER
{SSH_STRICT_KEX_S, 0, NULL, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -359,7 +340,7 @@ void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall
len = buf->pos - startpos - 4;
buf_setpos(buf, startpos);
buf_putint(buf, len);
TRACE(("algolist add %d '%*s'", len, len, buf_getptr(buf, len)))
TRACE(("algolist add %d '%.*s'", len, len, buf_getptr(buf, len)))
buf_incrwritepos(buf, len);
}
@@ -381,7 +362,7 @@ static void get_algolist(char* algolist, unsigned int algolist_len,
}
if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
*ret_count = 0;
}
}
/* ret_list will contain a list of the strings parsed out.
We will have at least one string (even if it's just "") */
@@ -392,11 +373,11 @@ static void get_algolist(char* algolist, unsigned int algolist_len,
/* someone is trying something strange */
*ret_count = 0;
return;
}
}
if (algolist[i] == ',') {
if (*ret_count >= max_count) {
/* Too many */
dropbear_exit("Too many remote algorithms");
*ret_count = 0;
return;
}
@@ -463,7 +444,7 @@ algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
algolist = buf_getstring(buf, &len);
TRACE(("buf_match_algo: %s", algolist))
DEBUG3(("buf_match_algo: %s", algolist))
remotecount = MAX_PROPOSED_ALGO;
get_algolist(algolist, len, remotenames, &remotecount);

Some files were not shown because too many files have changed in this diff Show More