mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ea2e3463d | ||
|
|
ddb6751ab4 | ||
|
|
6e3c3c8c51 | ||
|
|
ef080502f8 | ||
|
|
fdbdbe5703 | ||
|
|
921592d37e | ||
|
|
04a02730bc | ||
|
|
dcce2cfd8d | ||
|
|
00a1290173 | ||
|
|
a3a0b26581 | ||
|
|
276197b404 | ||
|
|
484d1e9b81 | ||
|
|
278a3e43e5 | ||
|
|
2df2117388 | ||
|
|
187fc95deb | ||
|
|
b75a033787 | ||
|
|
423be0d5e6 | ||
|
|
68b3ef0734 | ||
|
|
d58e0497cc | ||
|
|
af10eb8346 | ||
|
|
8e93ac9925 | ||
|
|
6d5b27715a | ||
|
|
f295fbe0b2 | ||
|
|
575f0e5f92 | ||
|
|
85374c5ba2 | ||
|
|
83f3f55280 | ||
|
|
b2beb2c2da | ||
|
|
48ad370a19 | ||
|
|
c36f94a322 | ||
|
|
6493bbb7e7 | ||
|
|
3ec2737d54 | ||
|
|
72ccfda5b2 | ||
|
|
003ec5d356 | ||
|
|
f91d66448a | ||
|
|
ccfdf7e039 | ||
|
|
95ce05da40 | ||
|
|
c5d53cf81c | ||
|
|
5574460d25 | ||
|
|
233fd96994 | ||
|
|
d1b29336b1 | ||
|
|
fa5eb62464 | ||
|
|
0b48a4f879 | ||
|
|
00ef081fcf | ||
|
|
dabeaec461 | ||
|
|
d4ed2fffe4 | ||
|
|
0533b87b1a | ||
|
|
7504cd1a1a | ||
|
|
482dc0eff4 | ||
|
|
fc34d02427 | ||
|
|
5ce5fbcba0 | ||
|
|
31d2311537 |
9
.github/multiwrapper
vendored
9
.github/multiwrapper
vendored
@@ -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 "$@"
|
|
||||||
|
|
||||||
25
.github/workflows/autoconf.yml
vendored
25
.github/workflows/autoconf.yml
vendored
@@ -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
|
|
||||||
268
.github/workflows/build.yml
vendored
268
.github/workflows/build.yml
vendored
@@ -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
|
|
||||||
30
.github/workflows/cifuzz.yml
vendored
30
.github/workflows/cifuzz.yml
vendored
@@ -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
|
|
||||||
36
.github/workflows/tarball.yml
vendored
36
.github/workflows/tarball.yml
vendored
@@ -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
10
.gitignore
vendored
@@ -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
|
|
||||||
|
|||||||
2
.hgsigs
2
.hgsigs
@@ -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=
|
|
||||||
|
|||||||
2
.hgtags
2
.hgtags
@@ -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
36
.travis.yml
Normal 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
281
CHANGES
@@ -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
|
||||||
|
|
||||||
|
|||||||
6
INSTALL
6
INSTALL
@@ -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
|
||||||
|
|||||||
91
Makefile.in
91
Makefile.in
@@ -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
2
README
@@ -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
11
SMALL
@@ -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
20
auth.h
@@ -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
|
||||||
|
|
||||||
|
|||||||
4
bignum.c
4
bignum.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
2
bignum.h
2
bignum.h
@@ -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_ */
|
||||||
|
|||||||
41
buffer.c
41
buffer.c
@@ -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"))
|
||||||
|
|||||||
7
buffer.h
7
buffer.h
@@ -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);
|
||||||
|
|
||||||
|
|||||||
25
channel.h
25
channel.h
@@ -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[]);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
40
cli-auth.c
40
cli-auth.c
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
17
cli-kex.c
17
cli-kex.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
73
cli-main.c
73
cli-main.c
@@ -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 */
|
||||||
|
|||||||
127
cli-runopts.c
127
cli-runopts.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
11
cli-tcpfwd.c
11
cli-tcpfwd.c
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
30
common-kex.c
30
common-kex.c
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
compat.c
3
compat.c
@@ -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
1293
config.guess
vendored
File diff suppressed because it is too large
Load Diff
456
config.h.in
456
config.h.in
@@ -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
1062
config.sub
vendored
File diff suppressed because it is too large
Load Diff
110
configure.ac
110
configure.ac
@@ -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()
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
46
dbclient.1
46
dbclient.1
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
19
dbmulti.c
19
dbmulti.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
51
dbrandom.c
51
dbrandom.c
@@ -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;
|
||||||
|
|||||||
@@ -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
186
dbutil.c
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
19
dbutil.h
19
dbutil.h
@@ -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
24
debian/changelog
vendored
@@ -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.
|
||||||
|
|||||||
2
debian/dropbear.init
vendored
2
debian/dropbear.init
vendored
@@ -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
38
debug.h
@@ -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. */
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
32
dropbear.8
32
dropbear.8
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
23
ecdsa.c
@@ -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++) {
|
||||||
|
|||||||
17
ed25519.c
17
ed25519.c
@@ -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) {
|
||||||
|
|||||||
@@ -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
209
fuzz-common.c
Normal 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);
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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
60
fuzz.h
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#include "fuzz.h"
|
|
||||||
|
|
||||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|
||||||
return fuzz_run_server(Data, Size, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#include "fuzz.h"
|
|
||||||
|
|
||||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|
||||||
return fuzz_run_server(Data, Size, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#include "fuzz.h"
|
|
||||||
|
|
||||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|
||||||
return fuzz_run_server(Data, Size, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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();
|
||||||
@@ -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
|
||||||
|
|||||||
4
genrsa.c
4
genrsa.c
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
1107
keyimport.c
1107
keyimport.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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} $@"
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
96
netio.c
@@ -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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
netio.h
8
netio.h
@@ -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);
|
||||||
|
|||||||
59
packet.c
59
packet.c
@@ -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
|
||||||
|
|
||||||
|
|||||||
77
release.sh
77
release.sh
@@ -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
|
|
||||||
|
|||||||
24
runopts.h
24
runopts.h
@@ -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
Reference in New Issue
Block a user