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-20.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
|
||||
199
.github/workflows/build.yml
vendored
199
.github/workflows/build.yml
vendored
@@ -1,199 +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-20.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: 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 10.15
|
||||
os: macos-10.15
|
||||
cc: clang
|
||||
# OS X says daemon() and utmp are deprecated
|
||||
extracflags: -Wno-deprecated-declarations
|
||||
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
|
||||
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
|
||||
|
||||
# # 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' }}
|
||||
# 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 $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
|
||||
cat localoptions.h
|
||||
|
||||
- name: make
|
||||
run: make -j3
|
||||
|
||||
- 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
|
||||
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
|
||||
run: ~/inst/bin/dropbearkey -t rsa -f testrsa
|
||||
- name: gendss
|
||||
run: ~/inst/bin/dropbearkey -t dss -f testdss
|
||||
- name: genecdsa256
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256
|
||||
- name: genecdsa384
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384
|
||||
- name: genecdsa521
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521
|
||||
- name: gened25519
|
||||
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-20.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
|
||||
/scp
|
||||
/scp-progress
|
||||
config.h
|
||||
default_options_guard.h
|
||||
localoptions.h
|
||||
Makefile
|
||||
config.h
|
||||
config.h.in
|
||||
configure
|
||||
default_options_guard.h
|
||||
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=
|
||||
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=
|
||||
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
|
||||
009d52ae26d35f3381c801e02318fa9be34be93c DROPBEAR_2019.78
|
||||
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
|
||||
173
CHANGES
173
CHANGES
@@ -1,154 +1,3 @@
|
||||
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". This can be used to prevent
|
||||
the server immediately accepting successful authentication (before any auth
|
||||
request) which could cause UI confusion and security issues with agent
|
||||
forwarding - it isn't clear which host is prompting to use a key.
|
||||
Thanks to Manfred Kaiser from Austrian MilCERT
|
||||
|
||||
- Add -q client option to hide remote banner, from Hans Harder
|
||||
|
||||
- Add -e option to pass all server environment variables to child processes.
|
||||
This should be used with caution.
|
||||
Patch from Roland Vollgraf (github #118)
|
||||
|
||||
- >> Use DSCP for QoS traffic classes. Priority (tty) traffic is now set to
|
||||
AF21 "interactive". Previously TOS classes were used, they are not used by
|
||||
modern traffic classifiers. Non-tty traffic is left at default priority.
|
||||
|
||||
- >> Disable dh-group1 key exchange by default. It has been disabled server
|
||||
side by default since 2018.
|
||||
|
||||
- >> Removed Twofish cipher
|
||||
|
||||
Fixes:
|
||||
|
||||
- Fix flushing channel data when pty was allocated (github #85)
|
||||
Data wasn't completely transmitted at channel close.
|
||||
Reported and initial patch thanks to Yousong Zhou
|
||||
|
||||
- Dropbear now re-executes itself rather than just forking for each connection
|
||||
(only on Linux). This allows ASLR to randomise address space for each
|
||||
connection as a security mitigation. It should not have any visible impact
|
||||
- if there are any performance impacts in the wild please report it.
|
||||
|
||||
- Check authorized_keys permissions as the user, fixes NFS squash root.
|
||||
Patch from Chris Dragan (github #107)
|
||||
|
||||
- A missing home directory is now non-fatal, starting in / instead
|
||||
|
||||
- Fixed IPv6 [address]:port parsing for dbclient -b
|
||||
Reported by Fabio Molinari
|
||||
|
||||
- Improve error logging so that they are logged on the server rather than being
|
||||
sent to the client over the connection
|
||||
|
||||
- Max window size is increased to 10MB, more graceful fallback if it's invalid.
|
||||
|
||||
- Fix correctness of Dropbear's handling of global requests.
|
||||
Patch from Dirkjan Bussink
|
||||
|
||||
- Fix some small bugs found by fuzzers, null pointer dereference crash and leaks
|
||||
(post authentication)
|
||||
|
||||
- $HOME variable is used before /etc/passwd when expanding paths such as
|
||||
~/.ssh/id_dropbear (for the client). Patch from Matt Robinson
|
||||
|
||||
- C89 build fixes from Guillaume Picquet
|
||||
|
||||
Infrastructure:
|
||||
|
||||
- Improvements to fuzzers. Added post-auth fuzzer, and a mutator that can
|
||||
handle the structure of SSH packet streams. Added cifuzz to run on commits
|
||||
and pull requests.
|
||||
Thanks to OSS-Fuzz for the tools/clusters and reward funding.
|
||||
|
||||
- Dropbear source tarballs generated by release.sh are now reproducible from a
|
||||
Git or Mercurial checkout, they will be identical on any system. Tested
|
||||
on ubuntu and macos.
|
||||
|
||||
- Added some integration testing using pytest. Currently this has tests
|
||||
for various channel handling edge cases, ASLR fork randomisation,
|
||||
dropbearconvert, and SSH_PUBKEYINFO
|
||||
|
||||
- Set up github actions. This runs the pytest suite and other checks.
|
||||
- build matrix includes c89, dropbearmulti, bundled libtom, macos, DEBUG_TRACE
|
||||
- test for configure script regeneration
|
||||
- build a tarball for external reproducibility
|
||||
|
||||
2020.81 - 29 October 2020
|
||||
|
||||
- Fix regression in 2020.79 which prevented connecting with some SSH
|
||||
implementations. Increase MAX_PROPOSED_ALGO to 50, and print a log
|
||||
message if the limit is hit. This fixes interoperability with sshj
|
||||
library (used by PyCharm), and GoAnywhere.
|
||||
Reported by Pirmin Walthert and Piotr Jurkiewicz
|
||||
|
||||
- Fix building with non-GCC compilers, reported by Kazuo Kuroi
|
||||
|
||||
- Fix potential long delay in dbclient, found by OSS Fuzz
|
||||
|
||||
- Fix null pointer dereference crash, found by OSS Fuzz
|
||||
|
||||
- libtommath now uses the same random source as Dropbear (in 2020.79
|
||||
and 2020.80 used getrandom() separately)
|
||||
|
||||
- Some fuzzing improvements, start of a dbclient fuzzer
|
||||
|
||||
2020.80 - 26 June 2020
|
||||
|
||||
- Don't block authorized_keys logins with no-X11-forwarding or no-agent-forwarding
|
||||
@@ -366,7 +215,7 @@ Infrastructure:
|
||||
dropbear is running with -a (Allow connections to forwarded ports from any host)
|
||||
This could potentially allow arbitrary code execution as root by an authenticated user.
|
||||
Affects versions 2013.56 to 2016.74. Thanks to Mark Shepard for reporting the crash.
|
||||
CVE-2017-9078 https://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.
|
||||
Dropbear parsed authorized_keys as root, even if it were a symlink. The fix
|
||||
@@ -378,7 +227,7 @@ Infrastructure:
|
||||
contents of that file.
|
||||
This information disclosure is to an already authenticated user.
|
||||
Thanks to Jann Horn of Google Project Zero for reporting this.
|
||||
CVE-2017-9079 https://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
|
||||
Thanks to Andrei Gherzan for a patch
|
||||
@@ -398,23 +247,23 @@ Infrastructure:
|
||||
run arbitrary code as the dbclient user. This could be a problem if scripts
|
||||
or webpages pass untrusted input to the dbclient program.
|
||||
CVE-2016-7406
|
||||
https://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
|
||||
the local dropbearconvert user when parsing malicious key files
|
||||
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
|
||||
particular -m or -c arguments are provided. This could be an issue where
|
||||
dbclient is used in scripts.
|
||||
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
|
||||
running user if compiled with DEBUG_TRACE and running with -v
|
||||
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
|
||||
Beyond Security's SecuriTeam Secure Disclosure www.beyondsecurity.com/ssd.html
|
||||
@@ -460,7 +309,7 @@ Infrastructure:
|
||||
|
||||
- Validate X11 forwarding input. Could allow bypass of authorized_keys command= restrictions,
|
||||
found by github.com/tintinweb. Thanks for Damien Miller for a patch. CVE-2016-3116
|
||||
https://hg.ucc.asn.au/dropbear/rev/a3e8389e01ff
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/a3e8389e01ff
|
||||
|
||||
2015.71 - 3 December 2015
|
||||
|
||||
@@ -741,11 +590,11 @@ kernels, from Steve Dover
|
||||
- Limit the size of decompressed payloads, avoids memory exhaustion denial
|
||||
of service
|
||||
Thanks to Logan Lamb for reporting and investigating it. CVE-2013-4421
|
||||
https://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
|
||||
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
|
||||
|
||||
@@ -848,7 +697,7 @@ though probably will be soon
|
||||
This bug affects releases 0.52 onwards. Ref CVE-2012-0920.
|
||||
Thanks to Danny Fullerton of Mantor Organization for reporting
|
||||
the bug.
|
||||
https://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
|
||||
Thanks to Gustavo Zacarias for the patch
|
||||
@@ -892,7 +741,7 @@ though probably will be soon
|
||||
- New version numbering scheme.
|
||||
|
||||
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
|
||||
|
||||
|
||||
4
INSTALL
4
INSTALL
@@ -6,12 +6,12 @@ Basic Dropbear build instructions:
|
||||
localoptions.h should be located in the build directory if you are
|
||||
building out of tree.
|
||||
|
||||
- If using a Mercurial or Git checkout, "autoconf; autoheader"
|
||||
|
||||
- Configure for your system:
|
||||
./configure (optionally with --disable-zlib or --disable-syslog,
|
||||
or --help for other options)
|
||||
|
||||
(you'll need to first run "autoconf; autoheader" if you edit configure.ac)
|
||||
|
||||
- Compile:
|
||||
|
||||
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
|
||||
|
||||
93
Makefile.in
93
Makefile.in
@@ -20,13 +20,13 @@ LIBTOM_LIBS=@LIBTOM_LIBS@
|
||||
ifeq (@BUNDLED_LIBTOM@, 1)
|
||||
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
|
||||
LIBTOM_CLEAN=ltc-clean ltm-clean
|
||||
CPPFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
|
||||
CFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
|
||||
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
|
||||
endif
|
||||
|
||||
OPTION_HEADERS = default_options_guard.h sysoptions.h
|
||||
ifneq ($(wildcard localoptions.h),)
|
||||
CPPFLAGS+=-DLOCALOPTIONS_H_EXISTS
|
||||
CFLAGS+=-DLOCALOPTIONS_H_EXISTS
|
||||
OPTION_HEADERS += localoptions.h
|
||||
endif
|
||||
|
||||
@@ -35,15 +35,15 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
|
||||
signkey.o rsa.o dbrandom.o \
|
||||
queue.o \
|
||||
atomicio.o compat.o fake-rfc2553.o \
|
||||
ltc_prng.o ecc.o ecdsa.o sk-ecdsa.o crypto_desc.o \
|
||||
curve25519.o ed25519.o sk-ed25519.o \
|
||||
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
|
||||
curve25519.o ed25519.o \
|
||||
dbmalloc.o \
|
||||
gensignkey.o gendss.o genrsa.o gened25519.o
|
||||
|
||||
SVROBJS=svr-kex.o svr-auth.o sshpty.o \
|
||||
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
|
||||
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\
|
||||
svr-tcpfwd.o svr-authpam.o @CRYPTLIB@
|
||||
svr-tcpfwd.o svr-authpam.o
|
||||
|
||||
CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
|
||||
cli-session.o cli-runopts.o cli-chansession.o \
|
||||
@@ -57,14 +57,15 @@ CLISVROBJS=common-session.o packet.o common-algo.o common-kex.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
|
||||
|
||||
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 cli-main.o, ,$(allobjs))
|
||||
allobjs:=$(sort $(allobjs))
|
||||
|
||||
dropbearobjs=$(allobjs) svr-main.o
|
||||
dbclientobjs=$(allobjs) cli-main.o
|
||||
@@ -72,7 +73,6 @@ ifeq (@DROPBEAR_FUZZ@, 1)
|
||||
dropbearconvertobjs=$(allobjs) $(CONVERTOBJS)
|
||||
# CXX only set when fuzzing
|
||||
CXX=@CXX@
|
||||
FUZZ_CLEAN=fuzz-clean
|
||||
else
|
||||
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
|
||||
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
|
||||
@@ -107,8 +107,8 @@ AR=@AR@
|
||||
RANLIB=@RANLIB@
|
||||
STRIP=@STRIP@
|
||||
INSTALL=@INSTALL@
|
||||
CPPFLAGS+=@CPPFLAGS@ -I. -I$(srcdir)
|
||||
CFLAGS+=@CFLAGS@
|
||||
CPPFLAGS=@CPPFLAGS@
|
||||
CFLAGS+=-I. -I$(srcdir) $(CPPFLAGS) @CFLAGS@
|
||||
LIBS+=@LIBS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
|
||||
@@ -119,16 +119,15 @@ STATIC=@STATIC@
|
||||
# whether we're building client, server, or both for the common objects.
|
||||
# evilness so we detect 'dropbear' by itself as a word
|
||||
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdropbearZ, Z$(prog)Z))))
|
||||
CPPFLAGS+= -DDROPBEAR_SERVER
|
||||
CFLAGS+= -DDROPBEAR_SERVER
|
||||
endif
|
||||
ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdbclientZ, Z$(prog)Z))))
|
||||
CPPFLAGS+= -DDROPBEAR_CLIENT
|
||||
CFLAGS+= -DDROPBEAR_CLIENT
|
||||
endif
|
||||
|
||||
# these are exported so that libtomcrypt's makefile will use them
|
||||
export CC
|
||||
export CFLAGS
|
||||
export CPPFLAGS
|
||||
export RANLIB AR STRIP
|
||||
|
||||
ifeq ($(STATIC), 1)
|
||||
@@ -143,7 +142,7 @@ endif
|
||||
|
||||
# for the scp progress meter. The -D doesn't affect anything else.
|
||||
ifeq ($(SCPPROGRESS), 1)
|
||||
CPPFLAGS+=-DPROGRESS_METER
|
||||
CFLAGS+=-DPROGRESS_METER
|
||||
endif
|
||||
|
||||
all: $(TARGETS)
|
||||
@@ -217,7 +216,7 @@ scp: $(SCPOBJS) $(HEADERS) Makefile
|
||||
MULTIOBJS=
|
||||
ifeq ($(MULTI),1)
|
||||
MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
|
||||
CPPFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
|
||||
CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
|
||||
endif
|
||||
|
||||
dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile
|
||||
@@ -237,7 +236,7 @@ $(STATIC_LTC): $(OPTION_HEADERS)
|
||||
$(STATIC_LTM): $(OPTION_HEADERS)
|
||||
$(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:
|
||||
$(MAKE) -C libtomcrypt clean
|
||||
@@ -248,7 +247,7 @@ ltm-clean:
|
||||
sizes: dropbear
|
||||
objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn
|
||||
|
||||
clean: $(LIBTOM_CLEAN) $(FUZZ_CLEAN) thisclean
|
||||
clean: $(LIBTOM_CLEAN) thisclean
|
||||
|
||||
thisclean:
|
||||
-rm -f dropbear$(EXEEXT) dbclient$(EXEEXT) dropbearkey$(EXEEXT) \
|
||||
@@ -266,46 +265,50 @@ tidy:
|
||||
lint:
|
||||
cd $(srcdir); ./dropbear_lint.sh
|
||||
|
||||
check: lint
|
||||
make -C test
|
||||
|
||||
## Fuzzing targets
|
||||
|
||||
# list of fuzz targets
|
||||
FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths \
|
||||
fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths \
|
||||
fuzzer-postauth_nomaths
|
||||
FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519
|
||||
|
||||
FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
|
||||
FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \
|
||||
fuzz/fuzz-sshpacketmutator.o
|
||||
|
||||
list-fuzz-targets:
|
||||
@echo $(FUZZ_TARGETS)
|
||||
|
||||
# fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs
|
||||
fuzzstandalone: FUZZLIB=fuzz/fuzz-harness.o
|
||||
fuzzstandalone: fuzz/fuzz-harness.o fuzz-targets
|
||||
fuzzstandalone: FUZZLIB=fuzz-harness.o
|
||||
fuzzstandalone: fuzz-harness.o fuzz-targets
|
||||
|
||||
# Build all the fuzzers. Usually like
|
||||
# make fuzz-targets FUZZLIB=-lFuzzer.a
|
||||
# the library provides main(). Otherwise
|
||||
# make fuzzstandalone
|
||||
# provides a main in fuzz-harness.c
|
||||
# exclude svr-main.o to avoid duplicate main
|
||||
svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs))
|
||||
|
||||
fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) fuzz-common.o
|
||||
|
||||
# build all the fuzzers. This will require fail to link unless built with
|
||||
# make fuzz-targets FUZZLIB=-lFuzzer.a
|
||||
# or similar - the library provides main().
|
||||
fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
|
||||
|
||||
$(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS)
|
||||
$(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
fuzzer-preauth: fuzzer-preauth.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
# fuzzers that use the custom mutator - these expect a SSH network stream
|
||||
MUTATOR_FUZZERS=fuzzer-client fuzzer-client_nomaths \
|
||||
fuzzer-preauth fuzzer-preauth_nomaths fuzzer-postauth_nomaths
|
||||
fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
# Skip custom mutators for -fsanitize-memory since libfuzzer doesn't initialise memory
|
||||
# Pending fix for it https://github.com/google/oss-fuzz/issues/4605
|
||||
ifeq (,$(findstring fsanitize=memory, $(CFLAGS)))
|
||||
$(MUTATOR_FUZZERS): allobjs += fuzz/fuzz-sshpacketmutator.o
|
||||
endif
|
||||
fuzzer-pubkey: fuzzer-pubkey.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-verify: fuzzer-verify.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-kexdh: fuzzer-kexdh.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-kexecdh: fuzzer-kexecdh.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-kexcurve25519: fuzzer-kexcurve25519.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-%.options: Makefile
|
||||
echo "[libfuzzer]" > $@
|
||||
@@ -324,5 +327,7 @@ fuzz-hostkeys:
|
||||
/usr/bin/xxd -i -a keyd >> hostkeys.c
|
||||
/usr/bin/xxd -i -a keyed25519 >> hostkeys.c
|
||||
|
||||
fuzz-clean:
|
||||
-rm -f fuzz/*.o $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
|
||||
# to make coverity happy?
|
||||
test:
|
||||
true
|
||||
|
||||
|
||||
5
SMALL
5
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
|
||||
|
||||
|
||||
2
auth.h
2
auth.h
@@ -30,6 +30,7 @@
|
||||
#include "chansession.h"
|
||||
|
||||
void svr_authinitialise(void);
|
||||
void cli_authinitialise(void);
|
||||
|
||||
/* Server functions */
|
||||
void recv_msg_userauth_request(void);
|
||||
@@ -125,7 +126,6 @@ struct AuthState {
|
||||
char *pw_passwd;
|
||||
#if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
|
||||
struct PubKeyOptions* pubkey_options;
|
||||
char *pubkey_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
2
bignum.c
2
bignum.c
@@ -100,5 +100,5 @@ void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
|
||||
plus header + some leeway*/
|
||||
buf_putmpint(buf, mp);
|
||||
hash_desc->process(hs, buf->data, buf->len);
|
||||
buf_burn_free(buf);
|
||||
buf_free(buf);
|
||||
}
|
||||
|
||||
39
buffer.c
39
buffer.c
@@ -39,32 +39,44 @@
|
||||
|
||||
/* Create (malloc) a new buffer of size */
|
||||
buffer* buf_new(unsigned int size) {
|
||||
|
||||
buffer* buf;
|
||||
|
||||
if (size > BUF_MAX_SIZE) {
|
||||
dropbear_exit("buf->size too big");
|
||||
}
|
||||
|
||||
buf = (buffer*)m_malloc(sizeof(buffer)+size);
|
||||
buf->data = (unsigned char*)buf + sizeof(buffer);
|
||||
|
||||
if (size > 0) {
|
||||
buf->data = (unsigned char*)buf + sizeof(buffer);
|
||||
} else {
|
||||
buf->data = NULL;
|
||||
}
|
||||
|
||||
buf->size = size;
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* free the buffer's data and the buffer itself */
|
||||
void buf_free(buffer* buf) {
|
||||
|
||||
m_free(buf);
|
||||
}
|
||||
|
||||
/* overwrite the contents of the buffer then free it */
|
||||
void buf_burn_free(buffer* buf) {
|
||||
/* overwrite the contents of the buffer to clear it */
|
||||
void buf_burn(const buffer* buf) {
|
||||
|
||||
m_burn(buf->data, buf->size);
|
||||
m_free(buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* resize a buffer, pos and len will be repositioned if required when
|
||||
* downsizing */
|
||||
buffer* buf_resize(buffer *buf, unsigned int newsize) {
|
||||
|
||||
if (newsize > BUF_MAX_SIZE) {
|
||||
dropbear_exit("buf->size too big");
|
||||
}
|
||||
@@ -127,23 +139,18 @@ void buf_incrwritepos(buffer* buf, unsigned int incr) {
|
||||
}
|
||||
}
|
||||
|
||||
/* increment the position by incr */
|
||||
void buf_incrpos(buffer* buf, unsigned int incr) {
|
||||
/* increment the position by incr, negative values are allowed, to
|
||||
* decrement the pos*/
|
||||
void buf_incrpos(buffer* buf, int incr) {
|
||||
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");
|
||||
}
|
||||
buf->pos += incr;
|
||||
}
|
||||
|
||||
/* decrement the position by decr */
|
||||
void buf_decrpos(buffer* buf, unsigned int decr) {
|
||||
if (decr > buf->pos) {
|
||||
dropbear_exit("Bad buf_decrpos");
|
||||
}
|
||||
buf->pos -= decr;
|
||||
}
|
||||
|
||||
/* Get a byte from the buffer and increment the pos */
|
||||
unsigned char buf_getbyte(buffer* buf) {
|
||||
|
||||
|
||||
5
buffer.h
5
buffer.h
@@ -44,13 +44,12 @@ buffer * buf_new(unsigned int size);
|
||||
/* Possibly returns a new buffer*, like realloc() */
|
||||
buffer * buf_resize(buffer *buf, unsigned int newsize);
|
||||
void buf_free(buffer* buf);
|
||||
void buf_burn_free(buffer* buf);
|
||||
void buf_burn(const buffer* buf);
|
||||
buffer* buf_newcopy(const buffer* buf);
|
||||
void buf_setlen(buffer* buf, unsigned int len);
|
||||
void buf_incrlen(buffer* buf, unsigned int incr);
|
||||
void buf_setpos(buffer* buf, unsigned int pos);
|
||||
void buf_incrpos(buffer* buf, unsigned int incr);
|
||||
void buf_decrpos(buffer* buf, unsigned int decr);
|
||||
void buf_incrpos(buffer* buf, int incr); /* -ve is ok, to go backwards */
|
||||
void buf_incrwritepos(buffer* buf, unsigned int incr);
|
||||
unsigned char buf_getbyte(buffer* buf);
|
||||
unsigned char buf_getbool(buffer* buf);
|
||||
|
||||
25
channel.h
25
channel.h
@@ -28,7 +28,6 @@
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "circbuffer.h"
|
||||
#include "netio.h"
|
||||
|
||||
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
|
||||
#define SSH_OPEN_CONNECT_FAILED 2
|
||||
@@ -42,6 +41,13 @@
|
||||
|
||||
struct ChanType;
|
||||
|
||||
enum dropbear_channel_prio {
|
||||
DROPBEAR_CHANNEL_PRIO_INTERACTIVE, /* pty shell, x11 */
|
||||
DROPBEAR_CHANNEL_PRIO_UNKNOWABLE, /* tcp - can't know what's being forwarded */
|
||||
DROPBEAR_CHANNEL_PRIO_BULK, /* the rest - probably scp or something */
|
||||
DROPBEAR_CHANNEL_PRIO_EARLY, /* channel is still being set up */
|
||||
};
|
||||
|
||||
struct Channel {
|
||||
|
||||
unsigned int index; /* the local channel index */
|
||||
@@ -54,9 +60,6 @@ struct Channel {
|
||||
int readfd; /* read from insecure side, written to wire */
|
||||
int errfd; /* used like writefd or readfd, depending if it's client or server.
|
||||
Doesn't exactly belong here, but is cleaner here */
|
||||
int bidir_fd; /* a boolean indicating that writefd/readfd are the same
|
||||
file descriptor (bidirectional), such as a network socket or PTY.
|
||||
That is handled differently when closing FDs */
|
||||
circbuffer *writebuf; /* data from the wire, for local consumption. Can be
|
||||
initially NULL */
|
||||
circbuffer *extrabuf; /* extended-data for the program - used like writebuf
|
||||
@@ -65,9 +68,6 @@ struct Channel {
|
||||
/* whether close/eof messages have been exchanged */
|
||||
int sent_close, recv_close;
|
||||
int recv_eof, sent_eof;
|
||||
/* once flushing is set, readfd will close once no more data is available
|
||||
(not waiting for EOF) */
|
||||
int flushing;
|
||||
|
||||
struct dropbear_progress_connection *conn_pending;
|
||||
int initconn; /* used for TCP forwarding, whether the channel has been
|
||||
@@ -77,22 +77,25 @@ struct Channel {
|
||||
for this channel (and are awaiting a confirmation
|
||||
or failure). */
|
||||
|
||||
int flushing;
|
||||
|
||||
/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
|
||||
void (*read_mangler)(const struct Channel*, const unsigned char* bytes, int *len);
|
||||
|
||||
const struct ChanType* type;
|
||||
|
||||
enum dropbear_prio prio;
|
||||
enum dropbear_channel_prio prio;
|
||||
};
|
||||
|
||||
struct ChanType {
|
||||
|
||||
int sepfds; /* Whether this channel has separate pipes for in/out or not */
|
||||
const char *name;
|
||||
/* Sets up the channel */
|
||||
int (*inithandler)(struct Channel*);
|
||||
/* Called to check whether a channel should close, separately from the FD being EOF.
|
||||
/* Called to check whether a channel should close, separately from the FD being closed.
|
||||
Used for noticing process exiting */
|
||||
int (*check_close)(struct Channel*);
|
||||
int (*check_close)(const struct Channel*);
|
||||
/* Handler for ssh_msg_channel_request */
|
||||
void (*reqhandler)(struct Channel*);
|
||||
/* Called prior to sending ssh_msg_channel_close, used for sending exit status */
|
||||
@@ -101,7 +104,7 @@ struct ChanType {
|
||||
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 chaninitialise(const struct ChanType *chantypes[]);
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
static int new_agent_chan(struct Channel * channel);
|
||||
|
||||
const struct ChanType cli_chan_agent = {
|
||||
0, /* sepfds */
|
||||
"auth-agent@openssh.com",
|
||||
new_agent_chan,
|
||||
NULL,
|
||||
@@ -93,7 +94,6 @@ static int new_agent_chan(struct Channel * channel) {
|
||||
|
||||
channel->readfd = fd;
|
||||
channel->writefd = fd;
|
||||
channel->bidir_fd = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
16
cli-auth.c
16
cli-auth.c
@@ -32,6 +32,12 @@
|
||||
#include "packet.h"
|
||||
#include "runopts.h"
|
||||
|
||||
void cli_authinitialise() {
|
||||
|
||||
memset(&ses.authstate, 0, sizeof(ses.authstate));
|
||||
}
|
||||
|
||||
|
||||
/* Send a "none" auth request to get available methods */
|
||||
void cli_auth_getmethods() {
|
||||
TRACE(("enter cli_auth_getmethods"))
|
||||
@@ -82,11 +88,6 @@ void recv_msg_userauth_banner() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_opts.quiet) {
|
||||
TRACE(("not showing banner"))
|
||||
return;
|
||||
}
|
||||
|
||||
banner = buf_getstring(ses.payload, &bannerlen);
|
||||
buf_eatstring(ses.payload); /* The language string */
|
||||
|
||||
@@ -265,10 +266,7 @@ void recv_msg_userauth_success() {
|
||||
/* This function can validly get called multiple times
|
||||
if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
|
||||
|
||||
DEBUG1(("received msg_userauth_success"))
|
||||
if (cli_opts.disable_trivial_auth && cli_ses.is_trivial_auth) {
|
||||
dropbear_exit("trivial authentication not allowed");
|
||||
}
|
||||
TRACE(("received msg_userauth_success"))
|
||||
/* Note: in delayed-zlib mode, setting authdone here
|
||||
* will enable compression in the transport layer */
|
||||
ses.authstate.authdone = 1;
|
||||
|
||||
@@ -115,7 +115,6 @@ void recv_msg_userauth_info_request() {
|
||||
|
||||
for (i = 0; i < num_prompts; i++) {
|
||||
unsigned int response_len = 0;
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
prompt = buf_getstring(ses.payload, NULL);
|
||||
cleantext(prompt);
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ void cli_auth_password() {
|
||||
char* password = NULL;
|
||||
char prompt[80];
|
||||
|
||||
DEBUG1(("enter cli_auth_password"))
|
||||
TRACE(("enter cli_auth_password"))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
snprintf(prompt, sizeof(prompt), "%s@%s's password: ",
|
||||
@@ -155,7 +155,7 @@ void cli_auth_password() {
|
||||
|
||||
encrypt_packet();
|
||||
m_burn(password, strlen(password));
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
|
||||
TRACE(("leave cli_auth_password"))
|
||||
}
|
||||
#endif /* DROPBEAR_CLI_PASSWORD_AUTH */
|
||||
|
||||
@@ -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,
|
||||
const buffer *data_buf) {
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
/* TODO: rsa-sha256 agent */
|
||||
// TODO: rsa-sha256 agent
|
||||
if (key->source == SIGNKEY_SOURCE_AGENT) {
|
||||
/* Format the agent signature ourselves, as buf_put_sign would. */
|
||||
buffer *sigblob;
|
||||
@@ -147,7 +147,7 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype,
|
||||
buffer* sigbuf = NULL;
|
||||
enum signkey_type keytype = signkey_type_from_signature(sigtype);
|
||||
|
||||
DEBUG1(("enter send_msg_userauth_pubkey %s", signature_name_from_type(sigtype, NULL)))
|
||||
TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
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);
|
||||
cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf);
|
||||
buf_free(sigbuf); /* Nothing confidential in the buffer */
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
}
|
||||
|
||||
encrypt_packet();
|
||||
|
||||
@@ -46,6 +46,7 @@ static int cli_init_netcat(struct Channel *channel);
|
||||
static void cli_tty_setup(void);
|
||||
|
||||
const struct ChanType clichansess = {
|
||||
0, /* sepfds */
|
||||
"session", /* name */
|
||||
cli_initchansess, /* inithandler */
|
||||
NULL, /* checkclosehandler */
|
||||
@@ -343,11 +344,11 @@ static int cli_init_stdpipe_sess(struct Channel *channel) {
|
||||
setnonblocking(STDERR_FILENO);
|
||||
|
||||
channel->extrabuf = cbuf_new(opts.recv_window);
|
||||
channel->bidir_fd = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_init_netcat(struct Channel *channel) {
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
return cli_init_stdpipe_sess(channel);
|
||||
}
|
||||
|
||||
@@ -360,9 +361,12 @@ static int cli_initchansess(struct Channel *channel) {
|
||||
cli_setup_agent(channel);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cli_opts.wantpty) {
|
||||
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);
|
||||
@@ -371,7 +375,7 @@ static int cli_initchansess(struct Channel *channel) {
|
||||
cli_tty_setup();
|
||||
channel->read_mangler = cli_escape_handler;
|
||||
cli_ses.last_char = '\r';
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
@@ -379,6 +383,7 @@ static int cli_initchansess(struct Channel *channel) {
|
||||
#if DROPBEAR_CLI_NETCAT
|
||||
|
||||
static const struct ChanType cli_chan_netcat = {
|
||||
0, /* sepfds */
|
||||
"direct-tcpip",
|
||||
cli_init_netcat, /* inithandler */
|
||||
NULL,
|
||||
|
||||
15
cli-kex.c
15
cli-kex.c
@@ -46,13 +46,6 @@ void send_msg_kexdh_init() {
|
||||
TRACE(("send_msg_kexdh_init()"))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
|
||||
switch (ses.newkeys->algo_kex->mode) {
|
||||
#if DROPBEAR_NORMAL_DH
|
||||
@@ -105,12 +98,6 @@ void recv_msg_kexdh_reply() {
|
||||
unsigned char* keyblob = NULL;
|
||||
|
||||
TRACE(("enter recv_msg_kexdh_reply"))
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cli_ses.kex_state != KEXDH_INIT_SENT) {
|
||||
dropbear_exit("Received out-of-order kexdhreply");
|
||||
@@ -371,7 +358,7 @@ static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen)
|
||||
|
||||
if (ret == DROPBEAR_SUCCESS) {
|
||||
/* Good matching key */
|
||||
DEBUG1(("server match %s", fingerprint))
|
||||
TRACE(("good matching key"))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
73
cli-main.c
73
cli-main.c
@@ -31,7 +31,9 @@
|
||||
#include "dbrandom.h"
|
||||
#include "crypto_desc.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
|
||||
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;
|
||||
struct dropbear_progress_connection *progress = NULL;
|
||||
pid_t proxy_cmd_pid = 0;
|
||||
|
||||
_dropbear_exit = cli_dropbear_exit;
|
||||
_dropbear_log = cli_dropbear_log;
|
||||
@@ -65,17 +66,14 @@ int main(int argc, char ** argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cli_opts.bind_address) {
|
||||
DEBUG1(("connect to: user=%s host=%s/%s bind_address=%s:%s", cli_opts.username,
|
||||
cli_opts.remotehost, cli_opts.remoteport, cli_opts.bind_address, cli_opts.bind_port))
|
||||
} else {
|
||||
DEBUG1(("connect to: user=%s host=%s/%s",cli_opts.username,cli_opts.remotehost,cli_opts.remoteport))
|
||||
}
|
||||
TRACE(("user='%s' host='%s' port='%s' bind_address='%s' bind_port='%s'", cli_opts.username,
|
||||
cli_opts.remotehost, cli_opts.remoteport, cli_opts.bind_address, cli_opts.bind_port))
|
||||
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||
dropbear_exit("signal() error");
|
||||
}
|
||||
|
||||
pid_t proxy_cmd_pid = 0;
|
||||
#if DROPBEAR_CLI_PROXYCMD
|
||||
if (cli_opts.proxycmd) {
|
||||
cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid);
|
||||
@@ -88,9 +86,8 @@ int main(int argc, char ** argv) {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
||||
cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port,
|
||||
DROPBEAR_PRIO_LOWDELAY);
|
||||
progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
||||
cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port);
|
||||
sock_in = sock_out = -1;
|
||||
}
|
||||
|
||||
@@ -101,6 +98,58 @@ int main(int argc, char ** argv) {
|
||||
}
|
||||
#endif /* DBMULTI stuff */
|
||||
|
||||
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
char exitmsg[150];
|
||||
char fullmsg[300];
|
||||
|
||||
/* Note that exit message must be rendered before session cleanup */
|
||||
|
||||
/* Render the formatted exit message */
|
||||
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
|
||||
TRACE(("Exited, cleaning up: %s", exitmsg))
|
||||
|
||||
/* Add the prefix depending on session/auth state */
|
||||
if (!ses.init_done) {
|
||||
snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
|
||||
} else {
|
||||
snprintf(fullmsg, sizeof(fullmsg),
|
||||
"Connection to %s@%s:%s exited: %s",
|
||||
cli_opts.username, cli_opts.remotehost,
|
||||
cli_opts.remoteport, exitmsg);
|
||||
}
|
||||
|
||||
/* Do the cleanup first, since then the terminal will be reset */
|
||||
session_cleanup();
|
||||
/* Avoid printing onwards from terminal cruft */
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
dropbear_log(LOG_INFO, "%s", fullmsg);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static void cli_dropbear_log(int priority,
|
||||
const char* format, va_list param) {
|
||||
|
||||
char printbuf[1024];
|
||||
const char *name;
|
||||
|
||||
name = cli_opts.progname;
|
||||
if (!name) {
|
||||
name = "dbclient";
|
||||
}
|
||||
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
|
||||
#ifndef DISABLE_SYSLOG
|
||||
if (opts.usingsyslog) {
|
||||
syslog(priority, "%s", printbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "%s: %s\n", name, printbuf);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
static void exec_proxy_cmd(const void *user_data_cmd) {
|
||||
const char *cmd = user_data_cmd;
|
||||
char *usershell;
|
||||
@@ -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,
|
||||
sock_out, sock_in, NULL, pid_out);
|
||||
DEBUG1(("cmd: %s pid=%d", ex_cmd,*pid_out))
|
||||
m_free(ex_cmd);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Failed running proxy command");
|
||||
@@ -151,5 +199,4 @@ static void kill_proxy_sighandler(int UNUSED(signo)) {
|
||||
kill_proxy_command();
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_CLI_PROXYCMD */
|
||||
|
||||
123
cli-runopts.c
123
cli-runopts.c
@@ -62,7 +62,6 @@ static void printhelp() {
|
||||
"-T Don't allocate a pty\n"
|
||||
"-N Don't run a remote command\n"
|
||||
"-f Run in background after auth\n"
|
||||
"-q quiet, don't show remote banner\n"
|
||||
"-y Always accept remote host key if unknown\n"
|
||||
"-y -y Don't perform any remote host key checking (caution)\n"
|
||||
"-s Request a subsystem (use by external sftp)\n"
|
||||
@@ -80,7 +79,7 @@ static void printhelp() {
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
"-R <[listenaddress:]listenport:remotehost:remoteport> Remote port forwarding\n"
|
||||
#endif
|
||||
"-W <receive_window_buffer> (default %d, larger may be faster, max 10MB)\n"
|
||||
"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
|
||||
"-K <keepalive> (0 is never, default %d)\n"
|
||||
"-I <idle_timeout> (0 is never, default %d)\n"
|
||||
#if DROPBEAR_CLI_NETCAT
|
||||
@@ -96,7 +95,7 @@ static void printhelp() {
|
||||
"-b [bind_address][:bind_port]\n"
|
||||
"-V Version\n"
|
||||
#if DEBUG_TRACE
|
||||
"-v verbose (repeat for more verbose)\n"
|
||||
"-v verbose (compiled with DEBUG_TRACE)\n"
|
||||
#endif
|
||||
,DROPBEAR_VERSION, cli_opts.progname,
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
@@ -142,7 +141,6 @@ void cli_getopts(int argc, char ** argv) {
|
||||
cli_opts.username = NULL;
|
||||
cli_opts.cmd = NULL;
|
||||
cli_opts.no_cmd = 0;
|
||||
cli_opts.quiet = 0;
|
||||
cli_opts.backgrounded = 0;
|
||||
cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
|
||||
cli_opts.always_accept_key = 0;
|
||||
@@ -154,7 +152,6 @@ void cli_getopts(int argc, char ** argv) {
|
||||
#if DROPBEAR_CLI_ANYTCPFWD
|
||||
cli_opts.exit_on_fwd_failure = 0;
|
||||
#endif
|
||||
cli_opts.disable_trivial_auth = 0;
|
||||
#if DROPBEAR_CLI_LOCALTCPFWD
|
||||
cli_opts.localfwds = list_new();
|
||||
opts.listen_fwd_all = 0;
|
||||
@@ -216,9 +213,6 @@ void cli_getopts(int argc, char ** argv) {
|
||||
}
|
||||
cli_opts.always_accept_key = 1;
|
||||
break;
|
||||
case 'q': /* quiet */
|
||||
cli_opts.quiet = 1;
|
||||
break;
|
||||
case 'p': /* remoteport */
|
||||
next = (char**)&cli_opts.remoteport;
|
||||
break;
|
||||
@@ -302,7 +296,7 @@ void cli_getopts(int argc, char ** argv) {
|
||||
#endif
|
||||
#if DEBUG_TRACE
|
||||
case 'v':
|
||||
debug_trace++;
|
||||
debug_trace = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'F':
|
||||
@@ -419,7 +413,7 @@ void cli_getopts(int argc, char ** argv) {
|
||||
|
||||
/* And now a few sanity checks and setup */
|
||||
|
||||
#if DROPBEAR_CLI_PROXYCMD
|
||||
#if DROPBEAR_CLI_PROXYCMD
|
||||
if (cli_opts.proxycmd) {
|
||||
/* To match the common path of m_freeing it */
|
||||
cli_opts.proxycmd = m_strdup(cli_opts.proxycmd);
|
||||
@@ -431,10 +425,14 @@ void cli_getopts(int argc, char ** argv) {
|
||||
}
|
||||
|
||||
if (bind_arg) {
|
||||
if (split_address_port(bind_arg,
|
||||
&cli_opts.bind_address, &cli_opts.bind_port)
|
||||
== DROPBEAR_FAILURE) {
|
||||
dropbear_exit("Bad -b argument");
|
||||
/* split [host][:port] */
|
||||
char *port = strrchr(bind_arg, ':');
|
||||
if (port) {
|
||||
cli_opts.bind_port = m_strdup(port+1);
|
||||
*port = '\0';
|
||||
}
|
||||
if (strlen(bind_arg) > 0) {
|
||||
cli_opts.bind_address = m_strdup(bind_arg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,9 +450,12 @@ void cli_getopts(int argc, char ** argv) {
|
||||
&& cli_opts.no_cmd == 0) {
|
||||
dropbear_exit("Command required for -f");
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
unsigned int val;
|
||||
@@ -478,17 +479,6 @@ void cli_getopts(int argc, char ** argv) {
|
||||
}
|
||||
#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)
|
||||
{
|
||||
char *expand_path = expand_homedir_path(DROPBEAR_DEFAULT_CLI_AUTHKEY);
|
||||
@@ -497,6 +487,14 @@ void cli_getopts(int argc, char ** argv) {
|
||||
}
|
||||
#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
|
||||
@@ -527,11 +525,11 @@ static void loadidentityfile(const char* filename, int warnfail) {
|
||||
static char*
|
||||
multihop_passthrough_args() {
|
||||
char *ret;
|
||||
unsigned int len, total;
|
||||
int total;
|
||||
unsigned int len = 0;
|
||||
m_list_elem *iter;
|
||||
/* Fill out -i, -y, -W options that make sense for all
|
||||
* the intermediate processes */
|
||||
len = 30; /* space for "-q -y -y -W <size>\0" */
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
|
||||
{
|
||||
@@ -539,40 +537,45 @@ multihop_passthrough_args() {
|
||||
len += 3 + strlen(key->filename);
|
||||
}
|
||||
#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);
|
||||
total = 0;
|
||||
|
||||
if (cli_opts.quiet) {
|
||||
total += m_snprintf(ret+total, len-total, "-q ");
|
||||
if (cli_opts.no_hostkey_check)
|
||||
{
|
||||
int written = snprintf(ret+total, len-total, "-y -y ");
|
||||
total += written;
|
||||
}
|
||||
else if (cli_opts.always_accept_key)
|
||||
{
|
||||
int written = snprintf(ret+total, len-total, "-y ");
|
||||
total += written;
|
||||
}
|
||||
|
||||
if (cli_opts.no_hostkey_check) {
|
||||
total += m_snprintf(ret+total, len-total, "-y -y ");
|
||||
} else if (cli_opts.always_accept_key) {
|
||||
total += m_snprintf(ret+total, len-total, "-y ");
|
||||
}
|
||||
|
||||
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 (opts.recv_window != DEFAULT_RECV_WINDOW)
|
||||
{
|
||||
int written = snprintf(ret+total, len-total, "-W %u ", opts.recv_window);
|
||||
total += written;
|
||||
}
|
||||
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
|
||||
{
|
||||
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 */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -586,9 +589,6 @@ multihop_passthrough_args() {
|
||||
* dbclient -J "dbclient -B madako:22 wrt" madako
|
||||
* etc for as many hosts as we want.
|
||||
*
|
||||
* Note that "-J" arguments aren't actually used, instead
|
||||
* below sets cli_opts.proxycmd directly.
|
||||
*
|
||||
* Ports for hosts can be specified as host/port.
|
||||
*/
|
||||
static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
|
||||
@@ -607,7 +607,7 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
|
||||
&& strchr(cli_opts.username, '@')) {
|
||||
unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
|
||||
hostbuf = m_malloc(len);
|
||||
m_snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
|
||||
snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
|
||||
} else {
|
||||
hostbuf = m_strdup(orighostarg);
|
||||
}
|
||||
@@ -630,18 +630,19 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
|
||||
/* Set up the proxycmd */
|
||||
unsigned int cmd_len = 0;
|
||||
char *passthrough_args = multihop_passthrough_args();
|
||||
if (cli_opts.proxycmd) {
|
||||
dropbear_exit("-J can't be used with multihop mode");
|
||||
}
|
||||
if (cli_opts.remoteport == NULL) {
|
||||
cli_opts.remoteport = "22";
|
||||
}
|
||||
cmd_len = strlen(argv0) + strlen(remainder)
|
||||
cmd_len = strlen(argv0) + strlen(remainder)
|
||||
+ strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport)
|
||||
+ strlen(passthrough_args)
|
||||
+ 30;
|
||||
/* replace proxycmd. old -J arguments have been copied
|
||||
to passthrough_args */
|
||||
cli_opts.proxycmd = m_realloc(cli_opts.proxycmd, cmd_len);
|
||||
m_snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s",
|
||||
argv0, cli_opts.remotehost, cli_opts.remoteport,
|
||||
cli_opts.proxycmd = m_malloc(cmd_len);
|
||||
snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s",
|
||||
argv0, cli_opts.remotehost, cli_opts.remoteport,
|
||||
passthrough_args, remainder);
|
||||
#ifndef DISABLE_ZLIB
|
||||
/* The stream will be incompressible since it's encrypted. */
|
||||
@@ -888,7 +889,6 @@ static void add_extendedopt(const char* origstr) {
|
||||
#if DROPBEAR_CLI_ANYTCPFWD
|
||||
"\tExitOnForwardFailure\n"
|
||||
#endif
|
||||
"\tDisableTrivialAuth\n"
|
||||
#ifndef DISABLE_SYSLOG
|
||||
"\tUseSyslog\n"
|
||||
#endif
|
||||
@@ -916,10 +916,5 @@ static void add_extendedopt(const char* origstr) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -102,9 +102,6 @@ void cli_connected(int result, int sock, void* userdata, const char *errstring)
|
||||
dropbear_exit("Connect failed: %s", errstring);
|
||||
}
|
||||
myses->sock_in = myses->sock_out = sock;
|
||||
DEBUG1(("cli_connected"))
|
||||
ses.socket_prio = DROPBEAR_PRIO_NORMAL;
|
||||
/* switches to lowdelay */
|
||||
update_channel_prio();
|
||||
}
|
||||
|
||||
@@ -168,7 +165,6 @@ static void cli_session_init(pid_t proxy_cmd_pid) {
|
||||
/* Auth */
|
||||
cli_ses.lastprivkey = NULL;
|
||||
cli_ses.lastauthtype = 0;
|
||||
cli_ses.is_trivial_auth = 1;
|
||||
|
||||
/* For printing "remote host closed" for the user */
|
||||
ses.remoteclosed = cli_remoteclosed;
|
||||
@@ -249,9 +245,6 @@ static void cli_sessionloop() {
|
||||
/* We've got the transport layer sorted, we now need to request
|
||||
* userauth */
|
||||
send_msg_service_request(SSH_SERVICE_USERAUTH);
|
||||
/* We aren't using any "implicit server authentication" methods,
|
||||
so don't need to wait for a response for SSH_SERVICE_USERAUTH
|
||||
before sending the auth messages (rfc4253 10) */
|
||||
cli_auth_getmethods();
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: sent userauth methods req"))
|
||||
@@ -359,11 +352,6 @@ static void cli_session_cleanup(void) {
|
||||
(void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
|
||||
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
|
||||
|
||||
/* Don't leak */
|
||||
m_close(cli_ses.stdincopy);
|
||||
m_close(cli_ses.stdoutcopy);
|
||||
m_close(cli_ses.stderrcopy);
|
||||
|
||||
cli_tty_cleanup();
|
||||
if (cli_ses.server_sig_algs) {
|
||||
buf_free(cli_ses.server_sig_algs);
|
||||
@@ -415,75 +403,7 @@ void cleantext(char* dirtytext) {
|
||||
}
|
||||
|
||||
static void recv_msg_global_request_cli(void) {
|
||||
unsigned int wantreply = 0;
|
||||
|
||||
buf_eatstring(ses.payload);
|
||||
wantreply = buf_getbool(ses.payload);
|
||||
|
||||
TRACE(("recv_msg_global_request_cli: want_reply: %u", wantreply));
|
||||
|
||||
if (wantreply) {
|
||||
/* Send a proper rejection */
|
||||
send_msg_request_failure();
|
||||
}
|
||||
TRACE(("recv_msg_global_request_cli"))
|
||||
/* 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);
|
||||
|
||||
const struct ChanType cli_chan_tcpremote = {
|
||||
1, /* sepfds */
|
||||
"forwarded-tcpip",
|
||||
newtcpforwarded,
|
||||
NULL,
|
||||
@@ -50,8 +51,9 @@ static int cli_localtcp(const char* listenaddr,
|
||||
const char* remoteaddr,
|
||||
unsigned int remoteport);
|
||||
static const struct ChanType cli_chan_tcplocal = {
|
||||
1, /* sepfds */
|
||||
"direct-tcpip",
|
||||
NULL,
|
||||
tcp_prio_inithandler,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -271,11 +273,12 @@ static int newtcpforwarded(struct Channel * channel) {
|
||||
origaddr, origport);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
|
||||
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done,
|
||||
channel, NULL, NULL, DROPBEAR_PRIO_NORMAL);
|
||||
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel, NULL, NULL);
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
|
||||
err = SSH_OPEN_IN_PROGRESS;
|
||||
|
||||
out:
|
||||
|
||||
@@ -64,6 +64,14 @@ static const struct dropbear_cipher dropbear_aes256 =
|
||||
static const struct dropbear_cipher dropbear_aes128 =
|
||||
{&aes_desc, 16, 16};
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH256
|
||||
static const struct dropbear_cipher dropbear_twofish256 =
|
||||
{&twofish_desc, 32, 16};
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH128
|
||||
static const struct dropbear_cipher dropbear_twofish128 =
|
||||
{&twofish_desc, 16, 16};
|
||||
#endif
|
||||
#if DROPBEAR_3DES
|
||||
static const struct dropbear_cipher dropbear_3des =
|
||||
{&des3_desc, 24, 8};
|
||||
@@ -148,6 +156,15 @@ algo_type sshciphers[] = {
|
||||
#if DROPBEAR_AES256
|
||||
{"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH_CTR
|
||||
/* twofish ctr is conditional as it hasn't been tested for interoperability, see options.h */
|
||||
#if DROPBEAR_TWOFISH256
|
||||
{"twofish256-ctr", 0, &dropbear_twofish256, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH128
|
||||
{"twofish128-ctr", 0, &dropbear_twofish128, 1, &dropbear_mode_ctr},
|
||||
#endif
|
||||
#endif /* DROPBEAR_TWOFISH_CTR */
|
||||
#endif /* DROPBEAR_ENABLE_CTR_MODE */
|
||||
|
||||
#if DROPBEAR_ENABLE_CBC_MODE
|
||||
@@ -157,6 +174,13 @@ algo_type sshciphers[] = {
|
||||
#if DROPBEAR_AES256
|
||||
{"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH256
|
||||
{"twofish256-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
|
||||
{"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH128
|
||||
{"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc},
|
||||
#endif
|
||||
#endif /* DROPBEAR_ENABLE_CBC_MODE */
|
||||
|
||||
#if DROPBEAR_3DES
|
||||
@@ -215,9 +239,6 @@ algo_type ssh_nocompress[] = {
|
||||
algo_type sigalgs[] = {
|
||||
#if DROPBEAR_ED25519
|
||||
{"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL},
|
||||
#if DROPBEAR_SK_ED25519
|
||||
{"sk-ssh-ed25519@openssh.com", DROPBEAR_SIGNATURE_SK_ED25519, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
#if DROPBEAR_ECC_256
|
||||
@@ -229,9 +250,6 @@ algo_type sigalgs[] = {
|
||||
#if DROPBEAR_ECC_521
|
||||
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
{"sk-ecdsa-sha2-nistp256@openssh.com", DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_RSA
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
@@ -341,7 +359,7 @@ void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall
|
||||
len = buf->pos - startpos - 4;
|
||||
buf_setpos(buf, startpos);
|
||||
buf_putint(buf, len);
|
||||
TRACE(("algolist add %d '%.*s'", len, len, buf_getptr(buf, len)))
|
||||
TRACE(("algolist add %d '%*s'", len, len, buf_getptr(buf, len)))
|
||||
buf_incrwritepos(buf, len);
|
||||
}
|
||||
|
||||
@@ -363,7 +381,7 @@ static void get_algolist(char* algolist, unsigned int algolist_len,
|
||||
}
|
||||
if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
|
||||
*ret_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ret_list will contain a list of the strings parsed out.
|
||||
We will have at least one string (even if it's just "") */
|
||||
@@ -374,11 +392,11 @@ static void get_algolist(char* algolist, unsigned int algolist_len,
|
||||
/* someone is trying something strange */
|
||||
*ret_count = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (algolist[i] == ',') {
|
||||
if (*ret_count >= max_count) {
|
||||
dropbear_exit("Too many remote algorithms");
|
||||
/* Too many */
|
||||
*ret_count = 0;
|
||||
return;
|
||||
}
|
||||
@@ -445,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" */
|
||||
algolist = buf_getstring(buf, &len);
|
||||
DEBUG3(("buf_match_algo: %s", algolist))
|
||||
TRACE(("buf_match_algo: %s", algolist))
|
||||
remotecount = MAX_PROPOSED_ALGO;
|
||||
get_algolist(algolist, len, remotenames, &remotecount);
|
||||
|
||||
|
||||
@@ -154,6 +154,7 @@ static struct Channel* newchannel(unsigned int remotechan,
|
||||
newchan->readfd = FD_UNINIT;
|
||||
newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
|
||||
newchan->await_open = 0;
|
||||
newchan->flushing = 0;
|
||||
|
||||
newchan->writebuf = cbuf_new(opts.recv_window);
|
||||
newchan->recvwindow = opts.recv_window;
|
||||
@@ -162,7 +163,7 @@ static struct Channel* newchannel(unsigned int remotechan,
|
||||
newchan->recvdonelen = 0;
|
||||
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.chancount++;
|
||||
@@ -283,29 +284,24 @@ static void check_close(struct Channel *channel) {
|
||||
channel->writebuf ? cbuf_getused(channel->writebuf) : 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
|
||||
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. */
|
||||
if (!channel->type->check_close
|
||||
if (!channel->type->check_close
|
||||
|| channel->sent_close
|
||||
|| channel->type->check_close(channel)) {
|
||||
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->sent_close) {
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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 (!channel->sent_eof
|
||||
&& 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
|
||||
* it is important that the channel reference isn't used after a call to this
|
||||
* 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;
|
||||
|
||||
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)
|
||||
{
|
||||
channel->readfd = channel->writefd = sock;
|
||||
channel->bidir_fd = 1;
|
||||
channel->conn_pending = NULL;
|
||||
send_msg_channel_open_confirmation(channel, channel->recvwindow,
|
||||
channel->recvmaxpacket);
|
||||
@@ -361,9 +373,9 @@ void channel_connect_done(int result, int sock, void* user_data, const char* err
|
||||
else
|
||||
{
|
||||
send_msg_channel_open_failure(channel->remotechan,
|
||||
SSH_OPEN_CONNECT_FAILED, errstring, "");
|
||||
SSH_OPEN_CONNECT_FAILED, "", "");
|
||||
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;
|
||||
|
||||
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"))
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
send_msg_channel_open_confirmation(channel, channel->recvwindow,
|
||||
@@ -968,6 +990,8 @@ failure:
|
||||
|
||||
cleanup:
|
||||
m_free(type);
|
||||
|
||||
update_channel_prio();
|
||||
|
||||
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;
|
||||
|
||||
if (channel->bidir_fd) {
|
||||
if (channel->type->sepfds) {
|
||||
TRACE(("SHUTDOWN(%d, %d)", fd, how))
|
||||
shutdown(fd, how);
|
||||
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
|
||||
* 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) {
|
||||
TRACE(("CLOSE (finally) of %d", 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;
|
||||
ses.maxfd = MAX(ses.maxfd, fd);
|
||||
chan->bidir_fd = 1;
|
||||
|
||||
chan->await_open = 1;
|
||||
|
||||
@@ -1129,7 +1152,7 @@ int send_msg_channel_open_init(int fd, const struct ChanType *type) {
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Confirmation that our channel open request was
|
||||
/* Confirmation that our channel open request (for forwardings) was
|
||||
* successful*/
|
||||
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();
|
||||
|
||||
|
||||
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
|
||||
* 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.
|
||||
* 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 */
|
||||
static void hashkeys(unsigned char *out, unsigned int outlen,
|
||||
@@ -306,7 +306,8 @@ static void gen_new_keys() {
|
||||
mp_clear(ses.dh_K);
|
||||
m_free(ses.dh_K);
|
||||
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;
|
||||
|
||||
if (IS_DROPBEAR_CLIENT) {
|
||||
@@ -486,12 +487,6 @@ void recv_msg_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 */
|
||||
local_ident_len = strlen(LOCAL_IDENT);
|
||||
remote_ident_len = strlen(ses.remoteident);
|
||||
@@ -802,7 +797,8 @@ void finish_kexhashbuf(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
buf_burn_free(ses.kexhashbuf);
|
||||
buf_burn(ses.kexhashbuf);
|
||||
buf_free(ses.kexhashbuf);
|
||||
m_burn(&hs, sizeof(hash_state));
|
||||
ses.kexhashbuf = NULL;
|
||||
|
||||
@@ -867,7 +863,7 @@ static void read_kex_algos() {
|
||||
goto error;
|
||||
}
|
||||
TRACE(("kexguess2 %d", kexguess2))
|
||||
DEBUG3(("kex algo %s", algo->name))
|
||||
TRACE(("kex algo %s", algo->name))
|
||||
ses.newkeys->algo_kex = algo->data;
|
||||
|
||||
/* server_host_key_algorithms */
|
||||
@@ -877,7 +873,7 @@ static void read_kex_algos() {
|
||||
erralgo = "hostkey";
|
||||
goto error;
|
||||
}
|
||||
DEBUG2(("hostkey algo %s", algo->name))
|
||||
TRACE(("signature algo %s", algo->name))
|
||||
ses.newkeys->algo_signature = algo->val;
|
||||
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";
|
||||
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 */
|
||||
s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL);
|
||||
@@ -895,7 +891,7 @@ static void read_kex_algos() {
|
||||
erralgo = "enc s->c";
|
||||
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 */
|
||||
c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
|
||||
@@ -908,7 +904,7 @@ static void read_kex_algos() {
|
||||
erralgo = "mac c->s";
|
||||
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 */
|
||||
s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
|
||||
@@ -921,7 +917,7 @@ static void read_kex_algos() {
|
||||
erralgo = "mac s->c";
|
||||
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 */
|
||||
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";
|
||||
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 */
|
||||
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";
|
||||
goto error;
|
||||
}
|
||||
DEBUG2(("comp s2c is %s", s2c_comp_algo->name))
|
||||
TRACE(("hash s2c is %s", s2c_comp_algo->name))
|
||||
|
||||
/* languages_client_to_server */
|
||||
buf_eatstring(ses.payload);
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -35,7 +35,7 @@ runopts opts; /* GLOBAL */
|
||||
|
||||
/* returns success or failure, and the keytype in *type. If we want
|
||||
* 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) {
|
||||
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
@@ -57,7 +57,8 @@ int readhostkey(const char * filename, sign_key * hostkey,
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
out:
|
||||
|
||||
buf_burn_free(buf);
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -100,74 +101,4 @@ void print_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);
|
||||
}
|
||||
|
||||
ses.socket_prio = DROPBEAR_PRIO_NORMAL;
|
||||
ses.socket_prio = DROPBEAR_PRIO_DEFAULT;
|
||||
/* Sets it to lowdelay */
|
||||
update_channel_prio();
|
||||
|
||||
@@ -285,7 +285,8 @@ static void cleanup_buf(buffer **buf) {
|
||||
if (!*buf) {
|
||||
return;
|
||||
}
|
||||
buf_burn_free(*buf);
|
||||
buf_burn(*buf);
|
||||
buf_free(*buf);
|
||||
*buf = NULL;
|
||||
}
|
||||
|
||||
@@ -403,7 +404,7 @@ static void read_session_identification() {
|
||||
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"))
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
fuzz_dump(&in, 1);
|
||||
#endif
|
||||
|
||||
if (in == '\n') {
|
||||
/* end of ident string */
|
||||
break;
|
||||
@@ -666,16 +662,26 @@ void update_channel_prio() {
|
||||
return;
|
||||
}
|
||||
|
||||
new_prio = DROPBEAR_PRIO_NORMAL;
|
||||
new_prio = DROPBEAR_PRIO_BULK;
|
||||
for (i = 0; i < ses.chansize; 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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1271
config.guess
vendored
1271
config.guess
vendored
File diff suppressed because it is too large
Load Diff
459
config.h.in
459
config.h.in
@@ -1,459 +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 <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_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 <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 you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Use /dev/ptmx */
|
||||
#undef USE_DEV_PTMX
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* 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 to `int' if <sys/types.h> does not define. */
|
||||
#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
|
||||
1043
config.sub
vendored
1043
config.sub
vendored
File diff suppressed because it is too large
Load Diff
31
configure.ac
31
configure.ac
@@ -5,7 +5,7 @@
|
||||
# of the platform checks have been taken straight from OpenSSH's configure.ac
|
||||
# Huge thanks to them for dealing with the horrible platform-specifics :)
|
||||
|
||||
AC_PREREQ([2.59])
|
||||
AC_PREREQ(2.59)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR(buffer.c)
|
||||
|
||||
@@ -16,7 +16,6 @@ if test -s "`which hg`" && test -d "$srcdir/.hg"; then
|
||||
fi
|
||||
|
||||
ORIGCFLAGS="$CFLAGS"
|
||||
LATE_CFLAGS=""
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
@@ -48,9 +47,6 @@ DB_TRYADDCFLAGS([-Wno-pointer-sign])
|
||||
AC_MSG_NOTICE([Checking if compiler '$CC' supports -fno-strict-overflow])
|
||||
DB_TRYADDCFLAGS([-fno-strict-overflow])
|
||||
|
||||
# needed for various extensions. define early before autoconf tests
|
||||
AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions if glibc])
|
||||
|
||||
STATIC=0
|
||||
AC_ARG_ENABLE(static,
|
||||
[ --enable-static Build static binaries],
|
||||
@@ -128,17 +124,6 @@ if test "$hardenbuild" -eq 1; then
|
||||
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(werror,
|
||||
[ --enable-werror Set -Werror when building],
|
||||
[
|
||||
if test "x$enableval" = "xyes"; then
|
||||
# -Werror shouldn't be set when configure runs tests.
|
||||
# We add it to the Makefile's CFLAGS
|
||||
LATE_CFLAGS+="$LATE_CFLAGS -Werror"
|
||||
AC_MSG_NOTICE(Enabling -Werror)
|
||||
fi
|
||||
], [])
|
||||
|
||||
# large file support is useful for scp
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
@@ -362,7 +347,6 @@ AC_ARG_ENABLE(fuzz,
|
||||
DROPBEAR_FUZZ=1
|
||||
# libfuzzer needs linking with c++ libraries
|
||||
AC_PROG_CXX
|
||||
mkdir -pv fuzz
|
||||
else
|
||||
AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing)
|
||||
AC_MSG_NOTICE(Disabling fuzzing)
|
||||
@@ -380,13 +364,14 @@ AC_SUBST(DROPBEAR_FUZZ)
|
||||
AC_SUBST(CXX)
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \
|
||||
crypt.h \
|
||||
pty.h libutil.h libgen.h inttypes.h stropts.h utmp.h \
|
||||
utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h \
|
||||
pam/pam_appl.h netinet/in_systm.h sys/uio.h linux/pkt_sched.h \
|
||||
sys/random.h sys/prctl.h])
|
||||
sys/random.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
@@ -394,6 +379,7 @@ AC_TYPE_UID_T
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
|
||||
AC_CHECK_TYPES([uint8_t, u_int8_t, uint16_t, u_int16_t, uint32_t, u_int32_t])
|
||||
AC_CHECK_TYPES([struct sockaddr_storage])
|
||||
@@ -841,7 +827,7 @@ AC_FUNC_MEMCMP
|
||||
AC_FUNC_SELECT_ARGTYPES
|
||||
AC_CHECK_FUNCS([getpass getspnam getusershell putenv])
|
||||
AC_CHECK_FUNCS([clearenv strlcpy strlcat daemon basename _getpty getaddrinfo ])
|
||||
AC_CHECK_FUNCS([freeaddrinfo getnameinfo fork writev getgrouplist fexecve])
|
||||
AC_CHECK_FUNCS([freeaddrinfo getnameinfo fork writev getgrouplist])
|
||||
|
||||
AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
|
||||
|
||||
@@ -873,11 +859,8 @@ if test $BUNDLED_LIBTOM = 1 ; then
|
||||
LIBTOM_FILES="libtomcrypt/Makefile libtommath/Makefile"
|
||||
fi
|
||||
|
||||
# flags that should be set in Makefile but not for configure tests
|
||||
CFLAGS="$CFLAGS $LATE_CFLAGS"
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES(Makefile $LIBTOM_FILES test/Makefile)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_CONFIG_FILES(Makefile $LIBTOM_FILES)
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_NOTICE()
|
||||
|
||||
@@ -3,18 +3,11 @@
|
||||
#include "crypto_desc.h"
|
||||
#include "ltc_prng.h"
|
||||
#include "ecc.h"
|
||||
#include "dbrandom.h"
|
||||
|
||||
#if DROPBEAR_LTC_PRNG
|
||||
int dropbear_ltc_prng = -1;
|
||||
#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.
|
||||
* This should be run before using any of the ciphers/hashes */
|
||||
@@ -24,6 +17,12 @@ void crypto_init() {
|
||||
#if DROPBEAR_AES
|
||||
&aes_desc,
|
||||
#endif
|
||||
#if DROPBEAR_BLOWFISH
|
||||
&blowfish_desc,
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH
|
||||
&twofish_desc,
|
||||
#endif
|
||||
#if DROPBEAR_3DES
|
||||
&des3_desc,
|
||||
#endif
|
||||
@@ -31,9 +30,8 @@ void crypto_init() {
|
||||
};
|
||||
|
||||
const struct ltc_hash_descriptor *reghashes[] = {
|
||||
#if DROPBEAR_SHA1_HMAC
|
||||
/* we need sha1 for hostkey stuff regardless */
|
||||
&sha1_desc,
|
||||
#endif
|
||||
#if DROPBEAR_MD5_HMAC
|
||||
&md5_desc,
|
||||
#endif
|
||||
@@ -47,9 +45,9 @@ void crypto_init() {
|
||||
&sha512_desc,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
};
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; regciphers[i] != NULL; i++) {
|
||||
if (register_cipher(regciphers[i]) == -1) {
|
||||
dropbear_exit("Error registering crypto");
|
||||
@@ -69,8 +67,6 @@ void crypto_init() {
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_rand_source(dropbear_rand_source);
|
||||
|
||||
#if DROPBEAR_ECC
|
||||
ltc_mp = ltm_desc;
|
||||
dropbear_ecc_fill_dp();
|
||||
|
||||
23
dbclient.1
23
dbclient.1
@@ -19,7 +19,7 @@ dbclient \- lightweight SSH client
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B dbclient
|
||||
is the client part of Dropbear SSH
|
||||
is a small SSH client
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.TP
|
||||
@@ -44,27 +44,27 @@ from OpenSSH with dropbearconvert(1). The default path ~/.ssh/id_dropbear is use
|
||||
.TP
|
||||
.B \-L\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
|
||||
Local port forwarding.
|
||||
Forward
|
||||
Forward the port
|
||||
.I listenport
|
||||
on the local host through the SSH connection to
|
||||
on the local host through the SSH connection to port
|
||||
.I port
|
||||
on
|
||||
on the host
|
||||
.IR host .
|
||||
.TP
|
||||
.B \-R\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
|
||||
Remote port forwarding.
|
||||
Forward
|
||||
Forward the port
|
||||
.I listenport
|
||||
on the remote host through the SSH connection to
|
||||
on the remote host through the SSH connection to port
|
||||
.I port
|
||||
on
|
||||
on the host
|
||||
.IR host .
|
||||
.TP
|
||||
.B \-l \fIuser
|
||||
Username.
|
||||
Login as
|
||||
.I user
|
||||
on the remote host. An alternative is to specify user@host.
|
||||
on the remote host.
|
||||
.TP
|
||||
.B \-t
|
||||
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.
|
||||
.TP
|
||||
.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
|
||||
.B \-N
|
||||
Don't request a remote shell or run any commands. Any command arguments are ignored.
|
||||
@@ -149,13 +149,10 @@ The following options have currently been implemented:
|
||||
.RS
|
||||
.TP
|
||||
.B ExitOnForwardFailure
|
||||
Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be "yes" or "no". The default is "no".
|
||||
Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be “yes” or “no”. The default is “no”.
|
||||
.TP
|
||||
.B UseSyslog
|
||||
Send dbclient log messages to syslog in addition to stderr.
|
||||
.TP
|
||||
.B Port
|
||||
Specify a listening port, like the \fI-p\fR argument.
|
||||
.RE
|
||||
.TP
|
||||
.B \-s
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef DBMALLOC_H_
|
||||
#define DBMALLOC_H_
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdlib.h"
|
||||
#include "options.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void * m_malloc(size_t size);
|
||||
void * m_calloc(size_t nmemb, size_t size);
|
||||
|
||||
19
dbmulti.c
19
dbmulti.c
@@ -23,15 +23,20 @@
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
static int runprog(const char *multipath,
|
||||
const char *progname, int argc, char ** argv, int *match) {
|
||||
/* definitions are cleanest if we just put them here */
|
||||
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;
|
||||
|
||||
#ifdef DBMULTI_dropbear
|
||||
if (strcmp(progname, "dropbear") == 0) {
|
||||
return dropbear_main(argc, argv, multipath);
|
||||
return dropbear_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#ifdef DBMULTI_dbclient
|
||||
@@ -62,16 +67,12 @@ static int runprog(const char *multipath,
|
||||
int main(int argc, char ** argv) {
|
||||
int 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 ..." */
|
||||
if (argc > i) {
|
||||
int match, res;
|
||||
/* figure which form we're being called as */
|
||||
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) {
|
||||
return res;
|
||||
}
|
||||
|
||||
49
dbrandom.c
49
dbrandom.c
@@ -34,7 +34,7 @@ static uint32_t counter = 0;
|
||||
/* the max value for the counter, so it won't integer overflow */
|
||||
#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;
|
||||
|
||||
#define INIT_SEED_SIZE 32 /* 256 bits */
|
||||
@@ -100,7 +100,7 @@ process_file(hash_state *hs, const char *filename,
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
sha256_process(hs, readbuf, readlen);
|
||||
sha1_process(hs, readbuf, readlen);
|
||||
readcount += readlen;
|
||||
}
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
@@ -120,13 +120,13 @@ void addrandom(const unsigned char * buf, unsigned int len)
|
||||
#endif
|
||||
|
||||
/* hash in the new seed data */
|
||||
sha256_init(&hs);
|
||||
sha1_init(&hs);
|
||||
/* existing state (zeroes on startup) */
|
||||
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
|
||||
/* new */
|
||||
sha256_process(&hs, buf, len);
|
||||
sha256_done(&hs, hashpool);
|
||||
sha1_process(&hs, buf, len);
|
||||
sha1_done(&hs, hashpool);
|
||||
}
|
||||
|
||||
static void write_urandom()
|
||||
@@ -150,12 +150,12 @@ static void write_urandom()
|
||||
}
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
void fuzz_seed(const unsigned char* dat, unsigned int len) {
|
||||
void fuzz_seed(void) {
|
||||
hash_state hs;
|
||||
sha256_init(&hs);
|
||||
sha256_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
|
||||
sha256_process(&hs, dat, len);
|
||||
sha256_done(&hs, hashpool);
|
||||
sha1_init(&hs);
|
||||
sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
|
||||
sha1_done(&hs, hashpool);
|
||||
|
||||
counter = 0;
|
||||
donerandinit = 1;
|
||||
}
|
||||
@@ -209,7 +209,7 @@ static int process_getrandom(hash_state *hs) {
|
||||
|
||||
if (ret == sizeof(buf)) {
|
||||
/* Success, stir in the entropy */
|
||||
sha256_process(hs, (void*)buf, sizeof(buf));
|
||||
sha1_process(hs, (void*)buf, sizeof(buf));
|
||||
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
|
||||
* be called multiple times */
|
||||
void seedrandom() {
|
||||
|
||||
hash_state hs;
|
||||
|
||||
pid_t pid;
|
||||
@@ -235,10 +236,10 @@ void seedrandom() {
|
||||
#endif
|
||||
|
||||
/* hash in the new seed data */
|
||||
sha256_init(&hs);
|
||||
sha1_init(&hs);
|
||||
|
||||
/* existing state */
|
||||
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
|
||||
#ifdef HAVE_GETRANDOM
|
||||
if (process_getrandom(&hs) == DROPBEAR_SUCCESS) {
|
||||
@@ -288,21 +289,21 @@ void seedrandom() {
|
||||
#endif
|
||||
|
||||
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
|
||||
OS X (10.8.3), avoid valgrind warnings by clearing it first */
|
||||
memset(&tv, 0x0, sizeof(tv));
|
||||
gettimeofday(&tv, NULL);
|
||||
sha256_process(&hs, (void*)&tv, sizeof(tv));
|
||||
sha1_process(&hs, (void*)&tv, sizeof(tv));
|
||||
|
||||
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
|
||||
* be added to the hashpool - see runopts.c */
|
||||
|
||||
sha256_done(&hs, hashpool);
|
||||
sha1_done(&hs, hashpool);
|
||||
|
||||
counter = 0;
|
||||
donerandinit = 1;
|
||||
@@ -316,7 +317,7 @@ void seedrandom() {
|
||||
void genrandom(unsigned char* buf, unsigned int len) {
|
||||
|
||||
hash_state hs;
|
||||
unsigned char hash[SHA256_HASH_SIZE];
|
||||
unsigned char hash[SHA1_HASH_SIZE];
|
||||
unsigned int copylen;
|
||||
|
||||
if (!donerandinit) {
|
||||
@@ -324,17 +325,17 @@ void genrandom(unsigned char* buf, unsigned int len) {
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
sha256_init(&hs);
|
||||
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
sha256_process(&hs, (void*)&counter, sizeof(counter));
|
||||
sha256_done(&hs, hash);
|
||||
sha1_init(&hs);
|
||||
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||
sha1_process(&hs, (void*)&counter, sizeof(counter));
|
||||
sha1_done(&hs, hash);
|
||||
|
||||
counter++;
|
||||
if (counter > MAX_COUNTER) {
|
||||
seedrandom();
|
||||
}
|
||||
|
||||
copylen = MIN(len, SHA256_HASH_SIZE);
|
||||
copylen = MIN(len, SHA1_HASH_SIZE);
|
||||
memcpy(buf, hash, copylen);
|
||||
len -= copylen;
|
||||
buf += copylen;
|
||||
|
||||
182
dbutil.c
182
dbutil.c
@@ -121,6 +121,7 @@ static void generic_dropbear_exit(int exitcode, const char* format,
|
||||
_dropbear_log(LOG_INFO, fmtbuf, param);
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
/* longjmp before cleaning up svr_opts */
|
||||
if (fuzz.do_jmp) {
|
||||
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;
|
||||
|
||||
@@ -185,63 +186,39 @@ static double time_since_start()
|
||||
return nowf - debug_start_time;
|
||||
}
|
||||
|
||||
static void dropbear_tracelevel(int level, const char *format, va_list param)
|
||||
{
|
||||
if (debug_trace == 0 || debug_trace < level) {
|
||||
void dropbear_trace(const char* format, ...) {
|
||||
va_list param;
|
||||
|
||||
if (!debug_trace) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
#if (DEBUG_TRACE>=2)
|
||||
|
||||
void dropbear_trace2(const char* format, ...) {
|
||||
static int trace_env = -1;
|
||||
va_list param;
|
||||
|
||||
va_start(param, format);
|
||||
dropbear_tracelevel(2, format, param);
|
||||
va_end(param);
|
||||
}
|
||||
#endif
|
||||
#if (DEBUG_TRACE>=3)
|
||||
void dropbear_trace3(const char* format, ...) {
|
||||
va_list param;
|
||||
if (trace_env == -1) {
|
||||
trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0;
|
||||
}
|
||||
|
||||
if (!(debug_trace && trace_env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
#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
|
||||
|
||||
#endif /* DEBUG_TRACE */
|
||||
|
||||
/* Connect to a given unix socket. The socket is blocking */
|
||||
#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 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 */
|
||||
if (pipe(infds) != 0) {
|
||||
return DROPBEAR_FAILURE;
|
||||
@@ -409,37 +380,20 @@ void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
|
||||
|
||||
#if DEBUG_TRACE
|
||||
void printhex(const char * label, const unsigned char * buf, int len) {
|
||||
int i, j;
|
||||
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "%s\n", label);
|
||||
/* for each 16 byte line */
|
||||
for (j = 0; j < len; j += 16) {
|
||||
const int linelen = MIN(16, len - j);
|
||||
|
||||
/* 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, " ");
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
fprintf(stderr, "%02x", buf[i]);
|
||||
if (i % 16 == 15) {
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/* print characters */
|
||||
fprintf(stderr, " ");
|
||||
for (i = 0; i < linelen; i++) {
|
||||
char c = buf[j+i];
|
||||
if (!isprint(c)) {
|
||||
c = '.';
|
||||
}
|
||||
fputc(c, stderr);
|
||||
else if (i % 2 == 1) {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void printmpint(const char *label, mp_int *mp) {
|
||||
@@ -599,28 +553,16 @@ void setnonblocking(int fd) {
|
||||
}
|
||||
|
||||
void disallow_core() {
|
||||
struct rlimit lim = {0};
|
||||
if (getrlimit(RLIMIT_CORE, &lim) < 0) {
|
||||
TRACE(("getrlimit(RLIMIT_CORE) failed"));
|
||||
}
|
||||
lim.rlim_cur = 0;
|
||||
if (setrlimit(RLIMIT_CORE, &lim) < 0) {
|
||||
TRACE(("setrlimit(RLIMIT_CORE) failed"));
|
||||
}
|
||||
struct rlimit lim;
|
||||
lim.rlim_cur = lim.rlim_max = 0;
|
||||
setrlimit(RLIMIT_CORE, &lim);
|
||||
}
|
||||
|
||||
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */
|
||||
int m_str_to_uint(const char* str, unsigned int *val) {
|
||||
unsigned long l;
|
||||
char *endp;
|
||||
|
||||
l = strtoul(str, &endp, 10);
|
||||
|
||||
if (endp == str || *endp != '\0') {
|
||||
/* parse error */
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(str, NULL, 10);
|
||||
/* The c99 spec doesn't actually seem to define EINVAL, but most platforms
|
||||
* I've looked at mention it in their manpage */
|
||||
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,
|
||||
otherwise returned as-is */
|
||||
/* Returns malloced path. inpath beginning with '/' is returned as-is,
|
||||
otherwise home directory is prepended */
|
||||
char * expand_homedir_path(const char *inpath) {
|
||||
struct passwd *pw = NULL;
|
||||
if (strncmp(inpath, "~/", 2) == 0) {
|
||||
char *homedir = getenv("HOME");
|
||||
|
||||
if (!homedir) {
|
||||
pw = getpwuid(getuid());
|
||||
if (pw) {
|
||||
homedir = pw->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (homedir) {
|
||||
int len = strlen(inpath)-2 + strlen(homedir) + 2;
|
||||
if (inpath[0] != '/') {
|
||||
pw = getpwuid(getuid());
|
||||
if (pw && pw->pw_dir) {
|
||||
int len = strlen(inpath) + strlen(pw->pw_dir) + 2;
|
||||
char *buf = m_malloc(len);
|
||||
snprintf(buf, len, "%s/%s", homedir, inpath+2);
|
||||
snprintf(buf, len, "%s/%s", pw->pw_dir, inpath);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
@@ -752,35 +686,3 @@ void fsync_parent_dir(const char* fn) {
|
||||
m_free(fn_dir);
|
||||
#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;
|
||||
}
|
||||
|
||||
17
dbutil.h
17
dbutil.h
@@ -47,11 +47,8 @@ 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;
|
||||
|
||||
#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_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 printmpint(const char *label, mp_int *mp);
|
||||
void debug_start_net(void);
|
||||
@@ -73,8 +70,6 @@ void m_close(int fd);
|
||||
void setnonblocking(int fd);
|
||||
void disallow_core(void);
|
||||
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 */
|
||||
#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);
|
||||
|
||||
int fd_read_pending(int fd);
|
||||
|
||||
#if DROPBEAR_MSAN
|
||||
/* 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)
|
||||
@@ -104,12 +97,4 @@ int fd_read_pending(int fd);
|
||||
#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
|
||||
#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_ */
|
||||
|
||||
36
debian/changelog
vendored
36
debian/changelog
vendored
@@ -1,21 +1,3 @@
|
||||
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
|
||||
|
||||
* New upstream release.
|
||||
@@ -173,24 +155,6 @@ dropbear (0.53-0.1) unstable; urgency=low
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 24 Feb 2011 22:54:00 +0900
|
||||
|
||||
dropbear (0.52-2) unstable; urgency=low
|
||||
|
||||
* Make key utils part of dropbear-server package (since it's
|
||||
required anyway, single binary saves space), rename -common to
|
||||
-keyutils
|
||||
* Don't make clean between builds, just rm *.o since only
|
||||
top-level files change
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 19 Nov 2008 21:54:00 +0900
|
||||
|
||||
dropbear (0.52-1) unstable; urgency=low
|
||||
|
||||
* Maemo port, split into 5 packages
|
||||
(dropbear, dropbear-server, dropbear-client, dropbear-common, dropbear-scp).
|
||||
This avoids conflicts with openssh package.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Wed, 19 Nov 2008 20:54:00 +0900
|
||||
|
||||
dropbear (0.52-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
79
debian/control
vendored
79
debian/control
vendored
@@ -1,7 +1,7 @@
|
||||
Source: dropbear
|
||||
Section: user/network
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Matt Johnston <matt@ucc.asn.au>
|
||||
Maintainer: Gerrit Pape <pape@smarden.org>
|
||||
Build-Depends: libz-dev
|
||||
Standards-Version: 3.7.3.0
|
||||
|
||||
@@ -9,9 +9,6 @@ Package: dropbear
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Suggests: openssh-client, runit
|
||||
Section: user/network
|
||||
Conflicts: dropbear-server, dropbear-client, dropbear-keyutils, dropbear-scp
|
||||
XB-Maemo-Display-Name: Dropbear SSH Client and Server
|
||||
Description: lightweight SSH2 server and client
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
@@ -20,76 +17,4 @@ Description: lightweight SSH2 server and client
|
||||
It implements most required features of the SSH 2 protocol, and other
|
||||
features such as X11 and authentication agent forwarding.
|
||||
.
|
||||
This package provides Dropbear client and server as a single binary,
|
||||
as well as key utilities and SCP.
|
||||
.
|
||||
See http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
Package: dropbear-server
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Section: user/network
|
||||
Conflicts: dropbear, dropbear-keyutils
|
||||
Provides: dropbear-keyutils
|
||||
Recommends: dropbear-scp
|
||||
XB-Maemo-Display-Name: Dropbear SSH Server
|
||||
Description: lightweight SSH2 server
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
It implements most required features of the SSH 2 protocol, and other
|
||||
features such as X11 and authentication agent forwarding.
|
||||
.
|
||||
This package provides only the Dropbear server.
|
||||
.
|
||||
See http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
Package: dropbear-client
|
||||
Architecture: any
|
||||
Conflicts: dropbear
|
||||
Section: user/network
|
||||
Depends: ${shlibs:Depends}
|
||||
Recommends: dropbear-scp
|
||||
Suggests: dropbear-keyutils
|
||||
XB-Maemo-Display-Name: Dropbear SSH Client
|
||||
Description: lightweight SSH2 client
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
It implements most required features of the SSH 2 protocol, and other
|
||||
features such as X11 and authentication agent forwarding.
|
||||
.
|
||||
This package provides only the Dropbear client.
|
||||
.
|
||||
See http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
Package: dropbear-keyutils
|
||||
Architecture: any
|
||||
Conflicts: dropbear, dropbear-server
|
||||
Section: user/network
|
||||
XB-Maemo-Display-Name: Dropbear SSH Key Utils
|
||||
Depends: ${shlibs:Depends}
|
||||
Description: lightweight SSH2, key management utilities
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
This package provides dropbearkey and dropbearconvert programs,
|
||||
for generating keys and converting to/from OpenSSH keys.
|
||||
.
|
||||
See http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
Package: dropbear-scp
|
||||
Architecture: any
|
||||
Section: user/network
|
||||
Conflicts: dropbear
|
||||
XB-Maemo-Display-Name: Dropbear SCP
|
||||
Depends: ${shlibs:Depends}
|
||||
Description: lightweight SSH2 scp
|
||||
dropbear is a SSH 2 server and client designed to be small enough to
|
||||
be used in small memory environments, while still being functional and
|
||||
secure enough for general use.
|
||||
.
|
||||
This dropbear-scp package provides /usr/bin/scp.
|
||||
|
||||
3
debian/dropbear-server.conffiles
vendored
3
debian/dropbear-server.conffiles
vendored
@@ -1,3 +0,0 @@
|
||||
/etc/init.d/dropbear
|
||||
/etc/dropbear/run
|
||||
/etc/dropbear/log/run
|
||||
79
debian/dropbear-server.postinst
vendored
79
debian/dropbear-server.postinst
vendored
@@ -1,79 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'configure' || exit 0
|
||||
|
||||
if test ! -e /etc/dropbear/dropbear_rsa_host_key; then
|
||||
if test -f /etc/ssh/ssh_host_rsa_key; then
|
||||
echo "Converting existing OpenSSH RSA host key to Dropbear format."
|
||||
/usr/lib/dropbear/dropbearconvert openssh dropbear \
|
||||
/etc/ssh/ssh_host_rsa_key /etc/dropbear/dropbear_rsa_host_key
|
||||
else
|
||||
echo "Generating Dropbear RSA key. Please wait."
|
||||
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
|
||||
fi
|
||||
fi
|
||||
if test ! -e /etc/dropbear/dropbear_dss_host_key; then
|
||||
if test -f /etc/ssh/ssh_host_dsa_key; then
|
||||
echo "Converting existing OpenSSH RSA host key to Dropbear format."
|
||||
/usr/lib/dropbear/dropbearconvert openssh dropbear \
|
||||
/etc/ssh/ssh_host_dsa_key /etc/dropbear/dropbear_dss_host_key
|
||||
else
|
||||
echo "Generating Dropbear DSS key. Please wait."
|
||||
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
|
||||
fi
|
||||
fi
|
||||
if test ! -s /etc/default/dropbear; then
|
||||
# check whether OpenSSH seems to be installed.
|
||||
if test -x /usr/sbin/sshd; then
|
||||
cat <<EOT
|
||||
OpenSSH appears to be installed. Setting /etc/default/dropbear so that
|
||||
Dropbear will not start by default. Edit this file to change this behaviour.
|
||||
|
||||
EOT
|
||||
cat >>/etc/default/dropbear <<EOT
|
||||
# disabled because OpenSSH is installed
|
||||
# change to NO_START=0 to enable Dropbear
|
||||
NO_START=1
|
||||
|
||||
EOT
|
||||
fi
|
||||
cat >>/etc/default/dropbear <<EOT
|
||||
# the TCP port that Dropbear listens on
|
||||
DROPBEAR_PORT=22
|
||||
|
||||
# any additional arguments for Dropbear
|
||||
DROPBEAR_EXTRA_ARGS=
|
||||
|
||||
# specify an optional banner file containing a message to be
|
||||
# sent to clients before they connect, such as "/etc/issue.net"
|
||||
DROPBEAR_BANNER=""
|
||||
|
||||
# RSA hostkey file (default: /etc/dropbear/dropbear_rsa_host_key)
|
||||
#DROPBEAR_RSAKEY="/etc/dropbear/dropbear_rsa_host_key"
|
||||
|
||||
# DSS hostkey file (default: /etc/dropbear/dropbear_dss_host_key)
|
||||
#DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key"
|
||||
|
||||
# Receive window size - this is a tradeoff between memory and
|
||||
# network performance
|
||||
DROPBEAR_RECEIVE_WINDOW=65536
|
||||
EOT
|
||||
fi
|
||||
|
||||
if test -x /etc/init.d/dropbear; then
|
||||
update-rc.d dropbear defaults >/dev/null
|
||||
if test -x /usr/sbin/invoke-rc.d; then
|
||||
invoke-rc.d dropbear restart
|
||||
else
|
||||
/etc/init.d/dropbear restart
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$2" && dpkg --compare-versions "$2" lt '0.50-4' &&
|
||||
update-service --check dropbear 2>/dev/null; then
|
||||
update-service --remove /etc/dropbear 2>/dev/null || :
|
||||
sleep 6
|
||||
rm -rf /var/run/dropbear /var/run/dropbear.log
|
||||
update-service --add /etc/dropbear || :
|
||||
fi
|
||||
12
debian/dropbear-server.postrm
vendored
12
debian/dropbear-server.postrm
vendored
@@ -1,12 +0,0 @@
|
||||
#! /bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'purge' || exit 0
|
||||
if test -e /etc/dropbear; then
|
||||
rm -f /etc/dropbear/dropbear_rsa_host_key
|
||||
rm -f /etc/dropbear/dropbear_dss_host_key
|
||||
rmdir --ignore-fail-on-non-empty /etc/dropbear
|
||||
fi
|
||||
update-rc.d dropbear remove >/dev/null
|
||||
rm -f /etc/default/dropbear
|
||||
rm -rf /etc/dropbear/supervise /etc/dropbear/log/supervise
|
||||
11
debian/dropbear-server.prerm
vendored
11
debian/dropbear-server.prerm
vendored
@@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
test "$1" = 'remove' || test "$1" = 'deconfigure' || exit 0
|
||||
if test -x /etc/init.d/dropbear; then
|
||||
if test -x /usr/sbin/invoke-rc.d; then
|
||||
invoke-rc.d dropbear stop
|
||||
else
|
||||
/etc/init.d/dropbear stop
|
||||
fi
|
||||
fi
|
||||
4
debian/dropbear.init
vendored
4
debian/dropbear.init
vendored
@@ -39,7 +39,7 @@ test -n "$DROPBEAR_RECEIVE_WINDOW" || \
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
test "$NO_START" = "0" || cancel '/etc/default/dropbear NO_START is set, Dropbear will not run.'
|
||||
test "$NO_START" = "0" || cancel 'NO_START is not set to zero.'
|
||||
echo -n "Starting $DESC: "
|
||||
start-stop-daemon --start --quiet --pidfile /var/run/"$NAME".pid \
|
||||
--exec "$DAEMON" -- -d "$DROPBEAR_DSSKEY" -r "$DROPBEAR_RSAKEY" \
|
||||
@@ -52,7 +52,7 @@ case "$1" in
|
||||
echo "$NAME."
|
||||
;;
|
||||
restart|force-reload)
|
||||
test "$NO_START" = "0" || cancel '/etc/default/dropbear NO_START is set, Dropbear will not run.'
|
||||
test "$NO_START" = "0" || cancel 'NO_START is not set to zero.'
|
||||
echo -n "Restarting $DESC: "
|
||||
start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/"$NAME".pid
|
||||
sleep 1
|
||||
|
||||
144
debian/rules
vendored
144
debian/rules
vendored
@@ -20,6 +20,8 @@ ifneq (,$(findstring diet,$(DEB_BUILD_OPTIONS)))
|
||||
CC =diet -v -Os gcc -nostdinc
|
||||
endif
|
||||
|
||||
DIR =$(shell pwd)/debian/dropbear
|
||||
|
||||
patch: deb-checkdir patch-stamp
|
||||
patch-stamp:
|
||||
for i in `ls -1 debian/diff/*.diff || :`; do \
|
||||
@@ -34,15 +36,13 @@ config.status: patch-stamp configure
|
||||
--build='$(DEB_BUILD_GNU_TYPE)' --prefix=/usr \
|
||||
--mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info \
|
||||
$(CONFFLAGS)
|
||||
$(MAKE) clean
|
||||
|
||||
build: deb-checkdir build-stamp
|
||||
build-stamp: config.status
|
||||
$(MAKE) CC='$(CC)' LD='$(CC)'
|
||||
touch build-stamp
|
||||
|
||||
clean: DIR=$(shell pwd)/debian/dropbear
|
||||
clean: deb-checkdir deb-checkuid
|
||||
clean: deb-checkdir deb-checkuid
|
||||
test ! -r Makefile || $(MAKE) distclean
|
||||
rm -f libtomcrypt/Makefile libtommath/Makefile
|
||||
test ! -e patch-stamp || \
|
||||
@@ -51,117 +51,22 @@ clean: deb-checkdir deb-checkuid
|
||||
done
|
||||
rm -f patch-stamp build-stamp config.log config.status
|
||||
rm -rf '$(DIR)'
|
||||
rm -rf '$(DIR)'-client
|
||||
rm -rf '$(DIR)'-server
|
||||
rm -rf '$(DIR)'-keyutils
|
||||
rm -rf '$(DIR)'-scp
|
||||
rm -f debian/files debian/substvars debian/copyright changelog
|
||||
|
||||
install-server: DIR=$(shell pwd)/debian/dropbear-server
|
||||
install-server: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS="dropbear dropbearkey dropbearconvert" MULTI=1
|
||||
install: deb-checkdir deb-checkuid build-stamp
|
||||
rm -rf '$(DIR)'
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear
|
||||
# programs
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -d -m0755 '$(DIR)'/usr/sbin
|
||||
install -d -m0755 '$(DIR)'/usr/lib/dropbear
|
||||
install -m0755 dropbearmulti \
|
||||
'$(DIR)'/usr/lib/dropbear/dropbearmulti
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/dropbearkey
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/sbin/dropbear
|
||||
ln -s dropbearmulti '$(DIR)'/usr/lib/dropbear/dropbearconvert
|
||||
# init and run scripts
|
||||
install -d -m0755 '$(DIR)'/etc/init.d
|
||||
install -m0755 debian/dropbear.init '$(DIR)'/etc/init.d/dropbear
|
||||
install -m0755 debian/service/run '$(DIR)'/etc/dropbear/run
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear/log
|
||||
install -m0755 debian/service/log '$(DIR)'/etc/dropbear/log/run
|
||||
ln -s /var/log/dropbear '$(DIR)'/etc/dropbear/log/main
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man8
|
||||
for i in dropbear.8 ; do \
|
||||
install -m644 $$i '$(DIR)'/usr/share/man/man8/ || exit 1; \
|
||||
done
|
||||
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
|
||||
# copyright, changelog
|
||||
cat debian/copyright.in LICENSE > debian/copyright
|
||||
test -r changelog || ln -s CHANGES changelog
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install-client: DIR=$(shell pwd)/debian/dropbear-client
|
||||
install-client: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS=dbclient dbclient
|
||||
install -m0755 dropbear '$(DIR)'/usr/sbin/dropbear
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -m0755 dbclient '$(DIR)'/usr/bin/dbclient
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man1
|
||||
install -m644 dbclient.1 '$(DIR)'/usr/share/man/man1/
|
||||
gzip -9 '$(DIR)'/usr/share/man/man1/*.1
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/bin/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/bin/*
|
||||
|
||||
install-keyutils: DIR=$(shell pwd)/debian/dropbear-keyutils
|
||||
install-keyutils: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS="dropbearkey dropbearconvert" MULTI=1
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -m0755 dropbearkey '$(DIR)'/usr/bin/dropbearkey
|
||||
install -d -m0755 '$(DIR)'/usr/lib/dropbear
|
||||
install -m0755 dropbearmulti \
|
||||
'$(DIR)'/usr/lib/dropbear/dropbearmulti
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/dropbearkey
|
||||
ln -s dropbearmulti '$(DIR)'/usr/lib/dropbear/dropbearconvert
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man8
|
||||
for i in dropbearkey.8; do \
|
||||
install -m644 $$i '$(DIR)'/usr/share/man/man8/ || exit 1; \
|
||||
done
|
||||
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
|
||||
$(STRIP) -R .comment -R .note \
|
||||
'$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install-scp: DIR=$(shell pwd)/debian/dropbear-scp
|
||||
install-scp: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS="scp" scp
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -m0755 scp '$(DIR)'/usr/bin/scp
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/bin/*
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/bin/*
|
||||
|
||||
install-multi: DIR=$(shell pwd)/debian/dropbear
|
||||
install-multi: deb-checkdir deb-checkuid config.status
|
||||
rm -f '$(DIR)'
|
||||
rm *.o
|
||||
$(MAKE) CC='$(CC)' LD='$(LD)' PROGRAMS="dropbearkey dropbearconvert scp dropbear dbclient" MULTI=1
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear
|
||||
# programs
|
||||
install -d -m0755 '$(DIR)'/usr/bin
|
||||
install -d -m0755 '$(DIR)'/usr/sbin
|
||||
install -d -m0755 '$(DIR)'/usr/lib/dropbear
|
||||
install -m0755 dropbearmulti \
|
||||
'$(DIR)'/usr/lib/dropbear/dropbearmulti
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/dropbearkey
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/dbclient
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/bin/scp
|
||||
ln -s ../lib/dropbear/dropbearmulti '$(DIR)'/usr/sbin/dropbear
|
||||
ln -s dropbearmulti '$(DIR)'/usr/lib/dropbear/dropbearconvert
|
||||
install -m0755 dropbearconvert \
|
||||
'$(DIR)'/usr/lib/dropbear/dropbearconvert
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/sbin/* \
|
||||
'$(DIR)'/usr/bin/* '$(DIR)'/usr/lib/dropbear/*
|
||||
# init and run scripts
|
||||
install -d -m0755 '$(DIR)'/etc/init.d
|
||||
install -m0755 debian/dropbear.init '$(DIR)'/etc/init.d/dropbear
|
||||
@@ -169,6 +74,7 @@ install-multi: deb-checkdir deb-checkuid config.status
|
||||
install -d -m0755 '$(DIR)'/etc/dropbear/log
|
||||
install -m0755 debian/service/log '$(DIR)'/etc/dropbear/log/run
|
||||
ln -s /var/log/dropbear '$(DIR)'/etc/dropbear/log/main
|
||||
# man pages
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man8
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man1
|
||||
install -m644 dropbear.8 '$(DIR)'/usr/share/man/man8/
|
||||
@@ -177,26 +83,18 @@ install-multi: deb-checkdir deb-checkuid config.status
|
||||
done
|
||||
gzip -9 '$(DIR)'/usr/share/man/man8/*.8
|
||||
gzip -9 '$(DIR)'/usr/share/man/man1/*.1
|
||||
$(STRIP) -R .comment -R .note '$(DIR)'/usr/lib/dropbear/*
|
||||
# copyright, changelog
|
||||
cat debian/copyright.in LICENSE >debian/copyright
|
||||
test -r changelog || ln -s CHANGES changelog
|
||||
|
||||
install -d -m0755 '$(DIR)'/DEBIAN
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/lib/dropbear/*
|
||||
|
||||
install: install-client install-server install-keyutils install-multi install-scp
|
||||
binary-indep:
|
||||
|
||||
binary-arch: install dropbear.deb dropbear-server.deb dropbear-keyutils.deb dropbear-scp.deb dropbear-client.deb
|
||||
dpkg-gencontrol -isp -pdropbear -P'$(shell pwd)/debian'/dropbear
|
||||
dpkg-gencontrol -isp -pdropbear-server -P'$(shell pwd)/debian'/dropbear-server
|
||||
dpkg-gencontrol -isp -pdropbear-client -P'$(shell pwd)/debian'/dropbear-client
|
||||
dpkg-gencontrol -isp -pdropbear-keyutils -P'$(shell pwd)/debian'/dropbear-keyutils
|
||||
dpkg-gencontrol -isp -pdropbear-scp -P'$(shell pwd)/debian'/dropbear-scp
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear ..
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear-server ..
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear-keyutils ..
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear-scp ..
|
||||
dpkg -b '$(shell pwd)/debian'/dropbear-client ..
|
||||
binary-arch: install dropbear.deb
|
||||
test '$(CC)' != 'gcc' || \
|
||||
dpkg-shlibdeps '$(DIR)'/usr/sbin/* '$(DIR)'/usr/bin/* \
|
||||
'$(DIR)'/usr/lib/dropbear/*
|
||||
dpkg-gencontrol -isp -pdropbear -P'$(DIR)'
|
||||
dpkg -b '$(DIR)' ..
|
||||
|
||||
binary: binary-arch binary-indep
|
||||
|
||||
|
||||
38
debug.h
38
debug.h
@@ -48,43 +48,15 @@
|
||||
/*#define DEBUG_KEXHASH*/
|
||||
/*#define DEBUG_RSA*/
|
||||
|
||||
/* The level of TRACE() statements */
|
||||
#define DROPBEAR_VERBOSE_LEVEL 4
|
||||
|
||||
/* you don't need to touch this block */
|
||||
#if DEBUG_TRACE
|
||||
extern int debug_trace;
|
||||
#endif
|
||||
|
||||
/* Enable debug trace levels.
|
||||
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) dropbear_trace X;
|
||||
#define TRACE2(X) dropbear_trace2 X;
|
||||
#else /*DEBUG_TRACE*/
|
||||
#define TRACE(X)
|
||||
#define TRACE2(X)
|
||||
/* ... unless DEBUG_TRACE is high enough */
|
||||
#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
|
||||
#endif /*DEBUG_TRACE*/
|
||||
|
||||
/* To debug with GDB it is easier to run with no forking of child processes.
|
||||
You will need to pass "-F" as well. */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
default_options.h documents compile-time options, and provides default values.
|
||||
|
||||
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.
|
||||
|
||||
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 */
|
||||
#define DROPBEAR_DEFADDRESS ""
|
||||
|
||||
/* Default hostkey paths - these can be specified on the command line.
|
||||
* Homedir is prepended if path begins with ~/
|
||||
*/
|
||||
/* Default hostkey paths - these can be specified on the command line */
|
||||
#define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key"
|
||||
#define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_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 INETD_MODE 1
|
||||
|
||||
/* By default Dropbear will re-execute itself for each incoming connection so
|
||||
that memory layout may be re-randomised (ASLR) - exploiting
|
||||
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) */
|
||||
/* Include verbose debug output, enabled with -v at runtime.
|
||||
* This will add a reasonable amount to your executable size. */
|
||||
#define DEBUG_TRACE 0
|
||||
|
||||
/* 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
|
||||
* 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 */
|
||||
#define DROPBEAR_CLI_PROXYCMD 1
|
||||
|
||||
@@ -92,11 +80,13 @@ IMPORTANT: Some options will require "make clean" after changes */
|
||||
/* Encryption - at least one required.
|
||||
* AES128 should be enabled, some very old implementations might only
|
||||
* 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 */
|
||||
#define DROPBEAR_AES128 1
|
||||
#define DROPBEAR_AES256 1
|
||||
#define DROPBEAR_3DES 0
|
||||
#define DROPBEAR_TWOFISH256 0
|
||||
#define DROPBEAR_TWOFISH128 0
|
||||
|
||||
/* Enable Chacha20-Poly1305 authenticated encryption mode. This is
|
||||
* generally faster than AES256 on CPU w/o dedicated AES instructions,
|
||||
@@ -118,7 +108,7 @@ IMPORTANT: Some options will require "make clean" after changes */
|
||||
* Compiling in will add ~6kB to binary size on x86-64 */
|
||||
#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 */
|
||||
#define DROPBEAR_SHA1_HMAC 1
|
||||
#define DROPBEAR_SHA2_256_HMAC 1
|
||||
@@ -127,25 +117,18 @@ IMPORTANT: Some options will require "make clean" after changes */
|
||||
/* Hostkey/public key algorithms - at least one required, these are used
|
||||
* for hostkey as well as for verifying signatures with pubkey auth.
|
||||
* Removing either of these won't save very much space.
|
||||
* RSA is recommended.
|
||||
* RSA is recommended
|
||||
* DSS may be necessary to connect to some systems though
|
||||
* is not recommended for new keys.
|
||||
* See: RSA_PRIV_FILENAME and DSS_PRIV_FILENAME */
|
||||
is not recommended for new keys */
|
||||
#define DROPBEAR_RSA 1
|
||||
#define DROPBEAR_DSS 1
|
||||
/* ECDSA is significantly faster than RSA or DSS. Compiling in ECC
|
||||
* code (either ECDSA or ECDH) increases binary size - around 30kB
|
||||
* on x86-64.
|
||||
* See: ECDSA_PRIV_FILENAME */
|
||||
* on x86-64 */
|
||||
#define DROPBEAR_ECDSA 1
|
||||
/* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases
|
||||
* binary size - around 7,5kB on x86-64.
|
||||
* See: ED25519_PRIV_FILENAME */
|
||||
binary size - around 7,5kB on x86-64 */
|
||||
#define DROPBEAR_ED25519 1
|
||||
/* SK_ECDSA/SK_ED25519 allows u2f security keys for public key auth.
|
||||
* This is currently server-only. */
|
||||
#define DROPBEAR_SK_ECDSA 1
|
||||
#define DROPBEAR_SK_ED25519 1
|
||||
|
||||
/* RSA must be >=1024 */
|
||||
#define DROPBEAR_DEFAULT_RSA_SIZE 2048
|
||||
@@ -179,13 +162,13 @@ IMPORTANT: Some options will require "make clean" after changes */
|
||||
|
||||
* Small systems should generally include either curve25519 or ecdh for performance.
|
||||
* curve25519 is less widely supported but is faster
|
||||
*/
|
||||
*/
|
||||
#define DROPBEAR_DH_GROUP14_SHA1 1
|
||||
#define DROPBEAR_DH_GROUP14_SHA256 1
|
||||
#define DROPBEAR_DH_GROUP16 0
|
||||
#define DROPBEAR_CURVE25519 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
|
||||
not as a server, due to concerns over its strength. Set to 0 to allow
|
||||
@@ -220,8 +203,7 @@ group1 in Dropbear server too */
|
||||
* You can't enable both PASSWORD and PAM. */
|
||||
#define DROPBEAR_SVR_PAM_AUTH 0
|
||||
|
||||
/* ~/.ssh/authorized_keys authentication.
|
||||
* You must define DROPBEAR_SVR_PUBKEY_AUTH in order to use plugins. */
|
||||
/* ~/.ssh/authorized_keys authentication */
|
||||
#define DROPBEAR_SVR_PUBKEY_AUTH 1
|
||||
|
||||
/* Whether to take public key options in
|
||||
@@ -237,10 +219,9 @@ group1 in Dropbear server too */
|
||||
#define DROPBEAR_CLI_PASSWORD_AUTH 1
|
||||
#define DROPBEAR_CLI_PUBKEY_AUTH 1
|
||||
|
||||
/* A default argument for dbclient -i <privatekey>.
|
||||
* Homedir is prepended if path begins with ~/
|
||||
*/
|
||||
#define DROPBEAR_DEFAULT_CLI_AUTHKEY "~/.ssh/id_dropbear"
|
||||
/* A default argument for dbclient -i <privatekey>.
|
||||
Homedir is prepended unless path begins with / */
|
||||
#define DROPBEAR_DEFAULT_CLI_AUTHKEY ".ssh/id_dropbear"
|
||||
|
||||
/* Allow specifying the password for dbclient via the DROPBEAR_PASSWORD
|
||||
* environment variable. */
|
||||
@@ -275,16 +256,8 @@ group1 in Dropbear server too */
|
||||
/* -T server option overrides */
|
||||
#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
|
||||
* scripts etc. This can be overridden with the -P flag.
|
||||
* Homedir is prepended if path begins with ~/
|
||||
*/
|
||||
scripts etc. This can be overridden with the -P flag */
|
||||
#define DROPBEAR_PIDFILE "/var/run/dropbear.pid"
|
||||
|
||||
/* The command to invoke for xauth when using X11 forwarding.
|
||||
@@ -292,11 +265,9 @@ group1 in Dropbear server too */
|
||||
#define XAUTH_COMMAND "/usr/bin/xauth -q"
|
||||
|
||||
|
||||
/* If you want to enable running an sftp server (such as the one included with
|
||||
* OpenSSH), set the path below and set DROPBEAR_SFTPSERVER.
|
||||
* The sftp-server program is not provided by Dropbear itself.
|
||||
* Homedir is prepended if path begins 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.
|
||||
* The sftp-server program is not provided by Dropbear itself */
|
||||
#define DROPBEAR_SFTPSERVER 1
|
||||
#define SFTPSERVER_PATH "/usr/libexec/sftp-server"
|
||||
|
||||
@@ -339,6 +310,5 @@ be overridden at runtime with -I. 0 disables idle timeouts */
|
||||
|
||||
/* The default path. This will often get replaced by the shell */
|
||||
#define DEFAULT_PATH "/usr/bin:/bin"
|
||||
#define DEFAULT_ROOT_PATH "/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
#endif /* DROPBEAR_DEFAULT_OPTIONS_H_ */
|
||||
|
||||
17
dropbear.8
17
dropbear.8
@@ -35,12 +35,6 @@ Don't fork into background.
|
||||
.B \-E
|
||||
Log to standard error rather than syslog.
|
||||
.TP
|
||||
.B \-e
|
||||
Pass on the server environment to all child processes. This is required, for example,
|
||||
if Dropbear is launched on the fly from a SLURM workload manager. The environment is not
|
||||
passed by default. Note that this could expose secrets in environment variables from
|
||||
the calling process - use with caution.
|
||||
.TP
|
||||
.B \-m
|
||||
Don't display the message of the day on login.
|
||||
.TP
|
||||
@@ -66,7 +60,7 @@ and TCP
|
||||
.I port.
|
||||
If just a port is given listen
|
||||
on all addresses.
|
||||
Up to 10 can be specified (default 22 if none specified).
|
||||
up to 10 can be specified (default 22 if none specified).
|
||||
.TP
|
||||
.B \-i
|
||||
Service program mode.
|
||||
@@ -92,7 +86,7 @@ Ensure that traffic is transmitted at a certain interval in seconds. This is
|
||||
useful for working around firewalls or routers that drop connections after
|
||||
a certain period of inactivity. The trade-off is that a session may be
|
||||
closed if there is a temporary lapse of network connectivity. A setting
|
||||
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
|
||||
.B \-I \fIidle_timeout
|
||||
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
|
||||
@@ -102,8 +96,7 @@ Set the number of authentication attempts allowed per connection. If unspecified
|
||||
.TP
|
||||
.B \-c \fIforced_command
|
||||
Disregard the command provided by the user and always run \fIforced_command\fR. This also
|
||||
overrides any authorized_keys command= option. The original command is saved in the
|
||||
SSH_ORIGINAL_COMMAND environment variable (see below).
|
||||
overrides any authorized_keys command= option.
|
||||
.TP
|
||||
.B \-V
|
||||
Print the version
|
||||
@@ -140,10 +133,6 @@ Don't allow X11 forwarding for this connection
|
||||
Disable PTY allocation. Note that a user can still obtain most of the
|
||||
same functionality with other means even if no-pty is set.
|
||||
|
||||
.TP
|
||||
.B restrict
|
||||
Applies all the no- restrictions listed above.
|
||||
|
||||
.TP
|
||||
.B command=\fR"\fIforced_command\fR"
|
||||
Disregard the command provided by the user and always run \fIforced_command\fR.
|
||||
|
||||
@@ -9,7 +9,7 @@ dropbearconvert \- convert between Dropbear and OpenSSH private key formats
|
||||
.I output_file
|
||||
.SH DESCRIPTION
|
||||
.B Dropbear
|
||||
and
|
||||
and
|
||||
.B OpenSSH
|
||||
SSH implementations have different private key formats.
|
||||
.B dropbearconvert
|
||||
@@ -24,15 +24,15 @@ first.
|
||||
.SH ARGUMENTS
|
||||
.TP
|
||||
.I input_type
|
||||
Either
|
||||
Either
|
||||
.I dropbear
|
||||
or
|
||||
or
|
||||
.I openssh
|
||||
.TP
|
||||
.I output_type
|
||||
Either
|
||||
Either
|
||||
.I dropbear
|
||||
or
|
||||
or
|
||||
.I openssh
|
||||
.TP
|
||||
.I input_file
|
||||
@@ -40,15 +40,6 @@ An existing Dropbear or OpenSSH private key file
|
||||
.TP
|
||||
.I output_file
|
||||
The path to write the converted private key file. For client authentication ~/.ssh/id_dropbear is loaded by default
|
||||
.SH SUPPORTED FORMATS
|
||||
.B dropbearconvert
|
||||
can read OpenSSH format files, and older PEM format files (
|
||||
.B ssh-keygen
|
||||
.I -m PEM
|
||||
).
|
||||
.B dropbearconvert
|
||||
will write OpenSSH format files, usable with OpenSSH 6.5 and later.
|
||||
Reading OpenSSH format DSS files or PKCS8 files is not currently supported.
|
||||
.SH EXAMPLE
|
||||
# dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_dropbear
|
||||
.SH AUTHOR
|
||||
|
||||
@@ -69,7 +69,7 @@ int main(int argc, char ** argv) {
|
||||
|
||||
#if DEBUG_TRACE
|
||||
/* It's hard for it to get in the way _too_ much */
|
||||
debug_trace = DROPBEAR_VERBOSE_LEVEL;
|
||||
debug_trace = 1;
|
||||
#endif
|
||||
|
||||
/* get the commandline options */
|
||||
|
||||
@@ -195,7 +195,7 @@ int main(int argc, char ** argv) {
|
||||
break;
|
||||
#if DEBUG_TRACE
|
||||
case 'v':
|
||||
debug_trace = DROPBEAR_VERBOSE_LEVEL;
|
||||
debug_trace = 1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -309,7 +309,8 @@ static int printpubfile(const char* filename) {
|
||||
err = DROPBEAR_SUCCESS;
|
||||
|
||||
out:
|
||||
buf_burn_free(buf);
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
buf = NULL;
|
||||
if (key) {
|
||||
sign_key_free(key);
|
||||
@@ -341,7 +342,7 @@ static void printpubkey(sign_key * key, int keytype) {
|
||||
err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
|
||||
|
||||
if (err != CRYPT_OK) {
|
||||
dropbear_exit("base64 failed");
|
||||
fprintf(stderr, "base64 failed");
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
/* string "[identifier]" */
|
||||
identifier = (unsigned char*)buf_getstring(buf, &identifier_len);
|
||||
|
||||
if (strcmp (key_ident, "sk-ecdsa-sha2-nistp256@openssh.com") == 0) {
|
||||
if (strcmp (identifier, "nistp256") != 0) {
|
||||
TRACE(("mismatching identifiers"))
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (key_ident_len != identifier_len + strlen ("ecdsa-sha2-")) {
|
||||
TRACE(("Bad identifier lengths"))
|
||||
goto out;
|
||||
}
|
||||
if (memcmp(&key_ident[strlen ("ecdsa-sha2-")], identifier, identifier_len) != 0) {
|
||||
TRACE(("mismatching identifiers"))
|
||||
goto out;
|
||||
}
|
||||
if (key_ident_len != identifier_len + strlen("ecdsa-sha2-")) {
|
||||
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++) {
|
||||
|
||||
17
ed25519.c
17
ed25519.c
@@ -38,25 +38,14 @@
|
||||
* The key will have the same format as buf_put_ed25519_key.
|
||||
* These should be freed with ed25519_key_free.
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key,
|
||||
enum signkey_type expect_keytype) {
|
||||
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key) {
|
||||
|
||||
|
||||
unsigned int len, typelen;
|
||||
char *keytype = NULL;
|
||||
enum signkey_type buf_keytype;
|
||||
unsigned int len;
|
||||
|
||||
TRACE(("enter buf_get_ed25519_pub_key"))
|
||||
dropbear_assert(key != NULL);
|
||||
|
||||
/* consume and check the key string */
|
||||
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;
|
||||
}
|
||||
buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */
|
||||
|
||||
len = buf_getint(buf);
|
||||
if (len != CURVE25519_LEN || buf->len - buf->pos < len) {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "signkey.h"
|
||||
|
||||
#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
|
||||
int buf_ed25519_verify(buffer * buf, const dropbear_ed25519_key *key, const buffer *data_buf);
|
||||
#endif
|
||||
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key,
|
||||
enum signkey_type expect_keytype);
|
||||
int buf_get_ed25519_pub_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_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 i;
|
||||
buffer *input = buf_new(100000);
|
||||
int quiet = 0;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
printf("arg %s\n", argv[i]);
|
||||
#if DEBUG_TRACE
|
||||
if (strcmp(argv[i], "-v") == 0) {
|
||||
debug_trace++;
|
||||
fprintf(stderr, "debug level -> %d\n", debug_trace);
|
||||
debug_trace = 1;
|
||||
TRACE(("debug printing on"))
|
||||
}
|
||||
#endif
|
||||
if (strcmp(argv[i], "-q") == 0) {
|
||||
printf("Running quiet\n");
|
||||
quiet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int old_fuzz_wrapfds = 0;
|
||||
@@ -34,19 +30,12 @@ int main(int argc, char ** argv) {
|
||||
buf_readfile(input, fn);
|
||||
buf_setpos(input, 0);
|
||||
|
||||
/* Run twice to catch problems with statefulness */
|
||||
fuzz.wrapfds = old_fuzz_wrapfds;
|
||||
if (!quiet) {
|
||||
printf("Running %s once \n", fn);
|
||||
}
|
||||
printf("Running %s once \n", fn);
|
||||
LLVMFuzzerTestOneInput(input->data, input->len);
|
||||
if (!quiet) {
|
||||
printf("Running %s twice \n", fn);
|
||||
}
|
||||
printf("Running %s twice \n", fn);
|
||||
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 */
|
||||
old_fuzz_wrapfds = fuzz.wrapfds;
|
||||
@@ -57,10 +46,3 @@ int main(int argc, char ** argv) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Just to let it link
|
||||
size_t LLVMFuzzerMutate(uint8_t *UNUSED(Data), size_t UNUSED(Size), size_t UNUSED(MaxSize)) {
|
||||
printf("standalone fuzzer harness shouldn't call LLVMFuzzerMutate");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,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, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xb1,
|
||||
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,
|
||||
0xa3
|
||||
};
|
||||
static unsigned int keyr_len = 805;
|
||||
static unsigned char keye[] = {
|
||||
unsigned int keyr_len = 805;
|
||||
unsigned char keye[] = {
|
||||
0x00, 0x00, 0x00, 0x13, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x73, 0x68,
|
||||
0x61, 0x32, 0x2d, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00,
|
||||
0x00, 0x00, 0x08, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00,
|
||||
@@ -85,8 +84,8 @@ static unsigned char keye[] = {
|
||||
0x3c, 0x58, 0x28, 0x70, 0x9b, 0x23, 0x39, 0x51, 0xd7, 0xbc, 0xa7, 0x1a,
|
||||
0xf5, 0xb4, 0x23, 0xd3, 0xf6, 0x17, 0xa6, 0x9c, 0x02
|
||||
};
|
||||
static unsigned int keye_len = 141;
|
||||
static unsigned char keyd[] = {
|
||||
unsigned int keye_len = 141;
|
||||
unsigned char keyd[] = {
|
||||
0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00,
|
||||
0x00, 0x00, 0x81, 0x00, 0xb0, 0x02, 0x19, 0x8b, 0xf3, 0x46, 0xf9, 0xc5,
|
||||
0x47, 0x78, 0x3d, 0x7f, 0x04, 0x10, 0x0a, 0x43, 0x8e, 0x00, 0x9e, 0xa4,
|
||||
@@ -127,8 +126,8 @@ static unsigned char keyd[] = {
|
||||
0x7b, 0xac, 0xaa, 0x0c, 0xa2, 0xca, 0x7b, 0xa8, 0xd4, 0xdf, 0x68, 0x56,
|
||||
0xf9, 0x39
|
||||
};
|
||||
static unsigned int keyd_len = 458;
|
||||
static unsigned char keyed25519[] = {
|
||||
unsigned int keyd_len = 458;
|
||||
unsigned char keyed25519[] = {
|
||||
0x00, 0x00, 0x00, 0x0b, 0x73, 0x73, 0x68, 0x2d, 0x65, 0x64, 0x32, 0x35,
|
||||
0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb3, 0x79, 0x06, 0xe5,
|
||||
0x9b, 0xe7, 0xe4, 0x6e, 0xec, 0xfe, 0xa5, 0x39, 0x21, 0x7c, 0xf6, 0x66,
|
||||
@@ -137,4 +136,4 @@ static unsigned char keyed25519[] = {
|
||||
0xa4, 0xd5, 0xe9, 0x23, 0xfe, 0x8e, 0xd6, 0xd4, 0xf9, 0xb1, 0x11, 0x69,
|
||||
0x7c, 0x57, 0x52, 0x0e, 0x41, 0xdb, 0x1b, 0x12, 0x87, 0xfa, 0xc9
|
||||
};
|
||||
static unsigned int keyed25519_len = 83;
|
||||
unsigned int keyed25519_len = 83;
|
||||
@@ -17,33 +17,25 @@ static const double CHANCE_WRITE2 = 0.5;
|
||||
|
||||
struct fdwrap {
|
||||
enum wrapfd_mode mode;
|
||||
buffer *buf;
|
||||
int closein;
|
||||
int closeout;
|
||||
};
|
||||
|
||||
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1] = {{UNUSED, 0, 0}};
|
||||
static int wrapfd_maxfd = -1;
|
||||
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
|
||||
/* for quick selection of in-use descriptors */
|
||||
static int wrap_used[IOWRAP_MAXFD+1];
|
||||
static unsigned int nused;
|
||||
static unsigned short rand_state[3];
|
||||
static buffer *input_buf;
|
||||
static int devnull_fd = -1;
|
||||
|
||||
static void wrapfd_remove(int fd);
|
||||
|
||||
void wrapfd_setup(buffer *buf) {
|
||||
void wrapfd_setup(void) {
|
||||
TRACE(("wrapfd_setup"))
|
||||
|
||||
// clean old ones
|
||||
int i;
|
||||
for (i = 0; i <= wrapfd_maxfd; i++) {
|
||||
if (wrap_fds[i].mode != UNUSED) {
|
||||
wrapfd_remove(i);
|
||||
}
|
||||
}
|
||||
wrapfd_maxfd = -1;
|
||||
nused = 0;
|
||||
memset(wrap_fds, 0x0, sizeof(wrap_fds));
|
||||
memset(wrap_used, 0x0, sizeof(wrap_used));
|
||||
|
||||
memset(rand_state, 0x0, sizeof(rand_state));
|
||||
wrapfd_setseed(50);
|
||||
input_buf = buf;
|
||||
}
|
||||
|
||||
void wrapfd_setseed(uint32_t seed) {
|
||||
@@ -51,55 +43,39 @@ void wrapfd_setseed(uint32_t seed) {
|
||||
nrand48(rand_state);
|
||||
}
|
||||
|
||||
int wrapfd_new_fuzzinput() {
|
||||
if (devnull_fd == -1) {
|
||||
devnull_fd = open("/dev/null", O_RDONLY);
|
||||
assert(devnull_fd != -1);
|
||||
}
|
||||
|
||||
int fd = dup(devnull_fd);
|
||||
assert(fd != -1);
|
||||
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
|
||||
TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
|
||||
assert(fd >= 0);
|
||||
assert(fd <= IOWRAP_MAXFD);
|
||||
assert(wrap_fds[fd].mode == UNUSED);
|
||||
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].closeout = 0;
|
||||
wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
|
||||
wrap_used[nused] = fd;
|
||||
|
||||
return fd;
|
||||
nused++;
|
||||
}
|
||||
|
||||
int wrapfd_new_dummy() {
|
||||
if (devnull_fd == -1) {
|
||||
devnull_fd = open("/dev/null", O_RDONLY);
|
||||
assert(devnull_fd != -1);
|
||||
}
|
||||
|
||||
int fd = dup(devnull_fd);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (fd > IOWRAP_MAXFD) {
|
||||
close(fd);
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
assert(wrap_fds[fd].mode == UNUSED);
|
||||
wrap_fds[fd].mode = DUMMY;
|
||||
wrap_fds[fd].closein = 0;
|
||||
wrap_fds[fd].closeout = 0;
|
||||
wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
static void wrapfd_remove(int fd) {
|
||||
void wrapfd_remove(int fd) {
|
||||
unsigned int i, j;
|
||||
TRACE(("wrapfd_remove %d", fd))
|
||||
assert(fd >= 0);
|
||||
assert(fd <= IOWRAP_MAXFD);
|
||||
assert(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) {
|
||||
@@ -113,6 +89,7 @@ int wrapfd_close(int fd) {
|
||||
|
||||
int wrapfd_read(int fd, void *out, size_t count) {
|
||||
size_t maxread;
|
||||
buffer *buf;
|
||||
|
||||
if (!fuzz.wrapfds) {
|
||||
return read(fd, out, count);
|
||||
@@ -138,18 +115,18 @@ int wrapfd_read(int fd, void *out, size_t count) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (input_buf && wrap_fds[fd].mode == COMMONBUF) {
|
||||
maxread = MIN(input_buf->len - input_buf->pos, count);
|
||||
buf = wrap_fds[fd].buf;
|
||||
if (buf) {
|
||||
maxread = MIN(buf->len - buf->pos, count);
|
||||
/* returns 0 if buf is EOF, as intended */
|
||||
if (maxread > 0) {
|
||||
maxread = nrand48(rand_state) % maxread + 1;
|
||||
}
|
||||
memcpy(out, buf_getptr(input_buf, maxread), maxread);
|
||||
buf_incrpos(input_buf, maxread);
|
||||
memcpy(out, buf_getptr(buf, maxread), maxread);
|
||||
buf_incrpos(buf, maxread);
|
||||
return maxread;
|
||||
}
|
||||
|
||||
// return fixed output, of random length
|
||||
maxread = MIN(MAX_RANDOM_IN, count);
|
||||
maxread = nrand48(rand_state) % maxread + 1;
|
||||
memset(out, 0xef, maxread);
|
||||
@@ -198,6 +175,8 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
int ret = 0;
|
||||
int fdlist[IOWRAP_MAXFD+1];
|
||||
|
||||
memset(fdlist, 0x0, sizeof(fdlist));
|
||||
|
||||
if (!fuzz.wrapfds) {
|
||||
return select(nfds, readfds, writefds, exceptfds, timeout);
|
||||
}
|
||||
@@ -265,15 +244,3 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fuzz_kill(pid_t pid, int sig) {
|
||||
if (fuzz.fuzzing) {
|
||||
TRACE(("fuzz_kill ignoring pid %d signal %d", (pid), sig))
|
||||
if (sig >= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return kill(pid, sig);
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
#ifndef FUZZ_WRAPFD_H
|
||||
#define FUZZ_WRAPFD_H
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
|
||||
enum wrapfd_mode {
|
||||
UNUSED = 0,
|
||||
COMMONBUF, // using the common buffer
|
||||
DUMMY, // reads return fixed output, of random length
|
||||
PLAIN,
|
||||
INPROGRESS,
|
||||
RANDOMIN
|
||||
};
|
||||
|
||||
// buf is a common buffer read by all wrapped FDs. doesn't take ownership of buf
|
||||
void wrapfd_setup(buffer *buf);
|
||||
void wrapfd_setup(void);
|
||||
void wrapfd_setseed(uint32_t seed);
|
||||
int wrapfd_new_fuzzinput(void);
|
||||
int wrapfd_new_dummy(void);
|
||||
// doesn't take ownership of buf. buf is optional.
|
||||
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode);
|
||||
|
||||
// called via #defines for read/write/select
|
||||
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,
|
||||
fd_set *exceptfds, struct timeval *timeout);
|
||||
int wrapfd_close(int fd);
|
||||
int fuzz_kill(pid_t pid, int sig);
|
||||
|
||||
#endif // FUZZ_WRAPFD_H
|
||||
|
||||
60
fuzz.h
60
fuzz.h
@@ -8,24 +8,17 @@
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "algo.h"
|
||||
#include "netio.h"
|
||||
#include "fuzz-wrapfd.h"
|
||||
|
||||
// once per process
|
||||
void fuzz_common_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.
|
||||
// returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
|
||||
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_client(const uint8_t *Data, size_t Size, int skip_kexmaths);
|
||||
int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths);
|
||||
const void* fuzz_get_algo(const algo_type *algos, const char* name);
|
||||
|
||||
// fuzzer functions that intrude into general code
|
||||
@@ -34,18 +27,10 @@ int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename,
|
||||
const char* algo, unsigned int algolen,
|
||||
const unsigned char* keyblob, unsigned int keybloblen);
|
||||
extern const char * const * fuzz_signkey_names;
|
||||
void fuzz_seed(const unsigned char* dat, unsigned int len);
|
||||
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_seed(void);
|
||||
void fuzz_get_socket_address(int fd, char **local_host, char **local_port,
|
||||
char **remote_host, char **remote_port, int host_lookup);
|
||||
void fuzz_fake_send_kexdh_reply(void);
|
||||
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
|
||||
#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 read(fd, buf, count) wrapfd_read(fd, buf, count)
|
||||
#define close(fd) wrapfd_close(fd)
|
||||
#define kill(pid, sig) fuzz_kill(pid, sig)
|
||||
#endif // FUZZ_SKIP_WRAP
|
||||
|
||||
struct dropbear_fuzz_options {
|
||||
@@ -68,47 +52,21 @@ struct dropbear_fuzz_options {
|
||||
|
||||
// whether to skip slow bignum maths
|
||||
int skip_kexmaths;
|
||||
// whether is svr_postauth mode
|
||||
int svr_postauth;
|
||||
|
||||
// dropbear_exit() jumps back
|
||||
int do_jmp;
|
||||
sigjmp_buf jmp;
|
||||
|
||||
// write out decrypted session data to this FD if it is set
|
||||
// flag - this needs to be set manually in cli-main.c etc
|
||||
int dumping;
|
||||
// the file descriptor
|
||||
int recv_dumpfd;
|
||||
|
||||
// avoid filling fuzzing logs, this points to /dev/null
|
||||
FILE *fake_stderr;
|
||||
uid_t pw_uid;
|
||||
gid_t pw_gid;
|
||||
char* pw_name;
|
||||
char* pw_dir;
|
||||
char* pw_shell;
|
||||
char* pw_passwd;
|
||||
};
|
||||
|
||||
extern struct dropbear_fuzz_options fuzz;
|
||||
|
||||
/* guard for when fuzz.h is included by fuzz-common.c */
|
||||
#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
|
||||
|
||||
#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 "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) {
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
@@ -6,29 +6,33 @@
|
||||
#include "algo.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) {
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
@@ -6,38 +6,38 @@
|
||||
#include "algo.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) {
|
||||
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) {
|
||||
return 0;
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fuzz.h"
|
||||
|
||||
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"
|
||||
|
||||
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;
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@
|
||||
|
||||
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
|
||||
# use xargs to split the too-long argument list
|
||||
# -q quiet because travis has a logfile limit
|
||||
echo fuzzcorpus/$f/* | xargs -n 1000 ./$f -q || result=1
|
||||
./$f fuzzcorpus/$f/* || result=1
|
||||
done
|
||||
|
||||
exit $result
|
||||
|
||||
@@ -181,7 +181,8 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename,
|
||||
|
||||
out:
|
||||
if (buf) {
|
||||
buf_burn_free(buf);
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
}
|
||||
|
||||
if (fn_temp) {
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#ifndef DROPBEAR_INCLUDES_H_
|
||||
#define DROPBEAR_INCLUDES_H_
|
||||
|
||||
/* uclibc needs _GNU_SOURCE, maybe other things? */
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "options.h"
|
||||
#include "debug.h"
|
||||
|
||||
@@ -127,10 +130,6 @@
|
||||
#include <sys/random.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef BUNDLED_LIBTOM
|
||||
#include "libtomcrypt/src/headers/tomcrypt.h"
|
||||
#include "libtommath/tommath.h"
|
||||
@@ -175,8 +174,6 @@ typedef u_int32_t uint32_t;
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
extern char** environ;
|
||||
|
||||
#include "fake-rfc2553.h"
|
||||
|
||||
#include "fuzz.h"
|
||||
|
||||
1096
keyimport.c
1096
keyimport.c
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@ ARFLAGS = r
|
||||
EXTRALIBS = ../libtommath/libtommath.a
|
||||
|
||||
#Compilation flags
|
||||
LTC_CFLAGS = -Isrc/headers/ -I$(srcdir)/src/headers/ -I../ -I$(srcdir)/../ -DLTC_SOURCE -I../libtommath/ -I$(srcdir)/../libtommath/ $(CFLAGS) $(CPPFLAGS)
|
||||
LTC_CFLAGS = -Isrc/headers/ -I$(srcdir)/src/headers/ -I../ -I$(srcdir)/../ -DLTC_SOURCE -I../libtommath/ -I$(srcdir)/../libtommath/ $(CFLAGS)
|
||||
LTC_LDFLAGS = $(LDFLAGS) $(EXTRALIBS)
|
||||
VERSION=1.18.1
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
#if DROPBEAR_AES
|
||||
#define LTC_RIJNDAEL
|
||||
#endif
|
||||
/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
|
||||
* (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
|
||||
#if DROPBEAR_TWOFISH
|
||||
#define LTC_TWOFISH
|
||||
#define LTC_TWOFISH_SMALL
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_3DES
|
||||
#define LTC_DES
|
||||
@@ -50,9 +56,7 @@
|
||||
#define LTC_SHA256
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_SHA1
|
||||
#define LTC_SHA1
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_MD5
|
||||
#define LTC_MD5
|
||||
|
||||
@@ -8,7 +8,6 @@ srcdir=@srcdir@
|
||||
# So that libtommath can include Dropbear headers for options and m_burn()
|
||||
CFLAGS += -I$(srcdir) -I../libtomcrypt/src/headers/ -I$(srcdir)/../libtomcrypt/src/headers/ -I../ -I$(srcdir)/../
|
||||
CFLAGS += -Wno-deprecated
|
||||
CFLAGS += $(CPPFLAGS)
|
||||
|
||||
V = 1
|
||||
|
||||
|
||||
@@ -3,13 +3,11 @@
|
||||
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
|
||||
/* SPDX-License-Identifier: Unlicense */
|
||||
|
||||
/* Dropbear sets this separately, avoid platform code */
|
||||
mp_err(*s_mp_rand_source)(void *out, size_t size) = NULL;
|
||||
mp_err(*s_mp_rand_source)(void *out, size_t size) = s_mp_rand_platform;
|
||||
|
||||
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;
|
||||
s_mp_rand_source = (source == NULL) ? s_mp_rand_platform : source;
|
||||
}
|
||||
|
||||
mp_err mp_rand(mp_int *a, int digits)
|
||||
|
||||
@@ -1316,8 +1316,6 @@
|
||||
#undef BN_S_MP_KARATSUBA_SQR_C
|
||||
#undef BN_S_MP_TOOM_MUL_C
|
||||
#undef BN_S_MP_TOOM_SQR_C
|
||||
/* Dropbear uses its own random source */
|
||||
#undef BN_S_MP_RAND_PLATFORM_C
|
||||
|
||||
#include "dbmalloc.h"
|
||||
#define MP_MALLOC m_malloc
|
||||
|
||||
@@ -139,7 +139,7 @@ struct Listener * get_listener(int type, const void* typedata,
|
||||
struct Listener* listener;
|
||||
|
||||
for (i = 0, listener = ses.listeners[i]; i < ses.listensize; i++) {
|
||||
if (listener && listener->type == type
|
||||
if (listener->type == type
|
||||
&& match(typedata, listener->typedata)) {
|
||||
return listener;
|
||||
}
|
||||
|
||||
93
netio.c
93
netio.c
@@ -20,7 +20,6 @@ struct dropbear_progress_connection {
|
||||
|
||||
char* errstring;
|
||||
char *bind_address, *bind_port;
|
||||
enum dropbear_prio prio;
|
||||
};
|
||||
|
||||
/* Deallocate a progress connection. Removes from the pending list if iter!=NULL.
|
||||
@@ -111,7 +110,6 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
|
||||
|
||||
ses.maxfd = MAX(ses.maxfd, c->sock);
|
||||
set_sock_nodelay(c->sock);
|
||||
set_sock_priority(c->sock, c->prio);
|
||||
setnonblocking(c->sock);
|
||||
|
||||
#if DROPBEAR_CLIENT_TCP_FAST_OPEN
|
||||
@@ -174,8 +172,8 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
|
||||
|
||||
/* Connect via TCP to a host. */
|
||||
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, enum dropbear_prio prio)
|
||||
connect_callback cb, void* cb_data,
|
||||
const char* bind_address, const char* bind_port)
|
||||
{
|
||||
struct dropbear_progress_connection *c = NULL;
|
||||
int err;
|
||||
@@ -187,17 +185,9 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons
|
||||
c->sock = -1;
|
||||
c->cb = cb;
|
||||
c->cb_data = cb_data;
|
||||
c->prio = prio;
|
||||
|
||||
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));
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
@@ -366,7 +356,12 @@ void set_listen_fast_open(int sock) {
|
||||
void set_sock_priority(int sock, enum dropbear_prio prio) {
|
||||
|
||||
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 (fuzz.fuzzing) {
|
||||
@@ -374,51 +369,37 @@ void set_sock_priority(int sock, enum dropbear_prio prio) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Don't log ENOTSOCK errors so that this can harmlessly be called
|
||||
* on a client '-J' proxy pipe */
|
||||
|
||||
#ifdef IP_TOS
|
||||
/* 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.
|
||||
*/
|
||||
/* set the TOS bit for either ipv4 or ipv6 */
|
||||
#ifdef IPTOS_LOWDELAY
|
||||
if (prio == DROPBEAR_PRIO_LOWDELAY) {
|
||||
val = 0x48; /* IPTOS_DSCP_AF21 */
|
||||
} else {
|
||||
val = 0; /* default */
|
||||
iptos_val = IPTOS_LOWDELAY;
|
||||
} else if (prio == DROPBEAR_PRIO_BULK) {
|
||||
iptos_val = IPTOS_THROUGHPUT;
|
||||
}
|
||||
#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) {
|
||||
TRACE(("Couldn't set IPV6_TCLASS (%s)", strerror(errno)));
|
||||
}
|
||||
#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) {
|
||||
TRACE(("Couldn't set IP_TOS (%s)", strerror(errno)));
|
||||
}
|
||||
#endif /* IP_TOS */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINUX_PKT_SCHED_H
|
||||
/* Set scheduling priority within the local Linux network stack */
|
||||
if (prio == DROPBEAR_PRIO_LOWDELAY) {
|
||||
val = TC_PRIO_INTERACTIVE;
|
||||
} else {
|
||||
val = 0;
|
||||
so_prio_val = TC_PRIO_INTERACTIVE;
|
||||
} else if (prio == DROPBEAR_PRIO_BULK) {
|
||||
so_prio_val = TC_PRIO_BULK;
|
||||
}
|
||||
/* 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) {
|
||||
TRACE(("Couldn't set SO_PRIORITY (%s)", strerror(errno)))
|
||||
}
|
||||
@@ -472,16 +453,8 @@ int dropbear_listen(const char* address, const char* port,
|
||||
struct linger linger;
|
||||
int val;
|
||||
int sock;
|
||||
uint16_t *allocated_lport_p = NULL;
|
||||
int allocated_lport = 0;
|
||||
|
||||
TRACE(("enter dropbear_listen"))
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing) {
|
||||
return fuzz_dropbear_listen(address, port, socks, sockcount, errstring, maxfd);
|
||||
}
|
||||
#endif
|
||||
TRACE(("enter dropbear_listen"))
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
|
||||
@@ -517,15 +490,20 @@ int dropbear_listen(const char* address, const char* port,
|
||||
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)
|
||||
* causing problems for tcpip-forward.
|
||||
* Caller can do a get_socket_address to discover assigned-port
|
||||
* hence, use same port for all address families */
|
||||
allocated_lport = 0;
|
||||
* causing problems for tcpip-forward
|
||||
* caller can do a get_socket_address to discover assigned-port
|
||||
* hence, use same port for all address families
|
||||
*/
|
||||
u_int16_t *allocated_lport_p = NULL;
|
||||
int allocated_lport = 0;
|
||||
|
||||
nsock = 0;
|
||||
for (res = res0; res != NULL && nsock < sockcount;
|
||||
res = res->ai_next) {
|
||||
|
||||
if (allocated_lport > 0) {
|
||||
if (AF_INET == res->ai_family) {
|
||||
allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
|
||||
@@ -536,8 +514,11 @@ int dropbear_listen(const char* address, const char* port,
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
if (sock < 0) {
|
||||
err = errno;
|
||||
TRACE(("socket() failed"))
|
||||
@@ -561,6 +542,7 @@ int dropbear_listen(const char* address, const char* port,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
set_sock_nodelay(sock);
|
||||
|
||||
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
@@ -582,6 +564,7 @@ int dropbear_listen(const char* address, const char* port,
|
||||
}
|
||||
|
||||
*maxfd = MAX(*maxfd, sock);
|
||||
|
||||
nsock++;
|
||||
}
|
||||
|
||||
|
||||
8
netio.h
8
netio.h
@@ -6,8 +6,9 @@
|
||||
#include "queue.h"
|
||||
|
||||
enum dropbear_prio {
|
||||
DROPBEAR_PRIO_NORMAL = 0, /* the rest - tcp-fwd, scp, rsync, git, etc */
|
||||
DROPBEAR_PRIO_LOWDELAY, /* pty shell, x11 */
|
||||
DROPBEAR_PRIO_DEFAULT = 10,
|
||||
DROPBEAR_PRIO_LOWDELAY = 11,
|
||||
DROPBEAR_PRIO_BULK = 12,
|
||||
};
|
||||
|
||||
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 */
|
||||
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,
|
||||
enum dropbear_prio prio);
|
||||
connect_callback cb, void *cb_data, const char* bind_address, const char* bind_port);
|
||||
|
||||
/* Sets up for select() */
|
||||
void set_connect_fds(fd_set *writefd);
|
||||
|
||||
5
packet.c
5
packet.c
@@ -344,12 +344,7 @@ void decrypt_packet() {
|
||||
if (checkmac() != DROPBEAR_SUCCESS) {
|
||||
dropbear_exit("Integrity error");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
fuzz_dump(ses.readbuf->data, ses.readbuf->len);
|
||||
#endif
|
||||
|
||||
/* get padding length */
|
||||
buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
|
||||
|
||||
77
release.sh
77
release.sh
@@ -1,47 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$1" = '--testrel' ]; then
|
||||
# --testrel won't check changelog version correctness and will build in a temporary dir
|
||||
TESTREL=1
|
||||
else
|
||||
TESTREL=0
|
||||
VERSION=$(echo '#include "sysoptions.h"\necho DROPBEAR_VERSION' | cpp - | sh)
|
||||
echo Releasing version "$VERSION" ...
|
||||
if ! head -n1 CHANGES | grep -q $VERSION ; then
|
||||
echo "CHANGES needs updating"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=$(echo '#include "default_options.h"\n#include "sysoptions.h"\necho DROPBEAR_VERSION' | cpp -DHAVE_CRYPT - | sh)
|
||||
|
||||
if [ $TESTREL -eq 1 ]; then
|
||||
echo Making test tarball for "$VERSION" ...
|
||||
echo Not checking version mismatches.
|
||||
WORKDIR=$(mktemp -d)
|
||||
TARSUFFIX="-testrel"
|
||||
else
|
||||
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=""
|
||||
if ! head -n1 debian/changelog | grep -q $VERSION ; then
|
||||
echo "debian/changelog needs updating"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RELDIR=$WORKDIR/dropbear-$VERSION
|
||||
ARCHIVE=${RELDIR}${TARSUFFIX}.tar.bz2
|
||||
|
||||
head -n1 CHANGES
|
||||
|
||||
if tar --version | grep -q 'GNU tar'; then
|
||||
TAR=tar
|
||||
else
|
||||
TAR=gtar
|
||||
fi
|
||||
#sleep 3
|
||||
|
||||
RELDIR=$PWD/../dropbear-$VERSION
|
||||
ARCHIVE=${RELDIR}.tar.bz2
|
||||
if test -e $RELDIR; then
|
||||
echo "$RELDIR exists"
|
||||
exit 1
|
||||
@@ -52,33 +27,19 @@ if test -e $ARCHIVE; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d .hg ]; then
|
||||
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
|
||||
hg archive "$RELDIR" || exit 2
|
||||
|
||||
chmod -R a+rX $RELDIR
|
||||
(cd "$RELDIR" && autoconf && autoheader) || exit 2
|
||||
|
||||
RELDATE=$(head -n1 CHANGES | cut -d - -f 2)
|
||||
# timezone keeps it consistent, choose a plausible release time
|
||||
RELTIME="22:30:00 +0800"
|
||||
rm -r "$RELDIR/autom4te.cache" || exit 2
|
||||
|
||||
# from https://reproducible-builds.org/docs/archives/
|
||||
TAROPTS="--sort=name --owner=0 --group=0 --numeric-owner"
|
||||
(cd "$RELDIR/.." && $TAR cjf $ARCHIVE $TAROPTS --mtime="$RELDATE $RELTIME" `basename "$RELDIR"`) || exit 2
|
||||
rm "$RELDIR/.hgtags"
|
||||
|
||||
(cd "$RELDIR/.." && tar cjf $ARCHIVE `basename "$RELDIR"`) || exit 2
|
||||
|
||||
ls -l $ARCHIVE
|
||||
openssl sha256 $ARCHIVE
|
||||
echo Done to
|
||||
echo "$ARCHIVE"
|
||||
|
||||
if [ $TESTREL -eq 0 ]; then
|
||||
echo Sign it with
|
||||
echo gpg2 --detach-sign -a -u F29C6773 "$ARCHIVE"
|
||||
fi
|
||||
echo Sign it with
|
||||
echo gpg2 --detach-sign -a -u F29C6773 "$ARCHIVE"
|
||||
|
||||
11
runopts.h
11
runopts.h
@@ -72,15 +72,13 @@ typedef struct svr_runopts {
|
||||
|
||||
int forkbg;
|
||||
|
||||
/* ports and addresses are arrays of the portcount
|
||||
/* ports and addresses are arrays of the portcount
|
||||
listening ports. strings are malloced. */
|
||||
char *ports[DROPBEAR_MAX_PORTS];
|
||||
unsigned int portcount;
|
||||
char *addresses[DROPBEAR_MAX_PORTS];
|
||||
|
||||
int inetdmode;
|
||||
/* Hidden "-2" flag indicates it's re-executing itself */
|
||||
int reexec_child;
|
||||
|
||||
/* Flags indicating whether to use ipv4 and ipv6 */
|
||||
/* not used yet
|
||||
@@ -92,6 +90,7 @@ typedef struct svr_runopts {
|
||||
/* whether to print the MOTD */
|
||||
int domotd;
|
||||
#endif
|
||||
|
||||
int norootlogin;
|
||||
|
||||
#ifdef HAVE_GETGROUPLIST
|
||||
@@ -131,8 +130,6 @@ typedef struct svr_runopts {
|
||||
char *pubkey_plugin_options;
|
||||
#endif
|
||||
|
||||
int pass_on_env;
|
||||
|
||||
} svr_runopts;
|
||||
|
||||
extern svr_runopts svr_opts;
|
||||
@@ -154,7 +151,6 @@ typedef struct cli_runopts {
|
||||
int always_accept_key;
|
||||
int no_hostkey_check;
|
||||
int no_cmd;
|
||||
int quiet;
|
||||
int backgrounded;
|
||||
int is_subsystem;
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
@@ -163,7 +159,6 @@ typedef struct cli_runopts {
|
||||
#if DROPBEAR_CLI_ANYTCPFWD
|
||||
int exit_on_fwd_failure;
|
||||
#endif
|
||||
int disable_trivial_auth;
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
m_list * remotefwds;
|
||||
#endif
|
||||
@@ -197,7 +192,5 @@ void parse_ciphers_macs(void);
|
||||
#endif
|
||||
|
||||
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_ */
|
||||
|
||||
7
scp.c
7
scp.c
@@ -185,7 +185,7 @@ arg_setup(char *host, char *remuser, char *cmd)
|
||||
}
|
||||
|
||||
int
|
||||
do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
|
||||
do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
|
||||
{
|
||||
int pin[2], pout[2], reserved[2];
|
||||
|
||||
@@ -532,7 +532,8 @@ toremote(char *targ, int argc, char **argv)
|
||||
bp = xmalloc(len);
|
||||
(void) snprintf(bp, len, "%s -t %s", cmd, targ);
|
||||
host = cleanhostname(thost);
|
||||
if (do_cmd(host, tuser, bp, &remin, &remout) < 0)
|
||||
if (do_cmd(host, tuser, bp, &remin,
|
||||
&remout, argc) < 0)
|
||||
exit(1);
|
||||
if (response() < 0)
|
||||
exit(1);
|
||||
@@ -583,7 +584,7 @@ tolocal(int argc, char **argv)
|
||||
len = strlen(src) + CMDNEEDS + 20;
|
||||
bp = xmalloc(len);
|
||||
(void) snprintf(bp, len, "%s -f %s", cmd, src);
|
||||
if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
|
||||
if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) {
|
||||
(void) xfree(bp);
|
||||
++errs;
|
||||
continue;
|
||||
|
||||
@@ -64,8 +64,6 @@ void svr_dropbear_log(int priority, const char* format, va_list param);
|
||||
/* Client */
|
||||
void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress, pid_t proxy_cmd_pid) ATTRIB_NORETURN;
|
||||
void cli_connected(int result, int sock, void* userdata, const char *errstring);
|
||||
void cli_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
|
||||
void cli_dropbear_log(int priority, const char* format, va_list param);
|
||||
void cleantext(char* dirtytext);
|
||||
void kill_proxy_command(void);
|
||||
|
||||
@@ -316,7 +314,6 @@ struct clientsession {
|
||||
|
||||
int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
|
||||
for the last type of auth we tried */
|
||||
int is_trivial_auth;
|
||||
int ignore_next_auth_response;
|
||||
#if DROPBEAR_CLI_INTERACT_AUTH
|
||||
int auth_interact_failed; /* flag whether interactive auth can still
|
||||
|
||||
177
signkey.c
177
signkey.c
@@ -28,8 +28,6 @@
|
||||
#include "buffer.h"
|
||||
#include "ssh.h"
|
||||
#include "ecdsa.h"
|
||||
#include "sk-ecdsa.h"
|
||||
#include "sk-ed25519.h"
|
||||
#include "rsa.h"
|
||||
#include "dss.h"
|
||||
#include "ed25519.h"
|
||||
@@ -45,15 +43,9 @@ static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = {
|
||||
"ecdsa-sha2-nistp256",
|
||||
"ecdsa-sha2-nistp384",
|
||||
"ecdsa-sha2-nistp521",
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
"sk-ecdsa-sha2-nistp256@openssh.com",
|
||||
#endif /* DROPBEAR_SK_ECDSA */
|
||||
#endif /* DROPBEAR_ECDSA */
|
||||
#if DROPBEAR_ED25519
|
||||
"ssh-ed25519",
|
||||
#if DROPBEAR_SK_ED25519
|
||||
"sk-ssh-ed25519@openssh.com",
|
||||
#endif /* DROPBEAR_SK_ED25519 */
|
||||
#endif /* DROPBEAR_ED25519 */
|
||||
/* "rsa-sha2-256" is special-cased below since it is only a signature name, not key type */
|
||||
};
|
||||
@@ -188,17 +180,11 @@ signkey_key_ptr(sign_key *key, enum signkey_type type) {
|
||||
switch (type) {
|
||||
#if DROPBEAR_ED25519
|
||||
case DROPBEAR_SIGNKEY_ED25519:
|
||||
#if DROPBEAR_SK_ED25519
|
||||
case DROPBEAR_SIGNKEY_SK_ED25519:
|
||||
#endif
|
||||
return (void**)&key->ed25519key;
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
#if DROPBEAR_ECC_256
|
||||
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
case DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256:
|
||||
#endif
|
||||
return (void**)&key->ecckey256;
|
||||
#endif
|
||||
#if DROPBEAR_ECC_384
|
||||
@@ -249,7 +235,7 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
*type = keytype;
|
||||
|
||||
/* Rewind the buffer back before "ssh-rsa" etc */
|
||||
buf_decrpos(buf, len + 4);
|
||||
buf_incrpos(buf, -len - 4);
|
||||
|
||||
#if DROPBEAR_DSS
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
||||
@@ -274,11 +260,7 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
if (signkey_is_ecdsa(keytype)
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
|| keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
|
||||
#endif
|
||||
) {
|
||||
if (signkey_is_ecdsa(keytype)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck) {
|
||||
if (*eck) {
|
||||
@@ -294,14 +276,10 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
if (keytype == DROPBEAR_SIGNKEY_ED25519
|
||||
#if DROPBEAR_SK_ED25519
|
||||
|| keytype == DROPBEAR_SIGNKEY_SK_ED25519
|
||||
#endif
|
||||
) {
|
||||
if (keytype == DROPBEAR_SIGNKEY_ED25519) {
|
||||
ed25519_key_free(key->ed25519key);
|
||||
key->ed25519key = m_malloc(sizeof(*key->ed25519key));
|
||||
ret = buf_get_ed25519_pub_key(buf, key->ed25519key, keytype);
|
||||
ret = buf_get_ed25519_pub_key(buf, key->ed25519key);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
m_free(key->ed25519key);
|
||||
key->ed25519key = NULL;
|
||||
@@ -309,19 +287,6 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
|
||||
if (0
|
||||
#if DROPBEAR_SK_ED25519
|
||||
|| keytype == DROPBEAR_SIGNKEY_SK_ED25519
|
||||
#endif
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
|| keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
|
||||
#endif
|
||||
) {
|
||||
key->sk_app = buf_getstring(buf, &key->sk_applen);
|
||||
}
|
||||
#endif
|
||||
|
||||
TRACE2(("leave buf_get_pub_key"))
|
||||
|
||||
return ret;
|
||||
@@ -351,7 +316,7 @@ int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
*type = keytype;
|
||||
|
||||
/* Rewind the buffer back before "ssh-rsa" etc */
|
||||
buf_decrpos(buf, len + 4);
|
||||
buf_incrpos(buf, -len - 4);
|
||||
|
||||
#if DROPBEAR_DSS
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
||||
@@ -436,11 +401,7 @@ void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) {
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
if (type == DROPBEAR_SIGNKEY_ED25519
|
||||
#if DROPBEAR_SK_ED25519
|
||||
|| type == DROPBEAR_SIGNKEY_SK_ED25519
|
||||
#endif
|
||||
) {
|
||||
if (type == DROPBEAR_SIGNKEY_ED25519) {
|
||||
buf_put_ed25519_pub_key(pubkeys, key->ed25519key);
|
||||
}
|
||||
#endif
|
||||
@@ -534,52 +495,103 @@ void sign_key_free(sign_key *key) {
|
||||
#endif
|
||||
|
||||
m_free(key->filename);
|
||||
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
|
||||
if (key->sk_app) {
|
||||
m_free(key->sk_app);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_free(key);
|
||||
TRACE2(("leave sign_key_free"))
|
||||
}
|
||||
|
||||
static char * sign_key_sha256_fingerprint(const unsigned char* keyblob,
|
||||
static char hexdig(unsigned char x) {
|
||||
if (x > 0xf)
|
||||
return 'X';
|
||||
|
||||
if (x < 10)
|
||||
return '0' + x;
|
||||
else
|
||||
return 'a' + x - 10;
|
||||
}
|
||||
|
||||
/* Since we're not sure if we'll have md5 or sha1, we present both.
|
||||
* MD5 is used in preference, but sha1 could still be useful */
|
||||
#if DROPBEAR_MD5_HMAC
|
||||
static char * sign_key_md5_fingerprint(const unsigned char* keyblob,
|
||||
unsigned int keybloblen) {
|
||||
|
||||
char * ret;
|
||||
hash_state hs;
|
||||
unsigned char hash[SHA256_HASH_SIZE];
|
||||
unsigned int b64chars, start;
|
||||
unsigned long b64size;
|
||||
const char *prefix = "SHA256:";
|
||||
int err;
|
||||
unsigned char hash[MD5_HASH_SIZE];
|
||||
unsigned int i;
|
||||
unsigned int buflen;
|
||||
|
||||
sha256_init(&hs);
|
||||
sha256_process(&hs, keyblob, keybloblen);
|
||||
sha256_done(&hs, hash);
|
||||
md5_init(&hs);
|
||||
|
||||
/* eg "SHA256:P9szN0L2ls6KxkVv7Bppv3asnZCn03rY7Msm/c8+ZgA"
|
||||
* 256/6 = 42.66 => 43 base64 chars. OpenSSH discards
|
||||
* base64 padding output. */
|
||||
start = strlen(prefix);
|
||||
b64chars = 43;
|
||||
/* space for discarded b64 padding and null terminator */
|
||||
b64size = b64chars + 4;
|
||||
ret = m_malloc(start + b64size);
|
||||
/* skip the size int of the string - this is a bit messy */
|
||||
md5_process(&hs, keyblob, keybloblen);
|
||||
|
||||
memcpy(ret, prefix, start);
|
||||
err = base64_encode(hash, SHA256_HASH_SIZE, &ret[start], &b64size);
|
||||
if (err != CRYPT_OK) {
|
||||
dropbear_exit("base64 failed");
|
||||
md5_done(&hs, hash);
|
||||
|
||||
/* "md5 hexfingerprinthere\0", each hex digit is "AB:" etc */
|
||||
buflen = 4 + 3*MD5_HASH_SIZE;
|
||||
ret = (char*)m_malloc(buflen);
|
||||
|
||||
memset(ret, 'Z', buflen);
|
||||
strcpy(ret, "md5 ");
|
||||
|
||||
for (i = 0; i < MD5_HASH_SIZE; i++) {
|
||||
unsigned int pos = 4 + i*3;
|
||||
ret[pos] = hexdig(hash[i] >> 4);
|
||||
ret[pos+1] = hexdig(hash[i] & 0x0f);
|
||||
ret[pos+2] = ':';
|
||||
}
|
||||
ret[start + b64chars] = '\0';
|
||||
ret[buflen-1] = 0x0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This will return a freshly malloced string */
|
||||
#else /* use SHA1 rather than MD5 for fingerprint */
|
||||
static char * sign_key_sha1_fingerprint(const unsigned char* keyblob,
|
||||
unsigned int keybloblen) {
|
||||
|
||||
char * ret;
|
||||
hash_state hs;
|
||||
unsigned char hash[SHA1_HASH_SIZE];
|
||||
unsigned int i;
|
||||
unsigned int buflen;
|
||||
|
||||
sha1_init(&hs);
|
||||
|
||||
/* skip the size int of the string - this is a bit messy */
|
||||
sha1_process(&hs, keyblob, keybloblen);
|
||||
|
||||
sha1_done(&hs, hash);
|
||||
|
||||
/* "sha1!! hexfingerprinthere\0", each hex digit is "AB:" etc */
|
||||
buflen = 7 + 3*SHA1_HASH_SIZE;
|
||||
ret = (char*)m_malloc(buflen);
|
||||
|
||||
strcpy(ret, "sha1!! ");
|
||||
|
||||
for (i = 0; i < SHA1_HASH_SIZE; i++) {
|
||||
unsigned int pos = 7 + 3*i;
|
||||
ret[pos] = hexdig(hash[i] >> 4);
|
||||
ret[pos+1] = hexdig(hash[i] & 0x0f);
|
||||
ret[pos+2] = ':';
|
||||
}
|
||||
ret[buflen-1] = 0x0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MD5/SHA1 switch */
|
||||
|
||||
/* This will return a freshly malloced string, containing a fingerprint
|
||||
* in either sha1 or md5 */
|
||||
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen) {
|
||||
return sign_key_sha256_fingerprint(keyblob, keybloblen);
|
||||
|
||||
#if DROPBEAR_MD5_HMAC
|
||||
return sign_key_md5_fingerprint(keyblob, keybloblen);
|
||||
#else
|
||||
return sign_key_sha1_fingerprint(keyblob, keybloblen);
|
||||
#endif
|
||||
}
|
||||
|
||||
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
|
||||
@@ -627,7 +639,6 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
|
||||
}
|
||||
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
|
||||
/* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE.
|
||||
* If FAILURE is returned, the position of
|
||||
* buf is undefined. If SUCCESS is returned, buf will be positioned after the
|
||||
@@ -684,22 +695,6 @@ int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype,
|
||||
return buf_ed25519_verify(buf, key->ed25519key, data_buf);
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
if (keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck && *eck) {
|
||||
return buf_sk_ecdsa_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_SK_ED25519
|
||||
if (keytype == DROPBEAR_SIGNKEY_SK_ED25519) {
|
||||
dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck && *eck) {
|
||||
return buf_sk_ed25519_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dropbear_exit("Non-matching signing type");
|
||||
return DROPBEAR_FAILURE;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user