Compare commits

..

51 Commits

Author SHA1 Message Date
Matt Johnston
0ea2e3463d try fix coverity build
--HG--
branch : coverity
2020-06-26 21:20:57 +08:00
Matt Johnston
ddb6751ab4 merge coverity from main
--HG--
branch : coverity
2020-06-26 21:07:34 +08:00
Matt Johnston
6e3c3c8c51 try for coverity
--HG--
branch : coverity
2019-03-21 23:28:59 +08:00
Matt Johnston
ef080502f8 merge coverity
--HG--
branch : coverity
2019-03-21 00:14:38 +08:00
Matt Johnston
fdbdbe5703 merge coverity
--HG--
branch : coverity
2018-03-21 00:52:02 +08:00
Matt Johnston
921592d37e merge coverity
--HG--
branch : coverity
2018-03-04 15:07:09 +08:00
Matt Johnston
04a02730bc merge coverity
--HG--
branch : coverity
2018-02-26 22:43:12 +08:00
Matt Johnston
dcce2cfd8d merge coverity
--HG--
branch : coverity
2018-02-19 23:14:49 +08:00
Matt Johnston
00a1290173 merge coverity up to date
--HG--
branch : coverity
2018-02-17 11:29:17 +08:00
Matt Johnston
a3a0b26581 limit travis branches
--HG--
branch : coverity
2018-02-10 19:06:13 +08:00
Matt Johnston
276197b404 merge
--HG--
branch : coverity
2018-02-10 19:03:54 +08:00
Matt Johnston
484d1e9b81 merge
--HG--
branch : coverity
2018-02-10 08:27:30 +08:00
Matt Johnston
278a3e43e5 merge
--HG--
branch : coverity
2018-02-09 23:58:47 +08:00
Matt Johnston
2df2117388 update coverity
--HG--
branch : coverity
2018-02-09 23:49:22 +08:00
Matt Johnston
187fc95deb merge
--HG--
branch : coverity
2017-06-24 23:33:16 +08:00
Matt Johnston
b75a033787 merge
--HG--
branch : coverity
2017-06-03 00:10:58 +08:00
Matt Johnston
423be0d5e6 merge coverity
--HG--
branch : coverity
2017-05-18 23:02:39 +08:00
Matt Johnston
68b3ef0734 merge coverity
--HG--
branch : coverity
2016-07-22 00:08:02 +08:00
Matt Johnston
d58e0497cc merge
--HG--
branch : coverity
2016-03-18 22:47:33 +08:00
Matt Johnston
af10eb8346 merge
--HG--
branch : coverity
2016-03-15 23:20:40 +08:00
Matt Johnston
8e93ac9925 merge up to date
--HG--
branch : coverity
2016-03-15 22:45:43 +08:00
Matt Johnston
6d5b27715a merge
--HG--
branch : coverity
2015-12-15 22:24:34 +08:00
Matt Johnston
f295fbe0b2 merge
--HG--
branch : coverity
2015-12-02 22:37:51 +08:00
Matt Johnston
575f0e5f92 merge
--HG--
branch : coverity
2015-11-23 23:04:48 +08:00
Matt Johnston
85374c5ba2 merge
--HG--
branch : coverity
2015-08-07 21:26:03 +08:00
Matt Johnston
83f3f55280 merge
--HG--
branch : coverity
2015-06-23 21:49:04 +08:00
Matt Johnston
b2beb2c2da coverity shouldn't have a matrix
--HG--
branch : coverity
2015-06-13 23:39:55 +08:00
Matt Johnston
48ad370a19 fix travis coverity matrix?
--HG--
branch : coverity
2015-06-13 23:36:03 +08:00
Matt Johnston
c36f94a322 fiddle with coverity travis
--HG--
branch : coverity
2015-06-13 23:32:15 +08:00
Matt Johnston
6493bbb7e7 merge up to date, attempt to fix travis.yml
--HG--
branch : coverity
2015-06-12 23:02:15 +08:00
Matt Johnston
3ec2737d54 merge main
--HG--
branch : coverity
2015-04-14 20:44:30 +08:00
Matt Johnston
72ccfda5b2 merge
--HG--
branch : coverity
2015-03-02 21:17:41 +08:00
Matt Johnston
003ec5d356 merge
--HG--
branch : coverity
2015-02-28 23:25:16 +08:00
Matt Johnston
f91d66448a merge
--HG--
branch : coverity
2015-02-24 22:48:34 +08:00
Matt Johnston
ccfdf7e039 merge
--HG--
branch : coverity
2015-02-10 21:47:43 +08:00
Matt Johnston
95ce05da40 merge
--HG--
branch : coverity
2015-01-28 22:49:55 +08:00
Matt Johnston
c5d53cf81c merge
--HG--
branch : coverity
2015-01-28 21:40:34 +08:00
Matt Johnston
5574460d25 merge
--HG--
branch : coverity
2015-01-04 22:33:12 +08:00
Matt Johnston
233fd96994 merge to coverity
--HG--
branch : coverity
2014-10-21 22:34:20 +08:00
Matt Johnston
d1b29336b1 merge
--HG--
branch : coverity
2014-08-19 23:36:46 +08:00
Matt Johnston
fa5eb62464 merge
--HG--
branch : coverity
2014-08-08 21:26:07 +08:00
Matt Johnston
0b48a4f879 merge
--HG--
branch : coverity
2014-07-28 23:38:54 +08:00
Matt Johnston
00ef081fcf merge
--HG--
branch : coverity
2014-07-28 22:56:07 +08:00
Matt Johnston
dabeaec461 merge
--HG--
branch : coverity
2014-07-26 10:23:53 +08:00
Matt Johnston
d4ed2fffe4 merge
--HG--
branch : coverity
2014-07-25 22:23:50 +08:00
Matt Johnston
0533b87b1a merge
--HG--
branch : coverity
2014-03-08 21:02:02 +08:00
Matt Johnston
7504cd1a1a Don't 'make install' for coverity
--HG--
branch : coverity
2014-03-08 21:00:32 +08:00
Matt Johnston
482dc0eff4 Fix the right build line
--HG--
branch : coverity
2014-03-08 18:16:11 +08:00
Matt Johnston
fc34d02427 Fix quoting for coverity
--HG--
branch : coverity
2014-03-08 18:09:00 +08:00
Matt Johnston
5ce5fbcba0 More for coverity
--HG--
branch : coverity
2014-03-08 16:56:15 +08:00
Matt Johnston
31d2311537 Add coverity bits
--HG--
branch : coverity
2014-03-08 14:56:27 +08:00
137 changed files with 3601 additions and 16439 deletions

View File

@@ -1,9 +0,0 @@
#!/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 "$@"

View File

@@ -1,25 +0,0 @@
# Checks that autoconf has been run if configure.ac was updated
# Assumes that autoconf 2.69 was run, the same as ubuntu 20.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@v2
- name: run autoconf
run: autoconf && autoheader
- name: check no difference
run: git diff --exit-code

View File

@@ -1,268 +0,0 @@
# 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-18.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
- 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
- name: macos 11
os: macos-11
cc: clang
extracflags: -Wno-deprecated-declarations -Wno-undef
runcheck: 'no'
apt: 'no'
ranlib: ranlib -no_warning_for_no_symbols
# Check that debug code doesn't bitrot
- name: DEBUG_TRACE
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
# # 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@v2
- 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" > localoptions.h
echo "#define DROPBEAR_DSS 1" >> localoptions.h
cat localoptions.h
- name: nondefault
if: ${{ matrix.nondefault }}
run: |
# Turn on anything that's off by default. Rough but seems sufficient
grep ' 0$' 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: 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: gendss
if: ${{ matrix.runcheck != 'no' }}
run: ~/inst/bin/dropbearkey -t dss -f testdss
- 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

View File

@@ -1,30 +0,0 @@
# 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@v1
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

View File

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

10
.gitignore vendored
View File

@@ -19,11 +19,9 @@
/fuzzer-*.options /fuzzer-*.options
/scp /scp
/scp-progress /scp-progress
config.h
default_options_guard.h
localoptions.h
Makefile Makefile
config.h
config.h.in
configure
default_options_guard.h
tags tags
.pytest*
*.pyc
/test/venv

View File

@@ -1,6 +1,2 @@
\..*\.swp .*\.o
.*~ .*~
tags
.pytest*
.*\.pyc
test/venv

View File

@@ -27,5 +27,3 @@ fd1981f41c626a969f07b4823848deaefef3c8aa 0 iQIcBAABCgAGBQJW4W2TAAoJEESTFJTynGdzu
07b0d56d186d7eeef4106137a3eba554959ba0e3 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlyWOo8ACgkQRJMUlPKcZ3O+MQ//c5oeDUvZuFiI4FHZqfIK/59YAciTP+9TQmoWDVSuOdkd9ZYJA7b7DCusqP2TWFEIl9M7i5hTLTMD21xuEQQtfOSP6EXpUw6JNdh/lsJs7EDlFANtwkdEozAQozFKnXbJEV3y9WldEWUlmPFjt4fJQIuG10SU7MTJHcSaQddJCh3I1//F4EvgRe+OqyrFwKekGiFdvfjcIFN3lQmk6K1Sc0MgyIO/VVZm/AQpBi0Dlg0yOl+EDcxxlmeSInbvLceWSP6op35I4dE5YWH1UetjzIsr5AIM15/k3viAKDDefY1EMAzK9b7YAF4BLw0a6XoQu0apvcWaALE/bJzWNSg/QbCm2JAZzk21WLLvR+AELzPfKXrHX3o0h51lpQ4rs7EWKUm43dJPoWkcFNOU+BDsNzffcJgChbRs48ut89DYLiGmSxhRxE77VPbA+klgTGdctOTLd8psseRlGYCuGe8zeota80bV9fUZ9WJZHwNgEWGowKUoTjy6l5k9OH3iQuQX3OXoy78ufRgWDulE7noVTMhXurQ8a0Jf2k/MW9dcnqGVkWitCFKPEvZwVmWyW2AWsdMcBJnFFGzDsNSxWTtCF9XcxieDO1IB8vGwYcb1TwEVuVzvR/wwvc3PgVikF+4Qv2NqdoQc1yn2PkocY2hwXyIZUAwz7erNumlTbeC/JK8= 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= 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= 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=
88f63b8b0f131f24aa90c9b852622b922b1ad738 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl71/sAACgkQRJMUlPKcZ3OlSQ/9GYLotOmsYK0gvSfWLYR9a8WGgT/4EU6RgAkMBLS9TBp0E3V4VUDralnqoId7hNO2cUkRS7boOM2g4/YRShah8gonSJa70lKjUpDeQUPuGwUYWLNKr9qxJtnAcd1rOE4WYxKEUfjPWHBbVsT3QIIdj1Zy31GDKZgELRBQeOyt62RdXYHMaMHHDgg2U/wO9bcRRe5G7mYJf7Vm8sAWyTZXvta2jORxgs4XxWe7xJ9Dj0lMSG5HmfvH5NrGHM1GK3pL0GREKj2+xNSFdkSeHIgSSoHM2qZTVSWtNfx0+fZaRBgvXPPYzDTTghj1mKEaPFoRzg/B8s+NmHupJftT1yyapKFjALo1N6eaPHRRSwVfmnoWSJLu4fwL8TK5wMJr9eGl3QgAnperQPEFT9UHJBIwZ1D+RMuI3pEESdHBJFAYIAyisJI6XyzMhLsysoShlHs6OjFcJ9jTe4pzg9pO+KaPbLYsBJxJUsrtHwV8P9CHxY6CEuKm0AZjYDopYhzLuAUjGJjYDf/C9vJ/xtTOqIm9nywfcFwqgLrmQFhNHHGyOJVr+y/cey1sT9E4/gBv9kor+6qSITALv2g0JTaOpzpkE0zbafUy2r777Wex4WNQEha6bYZFi2aiqxqqX93UHzv+YhmN8n9mlc21xoZMPNtAb2mSxx7rO+PScb5uflKOCYE=
5879c5829e8569466386e7c64252b01b99705628 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl+axlIACgkQRJMUlPKcZ3PZuhAAkzCj+lOt2hHigIHB0zkNUC9nRIE1TItJD4wqQ03nMY4ycBMsb74o1AHsQTtVG6sm2YGSmQuZ0VxG1iuW9nKTsM1hzB40G45i5waIEzxVG8PbZ2i6zLK2Xz2YQ+FBvIg1EKfH7Dyd3r4FqYxauGOQdrUiKwuc3H4r65HpUmT0tIypqahFoRmj1+K/ZSPak0+ZPL27VQ4b/Ts8QS7XwFYTZsMDovYNdFJmaMhBbBe33/zGFWBPk6NCJWrBd3jmJN/LhZp0a5T4fAZ6iA2WjXDWOSiWZaLLk49zM6WYrc4QihEj7ngecj/UUXKR/sWPva8+rHf9YQLZu2lc6IMABCpUkeKLFoJqzvnKGA2rhl1LpRcnNA30/7yJt0YhfFcKhBkjjSxiOH3v0qMPADHMo5poqCKH/x4TVGVyVgzCqcxd+AzsDu77fzfzbxlyQ7wp+VmwXmeHbPfuBc8u9HUBa6Fc4b667aDD26a2S9VKdRYuSp3DkOwCLJUmRqmw+sXKvXlPyxPMUxOi/4R5nbJacD5Js1AH7WH49pAFMJ6bDCQ8QEmOh+Qpqc3RzTBwt1CLl+zt0NLKDmRYSgAY9GZpuju7r+aj2Semjd7nwmq4Y5xtWCh673lea/n7JS0mtBWouVbGgMJErg7QjuqOS3oE77viLcGLpX9niDcGvCL/N3gE13A=

View File

@@ -59,5 +59,3 @@ c31276613181c5cff7854e7ef586ace03424e55e DROPBEAR_2017.75
6d1bbe7d5fa5827c7eae28bca044d691f7efa785 DROPBEAR_2019.77 6d1bbe7d5fa5827c7eae28bca044d691f7efa785 DROPBEAR_2019.77
009d52ae26d35f3381c801e02318fa9be34be93c DROPBEAR_2019.78 009d52ae26d35f3381c801e02318fa9be34be93c DROPBEAR_2019.78
e2e4929d057b09422f2ea4556fb64209aff58161 DROPBEAR_2020.79 e2e4929d057b09422f2ea4556fb64209aff58161 DROPBEAR_2020.79
73646de50f1351735c868d4874f058ff9ad62c96 DROPBEAR_2020.80
4b984c42372d01fcc2fd487c58af6a5aa65eb88e DROPBEAR_2020.81

36
.travis.yml Normal file
View File

@@ -0,0 +1,36 @@
language: c
git:
depth: 3
env:
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
- secure: "F4rKQrHK/u58vPo3F9+x0WYXAeMFJvvtH9BIGZqx9yw8bUnL+gk0Ge9wnHHTXRcgCTqoc7B35uMS5njpH+Su/esVjrLAq85f/AmQctlRpmApwGK9LyxkIvx3UJN0nqfeeDXA90/8FUZ+n/qnCydXmYCEgqSaBCNydDxW1oqYUIc="
- BUNDLEDLIBTOM=--enable-bundled-libtom
- MULTI=1
before_install:
- echo -n | openssl s_client -connect https://scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
addons:
apt:
packages:
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
- zlib1g-dev
- libtomcrypt-dev
- libtommath-dev
coverity_scan:
project:
name: "mkj/dropbear"
description: "Dropbear SSH"
notification_email: matt@ucc.asn.au
build_command_prepend: autoconf && autoheader && ./configure --enable-bundled-libtom CFLAGS='-O2 -Wall -Wno-pointer-sign' --prefix=$HOME/inst
build_command: make MULTI=1
branch_pattern: coverity
branches:
only:
- master
- coverity

281
CHANGES
View File

@@ -1,262 +1,3 @@
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 2020.80 - 26 June 2020
- Don't block authorized_keys logins with no-X11-forwarding or no-agent-forwarding - Don't block authorized_keys logins with no-X11-forwarding or no-agent-forwarding
@@ -474,7 +215,7 @@ Infrastructure:
dropbear is running with -a (Allow connections to forwarded ports from any host) 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. 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. Affects versions 2013.56 to 2016.74. Thanks to Mark Shepard for reporting the crash.
CVE-2017-9078 https://hg.ucc.asn.au/dropbear/rev/c8114a48837c CVE-2017-9078 https://secure.ucc.asn.au/hg/dropbear/rev/c8114a48837c
- Security: Fix information disclosure with ~/.ssh/authorized_keys symlink. - Security: Fix information disclosure with ~/.ssh/authorized_keys symlink.
Dropbear parsed authorized_keys as root, even if it were a symlink. The fix Dropbear parsed authorized_keys as root, even if it were a symlink. The fix
@@ -486,7 +227,7 @@ Infrastructure:
contents of that file. contents of that file.
This information disclosure is to an already authenticated user. This information disclosure is to an already authenticated user.
Thanks to Jann Horn of Google Project Zero for reporting this. Thanks to Jann Horn of Google Project Zero for reporting this.
CVE-2017-9079 https://hg.ucc.asn.au/dropbear/rev/0d889b068123 CVE-2017-9079 https://secure.ucc.asn.au/hg/dropbear/rev/0d889b068123
- Generate hostkeys with dropbearkey atomically and flush to disk with fsync - Generate hostkeys with dropbearkey atomically and flush to disk with fsync
Thanks to Andrei Gherzan for a patch Thanks to Andrei Gherzan for a patch
@@ -506,23 +247,23 @@ Infrastructure:
run arbitrary code as the dbclient user. This could be a problem if scripts run arbitrary code as the dbclient user. This could be a problem if scripts
or webpages pass untrusted input to the dbclient program. or webpages pass untrusted input to the dbclient program.
CVE-2016-7406 CVE-2016-7406
https://hg.ucc.asn.au/dropbear/rev/b66a483f3dcb https://secure.ucc.asn.au/hg/dropbear/rev/b66a483f3dcb
- Security: dropbearconvert import of OpenSSH keys could run arbitrary code as - Security: dropbearconvert import of OpenSSH keys could run arbitrary code as
the local dropbearconvert user when parsing malicious key files the local dropbearconvert user when parsing malicious key files
CVE-2016-7407 CVE-2016-7407
https://hg.ucc.asn.au/dropbear/rev/34e6127ef02e https://secure.ucc.asn.au/hg/dropbear/rev/34e6127ef02e
- Security: dbclient could run arbitrary code as the local dbclient user if - 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 particular -m or -c arguments are provided. This could be an issue where
dbclient is used in scripts. dbclient is used in scripts.
CVE-2016-7408 CVE-2016-7408
https://hg.ucc.asn.au/dropbear/rev/eed9376a4ad6 https://secure.ucc.asn.au/hg/dropbear/rev/eed9376a4ad6
- Security: dbclient or dropbear server could expose process memory to the - Security: dbclient or dropbear server could expose process memory to the
running user if compiled with DEBUG_TRACE and running with -v running user if compiled with DEBUG_TRACE and running with -v
CVE-2016-7409 CVE-2016-7409
https://hg.ucc.asn.au/dropbear/rev/6a14b1f6dc04 https://secure.ucc.asn.au/hg/dropbear/rev/6a14b1f6dc04
The security issues were reported by an anonymous researcher working with The security issues were reported by an anonymous researcher working with
Beyond Security's SecuriTeam Secure Disclosure www.beyondsecurity.com/ssd.html Beyond Security's SecuriTeam Secure Disclosure www.beyondsecurity.com/ssd.html
@@ -568,7 +309,7 @@ Infrastructure:
- Validate X11 forwarding input. Could allow bypass of authorized_keys command= restrictions, - 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 found by github.com/tintinweb. Thanks for Damien Miller for a patch. CVE-2016-3116
https://hg.ucc.asn.au/dropbear/rev/a3e8389e01ff https://secure.ucc.asn.au/hg/dropbear/rev/a3e8389e01ff
2015.71 - 3 December 2015 2015.71 - 3 December 2015
@@ -849,11 +590,11 @@ kernels, from Steve Dover
- Limit the size of decompressed payloads, avoids memory exhaustion denial - Limit the size of decompressed payloads, avoids memory exhaustion denial
of service of service
Thanks to Logan Lamb for reporting and investigating it. CVE-2013-4421 Thanks to Logan Lamb for reporting and investigating it. CVE-2013-4421
https://hg.ucc.asn.au/dropbear/rev/0bf76f54de6f https://secure.ucc.asn.au/hg/dropbear/rev/0bf76f54de6f
- Avoid disclosing existence of valid users through inconsistent delays - Avoid disclosing existence of valid users through inconsistent delays
Thanks to Logan Lamb for reporting. CVE-2013-4434 Thanks to Logan Lamb for reporting. CVE-2013-4434
https://hg.ucc.asn.au/dropbear/rev/d7784616409a https://secure.ucc.asn.au/hg/dropbear/rev/d7784616409a
- Update config.guess and config.sub for newer architectures - Update config.guess and config.sub for newer architectures
@@ -956,7 +697,7 @@ though probably will be soon
This bug affects releases 0.52 onwards. Ref CVE-2012-0920. This bug affects releases 0.52 onwards. Ref CVE-2012-0920.
Thanks to Danny Fullerton of Mantor Organization for reporting Thanks to Danny Fullerton of Mantor Organization for reporting
the bug. the bug.
https://hg.ucc.asn.au/dropbear/rev/818108bf7749 https://secure.ucc.asn.au/hg/dropbear/rev/818108bf7749
- Compile fix, only apply IPV6 socket options if they are available in headers - Compile fix, only apply IPV6 socket options if they are available in headers
Thanks to Gustavo Zacarias for the patch Thanks to Gustavo Zacarias for the patch
@@ -1000,7 +741,7 @@ though probably will be soon
- New version numbering scheme. - New version numbering scheme.
Source repository has now migrated to Mercurial at Source repository has now migrated to Mercurial at
https://hg.ucc.asn.au/dropbear/graph/default https://secure.ucc.asn.au/hg/dropbear/graph/default
0.53.1 - Wednesday 2 March 2011 0.53.1 - Wednesday 2 March 2011

View File

@@ -6,12 +6,12 @@ Basic Dropbear build instructions:
localoptions.h should be located in the build directory if you are localoptions.h should be located in the build directory if you are
building out of tree. building out of tree.
- If using a Mercurial or Git checkout, "autoconf; autoheader"
- Configure for your system: - Configure for your system:
./configure (optionally with --disable-zlib or --disable-syslog, ./configure (optionally with --disable-zlib or --disable-syslog,
or --help for other options) or --help for other options)
(you'll need to first run "autoconf; autoheader" if you edit configure.ac)
- Compile: - Compile:
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
@@ -58,7 +58,7 @@ 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). 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 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, 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 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 It is possible to compile zlib in, by copying zlib.h and zconf.h into a
subdirectory (ie zlibincludes), and subdirectory (ie zlibincludes), and

View File

@@ -20,13 +20,13 @@ LIBTOM_LIBS=@LIBTOM_LIBS@
ifeq (@BUNDLED_LIBTOM@, 1) ifeq (@BUNDLED_LIBTOM@, 1)
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM) LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_CLEAN=ltc-clean ltm-clean LIBTOM_CLEAN=ltc-clean ltm-clean
CPPFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/ CFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM) LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
endif endif
OPTION_HEADERS = default_options_guard.h sysoptions.h OPTION_HEADERS = default_options_guard.h sysoptions.h
ifneq ($(wildcard localoptions.h),) ifneq ($(wildcard localoptions.h),)
CPPFLAGS+=-DLOCALOPTIONS_H_EXISTS CFLAGS+=-DLOCALOPTIONS_H_EXISTS
OPTION_HEADERS += localoptions.h OPTION_HEADERS += localoptions.h
endif endif
@@ -35,8 +35,8 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
signkey.o rsa.o dbrandom.o \ signkey.o rsa.o dbrandom.o \
queue.o \ queue.o \
atomicio.o compat.o fake-rfc2553.o \ atomicio.o compat.o fake-rfc2553.o \
ltc_prng.o ecc.o ecdsa.o sk-ecdsa.o crypto_desc.o \ ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
curve25519.o ed25519.o sk-ed25519.o \ curve25519.o ed25519.o \
dbmalloc.o \ dbmalloc.o \
gensignkey.o gendss.o genrsa.o gened25519.o gensignkey.o gendss.o genrsa.o gened25519.o
@@ -57,14 +57,15 @@ CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
KEYOBJS=dropbearkey.o KEYOBJS=dropbearkey.o
CONVERTOBJS=dropbearconvert.o keyimport.o signkey_ossh.o CONVERTOBJS=dropbearconvert.o keyimport.o
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
ifeq (@DROPBEAR_FUZZ@, 1) ifeq (@DROPBEAR_FUZZ@, 1)
allobjs = $(COMMONOBJS) fuzz/fuzz-common.o fuzz/fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@ allobjs = $(COMMONOBJS) fuzz-common.o fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@
allobjs:=$(subst svr-main.o, ,$(allobjs)) allobjs:=$(subst svr-main.o, ,$(allobjs))
allobjs:=$(subst cli-main.o, ,$(allobjs)) allobjs:=$(subst cli-main.o, ,$(allobjs))
allobjs:=$(sort $(allobjs))
dropbearobjs=$(allobjs) svr-main.o dropbearobjs=$(allobjs) svr-main.o
dbclientobjs=$(allobjs) cli-main.o dbclientobjs=$(allobjs) cli-main.o
@@ -72,7 +73,6 @@ ifeq (@DROPBEAR_FUZZ@, 1)
dropbearconvertobjs=$(allobjs) $(CONVERTOBJS) dropbearconvertobjs=$(allobjs) $(CONVERTOBJS)
# CXX only set when fuzzing # CXX only set when fuzzing
CXX=@CXX@ CXX=@CXX@
FUZZ_CLEAN=fuzz-clean
else else
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS) dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS) dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
@@ -107,8 +107,8 @@ AR=@AR@
RANLIB=@RANLIB@ RANLIB=@RANLIB@
STRIP=@STRIP@ STRIP=@STRIP@
INSTALL=@INSTALL@ INSTALL=@INSTALL@
CPPFLAGS+=@CPPFLAGS@ -I. -I$(srcdir) CPPFLAGS=@CPPFLAGS@
CFLAGS+=@CFLAGS@ CFLAGS+=-I. -I$(srcdir) $(CPPFLAGS) @CFLAGS@
LIBS+=@LIBS@ LIBS+=@LIBS@
LDFLAGS=@LDFLAGS@ LDFLAGS=@LDFLAGS@
@@ -119,16 +119,15 @@ STATIC=@STATIC@
# whether we're building client, server, or both for the common objects. # whether we're building client, server, or both for the common objects.
# evilness so we detect 'dropbear' by itself as a word # evilness so we detect 'dropbear' by itself as a word
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdropbearZ, Z$(prog)Z)))) ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdropbearZ, Z$(prog)Z))))
CPPFLAGS+= -DDROPBEAR_SERVER CFLAGS+= -DDROPBEAR_SERVER
endif endif
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdbclientZ, Z$(prog)Z)))) ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdbclientZ, Z$(prog)Z))))
CPPFLAGS+= -DDROPBEAR_CLIENT CFLAGS+= -DDROPBEAR_CLIENT
endif endif
# these are exported so that libtomcrypt's makefile will use them # these are exported so that libtomcrypt's makefile will use them
export CC export CC
export CFLAGS export CFLAGS
export CPPFLAGS
export RANLIB AR STRIP export RANLIB AR STRIP
ifeq ($(STATIC), 1) ifeq ($(STATIC), 1)
@@ -143,7 +142,7 @@ endif
# for the scp progress meter. The -D doesn't affect anything else. # for the scp progress meter. The -D doesn't affect anything else.
ifeq ($(SCPPROGRESS), 1) ifeq ($(SCPPROGRESS), 1)
CPPFLAGS+=-DPROGRESS_METER CFLAGS+=-DPROGRESS_METER
endif endif
all: $(TARGETS) all: $(TARGETS)
@@ -217,7 +216,7 @@ scp: $(SCPOBJS) $(HEADERS) Makefile
MULTIOBJS= MULTIOBJS=
ifeq ($(MULTI),1) ifeq ($(MULTI),1)
MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs))) MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
CPPFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
endif endif
dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile
@@ -237,7 +236,7 @@ $(STATIC_LTC): $(OPTION_HEADERS)
$(STATIC_LTM): $(OPTION_HEADERS) $(STATIC_LTM): $(OPTION_HEADERS)
$(MAKE) -C libtommath $(MAKE) -C libtommath
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint check .PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint
ltc-clean: ltc-clean:
$(MAKE) -C libtomcrypt clean $(MAKE) -C libtomcrypt clean
@@ -248,7 +247,7 @@ ltm-clean:
sizes: dropbear sizes: dropbear
objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn
clean: $(LIBTOM_CLEAN) $(FUZZ_CLEAN) thisclean clean: $(LIBTOM_CLEAN) thisclean
thisclean: thisclean:
-rm -f dropbear$(EXEEXT) dbclient$(EXEEXT) dropbearkey$(EXEEXT) \ -rm -f dropbear$(EXEEXT) dbclient$(EXEEXT) dropbearkey$(EXEEXT) \
@@ -266,46 +265,50 @@ tidy:
lint: lint:
cd $(srcdir); ./dropbear_lint.sh cd $(srcdir); ./dropbear_lint.sh
check: lint
make -C test
## Fuzzing targets ## Fuzzing targets
# list of fuzz targets # list of fuzz targets
FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths \ FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519
fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths \
fuzzer-postauth_nomaths
FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \
fuzz/fuzz-sshpacketmutator.o
list-fuzz-targets: list-fuzz-targets:
@echo $(FUZZ_TARGETS) @echo $(FUZZ_TARGETS)
# fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs # fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs
fuzzstandalone: FUZZLIB=fuzz/fuzz-harness.o fuzzstandalone: FUZZLIB=fuzz-harness.o
fuzzstandalone: fuzz/fuzz-harness.o fuzz-targets fuzzstandalone: fuzz-harness.o fuzz-targets
# Build all the fuzzers. Usually like # exclude svr-main.o to avoid duplicate main
# make fuzz-targets FUZZLIB=-lFuzzer.a svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs))
# the library provides main(). Otherwise
# make fuzzstandalone fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) fuzz-common.o
# provides a main in fuzz-harness.c
# 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().
fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS) fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
$(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS) fuzzer-preauth: fuzzer-preauth.o fuzz-harness.o
$(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
# fuzzers that use the custom mutator - these expect a SSH network stream fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o fuzz-harness.o
MUTATOR_FUZZERS=fuzzer-client fuzzer-client_nomaths \ $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
fuzzer-preauth fuzzer-preauth_nomaths fuzzer-postauth_nomaths
# Skip custom mutators for -fsanitize-memory since libfuzzer doesn't initialise memory fuzzer-pubkey: fuzzer-pubkey.o fuzz-harness.o
# Pending fix for it https://github.com/google/oss-fuzz/issues/4605 $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
ifeq (,$(findstring fsanitize=memory, $(CFLAGS)))
$(MUTATOR_FUZZERS): allobjs += fuzz/fuzz-sshpacketmutator.o fuzzer-verify: fuzzer-verify.o fuzz-harness.o
endif $(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@
fuzzer-%.options: Makefile fuzzer-%.options: Makefile
echo "[libfuzzer]" > $@ echo "[libfuzzer]" > $@
@@ -324,5 +327,7 @@ fuzz-hostkeys:
/usr/bin/xxd -i -a keyd >> hostkeys.c /usr/bin/xxd -i -a keyd >> hostkeys.c
/usr/bin/xxd -i -a keyed25519 >> hostkeys.c /usr/bin/xxd -i -a keyed25519 >> hostkeys.c
fuzz-clean: # to make coverity happy?
-rm -f fuzz/*.o $(FUZZ_TARGETS) $(FUZZER_OPTIONS) test:
true

2
README
View File

@@ -8,8 +8,6 @@ which performs multiple tasks, to save disk space)
SMALL has some tips on creating small binaries. SMALL 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 :) 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 There is also a mailing list http://lists.ucc.gu.uwa.edu.au/mailman/listinfo/dropbear

11
SMALL
View File

@@ -9,7 +9,10 @@ The same applies if you are compiling just a client.
--- ---
The following are set in localoptions.h: 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 - If you're compiling statically, you can turn off host lookups
@@ -47,10 +50,4 @@ deciding.
Of course using small C libraries such as uClibc and dietlibc can also help. Of course using small C libraries such as uClibc and dietlibc 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. If you have any queries, mail me and I'll see if I can help.

20
auth.h
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -28,7 +28,6 @@
#include "includes.h" #include "includes.h"
#include "buffer.h" #include "buffer.h"
#include "circbuffer.h" #include "circbuffer.h"
#include "netio.h"
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1 #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
#define SSH_OPEN_CONNECT_FAILED 2 #define SSH_OPEN_CONNECT_FAILED 2
@@ -42,6 +41,13 @@
struct ChanType; 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 { struct Channel {
unsigned int index; /* the local channel index */ unsigned int index; /* the local channel index */
@@ -54,9 +60,6 @@ struct Channel {
int readfd; /* read from insecure side, written to wire */ int readfd; /* read from insecure side, written to wire */
int errfd; /* used like writefd or readfd, depending if it's client or server. int errfd; /* used like writefd or readfd, depending if it's client or server.
Doesn't exactly belong here, but is cleaner here */ 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 socket or PTY.
That is handled differently when closing FDs */
circbuffer *writebuf; /* data from the wire, for local consumption. Can be circbuffer *writebuf; /* data from the wire, for local consumption. Can be
initially NULL */ initially NULL */
circbuffer *extrabuf; /* extended-data for the program - used like writebuf circbuffer *extrabuf; /* extended-data for the program - used like writebuf
@@ -65,9 +68,6 @@ struct Channel {
/* whether close/eof messages have been exchanged */ /* whether close/eof messages have been exchanged */
int sent_close, recv_close; int sent_close, recv_close;
int recv_eof, sent_eof; 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; struct dropbear_progress_connection *conn_pending;
int initconn; /* used for TCP forwarding, whether the channel has been int initconn; /* used for TCP forwarding, whether the channel has been
@@ -77,22 +77,25 @@ struct Channel {
for this channel (and are awaiting a confirmation for this channel (and are awaiting a confirmation
or failure). */ or failure). */
int flushing;
/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */ /* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
void (*read_mangler)(const struct Channel*, const unsigned char* bytes, int *len); void (*read_mangler)(const struct Channel*, const unsigned char* bytes, int *len);
const struct ChanType* type; const struct ChanType* type;
enum dropbear_prio prio; enum dropbear_channel_prio prio;
}; };
struct ChanType { struct ChanType {
int sepfds; /* Whether this channel has separate pipes for in/out or not */
const char *name; const char *name;
/* Sets up the channel */ /* Sets up the channel */
int (*inithandler)(struct Channel*); int (*inithandler)(struct Channel*);
/* Called to check whether a channel should close, separately from the FD being EOF. /* Called to check whether a channel should close, separately from the FD being closed.
Used for noticing process exiting */ Used for noticing process exiting */
int (*check_close)(struct Channel*); int (*check_close)(const struct Channel*);
/* Handler for ssh_msg_channel_request */ /* Handler for ssh_msg_channel_request */
void (*reqhandler)(struct Channel*); void (*reqhandler)(struct Channel*);
/* Called prior to sending ssh_msg_channel_close, used for sending exit status */ /* Called prior to sending ssh_msg_channel_close, used for sending exit status */
@@ -101,7 +104,7 @@ struct ChanType {
void (*cleanup)(const struct Channel*); void (*cleanup)(const struct Channel*);
}; };
/* Callback for connect_remote. errstring may be NULL if result == DROPBEAR_SUCCESS */ /* Callback for connect_remote */
void channel_connect_done(int result, int sock, void* user_data, const char* errstring); void channel_connect_done(int result, int sock, void* user_data, const char* errstring);
void chaninitialise(const struct ChanType *chantypes[]); void chaninitialise(const struct ChanType *chantypes[]);

View File

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

View File

@@ -32,6 +32,12 @@
#include "packet.h" #include "packet.h"
#include "runopts.h" #include "runopts.h"
void cli_authinitialise() {
memset(&ses.authstate, 0, sizeof(ses.authstate));
}
/* Send a "none" auth request to get available methods */ /* Send a "none" auth request to get available methods */
void cli_auth_getmethods() { void cli_auth_getmethods() {
TRACE(("enter cli_auth_getmethods")) TRACE(("enter cli_auth_getmethods"))
@@ -82,11 +88,6 @@ void recv_msg_userauth_banner() {
return; return;
} }
if (cli_opts.quiet) {
TRACE(("not showing banner"))
return;
}
banner = buf_getstring(ses.payload, &bannerlen); banner = buf_getstring(ses.payload, &bannerlen);
buf_eatstring(ses.payload); /* The language string */ buf_eatstring(ses.payload); /* The language string */
@@ -265,10 +266,7 @@ void recv_msg_userauth_success() {
/* This function can validly get called multiple times /* This function can validly get called multiple times
if DROPBEAR_CLI_IMMEDIATE_AUTH is set */ if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
DEBUG1(("received msg_userauth_success")) TRACE(("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 /* Note: in delayed-zlib mode, setting authdone here
* will enable compression in the transport layer */ * will enable compression in the transport layer */
ses.authstate.authdone = 1; ses.authstate.authdone = 1;
@@ -296,6 +294,18 @@ int cli_auth_try() {
} }
#endif #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 DROPBEAR_CLI_INTERACT_AUTH
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) { if (!finished && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) { if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
@@ -310,18 +320,6 @@ int cli_auth_try() {
} }
#endif #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
TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype)) TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype))
if (finished) { if (finished) {

View File

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

View File

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

View File

@@ -125,7 +125,7 @@ void recv_msg_userauth_pk_ok() {
static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
const buffer *data_buf) { const buffer *data_buf) {
#if DROPBEAR_CLI_AGENTFWD #if DROPBEAR_CLI_AGENTFWD
/* TODO: rsa-sha256 agent */ // TODO: rsa-sha256 agent
if (key->source == SIGNKEY_SOURCE_AGENT) { if (key->source == SIGNKEY_SOURCE_AGENT) {
/* Format the agent signature ourselves, as buf_put_sign would. */ /* Format the agent signature ourselves, as buf_put_sign would. */
buffer *sigblob; buffer *sigblob;
@@ -147,7 +147,7 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype,
buffer* sigbuf = NULL; buffer* sigbuf = NULL;
enum signkey_type keytype = signkey_type_from_signature(sigtype); enum signkey_type keytype = signkey_type_from_signature(sigtype);
DEBUG1(("enter send_msg_userauth_pubkey %s", signature_name_from_type(sigtype, NULL))) TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype))
CHECKCLEARTOWRITE(); CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
@@ -176,7 +176,6 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype,
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len); buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf); cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf);
buf_free(sigbuf); /* Nothing confidential in the buffer */ buf_free(sigbuf); /* Nothing confidential in the buffer */
cli_ses.is_trivial_auth = 0;
} }
encrypt_packet(); encrypt_packet();

View File

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

View File

@@ -46,13 +46,6 @@ void send_msg_kexdh_init() {
TRACE(("send_msg_kexdh_init()")) TRACE(("send_msg_kexdh_init()"))
CHECKCLEARTOWRITE(); CHECKCLEARTOWRITE();
#if DROPBEAR_FUZZ
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
return;
}
#endif
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT); buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
switch (ses.newkeys->algo_kex->mode) { switch (ses.newkeys->algo_kex->mode) {
#if DROPBEAR_NORMAL_DH #if DROPBEAR_NORMAL_DH
@@ -105,12 +98,6 @@ void recv_msg_kexdh_reply() {
unsigned char* keyblob = NULL; unsigned char* keyblob = NULL;
TRACE(("enter recv_msg_kexdh_reply")) 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) { if (cli_ses.kex_state != KEXDH_INIT_SENT) {
dropbear_exit("Received out-of-order kexdhreply"); dropbear_exit("Received out-of-order kexdhreply");
@@ -229,8 +216,6 @@ static void ask_to_confirm(const unsigned char* keyblob, unsigned int keybloblen
fclose(tty); fclose(tty);
} else { } else {
response = getc(stdin); response = getc(stdin);
/* flush stdin buffer */
while ((getchar()) != '\n');
} }
if (response == 'y') { if (response == 'y') {
@@ -373,7 +358,7 @@ static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen)
if (ret == DROPBEAR_SUCCESS) { if (ret == DROPBEAR_SUCCESS) {
/* Good matching key */ /* Good matching key */
DEBUG1(("server match %s", fingerprint)) TRACE(("good matching key"))
goto out; goto out;
} }

View File

@@ -31,7 +31,9 @@
#include "dbrandom.h" #include "dbrandom.h"
#include "crypto_desc.h" #include "crypto_desc.h"
#include "netio.h" #include "netio.h"
#include "fuzz.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);
#if DROPBEAR_CLI_PROXYCMD #if DROPBEAR_CLI_PROXYCMD
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out); static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out);
@@ -47,7 +49,6 @@ int main(int argc, char ** argv) {
int sock_in, sock_out; int sock_in, sock_out;
struct dropbear_progress_connection *progress = NULL; struct dropbear_progress_connection *progress = NULL;
pid_t proxy_cmd_pid = 0;
_dropbear_exit = cli_dropbear_exit; _dropbear_exit = cli_dropbear_exit;
_dropbear_log = cli_dropbear_log; _dropbear_log = cli_dropbear_log;
@@ -65,17 +66,14 @@ int main(int argc, char ** argv) {
} }
#endif #endif
if (cli_opts.bind_address) { TRACE(("user='%s' host='%s' port='%s' bind_address='%s' bind_port='%s'", cli_opts.username,
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))
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) { if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
dropbear_exit("signal() error"); dropbear_exit("signal() error");
} }
pid_t proxy_cmd_pid = 0;
#if DROPBEAR_CLI_PROXYCMD #if DROPBEAR_CLI_PROXYCMD
if (cli_opts.proxycmd) { if (cli_opts.proxycmd) {
cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid); cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid);
@@ -88,9 +86,8 @@ int main(int argc, char ** argv) {
} else } else
#endif #endif
{ {
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port, cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port);
DROPBEAR_PRIO_LOWDELAY);
sock_in = sock_out = -1; sock_in = sock_out = -1;
} }
@@ -101,6 +98,58 @@ int main(int argc, char ** argv) {
} }
#endif /* DBMULTI stuff */ #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) { static void exec_proxy_cmd(const void *user_data_cmd) {
const char *cmd = user_data_cmd; const char *cmd = user_data_cmd;
char *usershell; char *usershell;
@@ -139,7 +188,6 @@ static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out) {
ret = spawn_command(exec_proxy_cmd, ex_cmd, ret = spawn_command(exec_proxy_cmd, ex_cmd,
sock_out, sock_in, NULL, pid_out); sock_out, sock_in, NULL, pid_out);
DEBUG1(("cmd: %s pid=%d", ex_cmd,*pid_out))
m_free(ex_cmd); m_free(ex_cmd);
if (ret == DROPBEAR_FAILURE) { if (ret == DROPBEAR_FAILURE) {
dropbear_exit("Failed running proxy command"); dropbear_exit("Failed running proxy command");
@@ -151,5 +199,4 @@ static void kill_proxy_sighandler(int UNUSED(signo)) {
kill_proxy_command(); kill_proxy_command();
_exit(1); _exit(1);
} }
#endif /* DROPBEAR_CLI_PROXYCMD */ #endif /* DROPBEAR_CLI_PROXYCMD */

View File

@@ -62,7 +62,6 @@ static void printhelp() {
"-T Don't allocate a pty\n" "-T Don't allocate a pty\n"
"-N Don't run a remote command\n" "-N Don't run a remote command\n"
"-f Run in background after auth\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 Always accept remote host key if unknown\n"
"-y -y Don't perform any remote host key checking (caution)\n" "-y -y Don't perform any remote host key checking (caution)\n"
"-s Request a subsystem (use by external sftp)\n" "-s Request a subsystem (use by external sftp)\n"
@@ -80,10 +79,9 @@ static void printhelp() {
#if DROPBEAR_CLI_REMOTETCPFWD #if DROPBEAR_CLI_REMOTETCPFWD
"-R <[listenaddress:]listenport:remotehost:remoteport> Remote port forwarding\n" "-R <[listenaddress:]listenport:remotehost:remoteport> Remote port forwarding\n"
#endif #endif
"-W <receive_window_buffer> (default %d, larger may be faster, max 10MB)\n" "-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
"-K <keepalive> (0 is never, default %d)\n" "-K <keepalive> (0 is never, default %d)\n"
"-I <idle_timeout> (0 is never, default %d)\n" "-I <idle_timeout> (0 is never, default %d)\n"
"-z disable QoS\n"
#if DROPBEAR_CLI_NETCAT #if DROPBEAR_CLI_NETCAT
"-B <endhost:endport> Netcat-alike forwarding\n" "-B <endhost:endport> Netcat-alike forwarding\n"
#endif #endif
@@ -97,7 +95,7 @@ static void printhelp() {
"-b [bind_address][:bind_port]\n" "-b [bind_address][:bind_port]\n"
"-V Version\n" "-V Version\n"
#if DEBUG_TRACE #if DEBUG_TRACE
"-v verbose (repeat for more verbose)\n" "-v verbose (compiled with DEBUG_TRACE)\n"
#endif #endif
,DROPBEAR_VERSION, cli_opts.progname, ,DROPBEAR_VERSION, cli_opts.progname,
#if DROPBEAR_CLI_PUBKEY_AUTH #if DROPBEAR_CLI_PUBKEY_AUTH
@@ -143,7 +141,6 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.username = NULL; cli_opts.username = NULL;
cli_opts.cmd = NULL; cli_opts.cmd = NULL;
cli_opts.no_cmd = 0; cli_opts.no_cmd = 0;
cli_opts.quiet = 0;
cli_opts.backgrounded = 0; cli_opts.backgrounded = 0;
cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */ cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
cli_opts.always_accept_key = 0; cli_opts.always_accept_key = 0;
@@ -155,7 +152,6 @@ void cli_getopts(int argc, char ** argv) {
#if DROPBEAR_CLI_ANYTCPFWD #if DROPBEAR_CLI_ANYTCPFWD
cli_opts.exit_on_fwd_failure = 0; cli_opts.exit_on_fwd_failure = 0;
#endif #endif
cli_opts.disable_trivial_auth = 0;
#if DROPBEAR_CLI_LOCALTCPFWD #if DROPBEAR_CLI_LOCALTCPFWD
cli_opts.localfwds = list_new(); cli_opts.localfwds = list_new();
opts.listen_fwd_all = 0; opts.listen_fwd_all = 0;
@@ -217,9 +213,6 @@ void cli_getopts(int argc, char ** argv) {
} }
cli_opts.always_accept_key = 1; cli_opts.always_accept_key = 1;
break; break;
case 'q': /* quiet */
cli_opts.quiet = 1;
break;
case 'p': /* remoteport */ case 'p': /* remoteport */
next = (char**)&cli_opts.remoteport; next = (char**)&cli_opts.remoteport;
break; break;
@@ -303,7 +296,7 @@ void cli_getopts(int argc, char ** argv) {
#endif #endif
#if DEBUG_TRACE #if DEBUG_TRACE
case 'v': case 'v':
debug_trace++; debug_trace = 1;
break; break;
#endif #endif
case 'F': case 'F':
@@ -326,9 +319,6 @@ void cli_getopts(int argc, char ** argv) {
case 'b': case 'b':
next = &bind_arg; next = &bind_arg;
break; break;
case 'z':
opts.disable_ip_tos = 1;
break;
default: default:
fprintf(stderr, fprintf(stderr,
"WARNING: Ignoring unknown option -%c\n", c); "WARNING: Ignoring unknown option -%c\n", c);
@@ -423,7 +413,7 @@ void cli_getopts(int argc, char ** argv) {
/* And now a few sanity checks and setup */ /* And now a few sanity checks and setup */
#if DROPBEAR_CLI_PROXYCMD #if DROPBEAR_CLI_PROXYCMD
if (cli_opts.proxycmd) { if (cli_opts.proxycmd) {
/* To match the common path of m_freeing it */ /* To match the common path of m_freeing it */
cli_opts.proxycmd = m_strdup(cli_opts.proxycmd); cli_opts.proxycmd = m_strdup(cli_opts.proxycmd);
@@ -435,10 +425,14 @@ void cli_getopts(int argc, char ** argv) {
} }
if (bind_arg) { if (bind_arg) {
if (split_address_port(bind_arg, /* split [host][:port] */
&cli_opts.bind_address, &cli_opts.bind_port) char *port = strrchr(bind_arg, ':');
== DROPBEAR_FAILURE) { if (port) {
dropbear_exit("Bad -b argument"); cli_opts.bind_port = m_strdup(port+1);
*port = '\0';
}
if (strlen(bind_arg) > 0) {
cli_opts.bind_address = m_strdup(bind_arg);
} }
} }
@@ -456,9 +450,12 @@ void cli_getopts(int argc, char ** argv) {
&& cli_opts.no_cmd == 0) { && cli_opts.no_cmd == 0) {
dropbear_exit("Command required for -f"); dropbear_exit("Command required for -f");
} }
if (recv_window_arg) { if (recv_window_arg) {
parse_recv_window(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);
}
} }
if (keepalive_arg) { if (keepalive_arg) {
unsigned int val; unsigned int val;
@@ -482,17 +479,6 @@ void cli_getopts(int argc, char ** argv) {
} }
#endif #endif
/* The hostname gets set up last, since
* in multi-hop mode it will require knowledge
* of other flags such as -i */
#if DROPBEAR_CLI_MULTIHOP
parse_multihop_hostname(host_arg, argv[0]);
#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) #if (DROPBEAR_CLI_PUBKEY_AUTH)
{ {
char *expand_path = expand_homedir_path(DROPBEAR_DEFAULT_CLI_AUTHKEY); char *expand_path = expand_homedir_path(DROPBEAR_DEFAULT_CLI_AUTHKEY);
@@ -501,6 +487,14 @@ void cli_getopts(int argc, char ** argv) {
} }
#endif #endif
/* The hostname gets set up last, since
* in multi-hop mode it will require knowledge
* of other flags such as -i */
#if DROPBEAR_CLI_MULTIHOP
parse_multihop_hostname(host_arg, argv[0]);
#else
parse_hostname(host_arg);
#endif
} }
#if DROPBEAR_CLI_PUBKEY_AUTH #if DROPBEAR_CLI_PUBKEY_AUTH
@@ -531,11 +525,11 @@ static void loadidentityfile(const char* filename, int warnfail) {
static char* static char*
multihop_passthrough_args() { multihop_passthrough_args() {
char *ret; char *ret;
unsigned int len, total; int total;
unsigned int len = 0;
m_list_elem *iter; m_list_elem *iter;
/* Fill out -i, -y, -W options that make sense for all /* Fill out -i, -y, -W options that make sense for all
* the intermediate processes */ * the intermediate processes */
len = 30; /* space for "-q -y -y -W <size>\0" */
#if DROPBEAR_CLI_PUBKEY_AUTH #if DROPBEAR_CLI_PUBKEY_AUTH
for (iter = cli_opts.privkeys->first; iter; iter = iter->next) for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{ {
@@ -543,40 +537,45 @@ multihop_passthrough_args() {
len += 3 + strlen(key->filename); len += 3 + strlen(key->filename);
} }
#endif /* DROPBEAR_CLI_PUBKEY_AUTH */ #endif /* DROPBEAR_CLI_PUBKEY_AUTH */
if (cli_opts.proxycmd) {
/* "-J 'cmd'" */
len += 6 + strlen(cli_opts.proxycmd);
}
len += 30; /* space for -W <size>, terminator. */
ret = m_malloc(len); ret = m_malloc(len);
total = 0; total = 0;
if (cli_opts.quiet) { if (cli_opts.no_hostkey_check)
total += m_snprintf(ret+total, len-total, "-q "); {
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;
} }
if (cli_opts.no_hostkey_check) { if (opts.recv_window != DEFAULT_RECV_WINDOW)
total += m_snprintf(ret+total, len-total, "-y -y "); {
} else if (cli_opts.always_accept_key) { int written = snprintf(ret+total, len-total, "-W %u ", opts.recv_window);
total += m_snprintf(ret+total, len-total, "-y "); total += written;
}
if (cli_opts.proxycmd) {
total += m_snprintf(ret+total, len-total, "-J '%s' ", cli_opts.proxycmd);
}
if (opts.recv_window != DEFAULT_RECV_WINDOW) {
total += m_snprintf(ret+total, len-total, "-W %u ", opts.recv_window);
} }
#if DROPBEAR_CLI_PUBKEY_AUTH #if DROPBEAR_CLI_PUBKEY_AUTH
for (iter = cli_opts.privkeys->first; iter; iter = iter->next) for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{ {
sign_key * key = (sign_key*)iter->item; sign_key * key = (sign_key*)iter->item;
total += m_snprintf(ret+total, len-total, "-i %s ", key->filename); const size_t size = len - total;
int written = snprintf(ret+total, size, "-i %s ", key->filename);
dropbear_assert((unsigned int)written < size);
total += written;
} }
#endif /* DROPBEAR_CLI_PUBKEY_AUTH */ #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 ret;
} }
@@ -590,9 +589,6 @@ multihop_passthrough_args() {
* dbclient -J "dbclient -B madako:22 wrt" madako * dbclient -J "dbclient -B madako:22 wrt" madako
* etc for as many hosts as we want. * 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. * Ports for hosts can be specified as host/port.
*/ */
static void parse_multihop_hostname(const char* orighostarg, const char* argv0) { static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
@@ -611,7 +607,7 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
&& strchr(cli_opts.username, '@')) { && strchr(cli_opts.username, '@')) {
unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2; unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
hostbuf = m_malloc(len); hostbuf = m_malloc(len);
m_snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg); snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
} else { } else {
hostbuf = m_strdup(orighostarg); hostbuf = m_strdup(orighostarg);
} }
@@ -634,18 +630,19 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
/* Set up the proxycmd */ /* Set up the proxycmd */
unsigned int cmd_len = 0; unsigned int cmd_len = 0;
char *passthrough_args = multihop_passthrough_args(); 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) { if (cli_opts.remoteport == NULL) {
cli_opts.remoteport = "22"; 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(cli_opts.remotehost) + strlen(cli_opts.remoteport)
+ strlen(passthrough_args) + strlen(passthrough_args)
+ 30; + 30;
/* replace proxycmd. old -J arguments have been copied cli_opts.proxycmd = m_malloc(cmd_len);
to passthrough_args */ snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s",
cli_opts.proxycmd = m_realloc(cli_opts.proxycmd, cmd_len); argv0, cli_opts.remotehost, cli_opts.remoteport,
m_snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s",
argv0, cli_opts.remotehost, cli_opts.remoteport,
passthrough_args, remainder); passthrough_args, remainder);
#ifndef DISABLE_ZLIB #ifndef DISABLE_ZLIB
/* The stream will be incompressible since it's encrypted. */ /* The stream will be incompressible since it's encrypted. */
@@ -892,7 +889,6 @@ static void add_extendedopt(const char* origstr) {
#if DROPBEAR_CLI_ANYTCPFWD #if DROPBEAR_CLI_ANYTCPFWD
"\tExitOnForwardFailure\n" "\tExitOnForwardFailure\n"
#endif #endif
"\tDisableTrivialAuth\n"
#ifndef DISABLE_SYSLOG #ifndef DISABLE_SYSLOG
"\tUseSyslog\n" "\tUseSyslog\n"
#endif #endif
@@ -920,10 +916,5 @@ static void add_extendedopt(const char* origstr) {
return; return;
} }
if (match_extendedopt(&optstr, "DisableTrivialAuth") == DROPBEAR_SUCCESS) {
cli_opts.disable_trivial_auth = parse_flag_value(optstr);
return;
}
dropbear_log(LOG_WARNING, "Ignoring unknown configuration option '%s'", origstr); dropbear_log(LOG_WARNING, "Ignoring unknown configuration option '%s'", origstr);
} }

View File

@@ -102,9 +102,6 @@ void cli_connected(int result, int sock, void* userdata, const char *errstring)
dropbear_exit("Connect failed: %s", errstring); dropbear_exit("Connect failed: %s", errstring);
} }
myses->sock_in = myses->sock_out = sock; myses->sock_in = myses->sock_out = sock;
DEBUG1(("cli_connected"))
ses.socket_prio = DROPBEAR_PRIO_NORMAL;
/* switches to lowdelay */
update_channel_prio(); update_channel_prio();
} }
@@ -168,7 +165,6 @@ static void cli_session_init(pid_t proxy_cmd_pid) {
/* Auth */ /* Auth */
cli_ses.lastprivkey = NULL; cli_ses.lastprivkey = NULL;
cli_ses.lastauthtype = 0; cli_ses.lastauthtype = 0;
cli_ses.is_trivial_auth = 1;
/* For printing "remote host closed" for the user */ /* For printing "remote host closed" for the user */
ses.remoteclosed = cli_remoteclosed; ses.remoteclosed = cli_remoteclosed;
@@ -249,9 +245,6 @@ static void cli_sessionloop() {
/* We've got the transport layer sorted, we now need to request /* We've got the transport layer sorted, we now need to request
* userauth */ * userauth */
send_msg_service_request(SSH_SERVICE_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_auth_getmethods();
cli_ses.state = USERAUTH_REQ_SENT; cli_ses.state = USERAUTH_REQ_SENT;
TRACE(("leave cli_sessionloop: sent userauth methods req")) TRACE(("leave cli_sessionloop: sent userauth methods req"))
@@ -359,11 +352,6 @@ static void cli_session_cleanup(void) {
(void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags); (void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags); (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(); cli_tty_cleanup();
if (cli_ses.server_sig_algs) { if (cli_ses.server_sig_algs) {
buf_free(cli_ses.server_sig_algs); buf_free(cli_ses.server_sig_algs);
@@ -415,75 +403,7 @@ void cleantext(char* dirtytext) {
} }
static void recv_msg_global_request_cli(void) { static void recv_msg_global_request_cli(void) {
unsigned int wantreply = 0; TRACE(("recv_msg_global_request_cli"))
/* Send a proper rejection */
buf_eatstring(ses.payload); send_msg_request_failure();
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);
}

View File

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

View File

@@ -64,6 +64,14 @@ static const struct dropbear_cipher dropbear_aes256 =
static const struct dropbear_cipher dropbear_aes128 = static const struct dropbear_cipher dropbear_aes128 =
{&aes_desc, 16, 16}; {&aes_desc, 16, 16};
#endif #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 #if DROPBEAR_3DES
static const struct dropbear_cipher dropbear_3des = static const struct dropbear_cipher dropbear_3des =
{&des3_desc, 24, 8}; {&des3_desc, 24, 8};
@@ -114,6 +122,10 @@ static const struct dropbear_hash dropbear_sha2_256 =
static const struct dropbear_hash dropbear_sha2_512 = static const struct dropbear_hash dropbear_sha2_512 =
{&sha512_desc, 64, 64}; {&sha512_desc, 64, 64};
#endif #endif
#if DROPBEAR_MD5_HMAC
static const struct dropbear_hash dropbear_md5 =
{&md5_desc, 16, 16};
#endif
const struct dropbear_hash dropbear_nohash = const struct dropbear_hash dropbear_nohash =
{NULL, 16, 0}; /* used initially */ {NULL, 16, 0}; /* used initially */
@@ -144,6 +156,15 @@ algo_type sshciphers[] = {
#if DROPBEAR_AES256 #if DROPBEAR_AES256
{"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr}, {"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
#endif #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 */ #endif /* DROPBEAR_ENABLE_CTR_MODE */
#if DROPBEAR_ENABLE_CBC_MODE #if DROPBEAR_ENABLE_CBC_MODE
@@ -153,6 +174,13 @@ algo_type sshciphers[] = {
#if DROPBEAR_AES256 #if DROPBEAR_AES256
{"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc}, {"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
#endif #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 */ #endif /* DROPBEAR_ENABLE_CBC_MODE */
#if DROPBEAR_3DES #if DROPBEAR_3DES
@@ -181,6 +209,9 @@ algo_type sshhashes[] = {
#endif #endif
#if DROPBEAR_SHA2_512_HMAC #if DROPBEAR_SHA2_512_HMAC
{"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL}, {"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL},
#endif
#if DROPBEAR_MD5_HMAC
{"hmac-md5", 0, (void*)&dropbear_md5, 1, NULL},
#endif #endif
{NULL, 0, NULL, 0, NULL} {NULL, 0, NULL, 0, NULL}
}; };
@@ -208,9 +239,6 @@ algo_type ssh_nocompress[] = {
algo_type sigalgs[] = { algo_type sigalgs[] = {
#if DROPBEAR_ED25519 #if DROPBEAR_ED25519
{"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL}, {"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 #endif
#if DROPBEAR_ECDSA #if DROPBEAR_ECDSA
#if DROPBEAR_ECC_256 #if DROPBEAR_ECC_256
@@ -222,9 +250,6 @@ algo_type sigalgs[] = {
#if DROPBEAR_ECC_521 #if DROPBEAR_ECC_521
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL}, {"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
#endif #endif
#if DROPBEAR_SK_ECDSA
{"sk-ecdsa-sha2-nistp256@openssh.com", DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256, NULL, 1, NULL},
#endif
#endif #endif
#if DROPBEAR_RSA #if DROPBEAR_RSA
#if DROPBEAR_RSA_SHA256 #if DROPBEAR_RSA_SHA256
@@ -334,7 +359,7 @@ void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall
len = buf->pos - startpos - 4; len = buf->pos - startpos - 4;
buf_setpos(buf, startpos); buf_setpos(buf, startpos);
buf_putint(buf, len); 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); buf_incrwritepos(buf, len);
} }
@@ -356,7 +381,7 @@ static void get_algolist(char* algolist, unsigned int algolist_len,
} }
if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) { if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
*ret_count = 0; *ret_count = 0;
} }
/* ret_list will contain a list of the strings parsed out. /* ret_list will contain a list of the strings parsed out.
We will have at least one string (even if it's just "") */ We will have at least one string (even if it's just "") */
@@ -367,11 +392,11 @@ static void get_algolist(char* algolist, unsigned int algolist_len,
/* someone is trying something strange */ /* someone is trying something strange */
*ret_count = 0; *ret_count = 0;
return; return;
} }
if (algolist[i] == ',') { if (algolist[i] == ',') {
if (*ret_count >= max_count) { if (*ret_count >= max_count) {
dropbear_exit("Too many remote algorithms"); /* Too many */
*ret_count = 0; *ret_count = 0;
return; return;
} }
@@ -438,7 +463,7 @@ algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */ /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
algolist = buf_getstring(buf, &len); algolist = buf_getstring(buf, &len);
DEBUG3(("buf_match_algo: %s", algolist)) TRACE(("buf_match_algo: %s", algolist))
remotecount = MAX_PROPOSED_ALGO; remotecount = MAX_PROPOSED_ALGO;
get_algolist(algolist, len, remotenames, &remotecount); get_algolist(algolist, len, remotenames, &remotecount);

View File

@@ -154,6 +154,7 @@ static struct Channel* newchannel(unsigned int remotechan,
newchan->readfd = FD_UNINIT; newchan->readfd = FD_UNINIT;
newchan->errfd = FD_CLOSED; /* this isn't always set to start with */ newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
newchan->await_open = 0; newchan->await_open = 0;
newchan->flushing = 0;
newchan->writebuf = cbuf_new(opts.recv_window); newchan->writebuf = cbuf_new(opts.recv_window);
newchan->recvwindow = opts.recv_window; newchan->recvwindow = opts.recv_window;
@@ -162,7 +163,7 @@ static struct Channel* newchannel(unsigned int remotechan,
newchan->recvdonelen = 0; newchan->recvdonelen = 0;
newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN; newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
newchan->prio = DROPBEAR_PRIO_NORMAL; newchan->prio = DROPBEAR_CHANNEL_PRIO_EARLY; /* inithandler sets it */
ses.channels[i] = newchan; ses.channels[i] = newchan;
ses.chancount++; ses.chancount++;
@@ -283,29 +284,24 @@ static void check_close(struct Channel *channel) {
channel->writebuf ? cbuf_getused(channel->writebuf) : 0, channel->writebuf ? cbuf_getused(channel->writebuf) : 0,
channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
if (!channel->flushing
&& !channel->sent_close
&& channel->type->check_close
&& channel->type->check_close(channel))
{
channel->flushing = 1;
}
/* if a type-specific check_close is defined we will only exit /* if a type-specific check_close is defined we will only exit
once that has been triggered. this is only used for a server "session" once that has been triggered. this is only used for a server "session"
channel, to ensure that the shell has exited (and the exit status channel, to ensure that the shell has exited (and the exit status
retrieved) before we close things up. */ retrieved) before we close things up. */
if (!channel->type->check_close if (!channel->type->check_close
|| channel->sent_close || channel->sent_close
|| channel->type->check_close(channel)) { || channel->type->check_close(channel)) {
close_allowed = 1; close_allowed = 1;
} }
/* In flushing mode we close FDs as soon as pipes are empty.
This is used to drain out FDs when the process exits, in the case
where the FD doesn't have EOF - "sleep 10&echo hello" case */
if (channel->flushing) {
if (channel->readfd >= 0 && !fd_read_pending(channel->readfd)) {
close_chan_fd(channel, channel->readfd, SHUT_RD);
}
if (ERRFD_IS_READ(channel)
&& channel->errfd >= 0 && !fd_read_pending(channel->errfd)) {
close_chan_fd(channel, channel->errfd, SHUT_RD);
}
}
if (channel->recv_close && !write_pending(channel) && close_allowed) { if (channel->recv_close && !write_pending(channel) && close_allowed) {
if (!channel->sent_close) { if (!channel->sent_close) {
TRACE(("Sending MSG_CHANNEL_CLOSE in response to same.")) TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
@@ -321,6 +317,22 @@ static void check_close(struct Channel *channel) {
close_chan_fd(channel, channel->writefd, SHUT_WR); close_chan_fd(channel, channel->writefd, SHUT_WR);
} }
/* Special handling for flushing read data after an exit. We
read regardless of whether the select FD was set,
and if there isn't data available, the channel will get closed. */
if (channel->flushing) {
TRACE(("might send data, flushing"))
if (channel->readfd >= 0 && channel->transwindow > 0) {
TRACE(("send data readfd"))
send_msg_channel_data(channel, 0);
}
if (ERRFD_IS_READ(channel) && channel->errfd >= 0
&& channel->transwindow > 0) {
TRACE(("send data errfd"))
send_msg_channel_data(channel, 1);
}
}
/* If we're not going to send any more data, send EOF */ /* If we're not going to send any more data, send EOF */
if (!channel->sent_eof if (!channel->sent_eof
&& channel->readfd == FD_CLOSED && channel->readfd == FD_CLOSED
@@ -344,7 +356,8 @@ static void check_close(struct Channel *channel) {
* if so, set up the channel properly. Otherwise, the channel is cleaned up, so * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
* it is important that the channel reference isn't used after a call to this * it is important that the channel reference isn't used after a call to this
* function */ * function */
void channel_connect_done(int result, int sock, void* user_data, const char* errstring) { void channel_connect_done(int result, int sock, void* user_data, const char* UNUSED(errstring)) {
struct Channel *channel = user_data; struct Channel *channel = user_data;
TRACE(("enter channel_connect_done")) TRACE(("enter channel_connect_done"))
@@ -352,7 +365,6 @@ void channel_connect_done(int result, int sock, void* user_data, const char* err
if (result == DROPBEAR_SUCCESS) if (result == DROPBEAR_SUCCESS)
{ {
channel->readfd = channel->writefd = sock; channel->readfd = channel->writefd = sock;
channel->bidir_fd = 1;
channel->conn_pending = NULL; channel->conn_pending = NULL;
send_msg_channel_open_confirmation(channel, channel->recvwindow, send_msg_channel_open_confirmation(channel, channel->recvwindow,
channel->recvmaxpacket); channel->recvmaxpacket);
@@ -361,9 +373,9 @@ void channel_connect_done(int result, int sock, void* user_data, const char* err
else else
{ {
send_msg_channel_open_failure(channel->remotechan, send_msg_channel_open_failure(channel->remotechan,
SSH_OPEN_CONNECT_FAILED, errstring, ""); SSH_OPEN_CONNECT_FAILED, "", "");
remove_channel(channel); remove_channel(channel);
TRACE(("leave check_in_progress: fail. internal errstring: %s", errstring)) TRACE(("leave check_in_progress: fail"))
} }
} }
@@ -768,6 +780,14 @@ static void send_msg_channel_data(struct Channel *channel, int isextended) {
channel->transwindow -= len; channel->transwindow -= len;
encrypt_packet(); encrypt_packet();
/* If we receive less data than we requested when flushing, we've
reached the equivalent of EOF */
if (channel->flushing && len < (ssize_t)maxlen)
{
TRACE(("closing from channel, flushing out."))
close_chan_fd(channel, fd, SHUT_RD);
}
TRACE(("leave send_msg_channel_data")) TRACE(("leave send_msg_channel_data"))
} }
@@ -955,7 +975,9 @@ void recv_msg_channel_open() {
} }
} }
update_channel_prio(); if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
}
/* success */ /* success */
send_msg_channel_open_confirmation(channel, channel->recvwindow, send_msg_channel_open_confirmation(channel, channel->recvwindow,
@@ -968,6 +990,8 @@ failure:
cleanup: cleanup:
m_free(type); m_free(type);
update_channel_prio();
TRACE(("leave recv_msg_channel_open")) TRACE(("leave recv_msg_channel_open"))
} }
@@ -1049,7 +1073,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
int closein = 0, closeout = 0; int closein = 0, closeout = 0;
if (channel->bidir_fd) { if (channel->type->sepfds) {
TRACE(("SHUTDOWN(%d, %d)", fd, how)) TRACE(("SHUTDOWN(%d, %d)", fd, how))
shutdown(fd, how); shutdown(fd, how);
if (how == 0) { if (how == 0) {
@@ -1079,7 +1103,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
/* if we called shutdown on it and all references are gone, then we /* if we called shutdown on it and all references are gone, then we
* need to close() it to stop it lingering */ * need to close() it to stop it lingering */
if (channel->bidir_fd && channel->readfd == FD_CLOSED if (channel->type->sepfds && channel->readfd == FD_CLOSED
&& channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) { && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
TRACE(("CLOSE (finally) of %d", fd)) TRACE(("CLOSE (finally) of %d", fd))
m_close(fd); m_close(fd);
@@ -1112,7 +1136,6 @@ int send_msg_channel_open_init(int fd, const struct ChanType *type) {
chan->writefd = chan->readfd = fd; chan->writefd = chan->readfd = fd;
ses.maxfd = MAX(ses.maxfd, fd); ses.maxfd = MAX(ses.maxfd, fd);
chan->bidir_fd = 1;
chan->await_open = 1; chan->await_open = 1;
@@ -1129,7 +1152,7 @@ int send_msg_channel_open_init(int fd, const struct ChanType *type) {
return DROPBEAR_SUCCESS; return DROPBEAR_SUCCESS;
} }
/* Confirmation that our channel open request was /* Confirmation that our channel open request (for forwardings) was
* successful*/ * successful*/
void recv_msg_channel_open_confirmation() { void recv_msg_channel_open_confirmation() {
@@ -1162,8 +1185,11 @@ void recv_msg_channel_open_confirmation() {
} }
} }
if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
}
update_channel_prio(); update_channel_prio();
TRACE(("leave recv_msg_channel_open_confirmation")) TRACE(("leave recv_msg_channel_open_confirmation"))
} }

View File

@@ -249,7 +249,7 @@ static void kexinitialise() {
/* Helper function for gen_new_keys, creates a hash. It makes a copy of the /* Helper function for gen_new_keys, creates a hash. It makes a copy of the
* already initialised hash_state hs, which should already have processed * already initialised hash_state hs, which should already have processed
* the dh_K and hash, since these are common. X is the letter 'A', 'B' etc. * the dh_K and hash, since these are common. X is the letter 'A', 'B' etc.
* out must have at least min(hash_size, outlen) bytes allocated. * out must have at least min(SHA1_HASH_SIZE, outlen) bytes allocated.
* *
* See Section 7.2 of rfc4253 (ssh transport) for details */ * See Section 7.2 of rfc4253 (ssh transport) for details */
static void hashkeys(unsigned char *out, unsigned int outlen, static void hashkeys(unsigned char *out, unsigned int outlen,
@@ -306,7 +306,8 @@ static void gen_new_keys() {
mp_clear(ses.dh_K); mp_clear(ses.dh_K);
m_free(ses.dh_K); m_free(ses.dh_K);
hash_desc->process(&hs, ses.hash->data, ses.hash->len); hash_desc->process(&hs, ses.hash->data, ses.hash->len);
buf_burn_free(ses.hash); buf_burn(ses.hash);
buf_free(ses.hash);
ses.hash = NULL; ses.hash = NULL;
if (IS_DROPBEAR_CLIENT) { if (IS_DROPBEAR_CLIENT) {
@@ -486,12 +487,6 @@ void recv_msg_kexinit() {
TRACE(("continue recv_msg_kexinit: sent kexinit")) TRACE(("continue recv_msg_kexinit: sent kexinit"))
} }
/* "Once a party has sent a SSH_MSG_KEXINIT message ...
further SSH_MSG_KEXINIT messages MUST NOT be sent" */
if (ses.kexstate.recvkexinit) {
dropbear_exit("Unexpected KEXINIT");
}
/* start the kex hash */ /* start the kex hash */
local_ident_len = strlen(LOCAL_IDENT); local_ident_len = strlen(LOCAL_IDENT);
remote_ident_len = strlen(ses.remoteident); remote_ident_len = strlen(ses.remoteident);
@@ -802,7 +797,8 @@ void finish_kexhashbuf(void) {
} }
#endif #endif
buf_burn_free(ses.kexhashbuf); buf_burn(ses.kexhashbuf);
buf_free(ses.kexhashbuf);
m_burn(&hs, sizeof(hash_state)); m_burn(&hs, sizeof(hash_state));
ses.kexhashbuf = NULL; ses.kexhashbuf = NULL;
@@ -867,7 +863,7 @@ static void read_kex_algos() {
goto error; goto error;
} }
TRACE(("kexguess2 %d", kexguess2)) TRACE(("kexguess2 %d", kexguess2))
DEBUG3(("kex algo %s", algo->name)) TRACE(("kex algo %s", algo->name))
ses.newkeys->algo_kex = algo->data; ses.newkeys->algo_kex = algo->data;
/* server_host_key_algorithms */ /* server_host_key_algorithms */
@@ -877,7 +873,7 @@ static void read_kex_algos() {
erralgo = "hostkey"; erralgo = "hostkey";
goto error; goto error;
} }
DEBUG2(("hostkey algo %s", algo->name)) TRACE(("signature algo %s", algo->name))
ses.newkeys->algo_signature = algo->val; ses.newkeys->algo_signature = algo->val;
ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature); ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
@@ -887,7 +883,7 @@ static void read_kex_algos() {
erralgo = "enc c->s"; erralgo = "enc c->s";
goto error; goto error;
} }
DEBUG2(("enc c2s is %s", c2s_cipher_algo->name)) TRACE(("enc c2s is %s", c2s_cipher_algo->name))
/* encryption_algorithms_server_to_client */ /* encryption_algorithms_server_to_client */
s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL); s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL);
@@ -895,7 +891,7 @@ static void read_kex_algos() {
erralgo = "enc s->c"; erralgo = "enc s->c";
goto error; goto error;
} }
DEBUG2(("enc s2c is %s", s2c_cipher_algo->name)) TRACE(("enc s2c is %s", s2c_cipher_algo->name))
/* mac_algorithms_client_to_server */ /* mac_algorithms_client_to_server */
c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL); c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
@@ -908,7 +904,7 @@ static void read_kex_algos() {
erralgo = "mac c->s"; erralgo = "mac c->s";
goto error; goto error;
} }
DEBUG2(("hmac c2s is %s", c2s_hash_algo ? c2s_hash_algo->name : "<implicit>")) TRACE(("hash c2s is %s", c2s_hash_algo ? c2s_hash_algo->name : "<implicit>"))
/* mac_algorithms_server_to_client */ /* mac_algorithms_server_to_client */
s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL); s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
@@ -921,7 +917,7 @@ static void read_kex_algos() {
erralgo = "mac s->c"; erralgo = "mac s->c";
goto error; goto error;
} }
DEBUG2(("hmac s2c is %s", s2c_hash_algo ? s2c_hash_algo->name : "<implicit>")) TRACE(("hash s2c is %s", s2c_hash_algo ? s2c_hash_algo->name : "<implicit>"))
/* compression_algorithms_client_to_server */ /* compression_algorithms_client_to_server */
c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, 0, NULL); c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, 0, NULL);
@@ -929,7 +925,7 @@ static void read_kex_algos() {
erralgo = "comp c->s"; erralgo = "comp c->s";
goto error; goto error;
} }
DEBUG2(("comp c2s is %s", c2s_comp_algo->name)) TRACE(("hash c2s is %s", c2s_comp_algo->name))
/* compression_algorithms_server_to_client */ /* compression_algorithms_server_to_client */
s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, 0, NULL); s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, 0, NULL);
@@ -937,7 +933,7 @@ static void read_kex_algos() {
erralgo = "comp s->c"; erralgo = "comp s->c";
goto error; goto error;
} }
DEBUG2(("comp s2c is %s", s2c_comp_algo->name)) TRACE(("hash s2c is %s", s2c_comp_algo->name))
/* languages_client_to_server */ /* languages_client_to_server */
buf_eatstring(ses.payload); buf_eatstring(ses.payload);

View File

@@ -1,19 +1,19 @@
/* /*
* Dropbear - a SSH2 server * Dropbear - a SSH2 server
* *
* Copyright (c) 2002,2003 Matt Johnston * Copyright (c) 2002,2003 Matt Johnston
* All rights reserved. * All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -35,7 +35,7 @@ runopts opts; /* GLOBAL */
/* returns success or failure, and the keytype in *type. If we want /* returns success or failure, and the keytype in *type. If we want
* to restrict the type, type can contain a type to return */ * to restrict the type, type can contain a type to return */
int readhostkey(const char * filename, sign_key * hostkey, int readhostkey(const char * filename, sign_key * hostkey,
enum signkey_type *type) { enum signkey_type *type) {
int ret = DROPBEAR_FAILURE; int ret = DROPBEAR_FAILURE;
@@ -57,7 +57,8 @@ int readhostkey(const char * filename, sign_key * hostkey,
ret = DROPBEAR_SUCCESS; ret = DROPBEAR_SUCCESS;
out: out:
buf_burn_free(buf); buf_burn(buf);
buf_free(buf);
return ret; return ret;
} }
@@ -100,74 +101,4 @@ void print_version() {
fprintf(stderr, "Dropbear v%s\n", DROPBEAR_VERSION); fprintf(stderr, "Dropbear v%s\n", DROPBEAR_VERSION);
} }
void parse_recv_window(const char* recv_window_arg) {
int ret;
unsigned int rw;
ret = m_str_to_uint(recv_window_arg, &rw);
if (ret == DROPBEAR_FAILURE || rw == 0 || rw > MAX_RECV_WINDOW) {
if (rw > MAX_RECV_WINDOW) {
opts.recv_window = MAX_RECV_WINDOW;
}
dropbear_log(LOG_WARNING, "Bad recv window '%s', using %d",
recv_window_arg, opts.recv_window);
} else {
opts.recv_window = rw;
}
}
/* Splits addr:port. Handles IPv6 [2001:0011::4]:port style format.
Returns first/second parts as malloced strings, second will
be NULL if no separator is found.
:port -> (NULL, "port")
port -> (port, NULL)
addr:port (addr, port)
addr: -> (addr, "")
Returns DROPBEAR_SUCCESS/DROPBEAR_FAILURE */
int split_address_port(const char* spec, char **first, char ** second) {
char *spec_copy = NULL, *addr = NULL, *colon = NULL;
int ret = DROPBEAR_FAILURE;
*first = NULL;
*second = NULL;
spec_copy = m_strdup(spec);
addr = spec_copy;
if (*addr == '[') {
addr++;
colon = strchr(addr, ']');
if (!colon) {
dropbear_log(LOG_WARNING, "Bad address '%s'", spec);
goto out;
}
*colon = '\0';
colon++;
if (*colon == '\0') {
/* No port part */
colon = NULL;
} else if (*colon != ':') {
dropbear_log(LOG_WARNING, "Bad address '%s'", spec);
goto out;
}
} else {
/* search for ':', that separates address and port */
colon = strrchr(addr, ':');
}
/* colon points to ':' now, or is NULL */
if (colon) {
/* Split the address/port */
*colon = '\0';
colon++;
*second = m_strdup(colon);
}
if (strlen(addr)) {
*first = m_strdup(addr);
}
ret = DROPBEAR_SUCCESS;
out:
m_free(spec_copy);
return ret;
}

View File

@@ -64,7 +64,7 @@ void common_session_init(int sock_in, int sock_out) {
setnonblocking(sock_out); setnonblocking(sock_out);
} }
ses.socket_prio = DROPBEAR_PRIO_NORMAL; ses.socket_prio = DROPBEAR_PRIO_DEFAULT;
/* Sets it to lowdelay */ /* Sets it to lowdelay */
update_channel_prio(); update_channel_prio();
@@ -285,7 +285,8 @@ static void cleanup_buf(buffer **buf) {
if (!*buf) { if (!*buf) {
return; return;
} }
buf_burn_free(*buf); buf_burn(*buf);
buf_free(*buf);
*buf = NULL; *buf = NULL;
} }
@@ -403,7 +404,7 @@ static void read_session_identification() {
dropbear_exit("Incompatible remote version '%s'", ses.remoteident); dropbear_exit("Incompatible remote version '%s'", ses.remoteident);
} }
DEBUG1(("remoteident: %s", ses.remoteident)) TRACE(("remoteident: %s", ses.remoteident))
} }
@@ -464,11 +465,6 @@ static int ident_readln(int fd, char* buf, int count) {
TRACE(("leave ident_readln: EOF")) TRACE(("leave ident_readln: EOF"))
return -1; return -1;
} }
#if DROPBEAR_FUZZ
fuzz_dump(&in, 1);
#endif
if (in == '\n') { if (in == '\n') {
/* end of ident string */ /* end of ident string */
break; break;
@@ -519,24 +515,15 @@ static void send_msg_keepalive() {
ses.last_packet_time_idle = old_time_idle; ses.last_packet_time_idle = old_time_idle;
} }
/* Returns the difference in seconds, clamped to LONG_MAX */
static long elapsed(time_t now, time_t prev) {
time_t del = now - prev;
if (del > LONG_MAX) {
return LONG_MAX;
}
return (long)del;
}
/* Check all timeouts which are required. Currently these are the time for /* Check all timeouts which are required. Currently these are the time for
* user authentication, and the automatic rekeying. */ * user authentication, and the automatic rekeying. */
static void checktimeouts() { static void checktimeouts() {
time_t now; time_t now;
now = monotonic_now(); now = monotonic_now();
if (IS_DROPBEAR_SERVER && ses.connect_time != 0 if (IS_DROPBEAR_SERVER && ses.connect_time != 0
&& elapsed(now, ses.connect_time) >= AUTH_TIMEOUT) { && now - ses.connect_time >= AUTH_TIMEOUT) {
dropbear_close("Timeout before auth"); dropbear_close("Timeout before auth");
} }
@@ -546,47 +533,45 @@ static void checktimeouts() {
} }
if (!ses.kexstate.sentkexinit if (!ses.kexstate.sentkexinit
&& (elapsed(now, ses.kexstate.lastkextime) >= KEX_REKEY_TIMEOUT && (now - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) { || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
TRACE(("rekeying after timeout or max data reached")) TRACE(("rekeying after timeout or max data reached"))
send_msg_kexinit(); send_msg_kexinit();
} }
if (opts.keepalive_secs > 0 && ses.authstate.authdone) { if (opts.keepalive_secs > 0 && ses.authstate.authdone) {
/* Avoid sending keepalives prior to auth - those are /* Avoid sending keepalives prior to auth - those are
not valid pre-auth packet types */ not valid pre-auth packet types */
/* Send keepalives if we've been idle */ /* Send keepalives if we've been idle */
if (elapsed(now, ses.last_packet_time_any_sent) >= opts.keepalive_secs) { if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) {
send_msg_keepalive(); send_msg_keepalive();
} }
/* Also send an explicit keepalive message to trigger a response /* Also send an explicit keepalive message to trigger a response
if the remote end hasn't sent us anything */ if the remote end hasn't sent us anything */
if (elapsed(now, ses.last_packet_time_keepalive_recv) >= opts.keepalive_secs if (now - ses.last_packet_time_keepalive_recv >= opts.keepalive_secs
&& elapsed(now, ses.last_packet_time_keepalive_sent) >= opts.keepalive_secs) { && now - ses.last_packet_time_keepalive_sent >= opts.keepalive_secs) {
send_msg_keepalive(); send_msg_keepalive();
} }
if (elapsed(now, ses.last_packet_time_keepalive_recv) if (now - ses.last_packet_time_keepalive_recv
>= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) { >= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) {
dropbear_exit("Keepalive timeout"); dropbear_exit("Keepalive timeout");
} }
} }
if (opts.idle_timeout_secs > 0 if (opts.idle_timeout_secs > 0
&& elapsed(now, ses.last_packet_time_idle) >= opts.idle_timeout_secs) { && now - ses.last_packet_time_idle >= opts.idle_timeout_secs) {
dropbear_close("Idle timeout"); dropbear_close("Idle timeout");
} }
} }
static void update_timeout(long limit, time_t now, time_t last_event, long * timeout) { static void update_timeout(long limit, long now, long last_event, long * timeout) {
TRACE2(("update_timeout limit %ld, now %llu, last %llu, timeout %ld", TRACE2(("update_timeout limit %ld, now %ld, last %ld, timeout %ld",
limit, limit, now, last_event, *timeout))
(unsigned long long)now,
(unsigned long long)last_event, *timeout))
if (last_event > 0 && limit > 0) { if (last_event > 0 && limit > 0) {
*timeout = MIN(*timeout, elapsed(now, last_event) + limit); *timeout = MIN(*timeout, last_event+limit-now);
TRACE2(("new timeout %ld", *timeout)) TRACE2(("new timeout %ld", *timeout))
} }
} }
@@ -595,7 +580,7 @@ static long select_timeout() {
/* determine the minimum timeout that might be required, so /* determine the minimum timeout that might be required, so
as to avoid waking when unneccessary */ as to avoid waking when unneccessary */
long timeout = KEX_REKEY_TIMEOUT; long timeout = KEX_REKEY_TIMEOUT;
time_t now = monotonic_now(); long now = monotonic_now();
if (!ses.kexstate.sentkexinit) { if (!ses.kexstate.sentkexinit) {
update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout); update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout);
@@ -607,7 +592,7 @@ static long select_timeout() {
} }
if (ses.authstate.authdone) { if (ses.authstate.authdone) {
update_timeout(opts.keepalive_secs, now, update_timeout(opts.keepalive_secs, now,
MAX(ses.last_packet_time_keepalive_recv, ses.last_packet_time_keepalive_sent), MAX(ses.last_packet_time_keepalive_recv, ses.last_packet_time_keepalive_sent),
&timeout); &timeout);
} }
@@ -677,16 +662,26 @@ void update_channel_prio() {
return; return;
} }
new_prio = DROPBEAR_PRIO_NORMAL; new_prio = DROPBEAR_PRIO_BULK;
for (i = 0; i < ses.chansize; i++) { for (i = 0; i < ses.chansize; i++) {
struct Channel *channel = ses.channels[i]; struct Channel *channel = ses.channels[i];
if (!channel) { if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
TRACE(("update_channel_prio: early %d", channel->index))
}
continue; continue;
} }
any = 1; any = 1;
if (channel->prio == DROPBEAR_PRIO_LOWDELAY) { if (channel->prio == DROPBEAR_CHANNEL_PRIO_INTERACTIVE)
{
TRACE(("update_channel_prio: lowdelay %d", channel->index))
new_prio = DROPBEAR_PRIO_LOWDELAY; new_prio = DROPBEAR_PRIO_LOWDELAY;
break; break;
} else if (channel->prio == DROPBEAR_CHANNEL_PRIO_UNKNOWABLE
&& new_prio == DROPBEAR_PRIO_BULK)
{
TRACE(("update_channel_prio: unknowable %d", channel->index))
new_prio = DROPBEAR_PRIO_DEFAULT;
} }
} }

View File

@@ -231,7 +231,8 @@ void setusershell() {
} }
static char **initshells() { static char **initshells() {
static const char *okshells[] = { COMPAT_USER_SHELLS, NULL }; /* don't touch this list. */
static const char *okshells[] = { "/bin/sh", "/bin/csh", NULL };
register char **sp, *cp; register char **sp, *cp;
register FILE *fp; register FILE *fp;
struct stat statb; struct stat statb;

1293
config.guess vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,456 +0,0 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Using AIX */
#undef AIX
/* Broken getaddrinfo */
#undef BROKEN_GETADDRINFO
/* Use bundled libtom */
#undef BUNDLED_LIBTOM
/* lastlog file location */
#undef CONF_LASTLOG_FILE
/* utmpx file location */
#undef CONF_UTMPX_FILE
/* utmp file location */
#undef CONF_UTMP_FILE
/* wtmpx file location */
#undef CONF_WTMPX_FILE
/* wtmp file location */
#undef CONF_WTMP_FILE
/* Disable use of lastlog() */
#undef DISABLE_LASTLOG
/* Use PAM */
#undef DISABLE_PAM
/* Disable use of pututline() */
#undef DISABLE_PUTUTLINE
/* Disable use of pututxline() */
#undef DISABLE_PUTUTXLINE
/* Using syslog */
#undef DISABLE_SYSLOG
/* Disable use of utmp */
#undef DISABLE_UTMP
/* Disable use of utmpx */
#undef DISABLE_UTMPX
/* Disable use of wtmp */
#undef DISABLE_WTMP
/* Disable use of wtmpx */
#undef DISABLE_WTMPX
/* Use zlib */
#undef DISABLE_ZLIB
/* Fuzzing */
#undef DROPBEAR_FUZZ
/* External Public Key Authentication */
#undef DROPBEAR_PLUGIN
/* Define to 1 if you have the `basename' function. */
#undef HAVE_BASENAME
/* Define to 1 if you have the `clearenv' function. */
#undef HAVE_CLEARENV
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* Define if gai_strerror() returns const char * */
#undef HAVE_CONST_GAI_STRERROR_PROTO
/* crypt() function */
#undef HAVE_CRYPT
/* Define to 1 if you have the <crypt.h> header file. */
#undef HAVE_CRYPT_H
/* Define to 1 if you have the `daemon' function. */
#undef HAVE_DAEMON
/* Use /dev/ptc & /dev/pts */
#undef HAVE_DEV_PTS_AND_PTC
/* Define to 1 if you have the `endutent' function. */
#undef HAVE_ENDUTENT
/* Define to 1 if you have the `endutxent' function. */
#undef HAVE_ENDUTXENT
/* Define to 1 if you have the `explicit_bzero' function. */
#undef HAVE_EXPLICIT_BZERO
/* Define to 1 if you have the `fexecve' function. */
#undef HAVE_FEXECVE
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
/* Define to 1 if you have the `freeaddrinfo' function. */
#undef HAVE_FREEADDRINFO
/* Define to 1 if you have the `gai_strerror' function. */
#undef HAVE_GAI_STRERROR
/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO
/* Define to 1 if you have the `getgrouplist' function. */
#undef HAVE_GETGROUPLIST
/* Define to 1 if you have the `getnameinfo' function. */
#undef HAVE_GETNAMEINFO
/* Define to 1 if you have the `getpass' function. */
#undef HAVE_GETPASS
/* Define to 1 if you have the `getrandom' function. */
#undef HAVE_GETRANDOM
/* Define to 1 if you have the `getspnam' function. */
#undef HAVE_GETSPNAM
/* Define to 1 if you have the `getusershell' function. */
#undef HAVE_GETUSERSHELL
/* Define to 1 if you have the `getutent' function. */
#undef HAVE_GETUTENT
/* Define to 1 if you have the `getutid' function. */
#undef HAVE_GETUTID
/* Define to 1 if you have the `getutline' function. */
#undef HAVE_GETUTLINE
/* Define to 1 if you have the `getutxent' function. */
#undef HAVE_GETUTXENT
/* Define to 1 if you have the `getutxid' function. */
#undef HAVE_GETUTXID
/* Define to 1 if you have the `getutxline' function. */
#undef HAVE_GETUTXLINE
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <lastlog.h> header file. */
#undef HAVE_LASTLOG_H
/* Define to 1 if you have the <libgen.h> header file. */
#undef HAVE_LIBGEN_H
/* Define to 1 if you have the `pam' library (-lpam). */
#undef HAVE_LIBPAM
/* Define to 1 if you have the <libutil.h> header file. */
#undef HAVE_LIBUTIL_H
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if you have the <linux/pkt_sched.h> header file. */
#undef HAVE_LINUX_PKT_SCHED_H
/* Have login() function */
#undef HAVE_LOGIN
/* Define to 1 if you have the `logout' function. */
#undef HAVE_LOGOUT
/* Define to 1 if you have the `logwtmp' function. */
#undef HAVE_LOGWTMP
/* Define to 1 if you have the `mach_absolute_time' function. */
#undef HAVE_MACH_ABSOLUTE_TIME
/* Define to 1 if you have the <mach/mach_time.h> header file. */
#undef HAVE_MACH_MACH_TIME_H
/* Define to 1 if you have the `memset_s' function. */
#undef HAVE_MEMSET_S
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the <netinet/in_systm.h> header file. */
#undef HAVE_NETINET_IN_SYSTM_H
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#undef HAVE_NETINET_TCP_H
/* Have openpty() function */
#undef HAVE_OPENPTY
/* Define to 1 if you have the `pam_fail_delay' function. */
#undef HAVE_PAM_FAIL_DELAY
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
#undef HAVE_PAM_PAM_APPL_H
/* Define to 1 if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
/* Define to 1 if you have the <pty.h> header file. */
#undef HAVE_PTY_H
/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
/* Define to 1 if you have the `pututline' function. */
#undef HAVE_PUTUTLINE
/* Define to 1 if you have the `pututxline' function. */
#undef HAVE_PUTUTXLINE
/* Define to 1 if you have the <security/pam_appl.h> header file. */
#undef HAVE_SECURITY_PAM_APPL_H
/* Define to 1 if you have the `setutent' function. */
#undef HAVE_SETUTENT
/* Define to 1 if you have the `setutxent' function. */
#undef HAVE_SETUTXENT
/* Define to 1 if you have the <shadow.h> header file. */
#undef HAVE_SHADOW_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlcat' function. */
#undef HAVE_STRLCAT
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
/* Define to 1 if you have the <stropts.h> header file. */
#undef HAVE_STROPTS_H
/* Have struct addrinfo */
#undef HAVE_STRUCT_ADDRINFO
/* Have struct in6_addr */
#undef HAVE_STRUCT_IN6_ADDR
/* Have struct sockaddr_in6 */
#undef HAVE_STRUCT_SOCKADDR_IN6
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
#undef HAVE_STRUCT_SOCKADDR_STORAGE
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
/* Define to 1 if `ut_addr' is a member of `struct utmpx'. */
#undef HAVE_STRUCT_UTMPX_UT_ADDR
/* Define to 1 if `ut_addr_v6' is a member of `struct utmpx'. */
#undef HAVE_STRUCT_UTMPX_UT_ADDR_V6
/* Define to 1 if `ut_host' is a member of `struct utmpx'. */
#undef HAVE_STRUCT_UTMPX_UT_HOST
/* Define to 1 if `ut_id' is a member of `struct utmpx'. */
#undef HAVE_STRUCT_UTMPX_UT_ID
/* Define to 1 if `ut_syslen' is a member of `struct utmpx'. */
#undef HAVE_STRUCT_UTMPX_UT_SYSLEN
/* Define to 1 if `ut_time' is a member of `struct utmpx'. */
#undef HAVE_STRUCT_UTMPX_UT_TIME
/* Define to 1 if `ut_tv' is a member of `struct utmpx'. */
#undef HAVE_STRUCT_UTMPX_UT_TV
/* Define to 1 if `ut_type' is a member of `struct utmpx'. */
#undef HAVE_STRUCT_UTMPX_UT_TYPE
/* Define to 1 if `ut_addr' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_ADDR
/* Define to 1 if `ut_addr_v6' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_ADDR_V6
/* Define to 1 if `ut_exit' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_EXIT
/* Define to 1 if `ut_host' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_HOST
/* Define to 1 if `ut_id' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_ID
/* Define to 1 if `ut_pid' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_PID
/* Define to 1 if `ut_time' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_TIME
/* Define to 1 if `ut_tv' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_TV
/* Define to 1 if `ut_type' is a member of `struct utmp'. */
#undef HAVE_STRUCT_UTMP_UT_TYPE
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
/* Define to 1 if you have the <sys/random.h> header file. */
#undef HAVE_SYS_RANDOM_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if the system has the type `uint16_t'. */
#undef HAVE_UINT16_T
/* Define to 1 if the system has the type `uint32_t'. */
#undef HAVE_UINT32_T
/* Define to 1 if the system has the type `uint8_t'. */
#undef HAVE_UINT8_T
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `updwtmp' function. */
#undef HAVE_UPDWTMP
/* Define to 1 if you have the <util.h> header file. */
#undef HAVE_UTIL_H
/* Define to 1 if you have the `utmpname' function. */
#undef HAVE_UTMPNAME
/* Define to 1 if you have the `utmpxname' function. */
#undef HAVE_UTMPXNAME
/* Define to 1 if you have the <utmpx.h> header file. */
#undef HAVE_UTMPX_H
/* Define to 1 if you have the <utmp.h> header file. */
#undef HAVE_UTMP_H
/* Define to 1 if the system has the type `u_int16_t'. */
#undef HAVE_U_INT16_T
/* Define to 1 if the system has the type `u_int32_t'. */
#undef HAVE_U_INT32_T
/* Define to 1 if the system has the type `u_int8_t'. */
#undef HAVE_U_INT8_T
/* Define to 1 if you have the `writev' function. */
#undef HAVE_WRITEV
/* Define to 1 if you have the `_getpty' function. */
#undef HAVE__GETPTY
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to the type of arg 1 for `select'. */
#undef SELECT_TYPE_ARG1
/* Define to the type of args 2, 3 and 4 for `select'. */
#undef SELECT_TYPE_ARG234
/* Define to the type of arg 5 for `select'. */
#undef SELECT_TYPE_ARG5
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* Use /dev/ptmx */
#undef USE_DEV_PTMX
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Use GNU extensions if glibc */
#undef _GNU_SOURCE
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t
/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* type to use in place of socklen_t if not defined */
#undef socklen_t
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t

1062
config.sub vendored

File diff suppressed because it is too large Load Diff

10004
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
# of the platform checks have been taken straight from OpenSSH's configure.ac # of the platform checks have been taken straight from OpenSSH's configure.ac
# Huge thanks to them for dealing with the horrible platform-specifics :) # Huge thanks to them for dealing with the horrible platform-specifics :)
AC_PREREQ([2.59]) AC_PREREQ(2.59)
AC_INIT AC_INIT
AC_CONFIG_SRCDIR(buffer.c) AC_CONFIG_SRCDIR(buffer.c)
@@ -16,22 +16,21 @@ if test -s "`which hg`" && test -d "$srcdir/.hg"; then
fi fi
ORIGCFLAGS="$CFLAGS" ORIGCFLAGS="$CFLAGS"
LATE_CFLAGS=""
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
if test -z "$LD" ; then if test -z "$LD" ; then
LD=$CC LD=$CC
fi fi
AC_SUBST(LD) AC_SUBST(LD)
AC_DEFUN(DB_TRYADDCFLAGS, AC_DEFUN(DB_TRYADDCFLAGS,
[{ [{
OLDFLAGS="$CFLAGS" OLDFLAGS="$CFLAGS"
TESTFLAGS="$1" TESTFLAGS="$1"
CFLAGS="$TESTFLAGS $CFLAGS" CFLAGS="$CFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])], [AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDFLAGS" ] [AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDFLAGS" ]
) )
}]) }])
@@ -42,28 +41,12 @@ if test -z "$ORIGCFLAGS" && test "$GCC" = "yes"; then
CFLAGS="-Os -W -Wall" CFLAGS="-Os -W -Wall"
fi 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]) AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wno-pointer-sign])
DB_TRYADDCFLAGS([-Wno-pointer-sign]) DB_TRYADDCFLAGS([-Wno-pointer-sign])
AC_MSG_NOTICE([Checking if compiler '$CC' supports -fno-strict-overflow]) AC_MSG_NOTICE([Checking if compiler '$CC' supports -fno-strict-overflow])
DB_TRYADDCFLAGS([-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 STATIC=0
AC_ARG_ENABLE(static, AC_ARG_ENABLE(static,
[ --enable-static Build static binaries], [ --enable-static Build static binaries],
@@ -94,15 +77,15 @@ if test "$hardenbuild" -eq 1; then
OLDLDFLAGS="$LDFLAGS" OLDLDFLAGS="$LDFLAGS"
TESTFLAGS="-Wl,-pie" TESTFLAGS="-Wl,-pie"
LDFLAGS="$TESTFLAGS $LDFLAGS" LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])], AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])], [AC_MSG_NOTICE([Setting $TESTFLAGS])],
[ [
LDFLAGS="$OLDLDFLAGS" LDFLAGS="$OLDLDFLAGS"
TESTFLAGS="-pie" TESTFLAGS="-pie"
LDFLAGS="$TESTFLAGS $LDFLAGS" LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])], AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])], [AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ] [AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
) )
] ]
@@ -110,24 +93,24 @@ if test "$hardenbuild" -eq 1; then
# readonly elf relocation sections (relro) # readonly elf relocation sections (relro)
OLDLDFLAGS="$LDFLAGS" OLDLDFLAGS="$LDFLAGS"
TESTFLAGS="-Wl,-z,now -Wl,-z,relro" TESTFLAGS="-Wl,-z,now -Wl,-z,relro"
LDFLAGS="$TESTFLAGS $LDFLAGS" LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])], AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])], [AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ] [AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
) )
fi # non-static fi # non-static
# stack protector. -strong is good but only in gcc 4.9 or later # stack protector. -strong is good but only in gcc 4.9 or later
OLDCFLAGS="$CFLAGS" OLDCFLAGS="$CFLAGS"
TESTFLAGS="-fstack-protector-strong" TESTFLAGS="-fstack-protector-strong"
CFLAGS="$TESTFLAGS $CFLAGS" CFLAGS="$CFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])], [AC_MSG_NOTICE([Setting $TESTFLAGS])],
[ [
CFLAGS="$OLDCFLAGS" CFLAGS="$OLDCFLAGS"
TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4" TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4"
CFLAGS="$TESTFLAGS $CFLAGS" CFLAGS="$CFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])], [AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDCFLAGS" ] [AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDCFLAGS" ]
) )
] ]
@@ -141,17 +124,6 @@ if test "$hardenbuild" -eq 1; then
fi 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 # large file support is useful for scp
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
@@ -187,7 +159,7 @@ case "$host" in
# OpenSSH thinks it's broken. If it isn't, let me know. # OpenSSH thinks it's broken. If it isn't, let me know.
AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo) AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
;; ;;
*-*-hpux*) *-*-hpux*)
LIBS="$LIBS -lsec" LIBS="$LIBS -lsec"
# It's probably broken. # It's probably broken.
@@ -204,7 +176,7 @@ AC_CHECK_TOOL(STRIP, strip, :)
AC_CHECK_TOOL(INSTALL, install, :) AC_CHECK_TOOL(INSTALL, install, :)
dnl Can't use login() or logout() with uclibc dnl Can't use login() or logout() with uclibc
AC_CHECK_DECL(__UCLIBC__, AC_CHECK_DECL(__UCLIBC__,
[ [
no_loginfunc_check=1 no_loginfunc_check=1
AC_MSG_NOTICE([Using uClibc - login() and logout() probably don't work, so we won't use them.]) AC_MSG_NOTICE([Using uClibc - login() and logout() probably don't work, so we won't use them.])
@@ -212,14 +184,14 @@ AC_CHECK_DECL(__UCLIBC__,
dnl We test for crypt() specially. On Linux (and others?) it resides in libcrypt 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 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_FUNC(crypt, found_crypt_func=here)
AC_CHECK_LIB(crypt, crypt, AC_CHECK_LIB(crypt, crypt,
[ [
CRYPTLIB="-lcrypt" CRYPTLIB="-lcrypt"
found_crypt_func=here found_crypt_func=here
]) ])
AC_SUBST(CRYPTLIB) AC_SUBST(CRYPTLIB)
if test "t$found_crypt_func" = there; then if test "t$found_crypt_func" = there; then
AC_DEFINE(HAVE_CRYPT, 1, [crypt() function]) AC_DEFINE(HAVE_CRYPT, 1, [crypt() function])
fi fi
@@ -375,7 +347,6 @@ AC_ARG_ENABLE(fuzz,
DROPBEAR_FUZZ=1 DROPBEAR_FUZZ=1
# libfuzzer needs linking with c++ libraries # libfuzzer needs linking with c++ libraries
AC_PROG_CXX AC_PROG_CXX
mkdir -pv fuzz
else else
AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing) AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing)
AC_MSG_NOTICE(Disabling fuzzing) AC_MSG_NOTICE(Disabling fuzzing)
@@ -393,13 +364,14 @@ AC_SUBST(DROPBEAR_FUZZ)
AC_SUBST(CXX) AC_SUBST(CXX)
# Checks for header files. # Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \ AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \
crypt.h \ crypt.h \
pty.h libutil.h libgen.h inttypes.h stropts.h utmp.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 \ 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 \ pam/pam_appl.h netinet/in_systm.h sys/uio.h linux/pkt_sched.h \
sys/random.h sys/prctl.h]) sys/random.h])
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST AC_C_CONST
@@ -407,6 +379,7 @@ AC_TYPE_UID_T
AC_TYPE_MODE_T AC_TYPE_MODE_T
AC_TYPE_PID_T AC_TYPE_PID_T
AC_TYPE_SIZE_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([uint8_t, u_int8_t, uint16_t, u_int16_t, uint32_t, u_int32_t])
AC_CHECK_TYPES([struct sockaddr_storage]) AC_CHECK_TYPES([struct sockaddr_storage])
@@ -581,7 +554,7 @@ AC_ARG_ENABLE(bundled-libtom,
) )
if test $BUNDLED_LIBTOM = 1 ; then if test $BUNDLED_LIBTOM = 1 ; then
AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom) AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom)
fi fi
AC_SUBST(LIBTOM_LIBS) AC_SUBST(LIBTOM_LIBS)
@@ -654,7 +627,7 @@ AC_ARG_ENABLE(pututxline,
AC_ARG_WITH(lastlog, AC_ARG_WITH(lastlog,
[ --with-lastlog=FILE|DIR specify lastlog location [common locations]], [ --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) AC_DEFINE(DISABLE_LASTLOG)
else else
conf_lastlog_location=$withval conf_lastlog_location=$withval
@@ -729,7 +702,7 @@ fi
if test -n "$conf_lastlog_location"; then if test -n "$conf_lastlog_location"; then
AC_DEFINE_UNQUOTED(CONF_LASTLOG_FILE, "$conf_lastlog_location", lastlog file location) AC_DEFINE_UNQUOTED(CONF_LASTLOG_FILE, "$conf_lastlog_location", lastlog file location)
fi fi
dnl utmp detection dnl utmp detection
AC_MSG_CHECKING([if your system defines UTMP_FILE]) AC_MSG_CHECKING([if your system defines UTMP_FILE])
@@ -759,7 +732,7 @@ if test -z "$conf_utmp_location"; then
fi fi
if test -n "$conf_utmp_location"; then if test -n "$conf_utmp_location"; then
AC_DEFINE_UNQUOTED(CONF_UTMP_FILE, "$conf_utmp_location", utmp file location) AC_DEFINE_UNQUOTED(CONF_UTMP_FILE, "$conf_utmp_location", utmp file location)
fi fi
dnl wtmp detection dnl wtmp detection
AC_MSG_CHECKING([if your system defines WTMP_FILE]) AC_MSG_CHECKING([if your system defines WTMP_FILE])
@@ -791,7 +764,7 @@ if test -z "$conf_wtmp_location"; then
fi fi
if test -n "$conf_wtmp_location"; then if test -n "$conf_wtmp_location"; then
AC_DEFINE_UNQUOTED(CONF_WTMP_FILE, "$conf_wtmp_location", wtmp file location) 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 dnl utmpx detection - I don't know any system so perverse as to require
@@ -819,7 +792,7 @@ if test -z "$conf_utmpx_location"; then
fi fi
else else
AC_DEFINE_UNQUOTED(CONF_UTMPX_FILE, "$conf_utmpx_location", utmpx file location) AC_DEFINE_UNQUOTED(CONF_UTMPX_FILE, "$conf_utmpx_location", utmpx file location)
fi fi
dnl wtmpx detection dnl wtmpx detection
AC_MSG_CHECKING([if your system defines WTMPX_FILE]) AC_MSG_CHECKING([if your system defines WTMPX_FILE])
@@ -846,7 +819,7 @@ if test -z "$conf_wtmpx_location"; then
fi fi
else else
AC_DEFINE_UNQUOTED(CONF_WTMPX_FILE, "$conf_wtmpx_location", wtmpx file location) AC_DEFINE_UNQUOTED(CONF_WTMPX_FILE, "$conf_wtmpx_location", wtmpx file location)
fi fi
# Checks for library functions. # Checks for library functions.
AC_PROG_GCC_TRADITIONAL AC_PROG_GCC_TRADITIONAL
@@ -854,7 +827,7 @@ AC_FUNC_MEMCMP
AC_FUNC_SELECT_ARGTYPES AC_FUNC_SELECT_ARGTYPES
AC_CHECK_FUNCS([getpass getspnam getusershell putenv]) AC_CHECK_FUNCS([getpass getspnam getusershell putenv])
AC_CHECK_FUNCS([clearenv strlcpy strlcat daemon basename _getpty getaddrinfo ]) AC_CHECK_FUNCS([clearenv strlcpy strlcat daemon basename _getpty getaddrinfo ])
AC_CHECK_FUNCS([freeaddrinfo getnameinfo fork writev getgrouplist fexecve]) AC_CHECK_FUNCS([freeaddrinfo getnameinfo fork writev getgrouplist])
AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME)) AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
@@ -882,15 +855,12 @@ fi
AC_EXEEXT AC_EXEEXT
if test $BUNDLED_LIBTOM = 1 ; then 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" LIBTOM_FILES="libtomcrypt/Makefile libtommath/Makefile"
fi fi
# flags that should be set in Makefile but not for configure tests AC_CONFIG_HEADER(config.h)
CFLAGS="$CFLAGS $LATE_CFLAGS" AC_CONFIG_FILES(Makefile $LIBTOM_FILES)
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES(Makefile $LIBTOM_FILES test/Makefile)
AC_OUTPUT AC_OUTPUT
AC_MSG_NOTICE() AC_MSG_NOTICE()

View File

@@ -3,18 +3,11 @@
#include "crypto_desc.h" #include "crypto_desc.h"
#include "ltc_prng.h" #include "ltc_prng.h"
#include "ecc.h" #include "ecc.h"
#include "dbrandom.h"
#if DROPBEAR_LTC_PRNG #if DROPBEAR_LTC_PRNG
int dropbear_ltc_prng = -1; int dropbear_ltc_prng = -1;
#endif #endif
/* Wrapper for libtommath */
static mp_err dropbear_rand_source(void* out, size_t size) {
genrandom((unsigned char*)out, (unsigned int)size);
return MP_OKAY;
}
/* Register the compiled in ciphers. /* Register the compiled in ciphers.
* This should be run before using any of the ciphers/hashes */ * This should be run before using any of the ciphers/hashes */
@@ -24,6 +17,12 @@ void crypto_init() {
#if DROPBEAR_AES #if DROPBEAR_AES
&aes_desc, &aes_desc,
#endif #endif
#if DROPBEAR_BLOWFISH
&blowfish_desc,
#endif
#if DROPBEAR_TWOFISH
&twofish_desc,
#endif
#if DROPBEAR_3DES #if DROPBEAR_3DES
&des3_desc, &des3_desc,
#endif #endif
@@ -31,8 +30,10 @@ void crypto_init() {
}; };
const struct ltc_hash_descriptor *reghashes[] = { const struct ltc_hash_descriptor *reghashes[] = {
#if DROPBEAR_SHA1_HMAC /* we need sha1 for hostkey stuff regardless */
&sha1_desc, &sha1_desc,
#if DROPBEAR_MD5_HMAC
&md5_desc,
#endif #endif
#if DROPBEAR_SHA256 #if DROPBEAR_SHA256
&sha256_desc, &sha256_desc,
@@ -44,9 +45,9 @@ void crypto_init() {
&sha512_desc, &sha512_desc,
#endif #endif
NULL NULL
}; };
int i; int i;
for (i = 0; regciphers[i] != NULL; i++) { for (i = 0; regciphers[i] != NULL; i++) {
if (register_cipher(regciphers[i]) == -1) { if (register_cipher(regciphers[i]) == -1) {
dropbear_exit("Error registering crypto"); dropbear_exit("Error registering crypto");
@@ -66,8 +67,6 @@ void crypto_init() {
} }
#endif #endif
mp_rand_source(dropbear_rand_source);
#if DROPBEAR_ECC #if DROPBEAR_ECC
ltc_mp = ltm_desc; ltc_mp = ltm_desc;
dropbear_ecc_fill_dp(); dropbear_ecc_fill_dp();

View File

@@ -19,7 +19,7 @@ dbclient \- lightweight SSH client
.SH DESCRIPTION .SH DESCRIPTION
.B dbclient .B dbclient
is the client part of Dropbear SSH is a small SSH client
.SH OPTIONS .SH OPTIONS
.TP .TP
.TP .TP
@@ -44,27 +44,27 @@ from OpenSSH with dropbearconvert(1). The default path ~/.ssh/id_dropbear is use
.TP .TP
.B \-L\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR .B \-L\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
Local port forwarding. Local port forwarding.
Forward Forward the port
.I listenport .I listenport
on the local host through the SSH connection to on the local host through the SSH connection to port
.I port .I port
on on the host
.IR host . .IR host .
.TP .TP
.B \-R\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR .B \-R\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
Remote port forwarding. Remote port forwarding.
Forward Forward the port
.I listenport .I listenport
on the remote host through the SSH connection to on the remote host through the SSH connection to port
.I port .I port
on on the host
.IR host . .IR host .
.TP .TP
.B \-l \fIuser .B \-l \fIuser
Username. Username.
Login as Login as
.I user .I user
on the remote host. An alternative is to specify user@host. on the remote host.
.TP .TP
.B \-t .B \-t
Allocate a PTY. This is the default when no command is given, it gives a full Allocate a PTY. This is the default when no command is given, it gives a full
@@ -72,7 +72,7 @@ interactive remote session. The main effect is that keystrokes are sent remotely
immediately as opposed to local line-based editing. immediately as opposed to local line-based editing.
.TP .TP
.B \-T .B \-T
Don't allocate a PTY. This is the default when a command is given. See -t. Don't allocate a PTY. This is the default a command is given. See -t.
.TP .TP
.B \-N .B \-N
Don't request a remote shell or run any commands. Any command arguments are ignored. Don't request a remote shell or run any commands. Any command arguments are ignored.
@@ -94,18 +94,7 @@ is performed at all, this is usually undesirable.
.B \-A .B \-A
Forward agent connections to the remote host. dbclient will use any Forward agent connections to the remote host. dbclient will use any
OpenSSH-style agent program if available ($SSH_AUTH_SOCK will be set) for OpenSSH-style agent program if available ($SSH_AUTH_SOCK will be set) for
public key authentication. Forwarding is only enabled if \fI-A\fR is specified. public key authentication. Forwarding is only enabled if -A 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 .TP
.B \-W \fIwindowsize .B \-W \fIwindowsize
Specify the per-channel receive window buffer size. Increasing this Specify the per-channel receive window buffer size. Increasing this
@@ -122,9 +111,6 @@ if 0 disables keepalives. If no response is received for 3 consecutive keepalive
.B \-I \fIidle_timeout .B \-I \fIidle_timeout
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds. Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
.TP .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? .\" TODO: how to avoid a line break between these two -J arguments?
.B \-J \fIproxy_command .B \-J \fIproxy_command
@@ -163,20 +149,10 @@ The following options have currently been implemented:
.RS .RS
.TP .TP
.B ExitOnForwardFailure .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 is no.
.TP .TP
.B UseSyslog .B UseSyslog
Send dbclient log messages to syslog in addition to stderr. Send dbclient log messages to syslog in addition to stderr.
.TP
.B Port
Specify a listening port, like the \fI-p\fR argument.
.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.
.RE .RE
.TP .TP
.B \-s .B \-s

View File

@@ -1,9 +1,9 @@
#ifndef DBMALLOC_H_ #ifndef DBMALLOC_H_
#define DBMALLOC_H_ #define DBMALLOC_H_
#include "stdint.h"
#include "stdlib.h"
#include "options.h" #include "options.h"
#include <stdint.h>
#include <stdlib.h>
void * m_malloc(size_t size); void * m_malloc(size_t size);
void * m_calloc(size_t nmemb, size_t size); void * m_calloc(size_t nmemb, size_t size);

View File

@@ -23,15 +23,20 @@
* SOFTWARE. */ * SOFTWARE. */
#include "includes.h" #include "includes.h"
#include "dbutil.h"
static int runprog(const char *multipath, /* definitions are cleanest if we just put them here */
const char *progname, int argc, char ** argv, int *match) { int dropbear_main(int argc, char ** argv);
int cli_main(int argc, char ** argv);
int dropbearkey_main(int argc, char ** argv);
int dropbearconvert_main(int argc, char ** argv);
int scp_main(int argc, char ** argv);
static int runprog(const char *progname, int argc, char ** argv, int *match) {
*match = DROPBEAR_SUCCESS; *match = DROPBEAR_SUCCESS;
#ifdef DBMULTI_dropbear #ifdef DBMULTI_dropbear
if (strcmp(progname, "dropbear") == 0) { if (strcmp(progname, "dropbear") == 0) {
return dropbear_main(argc, argv, multipath); return dropbear_main(argc, argv);
} }
#endif #endif
#ifdef DBMULTI_dbclient #ifdef DBMULTI_dbclient
@@ -62,16 +67,12 @@ static int runprog(const char *multipath,
int main(int argc, char ** argv) { int main(int argc, char ** argv) {
int i; int i;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
const char* multipath = NULL;
if (i == 1) {
multipath = argv[0];
}
/* Try symlink first, then try as an argument eg "dropbearmulti dbclient host ..." */ /* Try symlink first, then try as an argument eg "dropbearmulti dbclient host ..." */
if (argc > i) { if (argc > i) {
int match, res; int match, res;
/* figure which form we're being called as */ /* figure which form we're being called as */
const char* progname = basename(argv[i]); const char* progname = basename(argv[i]);
res = runprog(multipath, progname, argc-i, &argv[i], &match); res = runprog(progname, argc-i, &argv[i], &match);
if (match == DROPBEAR_SUCCESS) { if (match == DROPBEAR_SUCCESS) {
return res; return res;
} }

View File

@@ -34,7 +34,7 @@ static uint32_t counter = 0;
/* the max value for the counter, so it won't integer overflow */ /* the max value for the counter, so it won't integer overflow */
#define MAX_COUNTER (1<<30) #define MAX_COUNTER (1<<30)
static unsigned char hashpool[SHA256_HASH_SIZE] = {0}; static unsigned char hashpool[SHA1_HASH_SIZE] = {0};
static int donerandinit = 0; static int donerandinit = 0;
#define INIT_SEED_SIZE 32 /* 256 bits */ #define INIT_SEED_SIZE 32 /* 256 bits */
@@ -100,7 +100,7 @@ process_file(hash_state *hs, const char *filename,
} }
goto out; goto out;
} }
sha256_process(hs, readbuf, readlen); sha1_process(hs, readbuf, readlen);
readcount += readlen; readcount += readlen;
} }
ret = DROPBEAR_SUCCESS; ret = DROPBEAR_SUCCESS;
@@ -120,13 +120,13 @@ void addrandom(const unsigned char * buf, unsigned int len)
#endif #endif
/* hash in the new seed data */ /* hash in the new seed data */
sha256_init(&hs); sha1_init(&hs);
/* existing state (zeroes on startup) */ /* existing state (zeroes on startup) */
sha256_process(&hs, (void*)hashpool, sizeof(hashpool)); sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
/* new */ /* new */
sha256_process(&hs, buf, len); sha1_process(&hs, buf, len);
sha256_done(&hs, hashpool); sha1_done(&hs, hashpool);
} }
static void write_urandom() static void write_urandom()
@@ -150,12 +150,12 @@ static void write_urandom()
} }
#if DROPBEAR_FUZZ #if DROPBEAR_FUZZ
void fuzz_seed(const unsigned char* dat, unsigned int len) { void fuzz_seed(void) {
hash_state hs; hash_state hs;
sha256_init(&hs); sha1_init(&hs);
sha256_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz")); sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
sha256_process(&hs, dat, len); sha1_done(&hs, hashpool);
sha256_done(&hs, hashpool);
counter = 0; counter = 0;
donerandinit = 1; donerandinit = 1;
} }
@@ -209,7 +209,7 @@ static int process_getrandom(hash_state *hs) {
if (ret == sizeof(buf)) { if (ret == sizeof(buf)) {
/* Success, stir in the entropy */ /* Success, stir in the entropy */
sha256_process(hs, (void*)buf, sizeof(buf)); sha1_process(hs, (void*)buf, sizeof(buf));
return DROPBEAR_SUCCESS; return DROPBEAR_SUCCESS;
} }
@@ -221,6 +221,7 @@ static int process_getrandom(hash_state *hs) {
/* Initialise the prng from /dev/urandom or prngd. This function can /* Initialise the prng from /dev/urandom or prngd. This function can
* be called multiple times */ * be called multiple times */
void seedrandom() { void seedrandom() {
hash_state hs; hash_state hs;
pid_t pid; pid_t pid;
@@ -235,10 +236,10 @@ void seedrandom() {
#endif #endif
/* hash in the new seed data */ /* hash in the new seed data */
sha256_init(&hs); sha1_init(&hs);
/* existing state */ /* existing state */
sha256_process(&hs, (void*)hashpool, sizeof(hashpool)); sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
#ifdef HAVE_GETRANDOM #ifdef HAVE_GETRANDOM
if (process_getrandom(&hs) == DROPBEAR_SUCCESS) { if (process_getrandom(&hs) == DROPBEAR_SUCCESS) {
@@ -288,21 +289,21 @@ void seedrandom() {
#endif #endif
pid = getpid(); pid = getpid();
sha256_process(&hs, (void*)&pid, sizeof(pid)); sha1_process(&hs, (void*)&pid, sizeof(pid));
/* gettimeofday() doesn't completely fill out struct timeval on /* gettimeofday() doesn't completely fill out struct timeval on
OS X (10.8.3), avoid valgrind warnings by clearing it first */ OS X (10.8.3), avoid valgrind warnings by clearing it first */
memset(&tv, 0x0, sizeof(tv)); memset(&tv, 0x0, sizeof(tv));
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
sha256_process(&hs, (void*)&tv, sizeof(tv)); sha1_process(&hs, (void*)&tv, sizeof(tv));
clockval = clock(); clockval = clock();
sha256_process(&hs, (void*)&clockval, sizeof(clockval)); sha1_process(&hs, (void*)&clockval, sizeof(clockval));
/* When a private key is read by the client or server it will /* When a private key is read by the client or server it will
* be added to the hashpool - see runopts.c */ * be added to the hashpool - see runopts.c */
sha256_done(&hs, hashpool); sha1_done(&hs, hashpool);
counter = 0; counter = 0;
donerandinit = 1; donerandinit = 1;
@@ -316,7 +317,7 @@ void seedrandom() {
void genrandom(unsigned char* buf, unsigned int len) { void genrandom(unsigned char* buf, unsigned int len) {
hash_state hs; hash_state hs;
unsigned char hash[SHA256_HASH_SIZE]; unsigned char hash[SHA1_HASH_SIZE];
unsigned int copylen; unsigned int copylen;
if (!donerandinit) { if (!donerandinit) {
@@ -324,17 +325,17 @@ void genrandom(unsigned char* buf, unsigned int len) {
} }
while (len > 0) { while (len > 0) {
sha256_init(&hs); sha1_init(&hs);
sha256_process(&hs, (void*)hashpool, sizeof(hashpool)); sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
sha256_process(&hs, (void*)&counter, sizeof(counter)); sha1_process(&hs, (void*)&counter, sizeof(counter));
sha256_done(&hs, hash); sha1_done(&hs, hash);
counter++; counter++;
if (counter > MAX_COUNTER) { if (counter > MAX_COUNTER) {
seedrandom(); seedrandom();
} }
copylen = MIN(len, SHA256_HASH_SIZE); copylen = MIN(len, SHA1_HASH_SIZE);
memcpy(buf, hash, copylen); memcpy(buf, hash, copylen);
len -= copylen; len -= copylen;
buf += copylen; buf += copylen;
@@ -347,7 +348,7 @@ void genrandom(unsigned char* buf, unsigned int len) {
* rand must be an initialised *mp_int for the result. * rand must be an initialised *mp_int for the result.
* the result rand satisfies: 0 < rand < max * the result rand satisfies: 0 < rand < max
* */ * */
void gen_random_mpint(const mp_int *max, mp_int *rand) { void gen_random_mpint(mp_int *max, mp_int *rand) {
unsigned char *randbuf = NULL; unsigned char *randbuf = NULL;
unsigned int len = 0; unsigned int len = 0;

View File

@@ -30,6 +30,6 @@
void seedrandom(void); void seedrandom(void);
void genrandom(unsigned char* buf, unsigned int len); void genrandom(unsigned char* buf, unsigned int len);
void addrandom(const unsigned char * buf, unsigned int len); void addrandom(const unsigned char * buf, unsigned int len);
void gen_random_mpint(const mp_int *max, mp_int *rand); void gen_random_mpint(mp_int *max, mp_int *rand);
#endif /* DROPBEAR_RANDOM_H_ */ #endif /* DROPBEAR_RANDOM_H_ */

186
dbutil.c
View File

@@ -121,6 +121,7 @@ static void generic_dropbear_exit(int exitcode, const char* format,
_dropbear_log(LOG_INFO, fmtbuf, param); _dropbear_log(LOG_INFO, fmtbuf, param);
#if DROPBEAR_FUZZ #if DROPBEAR_FUZZ
/* longjmp before cleaning up svr_opts */
if (fuzz.do_jmp) { if (fuzz.do_jmp) {
longjmp(fuzz.jmp, 1); longjmp(fuzz.jmp, 1);
} }
@@ -155,7 +156,7 @@ void dropbear_log(int priority, const char* format, ...) {
} }
#if DEBUG_TRACE #if DEBUG_TRACE
static double debug_start_time = -1; static double debug_start_time = -1;
@@ -185,63 +186,39 @@ static double time_since_start()
return nowf - debug_start_time; return nowf - debug_start_time;
} }
static void dropbear_tracelevel(int level, const char *format, va_list param) void dropbear_trace(const char* format, ...) {
{ va_list param;
if (debug_trace == 0 || debug_trace < level) {
if (!debug_trace) {
return; return;
} }
fprintf(stderr, "TRACE%d (%d) %f: ", level, getpid(), time_since_start()); va_start(param, format);
fprintf(stderr, "TRACE (%d) %f: ", getpid(), time_since_start());
vfprintf(stderr, format, param); vfprintf(stderr, format, param);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
}
#if (DEBUG_TRACE>=1)
void dropbear_trace1(const char* format, ...) {
va_list param;
va_start(param, format);
dropbear_tracelevel(1, format, param);
va_end(param); va_end(param);
} }
#endif
#if (DEBUG_TRACE>=2)
void dropbear_trace2(const char* format, ...) { void dropbear_trace2(const char* format, ...) {
static int trace_env = -1;
va_list param; va_list param;
va_start(param, format); if (trace_env == -1) {
dropbear_tracelevel(2, format, param); trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0;
va_end(param); }
}
#endif if (!(debug_trace && trace_env)) {
#if (DEBUG_TRACE>=3) return;
void dropbear_trace3(const char* format, ...) { }
va_list param;
va_start(param, format); va_start(param, format);
dropbear_tracelevel(3, format, param); fprintf(stderr, "TRACE2 (%d) %f: ", getpid(), time_since_start());
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param); va_end(param);
} }
#endif #endif /* DEBUG_TRACE */
#if (DEBUG_TRACE>=4)
void dropbear_trace4(const char* format, ...) {
va_list param;
va_start(param, format);
dropbear_tracelevel(4, format, param);
va_end(param);
}
#endif
#if (DEBUG_TRACE>=5)
void dropbear_trace5(const char* format, ...) {
va_list param;
va_start(param, format);
dropbear_tracelevel(5, format, param);
va_end(param);
}
#endif
#endif
/* Connect to a given unix socket. The socket is blocking */ /* Connect to a given unix socket. The socket is blocking */
#if ENABLE_CONNECT_UNIX #if ENABLE_CONNECT_UNIX
@@ -281,12 +258,6 @@ int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
const int FDIN = 0; const int FDIN = 0;
const int FDOUT = 1; const int FDOUT = 1;
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
return fuzz_spawn_command(ret_writefd, ret_readfd, ret_errfd, ret_pid);
}
#endif
/* redirect stdin/stdout/stderr */ /* redirect stdin/stdout/stderr */
if (pipe(infds) != 0) { if (pipe(infds) != 0) {
return DROPBEAR_FAILURE; return DROPBEAR_FAILURE;
@@ -409,40 +380,23 @@ void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
#if DEBUG_TRACE #if DEBUG_TRACE
void printhex(const char * label, const unsigned char * buf, int len) { void printhex(const char * label, const unsigned char * buf, int len) {
int i, j;
int i;
fprintf(stderr, "%s\n", label); fprintf(stderr, "%s\n", label);
/* for each 16 byte line */ for (i = 0; i < len; i++) {
for (j = 0; j < len; j += 16) { fprintf(stderr, "%02x", buf[i]);
const int linelen = MIN(16, len - j); if (i % 16 == 15) {
fprintf(stderr, "\n");
/* print hex digits */
for (i = 0; i < 16; i++) {
if (i < linelen) {
fprintf(stderr, "%02x", buf[j+i]);
} else {
fprintf(stderr, " ");
}
// separator between pairs
if (i % 2 ==1) {
fprintf(stderr, " ");
}
} }
else if (i % 2 == 1) {
/* print characters */ fprintf(stderr, " ");
fprintf(stderr, " ");
for (i = 0; i < linelen; i++) {
char c = buf[j+i];
if (!isprint(c)) {
c = '.';
}
fputc(c, stderr);
} }
fprintf(stderr, "\n");
} }
fprintf(stderr, "\n");
} }
void printmpint(const char *label, const mp_int *mp) { void printmpint(const char *label, mp_int *mp) {
buffer *buf = buf_new(1000); buffer *buf = buf_new(1000);
buf_putmpint(buf, mp); buf_putmpint(buf, mp);
fprintf(stderr, "%d bits ", mp_count_bits(mp)); fprintf(stderr, "%d bits ", mp_count_bits(mp));
@@ -599,28 +553,16 @@ void setnonblocking(int fd) {
} }
void disallow_core() { void disallow_core() {
struct rlimit lim = {0}; struct rlimit lim;
if (getrlimit(RLIMIT_CORE, &lim) < 0) { lim.rlim_cur = lim.rlim_max = 0;
TRACE(("getrlimit(RLIMIT_CORE) failed")); setrlimit(RLIMIT_CORE, &lim);
}
lim.rlim_cur = 0;
if (setrlimit(RLIMIT_CORE, &lim) < 0) {
TRACE(("setrlimit(RLIMIT_CORE) failed"));
}
} }
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */ /* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */
int m_str_to_uint(const char* str, unsigned int *val) { int m_str_to_uint(const char* str, unsigned int *val) {
unsigned long l; unsigned long l;
char *endp; errno = 0;
l = strtoul(str, NULL, 10);
l = strtoul(str, &endp, 10);
if (endp == str || *endp != '\0') {
/* parse error */
return DROPBEAR_FAILURE;
}
/* The c99 spec doesn't actually seem to define EINVAL, but most platforms /* The c99 spec doesn't actually seem to define EINVAL, but most platforms
* I've looked at mention it in their manpage */ * I've looked at mention it in their manpage */
if ((l == 0 && errno == EINVAL) if ((l == 0 && errno == EINVAL)
@@ -633,24 +575,16 @@ int m_str_to_uint(const char* str, unsigned int *val) {
} }
} }
/* Returns malloced path. inpath beginning with '~/' expanded, /* Returns malloced path. inpath beginning with '/' is returned as-is,
otherwise returned as-is */ otherwise home directory is prepended */
char * expand_homedir_path(const char *inpath) { char * expand_homedir_path(const char *inpath) {
struct passwd *pw = NULL; struct passwd *pw = NULL;
if (strncmp(inpath, "~/", 2) == 0) { if (inpath[0] != '/') {
char *homedir = getenv("HOME"); pw = getpwuid(getuid());
if (pw && pw->pw_dir) {
if (!homedir) { int len = strlen(inpath) + strlen(pw->pw_dir) + 2;
pw = getpwuid(getuid());
if (pw) {
homedir = pw->pw_dir;
}
}
if (homedir) {
int len = strlen(inpath)-2 + strlen(homedir) + 2;
char *buf = m_malloc(len); char *buf = m_malloc(len);
snprintf(buf, len, "%s/%s", homedir, inpath+2); snprintf(buf, len, "%s/%s", pw->pw_dir, inpath);
return buf; return buf;
} }
} }
@@ -724,7 +658,7 @@ void gettime_wrapper(struct timespec *now) {
/* Fallback for everything else - this will sometimes go backwards */ /* Fallback for everything else - this will sometimes go backwards */
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
now->tv_sec = tv.tv_sec; now->tv_sec = tv.tv_sec;
now->tv_nsec = 1000*(long)tv.tv_usec; now->tv_nsec = 1000*tv.tv_usec;
} }
/* second-resolution monotonic timestamp */ /* second-resolution monotonic timestamp */
@@ -752,35 +686,3 @@ void fsync_parent_dir(const char* fn) {
m_free(fn_dir); m_free(fn_dir);
#endif #endif
} }
int fd_read_pending(int fd) {
fd_set fds;
struct timeval timeout;
DROPBEAR_FD_ZERO(&fds);
FD_SET(fd, &fds);
while (1) {
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if (select(fd+1, &fds, NULL, NULL, &timeout) < 0) {
if (errno == EINTR) {
continue;
}
return 0;
}
return FD_ISSET(fd, &fds);
}
}
int m_snprintf(char *str, size_t size, const char *format, ...) {
va_list param;
int ret;
va_start(param, format);
ret = vsnprintf(str, size, format, param);
va_end(param);
if (ret < 0) {
dropbear_exit("snprintf failed");
}
return ret;
}

View File

@@ -47,13 +47,10 @@ void dropbear_log(int priority, const char* format, ...) ATTRIB_PRINTF(2,3) ;
void fail_assert(const char* expr, const char* file, int line) ATTRIB_NORETURN; void fail_assert(const char* expr, const char* file, int line) ATTRIB_NORETURN;
#if DEBUG_TRACE #if DEBUG_TRACE
void dropbear_trace1(const char* format, ...) ATTRIB_PRINTF(1,2); void dropbear_trace(const char* format, ...) ATTRIB_PRINTF(1,2);
void dropbear_trace2(const char* format, ...) ATTRIB_PRINTF(1,2); void dropbear_trace2(const char* format, ...) ATTRIB_PRINTF(1,2);
void dropbear_trace3(const char* format, ...) ATTRIB_PRINTF(1,2);
void dropbear_trace4(const char* format, ...) ATTRIB_PRINTF(1,2);
void dropbear_trace5(const char* format, ...) ATTRIB_PRINTF(1,2);
void printhex(const char * label, const unsigned char * buf, int len); void printhex(const char * label, const unsigned char * buf, int len);
void printmpint(const char *label, const mp_int *mp); void printmpint(const char *label, mp_int *mp);
void debug_start_net(void); void debug_start_net(void);
extern int debug_trace; extern int debug_trace;
#endif #endif
@@ -73,8 +70,6 @@ void m_close(int fd);
void setnonblocking(int fd); void setnonblocking(int fd);
void disallow_core(void); void disallow_core(void);
int m_str_to_uint(const char* str, unsigned int *val); int m_str_to_uint(const char* str, unsigned int *val);
/* The same as snprintf() but exits rather than returning negative */
int m_snprintf(char *str, size_t size, const char *format, ...);
/* Used to force mp_ints to be initialised */ /* Used to force mp_ints to be initialised */
#define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL} #define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
@@ -95,8 +90,6 @@ char * expand_homedir_path(const char *inpath);
void fsync_parent_dir(const char* fn); void fsync_parent_dir(const char* fn);
int fd_read_pending(int fd);
#if DROPBEAR_MSAN #if DROPBEAR_MSAN
/* FD_ZERO seems to leave some memory uninitialized. clear it to avoid false positives */ /* FD_ZERO seems to leave some memory uninitialized. clear it to avoid false positives */
#define DROPBEAR_FD_ZERO(fds) do { memset((fds), 0x0, sizeof(fd_set)); FD_ZERO(fds); } while(0) #define DROPBEAR_FD_ZERO(fds) do { memset((fds), 0x0, sizeof(fd_set)); FD_ZERO(fds); } while(0)
@@ -104,12 +97,4 @@ int fd_read_pending(int fd);
#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds) #define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
#endif #endif
/* dropbearmulti entry points */
int dropbear_main(int argc, char ** argv, const char * multipath);
int cli_main(int argc, char ** argv);
int dropbearkey_main(int argc, char ** argv);
int dropbearconvert_main(int argc, char ** argv);
int scp_main(int argc, char ** argv);
#endif /* DROPBEAR_DBUTIL_H_ */ #endif /* DROPBEAR_DBUTIL_H_ */

24
debian/changelog vendored
View File

@@ -1,27 +1,3 @@
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.
-- Matt Johnston <matt@ucc.asn.au> Fri, 26 Jun 2020 22:51:57 +0800
dropbear (2020.79-0.1) unstable; urgency=low dropbear (2020.79-0.1) unstable; urgency=low
* New upstream release. * New upstream release.

View File

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

38
debug.h
View File

@@ -48,43 +48,15 @@
/*#define DEBUG_KEXHASH*/ /*#define DEBUG_KEXHASH*/
/*#define DEBUG_RSA*/ /*#define DEBUG_RSA*/
/* The level of TRACE() statements */ /* you don't need to touch this block */
#define DROPBEAR_VERBOSE_LEVEL 4
#if DEBUG_TRACE #if DEBUG_TRACE
extern int debug_trace; extern int debug_trace;
#endif #define TRACE(X) dropbear_trace X;
#define TRACE2(X) dropbear_trace2 X;
/* Enable debug trace levels. #else /*DEBUG_TRACE*/
We can't use __VA_ARGS_ here because Dropbear supports
old ~C89 compilers */
/* Default is to discard output ... */
#define DEBUG1(X)
#define DEBUG2(X)
#define DEBUG3(X)
#define TRACE(X) #define TRACE(X)
#define TRACE2(X) #define TRACE2(X)
/* ... unless DEBUG_TRACE is high enough */ #endif /*DEBUG_TRACE*/
#if (DEBUG_TRACE>=1)
#undef DEBUG1
#define DEBUG1(X) dropbear_trace1 X;
#endif
#if (DEBUG_TRACE>=2)
#undef DEBUG2
#define DEBUG2(X) dropbear_trace2 X;
#endif
#if (DEBUG_TRACE>=3)
#undef DEBUG3
#define DEBUG3(X) dropbear_trace3 X;
#endif
#if (DEBUG_TRACE>=4)
#undef TRACE
#define TRACE(X) dropbear_trace4 X;
#endif
#if (DEBUG_TRACE>=5)
#undef TRACE2
#define TRACE2(X) dropbear_trace5 X;
#endif
/* To debug with GDB it is easier to run with no forking of child processes. /* To debug with GDB it is easier to run with no forking of child processes.
You will need to pass "-F" as well. */ You will need to pass "-F" as well. */

View File

@@ -6,7 +6,7 @@
default_options.h documents compile-time options, and provides default values. default_options.h documents compile-time options, and provides default values.
Local customisation should be added to localoptions.h which is Local customisation should be added to localoptions.h which is
used if it exists in the build directory. Options defined there will override used if it exists in the build directory. Options defined there will override
any options in this file. any options in this file.
Options can also be defined with -DDROPBEAR_XXX=[0,1] in Makefile CFLAGS Options can also be defined with -DDROPBEAR_XXX=[0,1] in Makefile CFLAGS
@@ -18,9 +18,7 @@ IMPORTANT: Some options will require "make clean" after changes */
/* Listen on all interfaces */ /* Listen on all interfaces */
#define DROPBEAR_DEFADDRESS "" #define DROPBEAR_DEFADDRESS ""
/* Default hostkey paths - these can be specified on the command line. /* Default hostkey paths - these can be specified on the command line */
* Homedir is prepended if path begins with ~/
*/
#define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key" #define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key"
#define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_host_key" #define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_host_key"
#define ECDSA_PRIV_FILENAME "/etc/dropbear/dropbear_ecdsa_host_key" #define ECDSA_PRIV_FILENAME "/etc/dropbear/dropbear_ecdsa_host_key"
@@ -39,18 +37,8 @@ IMPORTANT: Some options will require "make clean" after changes */
#define NON_INETD_MODE 1 #define NON_INETD_MODE 1
#define INETD_MODE 1 #define INETD_MODE 1
/* By default Dropbear will re-execute itself for each incoming connection so /* Include verbose debug output, enabled with -v at runtime.
that memory layout may be re-randomised (ASLR) - exploiting * This will add a reasonable amount to your executable size. */
vulnerabilities becomes harder. Re-exec causes slightly more memory use
per connection.
This option is ignored on non-Linux platforms at present */
#define DROPBEAR_REEXEC 1
/* Include verbose debug output, enabled with -v at runtime (repeat to increase).
* define which level of debug output you compile in
* TRACE1 - TRACE3 = approx 4 Kb (connection, remote identity, algos, auth type info)
* TRACE4 = approx 17 Kb (detailed before connection)
* TRACE5 = approx 8 Kb (detailed after connection) */
#define DEBUG_TRACE 0 #define DEBUG_TRACE 0
/* Set this if you want to use the DROPBEAR_SMALL_CODE option. This can save /* Set this if you want to use the DROPBEAR_SMALL_CODE option. This can save
@@ -78,7 +66,7 @@ IMPORTANT: Some options will require "make clean" after changes */
/* Note: Both DROPBEAR_CLI_PROXYCMD and DROPBEAR_CLI_NETCAT must be set to /* Note: Both DROPBEAR_CLI_PROXYCMD and DROPBEAR_CLI_NETCAT must be set to
* allow multihop dbclient connections */ * allow multihop dbclient connections */
/* Allow using -J <proxycommand> to run the connection through a /* Allow using -J <proxycommand> to run the connection through a
pipe to a program, rather the normal TCP connection */ pipe to a program, rather the normal TCP connection */
#define DROPBEAR_CLI_PROXYCMD 1 #define DROPBEAR_CLI_PROXYCMD 1
@@ -92,11 +80,13 @@ IMPORTANT: Some options will require "make clean" after changes */
/* Encryption - at least one required. /* Encryption - at least one required.
* AES128 should be enabled, some very old implementations might only * AES128 should be enabled, some very old implementations might only
* support 3DES. * support 3DES.
* Including both AES keysize variants (128 and 256) will result in * Including both AES keysize variants (128 and 256) will result in
* a minimal size increase */ * a minimal size increase */
#define DROPBEAR_AES128 1 #define DROPBEAR_AES128 1
#define DROPBEAR_AES256 1 #define DROPBEAR_AES256 1
#define DROPBEAR_3DES 0 #define DROPBEAR_3DES 0
#define DROPBEAR_TWOFISH256 0
#define DROPBEAR_TWOFISH128 0
/* Enable Chacha20-Poly1305 authenticated encryption mode. This is /* Enable Chacha20-Poly1305 authenticated encryption mode. This is
* generally faster than AES256 on CPU w/o dedicated AES instructions, * generally faster than AES256 on CPU w/o dedicated AES instructions,
@@ -118,48 +108,28 @@ IMPORTANT: Some options will require "make clean" after changes */
* Compiling in will add ~6kB to binary size on x86-64 */ * Compiling in will add ~6kB to binary size on x86-64 */
#define DROPBEAR_ENABLE_GCM_MODE 0 #define DROPBEAR_ENABLE_GCM_MODE 0
/* Message integrity. sha2-256 is recommended as a default, /* Message integrity. sha2-256 is recommended as a default,
sha1 for compatibility */ sha1 for compatibility */
#define DROPBEAR_SHA1_HMAC 1 #define DROPBEAR_SHA1_HMAC 1
#define DROPBEAR_SHA2_256_HMAC 1 #define DROPBEAR_SHA2_256_HMAC 1
#define DROPBEAR_SHA2_512_HMAC 0
#define DROPBEAR_SHA1_96_HMAC 0 #define DROPBEAR_SHA1_96_HMAC 0
/* Hostkey/public key algorithms - at least one required, these are used /* Hostkey/public key algorithms - at least one required, these are used
* for hostkey as well as for verifying signatures with pubkey auth. * for hostkey as well as for verifying signatures with pubkey auth.
* RSA is recommended. * Removing either of these won't save very much space.
* * RSA is recommended
* See: RSA_PRIV_FILENAME and DSS_PRIV_FILENAME */ * DSS may be necessary to connect to some systems though
is not recommended for new keys */
#define DROPBEAR_RSA 1 #define DROPBEAR_RSA 1
/* Newer SSH implementations use SHA256 for RSA signatures. SHA1 #define DROPBEAR_DSS 1
* support is required to communicate with some older implementations.
* It will be removed in future due to SHA1 insecurity, it can be
* disabled with DROPBEAR_RSA_SHA1 set to 0 */
#define DROPBEAR_RSA_SHA1 1
/* DSS may be necessary to connect to some systems but is not
* recommended for new keys (1024 bits is small, and it uses SHA1).
* RSA key generation will be faster with bundled libtommath
* if DROPBEAR_DSS is disabled.
* https://github.com/mkj/dropbear/issues/174#issuecomment-1267374858 */
#define DROPBEAR_DSS 0
/* ECDSA is significantly faster than RSA or DSS. Compiling in ECC /* ECDSA is significantly faster than RSA or DSS. Compiling in ECC
* code (either ECDSA or ECDH) increases binary size - around 30kB * code (either ECDSA or ECDH) increases binary size - around 30kB
* on x86-64. * on x86-64 */
* See: ECDSA_PRIV_FILENAME */
#define DROPBEAR_ECDSA 1 #define DROPBEAR_ECDSA 1
/* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases /* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases
* binary size - around 7,5kB on x86-64. binary size - around 7,5kB on x86-64 */
* See: ED25519_PRIV_FILENAME */
#define DROPBEAR_ED25519 1 #define DROPBEAR_ED25519 1
/* Allow U2F security keys for public key auth, with
* sk-ecdsa-sha2-nistp256@openssh.com or sk-ssh-ed25519@openssh.com keys.
* The corresponding DROPBEAR_ECDSA or DROPBEAR_ED25519 also needs to be set.
* This is currently server-only. */
#define DROPBEAR_SK_KEYS 1
/* RSA must be >=1024 */ /* RSA must be >=1024 */
#define DROPBEAR_DEFAULT_RSA_SIZE 2048 #define DROPBEAR_DEFAULT_RSA_SIZE 2048
/* DSS is always 1024 */ /* DSS is always 1024 */
@@ -192,13 +162,13 @@ IMPORTANT: Some options will require "make clean" after changes */
* Small systems should generally include either curve25519 or ecdh for performance. * Small systems should generally include either curve25519 or ecdh for performance.
* curve25519 is less widely supported but is faster * curve25519 is less widely supported but is faster
*/ */
#define DROPBEAR_DH_GROUP14_SHA1 1 #define DROPBEAR_DH_GROUP14_SHA1 1
#define DROPBEAR_DH_GROUP14_SHA256 1 #define DROPBEAR_DH_GROUP14_SHA256 1
#define DROPBEAR_DH_GROUP16 0 #define DROPBEAR_DH_GROUP16 0
#define DROPBEAR_CURVE25519 1 #define DROPBEAR_CURVE25519 1
#define DROPBEAR_ECDH 1 #define DROPBEAR_ECDH 1
#define DROPBEAR_DH_GROUP1 0 #define DROPBEAR_DH_GROUP1 1
/* When group1 is enabled it will only be allowed by Dropbear client /* When group1 is enabled it will only be allowed by Dropbear client
not as a server, due to concerns over its strength. Set to 0 to allow not as a server, due to concerns over its strength. Set to 0 to allow
@@ -233,8 +203,7 @@ group1 in Dropbear server too */
* You can't enable both PASSWORD and PAM. */ * You can't enable both PASSWORD and PAM. */
#define DROPBEAR_SVR_PAM_AUTH 0 #define DROPBEAR_SVR_PAM_AUTH 0
/* ~/.ssh/authorized_keys authentication. /* ~/.ssh/authorized_keys authentication */
* You must define DROPBEAR_SVR_PUBKEY_AUTH in order to use plugins. */
#define DROPBEAR_SVR_PUBKEY_AUTH 1 #define DROPBEAR_SVR_PUBKEY_AUTH 1
/* Whether to take public key options in /* Whether to take public key options in
@@ -250,10 +219,9 @@ group1 in Dropbear server too */
#define DROPBEAR_CLI_PASSWORD_AUTH 1 #define DROPBEAR_CLI_PASSWORD_AUTH 1
#define DROPBEAR_CLI_PUBKEY_AUTH 1 #define DROPBEAR_CLI_PUBKEY_AUTH 1
/* A default argument for dbclient -i <privatekey>. /* A default argument for dbclient -i <privatekey>.
* Homedir is prepended if path begins with ~/ Homedir is prepended unless path begins with / */
*/ #define DROPBEAR_DEFAULT_CLI_AUTHKEY ".ssh/id_dropbear"
#define DROPBEAR_DEFAULT_CLI_AUTHKEY "~/.ssh/id_dropbear"
/* Allow specifying the password for dbclient via the DROPBEAR_PASSWORD /* Allow specifying the password for dbclient via the DROPBEAR_PASSWORD
* environment variable. */ * environment variable. */
@@ -288,16 +256,8 @@ group1 in Dropbear server too */
/* -T server option overrides */ /* -T server option overrides */
#define MAX_AUTH_TRIES 10 #define MAX_AUTH_TRIES 10
/* Delay introduced before closing an unauthenticated session (seconds).
Disabled by default, can be set to say 30 seconds to reduce the speed
of password brute forcing. Note that there is a risk of denial of
service by setting this */
#define UNAUTH_CLOSE_DELAY 0
/* The default file to store the daemon's process ID, for shutdown /* The default file to store the daemon's process ID, for shutdown
* scripts etc. This can be overridden with the -P flag. scripts etc. This can be overridden with the -P flag */
* Homedir is prepended if path begins with ~/
*/
#define DROPBEAR_PIDFILE "/var/run/dropbear.pid" #define DROPBEAR_PIDFILE "/var/run/dropbear.pid"
/* The command to invoke for xauth when using X11 forwarding. /* The command to invoke for xauth when using X11 forwarding.
@@ -305,11 +265,9 @@ group1 in Dropbear server too */
#define XAUTH_COMMAND "/usr/bin/xauth -q" #define XAUTH_COMMAND "/usr/bin/xauth -q"
/* If you want to enable running an sftp server (such as the one included with /* if you want to enable running an sftp server (such as the one included with
* OpenSSH), set the path below and set DROPBEAR_SFTPSERVER. * OpenSSH), set the path below and set DROPBEAR_SFTPSERVER.
* The sftp-server program is not provided by Dropbear itself. * The sftp-server program is not provided by Dropbear itself */
* Homedir is prepended if path begins with ~/
*/
#define DROPBEAR_SFTPSERVER 1 #define DROPBEAR_SFTPSERVER 1
#define SFTPSERVER_PATH "/usr/libexec/sftp-server" #define SFTPSERVER_PATH "/usr/libexec/sftp-server"
@@ -352,6 +310,5 @@ be overridden at runtime with -I. 0 disables idle timeouts */
/* The default path. This will often get replaced by the shell */ /* The default path. This will often get replaced by the shell */
#define DEFAULT_PATH "/usr/bin:/bin" #define DEFAULT_PATH "/usr/bin:/bin"
#define DEFAULT_ROOT_PATH "/usr/sbin:/usr/bin:/sbin:/bin"
#endif /* DROPBEAR_DEFAULT_OPTIONS_H_ */ #endif /* DROPBEAR_DEFAULT_OPTIONS_H_ */

View File

@@ -35,12 +35,6 @@ Don't fork into background.
.B \-E .B \-E
Log to standard error rather than syslog. Log to standard error rather than syslog.
.TP .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 .B \-m
Don't display the message of the day on login. Don't display the message of the day on login.
.TP .TP
@@ -53,10 +47,6 @@ Disable password logins.
.B \-g .B \-g
Disable password logins for root. Disable password logins for root.
.TP .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 .B \-j
Disable local port forwarding. Disable local port forwarding.
.TP .TP
@@ -70,7 +60,7 @@ and TCP
.I port. .I port.
If just a port is given listen If just a port is given listen
on all addresses. 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 .TP
.B \-i .B \-i
Service program mode. Service program mode.
@@ -96,21 +86,17 @@ Ensure that traffic is transmitted at a certain interval in seconds. This is
useful for working around firewalls or routers that drop connections after 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 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 closed if there is a temporary lapse of network connectivity. A setting
of 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed. if 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
.TP .TP
.B \-I \fIidle_timeout .B \-I \fIidle_timeout
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds. Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
.TP .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 .B \-T \fImax_authentication_attempts
Set the number of authentication attempts allowed per connection. If unspecified the default is 10 (MAX_AUTH_TRIES) Set the number of authentication attempts allowed per connection. If unspecified the default is 10 (MAX_AUTH_TRIES)
.TP .TP
.B \-c \fIforced_command .B \-c \fIforced_command
Disregard the command provided by the user and always run \fIforced_command\fR. This also Disregard the command provided by the user and always run \fIforced_command\fR. This also
overrides any authorized_keys command= option. The original command is saved in the overrides any authorized_keys command= option.
SSH_ORIGINAL_COMMAND environment variable (see below).
.TP .TP
.B \-V .B \-V
Print the version Print the version
@@ -147,18 +133,6 @@ Don't allow X11 forwarding for this connection
Disable PTY allocation. Note that a user can still obtain most of the Disable PTY allocation. Note that a user can still obtain most of the
same functionality with other means even if no-pty is set. 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 .TP
.B command=\fR"\fIforced_command\fR" .B command=\fR"\fIforced_command\fR"
Disregard the command provided by the user and always run \fIforced_command\fR. Disregard the command provided by the user and always run \fIforced_command\fR.

View File

@@ -3,6 +3,6 @@
EXITCODE=0 EXITCODE=0
# #ifdef instead of #if # #ifdef instead of #if
grep '#ifdef DROPBEAR' -I -- *.c *.h && EXITCODE=1 grep '#ifdef DROPBEAR' -I *.c *.h && EXITCODE=1
exit $EXITCODE exit $EXITCODE

View File

@@ -9,7 +9,7 @@ dropbearconvert \- convert between Dropbear and OpenSSH private key formats
.I output_file .I output_file
.SH DESCRIPTION .SH DESCRIPTION
.B Dropbear .B Dropbear
and and
.B OpenSSH .B OpenSSH
SSH implementations have different private key formats. SSH implementations have different private key formats.
.B dropbearconvert .B dropbearconvert
@@ -24,15 +24,15 @@ first.
.SH ARGUMENTS .SH ARGUMENTS
.TP .TP
.I input_type .I input_type
Either Either
.I dropbear .I dropbear
or or
.I openssh .I openssh
.TP .TP
.I output_type .I output_type
Either Either
.I dropbear .I dropbear
or or
.I openssh .I openssh
.TP .TP
.I input_file .I input_file
@@ -40,15 +40,6 @@ An existing Dropbear or OpenSSH private key file
.TP .TP
.I output_file .I output_file
The path to write the converted private key file. For client authentication ~/.ssh/id_dropbear is loaded by default 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 .SH EXAMPLE
# dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_dropbear # dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_dropbear
.SH AUTHOR .SH AUTHOR

View File

@@ -69,7 +69,7 @@ int main(int argc, char ** argv) {
#if DEBUG_TRACE #if DEBUG_TRACE
/* It's hard for it to get in the way _too_ much */ /* It's hard for it to get in the way _too_ much */
debug_trace = DROPBEAR_VERBOSE_LEVEL; debug_trace = 1;
#endif #endif
/* get the commandline options */ /* get the commandline options */

View File

@@ -127,19 +127,18 @@ static void check_signkey_bits(enum signkey_type type, int bits)
#endif #endif
#if DROPBEAR_RSA #if DROPBEAR_RSA
case DROPBEAR_SIGNKEY_RSA: case DROPBEAR_SIGNKEY_RSA:
if (bits < 1024 || bits > 4096 || (bits % 8 != 0)) { if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
dropbear_exit("Bits must satisfy 1024 <= bits <= 4096, and be a" dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
" multiple of 8\n"); " multiple of 8\n");
} }
break; break;
#endif #endif
#if DROPBEAR_DSS #if DROPEAR_DSS
case DROPBEAR_SIGNKEY_DSS: case DROPBEAR_SIGNKEY_DSS:
if (bits != 1024) { if (bits != 1024) {
dropbear_exit("DSS keys have a fixed size of 1024 bits\n"); dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
break;
#endif #endif
default: default:
(void)0; /* quiet, compiler. ecdsa handles checks itself */ (void)0; /* quiet, compiler. ecdsa handles checks itself */
@@ -196,7 +195,7 @@ int main(int argc, char ** argv) {
break; break;
#if DEBUG_TRACE #if DEBUG_TRACE
case 'v': case 'v':
debug_trace = DROPBEAR_VERBOSE_LEVEL; debug_trace = 1;
break; break;
#endif #endif
default: default:
@@ -310,7 +309,8 @@ static int printpubfile(const char* filename) {
err = DROPBEAR_SUCCESS; err = DROPBEAR_SUCCESS;
out: out:
buf_burn_free(buf); buf_burn(buf);
buf_free(buf);
buf = NULL; buf = NULL;
if (key) { if (key) {
sign_key_free(key); sign_key_free(key);
@@ -342,7 +342,7 @@ static void printpubkey(sign_key * key, int keytype) {
err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len); err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
if (err != CRYPT_OK) { if (err != CRYPT_OK) {
dropbear_exit("base64 failed"); fprintf(stderr, "base64 failed");
} }
typestring = signkey_name_from_type(keytype, NULL); typestring = signkey_name_from_type(keytype, NULL);

23
ecdsa.c
View File

@@ -81,25 +81,18 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf) {
struct dropbear_ecc_curve **curve; struct dropbear_ecc_curve **curve;
ecc_key *new_key = NULL; ecc_key *new_key = NULL;
/* string "ecdsa-sha2-[identifier]" or "sk-ecdsa-sha2-nistp256@openssh.com" */ /* string "ecdsa-sha2-[identifier]" */
key_ident = (unsigned char*)buf_getstring(buf, &key_ident_len); key_ident = (unsigned char*)buf_getstring(buf, &key_ident_len);
/* string "[identifier]" */ /* string "[identifier]" */
identifier = (unsigned char*)buf_getstring(buf, &identifier_len); identifier = (unsigned char*)buf_getstring(buf, &identifier_len);
if (strcmp (key_ident, "sk-ecdsa-sha2-nistp256@openssh.com") == 0) { if (key_ident_len != identifier_len + strlen("ecdsa-sha2-")) {
if (strcmp (identifier, "nistp256") != 0) { TRACE(("Bad identifier lengths"))
TRACE(("mismatching identifiers")) goto out;
goto out; }
} if (memcmp(&key_ident[strlen("ecdsa-sha2-")], identifier, identifier_len) != 0) {
} else { TRACE(("mismatching identifiers"))
if (key_ident_len != identifier_len + strlen ("ecdsa-sha2-")) { goto out;
TRACE(("Bad identifier lengths"))
goto out;
}
if (memcmp(&key_ident[strlen ("ecdsa-sha2-")], identifier, identifier_len) != 0) {
TRACE(("mismatching identifiers"))
goto out;
}
} }
for (curve = dropbear_ecc_curves; *curve; curve++) { for (curve = dropbear_ecc_curves; *curve; curve++) {

View File

@@ -38,25 +38,14 @@
* The key will have the same format as buf_put_ed25519_key. * The key will have the same format as buf_put_ed25519_key.
* These should be freed with ed25519_key_free. * These should be freed with ed25519_key_free.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key, int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key) {
enum signkey_type expect_keytype) {
unsigned int len;
unsigned int len, typelen;
char *keytype = NULL;
enum signkey_type buf_keytype;
TRACE(("enter buf_get_ed25519_pub_key")) TRACE(("enter buf_get_ed25519_pub_key"))
dropbear_assert(key != NULL); dropbear_assert(key != NULL);
/* consume and check the key string */ buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */
keytype = buf_getstring(buf, &typelen);
buf_keytype = signkey_type_from_name(keytype, typelen);
m_free(keytype);
if (buf_keytype != expect_keytype) {
TRACE(("leave buf_get_ed25519_pub_key: mismatch key type"))
return DROPBEAR_FAILURE;
}
len = buf_getint(buf); len = buf_getint(buf);
if (len != CURVE25519_LEN || buf->len - buf->pos < len) { if (len != CURVE25519_LEN || buf->len - buf->pos < len) {

View File

@@ -27,7 +27,6 @@
#include "includes.h" #include "includes.h"
#include "buffer.h" #include "buffer.h"
#include "signkey.h"
#if DROPBEAR_ED25519 #if DROPBEAR_ED25519
@@ -44,8 +43,7 @@ void buf_put_ed25519_sign(buffer* buf, const dropbear_ed25519_key *key, const bu
#if DROPBEAR_SIGNKEY_VERIFY #if DROPBEAR_SIGNKEY_VERIFY
int buf_ed25519_verify(buffer * buf, const dropbear_ed25519_key *key, const buffer *data_buf); int buf_ed25519_verify(buffer * buf, const dropbear_ed25519_key *key, const buffer *data_buf);
#endif #endif
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key, int buf_get_ed25519_pub_key(buffer* buf, dropbear_ed25519_key *key);
enum signkey_type expect_keytype);
int buf_get_ed25519_priv_key(buffer* buf, dropbear_ed25519_key *key); int buf_get_ed25519_priv_key(buffer* buf, dropbear_ed25519_key *key);
void buf_put_ed25519_pub_key(buffer* buf, const dropbear_ed25519_key *key); void buf_put_ed25519_pub_key(buffer* buf, const dropbear_ed25519_key *key);
void buf_put_ed25519_priv_key(buffer* buf, const dropbear_ed25519_key *key); void buf_put_ed25519_priv_key(buffer* buf, const dropbear_ed25519_key *key);

209
fuzz-common.c Normal file
View File

@@ -0,0 +1,209 @@
#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);
}

View File

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

View File

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

View File

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

View File

@@ -1,20 +1,19 @@
#ifndef FUZZ_WRAPFD_H #ifndef FUZZ_WRAPFD_H
#define FUZZ_WRAPFD_H #define FUZZ_WRAPFD_H
#include "includes.h"
#include "buffer.h" #include "buffer.h"
enum wrapfd_mode { enum wrapfd_mode {
UNUSED = 0, UNUSED = 0,
COMMONBUF, // using the common buffer PLAIN,
DUMMY, // reads return fixed output, of random length INPROGRESS,
RANDOMIN
}; };
// buf is a common buffer read by all wrapped FDs. doesn't take ownership of buf void wrapfd_setup(void);
void wrapfd_setup(buffer *buf);
void wrapfd_setseed(uint32_t seed); void wrapfd_setseed(uint32_t seed);
int wrapfd_new_fuzzinput(void); // doesn't take ownership of buf. buf is optional.
int wrapfd_new_dummy(void); void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode);
// called via #defines for read/write/select // called via #defines for read/write/select
int wrapfd_read(int fd, void *out, size_t count); int wrapfd_read(int fd, void *out, size_t count);
@@ -22,6 +21,5 @@ int wrapfd_write(int fd, const void* in, size_t count);
int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds, int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout); fd_set *exceptfds, struct timeval *timeout);
int wrapfd_close(int fd); int wrapfd_close(int fd);
int fuzz_kill(pid_t pid, int sig);
#endif // FUZZ_WRAPFD_H #endif // FUZZ_WRAPFD_H

60
fuzz.h
View File

@@ -8,24 +8,17 @@
#include "includes.h" #include "includes.h"
#include "buffer.h" #include "buffer.h"
#include "algo.h" #include "algo.h"
#include "netio.h"
#include "fuzz-wrapfd.h" #include "fuzz-wrapfd.h"
// once per process // once per process
void fuzz_common_setup(void); void fuzz_common_setup(void);
void fuzz_svr_setup(void); void fuzz_svr_setup(void);
void fuzz_cli_setup(void);
// constructor attribute so it runs before main(), including
// in non-fuzzing mode.
void fuzz_early_setup(void) __attribute__((constructor));
// must be called once per fuzz iteration. // must be called once per fuzz iteration.
// returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
int fuzz_set_input(const uint8_t *Data, size_t Size); int fuzz_set_input(const uint8_t *Data, size_t Size);
int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int postauth); int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths);
int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths);
const void* fuzz_get_algo(const algo_type *algos, const char* name); const void* fuzz_get_algo(const algo_type *algos, const char* name);
// fuzzer functions that intrude into general code // fuzzer functions that intrude into general code
@@ -34,18 +27,10 @@ int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename,
const char* algo, unsigned int algolen, const char* algo, unsigned int algolen,
const unsigned char* keyblob, unsigned int keybloblen); const unsigned char* keyblob, unsigned int keybloblen);
extern const char * const * fuzz_signkey_names; extern const char * const * fuzz_signkey_names;
void fuzz_seed(const unsigned char* dat, unsigned int len); void fuzz_seed(void);
void fuzz_svr_hook_preloop(void);
int fuzz_dropbear_listen(const char* address, const char* port,
int *socks, unsigned int sockcount, char **errstring, int *maxfd);
// helpers
void fuzz_get_socket_address(int fd, char **local_host, char **local_port, void fuzz_get_socket_address(int fd, char **local_host, char **local_port,
char **remote_host, char **remote_port, int host_lookup); char **remote_host, char **remote_port, int host_lookup);
void fuzz_fake_send_kexdh_reply(void); void fuzz_fake_send_kexdh_reply(void);
int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid);
void fuzz_dump(const unsigned char* data, size_t len);
// fake IO wrappers // fake IO wrappers
#ifndef FUZZ_SKIP_WRAP #ifndef FUZZ_SKIP_WRAP
@@ -54,7 +39,6 @@ void fuzz_dump(const unsigned char* data, size_t len);
#define write(fd, buf, count) wrapfd_write(fd, buf, count) #define write(fd, buf, count) wrapfd_write(fd, buf, count)
#define read(fd, buf, count) wrapfd_read(fd, buf, count) #define read(fd, buf, count) wrapfd_read(fd, buf, count)
#define close(fd) wrapfd_close(fd) #define close(fd) wrapfd_close(fd)
#define kill(pid, sig) fuzz_kill(pid, sig)
#endif // FUZZ_SKIP_WRAP #endif // FUZZ_SKIP_WRAP
struct dropbear_fuzz_options { struct dropbear_fuzz_options {
@@ -68,47 +52,21 @@ struct dropbear_fuzz_options {
// whether to skip slow bignum maths // whether to skip slow bignum maths
int skip_kexmaths; int skip_kexmaths;
// whether is svr_postauth mode
int svr_postauth;
// dropbear_exit() jumps back // dropbear_exit() jumps back
int do_jmp; int do_jmp;
sigjmp_buf jmp; sigjmp_buf jmp;
// write out decrypted session data to this FD if it is set uid_t pw_uid;
// flag - this needs to be set manually in cli-main.c etc gid_t pw_gid;
int dumping; char* pw_name;
// the file descriptor char* pw_dir;
int recv_dumpfd; char* pw_shell;
char* pw_passwd;
// avoid filling fuzzing logs, this points to /dev/null
FILE *fake_stderr;
}; };
extern struct dropbear_fuzz_options fuzz; extern struct dropbear_fuzz_options fuzz;
/* guard for when fuzz.h is included by fuzz-common.c */ #endif // DROPBEAR_FUZZ
#ifndef FUZZ_NO_REPLACE_STDERR
/* This is a bodge but seems to work.
glibc stdio.h has the comment
"C89/C99 say they're macros. Make them happy." */
/* OS X has it as a macro */
#ifdef stderr
#undef stderr
#endif
#define stderr (fuzz.fake_stderr)
#endif /* FUZZ_NO_REPLACE_STDERR */
struct passwd* fuzz_getpwuid(uid_t uid);
struct passwd* fuzz_getpwnam(const char *login);
/* guard for when fuzz.h is included by fuzz-common.c */
#ifndef FUZZ_NO_REPLACE_GETPW
#define getpwnam(x) fuzz_getpwnam(x)
#define getpwuid(x) fuzz_getpwuid(x)
#endif // FUZZ_NO_REPLACE_GETPW
#endif /* DROPBEAR_FUZZ */
#endif /* DROPBEAR_FUZZ_H */ #endif /* DROPBEAR_FUZZ_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,30 +6,33 @@
#include "algo.h" #include "algo.h"
#include "bignum.h" #include "bignum.h"
static struct key_context* keep_newkeys = NULL;
/* An arbitrary limit */
#define NUM_PARAMS 80
static struct kex_curve25519_param *curve25519_params[NUM_PARAMS];
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;
/* 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) { 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];
if (!once) {
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;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
curve25519_params[i] = gen_kexcurve25519_param();
}
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0; return 0;
} }

View File

@@ -6,29 +6,33 @@
#include "algo.h" #include "algo.h"
#include "bignum.h" #include "bignum.h"
static struct key_context* keep_newkeys = NULL;
#define NUM_PARAMS 80
static struct kex_dh_param *dh_params[NUM_PARAMS];
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;
/* 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) { 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];
if (!once) {
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;
/* Pre-generate parameters */
int i;
for (i = 0; i < NUM_PARAMS; i++) {
dh_params[i] = gen_kexdh_param();
}
once = 1;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0; return 0;
} }

View File

@@ -6,38 +6,38 @@
#include "algo.h" #include "algo.h"
#include "bignum.h" #include "bignum.h"
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];
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;
/* 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) { 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];
if (!once) {
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;
/* 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;
}
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
return 0; return 0;

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,6 @@
#include "fuzz-wrapfd.h" #include "fuzz-wrapfd.h"
#include "debug.h" #include "debug.h"
#include "dss.h" #include "dss.h"
#include "ed25519.h"
static void setup_fuzzer(void) { static void setup_fuzzer(void) {
fuzz_common_setup(); fuzz_common_setup();
@@ -60,21 +59,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
/* Could also check g**q mod p == 1 */ /* 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) { if (!boguskey) {
printf("Random key/signature managed to verify!\n"); printf("Random key/signature managed to verify!\n");
abort(); abort();

View File

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

View File

@@ -34,7 +34,7 @@
#if DROPBEAR_RSA #if DROPBEAR_RSA
static void getrsaprime(mp_int* prime, mp_int *primeminus, static void getrsaprime(mp_int* prime, mp_int *primeminus,
const mp_int* rsa_e, unsigned int size_bytes); mp_int* rsa_e, unsigned int size_bytes);
/* mostly taken from libtomcrypt's rsa key generation routine */ /* mostly taken from libtomcrypt's rsa key generation routine */
dropbear_rsa_key * gen_rsa_priv_key(unsigned int size) { dropbear_rsa_key * gen_rsa_priv_key(unsigned int size) {
@@ -89,7 +89,7 @@ dropbear_rsa_key * gen_rsa_priv_key(unsigned int size) {
/* return a prime suitable for p or q */ /* return a prime suitable for p or q */
static void getrsaprime(mp_int* prime, mp_int *primeminus, static void getrsaprime(mp_int* prime, mp_int *primeminus,
const mp_int* rsa_e, unsigned int size_bytes) { mp_int* rsa_e, unsigned int size_bytes) {
unsigned char *buf; unsigned char *buf;
int trials; int trials;

View File

@@ -181,7 +181,8 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename,
out: out:
if (buf) { if (buf) {
buf_burn_free(buf); buf_burn(buf);
buf_free(buf);
} }
if (fn_temp) { if (fn_temp) {

View File

@@ -25,6 +25,9 @@
#ifndef DROPBEAR_INCLUDES_H_ #ifndef DROPBEAR_INCLUDES_H_
#define DROPBEAR_INCLUDES_H_ #define DROPBEAR_INCLUDES_H_
/* uclibc needs _GNU_SOURCE, maybe other things? */
#define _GNU_SOURCE
#include "options.h" #include "options.h"
#include "debug.h" #include "debug.h"
@@ -127,10 +130,6 @@
#include <sys/random.h> #include <sys/random.h>
#endif #endif
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
#ifdef BUNDLED_LIBTOM #ifdef BUNDLED_LIBTOM
#include "libtomcrypt/src/headers/tomcrypt.h" #include "libtomcrypt/src/headers/tomcrypt.h"
#include "libtommath/tommath.h" #include "libtommath/tommath.h"
@@ -175,8 +174,6 @@ typedef u_int32_t uint32_t;
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
extern char** environ;
#include "fake-rfc2553.h" #include "fake-rfc2553.h"
#include "fuzz.h" #include "fuzz.h"

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -16,6 +16,12 @@
#if DROPBEAR_AES #if DROPBEAR_AES
#define LTC_RIJNDAEL #define LTC_RIJNDAEL
#endif #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 #if DROPBEAR_3DES
#define LTC_DES #define LTC_DES
@@ -50,8 +56,10 @@
#define LTC_SHA256 #define LTC_SHA256
#endif #endif
#if DROPBEAR_SHA1
#define LTC_SHA1 #define LTC_SHA1
#if DROPBEAR_MD5
#define LTC_MD5
#endif #endif
/* ECC */ /* ECC */

View File

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

View File

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

View File

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

View File

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

View File

@@ -139,7 +139,7 @@ struct Listener * get_listener(int type, const void* typedata,
struct Listener* listener; struct Listener* listener;
for (i = 0, listener = ses.listeners[i]; i < ses.listensize; i++) { for (i = 0, listener = ses.listeners[i]; i < ses.listensize; i++) {
if (listener && listener->type == type if (listener->type == type
&& match(typedata, listener->typedata)) { && match(typedata, listener->typedata)) {
return listener; return listener;
} }

View File

@@ -459,7 +459,6 @@ line_abbrevname(char *dst, const char *src, size_t dstsize)
void void
set_utmp_time(struct logininfo *li, struct utmp *ut) set_utmp_time(struct logininfo *li, struct utmp *ut)
{ {
/* struct utmp in glibc isn't y2038 safe yet */
# ifdef HAVE_STRUCT_UTMP_UT_TV # ifdef HAVE_STRUCT_UTMP_UT_TV
ut->ut_tv.tv_sec = li->tv_sec; ut->ut_tv.tv_sec = li->tv_sec;
ut->ut_tv.tv_usec = li->tv_usec; ut->ut_tv.tv_usec = li->tv_usec;
@@ -830,7 +829,7 @@ utmpx_perform_login(struct logininfo *li)
return 0; return 0;
} }
# else # else
if (!utmpx_write_direct(li, &utx)) { if (!utmpx_write_direct(li, &ut)) {
dropbear_log(LOG_WARNING, "utmpx_perform_login: utmp_write_direct() failed"); dropbear_log(LOG_WARNING, "utmpx_perform_login: utmp_write_direct() failed");
return 0; return 0;
} }
@@ -1273,7 +1272,6 @@ lastlog_construct(struct logininfo *li, struct lastlog *last)
(void)line_stripname(last->ll_line, li->line, sizeof(last->ll_line)); (void)line_stripname(last->ll_line, li->line, sizeof(last->ll_line));
strlcpy(last->ll_host, li->hostname, strlcpy(last->ll_host, li->hostname,
MIN_SIZEOF(last->ll_host, li->hostname)); MIN_SIZEOF(last->ll_host, li->hostname));
/* struct lastlog in glibc isn't y2038 safe yet */
last->ll_time = li->tv_sec; last->ll_time = li->tv_sec;
} }

View File

@@ -139,8 +139,8 @@ struct logininfo {
/* struct timeval (sys/time.h) isn't always available, if it isn't we'll /* struct timeval (sys/time.h) isn't always available, if it isn't we'll
* use time_t's value as tv_sec and set tv_usec to 0 * use time_t's value as tv_sec and set tv_usec to 0
*/ */
time_t tv_sec; unsigned int tv_sec;
suseconds_t tv_usec; unsigned int tv_usec;
union login_netinfo hostaddr; /* caller's host address(es) */ union login_netinfo hostaddr; /* caller's host address(es) */
}; /* struct logininfo */ }; /* struct logininfo */

96
netio.c
View File

@@ -3,7 +3,6 @@
#include "dbutil.h" #include "dbutil.h"
#include "session.h" #include "session.h"
#include "debug.h" #include "debug.h"
#include "runopts.h"
struct dropbear_progress_connection { struct dropbear_progress_connection {
struct addrinfo *res; struct addrinfo *res;
@@ -21,7 +20,6 @@ struct dropbear_progress_connection {
char* errstring; char* errstring;
char *bind_address, *bind_port; char *bind_address, *bind_port;
enum dropbear_prio prio;
}; };
/* Deallocate a progress connection. Removes from the pending list if iter!=NULL. /* Deallocate a progress connection. Removes from the pending list if iter!=NULL.
@@ -112,7 +110,6 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
ses.maxfd = MAX(ses.maxfd, c->sock); ses.maxfd = MAX(ses.maxfd, c->sock);
set_sock_nodelay(c->sock); set_sock_nodelay(c->sock);
set_sock_priority(c->sock, c->prio);
setnonblocking(c->sock); setnonblocking(c->sock);
#if DROPBEAR_CLIENT_TCP_FAST_OPEN #if DROPBEAR_CLIENT_TCP_FAST_OPEN
@@ -175,8 +172,8 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
/* Connect via TCP to a host. */ /* Connect via TCP to a host. */
struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport, struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport,
connect_callback cb, void* cb_data, connect_callback cb, void* cb_data,
const char* bind_address, const char* bind_port, enum dropbear_prio prio) const char* bind_address, const char* bind_port)
{ {
struct dropbear_progress_connection *c = NULL; struct dropbear_progress_connection *c = NULL;
int err; int err;
@@ -188,17 +185,9 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons
c->sock = -1; c->sock = -1;
c->cb = cb; c->cb = cb;
c->cb_data = cb_data; c->cb_data = cb_data;
c->prio = prio;
list_append(&ses.conn_pending, c); list_append(&ses.conn_pending, c);
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
c->errstring = m_strdup("fuzzing connect_remote always fails");
return c;
}
#endif
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
@@ -367,7 +356,12 @@ void set_listen_fast_open(int sock) {
void set_sock_priority(int sock, enum dropbear_prio prio) { void set_sock_priority(int sock, enum dropbear_prio prio) {
int rc; int rc;
int val; #ifdef IPTOS_LOWDELAY
int iptos_val = 0;
#endif
#ifdef HAVE_LINUX_PKT_SCHED_H
int so_prio_val = 0;
#endif
#if DROPBEAR_FUZZ #if DROPBEAR_FUZZ
if (fuzz.fuzzing) { if (fuzz.fuzzing) {
@@ -375,53 +369,37 @@ void set_sock_priority(int sock, enum dropbear_prio prio) {
return; return;
} }
#endif #endif
/* Don't log ENOTSOCK errors so that this can harmlessly be called /* Don't log ENOTSOCK errors so that this can harmlessly be called
* on a client '-J' proxy pipe */ * on a client '-J' proxy pipe */
if (opts.disable_ip_tos == 0) { /* set the TOS bit for either ipv4 or ipv6 */
#ifdef IP_TOS #ifdef IPTOS_LOWDELAY
/* Set the DSCP field for outbound IP packet priority.
rfc4594 has some guidance to meanings.
We set AF21 as "Low-Latency" class for interactive (tty session,
also handshake/setup packets). Other traffic is left at the default.
OpenSSH at present uses AF21/CS1, rationale
https://cvsweb.openbsd.org/src/usr.bin/ssh/readconf.c#rev1.284
Old Dropbear/OpenSSH and Debian/Ubuntu OpenSSH (at Jan 2022) use
IPTOS_LOWDELAY/IPTOS_THROUGHPUT
DSCP constants are from Linux headers, applicable to other platforms
such as macos.
*/
if (prio == DROPBEAR_PRIO_LOWDELAY) { if (prio == DROPBEAR_PRIO_LOWDELAY) {
val = 0x48; /* IPTOS_DSCP_AF21 */ iptos_val = IPTOS_LOWDELAY;
} else { } else if (prio == DROPBEAR_PRIO_BULK) {
val = 0; /* default */ iptos_val = IPTOS_THROUGHPUT;
} }
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
rc = setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)&val, sizeof(val)); rc = setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)&iptos_val, sizeof(iptos_val));
if (rc < 0 && errno != ENOTSOCK) { if (rc < 0 && errno != ENOTSOCK) {
TRACE(("Couldn't set IPV6_TCLASS (%s)", strerror(errno))); TRACE(("Couldn't set IPV6_TCLASS (%s)", strerror(errno)));
} }
#endif #endif
rc = setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val)); rc = setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&iptos_val, sizeof(iptos_val));
if (rc < 0 && errno != ENOTSOCK) { if (rc < 0 && errno != ENOTSOCK) {
TRACE(("Couldn't set IP_TOS (%s)", strerror(errno))); TRACE(("Couldn't set IP_TOS (%s)", strerror(errno)));
} }
#endif /* IP_TOS */ #endif
}
#ifdef HAVE_LINUX_PKT_SCHED_H #ifdef HAVE_LINUX_PKT_SCHED_H
/* Set scheduling priority within the local Linux network stack */
if (prio == DROPBEAR_PRIO_LOWDELAY) { if (prio == DROPBEAR_PRIO_LOWDELAY) {
val = TC_PRIO_INTERACTIVE; so_prio_val = TC_PRIO_INTERACTIVE;
} else { } else if (prio == DROPBEAR_PRIO_BULK) {
val = 0; so_prio_val = TC_PRIO_BULK;
} }
/* linux specific, sets QoS class. see tc-prio(8) */ /* linux specific, sets QoS class. see tc-prio(8) */
rc = setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) &val, sizeof(val)); rc = setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) &so_prio_val, sizeof(so_prio_val));
if (rc < 0 && errno != ENOTSOCK) { if (rc < 0 && errno != ENOTSOCK) {
TRACE(("Couldn't set SO_PRIORITY (%s)", strerror(errno))) TRACE(("Couldn't set SO_PRIORITY (%s)", strerror(errno)))
} }
@@ -475,16 +453,8 @@ int dropbear_listen(const char* address, const char* port,
struct linger linger; struct linger linger;
int val; int val;
int sock; int sock;
uint16_t *allocated_lport_p = NULL;
int allocated_lport = 0;
TRACE(("enter dropbear_listen"))
#if DROPBEAR_FUZZ TRACE(("enter dropbear_listen"))
if (fuzz.fuzzing) {
return fuzz_dropbear_listen(address, port, socks, sockcount, errstring, maxfd);
}
#endif
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */ hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
@@ -520,15 +490,20 @@ int dropbear_listen(const char* address, const char* port,
return -1; return -1;
} }
/* When listening on server-assigned-port 0 /*
* when listening on server-assigned-port 0
* the assigned ports may differ for address families (v4/v6) * the assigned ports may differ for address families (v4/v6)
* causing problems for tcpip-forward. * causing problems for tcpip-forward
* Caller can do a get_socket_address to discover assigned-port * caller can do a get_socket_address to discover assigned-port
* hence, use same port for all address families */ * hence, use same port for all address families
allocated_lport = 0; */
u_int16_t *allocated_lport_p = NULL;
int allocated_lport = 0;
nsock = 0; nsock = 0;
for (res = res0; res != NULL && nsock < sockcount; for (res = res0; res != NULL && nsock < sockcount;
res = res->ai_next) { res = res->ai_next) {
if (allocated_lport > 0) { if (allocated_lport > 0) {
if (AF_INET == res->ai_family) { if (AF_INET == res->ai_family) {
allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port; allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
@@ -539,8 +514,11 @@ int dropbear_listen(const char* address, const char* port,
} }
/* Get a socket */ /* Get a socket */
socks[nsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); socks[nsock] = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
sock = socks[nsock]; /* For clarity */ sock = socks[nsock]; /* For clarity */
if (sock < 0) { if (sock < 0) {
err = errno; err = errno;
TRACE(("socket() failed")) TRACE(("socket() failed"))
@@ -564,6 +542,7 @@ int dropbear_listen(const char* address, const char* port,
} }
} }
#endif #endif
set_sock_nodelay(sock); set_sock_nodelay(sock);
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
@@ -585,6 +564,7 @@ int dropbear_listen(const char* address, const char* port,
} }
*maxfd = MAX(*maxfd, sock); *maxfd = MAX(*maxfd, sock);
nsock++; nsock++;
} }

View File

@@ -6,8 +6,9 @@
#include "queue.h" #include "queue.h"
enum dropbear_prio { enum dropbear_prio {
DROPBEAR_PRIO_NORMAL = 0, /* the rest - tcp-fwd, scp, rsync, git, etc */ DROPBEAR_PRIO_DEFAULT = 10,
DROPBEAR_PRIO_LOWDELAY, /* pty shell, x11 */ DROPBEAR_PRIO_LOWDELAY = 11,
DROPBEAR_PRIO_BULK = 12,
}; };
void set_sock_nodelay(int sock); void set_sock_nodelay(int sock);
@@ -29,8 +30,7 @@ typedef void(*connect_callback)(int result, int sock, void* data, const char* er
/* Always returns a progress connection, if it fails it will call the callback at a later point */ /* Always returns a progress connection, if it fails it will call the callback at a later point */
struct dropbear_progress_connection * connect_remote (const char* remotehost, const char* remoteport, struct dropbear_progress_connection * connect_remote (const char* remotehost, const char* remoteport,
connect_callback cb, void *cb_data, const char* bind_address, const char* bind_port, connect_callback cb, void *cb_data, const char* bind_address, const char* bind_port);
enum dropbear_prio prio);
/* Sets up for select() */ /* Sets up for select() */
void set_connect_fds(fd_set *writefd); void set_connect_fds(fd_set *writefd);

View File

@@ -344,12 +344,7 @@ void decrypt_packet() {
if (checkmac() != DROPBEAR_SUCCESS) { if (checkmac() != DROPBEAR_SUCCESS) {
dropbear_exit("Integrity error"); dropbear_exit("Integrity error");
} }
} }
#if DROPBEAR_FUZZ
fuzz_dump(ses.readbuf->data, ses.readbuf->len);
#endif
/* get padding length */ /* get padding length */
buf_setpos(ses.readbuf, PACKET_PADDING_OFF); buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
@@ -430,32 +425,44 @@ static buffer* buf_decompress(const buffer* buf, unsigned int len) {
z_streamp zstream; z_streamp zstream;
zstream = ses.keys->recv.zstream; zstream = ses.keys->recv.zstream;
/* We use RECV_MAX_PAYLOAD_LEN+1 here to ensure that ret = buf_new(len);
we can detect an oversized payload after inflate() */
ret = buf_new(RECV_MAX_PAYLOAD_LEN+1);
zstream->avail_in = len; zstream->avail_in = len;
zstream->next_in = buf_getptr(buf, len); zstream->next_in = buf_getptr(buf, len);
zstream->avail_out = ret->size;
zstream->next_out = ret->data;
result = inflate(zstream, Z_SYNC_FLUSH); /* decompress the payload, incrementally resizing the output buffer */
if (result != Z_OK) { while (1) {
dropbear_exit("zlib error");
zstream->avail_out = ret->size - ret->pos;
zstream->next_out = buf_getwriteptr(ret, zstream->avail_out);
result = inflate(zstream, Z_SYNC_FLUSH);
buf_setlen(ret, ret->size - zstream->avail_out);
buf_setpos(ret, ret->len);
if (result != Z_BUF_ERROR && result != Z_OK) {
dropbear_exit("zlib error");
}
if (zstream->avail_in == 0 &&
(zstream->avail_out != 0 || result == Z_BUF_ERROR)) {
/* we can only exit if avail_out hasn't all been used,
* and there's no remaining input */
return ret;
}
if (zstream->avail_out == 0) {
int new_size = 0;
if (ret->size >= RECV_MAX_PAYLOAD_LEN) {
/* Already been increased as large as it can go,
* yet didn't finish up the decompression */
dropbear_exit("bad packet, oversized decompressed");
}
new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR);
ret = buf_resize(ret, new_size);
}
} }
buf_setlen(ret, ret->size - zstream->avail_out);
if (zstream->avail_in > 0 || ret->len > RECV_MAX_PAYLOAD_LEN) {
/* The remote side sent larger than a payload size
* of uncompressed data.
*/
dropbear_exit("bad packet, oversized decompressed");
}
/* Success. All input was consumed and avail_out > 0 */
return ret;
} }
#endif #endif

View File

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

View File

@@ -33,14 +33,13 @@
typedef struct runopts { typedef struct runopts {
int disable_ip_tos;
#if DROPBEAR_SVR_REMOTETCPFWD || DROPBEAR_CLI_LOCALTCPFWD \ #if DROPBEAR_SVR_REMOTETCPFWD || DROPBEAR_CLI_LOCALTCPFWD \
|| DROPBEAR_CLI_REMOTETCPFWD || DROPBEAR_CLI_REMOTETCPFWD
int listen_fwd_all; int listen_fwd_all;
#endif #endif
unsigned int recv_window; unsigned int recv_window;
long keepalive_secs; /* Time between sending keepalives. 0 is off */ time_t keepalive_secs; /* Time between sending keepalives. 0 is off */
long idle_timeout_secs; /* Exit if no traffic is sent/received in this time */ time_t idle_timeout_secs; /* Exit if no traffic is sent/received in this time */
int usingsyslog; int usingsyslog;
#ifndef DISABLE_ZLIB #ifndef DISABLE_ZLIB
@@ -73,16 +72,13 @@ typedef struct svr_runopts {
int forkbg; int forkbg;
/* ports and addresses are arrays of the portcount /* ports and addresses are arrays of the portcount
listening ports. strings are malloced. */ listening ports. strings are malloced. */
char *ports[DROPBEAR_MAX_PORTS]; char *ports[DROPBEAR_MAX_PORTS];
unsigned int portcount; unsigned int portcount;
char *addresses[DROPBEAR_MAX_PORTS]; char *addresses[DROPBEAR_MAX_PORTS];
int inetdmode; int inetdmode;
/* Hidden "-2 childpipe_fd" flag indicates it's re-executing itself,
stores the childpipe preauth file descriptor. Set to -1 otherwise. */
int reexec_childpipe;
/* Flags indicating whether to use ipv4 and ipv6 */ /* Flags indicating whether to use ipv4 and ipv6 */
/* not used yet /* not used yet
@@ -94,6 +90,7 @@ typedef struct svr_runopts {
/* whether to print the MOTD */ /* whether to print the MOTD */
int domotd; int domotd;
#endif #endif
int norootlogin; int norootlogin;
#ifdef HAVE_GETGROUPLIST #ifdef HAVE_GETGROUPLIST
@@ -107,7 +104,6 @@ typedef struct svr_runopts {
int noauthpass; int noauthpass;
int norootpass; int norootpass;
int allowblankpass; int allowblankpass;
int multiauthmethod;
unsigned int maxauthtries; unsigned int maxauthtries;
#if DROPBEAR_SVR_REMOTETCPFWD #if DROPBEAR_SVR_REMOTETCPFWD
@@ -130,14 +126,10 @@ typedef struct svr_runopts {
char * forced_command; char * forced_command;
#if DROPBEAR_PLUGIN #if DROPBEAR_PLUGIN
/* malloced */ char *pubkey_plugin;
char *pubkey_plugin; char *pubkey_plugin_options;
/* points into pubkey_plugin */
char *pubkey_plugin_options;
#endif #endif
int pass_on_env;
} svr_runopts; } svr_runopts;
extern svr_runopts svr_opts; extern svr_runopts svr_opts;
@@ -159,7 +151,6 @@ typedef struct cli_runopts {
int always_accept_key; int always_accept_key;
int no_hostkey_check; int no_hostkey_check;
int no_cmd; int no_cmd;
int quiet;
int backgrounded; int backgrounded;
int is_subsystem; int is_subsystem;
#if DROPBEAR_CLI_PUBKEY_AUTH #if DROPBEAR_CLI_PUBKEY_AUTH
@@ -168,7 +159,6 @@ typedef struct cli_runopts {
#if DROPBEAR_CLI_ANYTCPFWD #if DROPBEAR_CLI_ANYTCPFWD
int exit_on_fwd_failure; int exit_on_fwd_failure;
#endif #endif
int disable_trivial_auth;
#if DROPBEAR_CLI_REMOTETCPFWD #if DROPBEAR_CLI_REMOTETCPFWD
m_list * remotefwds; m_list * remotefwds;
#endif #endif
@@ -202,7 +192,5 @@ void parse_ciphers_macs(void);
#endif #endif
void print_version(void); void print_version(void);
void parse_recv_window(const char* recv_window_arg);
int split_address_port(const char* spec, char **first, char ** second);
#endif /* DROPBEAR_RUNOPTS_H_ */ #endif /* DROPBEAR_RUNOPTS_H_ */

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