Compare commits

..

51 Commits

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

14
.gitignore vendored
View File

@@ -6,7 +6,6 @@
*.bbg
*.prof
.*.swp
/obj
/autom4te.cache
/config.log
/config.status
@@ -20,14 +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/
/test/init/
/test/fakekey
.vscode/

2
.hgignore Normal file
View File

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

29
.hgsigs Normal file
View File

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

61
.hgtags Normal file
View File

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

36
.travis.yml Normal file
View File

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

389
CHANGES
View File

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

View File

@@ -1,88 +1,75 @@
## Developer Notes
# Developer Notes
#### Building
## Building
See [INSTALL.md](INSTALL.md) for build instructions.
[SMALL.md](SMALL.md) has hints for building smaller binaries, also see comments in [default_options.h](./src/default_options.h).
See [INSTALL](INSTALL) for build instructions.
[SMALL](SMALL) has hints for building smaller binaries, also see comments
in default_options.h.
Debug symbols can be generated by adding `-g` to `CFLAGS` environment variable.
```
export CFLAGS="$CFLAGS -g"
```
## Debug printing
#### File dependencies
The GitHub [test build script](./.github/workflows/build.yml) requires the [default_options.h](./src/default_options.h) be at the top of the repository tree.
The script uses the file to generate `localoptions.h` with various features enabled/disabled.
Set `#define DEBUG_TRACE 1` in localoptions.h to enable a `-v` option
for dropbear and dbclient. That prints various details of the session. For
development running `dropbear -F -E` is useful to run in the foreground. You
can set `#define DEBUG_NOFORK 1` to make dropbear a one-shot server, easy to
run under a debugger.
Following are generated files in the format `<target>: <generator>(<source>)`
```
- configure: autoconf(configure.ac)
- src/config.h.in: autoheader(configure.ac)
- src/config.h: configure(src/config.h.in)
- Makefile: configure(Makefile.in)
- default_options_guard.h: make(default_options.h)
```
Although generated, the first two files are checked in as they change very infrequently.
## Random sources
#### Debug printing
Most cryptography requires a good random entropy source, both to generate secret
keys and in the course of a session. Dropbear uses the Linux kernel's
`getrandom()` syscall to ensure that the system RNG has been initialised before
using it. On some systems there is insufficient entropy gathered during early
boot - generating hostkeys then will block for some amount of time.
Dropbear has a `-R` option to generate hostkeys upon the first connection
as required - that will allow the system more time to gather entropy.
Set `#define DEBUG_TRACE 1` in [localoptions.h](./localoptions.h) to enable a `-v` verbose option for dropbear and dbclient.
Higher numbers can be used to allow increased debug levels, with `-v` argument repeated.
## Algorithms
For development running `dropbear -F -E` is useful to run in the foreground.
You can set `#define DEBUG_NOFORK 1` to make dropbear a one-shot server, easy to run under a debugger.
Default algorithm lists are specified in [common-algo.c](common-algo.c).
They are in priority order, the client's first matching choice is used
(see rfc4253).
Dropbear client has `-c` and `-m` arguments to choose which are enabled at
runtime (doesn't work for server as of June 2020).
#### Random sources
Enabling/disabling algorithms is done in [localoptions.h](localoptions.h),
see [default_options.h](default_options.h).
Most cryptography requires a good random entropy source, both to generate secret keys and in the course of a session.
Dropbear uses the Linux kernel's `getrandom()` syscall to ensure that the system RNG has been initialised before using it.
On some systems there is insufficient entropy gathered during early boot - generating hostkeys then will block for some amount of time.
Dropbear has a `-R` option to generate hostkeys upon the first connection as required - that will allow the system more time to gather entropy.
## Style
#### Algorithms
Default algorithm lists are specified in [common-algo.c](./src/common-algo.c). They are in priority order, the client's first matching choice is used (see [rfc4253](https://www.rfc-editor.org/rfc/rfc4253.html)). Dropbear client has `-c` and `-m` arguments to choose which are enabled at runtime (doesn't work for server as of June 2020).
Enabling/disabling algorithms is done in [localoptions.h](./localoptions.h), see [default_options.h](./src/default_options.h).
#### Style
In general please conform to the current style of the file you are editing.
Source code is indented with tabs, width set to 4 (though width shouldn't matter much).
Braces are on the same line as functions/loops/if - try to keep consistency with existing code.
Source code is indented with tabs, width set to 4 (though width shouldn't
matter much). Braces are on the same line as functions/loops/if - try
to keep consistency with existing code.
All `if` statements should have braces, no exceptions.
Add a single space between flow control statements and their open parenthesis:
```
if (...
for (...
switch (...
etc.
```
Use `snake_case` for variable and function names.
Avoid using pointer arithmetic, instead the functions in [buffer.h](./src/buffer.h) should be used.
Avoid using pointer arithmetic, instead the functions in
[buffer.h](buffer.h) should be used.
Some Dropbear platforms have old compilers.
Variable declarations must be at the top of a scope and comments must be `/* */` rather than `//`.
Variable declarations must be at the top of a scope and
comments must be `/* */` rather than `//`.
Pointer variables should be initialised to NULL - it can reduce the severity of bugs.
Pointer variables should be initialised to NULL - it can reduce the
severity of bugs.
#### Third party code
## Third party code
Libtomcrypt and libtommath are periodically synced from upstream, so avoid making changes to that code which will need to be maintained.
Libtomcrypt and libtommath are periodically synced from upstream, so
avoid making changes to that code which will need to be maintained.
Improvements can be sent upstream to the libtom project.
#### Non-root user
## Non-root user
Dropbear server will run fine as a non-root user, allowing logins only for that user.
Password authentication probably won't work (can't read shadow passwords). You will need to create hostkeys that are readable.
Dropbear server will run fine as a non-root user, allowing logins only for
that user. Password authentication probably won't work (can't read shadow
passwords). You will need to create hostkeys that are readable.
#### Connection setup
## Connection setup
Dropbear implements first_kex_packet_follows to reduce
handshake latency (rfc 4253 7.1). Some less common implementations don't
handle that, it can be a cause of problems connecting. Note also that
Dropbear may send several ssh packets within a single TCP packet - it's just a
stream.
Dropbear implements `first_kex_packet_follows` to reduce handshake latency [RFC 4253 7.1](https://www.rfc-editor.org/rfc/rfc4253.html#section-7.1).
Some less common implementations don't handle that - it can be a cause of problems connecting.
Note also that Dropbear may send several ssh packets within a single TCP packet - it's just a stream.

View File

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

View File

@@ -1,55 +1,77 @@
## Fuzzing Dropbear
# Fuzzing Dropbear
Dropbear is process-per-session so it assumes calling `dropbear_exit()` is fine at any point to clean up.
This makes fuzzing a bit trickier. A few pieces of wrapping infrastructure are used to work around this.
Dropbear is process-per-session so it assumes calling `dropbear_exit()`
is fine at any point to clean up. This makes fuzzing a bit trickier.
A few pieces of wrapping infrastructure are used to work around this.
The [libfuzzer](http://llvm.org/docs/LibFuzzer.html#fuzz-target) harness expects a long running process to continually run a test function with a string of crafted input.
That process should not leak resources or exit.
The [libfuzzer](http://llvm.org/docs/LibFuzzer.html#fuzz-target) harness
expects a long running process to continually run a test function with
a string of crafted input. That process should not leak resources or exit.
#### longjmp
## longjmp
When dropbear runs in fuzz mode it sets up a [`setjmp()`](http://man7.org/linux/man-pages/man3/setjmp.3.html) target prior to launching the code to be fuzzed, and then [`dropbear_exit()`](./src/dbutil.c#L125) calls `longjmp()` back there.
This avoids exiting though it doesn't free memory or other resources.
When dropbear runs in fuzz mode it sets up a
[`setjmp()`](http://man7.org/linux/man-pages/man3/setjmp.3.html) target prior
to launching the code to be fuzzed, and then [`dropbear_exit()`](dbutil.c#L125)
calls `longjmp()` back there. This avoids exiting though it doesn't free
memory or other resources.
#### malloc Wrapper
## malloc Wrapper
Dropbear normally uses a [`m_malloc()`](./src/dbmalloc.c) function that is the same as `malloc()` but exits if allocation fails.
In fuzzing mode this is replaced with a tracking allocator that stores all allocations in a linked list.
After the `longjmp()` occurs the fuzzer target calls [`m_malloc_free_epoch(1, 1)`](./src/dbmalloc.c#L80) to clean up any unreleased memory.
Dropbear normally uses a [`m_malloc()`](dbmalloc.c) function that is the same as `malloc()` but
exits if allocation fails. In fuzzing mode this is replaced with a tracking allocator
that stores all allocations in a linked list. After the `longjmp()` occurs the fuzzer target
calls [`m_malloc_free_epoch(1, 1)`](dbmalloc.c) to clean up any unreleased memory.
If the fuzz target runs to completion it calls `m_malloc_free_epoch(1, 0)` which will reset the tracked allocations but will not free memory.
That allows libfuzzer's leak checking to detect leaks in normal operation.
If the fuzz target runs to completion it calls `m_malloc_free_epoch(1, 0)` which will reset
the tracked allocations but will not free memory - that allows libfuzzer's leak checking
to detect leaks in normal operation.
#### File Descriptor Input
## File Descriptor Input
As a network process Dropbear reads and writes from a socket.
The wrappers for `read()`/`write()`/`select()` in [fuzz-wrapfd.c](./fuzz/fuzz-wrapfd.c) will read from the fuzzer input that has been set up with `wrapfd_add()`. `write()` output is currently discarded.
As a network process Dropbear reads and writes from a socket. The wrappers for
`read()`/`write()`/`select()` in [fuzz-wrapfd.c](fuzz-wrapfd.c) will read from the
fuzzer input that has been set up with `wrapfd_add()`. `write()` output is
currently discarded.
These also test error paths such as EINTR and short reads with certain probabilities.
This allows running the entire dropbear server process with network input provided by the fuzzer, without many modifications to the main code.
At the time of writing this only runs the pre-authentication stages, though post-authentication could be run similarly.
This allows running the entire dropbear server process with network input provided by the
fuzzer, without many modifications to the main code. At the time of writing this
only runs the pre-authentication stages, though post-authentication could be run similarly.
#### Encryption and Randomness
## Encryption and Randomness
When running in fuzzing mode Dropbear uses a [fixed seed](./src/dbrandom.c#L185) every time so that failures can be reproduced.
When running in fuzzing mode Dropbear uses a [fixed seed](dbrandom.c#L185)
every time so that failures can be reproduced.
Since the fuzzer cannot generate valid encrypted input the packet decryption and message authentication calls are disabled, see [packet.c](./src/packet.c).
Since the fuzzer cannot generate valid encrypted input the packet decryption and
message authentication calls are disabled, see [packet.c](packet.c).
MAC failures are set to occur with a low probability to test that error path.
#### Fuzzers
## Fuzzers
Current fuzzers are:
Current fuzzers are
* [fuzzer-preauth](./fuzz/fuzzer-preauth.c) - the fuzzer input is treated as a stream of session input.
This will test key exchange, packet ordering, authentication attempts etc.
* [fuzzer-preauth_nomaths](./fuzz/fuzzer-preauth_nomaths.c) - the same as fuzzer-preauth but with asymmetric crypto routines replaced with dummies for faster runtime.
corpora are shared between fuzzers by [oss-fuzz](https://github.com/google/oss-fuzz) so this will help fuzzer-preauth too.
* [fuzzer-verify](./fuzz/fuzzer-verify.c) - read a key and signature from fuzzer input and verify that signature.
It would not be expected to pass, though some keys with bad parameters are able to validate with a trivial signature - extra checks are added for that.
* [fuzzer-pubkey](./fuzz/fuzzer-pubkey.c) - test parsing of an `authorized_keys` line.
* [fuzzer-kexdh](./fuzz/fuzzer-kexdh.c) - test Diffie-Hellman key exchange where the fuzz input is the ephemeral public key that would be received over the network.
This is testing `mp_expt_mod()` and and other libtommath routines.
* [fuzzer-kexecdh](./fuzz/fuzzer-kexecdh.c) - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh.
- [fuzzer-preauth](fuzzer-preauth.c) - the fuzzer input is treated as a stream of session input. This will
test key exchange, packet ordering, authentication attempts etc.
- [fuzzer-preauth_nomaths](fuzzer-preauth_nomaths.c) - the same as fuzzer-preauth but with asymmetric crypto
routines replaced with dummies for faster runtime. corpora are shared
between fuzzers by [oss-fuzz](https://github.com/google/oss-fuzz) so this
will help fuzzer-preauth too.
- [fuzzer-verify](fuzzer-verify.c) - read a key and signature from fuzzer input and verify that signature.
It would not be expected to pass, though some keys with bad parameters are
able to validate with a trivial signature - extra checks are added for that.
- [fuzzer-pubkey](fuzzer-pubkey.c) - test parsing of an `authorized_keys` line.
- [fuzzer-kexdh](fuzzer-kexdh.c) - test Diffie-Hellman key exchange where the fuzz input is the
ephemeral public key that would be received over the network. This is testing `mp_expt_mod()`
and and other libtommath routines.
- [fuzzer-kexecdh](fuzzer-kexecdh.c) - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh.
This is testing libtommath ECC routines.
* [fuzzer-kexcurve25519](./fuzz/fuzzer-kexcurve25519.c) - test Curve25519 Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexecdh.
This is testing `dropbear_curve25519_scalarmult()` and other libtommath routines.
- [fuzzer-kexcurve25519](fuzzer-kexcurve25519.c) - test Curve25519 Elliptic Curve Diffie-Hellman key exchange
like fuzzer-kexecdh. This is testing `dropbear_curve25519_scalarmult()` and other libtommath routines.

93
INSTALL Normal file
View File

@@ -0,0 +1,93 @@
Basic Dropbear build instructions:
- Edit localoptions.h to set which features you want. Available options
are described in default_options.h, these will be overridden by
anything set in localoptions.h
localoptions.h should be located in the build directory if you are
building out of tree.
- If using a Mercurial or Git checkout, "autoconf; autoheader"
- Configure for your system:
./configure (optionally with --disable-zlib or --disable-syslog,
or --help for other options)
- Compile:
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
- Optionally install, or copy the binaries another way
make install (/usr/local/bin is usual default):
or
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
(you can leave items out of the PROGRAMS list to avoid compiling them. If you
recompile after changing the PROGRAMS list, you *MUST* "make clean" before
recompiling - bad things will happen otherwise)
DEVELOPING.md has some notes on other developer topics, including debugging.
See MULTI for instructions on making all-in-one binaries.
If you want to compile statically use ./configure --enable-static
By default Dropbear adds various build flags that improve robustness
against programming bugs (good for security). If these cause problems
they can be disabled with ./configure --disable-harden
Binaries can be stripped with "make strip"
============================================================================
If you're compiling for a 386-class CPU, you will probably need to add
CFLAGS=-DLTC_NO_BSWAP so that libtomcrypt doesn't use 486+ instructions.
============================================================================
Compiling with uClibc:
Firstly, make sure you have at least uclibc 0.9.17, as getusershell() in prior
versions is broken. Also note that you may get strange issues if your uClibc
headers don't match the library you are running with, ie the headers might
say that shadow password support exists, but the libraries don't have it.
Compiling for uClibc should be the same as normal, just set CC to the magic
uClibc toolchain compiler (ie export CC=i386-uclibc-gcc or whatever).
You can use "make STATIC=1" to make statically linked binaries, and it is
advisable to strip the binaries too. If you're looking to make a small binary,
you should remove unneeded ciphers and MD5, by editing localoptions.h
It is possible to compile zlib in, by copying zlib.h and zconf.h into a
subdirectory (ie zlibincludes), and
export CFLAGS="-Izlibincludes -I../zlibincludes"
export LDFLAGS=/usr/lib/libz.a
before ./configure and make.
If you disable zlib, you must explicitly disable compression for the client -
OpenSSH is possibly buggy in this regard, it seems you need to disable it
globally in ~/.ssh/config, not just in the host entry in that file.
You may want to manually disable lastlog recording when using uClibc, configure
with --disable-lastlog.
One common problem is pty allocation. There are a number of types of pty
allocation which can be used -- if they work properly, the end result is the
same for each type. Running configure should detect the best type to use
automatically, however for some systems, this may be incorrect. Some
things to note:
If your system expects /dev/pts to be mounted (this is a uClibc option),
make sure that it is.
Make sure that your libc headers match the library version you are using.
If openpty() is being used (HAVE_OPENPTY defined in config.h) and it fails,
you can try compiling with --disable-openpty. You will probably then need
to create all the /dev/pty?? and /dev/tty?? devices, which can be
problematic for devfs. In general, openpty() is the best way to allocate
PTYs, so it's best to try and get it working.

View File

@@ -1,97 +0,0 @@
## Basic Dropbear Build Instructions
### Build Options
Custom build options can be configured in `localoptions.h` in the build directory. This is a local file, not checked in to git.
Available options are described in [`src/default_options.h`](src/default_options.h)
Options include available cryptographic algorithms, SSH features, and file paths.
In addition, a `src/distrooptions.h` file will be used if it exists, for distributions to set configuration options.
### Configure for your system
```
./configure
```
Optionally with `--disable-zlib` or `--disable-syslog`.
Or `--help` for other options.
You'll need to first run `autoconf; autoheader` if you edit `configure.ac`.
### Compile:
```
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
```
Optionally install, or copy the binaries another way:
```
make install
```
`/usr/local/bin` is usual default.
or
```
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
```
To test the installation targeting a temporary forder set `DESTDIR`:
```
make install DESTDIR=/same/temp/location
```
You can leave items out of the `PROGRAMS` list to avoid compiling them.
If you recompile after changing the `PROGRAMS` list, you **MUST** `make clean` before recompiling - bad things will happen otherwise.
[DEVELOPING.md](DEVELOPING.md) has some notes on other developer topics, including debugging.
See [MULTI.md](MULTI.md) for instructions on making all-in-one binaries.
If you want to compile statically use
```
./configure --enable-static
```
By default Dropbear adds various build flags that improve robustness against programming bugs (good for security).
If these cause problems they can be disabled with `./configure --disable-harden`.
Binaries can be stripped with `make strip`.
> **Note**
> If you're compiling for a 386-class CPU, you will probably need to add CFLAGS=-DLTC_NO_BSWAP so that libtomcrypt doesn't use 486+ instructions.
## Compiling with uClibc
Firstly, make sure you have at least uclibc 0.9.17, as `getusershell()` in prior versions is broken.
Also note that you may get strange issues if your uClibc headers don't match the library you are running with.
I.e. the headers might say that shadow password support exists, but the libraries don't have it.
Compiling for uClibc should be the same as normal, just set CC to the magic uClibc toolchain compiler (ie `export CC=i386-uclibc-gcc` or whatever).
You can use `make STATIC=1` to make statically linked binaries, and it is advisable to strip the binaries too.
If you're looking to make a small binary, you should remove unneeded ciphers and algorithms, by editing [localoptions.h](./localoptions.h).
It is possible to compile zlib in, by copying zlib.h and zconf.h into a subdirectory (ie zlibincludes), and
```
export CFLAGS="-Izlibincludes -I../zlibincludes"
export LDFLAGS=/usr/lib/libz.a
```
before `./configure` and `make`.
If you disable zlib, you must explicitly disable compression for the client.
OpenSSH is possibly buggy in this regard, it seems you need to disable it globally in `~/.ssh/config`, not just in the host entry in that file.
You may want to manually disable lastlog recording when using uClibc, configure with `--disable-lastlog`.
One common problem is pty allocation.
There are a number of types of pty allocation which can be used -- if they work properly, the end result is the same for each type.
Running configure should detect the best type to use automatically, however for some systems, this may be incorrect.
Some things to note:
* If your system expects `/dev/pts` to be mounted (this is a uClibc option), make sure that it is.
* Make sure that your libc headers match the library version you are using.
* If `openpty()` is being used (`HAVE_OPENPTY` defined in `config.h`) and it fails, you can try compiling with `--disable-openpty`.
You will probably then need to create all the `/dev/pty??` and `/dev/tty??` devices, which can be problematic for `devfs`.
In general, `openpty()` is the best way to allocate PTYs, so it's best to try and get it working.

22
MULTI Normal file
View File

@@ -0,0 +1,22 @@
Multi-binary compilation
========================
To compile for systems without much space (floppy distributions etc), you
can create a single binary. This will save disk space by avoiding repeated
code between the various parts.
If you are familiar with "busybox", it's the same principle.
To compile the multi-binary, first "make clean" (if you've compiled
previously), then
make PROGRAMS="programs you want here" MULTI=1
To use the binary, symlink it from the desired executable:
ln -s dropbearmulti dropbear
ln -s dropbearmulti dbclient
etc
then execute as normal:
./dropbear <options here>

View File

@@ -1,25 +0,0 @@
## Multi-Binary Compilation
To compile for systems without much space (floppy distributions etc), you can create a single binary.
This will save disk space by avoiding repeated code between the various parts.
If you are familiar with BusyBox, it's the same principle.
To compile the multi-binary, first `make clean` (if you've compiled previously), then
```sh
make PROGRAMS="programs you want here" MULTI=1
```
To use the binary, symlink it from the desired executable:
```sh
ln -s dropbearmulti dropbear
ln -s dropbearmulti dbclient
```
etc.
Then execute as normal:
```
./dropbear <options here>
```

View File

@@ -12,81 +12,67 @@ ifndef PROGRAMS
PROGRAMS=dropbear dbclient dropbearkey dropbearconvert
endif
srcdir=@srcdir@/src
VPATH=@srcdir@/src
STATIC_LTC=libtomcrypt/libtomcrypt.a
STATIC_LTM=libtommath/libtommath.a
LIBTOM_LIBS=@LIBTOM_LIBS@
ifeq (@BUNDLED_LIBTOM@, 1)
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_CLEAN=ltc-clean ltm-clean
CPPFLAGS+=-I$(srcdir)/../libtomcrypt/src/headers/
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM)
LIBTOM_CLEAN=ltc-clean ltm-clean
CFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
endif
ifneq ($(wildcard ./localoptions.h),)
CPPFLAGS+=-DLOCALOPTIONS_H_EXISTS
endif
ifneq ($(wildcard $(srcdir)/distrooptions.h),)
CPPFLAGS+=-DDISTROOPTIONS_H_EXISTS
OPTION_HEADERS = default_options_guard.h sysoptions.h
ifneq ($(wildcard localoptions.h),)
CFLAGS+=-DLOCALOPTIONS_H_EXISTS
OPTION_HEADERS += localoptions.h
endif
OBJ_DIR=./obj
MAN_DIR=@srcdir@/manpages
_COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
dss.o bignum.o \
signkey.o rsa.o dbrandom.o \
queue.o \
atomicio.o compat.o fake-rfc2553.o \
ltc_prng.o ecc.o ecdsa.o 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
COMMONOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_COMMONOBJS))
_SVROBJS=svr-kex.o svr-auth.o sshpty.o \
SVROBJS=svr-kex.o svr-auth.o sshpty.o \
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\
svr-tcpfwd.o svr-authpam.o
SVROBJS = $(patsubst %,$(OBJ_DIR)/%,$(_SVROBJS))
_CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
cli-session.o cli-runopts.o cli-chansession.o \
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \
cli-agentfwd.o cli-readconf.o
CLIOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_CLIOBJS))
cli-agentfwd.o
_CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
common-channel.o common-chansession.o termcodes.o loginrec.o \
tcp-accept.o listener.o process-packet.o dh_groups.o \
common-runopts.o circbuffer.o list.o netio.o chachapoly.o gcm.o
CLISVROBJS = $(patsubst %,$(OBJ_DIR)/%,$(_CLISVROBJS))
CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
common-channel.o common-chansession.o termcodes.o loginrec.o \
tcp-accept.o listener.o process-packet.o dh_groups.o \
common-runopts.o circbuffer.o list.o netio.o chachapoly.o gcm.o
_KEYOBJS=dropbearkey.o
KEYOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_KEYOBJS))
KEYOBJS=dropbearkey.o
_CONVERTOBJS=dropbearconvert.o keyimport.o signkey_ossh.o
CONVERTOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_CONVERTOBJS))
CONVERTOBJS=dropbearconvert.o keyimport.o
_SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
SCPOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_SCPOBJS))
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:=$(subst $(OBJ_DIR)/svr-main.o, ,$(allobjs))
allobjs:=$(subst $(OBJ_DIR)/cli-main.o, ,$(allobjs))
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) $(OBJ_DIR)/svr-main.o
dbclientobjs=$(allobjs) $(OBJ_DIR)/cli-main.o
dropbearobjs=$(allobjs) svr-main.o
dbclientobjs=$(allobjs) cli-main.o
dropbearkeyobjs=$(allobjs) $(KEYOBJS)
dropbearconvertobjs=$(allobjs) $(CONVERTOBJS)
# CXX only set when fuzzing
CXX=@CXX@
FUZZ_CLEAN=fuzz-clean
else
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
@@ -96,14 +82,17 @@ else
endif
ifeq (@DROPBEAR_PLUGIN@, 1)
# rdynamic makes all the global symbols of dropbear available to all the loaded shared libraries
# this allow a plugin to reuse existing crypto/utilities like base64_decode/base64_encode without
# the need to rewrite them.
PLUGIN_LIBS=-ldl -rdynamic
# rdynamic makes all the global symbols of dropbear available to all the loaded shared libraries
# this allow a plugin to reuse existing crypto/utilities like base64_decode/base64_encode without
# the need to rewrite them.
PLUGIN_LIBS=-ldl -rdynamic
else
PLUGIN_LIBS=
PLUGIN_LIBS=
endif
VPATH=@srcdir@
srcdir=@srcdir@
prefix=@prefix@
exec_prefix=@exec_prefix@
datarootdir = @datarootdir@
@@ -118,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@
@@ -130,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)
@@ -154,30 +142,21 @@ 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)
# for simplicity assume all source depends on all headers
HEADERS=$(wildcard $(srcdir)/*.h *.h) default_options_guard.h
HEADERS=$(wildcard $(srcdir)/*.h *.h) $(OPTION_HEADERS)
%.o : %.c $(HEADERS)
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
$(OBJ_DIR):
mkdir -p $@
$(OBJ_DIR)/%.o: $(srcdir)/%.c $(HEADERS) | $(OBJ_DIR)
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ -c
fuzz/%.o: $(srcdir)/../fuzz/%.c $(HEADERS)
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ -c
default_options_guard.h: $(srcdir)/default_options.h
default_options_guard.h: default_options.h
@echo Creating $@
@printf "/*\n > > > Do not edit this file (default_options_guard.h) < < <\nGenerated from "$^"\nLocal customisation goes in localoptions.h\n*/\n\n" > $@.tmp
@$(srcdir)/ifndef_wrapper.sh < $^ >> $@.tmp
mv -v $@.tmp $@
pwd
ls -l $@
@mv $@.tmp $@
strip: $(TARGETS)
$(STRIP) $(addsuffix $(EXEEXT), $(TARGETS))
@@ -187,31 +166,31 @@ install: $(addprefix inst_, $(TARGETS))
insmultidropbear: dropbearmulti$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(sbindir)
-rm -f $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 644 $(MAN_DIR)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
insmulti%: dropbearmulti$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(bindir)
-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT)
-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
if test -e $(MAN_DIR)/$*.1; then $(INSTALL) -m 644 $(MAN_DIR)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
# dropbear should go in sbin, so it needs a separate rule
inst_dropbear: dropbear
$(INSTALL) -d $(DESTDIR)$(sbindir)
$(INSTALL) dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
$(INSTALL) -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 644 $(MAN_DIR)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
$(INSTALL) -m 644 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
inst_%: %
$(INSTALL) -d $(DESTDIR)$(bindir)
$(INSTALL) $*$(EXEEXT) $(DESTDIR)$(bindir)
$(INSTALL) -d $(DESTDIR)$(mandir)/man1
if test -e $(MAN_DIR)/$*.1; then $(INSTALL) -m 644 $(MAN_DIR)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
inst_dropbearmulti: $(addprefix insmulti, $(PROGRAMS))
inst_dropbearmulti: $(addprefix insmulti, $(PROGRAMS))
# for some reason the rule further down doesn't like $($@objs) as a prereq.
dropbear: $(dropbearobjs)
@@ -236,8 +215,8 @@ scp: $(SCPOBJS) $(HEADERS) Makefile
# multi-binary compilation.
MULTIOBJS=
ifeq ($(MULTI),1)
MULTIOBJS=$(OBJ_DIR)/dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
CPPFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
endif
dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile
@@ -251,13 +230,13 @@ link%:
-rm -f $*$(EXEEXT)
-ln -s dropbearmulti$(EXEEXT) $*$(EXEEXT)
$(STATIC_LTC): $(HEADERS)
$(STATIC_LTC): $(OPTION_HEADERS)
$(MAKE) -C libtomcrypt
$(STATIC_LTM): $(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
@@ -268,17 +247,16 @@ 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) \
dropbearconvert$(EXEEXT) scp$(EXEEXT) scp-progress$(EXEEXT) \
dropbearmulti$(EXEEXT) *.o *.da *.bb *.bbg *.prof \
$(OBJ_DIR)/*
dropbearmulti$(EXEEXT) *.o *.da *.bb *.bbg *.prof
distclean: clean tidy
-rm -f src/config.h config.status config.log
-rm -f Makefile test/Makefile
-rm -f config.h
-rm -f Makefile
-rm -f default_options_guard.h
tidy:
@@ -287,52 +265,56 @@ 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 fuzzer-cliconf
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): $(LIBTOM_DEPS) $(allobjs) $(FUZZ_OBJS)
$(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]" > $@
echo "max_len = 50000" >> $@
# run this to update hardcoded hostkeys for for fuzzing.
# run this to update hardcoded hostkeys for for fuzzing.
# hostkeys.c is checked in to hg.
fuzz-hostkeys:
dropbearkey -t rsa -f keyr
@@ -345,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

79
README Normal file
View File

@@ -0,0 +1,79 @@
This is Dropbear, a smallish SSH server and client.
https://matt.ucc.asn.au/dropbear/dropbear.html
INSTALL has compilation instructions.
MULTI has instructions on making a multi-purpose binary (ie a single binary
which performs multiple tasks, to save disk space)
SMALL has some tips on creating small binaries.
Please contact me if you have any questions/bugs found/features/ideas/comments etc :)
There is also a mailing list http://lists.ucc.gu.uwa.edu.au/mailman/listinfo/dropbear
Matt Johnston
matt@ucc.asn.au
In the absence of detailed documentation, some notes follow:
============================================================================
Server public key auth:
You can use ~/.ssh/authorized_keys in the same way as with OpenSSH, just put
the key entries in that file. They should be of the form:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwVa6M6cGVmUcLl2cFzkxEoJd06Ub4bVDsYrWvXhvUV+ZAM9uGuewZBDoAqNKJxoIn0Hyd0Nk/yU99UVv6NWV/5YSHtnf35LKds56j7cuzoQpFIdjNwdxAN0PCET/MG8qyskG/2IE2DPNIaJ3Wy+Ws4IZEgdJgPlTYUBWWtCWOGc= someone@hostname
You must make sure that ~/.ssh, and the key file, are only writable by the
user. Beware of editors that split the key into multiple lines.
Dropbear supports some options for authorized_keys entries, see the manpage.
============================================================================
Client public key auth:
Dropbear can do public key auth as a client, but you will have to convert
OpenSSH style keys to Dropbear format, or use dropbearkey to create them.
If you have an OpenSSH-style private key ~/.ssh/id_rsa, you need to do:
dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_rsa.db
dbclient -i ~/.ssh/id_rsa.db <hostname>
Dropbear does not support encrypted hostkeys though can connect to ssh-agent.
============================================================================
If you want to get the public-key portion of a Dropbear private key, look at
dropbearkey's '-y' option.
============================================================================
To run the server, you need to generate server keys, this is one-off:
./dropbearkey -t rsa -f dropbear_rsa_host_key
./dropbearkey -t dss -f dropbear_dss_host_key
./dropbearkey -t ecdsa -f dropbear_ecdsa_host_key
./dropbearkey -t ed25519 -f dropbear_ed25519_host_key
or alternatively convert OpenSSH keys to Dropbear:
./dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key dropbear_dss_host_key
You can also get Dropbear to create keys when the first connection is made -
this is preferable to generating keys when the system boots. Make sure
/etc/dropbear/ exists and then pass '-R' to the dropbear server.
============================================================================
If the server is run as non-root, you most likely won't be able to allocate a
pty, and you cannot login as any user other than that running the daemon
(obviously). Shadow passwords will also be unusable as non-root.
============================================================================
The Dropbear distribution includes a standalone version of OpenSSH's scp
program. You can compile it with "make scp", you may want to change the path
of the ssh binary, specified by _PATH_SSH_PROGRAM in options.h . By default
the progress meter isn't compiled in to save space, you can enable it by
adding 'SCPPROGRESS=1' to the make commandline.

View File

@@ -1,84 +0,0 @@
## Dropbear SSH
A smallish SSH server and client
https://matt.ucc.asn.au/dropbear/dropbear.html
[INSTALL.md](INSTALL.md) has compilation instructions.
[MULTI.md](MULTI.md) has instructions on making a multi-purpose binary (ie a single binary which performs multiple tasks, to save disk space).
[SMALL.md](SMALL.md) has some tips on creating small binaries.
A mirror of the Dropbear website and tarballs is available at https://dropbear.nl/mirror/.
Please contact me if you have any questions/bugs found/features/ideas/comments etc
There is also a mailing list https://lists.ucc.asn.au/mailman/listinfo/dropbear
Matt Johnston
matt@ucc.asn.au
### In the absence of detailed documentation, some notes follow
----
#### Server public key auth
You can use `~/.ssh/authorized_keys` in the same way as with OpenSSH, just put the key entries in that file.
They should be of the form:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwVa6M6cGVmUcLl2cFzkxEoJd06Ub4bVDsYrWvXhvUV+ZAM9uGuewZBDoAqNKJxoIn0Hyd0NkyU99UVv6NWV/5YSHtnf35LKds56j7cuzoQpFIdjNwdxAN0PCET/MG8qyskG/2IE2DPNIaJ3Wy+Ws4IZEgdJgPlTYUBWWtCWOGc= someone@hostname
You must make sure that `~/.ssh`, and the key file, are only writable by the user.
Beware of editors that split the key into multiple lines.
Dropbear supports some options for authorized_keys entries, see the manpage.
----
#### Client public key auth
Dropbear can do public key auth as a client.
But you will have to convert OpenSSH style keys to Dropbear format, or use dropbearkey to create them.
If you have an OpenSSH-style private key `~/.ssh/id_rsa`, you need to do:
```sh
dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_rsa.db
dbclient -i ~/.ssh/id_rsa.db <hostname>
```
Dropbear does not support encrypted hostkeys though can connect to ssh-agent.
----
If you want to get the public-key portion of a Dropbear private key, look at dropbearkey's `-y` option.
It will print both public key and fingerprint. If you need the pub key only you can grep by a prefix `ssh-`:
```sh
./dropbearkey -y -f ~/.ssh/id_ed25519 | grep "^ssh-" > ~/.ssh/id_ed25519.pub
```
----
To run the server, you need to generate server keys, this is one-off:
```sh
./dropbearkey -t rsa -f dropbear_rsa_host_key
./dropbearkey -t dss -f dropbear_dss_host_key
./dropbearkey -t ecdsa -f dropbear_ecdsa_host_key
./dropbearkey -t ed25519 -f dropbear_ed25519_host_key
```
Or alternatively convert OpenSSH keys to Dropbear:
```sh
./dropbearconvert openssh dropbear /etc/ssh/ssh_host_dsa_key dropbear_dss_host_key
```
You can also get Dropbear to create keys when the first connection is made - this is preferable to generating keys when the system boots.
Make sure `/etc/dropbear/` exists and then pass `-R` to the dropbear server.
----
If the server is run as non-root, you most likely won't be able to allocate a pty, and you cannot login as any user other than that running the daemon (obviously).
Shadow passwords will also be unusable as non-root.
----
The Dropbear distribution includes a standalone version of OpenSSH's `scp` program.
You can compile it with `make scp`.
You may want to change the path of the ssh binary, specified by `_PATH_SSH_PROGRAM` in `options.h`.
By default the progress meter isn't compiled in to save space, you can enable it by adding `SCPPROGRESS=1` to the `make` commandline.

53
SMALL Normal file
View File

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

View File

@@ -1,59 +0,0 @@
## Tips for a small system
If you only want server functionality, compile with
```
make PROGRAMS=dropbear
```
rather than just
```
make dropbear
```
so that client functionality in shared portions of Dropbear won't be included.
The same applies for `PROGRAMS=dbclient`.
---
The following are set in `localoptions.h`. See `default_options.h` for possibilities.
You can disable either password or public-key authentication.
Various algorithms can be disabled if they are not required by any connecting SSH clients/servers.
Disabling many is fine for a local install, though
builds for public consumption require more consideration.
You can disable x11, tcp and agent forwarding as desired. None of these are essential (depending on use cases).
---
If you are compiling statically, you may want to disable zlib, as it will use a few tens of kB of binary size
```
./configure --disable-zlib
```
You can create a combined binary, see the file [MULTI.md](MULTI.md), which will put all the functions into one binary, avoiding repeated code.
If you're compiling with gcc, you might want to look at gcc's options for stripping unused code.
The relevant vars to set before configure are:
```
LDFLAGS=-Wl,--gc-sections
CFLAGS="-ffunction-sections -fdata-sections"
```
You can also experiment with optimisation flags such as `-Os`. Note that in some cases these flags actually seem to increase size, so experiment before
deciding.
Of course using small C libraries such as musl can also help.
---
Libtommath has its own default `CFLAGS` to improve speed. You can use
```
./configure LTM_CFLAGS=-Os
```
to reduce size at the expense of speed.
If you have any queries, mail me and I'll see if I can help.

View File

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

View File

View File

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

View File

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

View File

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

View File

@@ -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) {
@@ -299,7 +306,7 @@ void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
/* for our purposes we only need positive (or 0) numbers, so will
* fail if we get negative numbers */
void buf_putmpint(buffer* buf, const mp_int * mp) {
void buf_putmpint(buffer* buf, mp_int * mp) {
size_t written;
unsigned int len, pad = 0;
TRACE2(("enter buf_putmpint"))

View File

@@ -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);
@@ -65,7 +64,7 @@ void buf_putint(buffer* buf, unsigned int val);
void buf_putstring(buffer* buf, const char* str, unsigned int len);
void buf_putbufstring(buffer *buf, const buffer* buf_str);
void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len);
void buf_putmpint(buffer* buf, const mp_int * mp);
void buf_putmpint(buffer* buf, mp_int * mp);
int buf_getmpint(buffer* buf, mp_int* mp);
unsigned int buf_getint(buffer* buf);

View File

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

View File

@@ -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,10 +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 sockets.
That is handled differently when closing FDs. Is only
applicable to sockets (which can be used with shutdown()) */
circbuffer *writebuf; /* data from the wire, for local consumption. Can be
initially NULL */
circbuffer *extrabuf; /* extended-data for the program - used like writebuf
@@ -66,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
@@ -78,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 */
@@ -102,7 +104,7 @@ struct ChanType {
void (*cleanup)(const struct Channel*);
};
/* Callback for connect_remote/connect_streamlocal. 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[]);

View File

@@ -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;
}

View File

@@ -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 */
@@ -161,7 +162,6 @@ void recv_msg_userauth_failure() {
unsigned int methlen = 0;
unsigned int partial = 0;
unsigned int i = 0;
int allow_pw_auth = 1;
TRACE(("<- MSG_USERAUTH_FAILURE"))
TRACE(("enter recv_msg_userauth_failure"))
@@ -176,13 +176,6 @@ void recv_msg_userauth_failure() {
dropbear_exit("Unexpected userauth failure");
}
/* Password authentication is only allowed in batch mode
* when a password can be provided non-interactively */
if (cli_opts.batch_mode && !getenv(DROPBEAR_PASSWORD_ENV)) {
allow_pw_auth = 0;
}
allow_pw_auth &= cli_opts.password_authentication;
/* When DROPBEAR_CLI_IMMEDIATE_AUTH is set there will be an initial response for
the "none" auth request, and then a response to the immediate auth request.
We need to be careful handling them. */
@@ -247,14 +240,14 @@ void recv_msg_userauth_failure() {
}
#endif
#if DROPBEAR_CLI_INTERACT_AUTH
if (allow_pw_auth
&& strncmp(AUTH_METHOD_INTERACT, tok, AUTH_METHOD_INTERACT_LEN) == 0) {
if (strncmp(AUTH_METHOD_INTERACT, tok,
AUTH_METHOD_INTERACT_LEN) == 0) {
ses.authstate.authtypes |= AUTH_TYPE_INTERACT;
}
#endif
#if DROPBEAR_CLI_PASSWORD_AUTH
if (allow_pw_auth
&& strncmp(AUTH_METHOD_PASSWORD, tok, AUTH_METHOD_PASSWORD_LEN) == 0) {
if (strncmp(AUTH_METHOD_PASSWORD, tok,
AUTH_METHOD_PASSWORD_LEN) == 0) {
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
}
#endif
@@ -273,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;
@@ -304,8 +294,20 @@ int cli_auth_try() {
}
#endif
#if DROPBEAR_CLI_PASSWORD_AUTH
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_PASSWORD)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
} else {
cli_auth_password();
finished = 1;
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
}
}
#endif
#if DROPBEAR_CLI_INTERACT_AUTH
if (!finished && cli_opts.password_authentication && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) {
if (!finished && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
fprintf(stderr, "Sorry, I won't let you use interactive auth unencrypted.\n");
} else {
@@ -318,18 +320,6 @@ int cli_auth_try() {
}
#endif
#if DROPBEAR_CLI_PASSWORD_AUTH
if (!finished && cli_opts.password_authentication && (ses.authstate.authtypes & AUTH_TYPE_PASSWORD)) {
if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
} else {
cli_auth_password();
finished = 1;
cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
}
}
#endif
TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype))
if (finished) {
@@ -355,13 +345,8 @@ char* getpass_or_cancel(const char* prompt)
return password;
}
#endif
if (cli_opts.batch_mode) {
dropbear_close("BatchMode active, no interactive session possible.");
}
if (!cli_opts.batch_mode) {
password = getpass(prompt);
}
password = getpass(prompt);
/* 0x03 is a ctrl-c character in the buffer. */
if (password == NULL || strchr(password, '\3') != NULL) {

View File

@@ -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);

View File

@@ -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 */

View File

@@ -66,10 +66,6 @@ void recv_msg_userauth_pk_ok() {
algotype = buf_getstring(ses.payload, &algolen);
sigtype = signature_type_from_name(algotype, algolen);
if (sigtype == DROPBEAR_SIGNATURE_NONE) {
/* Server replied with an algorithm that we didn't send */
dropbear_exit("Bad pk_ok");
}
keytype = signkey_type_from_signature(sigtype);
TRACE(("recv_msg_userauth_pk_ok: type %d", sigtype))
m_free(algotype);
@@ -129,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;
@@ -151,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);
@@ -180,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();

View File

@@ -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,

View File

@@ -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");
@@ -209,15 +196,6 @@ static void ask_to_confirm(const unsigned char* keyblob, unsigned int keybloblen
int response = 'z';
fp = sign_key_fingerprint(keyblob, keybloblen);
if (!cli_opts.ask_hostkey) {
dropbear_log(LOG_INFO, "\nHost '%s' key unknown.\n(%s fingerprint %s)",
cli_opts.remotehost,
algoname,
fp);
dropbear_exit("Not accepted automatically");
}
if (cli_opts.always_accept_key) {
dropbear_log(LOG_INFO, "\nHost '%s' key accepted unconditionally.\n(%s fingerprint %s)\n",
cli_opts.remotehost,
@@ -226,25 +204,18 @@ static void ask_to_confirm(const unsigned char* keyblob, unsigned int keybloblen
m_free(fp);
return;
}
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\n",
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\nDo you want to continue connecting? (y/n) ",
cli_opts.remotehost,
algoname,
fp);
m_free(fp);
if (cli_opts.batch_mode) {
dropbear_exit("Didn't validate host key");
}
fprintf(stderr, "Do you want to continue connecting? (y/n) ");
tty = fopen(_PATH_TTY, "r");
if (tty) {
response = getc(tty);
fclose(tty);
} else {
response = getc(stdin);
/* flush stdin buffer */
while ((getchar()) != '\n');
}
if (response == 'y') {
@@ -387,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;
}
@@ -413,7 +384,7 @@ static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen)
goto out;
}
if (!cli_opts.no_hostkey_check) {
if (!cli_opts.always_accept_key) {
/* put the new entry in the file */
fseek(hostsfile, 0, SEEK_END); /* In case it wasn't opened append */
buf_setpos(line, 0);

View File

@@ -31,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 */

View File

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

View File

@@ -46,7 +46,6 @@ static void cli_finished(void) ATTRIB_NORETURN;
static void recv_msg_service_accept(void);
static void cli_session_cleanup(void);
static void recv_msg_global_request_cli(void);
static void cli_algos_initialise(void);
struct clientsession cli_ses; /* GLOBAL */
@@ -103,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();
}
@@ -118,7 +114,6 @@ void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection
}
chaninitialise(cli_chantypes);
cli_algos_initialise();
/* Set up cli_ses vars */
cli_session_init(proxy_cmd_pid);
@@ -170,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;
@@ -251,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"))
@@ -361,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);
@@ -417,84 +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);
}
static void cli_algos_initialise(void) {
algo_type *algo;
for (algo = sshkex; algo->name; algo++) {
if (strcmp(algo->name, SSH_STRICT_KEX_S) == 0) {
algo->usable = 0;
}
}
}

View File

@@ -35,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:

View File

@@ -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};
@@ -114,6 +122,10 @@ static const struct dropbear_hash dropbear_sha2_256 =
static const struct dropbear_hash dropbear_sha2_512 =
{&sha512_desc, 64, 64};
#endif
#if DROPBEAR_MD5_HMAC
static const struct dropbear_hash dropbear_md5 =
{&md5_desc, 16, 16};
#endif
const struct dropbear_hash dropbear_nohash =
{NULL, 16, 0}; /* used initially */
@@ -144,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
@@ -153,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
@@ -181,6 +209,9 @@ algo_type sshhashes[] = {
#endif
#if DROPBEAR_SHA2_512_HMAC
{"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL},
#endif
#if DROPBEAR_MD5_HMAC
{"hmac-md5", 0, (void*)&dropbear_md5, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -208,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
@@ -222,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
@@ -307,12 +332,6 @@ algo_type sshkex[] = {
/* Set unusable by svr_algos_initialise() */
{SSH_EXT_INFO_C, 0, NULL, 1, NULL},
#endif
#endif
#if DROPBEAR_CLIENT
{SSH_STRICT_KEX_C, 0, NULL, 1, NULL},
#endif
#if DROPBEAR_SERVER
{SSH_STRICT_KEX_S, 0, NULL, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -340,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);
}
@@ -362,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 "") */
@@ -373,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;
}
@@ -444,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);

View File

@@ -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."))
@@ -317,11 +313,26 @@ static void check_close(struct Channel *channel) {
if ((channel->recv_eof && !write_pending(channel))
/* have a server "session" and child has exited */
|| (channel->writefd != FD_UNINIT
&& channel->type->check_close && close_allowed)) {
|| (channel->type->check_close && close_allowed)) {
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
@@ -345,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"))
@@ -353,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);
@@ -362,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"))
}
}
@@ -769,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"))
}
@@ -956,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,
@@ -969,6 +990,8 @@ failure:
cleanup:
m_free(type);
update_channel_prio();
TRACE(("leave recv_msg_channel_open"))
}
@@ -1050,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) {
@@ -1080,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);
@@ -1113,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;
@@ -1130,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() {
@@ -1163,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"))
}

View File

@@ -183,10 +183,6 @@ void send_msg_newkeys() {
gen_new_keys();
switch_keys();
if (ses.kexstate.strict_kex) {
ses.transseq = 0;
}
TRACE(("leave send_msg_newkeys"))
}
@@ -197,11 +193,7 @@ void recv_msg_newkeys() {
ses.kexstate.recvnewkeys = 1;
switch_keys();
if (ses.kexstate.strict_kex) {
ses.recvseq = 0;
}
TRACE(("leave recv_msg_newkeys"))
}
@@ -257,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,
@@ -314,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) {
@@ -494,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);
@@ -558,10 +545,6 @@ void recv_msg_kexinit() {
ses.kexstate.recvkexinit = 1;
if (ses.kexstate.strict_kex && !ses.kexstate.donefirstkex && ses.recvseq != 1) {
dropbear_exit("First packet wasn't kexinit");
}
TRACE(("leave recv_msg_kexinit"))
}
@@ -814,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;
@@ -871,18 +855,6 @@ static void read_kex_algos() {
}
#endif
if (!ses.kexstate.donefirstkex) {
const char* strict_name;
if (IS_DROPBEAR_CLIENT) {
strict_name = SSH_STRICT_KEX_S;
} else {
strict_name = SSH_STRICT_KEX_C;
}
if (buf_has_algo(ses.payload, strict_name) == DROPBEAR_SUCCESS) {
ses.kexstate.strict_kex = 1;
}
}
algo = buf_match_algo(ses.payload, sshkex, kexguess2, &goodguess);
allgood &= goodguess;
if (algo == NULL || algo->data == NULL) {
@@ -891,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 */
@@ -901,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);
@@ -911,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);
@@ -919,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);
@@ -932,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);
@@ -945,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);
@@ -953,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);
@@ -961,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);

View File

@@ -1,19 +1,19 @@
/*
* Dropbear - a SSH2 server
*
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -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;
}

View File

@@ -64,20 +64,17 @@ 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();
#if !DROPBEAR_SVR_MULTIUSER
/* A sanity check to prevent an accidental configuration option
leaving multiuser systems exposed */
{
int ret;
errno = 0;
ret = getgroups(0, NULL);
if (!(ret == -1 && errno == ENOSYS)) {
dropbear_exit("Non-multiuser Dropbear requires a non-multiuser kernel");
}
errno = 0;
getuid();
if (errno != ENOSYS) {
dropbear_exit("Non-multiuser Dropbear requires a non-multiuser kernel");
}
#endif
@@ -288,7 +285,8 @@ static void cleanup_buf(buffer **buf) {
if (!*buf) {
return;
}
buf_burn_free(*buf);
buf_burn(*buf);
buf_free(*buf);
*buf = NULL;
}
@@ -406,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))
}
@@ -467,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;
@@ -522,24 +515,15 @@ static void send_msg_keepalive() {
ses.last_packet_time_idle = old_time_idle;
}
/* Returns the difference in seconds, clamped to LONG_MAX */
static long elapsed(time_t now, time_t prev) {
time_t del = now - prev;
if (del > LONG_MAX) {
return LONG_MAX;
}
return (long)del;
}
/* Check all timeouts which are required. Currently these are the time for
* user authentication, and the automatic rekeying. */
static void checktimeouts() {
time_t now;
now = monotonic_now();
if (IS_DROPBEAR_SERVER && ses.connect_time != 0
&& elapsed(now, ses.connect_time) >= AUTH_TIMEOUT) {
&& now - ses.connect_time >= AUTH_TIMEOUT) {
dropbear_close("Timeout before auth");
}
@@ -549,47 +533,45 @@ static void checktimeouts() {
}
if (!ses.kexstate.sentkexinit
&& (elapsed(now, ses.kexstate.lastkextime) >= KEX_REKEY_TIMEOUT
&& (now - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
TRACE(("rekeying after timeout or max data reached"))
send_msg_kexinit();
}
if (opts.keepalive_secs > 0 && ses.authstate.authdone) {
/* Avoid sending keepalives prior to auth - those are
not valid pre-auth packet types */
/* Send keepalives if we've been idle */
if (elapsed(now, ses.last_packet_time_any_sent) >= opts.keepalive_secs) {
if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) {
send_msg_keepalive();
}
/* Also send an explicit keepalive message to trigger a response
if the remote end hasn't sent us anything */
if (elapsed(now, ses.last_packet_time_keepalive_recv) >= opts.keepalive_secs
&& elapsed(now, ses.last_packet_time_keepalive_sent) >= opts.keepalive_secs) {
if (now - ses.last_packet_time_keepalive_recv >= opts.keepalive_secs
&& now - ses.last_packet_time_keepalive_sent >= opts.keepalive_secs) {
send_msg_keepalive();
}
if (elapsed(now, ses.last_packet_time_keepalive_recv)
if (now - ses.last_packet_time_keepalive_recv
>= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) {
dropbear_exit("Keepalive timeout");
}
}
if (opts.idle_timeout_secs > 0
&& elapsed(now, ses.last_packet_time_idle) >= opts.idle_timeout_secs) {
if (opts.idle_timeout_secs > 0
&& now - ses.last_packet_time_idle >= opts.idle_timeout_secs) {
dropbear_close("Idle timeout");
}
}
static void update_timeout(long limit, time_t now, time_t last_event, long * timeout) {
TRACE2(("update_timeout limit %ld, now %llu, last %llu, timeout %ld",
limit,
(unsigned long long)now,
(unsigned long long)last_event, *timeout))
static void update_timeout(long limit, long now, long last_event, long * timeout) {
TRACE2(("update_timeout limit %ld, now %ld, last %ld, timeout %ld",
limit, now, last_event, *timeout))
if (last_event > 0 && limit > 0) {
*timeout = MIN(*timeout, elapsed(now, last_event) + limit);
*timeout = MIN(*timeout, last_event+limit-now);
TRACE2(("new timeout %ld", *timeout))
}
}
@@ -598,7 +580,7 @@ static long select_timeout() {
/* determine the minimum timeout that might be required, so
as to avoid waking when unneccessary */
long timeout = KEX_REKEY_TIMEOUT;
time_t now = monotonic_now();
long now = monotonic_now();
if (!ses.kexstate.sentkexinit) {
update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout);
@@ -610,7 +592,7 @@ static long select_timeout() {
}
if (ses.authstate.authdone) {
update_timeout(opts.keepalive_secs, now,
update_timeout(opts.keepalive_secs, now,
MAX(ses.last_packet_time_keepalive_recv, ses.last_packet_time_keepalive_sent),
&timeout);
}
@@ -653,16 +635,10 @@ void fill_passwd(const char* username) {
{
char *passwd_crypt = pw->pw_passwd;
#ifdef HAVE_SHADOW_H
/* "x" for the passwd crypt indicates shadow should be used */
if (pw->pw_passwd && strcmp(pw->pw_passwd, "x") == 0) {
/* get the shadow password */
struct spwd *spasswd = getspnam(ses.authstate.pw_name);
if (spasswd && spasswd->sp_pwdp) {
passwd_crypt = spasswd->sp_pwdp;
} else {
/* Fail if missing in /etc/shadow */
passwd_crypt = "!!";
}
/* get the shadow password if possible */
struct spwd *spasswd = getspnam(ses.authstate.pw_name);
if (spasswd && spasswd->sp_pwdp) {
passwd_crypt = spasswd->sp_pwdp;
}
#endif
if (!passwd_crypt) {
@@ -686,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;
}
}

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

10009
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,9 @@
# of the platform checks have been taken straight from OpenSSH's configure.ac
# Huge thanks to them for dealing with the horrible platform-specifics :)
AC_PREREQ([2.59])
AC_PREREQ(2.59)
AC_INIT
AC_CONFIG_SRCDIR(buffer.c)
# Record which revision is being built
if test -s "`which hg`" && test -d "$srcdir/.hg"; then
@@ -15,22 +16,21 @@ if test -s "`which hg`" && test -d "$srcdir/.hg"; then
fi
ORIGCFLAGS="$CFLAGS"
LATE_CFLAGS=""
# Checks for programs.
AC_PROG_CC
if test -z "$LD" ; then
LD=$CC
fi
AC_SUBST(LD)
AC_SUBST(LD)
AC_DEFUN(DB_TRYADDCFLAGS,
AC_DEFUN(DB_TRYADDCFLAGS,
[{
OLDFLAGS="$CFLAGS"
TESTFLAGS="$1"
CFLAGS="$TESTFLAGS $CFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDFLAGS" ]
)
}])
@@ -41,28 +41,12 @@ if test -z "$ORIGCFLAGS" && test "$GCC" = "yes"; then
CFLAGS="-Os -W -Wall"
fi
# LTM_CFLAGS is given to ./configure by the user,
# DROPBEAR_LTM_CFLAGS is substituted in the LTM Makefile.in
DROPBEAR_LTM_CFLAGS="$LTM_CFLAGS"
if test -z "$DROPBEAR_LTM_CFLAGS"; then
DROPBEAR_LTM_CFLAGS="-O3 -funroll-loops -fomit-frame-pointer"
fi
AC_MSG_NOTICE(Setting LTM_CFLAGS to $DROPBEAR_LTM_CFLAGS)
AC_ARG_VAR(LTM_CFLAGS, CFLAGS for bundled libtommath. Default -O3 -funroll-loops -fomit-frame-pointer)
AC_SUBST(DROPBEAR_LTM_CFLAGS)
AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wno-pointer-sign])
DB_TRYADDCFLAGS([-Wno-pointer-sign])
AC_MSG_NOTICE([Checking if compiler '$CC' supports -fno-strict-overflow])
DB_TRYADDCFLAGS([-fno-strict-overflow])
AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wundef])
DB_TRYADDCFLAGS([-Wundef])
# needed for various extensions. define early before autoconf tests
AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions if glibc])
STATIC=0
AC_ARG_ENABLE(static,
[ --enable-static Build static binaries],
@@ -93,15 +77,15 @@ if test "$hardenbuild" -eq 1; then
OLDLDFLAGS="$LDFLAGS"
TESTFLAGS="-Wl,-pie"
LDFLAGS="$TESTFLAGS $LDFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[
LDFLAGS="$OLDLDFLAGS"
TESTFLAGS="-pie"
LDFLAGS="$TESTFLAGS $LDFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
)
]
@@ -109,24 +93,24 @@ if test "$hardenbuild" -eq 1; then
# readonly elf relocation sections (relro)
OLDLDFLAGS="$LDFLAGS"
TESTFLAGS="-Wl,-z,now -Wl,-z,relro"
LDFLAGS="$TESTFLAGS $LDFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
LDFLAGS="$LDFLAGS $TESTFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ]
)
fi # non-static
# stack protector. -strong is good but only in gcc 4.9 or later
OLDCFLAGS="$CFLAGS"
TESTFLAGS="-fstack-protector-strong"
CFLAGS="$TESTFLAGS $CFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[
CFLAGS="$OLDCFLAGS"
TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4"
CFLAGS="$TESTFLAGS $CFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
CFLAGS="$CFLAGS $TESTFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_NOTICE([Setting $TESTFLAGS])],
[AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDCFLAGS" ]
)
]
@@ -140,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
@@ -186,7 +159,7 @@ case "$host" in
# OpenSSH thinks it's broken. If it isn't, let me know.
AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
;;
*-*-hpux*)
LIBS="$LIBS -lsec"
# It's probably broken.
@@ -200,10 +173,10 @@ esac
AC_CHECK_TOOL(AR, ar, :)
AC_CHECK_TOOL(RANLIB, ranlib, :)
AC_CHECK_TOOL(STRIP, strip, :)
AC_PROG_INSTALL
AC_CHECK_TOOL(INSTALL, install, :)
dnl Can't use login() or logout() with uclibc
AC_CHECK_DECL(__UCLIBC__,
AC_CHECK_DECL(__UCLIBC__,
[
no_loginfunc_check=1
AC_MSG_NOTICE([Using uClibc - login() and logout() probably don't work, so we won't use them.])
@@ -211,14 +184,14 @@ AC_CHECK_DECL(__UCLIBC__,
dnl We test for crypt() specially. On Linux (and others?) it resides in libcrypt
dnl but we don't want link all binaries to -lcrypt, just dropbear server.
dnl OS X doesn't need -lcrypt
dnl OS X doesn't need -lcrypt
AC_CHECK_FUNC(crypt, found_crypt_func=here)
AC_CHECK_LIB(crypt, crypt,
AC_CHECK_LIB(crypt, crypt,
[
CRYPTLIB="-lcrypt"
found_crypt_func=here
])
AC_SUBST(CRYPTLIB)
AC_SUBST(CRYPTLIB)
if test "t$found_crypt_func" = there; then
AC_DEFINE(HAVE_CRYPT, 1, [crypt() function])
fi
@@ -374,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)
@@ -392,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
@@ -406,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])
@@ -580,7 +554,7 @@ AC_ARG_ENABLE(bundled-libtom,
)
if test $BUNDLED_LIBTOM = 1 ; then
AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom)
AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom)
fi
AC_SUBST(LIBTOM_LIBS)
@@ -653,7 +627,7 @@ AC_ARG_ENABLE(pututxline,
AC_ARG_WITH(lastlog,
[ --with-lastlog=FILE|DIR specify lastlog location [common locations]],
[
if test "x$withval" = "xno" ; then
if test "x$withval" = "xno" ; then
AC_DEFINE(DISABLE_LASTLOG)
else
conf_lastlog_location=$withval
@@ -728,7 +702,7 @@ fi
if test -n "$conf_lastlog_location"; then
AC_DEFINE_UNQUOTED(CONF_LASTLOG_FILE, "$conf_lastlog_location", lastlog file location)
fi
fi
dnl utmp detection
AC_MSG_CHECKING([if your system defines UTMP_FILE])
@@ -758,7 +732,7 @@ if test -z "$conf_utmp_location"; then
fi
if test -n "$conf_utmp_location"; then
AC_DEFINE_UNQUOTED(CONF_UTMP_FILE, "$conf_utmp_location", utmp file location)
fi
fi
dnl wtmp detection
AC_MSG_CHECKING([if your system defines WTMP_FILE])
@@ -790,7 +764,7 @@ if test -z "$conf_wtmp_location"; then
fi
if test -n "$conf_wtmp_location"; then
AC_DEFINE_UNQUOTED(CONF_WTMP_FILE, "$conf_wtmp_location", wtmp file location)
fi
fi
dnl utmpx detection - I don't know any system so perverse as to require
@@ -818,7 +792,7 @@ if test -z "$conf_utmpx_location"; then
fi
else
AC_DEFINE_UNQUOTED(CONF_UTMPX_FILE, "$conf_utmpx_location", utmpx file location)
fi
fi
dnl wtmpx detection
AC_MSG_CHECKING([if your system defines WTMPX_FILE])
@@ -845,7 +819,7 @@ if test -z "$conf_wtmpx_location"; then
fi
else
AC_DEFINE_UNQUOTED(CONF_WTMPX_FILE, "$conf_wtmpx_location", wtmpx file location)
fi
fi
# Checks for library functions.
AC_PROG_GCC_TRADITIONAL
@@ -853,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))
@@ -881,17 +855,12 @@ fi
AC_EXEEXT
if test $BUNDLED_LIBTOM = 1 ; then
(cd $srcdir; find libtomcrypt -type d) | xargs mkdir -pv
(cd $srcdir; find libtomcrypt -type d) | xargs mkdir -pv
LIBTOM_FILES="libtomcrypt/Makefile libtommath/Makefile"
fi
# flags that should be set in Makefile but not for configure tests
CFLAGS="$CFLAGS $LATE_CFLAGS"
AC_CONFIG_AUX_DIR([src])
AC_CONFIG_HEADERS([config.h:src/config.h.in])
AC_CONFIG_FILES(Makefile $LIBTOM_FILES test/Makefile)
AC_CONFIG_HEADER(config.h)
AC_CONFIG_FILES(Makefile $LIBTOM_FILES)
AC_OUTPUT
AC_MSG_NOTICE()

View File

@@ -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,8 +30,10 @@ void crypto_init() {
};
const struct ltc_hash_descriptor *reghashes[] = {
#if DROPBEAR_SHA1_HMAC
/* we need sha1 for hostkey stuff regardless */
&sha1_desc,
#if DROPBEAR_MD5_HMAC
&md5_desc,
#endif
#if DROPBEAR_SHA256
&sha256_desc,
@@ -44,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");
@@ -66,8 +67,6 @@ void crypto_init() {
}
#endif
mp_rand_source(dropbear_rand_source);
#if DROPBEAR_ECC
ltc_mp = ltm_desc;
dropbear_ecc_fill_dp();

View File

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

View File

@@ -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);

View File

@@ -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
@@ -41,8 +46,7 @@ static int runprog(const char *multipath,
}
#endif
#ifdef DBMULTI_dropbearkey
if (strcmp(progname, "dropbearkey") == 0
|| strcmp(progname, "ssh-keygen") == 0) {
if (strcmp(progname, "dropbearkey") == 0) {
return dropbearkey_main(argc, argv);
}
#endif
@@ -63,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;
}
@@ -89,7 +89,7 @@ int main(int argc, char ** argv) {
"'dbclient' or 'ssh' - the Dropbear client\n"
#endif
#ifdef DBMULTI_dropbearkey
"'dropbearkey' or 'ssh-keygen' - the key generator\n"
"'dropbearkey' - the key generator\n"
#endif
#ifdef DBMULTI_dropbearconvert
"'dropbearconvert' - the key converter\n"

View File

@@ -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) {
@@ -268,6 +269,9 @@ void seedrandom() {
/* A few other sources to fall back on.
* Add more here for other platforms */
#ifdef __linux__
/* Seems to be a reasonable source of entropy from timers. Possibly hard
* for even local attackers to reproduce */
process_file(&hs, "/proc/timer_list", 0, 0);
/* Might help on systems with wireless */
process_file(&hs, "/proc/interrupts", 0, 0);
@@ -285,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;
@@ -313,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) {
@@ -321,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;
@@ -344,7 +348,7 @@ void genrandom(unsigned char* buf, unsigned int len) {
* rand must be an initialised *mp_int for the result.
* the result rand satisfies: 0 < rand < max
* */
void gen_random_mpint(const mp_int *max, mp_int *rand) {
void gen_random_mpint(mp_int *max, mp_int *rand) {
unsigned char *randbuf = NULL;
unsigned int len = 0;

View File

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

View File

@@ -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,40 +380,23 @@ 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, const mp_int *mp) {
void printmpint(const char *label, mp_int *mp) {
buffer *buf = buf_new(1000);
buf_putmpint(buf, mp);
fprintf(stderr, "%d bits ", mp_count_bits(mp));
@@ -573,10 +527,9 @@ void m_close(int fd) {
dropbear_exit("Error closing fd %d, %s", fd, strerror(errno));
}
}
void setnonblocking(int fd) {
int fl = 0;
TRACE(("setnonblocking: %d", fd))
#if DROPBEAR_FUZZ
@@ -584,47 +537,32 @@ void setnonblocking(int fd) {
return;
}
#endif
fl = fcntl(fd, F_GETFL, 0);
if (fl == -1) {
/* F_GETFL shouldn't fail */
dropbear_exit("Couldn't set nonblocking");
}
if (fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1) {
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
if (errno == ENODEV) {
/* Some devices (like /dev/null redirected in)
* can't be set to non-blocking */
TRACE(("ignoring ENODEV for setnonblocking"))
} else {
{
dropbear_exit("Couldn't set nonblocking");
}
}
}
TRACE(("leave setnonblocking"))
}
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)
@@ -637,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;
}
}
@@ -728,7 +658,7 @@ void gettime_wrapper(struct timespec *now) {
/* Fallback for everything else - this will sometimes go backwards */
gettimeofday(&tv, NULL);
now->tv_sec = tv.tv_sec;
now->tv_nsec = 1000*(long)tv.tv_usec;
now->tv_nsec = 1000*tv.tv_usec;
}
/* second-resolution monotonic timestamp */
@@ -756,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;
}

View File

@@ -47,13 +47,10 @@ void dropbear_log(int priority, const char* format, ...) ATTRIB_PRINTF(2,3) ;
void fail_assert(const char* expr, const char* file, int line) ATTRIB_NORETURN;
#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, const mp_int *mp);
void printmpint(const char *label, mp_int *mp);
void debug_start_net(void);
extern int debug_trace;
#endif
@@ -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,14 +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);
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#endif /* DROPBEAR_DBUTIL_H_ */

36
debian/changelog vendored
View File

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

View File

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

View File

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

4
debian/rules vendored
View File

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

View File

@@ -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. */

View File

@@ -3,14 +3,12 @@
/*
> > > Read This < < <
default_options.h documents compile-time options, and provides default values.
default_options.h documents compile-time options, and provides default values.
Local customisation should be added to localoptions.h which is
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.
Customisations will also be taken from src/distoptions.h if it exists.
Options can also be defined with -DDROPBEAR_XXX=[0,1] in Makefile CFLAGS
IMPORTANT: Some options will require "make clean" after changes */
@@ -20,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"
@@ -41,19 +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
* Level 0 = disabled
* Level 1-3 = approx 4 Kb (connection, remote identity, algos, auth type info)
* Level 4 = approx 17 Kb (detailed before connection)
* Level 5 = 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
@@ -73,7 +58,6 @@ IMPORTANT: Some options will require "make clean" after changes */
#define DROPBEAR_SVR_LOCALTCPFWD 1
#define DROPBEAR_SVR_REMOTETCPFWD 1
#define DROPBEAR_SVR_LOCALSTREAMFWD 1
/* Enable Authentication Agent Forwarding */
#define DROPBEAR_SVR_AGENTFWD 1
@@ -82,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
@@ -96,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,
@@ -122,55 +108,35 @@ 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
#define DROPBEAR_SHA2_512_HMAC 0
#define DROPBEAR_SHA1_96_HMAC 0
/* Hostkey/public key algorithms - at least one required, these are used
* for hostkey as well as for verifying signatures with pubkey auth.
* RSA is recommended.
*
* See: RSA_PRIV_FILENAME and DSS_PRIV_FILENAME */
* Removing either of these won't save very much space.
* RSA is recommended
* DSS may be necessary to connect to some systems though
is not recommended for new keys */
#define DROPBEAR_RSA 1
/* Newer SSH implementations use SHA256 for RSA signatures. SHA1
* support is required to communicate with some older implementations.
* It will be removed in future due to SHA1 insecurity, it can be
* disabled with DROPBEAR_RSA_SHA1 set to 0 */
#define DROPBEAR_RSA_SHA1 1
/* DSS may be necessary to connect to some systems but is not
* recommended for new keys (1024 bits is small, and it uses SHA1).
* RSA key generation will be faster with bundled libtommath
* if DROPBEAR_DSS is disabled.
* https://github.com/mkj/dropbear/issues/174#issuecomment-1267374858 */
#define DROPBEAR_DSS 0
#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
/* Allow U2F security keys for public key auth, with
* sk-ecdsa-sha2-nistp256@openssh.com or sk-ssh-ed25519@openssh.com keys.
* The corresponding DROPBEAR_ECDSA or DROPBEAR_ED25519 also needs to be set.
* This is currently server-only. */
#define DROPBEAR_SK_KEYS 1
/* RSA must be >=1024 */
#define DROPBEAR_DEFAULT_RSA_SIZE 2048
/* DSS is always 1024 */
/* ECDSA defaults to largest size configured, usually 521 */
/* Ed25519 is always 256 */
/* Add runtime flag "-R" to generate hostkeys as-needed when the first
/* Add runtime flag "-R" to generate hostkeys as-needed when the first
connection using that key type occurs.
This avoids the need to otherwise run "dropbearkey" and avoids some problems
with badly seeded /dev/urandom when systems first boot. */
@@ -186,7 +152,7 @@ IMPORTANT: Some options will require "make clean" after changes */
* curve25519 - elliptic curve DH
* ecdh - NIST elliptic curve DH (256, 384, 521)
*
* group1 is too small for security though is necessary if you need
* group1 is too small for security though is necessary if you need
compatibility with some implementations such as Dropbear versions < 0.53
* group14 is supported by most implementations.
* group16 provides a greater strength level but is slower and increases binary size
@@ -196,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
@@ -216,7 +182,7 @@ group1 in Dropbear server too */
* windowBits=8 will use 129kB for compression.
* Both modes will use ~35kB for decompression (using windowBits=15 for
* interoperability) */
#define DROPBEAR_ZLIB_WINDOW_BITS 15
#define DROPBEAR_ZLIB_WINDOW_BITS 15
/* Whether to do reverse DNS lookups. */
#define DO_HOST_LOOKUP 0
@@ -224,7 +190,6 @@ group1 in Dropbear server too */
/* Whether to print the message of the day (MOTD). */
#define DO_MOTD 1
#define MOTD_FILENAME "/etc/motd"
#define MOTD_MAXSIZE 2000
/* Authentication Types - at least one required.
RFC Draft requires pubkey auth, and recommends password */
@@ -238,11 +203,10 @@ 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
/* Whether to take public key options in
* authorized_keys file into account */
#define DROPBEAR_SVR_PUBKEY_OPTIONS 1
@@ -255,14 +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"
/* Per client configuration file
*/
#define DROPBEAR_USE_SSH_CONFIG 0
/* 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. */
@@ -276,8 +235,8 @@ group1 in Dropbear server too */
#define DROPBEAR_CLI_ASKPASS_HELPER 0
/* Save a network roundtrip by sendng a real auth request immediately after
* sending a query for the available methods. This is not yet enabled by default
since it could cause problems with non-compliant servers */
* sending a query for the available methods. This is not yet enabled by default
since it could cause problems with non-compliant servers */
#define DROPBEAR_CLI_IMMEDIATE_AUTH 0
/* Set this to use PRNGD or EGD instead of /dev/urandom */
@@ -289,7 +248,7 @@ group1 in Dropbear server too */
/* The first setting is per-IP, to avoid denial of service */
#define MAX_UNAUTH_PER_IP 5
/* And then a global limit to avoid chewing memory if connections
/* And then a global limit to avoid chewing memory if connections
* come from many IPs */
#define MAX_UNAUTH_CLIENTS 30
@@ -297,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.
@@ -314,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"
@@ -326,8 +275,8 @@ group1 in Dropbear server too */
* not using the Dropbear client, you'll need to change it */
#define DROPBEAR_PATH_SSH_PROGRAM "/usr/bin/dbclient"
/* Whether to log commands executed by a client. This only logs the
* (single) command sent to the server, not what a user did in a
/* Whether to log commands executed by a client. This only logs the
* (single) command sent to the server, not what a user did in a
* shell/sftp session etc. */
#define LOG_COMMANDS 0
@@ -361,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_ */

View File

@@ -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
@@ -53,12 +47,8 @@ Disable password logins.
.B \-g
Disable password logins for root.
.TP
.B \-t
Enable two-factor authentication. Both password login and public key authentication are
required. Should not be used with the '-s' option.
.TP
.B \-j
Disable local port forwarding. This includes unix stream forwards.
Disable local port forwarding.
.TP
.B \-k
Disable remote port forwarding.
@@ -70,11 +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).
.TP
.B \-l \fIinterface
Listen on the specified
.I interface
up to 10 can be specified (default 22 if none specified).
.TP
.B \-i
Service program mode.
@@ -100,21 +86,17 @@ Ensure that traffic is transmitted at a certain interval in seconds. This is
useful for working around firewalls or routers that drop connections after
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.
.TP
.B \-z
By default Dropbear will send network traffic with the \fBAF21\fR setting for QoS, letting network devices give it higher priority. Some devices may have problems with that, \fI-z\fR can be used to disable it.
.TP
.B \-T \fImax_authentication_attempts
Set the number of authentication attempts allowed per connection. If unspecified the default is 10 (MAX_AUTH_TRIES)
.TP
.B \-c \fIforced_command
Disregard the command provided by the user and always run \fIforced_command\fR. This also
overrides any authorized_keys command= option. 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
@@ -136,7 +118,7 @@ Available restrictions are:
.TP
.B no-port-forwarding
Don't allow port forwarding for this connection, including unix streams.
Don't allow port forwarding for this connection
.TP
.B no-agent-forwarding
@@ -151,18 +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 permitopen=\fR"\fIhost:port\fR"
Restrict local port forwarding so that connection is allowed only to the
specified host and port. Multiple permitopen options separated by commas
can be set in authorized_keys. Wildcard character ('*') may be used in
port specification for matching any port. Hosts must be literal domain names or
IP addresses.
.TP
.B command=\fR"\fIforced_command\fR"
Disregard the command provided by the user and always run \fIforced_command\fR.

View File

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

View File

@@ -9,7 +9,7 @@ dropbearconvert \- convert between Dropbear and OpenSSH private key formats
.I output_file
.SH DESCRIPTION
.B Dropbear
and
and
.B OpenSSH
SSH implementations have different private key formats.
.B dropbearconvert
@@ -24,15 +24,15 @@ first.
.SH ARGUMENTS
.TP
.I input_type
Either
Either
.I dropbear
or
or
.I openssh
.TP
.I output_type
Either
Either
.I dropbear
or
or
.I openssh
.TP
.I input_file
@@ -40,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

View File

@@ -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 */

View File

@@ -61,26 +61,11 @@
#include "dbrandom.h"
#include "gensignkey.h"
#if DROPBEAR_ED25519
#define DEFAULT_KEY_TYPE_NAME "ed25519"
#elif DROPBEAR_RSA
/* Different to the sigalgs list because negotiated hostkeys have fallbacks for compatibility,
* whereas a generated authkey doesn't, so RSA needs to be higher than ECDSA */
#define DEFAULT_KEY_TYPE_NAME "rsa"
#elif DROPBEAR_ECDSA
#define DEFAULT_KEY_TYPE_NAME "ecdsa"
#elif DROPBEAR_DSS
#define DEFAULT_KEY_TYPE_NAME "dss"
#endif
static void printhelp(char * progname);
static void printpubkey(sign_key * key, int keytype, const char * comment, int create_pub_file, const char * filename);
/* Print a public key and fingerprint to stdout.
* Used for "dropbearkey -y" command but also after generation of a new key.
* For the new key pair the create_pub_file will be TRUE and the pub key will be saved to a .pub file.
*/
static int printpubfile(const char* filename, const char * comment, int create_pub_file);
static void printpubkey(sign_key * key, int keytype);
static int printpubfile(const char* filename);
/* Print a help message */
static void printhelp(char * progname) {
@@ -122,7 +107,6 @@ static void printhelp(char * progname) {
" Ed25519 has a fixed size of 256 bits\n"
#endif
"-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
"-C Specify the key comment (email).\n"
#if DEBUG_TRACE
"-v verbose\n"
#endif
@@ -143,19 +127,18 @@ static void check_signkey_bits(enum signkey_type type, int bits)
#endif
#if DROPBEAR_RSA
case DROPBEAR_SIGNKEY_RSA:
if (bits < 1024 || bits > 4096 || (bits % 8 != 0)) {
dropbear_exit("Bits must satisfy 1024 <= bits <= 4096, and be a"
if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
" multiple of 8\n");
}
break;
#endif
#if DROPBEAR_DSS
#if DROPEAR_DSS
case DROPBEAR_SIGNKEY_DSS:
if (bits != 1024) {
dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
exit(EXIT_FAILURE);
}
break;
#endif
default:
(void)0; /* quiet, compiler. ecdsa handles checks itself */
@@ -173,10 +156,8 @@ int main(int argc, char ** argv) {
char ** next = NULL;
char * filename = NULL;
enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
char * typetext = DEFAULT_KEY_TYPE_NAME;
char * typetext = NULL;
char * sizetext = NULL;
char * passphrase = NULL;
char * comment = NULL;
unsigned int bits = 0, genbits;
int printpub = 0;
@@ -205,9 +186,6 @@ int main(int argc, char ** argv) {
case 's':
next = &sizetext;
break;
case 'C':
next = &comment;
break;
case 'y':
printpub = 1;
break;
@@ -215,16 +193,11 @@ int main(int argc, char ** argv) {
printhelp(argv[0]);
exit(EXIT_SUCCESS);
break;
case 'v':
#if DEBUG_TRACE
debug_trace = DROPBEAR_VERBOSE_LEVEL;
case 'v':
debug_trace = 1;
break;
#endif
break;
case 'q':
break; /* quiet is default */
case 'N':
next = &passphrase;
break;
default:
fprintf(stderr, "Unknown argument %s\n", argv[i]);
printhelp(argv[0]);
@@ -241,10 +214,17 @@ int main(int argc, char ** argv) {
}
if (printpub) {
int ret = printpubfile(filename, NULL, 0);
int ret = printpubfile(filename);
exit(ret);
}
/* check/parse args */
if (!typetext) {
fprintf(stderr, "Must specify key type\n");
printhelp(argv[0]);
exit(EXIT_FAILURE);
}
#if DROPBEAR_RSA
if (strcmp(typetext, "rsa") == 0)
{
@@ -285,11 +265,6 @@ int main(int argc, char ** argv) {
check_signkey_bits(keytype, bits);;
}
if (passphrase && *passphrase != '\0') {
fprintf(stderr, "Only empty passphrase is supported\n");
exit(EXIT_FAILURE);
}
genbits = signkey_generate_get_bits(keytype, bits);
fprintf(stderr, "Generating %u bit %s key, this may take a while...\n", genbits, typetext);
if (signkey_generate(keytype, bits, filename, 0) == DROPBEAR_FAILURE)
@@ -297,13 +272,13 @@ int main(int argc, char ** argv) {
dropbear_exit("Failed to generate key.\n");
}
printpubfile(filename, comment, 1);
printpubfile(filename);
return EXIT_SUCCESS;
}
#endif
static int printpubfile(const char* filename, const char* comment, int create_pub_file) {
static int printpubfile(const char* filename) {
buffer *buf = NULL;
sign_key *key = NULL;
@@ -329,12 +304,13 @@ static int printpubfile(const char* filename, const char* comment, int create_pu
goto out;
}
printpubkey(key, keytype, comment, create_pub_file, filename);
printpubkey(key, keytype);
err = DROPBEAR_SUCCESS;
out:
buf_burn_free(buf);
buf_burn(buf);
buf_free(buf);
buf = NULL;
if (key) {
sign_key_free(key);
@@ -343,7 +319,7 @@ out:
return err;
}
static void printpubkey(sign_key * key, int keytype, const char * comment, int create_pub_file, const char * filename) {
static void printpubkey(sign_key * key, int keytype) {
buffer * buf = NULL;
unsigned char base64key[MAX_PUBKEY_SIZE*2];
@@ -355,31 +331,6 @@ static void printpubkey(sign_key * key, int keytype, const char * comment, int c
struct passwd * pw = NULL;
char * username = NULL;
char hostname[100];
char * filename_pub = NULL;
FILE *pubkey_file = NULL;
if (create_pub_file) {
int pubkey_fd = -1;
int filename_pub_len = 0;
filename_pub_len = strlen(filename) + 5;
filename_pub = m_malloc(filename_pub_len);
snprintf(filename_pub, filename_pub_len, "%s.pub", filename);
/* open() to use O_EXCL, then use a FILE* for fprintf().
* dprintf() is only posix2008 onwards */
pubkey_fd = open(filename_pub, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (pubkey_fd >= 0) {
/* Convert the fd to a FILE*. The underlying FD is closed
* by later fclose() */
pubkey_file = fdopen(pubkey_fd, "w");
if (!pubkey_file) {
m_close(pubkey_fd);
}
}
if (!pubkey_file) {
dropbear_log(LOG_ERR, "Save public key to %s failed: %s", filename_pub, strerror(errno));
}
}
buf = buf_new(MAX_PUBKEY_SIZE);
buf_put_pub_key(buf, key, keytype);
@@ -391,50 +342,26 @@ static void printpubkey(sign_key * key, int keytype, const char * comment, int c
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);
printf("Public key portion is:\n");
fp = sign_key_fingerprint(buf_getptr(buf, len), len);
if (comment) {
printf("%s %s %s\n",
typestring, base64key, comment);
if (pubkey_file) {
fprintf(pubkey_file, "%s %s %s\n",
typestring, base64key, comment);
}
} else {
/* a user@host comment is informative */
username = "";
pw = getpwuid(getuid());
if (pw) {
username = pw->pw_name;
}
gethostname(hostname, sizeof(hostname));
hostname[sizeof(hostname) - 1] = '\0';
printf("%s %s %s@%s\n",
typestring, base64key, username, hostname);
if (pubkey_file) {
fprintf(pubkey_file, "%s %s %s@%s\n",
typestring, base64key, username, hostname);
}
/* a user@host comment is informative */
username = "";
pw = getpwuid(getuid());
if (pw) {
username = pw->pw_name;
}
fp = sign_key_fingerprint(buf_getptr(buf, len), len);
printf("Fingerprint: %s\n", fp);
gethostname(hostname, sizeof(hostname));
hostname[sizeof(hostname)-1] = '\0';
printf("Public key portion is:\n%s %s %s@%s\nFingerprint: %s\n",
typestring, base64key, username, hostname, fp);
m_free(fp);
buf_free(buf);
if (pubkey_file) {
if (fsync(fileno(pubkey_file)) != 0) {
dropbear_log(LOG_ERR, "fsync of %s failed: %s", filename_pub, strerror(errno));
}
fclose(pubkey_file);
}
m_free(filename_pub);
}

View File

View File

View File

View File

View File

@@ -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++) {

View File

@@ -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) {

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