mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Compare commits
309 Commits
DROPBEAR_2
...
DROPBEAR_C
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09bc32d7f8 | ||
|
|
07f1f1d5f9 | ||
|
|
af3488e293 | ||
|
|
9452f11bf9 | ||
|
|
ed8f0da039 | ||
|
|
d8900abd95 | ||
|
|
b63e8d8694 | ||
|
|
35427a2d0b | ||
|
|
78576360f6 | ||
|
|
31e3a973c1 | ||
|
|
9defeb477a | ||
|
|
7a53c7f0f4 | ||
|
|
febb805742 | ||
|
|
923a65ea0d | ||
|
|
39d955c49f | ||
|
|
f7b1ba6aad | ||
|
|
01415ef826 | ||
|
|
6fa49f98c5 | ||
|
|
8607215588 | ||
|
|
c043efb47c | ||
|
|
ec2215726c | ||
|
|
bd94cb712c | ||
|
|
cf7f9350b8 | ||
|
|
5a07edfa2b | ||
|
|
a7659fb581 | ||
|
|
1034024029 | ||
|
|
36a0313263 | ||
|
|
a4689e25ec | ||
|
|
e360dffff2 | ||
|
|
5a3bc9fa9c | ||
|
|
aa6559db66 | ||
|
|
b2b94acc97 | ||
|
|
960d374e65 | ||
|
|
fd234018a4 | ||
|
|
54a90ddac5 | ||
|
|
cda8070898 | ||
|
|
b5e941c0b1 | ||
|
|
e87a222ce7 | ||
|
|
e85f329e5c | ||
|
|
1d22801101 | ||
|
|
787391ea3b | ||
|
|
c9a16e661a | ||
|
|
b966cce3ae | ||
|
|
e5e6b6c1b8 | ||
|
|
c29c4e1024 | ||
|
|
1cdd95f997 | ||
|
|
86ac8411a0 | ||
|
|
2864c3d154 | ||
|
|
0e70732e1e | ||
|
|
cdaf52aead | ||
|
|
cdc83ad98a | ||
|
|
80fa169cb9 | ||
|
|
50a07a4889 | ||
|
|
dacc10a8cf | ||
|
|
0058cc69c8 | ||
|
|
963b9eafaa | ||
|
|
7c9bd09af6 | ||
|
|
72b28448a1 | ||
|
|
dc3c1a30cf | ||
|
|
71d78653c7 | ||
|
|
9f55ff216b | ||
|
|
b4c30b5e7e | ||
|
|
561ef41230 | ||
|
|
ab6ea4d697 | ||
|
|
9d320a73be | ||
|
|
f19a0494d7 | ||
|
|
ab70167534 | ||
|
|
d1fed8b451 | ||
|
|
5284a3da56 | ||
|
|
f7d306e963 | ||
|
|
86efbae708 | ||
|
|
64e270b6f2 | ||
|
|
b36707ba46 | ||
|
|
acf50a4f98 | ||
|
|
b734e5a423 | ||
|
|
4c67d03656 | ||
|
|
17e02fe614 | ||
|
|
e520d035e7 | ||
|
|
d48a2ba8b7 | ||
|
|
7de29c2686 | ||
|
|
1e4d64d300 | ||
|
|
a7e3b06b04 | ||
|
|
427e49003a | ||
|
|
808bc392a0 | ||
|
|
e03abf0d1a | ||
|
|
62ea53c1e5 | ||
|
|
544f28a051 | ||
|
|
f2318d831b | ||
|
|
1622c80be4 | ||
|
|
c77d02bb11 | ||
|
|
50c6e8d3c3 | ||
|
|
258f6127b4 | ||
|
|
b81c81c047 | ||
|
|
3c3e4f6e6b | ||
|
|
d8d1db2cf8 | ||
|
|
0c9318a0b2 | ||
|
|
46654cda85 | ||
|
|
72d8cae7a4 | ||
|
|
2e0a16c334 | ||
|
|
c4a0304b3f | ||
|
|
46106f71ab | ||
|
|
0292aacdf0 | ||
|
|
b8669b063b | ||
|
|
c6e2d50310 | ||
|
|
dd305c1533 | ||
|
|
7894254afa | ||
|
|
ac2433cb8d | ||
|
|
552385280a | ||
|
|
c93103746e | ||
|
|
abb577fcba | ||
|
|
0e042476a0 | ||
|
|
0fc4e35c94 | ||
|
|
9007a80616 | ||
|
|
ecc85f91e6 | ||
|
|
82bff01242 | ||
|
|
02a8c6cadd | ||
|
|
85f56f438a | ||
|
|
0de8d44297 | ||
|
|
8b202f86e2 | ||
|
|
f4be5a3c8b | ||
|
|
2f68f6693f | ||
|
|
6f793d42d0 | ||
|
|
04a4548ba2 | ||
|
|
6ad6210901 | ||
|
|
8b68eb55d9 | ||
|
|
6dc029f2cb | ||
|
|
9d36e94deb | ||
|
|
6ac92cf606 | ||
|
|
cb9a00951f | ||
|
|
81e3977360 | ||
|
|
bcbae1f4ba | ||
|
|
ee3828b3f8 | ||
|
|
81425365de | ||
|
|
3189d12c9f | ||
|
|
a70b9e34c8 | ||
|
|
ce745e98c0 | ||
|
|
d142639e38 | ||
|
|
bceba1f2ed | ||
|
|
3521b58690 | ||
|
|
635ae3d500 | ||
|
|
02eb74fbec | ||
|
|
515db2d706 | ||
|
|
9411bc21a8 | ||
|
|
0d4ab4fc09 | ||
|
|
be4f9ce8e7 | ||
|
|
f030618543 | ||
|
|
193d967123 | ||
|
|
94b693b43c | ||
|
|
1f169dafa8 | ||
|
|
9ea30b8932 | ||
|
|
098263950f | ||
|
|
d597b66571 | ||
|
|
98ef42a856 | ||
|
|
678cc6fcc0 | ||
|
|
b58f96526a | ||
|
|
10875e8524 | ||
|
|
355b248318 | ||
|
|
212583544a | ||
|
|
ae8a0abc34 | ||
|
|
488ffce133 | ||
|
|
360d60fb34 | ||
|
|
fa4a1ab435 | ||
|
|
35631a21a2 | ||
|
|
80e7143fd2 | ||
|
|
19cfb22d30 | ||
|
|
8d11116dcb | ||
|
|
26feb8f13e | ||
|
|
9124997602 | ||
|
|
12b094f0bf | ||
|
|
5334d58a15 | ||
|
|
3939321750 | ||
|
|
a95ca34a10 | ||
|
|
4c2d2fc3ac | ||
|
|
e93b03cb00 | ||
|
|
2b0238706a | ||
|
|
3fb2406717 | ||
|
|
d367503fb0 | ||
|
|
2a6dac19b5 | ||
|
|
da7f77a50d | ||
|
|
c7b7c9a99d | ||
|
|
ebb4018889 | ||
|
|
1c8f00bd59 | ||
|
|
a4362d3019 | ||
|
|
14bdd5a8ae | ||
|
|
f3a4ea511b | ||
|
|
f972813ecd | ||
|
|
8727f49dec | ||
|
|
5edd2ce32e | ||
|
|
c06d8254d8 | ||
|
|
18be2a6509 | ||
|
|
483b427335 | ||
|
|
27ffea3223 | ||
|
|
742e296115 | ||
|
|
0e43d68d81 | ||
|
|
bcb9d78d83 | ||
|
|
8da9646c83 | ||
|
|
da482ede60 | ||
|
|
f0495697e5 | ||
|
|
f9ced2c880 | ||
|
|
17e0c7e76f | ||
|
|
30adc15860 | ||
|
|
6138bdc62f | ||
|
|
e05945f67a | ||
|
|
3e640acd17 | ||
|
|
ae25761c7c | ||
|
|
e6152ccd7d | ||
|
|
8b0d31ab20 | ||
|
|
65f6e48a06 | ||
|
|
a7ef149463 | ||
|
|
043b0fbd1b | ||
|
|
110b55214b | ||
|
|
c08177a3af | ||
|
|
3c2436cd05 | ||
|
|
f3b72bfd18 | ||
|
|
f17400e738 | ||
|
|
8e6f73e879 | ||
|
|
7c2470ba3a | ||
|
|
cc59c08605 | ||
|
|
661d8ca225 | ||
|
|
41d4b4e7f7 | ||
|
|
dc016f900b | ||
|
|
4c8c879b38 | ||
|
|
210a983349 | ||
|
|
69e5709f75 | ||
|
|
2157d52352 | ||
|
|
846d38fe43 | ||
|
|
a8d6dac2c5 | ||
|
|
ee49a1b16d | ||
|
|
325d0c1d02 | ||
|
|
17f209f9b7 | ||
|
|
924d5a06a6 | ||
|
|
1bf7acc5bd | ||
|
|
8d0013bbe0 | ||
|
|
9262ffe861 | ||
|
|
1eb369272b | ||
|
|
c0ed29ea02 | ||
|
|
91ca561d7a | ||
|
|
ba260bd67b | ||
|
|
898bff3d4e | ||
|
|
67a8de30b7 | ||
|
|
6c571c54e5 | ||
|
|
d2bfa6aedc | ||
|
|
d0d1ede191 | ||
|
|
3c2f113a78 | ||
|
|
f193e95a3e | ||
|
|
03481aba06 | ||
|
|
8b0fdf8010 | ||
|
|
934cc87db3 | ||
|
|
ae94f64145 | ||
|
|
8552a0e9eb | ||
|
|
d20420e709 | ||
|
|
e8640bdca3 | ||
|
|
e4edbf2e57 | ||
|
|
5d60e5f312 | ||
|
|
38d7da5fe5 | ||
|
|
a6b2eeb190 | ||
|
|
e12ff23e7d | ||
|
|
007a5925dc | ||
|
|
d439ed26e4 | ||
|
|
f9ff3fa23d | ||
|
|
2c64335d9c | ||
|
|
286b6b9f80 | ||
|
|
220ba993a2 | ||
|
|
3c88d6536a | ||
|
|
f49b576e93 | ||
|
|
8ec9016585 | ||
|
|
15ea6d1106 | ||
|
|
24cfda9e3c | ||
|
|
121e6e6202 | ||
|
|
1b6e16ae7c | ||
|
|
b8352f8164 | ||
|
|
6aa065b1b4 | ||
|
|
6cf29061c2 | ||
|
|
f92f0777de | ||
|
|
9c70e4bed1 | ||
|
|
a51833c51a | ||
|
|
d852d69b50 | ||
|
|
1b603069db | ||
|
|
bf4058d1df | ||
|
|
4d716b6302 | ||
|
|
1260fbc5cd | ||
|
|
acd6a22a0c | ||
|
|
4e8a1da551 | ||
|
|
754dc50b93 | ||
|
|
c7cfa75e92 | ||
|
|
b070bcd570 | ||
|
|
037d26f055 | ||
|
|
cb252296c5 | ||
|
|
f37def57b0 | ||
|
|
1a208c460b | ||
|
|
34f24b1841 | ||
|
|
1a7b944917 | ||
|
|
3b400bd64e | ||
|
|
f74baa5830 | ||
|
|
4c5b8fb6d6 | ||
|
|
d5cc5eb25c | ||
|
|
9f642e2bd4 | ||
|
|
6ca24af24a | ||
|
|
400c7c161f | ||
|
|
5567c238a7 | ||
|
|
33eba22966 | ||
|
|
282fc81981 | ||
|
|
cc1b07dcf1 | ||
|
|
0e3e8db5bf | ||
|
|
17873e8c92 | ||
|
|
80e9281701 | ||
|
|
926c477188 | ||
|
|
d999575e34 | ||
|
|
49177312fb |
9
.github/multiwrapper
vendored
Executable file
9
.github/multiwrapper
vendored
Executable 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
25
.github/workflows/autoconf.yml
vendored
Normal 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
290
.github/workflows/build.yml
vendored
Normal 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
30
.github/workflows/cifuzz.yml
vendored
Normal 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
25
.github/workflows/outoftree.yml
vendored
Normal 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
36
.github/workflows/tarball.yml
vendored
Normal 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
12
.gitignore
vendored
@@ -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/
|
||||
|
||||
29
.hgsigs
29
.hgsigs
@@ -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
61
.hgtags
@@ -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
|
||||
72
.travis.yml
72
.travis.yml
@@ -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
389
CHANGES
@@ -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
|
||||
|
||||
|
||||
115
DEVELOPING.md
115
DEVELOPING.md
@@ -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
14
Dockerfile
Normal 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"]
|
||||
@@ -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
93
INSTALL
@@ -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
97
INSTALL.md
Normal 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
22
MULTI
@@ -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
25
MULTI.md
Normal 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>
|
||||
```
|
||||
205
Makefile.in
205
Makefile.in
@@ -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
79
README
@@ -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
84
README.md
Normal 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
53
SMALL
@@ -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
59
SMALL.md
Normal 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.
|
||||
21
_internal_/Dockerfile.python.nonroot
Normal file
21
_internal_/Dockerfile.python.nonroot
Normal 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
10
build.sh
Executable 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
|
||||
115
configure.ac
115
configure.ac
@@ -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
30
debian/changelog
vendored
@@ -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.
|
||||
|
||||
2
debian/dropbear.docs
vendored
2
debian/dropbear.docs
vendored
@@ -1,3 +1,3 @@
|
||||
README
|
||||
README.md
|
||||
debian/README.runit
|
||||
debian/README.Debian.diet
|
||||
|
||||
2
debian/dropbear.init
vendored
2
debian/dropbear.init
vendored
@@ -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
4
debian/rules
vendored
@@ -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
|
||||
|
||||
209
fuzz-common.c
209
fuzz-common.c
@@ -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
72
fuzz.h
@@ -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
398
fuzz/fuzz-common.c
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
306
fuzz/fuzz-sshpacketmutator.c
Normal file
306
fuzz/fuzz-sshpacketmutator.c
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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
79
fuzz/fuzzer-cliconf.c
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
6
fuzz/fuzzer-postauth_nomaths.c
Normal file
6
fuzz/fuzzer-postauth_nomaths.c
Normal 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
6
fuzz/fuzzer-preauth.c
Normal 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);
|
||||
}
|
||||
|
||||
6
fuzz/fuzzer-preauth_nomaths.c
Normal file
6
fuzz/fuzzer-preauth_nomaths.c
Normal 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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
@@ -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
|
||||
|
||||
2080
keyimport.c
2080
keyimport.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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} $@"
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
73
release.sh
73
release.sh
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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"))
|
||||
@@ -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);
|
||||
|
||||
@@ -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[]);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
@@ -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();
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
@@ -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
177
src/cli-readconf.c
Normal 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 */
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
@@ -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
Reference in New Issue
Block a user