mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Compare commits
51 Commits
sync_DROPB
...
coverity
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ea2e3463d | ||
|
|
ddb6751ab4 | ||
|
|
6e3c3c8c51 | ||
|
|
ef080502f8 | ||
|
|
fdbdbe5703 | ||
|
|
921592d37e | ||
|
|
04a02730bc | ||
|
|
dcce2cfd8d | ||
|
|
00a1290173 | ||
|
|
a3a0b26581 | ||
|
|
276197b404 | ||
|
|
484d1e9b81 | ||
|
|
278a3e43e5 | ||
|
|
2df2117388 | ||
|
|
187fc95deb | ||
|
|
b75a033787 | ||
|
|
423be0d5e6 | ||
|
|
68b3ef0734 | ||
|
|
d58e0497cc | ||
|
|
af10eb8346 | ||
|
|
8e93ac9925 | ||
|
|
6d5b27715a | ||
|
|
f295fbe0b2 | ||
|
|
575f0e5f92 | ||
|
|
85374c5ba2 | ||
|
|
83f3f55280 | ||
|
|
b2beb2c2da | ||
|
|
48ad370a19 | ||
|
|
c36f94a322 | ||
|
|
6493bbb7e7 | ||
|
|
3ec2737d54 | ||
|
|
72ccfda5b2 | ||
|
|
003ec5d356 | ||
|
|
f91d66448a | ||
|
|
ccfdf7e039 | ||
|
|
95ce05da40 | ||
|
|
c5d53cf81c | ||
|
|
5574460d25 | ||
|
|
233fd96994 | ||
|
|
d1b29336b1 | ||
|
|
fa5eb62464 | ||
|
|
0b48a4f879 | ||
|
|
00ef081fcf | ||
|
|
dabeaec461 | ||
|
|
d4ed2fffe4 | ||
|
|
0533b87b1a | ||
|
|
7504cd1a1a | ||
|
|
482dc0eff4 | ||
|
|
fc34d02427 | ||
|
|
5ce5fbcba0 | ||
|
|
31d2311537 |
9
.github/multiwrapper
vendored
9
.github/multiwrapper
vendored
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# symlink this to dropbear/dbclient/dropbearkey next to dropbearmulti
|
||||
# good enough for testing purposes.
|
||||
|
||||
DIR=$(dirname $0)
|
||||
PROG=$(basename $0)
|
||||
exec $DIR/dropbearmulti $PROG "$@"
|
||||
|
||||
25
.github/workflows/autoconf.yml
vendored
25
.github/workflows/autoconf.yml
vendored
@@ -1,25 +0,0 @@
|
||||
# Checks that autoconf has been run if configure.ac was updated
|
||||
# Assumes that autoconf 2.71 was run, the same as ubuntu 22.04
|
||||
name: Autoconf Up To Date
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
autoconf:
|
||||
runs-on: 'ubuntu-22.04'
|
||||
|
||||
steps:
|
||||
- name: deps
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install autoconf
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: run autoconf
|
||||
run: autoconf && autoheader
|
||||
|
||||
- name: check no difference
|
||||
run: git diff --exit-code
|
||||
290
.github/workflows/build.yml
vendored
290
.github/workflows/build.yml
vendored
@@ -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
|
||||
30
.github/workflows/cifuzz.yml
vendored
30
.github/workflows/cifuzz.yml
vendored
@@ -1,30 +0,0 @@
|
||||
# Runs fuzzers for a little while on pull requests.
|
||||
# From https://google.github.io/oss-fuzz/getting-started/continuous-integration/
|
||||
name: CIFuzz
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'dropbear'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'dropbear'
|
||||
fuzz-seconds: 1200
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
25
.github/workflows/outoftree.yml
vendored
25
.github/workflows/outoftree.yml
vendored
@@ -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
|
||||
36
.github/workflows/tarball.yml
vendored
36
.github/workflows/tarball.yml
vendored
@@ -1,36 +0,0 @@
|
||||
name: tarball sha256sum
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
tarball:
|
||||
runs-on: 'ubuntu-22.04'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@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
14
.gitignore
vendored
@@ -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/
|
||||
|
||||
29
.hgsigs
Normal file
29
.hgsigs
Normal 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
61
.hgtags
Normal 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
36
.travis.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
language: c
|
||||
|
||||
git:
|
||||
depth: 3
|
||||
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: "F4rKQrHK/u58vPo3F9+x0WYXAeMFJvvtH9BIGZqx9yw8bUnL+gk0Ge9wnHHTXRcgCTqoc7B35uMS5njpH+Su/esVjrLAq85f/AmQctlRpmApwGK9LyxkIvx3UJN0nqfeeDXA90/8FUZ+n/qnCydXmYCEgqSaBCNydDxW1oqYUIc="
|
||||
- BUNDLEDLIBTOM=--enable-bundled-libtom
|
||||
- MULTI=1
|
||||
|
||||
before_install:
|
||||
- echo -n | openssl s_client -connect https://scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
|
||||
- zlib1g-dev
|
||||
- libtomcrypt-dev
|
||||
- libtommath-dev
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "mkj/dropbear"
|
||||
description: "Dropbear SSH"
|
||||
notification_email: matt@ucc.asn.au
|
||||
build_command_prepend: autoconf && autoheader && ./configure --enable-bundled-libtom CFLAGS='-O2 -Wall -Wno-pointer-sign' --prefix=$HOME/inst
|
||||
build_command: make MULTI=1
|
||||
branch_pattern: coverity
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- coverity
|
||||
389
CHANGES
389
CHANGES
@@ -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
|
||||
|
||||
|
||||
115
DEVELOPING.md
115
DEVELOPING.md
@@ -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.
|
||||
|
||||
14
Dockerfile
14
Dockerfile
@@ -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"]
|
||||
@@ -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
93
INSTALL
Normal 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.
|
||||
97
INSTALL.md
97
INSTALL.md
@@ -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
22
MULTI
Normal 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>
|
||||
25
MULTI.md
25
MULTI.md
@@ -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>
|
||||
```
|
||||
208
Makefile.in
208
Makefile.in
@@ -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
79
README
Normal 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.
|
||||
84
README.md
84
README.md
@@ -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
53
SMALL
Normal 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.
|
||||
59
SMALL.md
59
SMALL.md
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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"))
|
||||
@@ -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);
|
||||
|
||||
10
build.sh
10
build.sh
@@ -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
|
||||
@@ -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[]);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -115,7 +115,6 @@ void recv_msg_userauth_info_request() {
|
||||
|
||||
for (i = 0; i < num_prompts; i++) {
|
||||
unsigned int response_len = 0;
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
prompt = buf_getstring(ses.payload, NULL);
|
||||
cleantext(prompt);
|
||||
|
||||
@@ -120,7 +120,7 @@ void cli_auth_password() {
|
||||
char* password = NULL;
|
||||
char prompt[80];
|
||||
|
||||
DEBUG1(("enter cli_auth_password"))
|
||||
TRACE(("enter cli_auth_password"))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
snprintf(prompt, sizeof(prompt), "%s@%s's password: ",
|
||||
@@ -155,7 +155,7 @@ void cli_auth_password() {
|
||||
|
||||
encrypt_packet();
|
||||
m_burn(password, strlen(password));
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
|
||||
TRACE(("leave cli_auth_password"))
|
||||
}
|
||||
#endif /* DROPBEAR_CLI_PASSWORD_AUTH */
|
||||
@@ -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();
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
static int newtcpforwarded(struct Channel * channel);
|
||||
|
||||
const struct ChanType cli_chan_tcpremote = {
|
||||
1, /* sepfds */
|
||||
"forwarded-tcpip",
|
||||
newtcpforwarded,
|
||||
NULL,
|
||||
@@ -50,8 +51,9 @@ static int cli_localtcp(const char* listenaddr,
|
||||
const char* remoteaddr,
|
||||
unsigned int remoteport);
|
||||
static const struct ChanType cli_chan_tcplocal = {
|
||||
1, /* sepfds */
|
||||
"direct-tcpip",
|
||||
NULL,
|
||||
tcp_prio_inithandler,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -271,11 +273,12 @@ static int newtcpforwarded(struct Channel * channel) {
|
||||
origaddr, origport);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
|
||||
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done,
|
||||
channel, NULL, NULL, DROPBEAR_PRIO_NORMAL);
|
||||
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel, NULL, NULL);
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
|
||||
err = SSH_OPEN_IN_PROGRESS;
|
||||
|
||||
out:
|
||||
@@ -64,6 +64,14 @@ static const struct dropbear_cipher dropbear_aes256 =
|
||||
static const struct dropbear_cipher dropbear_aes128 =
|
||||
{&aes_desc, 16, 16};
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH256
|
||||
static const struct dropbear_cipher dropbear_twofish256 =
|
||||
{&twofish_desc, 32, 16};
|
||||
#endif
|
||||
#if DROPBEAR_TWOFISH128
|
||||
static const struct dropbear_cipher dropbear_twofish128 =
|
||||
{&twofish_desc, 16, 16};
|
||||
#endif
|
||||
#if DROPBEAR_3DES
|
||||
static const struct dropbear_cipher dropbear_3des =
|
||||
{&des3_desc, 24, 8};
|
||||
@@ -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);
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -35,7 +35,7 @@ runopts opts; /* GLOBAL */
|
||||
|
||||
/* returns success or failure, and the keytype in *type. If we want
|
||||
* to restrict the type, type can contain a type to return */
|
||||
int readhostkey(const char * filename, sign_key * hostkey,
|
||||
int readhostkey(const char * filename, sign_key * hostkey,
|
||||
enum signkey_type *type) {
|
||||
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
@@ -57,7 +57,8 @@ int readhostkey(const char * filename, sign_key * hostkey,
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
out:
|
||||
|
||||
buf_burn_free(buf);
|
||||
buf_burn(buf);
|
||||
buf_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -100,74 +101,4 @@ void print_version() {
|
||||
fprintf(stderr, "Dropbear v%s\n", DROPBEAR_VERSION);
|
||||
}
|
||||
|
||||
void parse_recv_window(const char* recv_window_arg) {
|
||||
int ret;
|
||||
unsigned int rw;
|
||||
|
||||
ret = m_str_to_uint(recv_window_arg, &rw);
|
||||
if (ret == DROPBEAR_FAILURE || rw == 0 || rw > MAX_RECV_WINDOW) {
|
||||
if (rw > MAX_RECV_WINDOW) {
|
||||
opts.recv_window = MAX_RECV_WINDOW;
|
||||
}
|
||||
dropbear_log(LOG_WARNING, "Bad recv window '%s', using %d",
|
||||
recv_window_arg, opts.recv_window);
|
||||
} else {
|
||||
opts.recv_window = rw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Splits addr:port. Handles IPv6 [2001:0011::4]:port style format.
|
||||
Returns first/second parts as malloced strings, second will
|
||||
be NULL if no separator is found.
|
||||
:port -> (NULL, "port")
|
||||
port -> (port, NULL)
|
||||
addr:port (addr, port)
|
||||
addr: -> (addr, "")
|
||||
Returns DROPBEAR_SUCCESS/DROPBEAR_FAILURE */
|
||||
int split_address_port(const char* spec, char **first, char ** second) {
|
||||
char *spec_copy = NULL, *addr = NULL, *colon = NULL;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
*first = NULL;
|
||||
*second = NULL;
|
||||
spec_copy = m_strdup(spec);
|
||||
addr = spec_copy;
|
||||
|
||||
if (*addr == '[') {
|
||||
addr++;
|
||||
colon = strchr(addr, ']');
|
||||
if (!colon) {
|
||||
dropbear_log(LOG_WARNING, "Bad address '%s'", spec);
|
||||
goto out;
|
||||
}
|
||||
*colon = '\0';
|
||||
colon++;
|
||||
if (*colon == '\0') {
|
||||
/* No port part */
|
||||
colon = NULL;
|
||||
} else if (*colon != ':') {
|
||||
dropbear_log(LOG_WARNING, "Bad address '%s'", spec);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* search for ':', that separates address and port */
|
||||
colon = strrchr(addr, ':');
|
||||
}
|
||||
|
||||
/* colon points to ':' now, or is NULL */
|
||||
if (colon) {
|
||||
/* Split the address/port */
|
||||
*colon = '\0';
|
||||
colon++;
|
||||
*second = m_strdup(colon);
|
||||
}
|
||||
if (strlen(addr)) {
|
||||
*first = m_strdup(addr);
|
||||
}
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
|
||||
out:
|
||||
m_free(spec_copy);
|
||||
return ret;
|
||||
}
|
||||
@@ -64,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
1342
src/config.guess → config.guess
vendored
1342
src/config.guess → config.guess
vendored
File diff suppressed because it is too large
Load Diff
1203
src/config.sub → config.sub
vendored
1203
src/config.sub → config.sub
vendored
File diff suppressed because it is too large
Load Diff
115
configure.ac
115
configure.ac
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
36
debian/changelog
vendored
@@ -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.
|
||||
|
||||
2
debian/dropbear.docs
vendored
2
debian/dropbear.docs
vendored
@@ -1,3 +1,3 @@
|
||||
README.md
|
||||
README
|
||||
debian/README.runit
|
||||
debian/README.Debian.diet
|
||||
|
||||
2
debian/dropbear.init
vendored
2
debian/dropbear.init
vendored
@@ -25,7 +25,7 @@ set -e
|
||||
cancel() { echo "$1" >&2; exit 0; };
|
||||
test ! -r /etc/default/dropbear || . /etc/default/dropbear
|
||||
test -x "$DAEMON" || cancel "$DAEMON does not exist or is not executable."
|
||||
test ! -x /usr/sbin/update-service || ! update-service --check dropbear || \
|
||||
test ! -x /usr/sbin/update-service || ! update-service --check dropbear ||
|
||||
cancel 'The dropbear service is controlled through runit, use the sv(8) program'
|
||||
|
||||
test -z "$DROPBEAR_BANNER" || \
|
||||
|
||||
4
debian/rules
vendored
4
debian/rules
vendored
@@ -77,9 +77,9 @@ install: deb-checkdir deb-checkuid build-stamp
|
||||
# man pages
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man8
|
||||
install -d -m0755 '$(DIR)'/usr/share/man/man1
|
||||
install -m644 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
|
||||
|
||||
@@ -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. */
|
||||
@@ -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_ */
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -9,7 +9,7 @@ dropbearconvert \- convert between Dropbear and OpenSSH private key formats
|
||||
.I output_file
|
||||
.SH DESCRIPTION
|
||||
.B Dropbear
|
||||
and
|
||||
and
|
||||
.B OpenSSH
|
||||
SSH implementations have different private key formats.
|
||||
.B dropbearconvert
|
||||
@@ -24,15 +24,15 @@ first.
|
||||
.SH ARGUMENTS
|
||||
.TP
|
||||
.I input_type
|
||||
Either
|
||||
Either
|
||||
.I dropbear
|
||||
or
|
||||
or
|
||||
.I openssh
|
||||
.TP
|
||||
.I output_type
|
||||
Either
|
||||
Either
|
||||
.I dropbear
|
||||
or
|
||||
or
|
||||
.I openssh
|
||||
.TP
|
||||
.I input_file
|
||||
@@ -40,15 +40,6 @@ An existing Dropbear or OpenSSH private key file
|
||||
.TP
|
||||
.I output_file
|
||||
The path to write the converted private key file. For client authentication ~/.ssh/id_dropbear is loaded by default
|
||||
.SH SUPPORTED FORMATS
|
||||
.B dropbearconvert
|
||||
can read OpenSSH format files, and older PEM format files (
|
||||
.B ssh-keygen
|
||||
.I -m PEM
|
||||
).
|
||||
.B dropbearconvert
|
||||
will write OpenSSH format files, usable with OpenSSH 6.5 and later.
|
||||
Reading OpenSSH format DSS files or PKCS8 files is not currently supported.
|
||||
.SH EXAMPLE
|
||||
# dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/id_dropbear
|
||||
.SH AUTHOR
|
||||
@@ -69,7 +69,7 @@ int main(int argc, char ** argv) {
|
||||
|
||||
#if DEBUG_TRACE
|
||||
/* It's hard for it to get in the way _too_ much */
|
||||
debug_trace = DROPBEAR_VERBOSE_LEVEL;
|
||||
debug_trace = 1;
|
||||
#endif
|
||||
|
||||
/* get the commandline options */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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++) {
|
||||
@@ -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
Reference in New Issue
Block a user