From b63e8d8694846715e25fd7f89c3cac21d0bdccef Mon Sep 17 00:00:00 2001 From: allegroai Date: Wed, 24 Jul 2024 03:31:27 +0300 Subject: [PATCH] sync github July 2024 --- .github/workflows/autoconf.yml | 4 +- .github/workflows/build.yml | 58 ++- .github/workflows/cifuzz.yml | 2 +- .github/workflows/outoftree.yml | 25 ++ .github/workflows/tarball.yml | 8 +- .gitignore | 6 +- .hgignore | 6 - .hgsigs | 31 -- .hgtags | 63 --- CHANGES | 108 ++++++ DEVELOPING.md | 115 +++--- Dockerfile | 14 - FUZZER-NOTES.md | 94 ++--- INSTALL | 93 ----- INSTALL.md | 97 +++++ MULTI | 22 -- MULTI.md | 25 ++ Makefile.in | 129 ++++--- README | 81 ---- README.md | 84 ++++ SMALL | 56 --- SMALL.md | 59 +++ _internal_/Dockerfile.python.nonroot | 21 + build.sh | 7 - configure | 195 +++++----- configure.ac | 7 +- debian/changelog | 12 + debian/dropbear.docs | 2 +- debian/rules | 4 +- fuzz/fuzzer-cliconf.c | 79 ++++ libtomcrypt/Makefile.in | 2 +- libtommath/Makefile.in | 2 +- libtommath/bn_mp_2expt.c | 4 + libtommath/bn_mp_grow.c | 4 + libtommath/bn_mp_init_size.c | 5 + libtommath/bn_mp_mul_2d.c | 4 + libtommath/bn_s_mp_mul_digs.c | 4 + libtommath/bn_s_mp_mul_digs_fast.c | 4 + libtommath/bn_s_mp_mul_high_digs.c | 4 + libtommath/bn_s_mp_mul_high_digs_fast.c | 4 + dbclient.1 => manpages/dbclient.1 | 101 ++++- dropbear.8 => manpages/dropbear.8 | 8 +- .../dropbearconvert.1 | 0 dropbearkey.1 => manpages/dropbearkey.1 | 0 release.sh | 20 +- agentfwd.h => src/agentfwd.h | 0 algo.h => src/algo.h | 0 atomicio.c => src/atomicio.c | 0 atomicio.h => src/atomicio.h | 0 auth.h => src/auth.h | 0 bignum.c => src/bignum.c | 0 bignum.h => src/bignum.h | 0 buffer.c => src/buffer.c | 0 buffer.h => src/buffer.h | 0 chachapoly.c => src/chachapoly.c | 0 chachapoly.h => src/chachapoly.h | 0 channel.h => src/channel.h | 7 +- chansession.h => src/chansession.h | 0 circbuffer.c => src/circbuffer.c | 0 circbuffer.h => src/circbuffer.h | 0 cli-agentfwd.c => src/cli-agentfwd.c | 0 cli-auth.c => src/cli-auth.c | 27 +- cli-authinteract.c => src/cli-authinteract.c | 0 cli-authpasswd.c => src/cli-authpasswd.c | 0 cli-authpubkey.c => src/cli-authpubkey.c | 4 + cli-channel.c => src/cli-channel.c | 0 cli-chansession.c => src/cli-chansession.c | 0 cli-kex.c => src/cli-kex.c | 18 +- cli-main.c => src/cli-main.c | 0 src/cli-readconf.c | 176 +++++++++ cli-runopts.c => src/cli-runopts.c | 360 ++++++++++++------ cli-session.c => src/cli-session.c | 11 + cli-tcpfwd.c => src/cli-tcpfwd.c | 0 common-algo.c => src/common-algo.c | 6 + common-channel.c => src/common-channel.c | 0 .../common-chansession.c | 0 common-kex.c => src/common-kex.c | 26 +- common-runopts.c => src/common-runopts.c | 0 common-session.c => src/common-session.c | 25 +- compat.c => src/compat.c | 0 compat.h => src/compat.h | 0 config.guess => src/config.guess | 57 ++- config.h.in => src/config.h.in | 2 +- config.sub => src/config.sub | 217 +++++++---- crypto_desc.c => src/crypto_desc.c | 0 crypto_desc.h => src/crypto_desc.h | 0 curve25519.c => src/curve25519.c | 0 curve25519.h => src/curve25519.h | 0 dbhelpers.c => src/dbhelpers.c | 0 dbhelpers.h => src/dbhelpers.h | 0 dbmalloc.c => src/dbmalloc.c | 0 dbmalloc.h => src/dbmalloc.h | 0 dbmulti.c => src/dbmulti.c | 5 +- dbrandom.c => src/dbrandom.c | 3 - dbrandom.h => src/dbrandom.h | 0 dbutil.c => src/dbutil.c | 14 +- dbutil.h => src/dbutil.h | 2 + debug.h => src/debug.h | 0 default_options.h => src/default_options.h | 37 +- dh_groups.c => src/dh_groups.c | 0 dh_groups.h => src/dh_groups.h | 0 dropbear_lint.sh => src/dropbear_lint.sh | 0 dropbearconvert.c => src/dropbearconvert.c | 0 dropbearkey.c => src/dropbearkey.c | 131 +++++-- dss.c => src/dss.c | 0 dss.h => src/dss.h | 0 ecc.c => src/ecc.c | 0 ecc.h => src/ecc.h | 0 ecdsa.c => src/ecdsa.c | 0 ecdsa.h => src/ecdsa.h | 0 ed25519.c => src/ed25519.c | 0 ed25519.h => src/ed25519.h | 0 fake-rfc2553.c => src/fake-rfc2553.c | 0 fake-rfc2553.h => src/fake-rfc2553.h | 0 filelist.txt => src/filelist.txt | 0 fuzz-wrapfd.h => src/fuzz-wrapfd.h | 0 fuzz.h => src/fuzz.h | 0 gcm.c => src/gcm.c | 0 gcm.h => src/gcm.h | 0 gendss.c => src/gendss.c | 0 gendss.h => src/gendss.h | 0 gened25519.c => src/gened25519.c | 0 gened25519.h => src/gened25519.h | 0 genrsa.c => src/genrsa.c | 0 genrsa.h => src/genrsa.h | 0 gensignkey.c => src/gensignkey.c | 0 gensignkey.h => src/gensignkey.h | 0 ifndef_wrapper.sh => src/ifndef_wrapper.sh | 0 includes.h => src/includes.h | 4 +- install-sh => src/install-sh | 0 kex.h => src/kex.h | 3 + keyimport.c => src/keyimport.c | 0 keyimport.h => src/keyimport.h | 0 list.c => src/list.c | 0 list.h => src/list.h | 0 listener.c => src/listener.c | 0 listener.h => src/listener.h | 0 loginrec.c => src/loginrec.c | 0 loginrec.h => src/loginrec.h | 0 ltc_prng.c => src/ltc_prng.c | 0 ltc_prng.h => src/ltc_prng.h | 0 netio.c => src/netio.c | 90 ++++- netio.h => src/netio.h | 7 +- options.h => src/options.h | 13 +- packet.c => src/packet.c | 0 packet.h => src/packet.h | 0 process-packet.c => src/process-packet.c | 34 +- progressmeter.c => src/progressmeter.c | 0 progressmeter.h => src/progressmeter.h | 0 pubkeyapi.h => src/pubkeyapi.h | 0 queue.c => src/queue.c | 0 queue.h => src/queue.h | 0 rsa.c => src/rsa.c | 0 rsa.h => src/rsa.h | 0 runopts.h => src/runopts.h | 45 ++- scp.c => src/scp.c | 7 +- scpmisc.c => src/scpmisc.c | 0 scpmisc.h => src/scpmisc.h | 0 service.h => src/service.h | 0 session.h => src/session.h | 0 signkey.c => src/signkey.c | 0 signkey.h => src/signkey.h | 0 signkey_ossh.c => src/signkey_ossh.c | 0 signkey_ossh.h => src/signkey_ossh.h | 0 sk-ecdsa.c => src/sk-ecdsa.c | 0 sk-ecdsa.h => src/sk-ecdsa.h | 0 sk-ed25519.c => src/sk-ed25519.c | 0 sk-ed25519.h => src/sk-ed25519.h | 0 ssh.h => src/ssh.h | 4 + sshpty.c => src/sshpty.c | 0 sshpty.h => src/sshpty.h | 0 svr-agentfwd.c => src/svr-agentfwd.c | 0 svr-auth.c => src/svr-auth.c | 72 ---- svr-authpam.c => src/svr-authpam.c | 0 svr-authpasswd.c => src/svr-authpasswd.c | 0 svr-authpubkey.c => src/svr-authpubkey.c | 0 .../svr-authpubkeyoptions.c | 0 svr-chansession.c => src/svr-chansession.c | 9 +- svr-kex.c => src/svr-kex.c | 0 svr-main.c => src/svr-main.c | 10 +- svr-runopts.c => src/svr-runopts.c | 101 +++-- svr-service.c => src/svr-service.c | 0 svr-session.c => src/svr-session.c | 6 + svr-tcpfwd.c => src/svr-tcpfwd.c | 67 +++- svr-x11fwd.c => src/svr-x11fwd.c | 0 sysoptions.h => src/sysoptions.h | 32 +- tcp-accept.c => src/tcp-accept.c | 2 +- tcpfwd.h => src/tcpfwd.h | 3 + termcodes.c => src/termcodes.c | 0 termcodes.h => src/termcodes.h | 0 x11fwd.h => src/x11fwd.h | 0 test/test_aslr.py | 7 +- test/test_dropbear.py | 6 +- test/test_dropbearconvert.py | 1 - 194 files changed, 2174 insertions(+), 1150 deletions(-) create mode 100644 .github/workflows/outoftree.yml delete mode 100644 .hgignore delete mode 100644 .hgsigs delete mode 100644 .hgtags delete mode 100644 Dockerfile delete mode 100644 INSTALL create mode 100644 INSTALL.md delete mode 100644 MULTI create mode 100644 MULTI.md delete mode 100644 README create mode 100644 README.md delete mode 100644 SMALL create mode 100644 SMALL.md create mode 100644 _internal_/Dockerfile.python.nonroot delete mode 100755 build.sh create mode 100644 fuzz/fuzzer-cliconf.c rename dbclient.1 => manpages/dbclient.1 (74%) rename dropbear.8 => manpages/dropbear.8 (97%) rename dropbearconvert.1 => manpages/dropbearconvert.1 (100%) rename dropbearkey.1 => manpages/dropbearkey.1 (100%) rename agentfwd.h => src/agentfwd.h (100%) rename algo.h => src/algo.h (100%) rename atomicio.c => src/atomicio.c (100%) rename atomicio.h => src/atomicio.h (100%) rename auth.h => src/auth.h (100%) rename bignum.c => src/bignum.c (100%) rename bignum.h => src/bignum.h (100%) rename buffer.c => src/buffer.c (100%) rename buffer.h => src/buffer.h (100%) rename chachapoly.c => src/chachapoly.c (100%) rename chachapoly.h => src/chachapoly.h (100%) rename channel.h => src/channel.h (94%) rename chansession.h => src/chansession.h (100%) rename circbuffer.c => src/circbuffer.c (100%) rename circbuffer.h => src/circbuffer.h (100%) rename cli-agentfwd.c => src/cli-agentfwd.c (100%) rename cli-auth.c => src/cli-auth.c (92%) rename cli-authinteract.c => src/cli-authinteract.c (100%) rename cli-authpasswd.c => src/cli-authpasswd.c (100%) rename cli-authpubkey.c => src/cli-authpubkey.c (98%) rename cli-channel.c => src/cli-channel.c (100%) rename cli-chansession.c => src/cli-chansession.c (100%) rename cli-kex.c => src/cli-kex.c (96%) rename cli-main.c => src/cli-main.c (100%) create mode 100644 src/cli-readconf.c rename cli-runopts.c => src/cli-runopts.c (75%) rename cli-session.c => src/cli-session.c (98%) rename cli-tcpfwd.c => src/cli-tcpfwd.c (100%) rename common-algo.c => src/common-algo.c (99%) rename common-channel.c => src/common-channel.c (100%) rename common-chansession.c => src/common-chansession.c (100%) rename common-kex.c => src/common-kex.c (98%) rename common-runopts.c => src/common-runopts.c (100%) rename common-session.c => src/common-session.c (97%) rename compat.c => src/compat.c (100%) rename compat.h => src/compat.h (100%) rename config.guess => src/config.guess (97%) rename config.h.in => src/config.h.in (99%) rename config.sub => src/config.sub (90%) rename crypto_desc.c => src/crypto_desc.c (100%) rename crypto_desc.h => src/crypto_desc.h (100%) rename curve25519.c => src/curve25519.c (100%) rename curve25519.h => src/curve25519.h (100%) rename dbhelpers.c => src/dbhelpers.c (100%) rename dbhelpers.h => src/dbhelpers.h (100%) rename dbmalloc.c => src/dbmalloc.c (100%) rename dbmalloc.h => src/dbmalloc.h (100%) rename dbmulti.c => src/dbmulti.c (95%) rename dbrandom.c => src/dbrandom.c (98%) rename dbrandom.h => src/dbrandom.h (100%) rename dbutil.c => src/dbutil.c (98%) rename dbutil.h => src/dbutil.h (98%) rename debug.h => src/debug.h (100%) rename default_options.h => src/default_options.h (95%) rename dh_groups.c => src/dh_groups.c (100%) rename dh_groups.h => src/dh_groups.h (100%) rename dropbear_lint.sh => src/dropbear_lint.sh (100%) rename dropbearconvert.c => src/dropbearconvert.c (100%) rename dropbearkey.c => src/dropbearkey.c (70%) rename dss.c => src/dss.c (100%) rename dss.h => src/dss.h (100%) rename ecc.c => src/ecc.c (100%) rename ecc.h => src/ecc.h (100%) rename ecdsa.c => src/ecdsa.c (100%) rename ecdsa.h => src/ecdsa.h (100%) rename ed25519.c => src/ed25519.c (100%) rename ed25519.h => src/ed25519.h (100%) rename fake-rfc2553.c => src/fake-rfc2553.c (100%) rename fake-rfc2553.h => src/fake-rfc2553.h (100%) rename filelist.txt => src/filelist.txt (100%) rename fuzz-wrapfd.h => src/fuzz-wrapfd.h (100%) rename fuzz.h => src/fuzz.h (100%) rename gcm.c => src/gcm.c (100%) rename gcm.h => src/gcm.h (100%) rename gendss.c => src/gendss.c (100%) rename gendss.h => src/gendss.h (100%) rename gened25519.c => src/gened25519.c (100%) rename gened25519.h => src/gened25519.h (100%) rename genrsa.c => src/genrsa.c (100%) rename genrsa.h => src/genrsa.h (100%) rename gensignkey.c => src/gensignkey.c (100%) rename gensignkey.h => src/gensignkey.h (100%) rename ifndef_wrapper.sh => src/ifndef_wrapper.sh (100%) rename includes.h => src/includes.h (98%) rename install-sh => src/install-sh (100%) rename kex.h => src/kex.h (97%) rename keyimport.c => src/keyimport.c (100%) rename keyimport.h => src/keyimport.h (100%) rename list.c => src/list.c (100%) rename list.h => src/list.h (100%) rename listener.c => src/listener.c (100%) rename listener.h => src/listener.h (100%) rename loginrec.c => src/loginrec.c (100%) rename loginrec.h => src/loginrec.h (100%) rename ltc_prng.c => src/ltc_prng.c (100%) rename ltc_prng.h => src/ltc_prng.h (100%) rename netio.c => src/netio.c (88%) rename netio.h => src/netio.h (89%) rename options.h => src/options.h (69%) rename packet.c => src/packet.c (100%) rename packet.h => src/packet.h (100%) rename process-packet.c => src/process-packet.c (89%) rename progressmeter.c => src/progressmeter.c (100%) rename progressmeter.h => src/progressmeter.h (100%) rename pubkeyapi.h => src/pubkeyapi.h (100%) rename queue.c => src/queue.c (100%) rename queue.h => src/queue.h (100%) rename rsa.c => src/rsa.c (100%) rename rsa.h => src/rsa.h (100%) rename runopts.h => src/runopts.h (86%) rename scp.c => src/scp.c (99%) rename scpmisc.c => src/scpmisc.c (100%) rename scpmisc.h => src/scpmisc.h (100%) rename service.h => src/service.h (100%) rename session.h => src/session.h (100%) rename signkey.c => src/signkey.c (100%) rename signkey.h => src/signkey.h (100%) rename signkey_ossh.c => src/signkey_ossh.c (100%) rename signkey_ossh.h => src/signkey_ossh.h (100%) rename sk-ecdsa.c => src/sk-ecdsa.c (100%) rename sk-ecdsa.h => src/sk-ecdsa.h (100%) rename sk-ed25519.c => src/sk-ed25519.c (100%) rename sk-ed25519.h => src/sk-ed25519.h (100%) rename ssh.h => src/ssh.h (97%) rename sshpty.c => src/sshpty.c (100%) rename sshpty.h => src/sshpty.h (100%) rename svr-agentfwd.c => src/svr-agentfwd.c (100%) rename svr-auth.c => src/svr-auth.c (84%) rename svr-authpam.c => src/svr-authpam.c (100%) rename svr-authpasswd.c => src/svr-authpasswd.c (100%) rename svr-authpubkey.c => src/svr-authpubkey.c (100%) rename svr-authpubkeyoptions.c => src/svr-authpubkeyoptions.c (100%) rename svr-chansession.c => src/svr-chansession.c (99%) rename svr-kex.c => src/svr-kex.c (100%) rename svr-main.c => src/svr-main.c (98%) rename svr-runopts.c => src/svr-runopts.c (91%) rename svr-service.c => src/svr-service.c (100%) rename svr-session.c => src/svr-session.c (98%) rename svr-tcpfwd.c => src/svr-tcpfwd.c (84%) rename svr-x11fwd.c => src/svr-x11fwd.c (100%) rename sysoptions.h => src/sysoptions.h (92%) rename tcp-accept.c => src/tcp-accept.c (98%) rename tcpfwd.h => src/tcpfwd.h (97%) rename termcodes.c => src/termcodes.c (100%) rename termcodes.h => src/termcodes.h (100%) rename x11fwd.h => src/x11fwd.h (100%) diff --git a/.github/workflows/autoconf.yml b/.github/workflows/autoconf.yml index 51d37d4..fa2d52f 100644 --- a/.github/workflows/autoconf.yml +++ b/.github/workflows/autoconf.yml @@ -1,5 +1,5 @@ # Checks that autoconf has been run if configure.ac was updated -# Assumes that autoconf 2.69 was run, the same as ubuntu 20.04 +# Assumes that autoconf 2.71 was run, the same as ubuntu 22.04 name: Autoconf Up To Date on: pull_request: @@ -16,7 +16,7 @@ jobs: sudo apt-get -y update sudo apt-get -y install autoconf - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: run autoconf run: autoconf && autoheader diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2ea3308..c18da31 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,7 @@ jobs: - name: bundled libtom, bionic , no writev() # test can use an older distro with bundled libtommath - os: ubuntu-18.04 + os: ubuntu-20.04 configure_flags: --enable-bundled-libtom --enable-werror # NOWRITEV is unrelated, test here to save a job nowritev: 1 @@ -57,6 +57,21 @@ jobs: # 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 @@ -70,16 +85,10 @@ jobs: # .../ranlib: file: libtomcrypt.a(cbc_setiv.o) has no symbols ranlib: ranlib -no_warning_for_no_symbols - - name: macos 11 - os: macos-11 - cc: clang - extracflags: -Wno-deprecated-declarations -Wno-undef - runcheck: 'no' - apt: 'no' - ranlib: ranlib -no_warning_for_no_symbols - # Check that debug code doesn't bitrot - name: DEBUG_TRACE + nondefault: 1 + configure_flags: --enable-pam localoptions: | #define DEBUG_TRACE 5 @@ -124,6 +133,22 @@ jobs: #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 @@ -168,7 +193,7 @@ jobs: sudo apt-get -y update sudo apt-get -y install zlib1g-dev libtomcrypt-dev libtommath-dev mercurial python3-venv libpam0g-dev $CC - - uses: actions/checkout@v2 + - 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) @@ -179,22 +204,22 @@ jobs: - name: localoptions run: | - echo "$LOCALOPTIONS" > localoptions.h - echo "#define DROPBEAR_DSS 1" >> localoptions.h - cat localoptions.h + 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$' default_options.h | sed 's/0$/1/' > localoptions.h + 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: make -j3 $MAKE_TARGET + run: | + cat localoptions.h + make -j3 $MAKE_TARGET - name: multilink if: ${{ matrix.multilink }} @@ -247,9 +272,6 @@ jobs: - name: genrsa if: ${{ matrix.runcheck != 'no' }} run: ~/inst/bin/dropbearkey -t rsa -f testrsa - - name: gendss - if: ${{ matrix.runcheck != 'no' }} - run: ~/inst/bin/dropbearkey -t dss -f testdss - name: genecdsa256 if: ${{ matrix.runcheck != 'no' }} run: ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256 diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 0d61e3b..2e2ff82 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -23,7 +23,7 @@ jobs: fuzz-seconds: 1200 dry-run: false - name: Upload Crash - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/.github/workflows/outoftree.yml b/.github/workflows/outoftree.yml new file mode 100644 index 0000000..14f7eae --- /dev/null +++ b/.github/workflows/outoftree.yml @@ -0,0 +1,25 @@ +# 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 diff --git a/.github/workflows/tarball.yml b/.github/workflows/tarball.yml index 7c25416..0938ffa 100644 --- a/.github/workflows/tarball.yml +++ b/.github/workflows/tarball.yml @@ -8,19 +8,19 @@ jobs: runs-on: 'ubuntu-22.04' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: release.sh run: ./release.sh --testrel | tee log1.txt - name: extract output run: | - grep ^SHA256 log1.txt > sha256sum.txt + 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@v3 + uses: actions/upload-artifact@v4 with: name: sha256sum path: | @@ -28,7 +28,7 @@ jobs: hash.txt - name: tarball - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: tarball # only keep for debugging diff --git a/.gitignore b/.gitignore index 65b8e15..7cc820f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ *.bbg *.prof .*.swp +/obj /autom4te.cache /config.log /config.status @@ -26,4 +27,7 @@ Makefile tags .pytest* *.pyc -/test/venv +/test/venv/ +/test/init/ +/test/fakekey +.vscode/ diff --git a/.hgignore b/.hgignore deleted file mode 100644 index d0aaa7c..0000000 --- a/.hgignore +++ /dev/null @@ -1,6 +0,0 @@ -\..*\.swp -.*~ -tags -.pytest* -.*\.pyc -test/venv diff --git a/.hgsigs b/.hgsigs deleted file mode 100644 index 149e10e..0000000 --- a/.hgsigs +++ /dev/null @@ -1,31 +0,0 @@ -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= -88f63b8b0f131f24aa90c9b852622b922b1ad738 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl71/sAACgkQRJMUlPKcZ3OlSQ/9GYLotOmsYK0gvSfWLYR9a8WGgT/4EU6RgAkMBLS9TBp0E3V4VUDralnqoId7hNO2cUkRS7boOM2g4/YRShah8gonSJa70lKjUpDeQUPuGwUYWLNKr9qxJtnAcd1rOE4WYxKEUfjPWHBbVsT3QIIdj1Zy31GDKZgELRBQeOyt62RdXYHMaMHHDgg2U/wO9bcRRe5G7mYJf7Vm8sAWyTZXvta2jORxgs4XxWe7xJ9Dj0lMSG5HmfvH5NrGHM1GK3pL0GREKj2+xNSFdkSeHIgSSoHM2qZTVSWtNfx0+fZaRBgvXPPYzDTTghj1mKEaPFoRzg/B8s+NmHupJftT1yyapKFjALo1N6eaPHRRSwVfmnoWSJLu4fwL8TK5wMJr9eGl3QgAnperQPEFT9UHJBIwZ1D+RMuI3pEESdHBJFAYIAyisJI6XyzMhLsysoShlHs6OjFcJ9jTe4pzg9pO+KaPbLYsBJxJUsrtHwV8P9CHxY6CEuKm0AZjYDopYhzLuAUjGJjYDf/C9vJ/xtTOqIm9nywfcFwqgLrmQFhNHHGyOJVr+y/cey1sT9E4/gBv9kor+6qSITALv2g0JTaOpzpkE0zbafUy2r777Wex4WNQEha6bYZFi2aiqxqqX93UHzv+YhmN8n9mlc21xoZMPNtAb2mSxx7rO+PScb5uflKOCYE= -5879c5829e8569466386e7c64252b01b99705628 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl+axlIACgkQRJMUlPKcZ3PZuhAAkzCj+lOt2hHigIHB0zkNUC9nRIE1TItJD4wqQ03nMY4ycBMsb74o1AHsQTtVG6sm2YGSmQuZ0VxG1iuW9nKTsM1hzB40G45i5waIEzxVG8PbZ2i6zLK2Xz2YQ+FBvIg1EKfH7Dyd3r4FqYxauGOQdrUiKwuc3H4r65HpUmT0tIypqahFoRmj1+K/ZSPak0+ZPL27VQ4b/Ts8QS7XwFYTZsMDovYNdFJmaMhBbBe33/zGFWBPk6NCJWrBd3jmJN/LhZp0a5T4fAZ6iA2WjXDWOSiWZaLLk49zM6WYrc4QihEj7ngecj/UUXKR/sWPva8+rHf9YQLZu2lc6IMABCpUkeKLFoJqzvnKGA2rhl1LpRcnNA30/7yJt0YhfFcKhBkjjSxiOH3v0qMPADHMo5poqCKH/x4TVGVyVgzCqcxd+AzsDu77fzfzbxlyQ7wp+VmwXmeHbPfuBc8u9HUBa6Fc4b667aDD26a2S9VKdRYuSp3DkOwCLJUmRqmw+sXKvXlPyxPMUxOi/4R5nbJacD5Js1AH7WH49pAFMJ6bDCQ8QEmOh+Qpqc3RzTBwt1CLl+zt0NLKDmRYSgAY9GZpuju7r+aj2Semjd7nwmq4Y5xtWCh673lea/n7JS0mtBWouVbGgMJErg7QjuqOS3oE77viLcGLpX9niDcGvCL/N3gE13A= diff --git a/.hgtags b/.hgtags deleted file mode 100644 index 23ccaa4..0000000 --- a/.hgtags +++ /dev/null @@ -1,63 +0,0 @@ -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 -73646de50f1351735c868d4874f058ff9ad62c96 DROPBEAR_2020.80 -4b984c42372d01fcc2fd487c58af6a5aa65eb88e DROPBEAR_2020.81 diff --git a/CHANGES b/CHANGES index 38918fb..888658f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,111 @@ +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: diff --git a/DEVELOPING.md b/DEVELOPING.md index 1846b15..b6d3df8 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -1,75 +1,88 @@ -# Developer Notes +## Developer Notes -## Building +#### Building -See [INSTALL](INSTALL) for build instructions. -[SMALL](SMALL) has hints for building smaller binaries, also see comments -in default_options.h. +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). -## Debug printing +Debug symbols can be generated by adding `-g` to `CFLAGS` environment variable. +``` +export CFLAGS="$CFLAGS -g" +``` -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. +#### 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. -## Random sources +Following are generated files in the format `: ()` +``` +- 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. -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. +#### Debug printing -## Algorithms +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. -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). +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. -Enabling/disabling algorithms is done in [localoptions.h](localoptions.h), -see [default_options.h](default_options.h). +#### Random sources -## Style +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. -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. +#### 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. All `if` statements should have braces, no exceptions. -Avoid using pointer arithmetic, instead the functions in -[buffer.h](buffer.h) should be used. +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. 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 - -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. +#### Connection setup +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. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 2fc7685..0000000 --- a/Dockerfile +++ /dev/null @@ -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"] diff --git a/FUZZER-NOTES.md b/FUZZER-NOTES.md index 4967eba..703fb24 100644 --- a/FUZZER-NOTES.md +++ b/FUZZER-NOTES.md @@ -1,77 +1,55 @@ -# 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()`](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()`](./src/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()`](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. +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. -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-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/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](dbrandom.c#L185) -every time so that failures can be reproduced. +When running in fuzzing mode Dropbear uses a [fixed seed](./src/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](packet.c). +Since the fuzzer cannot generate valid encrypted input the packet decryption and message authentication calls are disabled, see [packet.c](./src/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](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. +* [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. This is testing libtommath ECC 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. +* [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. diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 60eb707..0000000 --- a/INSTALL +++ /dev/null @@ -1,93 +0,0 @@ -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. - -- 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 - -(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 algorithms, 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. diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..0129f67 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,97 @@ +## 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. diff --git a/MULTI b/MULTI deleted file mode 100644 index 606f815..0000000 --- a/MULTI +++ /dev/null @@ -1,22 +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 - -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 diff --git a/MULTI.md b/MULTI.md new file mode 100644 index 0000000..0c2290d --- /dev/null +++ b/MULTI.md @@ -0,0 +1,25 @@ +## 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 +``` diff --git a/Makefile.in b/Makefile.in index e824491..5ebfca2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,25 +12,32 @@ 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 + CPPFLAGS+=-I$(srcdir)/../libtomcrypt/src/headers/ + LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM) endif -OPTION_HEADERS = default_options_guard.h sysoptions.h -ifneq ($(wildcard localoptions.h),) -CPPFLAGS+=-DLOCALOPTIONS_H_EXISTS -OPTION_HEADERS += localoptions.h +ifneq ($(wildcard ./localoptions.h),) + CPPFLAGS+=-DLOCALOPTIONS_H_EXISTS +endif +ifneq ($(wildcard $(srcdir)/distrooptions.h),) + CPPFLAGS+=-DDISTROOPTIONS_H_EXISTS endif -COMMONOBJS=dbutil.o buffer.o dbhelpers.o \ +OBJ_DIR=./obj +MAN_DIR=@srcdir@/manpages + +_COMMONOBJS=dbutil.o buffer.o dbhelpers.o \ dss.o bignum.o \ signkey.o rsa.o dbrandom.o \ queue.o \ @@ -39,35 +46,42 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \ curve25519.o ed25519.o sk-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-agentfwd.o cli-readconf.o +CLIOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_CLIOBJS)) -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=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)) -KEYOBJS=dropbearkey.o +_KEYOBJS=dropbearkey.o +KEYOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_KEYOBJS)) -CONVERTOBJS=dropbearconvert.o keyimport.o signkey_ossh.o +_CONVERTOBJS=dropbearconvert.o keyimport.o signkey_ossh.o +CONVERTOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_CONVERTOBJS)) -SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o +_SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o +SCPOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_SCPOBJS)) ifeq (@DROPBEAR_FUZZ@, 1) allobjs = $(COMMONOBJS) fuzz/fuzz-common.o fuzz/fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@ - allobjs:=$(subst svr-main.o, ,$(allobjs)) - allobjs:=$(subst cli-main.o, ,$(allobjs)) + allobjs:=$(subst $(OBJ_DIR)/svr-main.o, ,$(allobjs)) + allobjs:=$(subst $(OBJ_DIR)/cli-main.o, ,$(allobjs)) - dropbearobjs=$(allobjs) svr-main.o - dbclientobjs=$(allobjs) cli-main.o + dropbearobjs=$(allobjs) $(OBJ_DIR)/svr-main.o + dbclientobjs=$(allobjs) $(OBJ_DIR)/cli-main.o dropbearkeyobjs=$(allobjs) $(KEYOBJS) dropbearconvertobjs=$(allobjs) $(CONVERTOBJS) # CXX only set when fuzzing @@ -82,17 +96,14 @@ 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@ @@ -149,15 +160,24 @@ endif all: $(TARGETS) # for simplicity assume all source depends on all headers -HEADERS=$(wildcard $(srcdir)/*.h *.h) $(OPTION_HEADERS) -%.o : %.c $(HEADERS) - $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +HEADERS=$(wildcard $(srcdir)/*.h *.h) default_options_guard.h -default_options_guard.h: default_options.h +$(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 @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 $@.tmp $@ + mv -v $@.tmp $@ + pwd + ls -l $@ strip: $(TARGETS) $(STRIP) $(addsuffix $(EXEEXT), $(TARGETS)) @@ -167,31 +187,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 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8 + $(INSTALL) -m 644 $(MAN_DIR)/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 $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi + if test -e $(MAN_DIR)/$*.1; then $(INSTALL) -m 644 $(MAN_DIR)/$*.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 $(srcdir)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8 + $(INSTALL) -m 644 $(MAN_DIR)/dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8 inst_%: % $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) $*$(EXEEXT) $(DESTDIR)$(bindir) $(INSTALL) -d $(DESTDIR)$(mandir)/man1 - if test -e $(srcdir)/$*.1; then $(INSTALL) -m 644 $(srcdir)/$*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi + if test -e $(MAN_DIR)/$*.1; then $(INSTALL) -m 644 $(MAN_DIR)/$*.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) @@ -216,7 +236,7 @@ scp: $(SCPOBJS) $(HEADERS) Makefile # multi-binary compilation. MULTIOBJS= ifeq ($(MULTI),1) - MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs))) + MULTIOBJS=$(OBJ_DIR)/dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs))) CPPFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI endif @@ -231,10 +251,10 @@ link%: -rm -f $*$(EXEEXT) -ln -s dropbearmulti$(EXEEXT) $*$(EXEEXT) -$(STATIC_LTC): $(OPTION_HEADERS) +$(STATIC_LTC): $(HEADERS) $(MAKE) -C libtomcrypt -$(STATIC_LTM): $(OPTION_HEADERS) +$(STATIC_LTM): $(HEADERS) $(MAKE) -C libtommath .PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint check @@ -253,11 +273,12 @@ clean: $(LIBTOM_CLEAN) $(FUZZ_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 + dropbearmulti$(EXEEXT) *.o *.da *.bb *.bbg *.prof \ + $(OBJ_DIR)/* distclean: clean tidy - -rm -f config.h - -rm -f Makefile + -rm -f src/config.h config.status config.log + -rm -f Makefile test/Makefile -rm -f default_options_guard.h tidy: @@ -274,7 +295,7 @@ check: lint # 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-postauth_nomaths fuzzer-cliconf FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \ @@ -288,13 +309,13 @@ fuzzstandalone: FUZZLIB=fuzz/fuzz-harness.o fuzzstandalone: fuzz/fuzz-harness.o fuzz-targets # Build all the fuzzers. Usually like -# make fuzz-targets FUZZLIB=-lFuzzer.a +# make fuzz-targets FUZZLIB=-lFuzzer.a # the library provides main(). Otherwise # make fuzzstandalone # provides a main in fuzz-harness.c fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS) -$(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS) +$(FUZZ_TARGETS): $(LIBTOM_DEPS) $(allobjs) $(FUZZ_OBJS) $(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ # fuzzers that use the custom mutator - these expect a SSH network stream @@ -311,7 +332,7 @@ 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 diff --git a/README b/README deleted file mode 100644 index bdc99dc..0000000 --- a/README +++ /dev/null @@ -1,81 +0,0 @@ -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. - -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 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 - -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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7d96427 --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +## 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 +``` + +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. diff --git a/SMALL b/SMALL deleted file mode 100644 index 02658b1..0000000 --- a/SMALL +++ /dev/null @@ -1,56 +0,0 @@ -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 localoptions.h: - - - 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. - ---- - -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. diff --git a/SMALL.md b/SMALL.md new file mode 100644 index 0000000..7fa7b9c --- /dev/null +++ b/SMALL.md @@ -0,0 +1,59 @@ +## 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. diff --git a/_internal_/Dockerfile.python.nonroot b/_internal_/Dockerfile.python.nonroot new file mode 100644 index 0000000..0e9bafb --- /dev/null +++ b/_internal_/Dockerfile.python.nonroot @@ -0,0 +1,21 @@ +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 + diff --git a/build.sh b/build.sh deleted file mode 100755 index 1e93564..0000000 --- a/build.sh +++ /dev/null @@ -1,7 +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\"" - -docker image rm dropbearbuild diff --git a/configure b/configure index e1986dd..ba94d3b 100755 --- a/configure +++ b/configure @@ -613,7 +613,6 @@ PACKAGE_STRING='' PACKAGE_BUGREPORT='' PACKAGE_URL='' -ac_unique_file="buffer.c" # Factoring default headers for most tests. ac_includes_default="\ #include @@ -659,7 +658,9 @@ CXXFLAGS CXX DROPBEAR_PLUGIN CRYPTLIB -INSTALL +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM STRIP RANLIB AR @@ -2808,10 +2809,10 @@ as_fn_append ac_header_c_list " sys/select.h sys_select_h HAVE_SYS_SELECT_H" as_fn_append ac_header_c_list " sys/socket.h sys_socket_h HAVE_SYS_SOCKET_H" # Auxiliary files required by this configure script. -ac_aux_files="config.guess config.sub" +ac_aux_files="install-sh config.guess config.sub" # Locations in which to look for auxiliary files. -ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." +ac_aux_dir_candidates="${srcdir}/src" # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. @@ -2974,7 +2975,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu - # Record which revision is being built if test -s "`which hg`" && test -d "$srcdir/.hg"; then hgrev=`hg id -i -R "$srcdir"` @@ -5118,19 +5118,29 @@ else STRIP="$ac_cv_prog_STRIP" fi -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}install", so it can be a program name with args. -set dummy ${ac_tool_prefix}install; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_INSTALL+y} + + # Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +printf %s "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test ${ac_cv_path_install+y} then : printf %s "(cached) " >&6 else $as_nop - if test -n "$INSTALL"; then - ac_cv_prog_INSTALL="$INSTALL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS @@ -5139,86 +5149,73 @@ do */) ;; *) as_dir=$as_dir/ ;; esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_prog_INSTALL="${ac_tool_prefix}install" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -INSTALL=$ac_cv_prog_INSTALL -if test -n "$INSTALL"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -printf "%s\n" "$INSTALL" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_INSTALL"; then - ac_ct_INSTALL=$INSTALL - # Extract the first word of "install", so it can be a program name with args. -set dummy install; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_ac_ct_INSTALL+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if test -n "$ac_ct_INSTALL"; then - ac_cv_prog_ac_ct_INSTALL="$ac_ct_INSTALL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_INSTALL="install" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_INSTALL=$ac_cv_prog_ac_ct_INSTALL -if test -n "$ac_ct_INSTALL"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_INSTALL" >&5 -printf "%s\n" "$ac_ct_INSTALL" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - if test "x$ac_ct_INSTALL" = x; then - INSTALL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; + # Account for fact that we put trailing slashes in our PATH walk. +case $as_dir in #(( + ./ | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; esac - INSTALL=$ac_ct_INSTALL - fi -else - INSTALL="$ac_cv_prog_INSTALL" + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + fi + if test ${ac_cv_path_install+y}; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +printf "%s\n" "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 @@ -8698,7 +8695,9 @@ fi # flags that should be set in Makefile but not for configure tests CFLAGS="$CFLAGS $LATE_CFLAGS" -ac_config_headers="$ac_config_headers config.h" + + +ac_config_headers="$ac_config_headers config.h:src/config.h.in" ac_config_files="$ac_config_files Makefile $LIBTOM_FILES test/Makefile" @@ -9275,6 +9274,7 @@ gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' +INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF @@ -9386,7 +9386,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 for ac_config_target in $ac_config_targets do case $ac_config_target in - "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:src/config.h.in" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "$LIBTOM_FILES") CONFIG_FILES="$CONFIG_FILES $LIBTOM_FILES" ;; "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; @@ -9833,6 +9833,10 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix # CONFIG_FILE # + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 @@ -9886,6 +9890,7 @@ s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ diff --git a/configure.ac b/configure.ac index a4f8f94..7a69a65 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,6 @@ 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 @@ -201,7 +200,7 @@ esac AC_CHECK_TOOL(AR, ar, :) AC_CHECK_TOOL(RANLIB, ranlib, :) AC_CHECK_TOOL(STRIP, strip, :) -AC_CHECK_TOOL(INSTALL, install, :) +AC_PROG_INSTALL dnl Can't use login() or logout() with uclibc AC_CHECK_DECL(__UCLIBC__, @@ -889,7 +888,9 @@ fi # flags that should be set in Makefile but not for configure tests CFLAGS="$CFLAGS $LATE_CFLAGS" -AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_AUX_DIR([src]) + +AC_CONFIG_HEADERS([config.h:src/config.h.in]) AC_CONFIG_FILES(Makefile $LIBTOM_FILES test/Makefile) AC_OUTPUT diff --git a/debian/changelog b/debian/changelog index 2fc5c5d..9aa79bc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +dropbear (2024.85-0.1) unstable; urgency=low + + * New upstream release. + + -- Matt Johnston Thu, 25 Apr 2024 22:51:57 +0800 + +dropbear (2024.84-0.1) unstable; urgency=low + + * New upstream release. + + -- Matt Johnston Thu, 4 Apr 2024 22:51:57 +0800 + dropbear (2022.83-0.1) unstable; urgency=low * New upstream release. diff --git a/debian/dropbear.docs b/debian/dropbear.docs index 4e43adc..ed26592 100644 --- a/debian/dropbear.docs +++ b/debian/dropbear.docs @@ -1,3 +1,3 @@ -README +README.md debian/README.runit debian/README.Debian.diet diff --git a/debian/rules b/debian/rules index c6b2e85..52e0b0c 100755 --- a/debian/rules +++ b/debian/rules @@ -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 dropbear.8 '$(DIR)'/usr/share/man/man8/ + install -m644 manpages/dropbear.8 '$(DIR)'/usr/share/man/man8/ for i in dbclient.1 dropbearkey.1 dropbearconvert.1; do \ - install -m644 $$i '$(DIR)'/usr/share/man/man1/ || exit 1; \ + install -m644 manpages/$$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 diff --git a/fuzz/fuzzer-cliconf.c b/fuzz/fuzzer-cliconf.c new file mode 100644 index 0000000..d5226aa --- /dev/null +++ b/fuzz/fuzzer-cliconf.c @@ -0,0 +1,79 @@ +/* fuzz target for cli-readconf.c */ + +#include "fuzz.h" +#include "fuzz-wrapfd.h" +#include "debug.h" +#include "runopts.h" + +static void setup_fuzzer(void) { + fuzz_common_setup(); + /* Set up commandline args */ + char* args[2] = { "dbclient", "far" }; + cli_getopts(2, args); +} + +// Needs to be outside so it doesn't get optimised away for the setjmp(). +// volatile doesn't seem to work, unsure why. +static FILE *conf_file = NULL; + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static int once = 0; + if (!once) { + setup_fuzzer(); + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + m_malloc_set_epoch(1); + + if (setjmp(fuzz.jmp) == 0) { + + /* remotehost most be set before config parsing */ + m_free(cli_opts.remotehost); + cli_opts.remotehost = m_strdup("far"); + /* optional arguments */ + if (buf_getbool(fuzz.input)) { + m_free(cli_opts.username); + cli_opts.username = m_strdup("someone"); + } + if (buf_getbool(fuzz.input)) { + m_free(cli_opts.remoteport); + cli_opts.remoteport = m_strdup("999"); + } + + buffer *conf_buf = buf_getstringbuf(fuzz.input); + if (conf_buf->len > 0) + { + conf_file = fmemopen(conf_buf->data, conf_buf->len, "r"); + read_config_file("fuzz", conf_file, &cli_opts); + fclose(conf_file); + conf_file = NULL; + } + buf_free(conf_buf); + + m_free(cli_opts.remotehost); + m_free(cli_opts.remoteport); + m_free(cli_opts.username); + + m_malloc_free_epoch(1, 0); + } else { + // Cleanup + if (conf_file) { + fclose(conf_file); + conf_file = NULL; + } + + m_free(cli_opts.remotehost); + m_free(cli_opts.remoteport); + m_free(cli_opts.username); + + m_malloc_free_epoch(1, 1); + TRACE(("dropbear_exit longjmped")) + /* dropbear_exit jumped here */ + } + + return 0; +} diff --git a/libtomcrypt/Makefile.in b/libtomcrypt/Makefile.in index d5c1f2f..ec135c5 100644 --- a/libtomcrypt/Makefile.in +++ b/libtomcrypt/Makefile.in @@ -42,7 +42,7 @@ ARFLAGS = r EXTRALIBS = ../libtommath/libtommath.a #Compilation flags -LTC_CFLAGS = -Isrc/headers/ -I$(srcdir)/src/headers/ -I../ -I$(srcdir)/../ -DLTC_SOURCE -I../libtommath/ -I$(srcdir)/../libtommath/ $(CFLAGS) $(CPPFLAGS) +LTC_CFLAGS = -Isrc/headers/ -I$(srcdir)/src/headers/ -I../ -I$(srcdir)/../src -DLTC_SOURCE -I../libtommath/ -I$(srcdir)/../libtommath/ $(CFLAGS) $(CPPFLAGS) LTC_LDFLAGS = $(LDFLAGS) $(EXTRALIBS) VERSION=1.18.1 diff --git a/libtommath/Makefile.in b/libtommath/Makefile.in index f1cb59c..3cacdd8 100644 --- a/libtommath/Makefile.in +++ b/libtommath/Makefile.in @@ -6,7 +6,7 @@ VPATH=@srcdir@ srcdir=@srcdir@ # So that libtommath can include Dropbear headers for options and m_burn() -CFLAGS += -I$(srcdir) -I../libtomcrypt/src/headers/ -I$(srcdir)/../libtomcrypt/src/headers/ -I../ -I$(srcdir)/../ +CFLAGS += -I$(srcdir) -I../libtomcrypt/src/headers/ -I$(srcdir)/../libtomcrypt/src/headers/ -I../ -I$(srcdir)/../src CFLAGS += -Wno-deprecated CFLAGS += $(CPPFLAGS) diff --git a/libtommath/bn_mp_2expt.c b/libtommath/bn_mp_2expt.c index 0ae3df1..23de0c3 100644 --- a/libtommath/bn_mp_2expt.c +++ b/libtommath/bn_mp_2expt.c @@ -12,6 +12,10 @@ mp_err mp_2expt(mp_int *a, int b) { mp_err err; + if (b < 0) { + return MP_VAL; + } + /* zero a as per default */ mp_zero(a); diff --git a/libtommath/bn_mp_grow.c b/libtommath/bn_mp_grow.c index 9e904c5..2b16826 100644 --- a/libtommath/bn_mp_grow.c +++ b/libtommath/bn_mp_grow.c @@ -9,6 +9,10 @@ mp_err mp_grow(mp_int *a, int size) int i; mp_digit *tmp; + if (size < 0) { + return MP_VAL; + } + /* if the alloc size is smaller alloc more ram */ if (a->alloc < size) { /* reallocate the array a->dp diff --git a/libtommath/bn_mp_init_size.c b/libtommath/bn_mp_init_size.c index d622687..9957383 100644 --- a/libtommath/bn_mp_init_size.c +++ b/libtommath/bn_mp_init_size.c @@ -6,6 +6,11 @@ /* init an mp_init for a given size */ mp_err mp_init_size(mp_int *a, int size) { + + if (size < 0) { + return MP_VAL; + } + size = MP_MAX(MP_MIN_PREC, size); /* alloc mem */ diff --git a/libtommath/bn_mp_mul_2d.c b/libtommath/bn_mp_mul_2d.c index 87354de..bfeaf2e 100644 --- a/libtommath/bn_mp_mul_2d.c +++ b/libtommath/bn_mp_mul_2d.c @@ -9,6 +9,10 @@ mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) mp_digit d; mp_err err; + if (b < 0) { + return MP_VAL; + } + /* copy */ if (a != c) { if ((err = mp_copy(a, c)) != MP_OKAY) { diff --git a/libtommath/bn_s_mp_mul_digs.c b/libtommath/bn_s_mp_mul_digs.c index 64509d4..3682b49 100644 --- a/libtommath/bn_s_mp_mul_digs.c +++ b/libtommath/bn_s_mp_mul_digs.c @@ -16,6 +16,10 @@ mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) mp_word r; mp_digit tmpx, *tmpt, *tmpy; + if (digs < 0) { + return MP_VAL; + } + /* can we use the fast multiplier? */ if ((digs < MP_WARRAY) && (MP_MIN(a->used, b->used) < MP_MAXFAST)) { diff --git a/libtommath/bn_s_mp_mul_digs_fast.c b/libtommath/bn_s_mp_mul_digs_fast.c index b2a287b..3c4176a 100644 --- a/libtommath/bn_s_mp_mul_digs_fast.c +++ b/libtommath/bn_s_mp_mul_digs_fast.c @@ -26,6 +26,10 @@ mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) mp_digit W[MP_WARRAY]; mp_word _W; + if (digs < 0) { + return MP_VAL; + } + /* grow the destination as required */ if (c->alloc < digs) { if ((err = mp_grow(c, digs)) != MP_OKAY) { diff --git a/libtommath/bn_s_mp_mul_high_digs.c b/libtommath/bn_s_mp_mul_high_digs.c index 2bb2a50..c9dd355 100644 --- a/libtommath/bn_s_mp_mul_high_digs.c +++ b/libtommath/bn_s_mp_mul_high_digs.c @@ -15,6 +15,10 @@ mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) mp_word r; mp_digit tmpx, *tmpt, *tmpy; + if (digs < 0) { + return MP_VAL; + } + /* can we use the fast multiplier? */ if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST) && ((a->used + b->used + 1) < MP_WARRAY) diff --git a/libtommath/bn_s_mp_mul_high_digs_fast.c b/libtommath/bn_s_mp_mul_high_digs_fast.c index a2c4fb6..4ce7f59 100644 --- a/libtommath/bn_s_mp_mul_high_digs_fast.c +++ b/libtommath/bn_s_mp_mul_high_digs_fast.c @@ -19,6 +19,10 @@ mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int mp_digit W[MP_WARRAY]; mp_word _W; + if (digs < 0) { + return MP_VAL; + } + /* grow the destination as required */ pa = a->used + b->used; if (c->alloc < pa) { diff --git a/dbclient.1 b/manpages/dbclient.1 similarity index 74% rename from dbclient.1 rename to manpages/dbclient.1 index 8a916dc..f924a59 100644 --- a/dbclient.1 +++ b/manpages/dbclient.1 @@ -1,4 +1,4 @@ -.TH dbclient 1 +.TH dbclient 1 2023-02-01 .SH NAME dbclient \- lightweight SSH client .SH SYNOPSIS @@ -22,7 +22,6 @@ dbclient \- lightweight SSH client is the client part of Dropbear SSH .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 @@ -162,21 +161,57 @@ The following options have currently been implemented: .RS .TP -.B ExitOnForwardFailure -Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be "yes" or "no". The default is "no". +.B BatchMode +Disable interactive prompts e.g. password prompts and host key confirmation. The argument must be "yes" or "no" (the default). .TP -.B UseSyslog -Send dbclient log messages to syslog in addition to stderr. -.TP -.B Port -Specify a listening port, like the \fI-p\fR argument. +.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. +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. + +.TP +.B UseSyslog +Send dbclient log messages to syslog in addition to stderr. .RE .TP .B \-s @@ -222,6 +257,52 @@ 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. diff --git a/dropbear.8 b/manpages/dropbear.8 similarity index 97% rename from dropbear.8 rename to manpages/dropbear.8 index d9bbfc2..bdb2ea0 100644 --- a/dropbear.8 +++ b/manpages/dropbear.8 @@ -58,7 +58,7 @@ Enable two-factor authentication. Both password login and public key authenticat required. Should not be used with the '-s' option. .TP .B \-j -Disable local port forwarding. +Disable local port forwarding. This includes unix stream forwards. .TP .B \-k Disable remote port forwarding. @@ -72,6 +72,10 @@ 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 +.TP .B \-i Service program mode. Use this option to run @@ -132,7 +136,7 @@ Available restrictions are: .TP .B no-port-forwarding -Don't allow port forwarding for this connection +Don't allow port forwarding for this connection, including unix streams. .TP .B no-agent-forwarding diff --git a/dropbearconvert.1 b/manpages/dropbearconvert.1 similarity index 100% rename from dropbearconvert.1 rename to manpages/dropbearconvert.1 diff --git a/dropbearkey.1 b/manpages/dropbearkey.1 similarity index 100% rename from dropbearkey.1 rename to manpages/dropbearkey.1 diff --git a/release.sh b/release.sh index 52eb5bf..e03d3d8 100755 --- a/release.sh +++ b/release.sh @@ -9,7 +9,7 @@ else TESTREL=0 fi -VERSION=$(echo '#include "default_options.h"\n#include "sysoptions.h"\necho DROPBEAR_VERSION' | cpp -DHAVE_CRYPT - | sh) +VERSION=$(echo '#include "src/default_options.h"\n#include "src/sysoptions.h"\necho DROPBEAR_VERSION' | cpp -DHAVE_CRYPT - | sh) if [ $TESTREL -eq 1 ]; then echo Making test tarball for "$VERSION" ... @@ -17,6 +17,11 @@ if [ $TESTREL -eq 1 ]; then WORKDIR=$(mktemp -d) TARSUFFIX="-testrel" else + if ! git diff -s --exit-code; then + echo "Git isn't clean" + exit 1 + fi + echo Releasing version "$VERSION" ... if ! head -n1 CHANGES | grep -q $VERSION ; then echo "CHANGES needs updating" @@ -52,16 +57,7 @@ if test -e $ARCHIVE; then exit 1 fi -if [ -d .hg ]; then - hg archive "$RELDIR" || exit 2 - # .hg_archival.txt seems to differ between hg versions, isn't good for reproducibility - rm "$RELDIR/.hg_archival.txt" -elif [ -d .git ]; then - git -c tar.umask=0022 archive --format tar -o /dev/stdout --prefix=dropbear-$VERSION/ HEAD | tar xf - -C $WORKDIR || exit 2 -else - echo "This isn't a hg or git checkout" - exit 1 -fi +git -c tar.umask=0022 archive --format tar -o /dev/stdout --prefix=dropbear-$VERSION/ HEAD | tar xf - -C $WORKDIR || exit 2 chmod -R a+rX $RELDIR @@ -80,5 +76,5 @@ echo "$ARCHIVE" if [ $TESTREL -eq 0 ]; then echo Sign it with - echo gpg2 --detach-sign -a -u F29C6773 "$ARCHIVE" + echo gpg --detach-sign -a -u F29C6773 "$ARCHIVE" fi diff --git a/agentfwd.h b/src/agentfwd.h similarity index 100% rename from agentfwd.h rename to src/agentfwd.h diff --git a/algo.h b/src/algo.h similarity index 100% rename from algo.h rename to src/algo.h diff --git a/atomicio.c b/src/atomicio.c similarity index 100% rename from atomicio.c rename to src/atomicio.c diff --git a/atomicio.h b/src/atomicio.h similarity index 100% rename from atomicio.h rename to src/atomicio.h diff --git a/auth.h b/src/auth.h similarity index 100% rename from auth.h rename to src/auth.h diff --git a/bignum.c b/src/bignum.c similarity index 100% rename from bignum.c rename to src/bignum.c diff --git a/bignum.h b/src/bignum.h similarity index 100% rename from bignum.h rename to src/bignum.h diff --git a/buffer.c b/src/buffer.c similarity index 100% rename from buffer.c rename to src/buffer.c diff --git a/buffer.h b/src/buffer.h similarity index 100% rename from buffer.h rename to src/buffer.h diff --git a/chachapoly.c b/src/chachapoly.c similarity index 100% rename from chachapoly.c rename to src/chachapoly.c diff --git a/chachapoly.h b/src/chachapoly.h similarity index 100% rename from chachapoly.h rename to src/chachapoly.h diff --git a/channel.h b/src/channel.h similarity index 94% rename from channel.h rename to src/channel.h index dd174aa..fdb6777 100644 --- a/channel.h +++ b/src/channel.h @@ -55,8 +55,9 @@ struct Channel { int errfd; /* used like writefd or readfd, depending if it's client or server. Doesn't exactly belong here, but is cleaner here */ int bidir_fd; /* a boolean indicating that writefd/readfd are the same - file descriptor (bidirectional), such as a network socket or PTY. - That is handled differently when closing FDs */ + 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 @@ -101,7 +102,7 @@ struct ChanType { void (*cleanup)(const struct Channel*); }; -/* Callback for connect_remote. errstring may be NULL if result == DROPBEAR_SUCCESS */ +/* Callback for connect_remote/connect_streamlocal. errstring may be NULL if result == DROPBEAR_SUCCESS */ void channel_connect_done(int result, int sock, void* user_data, const char* errstring); void chaninitialise(const struct ChanType *chantypes[]); diff --git a/chansession.h b/src/chansession.h similarity index 100% rename from chansession.h rename to src/chansession.h diff --git a/circbuffer.c b/src/circbuffer.c similarity index 100% rename from circbuffer.c rename to src/circbuffer.c diff --git a/circbuffer.h b/src/circbuffer.h similarity index 100% rename from circbuffer.h rename to src/circbuffer.h diff --git a/cli-agentfwd.c b/src/cli-agentfwd.c similarity index 100% rename from cli-agentfwd.c rename to src/cli-agentfwd.c diff --git a/cli-auth.c b/src/cli-auth.c similarity index 92% rename from cli-auth.c rename to src/cli-auth.c index 20d6371..fc414f3 100644 --- a/cli-auth.c +++ b/src/cli-auth.c @@ -161,6 +161,7 @@ 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")) @@ -175,6 +176,13 @@ 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. */ @@ -239,14 +247,14 @@ void recv_msg_userauth_failure() { } #endif #if DROPBEAR_CLI_INTERACT_AUTH - if (strncmp(AUTH_METHOD_INTERACT, tok, - AUTH_METHOD_INTERACT_LEN) == 0) { + if (allow_pw_auth + && strncmp(AUTH_METHOD_INTERACT, tok, AUTH_METHOD_INTERACT_LEN) == 0) { ses.authstate.authtypes |= AUTH_TYPE_INTERACT; } #endif #if DROPBEAR_CLI_PASSWORD_AUTH - if (strncmp(AUTH_METHOD_PASSWORD, tok, - AUTH_METHOD_PASSWORD_LEN) == 0) { + if (allow_pw_auth + && strncmp(AUTH_METHOD_PASSWORD, tok, AUTH_METHOD_PASSWORD_LEN) == 0) { ses.authstate.authtypes |= AUTH_TYPE_PASSWORD; } #endif @@ -297,7 +305,7 @@ int cli_auth_try() { #endif #if DROPBEAR_CLI_INTERACT_AUTH - if (!finished && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) { + if (!finished && cli_opts.password_authentication && (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 { @@ -311,7 +319,7 @@ int cli_auth_try() { #endif #if DROPBEAR_CLI_PASSWORD_AUTH - if (!finished && (ses.authstate.authtypes & AUTH_TYPE_PASSWORD)) { + 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 { @@ -347,8 +355,13 @@ char* getpass_or_cancel(const char* prompt) return password; } #endif + if (cli_opts.batch_mode) { + dropbear_close("BatchMode active, no interactive session possible."); + } - password = getpass(prompt); + if (!cli_opts.batch_mode) { + password = getpass(prompt); + } /* 0x03 is a ctrl-c character in the buffer. */ if (password == NULL || strchr(password, '\3') != NULL) { diff --git a/cli-authinteract.c b/src/cli-authinteract.c similarity index 100% rename from cli-authinteract.c rename to src/cli-authinteract.c diff --git a/cli-authpasswd.c b/src/cli-authpasswd.c similarity index 100% rename from cli-authpasswd.c rename to src/cli-authpasswd.c diff --git a/cli-authpubkey.c b/src/cli-authpubkey.c similarity index 98% rename from cli-authpubkey.c rename to src/cli-authpubkey.c index 975d3bd..5d5cea1 100644 --- a/cli-authpubkey.c +++ b/src/cli-authpubkey.c @@ -66,6 +66,10 @@ 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); diff --git a/cli-channel.c b/src/cli-channel.c similarity index 100% rename from cli-channel.c rename to src/cli-channel.c diff --git a/cli-chansession.c b/src/cli-chansession.c similarity index 100% rename from cli-chansession.c rename to src/cli-chansession.c diff --git a/cli-kex.c b/src/cli-kex.c similarity index 96% rename from cli-kex.c rename to src/cli-kex.c index 6cb75c2..6d2e4ac 100644 --- a/cli-kex.c +++ b/src/cli-kex.c @@ -209,6 +209,15 @@ 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, @@ -217,12 +226,17 @@ 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)\nDo you want to continue connecting? (y/n) ", + + fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\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); @@ -399,7 +413,7 @@ static void checkhostkey(const unsigned char* keyblob, unsigned int keybloblen) goto out; } - if (!cli_opts.always_accept_key) { + if (!cli_opts.no_hostkey_check) { /* put the new entry in the file */ fseek(hostsfile, 0, SEEK_END); /* In case it wasn't opened append */ buf_setpos(line, 0); diff --git a/cli-main.c b/src/cli-main.c similarity index 100% rename from cli-main.c rename to src/cli-main.c diff --git a/src/cli-readconf.c b/src/cli-readconf.c new file mode 100644 index 0000000..22af7c7 --- /dev/null +++ b/src/cli-readconf.c @@ -0,0 +1,176 @@ +/* + * Dropbear - a SSH2 server + * + * Copyright (c) 2023 TJ Kolev + * 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 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ + +#include "dbutil.h" +#include "runopts.h" + +#if DROPBEAR_USE_SSH_CONFIG + +#define TOKEN_CHARS " =\t\n" + +static const size_t MAX_CONF_LINE = 200; + +typedef enum { + opHost, + opHostName, + opHostPort, + opLoginUser, + opIdentityFile, +} cfg_option; + +static const struct { + const char *name; + cfg_option option; +} +config_options[] = { + /* Start of config section. */ + { "host", opHost }, + + { "hostname", opHostName }, + { "port", opHostPort }, + { "user", opLoginUser }, + { "identityfile", opIdentityFile }, +}; + +void read_config_file(char* filename, FILE* config_file, cli_runopts* options) { + char *line = NULL; + int linenum = 0; + buffer *buf = NULL; + char* cfg_key; + char* cfg_val; + char* saveptr; + int in_host_section = 0; + + DEBUG1(("Reading '%.200s'", filename)); + + buf = buf_new(MAX_CONF_LINE); + line = buf->data; + while (buf_getline(buf, config_file) == DROPBEAR_SUCCESS) { + char* commentStart = NULL; + cfg_option cfg_opt; + int found, i; + /* Update line number counter. */ + linenum++; + + /* Add nul terminator */ + if (buf->len == buf->size) { + dropbear_exit("Long line %s:%d", filename, linenum); + } + buf_setpos(buf, buf->len); + buf_putbyte(buf, '\0'); + buf_setpos(buf, 0); + + commentStart = strchr(line, '#'); + if (NULL != commentStart) { + *commentStart = '\0'; /* Drop the comments. */ + } + + cfg_key = strtok_r(line, TOKEN_CHARS, &saveptr); + if (NULL == cfg_key) { + continue; + } + + found = 0; + for (i = 0; i < ARRAY_SIZE(config_options); i++) { + if (0 == strcasecmp(cfg_key, config_options[i].name)) { + cfg_opt = config_options[i].option; + found = 1; + break; + } + } + + if (!found) { + dropbear_exit("Unsupported option %s at %s:%d", cfg_key, filename, linenum); + } + + + cfg_val = strtok_r(NULL, TOKEN_CHARS, &saveptr); + if (NULL == cfg_val) { + dropbear_exit("Missing value for %s at %s:%d", cfg_key, filename, linenum); + } + + if (in_host_section) { + switch (cfg_opt) { + case opHost: { + /* Hit the next host section. Done reading config. */ + goto outloop; + } + case opHostName: { + /* The host name is the alias given on the command line. + * Set the actual remote host specified in the config. + */ + m_free(options->remotehost); + options->remotehost = m_strdup(cfg_val); + options->remotehostfixed = 1; /* Subsequent command line parsing should leave it alone. */ + break; + } + + case opHostPort: { + m_free(options->remoteport); + options->remoteport = m_strdup(cfg_val); + break; + } + + case opLoginUser: { + m_free(options->username); + options->username = m_strdup(cfg_val); + break; + } + + case opIdentityFile: { +#if DROPBEAR_CLI_PUBKEY_AUTH + char* key_file_path; + if (strncmp(cfg_val, "~/", 2) == 0) { + key_file_path = expand_homedir_path(cfg_val); + } else if (cfg_val[0] != '/') { + char* config_dir = dirname(filename); + int path_len = strlen(config_dir) + strlen(cfg_val) + 10; + key_file_path = m_malloc(path_len); + snprintf(key_file_path, path_len, "%s/%s", config_dir, cfg_val); + } else { + key_file_path = m_strdup(cfg_val); + } + loadidentityfile(key_file_path, 1); + m_free(key_file_path); +#else + dropbear_exit("identityfile isn't supported in %s", filename); +#endif + break; + } + } + } + else + { + if (opHost != cfg_opt || 0 != strcmp(cfg_val, options->remotehost)) { + /* Not our host section. */ + continue; + } + in_host_section = 1; + } + } +outloop: + buf_free(buf); +} + +#endif /* DROPBEAR_USE_SSH_CONFIG */ diff --git a/cli-runopts.c b/src/cli-runopts.c similarity index 75% rename from cli-runopts.c rename to src/cli-runopts.c index 38a73f7..680fa4d 100644 --- a/cli-runopts.c +++ b/src/cli-runopts.c @@ -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,9 +37,6 @@ 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 @@ -48,6 +45,10 @@ 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" @@ -86,7 +87,7 @@ static void printhelp() { "-z disable QoS\n" #if DROPBEAR_CLI_NETCAT "-B Netcat-alike forwarding\n" -#endif +#endif #if DROPBEAR_CLI_PROXYCMD "-J Use program pipe rather than TCP connection\n" #endif @@ -104,12 +105,12 @@ static void printhelp() { DROPBEAR_DEFAULT_CLI_AUTHKEY, #endif DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT); - + } void cli_getopts(int argc, char ** argv) { unsigned int i, j; - char ** next = NULL; + const char ** next = NULL; enum { OPT_EXTENDED_OPTIONS, #if DROPBEAR_CLI_PUBKEY_AUTH @@ -129,16 +130,18 @@ void cli_getopts(int argc, char ** argv) { } opt; unsigned int cmdlen; - char* recv_window_arg = NULL; - char* keepalive_arg = NULL; - char* idle_timeout_arg = NULL; - char *host_arg = NULL; - char *bind_arg = NULL; + 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 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; @@ -147,6 +150,7 @@ void cli_getopts(int argc, char ** argv) { 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 @@ -156,6 +160,8 @@ void cli_getopts(int argc, char ** argv) { 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; @@ -171,8 +177,10 @@ 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 @@ -210,9 +218,12 @@ 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': /* always accept the remote hostkey */ + case 'y': + /* once is always accept the remote hostkey, + * the same as stricthostkeychecking=accept-new */ if (cli_opts.always_accept_key) { - /* twice means no checking at all */ + /* twice means no checking at all + * (stricthostkeychecking=no) */ cli_opts.no_hostkey_check = 1; } cli_opts.always_accept_key = 1; @@ -221,7 +232,7 @@ void cli_getopts(int argc, char ** argv) { cli_opts.quiet = 1; break; case 'p': /* remoteport */ - next = (char**)&cli_opts.remoteport; + next = &remoteport_arg; break; #if DROPBEAR_CLI_PUBKEY_AUTH case 'i': /* an identityfile */ @@ -266,11 +277,11 @@ void cli_getopts(int argc, char ** argv) { #endif #if DROPBEAR_CLI_PROXYCMD case 'J': - next = &cli_opts.proxycmd; + next = &proxycmd_arg; break; #endif case 'l': - next = &cli_opts.username; + next = &username_arg; break; case 'h': printhelp(); @@ -283,7 +294,7 @@ void cli_getopts(int argc, char ** argv) { next = &recv_window_arg; break; case 'K': - next = &keepalive_arg; + next = &cli_opts.keepalive_arg; break; case 'I': next = &idle_timeout_arg; @@ -324,7 +335,7 @@ void cli_getopts(int argc, char ** argv) { exit(EXIT_SUCCESS); break; case 'b': - next = &bind_arg; + next = &cli_opts.bind_arg; break; case 'z': opts.disable_ip_tos = 1; @@ -393,15 +404,34 @@ void cli_getopts(int argc, char ** argv) { parse_ciphers_macs(); #endif - /* 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); + 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 (i < (unsigned int)argc) { /* Build the command to send */ cmdlen = 0; @@ -424,18 +454,14 @@ void cli_getopts(int argc, char ** argv) { /* And now a few sanity checks and setup */ #if DROPBEAR_CLI_PROXYCMD - if (cli_opts.proxycmd) { + if (proxycmd_arg) { /* To match the common path of m_freeing it */ - cli_opts.proxycmd = m_strdup(cli_opts.proxycmd); + cli_opts.proxycmd = m_strdup(proxycmd_arg); } #endif - if (cli_opts.remoteport == NULL) { - cli_opts.remoteport = "22"; - } - - if (bind_arg) { - if (split_address_port(bind_arg, + 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"); @@ -460,10 +486,10 @@ void cli_getopts(int argc, char ** argv) { if (recv_window_arg) { parse_recv_window(recv_window_arg); } - if (keepalive_arg) { + if (cli_opts.keepalive_arg) { unsigned int val; - if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) { - dropbear_exit("Bad keepalive '%s'", keepalive_arg); + if (m_str_to_uint(cli_opts.keepalive_arg, &val) == DROPBEAR_FAILURE) { + dropbear_exit("Bad keepalive '%s'", cli_opts.keepalive_arg); } opts.keepalive_secs = val; } @@ -495,32 +521,32 @@ void cli_getopts(int argc, char ** argv) { -i argument for multihop, so handle it later. */ #if (DROPBEAR_CLI_PUBKEY_AUTH) { - char *expand_path = expand_homedir_path(DROPBEAR_DEFAULT_CLI_AUTHKEY); - loadidentityfile(expand_path, 0); - m_free(expand_path); + loadidentityfile(DROPBEAR_DEFAULT_CLI_AUTHKEY, 0); } #endif } #if DROPBEAR_CLI_PUBKEY_AUTH -static void loadidentityfile(const char* filename, int warnfail) { +void loadidentityfile(const char* filename, int warnfail) { sign_key *key; enum signkey_type keytype; - TRACE(("loadidentityfile %s", filename)) + char *id_key_path = expand_homedir_path(filename); + TRACE(("loadidentityfile %s", id_key_path)) key = new_sign_key(); keytype = DROPBEAR_SIGNKEY_ANY; - if ( readhostkey(filename, key, &keytype) != DROPBEAR_SUCCESS ) { + if ( readhostkey(id_key_path, key, &keytype) != DROPBEAR_SUCCESS ) { if (warnfail) { - dropbear_log(LOG_WARNING, "Failed loading keyfile '%s'\n", filename); + dropbear_log(LOG_WARNING, "Failed loading keyfile '%s'\n", id_key_path); } sign_key_free(key); + m_free(id_key_path); } else { key->type = keytype; key->source = SIGNKEY_SOURCE_RAW_FILE; - key->filename = m_strdup(filename); + key->filename = id_key_path; list_append(cli_opts.privkeys, key); } } @@ -528,56 +554,65 @@ static void loadidentityfile(const char* filename, int warnfail) { #if DROPBEAR_CLI_MULTIHOP -static char* -multihop_passthrough_args() { - char *ret; +/* 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 m_list_elem *iter; - /* Fill out -i, -y, -W options that make sense for all - * the intermediate processes */ - len = 30; /* space for "-q -y -y -W \0" */ +#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); + } #if DROPBEAR_CLI_PUBKEY_AUTH for (iter = cli_opts.privkeys->first; iter; iter = iter->next) { sign_key * key = (sign_key*)iter->item; - len += 3 + strlen(key->filename); - } -#endif /* DROPBEAR_CLI_PUBKEY_AUTH */ - if (cli_opts.proxycmd) { - /* "-J 'cmd'" */ - len += 6 + strlen(cli_opts.proxycmd); + len += 4 + strlen(key->filename); } +#endif - ret = m_malloc(len); + args = m_malloc(len); total = 0; + /* Create new argument string */ + if (cli_opts.quiet) { - total += m_snprintf(ret+total, len-total, "-q "); + total += m_snprintf(args+total, len-total, "-q "); } if (cli_opts.no_hostkey_check) { - total += m_snprintf(ret+total, len-total, "-y -y "); + total += m_snprintf(args+total, len-total, "-y -y "); } else if (cli_opts.always_accept_key) { - total += m_snprintf(ret+total, len-total, "-y "); + 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(ret+total, len-total, "-J '%s' ", 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(ret+total, len-total, "-W %u ", opts.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(ret+total, len-total, "-i %s ", key->filename); + total += m_snprintf(args+total, len-total, "-i %s ", key->filename); } #endif /* DROPBEAR_CLI_PUBKEY_AUTH */ - return ret; + return args; } /* Sets up 'onion-forwarding' connections. This will spawn @@ -606,8 +641,8 @@ 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); @@ -634,9 +669,6 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0) /* Set up the proxycmd */ unsigned int cmd_len = 0; char *passthrough_args = multihop_passthrough_args(); - if (cli_opts.remoteport == NULL) { - cli_opts.remoteport = "22"; - } cmd_len = strlen(argv0) + strlen(remainder) + strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport) + strlen(passthrough_args) @@ -655,51 +687,53 @@ 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); - cli_opts.remotehost = strchr(userhostarg, '@'); - if (cli_opts.remotehost == NULL) { + remotehost = strchr(userhostarg, '@'); + if (remotehost == NULL) { /* no username portion, the cli-auth.c code can figure the * local user's name */ - cli_opts.remotehost = userhostarg; + remotehost = userhostarg; } else { - cli_opts.remotehost[0] = '\0'; /* Split the user/host */ - cli_opts.remotehost++; - cli_opts.username = userhostarg; + remotehost[0] = '\0'; /* Split the user/host */ + remotehost++; + cli_opts.username = m_strdup(userhostarg); } - if (cli_opts.username == NULL) { - cli_opts.username = m_strdup(cli_opts.own_user); - } - - port = strchr(cli_opts.remotehost, '^'); + port = strchr(remotehost, '^'); if (!port) { /* legacy separator */ - port = strchr(cli_opts.remotehost, '/'); + port = strchr(remotehost, '/'); } if (port) { *port = '\0'; - cli_opts.remoteport = port+1; + cli_opts.remoteport = m_strdup(port+1); } - if (cli_opts.remotehost[0] == '\0') { - dropbear_exit("Bad hostname"); + if (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")) @@ -707,25 +741,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); } @@ -733,7 +767,7 @@ fail: static void fill_own_user() { uid_t uid; - struct passwd *pw = NULL; + struct passwd *pw = NULL; uid = getuid(); @@ -763,7 +797,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; @@ -823,7 +857,7 @@ static void addforward(const char* origstr, m_list *fwdlist) { TRACE(("listenport > 65535")) goto badport; } - + if (newfwd->connectport > 65535) { TRACE(("connectport > 65535")) goto badport; @@ -889,18 +923,50 @@ 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 - "\tDisableTrivialAuth\n" +#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); @@ -908,6 +974,75 @@ 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); @@ -915,15 +1050,24 @@ static void add_extendedopt(const char* origstr) { } #endif - if (match_extendedopt(&optstr, "Port") == DROPBEAR_SUCCESS) { - cli_opts.remoteport = optstr; - return; - } - - if (match_extendedopt(&optstr, "DisableTrivialAuth") == DROPBEAR_SUCCESS) { - cli_opts.disable_trivial_auth = parse_flag_value(optstr); - return; - } - dropbear_log(LOG_WARNING, "Ignoring unknown configuration option '%s'", origstr); } + +#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 diff --git a/cli-session.c b/src/cli-session.c similarity index 98% rename from cli-session.c rename to src/cli-session.c index 5981b24..d261c8f 100644 --- a/cli-session.c +++ b/src/cli-session.c @@ -46,6 +46,7 @@ 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 */ @@ -117,6 +118,7 @@ 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); @@ -487,3 +489,12 @@ void cli_dropbear_log(int priority, const char* format, va_list param) { 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; + } + } +} + diff --git a/cli-tcpfwd.c b/src/cli-tcpfwd.c similarity index 100% rename from cli-tcpfwd.c rename to src/cli-tcpfwd.c diff --git a/common-algo.c b/src/common-algo.c similarity index 99% rename from common-algo.c rename to src/common-algo.c index 378f0ca..f9d46eb 100644 --- a/common-algo.c +++ b/src/common-algo.c @@ -307,6 +307,12 @@ 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} }; diff --git a/common-channel.c b/src/common-channel.c similarity index 100% rename from common-channel.c rename to src/common-channel.c diff --git a/common-chansession.c b/src/common-chansession.c similarity index 100% rename from common-chansession.c rename to src/common-chansession.c diff --git a/common-kex.c b/src/common-kex.c similarity index 98% rename from common-kex.c rename to src/common-kex.c index ac88442..8e33b12 100644 --- a/common-kex.c +++ b/src/common-kex.c @@ -183,6 +183,10 @@ void send_msg_newkeys() { gen_new_keys(); switch_keys(); + if (ses.kexstate.strict_kex) { + ses.transseq = 0; + } + TRACE(("leave send_msg_newkeys")) } @@ -193,7 +197,11 @@ void recv_msg_newkeys() { ses.kexstate.recvnewkeys = 1; switch_keys(); - + + if (ses.kexstate.strict_kex) { + ses.recvseq = 0; + } + TRACE(("leave recv_msg_newkeys")) } @@ -550,6 +558,10 @@ 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")) } @@ -859,6 +871,18 @@ 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) { diff --git a/common-runopts.c b/src/common-runopts.c similarity index 100% rename from common-runopts.c rename to src/common-runopts.c diff --git a/common-session.c b/src/common-session.c similarity index 97% rename from common-session.c rename to src/common-session.c index 6991f57..a045adf 100644 --- a/common-session.c +++ b/src/common-session.c @@ -71,10 +71,13 @@ void common_session_init(int sock_in, int sock_out) { #if !DROPBEAR_SVR_MULTIUSER /* A sanity check to prevent an accidental configuration option leaving multiuser systems exposed */ - errno = 0; - getuid(); - if (errno != ENOSYS) { - dropbear_exit("Non-multiuser Dropbear requires a non-multiuser kernel"); + { + int ret; + errno = 0; + ret = getgroups(0, NULL); + if (!(ret == -1 && errno == ENOSYS)) { + dropbear_exit("Non-multiuser Dropbear requires a non-multiuser kernel"); + } } #endif @@ -650,10 +653,16 @@ void fill_passwd(const char* username) { { char *passwd_crypt = pw->pw_passwd; #ifdef HAVE_SHADOW_H - /* get the shadow password if possible */ - struct spwd *spasswd = getspnam(ses.authstate.pw_name); - if (spasswd && spasswd->sp_pwdp) { - passwd_crypt = spasswd->sp_pwdp; + /* "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 = "!!"; + } } #endif if (!passwd_crypt) { diff --git a/compat.c b/src/compat.c similarity index 100% rename from compat.c rename to src/compat.c diff --git a/compat.h b/src/compat.h similarity index 100% rename from compat.h rename to src/compat.h diff --git a/config.guess b/src/config.guess similarity index 97% rename from config.guess rename to src/config.guess index 980b020..cdfc439 100644 --- a/config.guess +++ b/src/config.guess @@ -1,10 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2022 Free Software Foundation, Inc. +# Copyright 1992-2023 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2022-09-17' +timestamp='2023-08-22' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -47,7 +47,7 @@ me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] -Output the configuration name of the system \`$me' is run on. +Output the configuration name of the system '$me' is run on. Options: -h, --help print this help, then exit @@ -60,13 +60,13 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2022 Free Software Foundation, Inc. +Copyright 1992-2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" -Try \`$me --help' for more information." +Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do @@ -102,8 +102,8 @@ GUESS= # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. +# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still +# use 'HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. @@ -155,6 +155,9 @@ Linux|GNU|GNU/*) set_cc_for_build cat <<-EOF > "$dummy.c" + #if defined(__ANDROID__) + LIBC=android + #else #include #if defined(__UCLIBC__) LIBC=uclibc @@ -169,6 +172,7 @@ Linux|GNU|GNU/*) LIBC=musl #endif #endif + #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" @@ -459,7 +463,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in UNAME_RELEASE=`uname -v` ;; esac - # Japanese Language versions have a version number like `4.1.3-JL'. + # Japanese Language versions have a version number like '4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; @@ -904,7 +908,7 @@ EOF fi ;; *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` + UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; @@ -976,7 +980,27 @@ EOF GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + set_cc_for_build + CPU=$UNAME_MACHINE + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + ABI=64 + sed 's/^ //' << EOF > "$dummy.c" + #ifdef __ARM_EABI__ + #ifdef __ARM_PCS_VFP + ABI=eabihf + #else + ABI=eabi + #endif + #endif +EOF + cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` + eval "$cc_set_abi" + case $ABI in + eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;; + esac + fi + GUESS=$CPU-unknown-linux-$LIBCABI ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be @@ -1042,6 +1066,15 @@ EOF k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; + kvx:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + kvx:cos:*:*) + GUESS=$UNAME_MACHINE-unknown-cos + ;; + kvx:mbr:*:*) + GUESS=$UNAME_MACHINE-unknown-mbr + ;; loongarch32:Linux:*:* | loongarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; @@ -1197,7 +1230,7 @@ EOF GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility + # If we were able to find 'uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; @@ -1338,7 +1371,7 @@ EOF GUESS=ns32k-sni-sysv fi ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; diff --git a/config.h.in b/src/config.h.in similarity index 99% rename from config.h.in rename to src/config.h.in index b70731c..f42d3e4 100644 --- a/config.h.in +++ b/src/config.h.in @@ -1,4 +1,4 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ /* Using AIX */ #undef AIX diff --git a/config.sub b/src/config.sub similarity index 90% rename from config.sub rename to src/config.sub index baf1512..defe52c 100644 --- a/config.sub +++ b/src/config.sub @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2022 Free Software Foundation, Inc. +# Copyright 1992-2023 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2022-09-17' +timestamp='2023-09-19' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -76,13 +76,13 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2022 Free Software Foundation, Inc. +Copyright 1992-2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" -Try \`$me --help' for more information." +Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do @@ -130,7 +130,7 @@ IFS=$saved_IFS # Separate into logical components for further validation case $1 in *-*-*-*-*) - echo Invalid configuration \`"$1"\': more than four components >&2 + echo "Invalid configuration '$1': more than four components" >&2 exit 1 ;; *-*-*-*) @@ -145,7 +145,8 @@ case $1 in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ - | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*) + | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \ + | windows-* ) basic_machine=$field1 basic_os=$maybe_os ;; @@ -943,7 +944,7 @@ $basic_machine EOF IFS=$saved_IFS ;; - # We use `pc' rather than `unknown' + # We use 'pc' rather than 'unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) @@ -1075,7 +1076,7 @@ case $cpu-$vendor in pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) cpu=i586 ;; - pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*) cpu=i686 ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) @@ -1180,7 +1181,7 @@ case $cpu-$vendor in case $cpu in 1750a | 580 \ | a29k \ - | aarch64 | aarch64_be \ + | aarch64 | aarch64_be | aarch64c | arm64ec \ | abacus \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ @@ -1199,12 +1200,14 @@ case $cpu-$vendor in | d10v | d30v | dlx | dsp16xx \ | e2k | elxsi | epiphany \ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | javascript \ | h8300 | h8500 \ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i*86 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ + | kvx \ | le32 | le64 \ | lm32 \ | loongarch32 | loongarch64 \ @@ -1213,31 +1216,7 @@ case $cpu-$vendor in | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ | m88110 | m88k | maxq | mb | mcore | mep | metag \ | microblaze | microblazeel \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64eb | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r3 | mipsisa32r3el \ - | mipsisa32r5 | mipsisa32r5el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r3 | mipsisa64r3el \ - | mipsisa64r5 | mipsisa64r5el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ + | mips* \ | mmix \ | mn10200 | mn10300 \ | moxie \ @@ -1285,7 +1264,7 @@ case $cpu-$vendor in ;; *) - echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2 exit 1 ;; esac @@ -1306,11 +1285,12 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if test x$basic_os != x +if test x"$basic_os" != x then # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. +obj= case $basic_os in gnu/linux*) kernel=linux @@ -1510,10 +1490,16 @@ case $os in os=eabi ;; *) - os=elf + os= + obj=elf ;; esac ;; + aout* | coff* | elf* | pe*) + # These are machine code file formats, not OSes + obj=$os + os= + ;; *) # No normalization, but not necessarily accepted, that comes below. ;; @@ -1532,12 +1518,15 @@ else # system, and we'll never get to this point. kernel= +obj= case $cpu-$vendor in score-*) - os=elf + os= + obj=elf ;; spu-*) - os=elf + os= + obj=elf ;; *-acorn) os=riscix1.2 @@ -1547,28 +1536,35 @@ case $cpu-$vendor in os=gnu ;; arm*-semi) - os=aout + os= + obj=aout ;; c4x-* | tic4x-*) - os=coff + os= + obj=coff ;; c8051-*) - os=elf + os= + obj=elf ;; clipper-intergraph) os=clix ;; hexagon-*) - os=elf + os= + obj=elf ;; tic54x-*) - os=coff + os= + obj=coff ;; tic55x-*) - os=coff + os= + obj=coff ;; tic6x-*) - os=coff + os= + obj=coff ;; # This must come before the *-dec entry. pdp10-*) @@ -1590,19 +1586,24 @@ case $cpu-$vendor in os=sunos3 ;; m68*-cisco) - os=aout + os= + obj=aout ;; mep-*) - os=elf + os= + obj=elf ;; mips*-cisco) - os=elf + os= + obj=elf ;; mips*-*) - os=elf + os= + obj=elf ;; or32-*) - os=coff + os= + obj=coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=sysv3 @@ -1611,7 +1612,8 @@ case $cpu-$vendor in os=sunos4.1.1 ;; pru-*) - os=elf + os= + obj=elf ;; *-be) os=beos @@ -1692,10 +1694,12 @@ case $cpu-$vendor in os=uxpv ;; *-rom68k) - os=coff + os= + obj=coff ;; *-*bug) - os=coff + os= + obj=coff ;; *-apple) os=macos @@ -1713,7 +1717,8 @@ esac fi -# Now, validate our (potentially fixed-up) OS. +# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ). + case $os in # Sometimes we do "kernel-libc", so those need to count as OSes. musl* | newlib* | relibc* | uclibc*) @@ -1724,6 +1729,9 @@ case $os in # VxWorks passes extra cpu info in the 4th filed. simlinux | simwindows | spe) ;; + # See `case $cpu-$os` validation below + ghcjs) + ;; # Now accept the basic system types. # The portable systems comes first. # Each alternative MUST end in a * to match a version number. @@ -1732,7 +1740,7 @@ case $os in | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ | hiux* | abug | nacl* | netware* | windows* \ - | os9* | macos* | osx* | ios* \ + | os9* | macos* | osx* | ios* | tvos* | watchos* \ | mpw* | magic* | mmixware* | mon960* | lnews* \ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ | aos* | aros* | cloudabi* | sortix* | twizzler* \ @@ -1741,11 +1749,11 @@ case $os in | mirbsd* | netbsd* | dicos* | openedition* | ose* \ | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ - | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ - | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | bosx* | nextstep* | cxux* | oabi* \ + | ptx* | ecoff* | winnt* | domain* | vsta* \ | udi* | lites* | ieee* | go32* | aux* | hcos* \ | chorusrdb* | cegcc* | glidix* | serenity* \ - | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | cygwin* | msys* | moss* | proelf* | rtems* \ | midipix* | mingw32* | mingw64* | mint* \ | uxpv* | beos* | mpeix* | udk* | moxiebox* \ | interix* | uwin* | mks* | rhapsody* | darwin* \ @@ -1758,7 +1766,7 @@ case $os in | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ - | fiwix* | mlibc* ) + | fiwix* | mlibc* | cos* | mbr* ) ;; # This one is extra strict with allowed versions sco3.2v2 | sco3.2v[4-9]* | sco5v6*) @@ -1766,54 +1774,99 @@ case $os in ;; none) ;; - kernel* ) + kernel* | msvc* ) # Restricted further below ;; + '') + if test x"$obj" = x + then + echo "Invalid configuration '$1': Blank OS only allowed with explicit machine code file format" 1>&2 + fi + ;; *) - echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 + echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2 + exit 1 + ;; +esac + +case $obj in + aout* | coff* | elf* | pe*) + ;; + '') + # empty is fine + ;; + *) + echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2 + exit 1 + ;; +esac + +# Here we handle the constraint that a (synthetic) cpu and os are +# valid only in combination with each other and nowhere else. +case $cpu-$os in + # The "javascript-unknown-ghcjs" triple is used by GHC; we + # accept it here in order to tolerate that, but reject any + # variations. + javascript-ghcjs) + ;; + javascript-* | *-ghcjs) + echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. -case $kernel-$os in - linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ - | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) +case $kernel-$os-$obj in + linux-gnu*- | linux-dietlibc*- | linux-android*- | linux-newlib*- \ + | linux-musl*- | linux-relibc*- | linux-uclibc*- | linux-mlibc*- ) ;; - uclinux-uclibc* ) + uclinux-uclibc*- ) ;; - managarm-mlibc* | managarm-kernel* ) + managarm-mlibc*- | managarm-kernel*- ) ;; - -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) + windows*-msvc*-) + ;; + -dietlibc*- | -newlib*- | -musl*- | -relibc*- | -uclibc*- | -mlibc*- ) # These are just libc implementations, not actual OSes, and thus # require a kernel. - echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 exit 1 ;; - -kernel* ) - echo "Invalid configuration \`$1': \`$os' needs explicit kernel." 1>&2 + -kernel*- ) + echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 exit 1 ;; - *-kernel* ) - echo "Invalid configuration \`$1': \`$kernel' does not support \`$os'." 1>&2 + *-kernel*- ) + echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 exit 1 ;; - kfreebsd*-gnu* | kopensolaris*-gnu*) + *-msvc*- ) + echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2 + exit 1 ;; - vxworks-simlinux | vxworks-simwindows | vxworks-spe) + kfreebsd*-gnu*- | kopensolaris*-gnu*-) ;; - nto-qnx*) + vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-) ;; - os2-emx) + nto-qnx*-) ;; - *-eabi* | *-gnueabi*) + os2-emx-) ;; - -*) + *-eabi*- | *-gnueabi*-) + ;; + none--*) + # None (no kernel, i.e. freestanding / bare metal), + # can be paired with an machine code file format + ;; + -*-) # Blank kernel with real OS is always fine. ;; - *-*) - echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + --*) + # Blank kernel and OS with real machine code file format is always fine. + ;; + *-*-*) + echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 exit 1 ;; esac @@ -1896,7 +1949,7 @@ case $vendor in ;; esac -echo "$cpu-$vendor-${kernel:+$kernel-}$os" +echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}" exit # Local variables: diff --git a/crypto_desc.c b/src/crypto_desc.c similarity index 100% rename from crypto_desc.c rename to src/crypto_desc.c diff --git a/crypto_desc.h b/src/crypto_desc.h similarity index 100% rename from crypto_desc.h rename to src/crypto_desc.h diff --git a/curve25519.c b/src/curve25519.c similarity index 100% rename from curve25519.c rename to src/curve25519.c diff --git a/curve25519.h b/src/curve25519.h similarity index 100% rename from curve25519.h rename to src/curve25519.h diff --git a/dbhelpers.c b/src/dbhelpers.c similarity index 100% rename from dbhelpers.c rename to src/dbhelpers.c diff --git a/dbhelpers.h b/src/dbhelpers.h similarity index 100% rename from dbhelpers.h rename to src/dbhelpers.h diff --git a/dbmalloc.c b/src/dbmalloc.c similarity index 100% rename from dbmalloc.c rename to src/dbmalloc.c diff --git a/dbmalloc.h b/src/dbmalloc.h similarity index 100% rename from dbmalloc.h rename to src/dbmalloc.h diff --git a/dbmulti.c b/src/dbmulti.c similarity index 95% rename from dbmulti.c rename to src/dbmulti.c index 28ee959..919ce3d 100644 --- a/dbmulti.c +++ b/src/dbmulti.c @@ -41,7 +41,8 @@ static int runprog(const char *multipath, } #endif #ifdef DBMULTI_dropbearkey - if (strcmp(progname, "dropbearkey") == 0) { + if (strcmp(progname, "dropbearkey") == 0 + || strcmp(progname, "ssh-keygen") == 0) { return dropbearkey_main(argc, argv); } #endif @@ -88,7 +89,7 @@ int main(int argc, char ** argv) { "'dbclient' or 'ssh' - the Dropbear client\n" #endif #ifdef DBMULTI_dropbearkey - "'dropbearkey' - the key generator\n" + "'dropbearkey' or 'ssh-keygen' - the key generator\n" #endif #ifdef DBMULTI_dropbearconvert "'dropbearconvert' - the key converter\n" diff --git a/dbrandom.c b/src/dbrandom.c similarity index 98% rename from dbrandom.c rename to src/dbrandom.c index 41aaa48..4e0a481 100644 --- a/dbrandom.c +++ b/src/dbrandom.c @@ -268,9 +268,6 @@ 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); diff --git a/dbrandom.h b/src/dbrandom.h similarity index 100% rename from dbrandom.h rename to src/dbrandom.h diff --git a/dbutil.c b/src/dbutil.c similarity index 98% rename from dbutil.c rename to src/dbutil.c index e8831c5..2bc1a0b 100644 --- a/dbutil.c +++ b/src/dbutil.c @@ -423,7 +423,7 @@ void printhex(const char * label, const unsigned char * buf, int len) { } else { fprintf(stderr, " "); } - // separator between pairs + /* separator between pairs */ if (i % 2 ==1) { fprintf(stderr, " "); } @@ -573,9 +573,10 @@ 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 @@ -583,17 +584,20 @@ 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, O_NONBLOCK) < 0) { + if (fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1) { 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")) } diff --git a/dbutil.h b/src/dbutil.h similarity index 98% rename from dbutil.h rename to src/dbutil.h index df2f89b..70e16c5 100644 --- a/dbutil.h +++ b/src/dbutil.h @@ -111,5 +111,7 @@ 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_ */ diff --git a/debug.h b/src/debug.h similarity index 100% rename from debug.h rename to src/debug.h diff --git a/default_options.h b/src/default_options.h similarity index 95% rename from default_options.h rename to src/default_options.h index 5132775..6e970bb 100644 --- a/default_options.h +++ b/src/default_options.h @@ -3,12 +3,14 @@ /* > > > 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 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 */ @@ -48,9 +50,10 @@ IMPORTANT: Some options will require "make clean" after changes */ /* Include verbose debug output, enabled with -v at runtime (repeat to increase). * define which level of debug output you compile in - * TRACE1 - TRACE3 = approx 4 Kb (connection, remote identity, algos, auth type info) - * TRACE4 = approx 17 Kb (detailed before connection) - * TRACE5 = approx 8 Kb (detailed after connection) */ + * 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) */ #define DEBUG_TRACE 0 /* Set this if you want to use the DROPBEAR_SMALL_CODE option. This can save @@ -70,6 +73,7 @@ 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 @@ -166,7 +170,7 @@ IMPORTANT: Some options will require "make clean" after changes */ /* 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. */ @@ -182,7 +186,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 @@ -212,7 +216,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 @@ -220,6 +224,7 @@ 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 */ @@ -237,7 +242,7 @@ group1 in Dropbear server too */ * You must define DROPBEAR_SVR_PUBKEY_AUTH in order to use plugins. */ #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,6 +260,10 @@ group1 in Dropbear server too */ */ #define DROPBEAR_DEFAULT_CLI_AUTHKEY "~/.ssh/id_dropbear" +/* Per client configuration file +*/ +#define DROPBEAR_USE_SSH_CONFIG 0 + /* Allow specifying the password for dbclient via the DROPBEAR_PASSWORD * environment variable. */ #define DROPBEAR_USE_PASSWORD_ENV 1 @@ -267,8 +276,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 */ @@ -280,7 +289,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 @@ -290,7 +299,7 @@ group1 in Dropbear server too */ /* 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 + of password brute forcing. Note that there is a risk of denial of service by setting this */ #define UNAUTH_CLOSE_DELAY 0 @@ -317,8 +326,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 diff --git a/dh_groups.c b/src/dh_groups.c similarity index 100% rename from dh_groups.c rename to src/dh_groups.c diff --git a/dh_groups.h b/src/dh_groups.h similarity index 100% rename from dh_groups.h rename to src/dh_groups.h diff --git a/dropbear_lint.sh b/src/dropbear_lint.sh similarity index 100% rename from dropbear_lint.sh rename to src/dropbear_lint.sh diff --git a/dropbearconvert.c b/src/dropbearconvert.c similarity index 100% rename from dropbearconvert.c rename to src/dropbearconvert.c diff --git a/dropbearkey.c b/src/dropbearkey.c similarity index 70% rename from dropbearkey.c rename to src/dropbearkey.c index bd9c6af..99e631f 100644 --- a/dropbearkey.c +++ b/src/dropbearkey.c @@ -61,11 +61,26 @@ #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); -static int printpubfile(const char* filename); +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); /* Print a help message */ static void printhelp(char * progname) { @@ -107,6 +122,7 @@ 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 .\n" + "-C Specify the key comment (email).\n" #if DEBUG_TRACE "-v verbose\n" #endif @@ -157,8 +173,10 @@ int main(int argc, char ** argv) { char ** next = NULL; char * filename = NULL; enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE; - char * typetext = NULL; + char * typetext = DEFAULT_KEY_TYPE_NAME; char * sizetext = NULL; + char * passphrase = NULL; + char * comment = NULL; unsigned int bits = 0, genbits; int printpub = 0; @@ -187,6 +205,9 @@ int main(int argc, char ** argv) { case 's': next = &sizetext; break; + case 'C': + next = &comment; + break; case 'y': printpub = 1; break; @@ -194,11 +215,16 @@ int main(int argc, char ** argv) { printhelp(argv[0]); exit(EXIT_SUCCESS); break; -#if DEBUG_TRACE case 'v': +#if DEBUG_TRACE debug_trace = DROPBEAR_VERBOSE_LEVEL; - 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]); @@ -215,17 +241,10 @@ int main(int argc, char ** argv) { } if (printpub) { - int ret = printpubfile(filename); + int ret = printpubfile(filename, NULL, 0); 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) { @@ -266,6 +285,11 @@ 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) @@ -273,13 +297,13 @@ int main(int argc, char ** argv) { dropbear_exit("Failed to generate key.\n"); } - printpubfile(filename); + printpubfile(filename, comment, 1); return EXIT_SUCCESS; } #endif -static int printpubfile(const char* filename) { +static int printpubfile(const char* filename, const char* comment, int create_pub_file) { buffer *buf = NULL; sign_key *key = NULL; @@ -305,7 +329,7 @@ static int printpubfile(const char* filename) { goto out; } - printpubkey(key, keytype); + printpubkey(key, keytype, comment, create_pub_file, filename); err = DROPBEAR_SUCCESS; @@ -319,7 +343,7 @@ out: return err; } -static void printpubkey(sign_key * key, int keytype) { +static void printpubkey(sign_key * key, int keytype, const char * comment, int create_pub_file, const char * filename) { buffer * buf = NULL; unsigned char base64key[MAX_PUBKEY_SIZE*2]; @@ -331,6 +355,31 @@ static void printpubkey(sign_key * key, int keytype) { 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); @@ -347,21 +396,45 @@ static void printpubkey(sign_key * key, int keytype) { typestring = signkey_name_from_type(keytype, NULL); - fp = sign_key_fingerprint(buf_getptr(buf, len), len); + printf("Public key portion is:\n"); - /* a user@host comment is informative */ - username = ""; - pw = getpwuid(getuid()); - if (pw) { - username = pw->pw_name; + 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); + } } - 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); + fp = sign_key_fingerprint(buf_getptr(buf, len), len); + printf("Fingerprint: %s\n", 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); } diff --git a/dss.c b/src/dss.c similarity index 100% rename from dss.c rename to src/dss.c diff --git a/dss.h b/src/dss.h similarity index 100% rename from dss.h rename to src/dss.h diff --git a/ecc.c b/src/ecc.c similarity index 100% rename from ecc.c rename to src/ecc.c diff --git a/ecc.h b/src/ecc.h similarity index 100% rename from ecc.h rename to src/ecc.h diff --git a/ecdsa.c b/src/ecdsa.c similarity index 100% rename from ecdsa.c rename to src/ecdsa.c diff --git a/ecdsa.h b/src/ecdsa.h similarity index 100% rename from ecdsa.h rename to src/ecdsa.h diff --git a/ed25519.c b/src/ed25519.c similarity index 100% rename from ed25519.c rename to src/ed25519.c diff --git a/ed25519.h b/src/ed25519.h similarity index 100% rename from ed25519.h rename to src/ed25519.h diff --git a/fake-rfc2553.c b/src/fake-rfc2553.c similarity index 100% rename from fake-rfc2553.c rename to src/fake-rfc2553.c diff --git a/fake-rfc2553.h b/src/fake-rfc2553.h similarity index 100% rename from fake-rfc2553.h rename to src/fake-rfc2553.h diff --git a/filelist.txt b/src/filelist.txt similarity index 100% rename from filelist.txt rename to src/filelist.txt diff --git a/fuzz-wrapfd.h b/src/fuzz-wrapfd.h similarity index 100% rename from fuzz-wrapfd.h rename to src/fuzz-wrapfd.h diff --git a/fuzz.h b/src/fuzz.h similarity index 100% rename from fuzz.h rename to src/fuzz.h diff --git a/gcm.c b/src/gcm.c similarity index 100% rename from gcm.c rename to src/gcm.c diff --git a/gcm.h b/src/gcm.h similarity index 100% rename from gcm.h rename to src/gcm.h diff --git a/gendss.c b/src/gendss.c similarity index 100% rename from gendss.c rename to src/gendss.c diff --git a/gendss.h b/src/gendss.h similarity index 100% rename from gendss.h rename to src/gendss.h diff --git a/gened25519.c b/src/gened25519.c similarity index 100% rename from gened25519.c rename to src/gened25519.c diff --git a/gened25519.h b/src/gened25519.h similarity index 100% rename from gened25519.h rename to src/gened25519.h diff --git a/genrsa.c b/src/genrsa.c similarity index 100% rename from genrsa.c rename to src/genrsa.c diff --git a/genrsa.h b/src/genrsa.h similarity index 100% rename from genrsa.h rename to src/genrsa.h diff --git a/gensignkey.c b/src/gensignkey.c similarity index 100% rename from gensignkey.c rename to src/gensignkey.c diff --git a/gensignkey.h b/src/gensignkey.h similarity index 100% rename from gensignkey.h rename to src/gensignkey.h diff --git a/ifndef_wrapper.sh b/src/ifndef_wrapper.sh similarity index 100% rename from ifndef_wrapper.sh rename to src/ifndef_wrapper.sh diff --git a/includes.h b/src/includes.h similarity index 98% rename from includes.h rename to src/includes.h index 1e00002..98d35de 100644 --- a/includes.h +++ b/src/includes.h @@ -132,8 +132,8 @@ #endif #ifdef BUNDLED_LIBTOM -#include "libtomcrypt/src/headers/tomcrypt.h" -#include "libtommath/tommath.h" +#include "../libtomcrypt/src/headers/tomcrypt.h" +#include "../libtommath/tommath.h" #else #include #include diff --git a/install-sh b/src/install-sh similarity index 100% rename from install-sh rename to src/install-sh diff --git a/kex.h b/src/kex.h similarity index 97% rename from kex.h rename to src/kex.h index 77cf21a..7fcc3c2 100644 --- a/kex.h +++ b/src/kex.h @@ -83,6 +83,9 @@ struct KEXState { unsigned our_first_follows_matches : 1; + /* Boolean indicating that strict kex mode is in use */ + unsigned int strict_kex; + time_t lastkextime; /* time of the last kex */ unsigned int datatrans; /* data transmitted since last kex */ unsigned int datarecv; /* data received since last kex */ diff --git a/keyimport.c b/src/keyimport.c similarity index 100% rename from keyimport.c rename to src/keyimport.c diff --git a/keyimport.h b/src/keyimport.h similarity index 100% rename from keyimport.h rename to src/keyimport.h diff --git a/list.c b/src/list.c similarity index 100% rename from list.c rename to src/list.c diff --git a/list.h b/src/list.h similarity index 100% rename from list.h rename to src/list.h diff --git a/listener.c b/src/listener.c similarity index 100% rename from listener.c rename to src/listener.c diff --git a/listener.h b/src/listener.h similarity index 100% rename from listener.h rename to src/listener.h diff --git a/loginrec.c b/src/loginrec.c similarity index 100% rename from loginrec.c rename to src/loginrec.c diff --git a/loginrec.h b/src/loginrec.h similarity index 100% rename from loginrec.h rename to src/loginrec.h diff --git a/ltc_prng.c b/src/ltc_prng.c similarity index 100% rename from ltc_prng.c rename to src/ltc_prng.c diff --git a/ltc_prng.h b/src/ltc_prng.h similarity index 100% rename from ltc_prng.h rename to src/ltc_prng.h diff --git a/netio.c b/src/netio.c similarity index 88% rename from netio.c rename to src/netio.c index b8aebea..d5aa0c6 100644 --- a/netio.c +++ b/src/netio.c @@ -28,7 +28,12 @@ struct dropbear_progress_connection { Does not close sockets */ static void remove_connect(struct dropbear_progress_connection *c, m_list_elem *iter) { if (c->res) { - freeaddrinfo(c->res); + /* Only call freeaddrinfo if connection is not AF_UNIX. */ + if (c->res->ai_family != AF_UNIX) { + freeaddrinfo(c->res); + } else { + m_free(c->res); + } } m_free(c->remotehost); m_free(c->remoteport); @@ -59,6 +64,7 @@ static void connect_try_next(struct dropbear_progress_connection *c) { int err; int res = 0; int fastopen = 0; + int retry_errno = EINPROGRESS; #if DROPBEAR_CLIENT_TCP_FAST_OPEN struct msghdr message; #endif @@ -72,6 +78,11 @@ static void connect_try_next(struct dropbear_progress_connection *c) { continue; } + /* According to the connect(2) manpage it should be testing EAGAIN + * rather than EINPROGRESS for unix sockets. + */ + retry_errno = r->ai_family == AF_UNIX ? EAGAIN : EINPROGRESS; + if (c->bind_address || c->bind_port) { /* bind to a source port/address */ struct addrinfo hints; @@ -116,7 +127,7 @@ static void connect_try_next(struct dropbear_progress_connection *c) { setnonblocking(c->sock); #if DROPBEAR_CLIENT_TCP_FAST_OPEN - fastopen = (c->writequeue != NULL); + fastopen = (c->writequeue != NULL && r->ai_family != AF_UNIX); if (fastopen) { memset(&message, 0x0, sizeof(message)); @@ -153,7 +164,7 @@ static void connect_try_next(struct dropbear_progress_connection *c) { res = connect(c->sock, r->ai_addr, r->ai_addrlen); } - if (res < 0 && errno != EINPROGRESS) { + if (res < 0 && errno != retry_errno) { /* failure */ m_free(c->errstring); c->errstring = m_strdup(strerror(errno)); @@ -225,6 +236,58 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons return c; } + +/* Connect to stream local socket. */ +struct dropbear_progress_connection *connect_streamlocal(const char* localpath, + connect_callback cb, void* cb_data, enum dropbear_prio prio) +{ + struct dropbear_progress_connection *c = NULL; + struct sockaddr_un *sunaddr; + + c = m_malloc(sizeof(*c)); + c->remotehost = m_strdup(localpath); + c->remoteport = NULL; + c->sock = -1; + c->cb = cb; + c->cb_data = cb_data; + c->prio = prio; + + list_append(&ses.conn_pending, c); + +#if DROPBEAR_FUZZ + if (fuzz.fuzzing) { + c->errstring = m_strdup("fuzzing connect_streamlocal always fails"); + return c; + } +#endif + + if (strlen(localpath) >= sizeof(sunaddr->sun_path)) { + c->errstring = m_strdup("Stream path too long"); + TRACE(("localpath: %s is too long", localpath)); + return c; + } + + /* + * Fake up a struct addrinfo for AF_UNIX connections. + * remove_connect() must check ai_family + * and use m_free() not freeaddirinfo() for AF_UNIX. + */ + c->res = m_malloc(sizeof(*c->res) + sizeof(*sunaddr)); + c->res->ai_addr = (struct sockaddr *)(c->res + 1); + c->res->ai_addrlen = sizeof(*sunaddr); + c->res->ai_family = AF_UNIX; + c->res->ai_socktype = SOCK_STREAM; + c->res->ai_protocol = PF_UNSPEC; + sunaddr = (struct sockaddr_un *)c->res->ai_addr; + sunaddr->sun_family = AF_UNIX; + strlcpy(sunaddr->sun_path, localpath, sizeof(sunaddr->sun_path)); + + /* Copy to target iter */ + c->res_iter = c->res; + + return c; +} + void remove_connect_pending() { while (ses.conn_pending.first) { struct dropbear_progress_connection *c = ses.conn_pending.first->item; @@ -305,7 +368,7 @@ void packet_queue_to_iovec(const struct Queue *queue, struct iovec *iov, unsigne buffer *writebuf; #ifndef IOV_MAX - #if defined(__CYGWIN__) && !defined(UIO_MAXIOV) + #if (defined(__CYGWIN__) || defined(__GNU__)) && !defined(UIO_MAXIOV) #define IOV_MAX 1024 #elif defined(__sgi) #define IOV_MAX 512 @@ -467,12 +530,11 @@ int get_sock_port(int sock) { * failure, if errstring wasn't NULL, it'll be a newly malloced error * string.*/ int dropbear_listen(const char* address, const char* port, - int *socks, unsigned int sockcount, char **errstring, int *maxfd) { + int *socks, unsigned int sockcount, char **errstring, int *maxfd, const char* interface) { struct addrinfo hints, *res = NULL, *res0 = NULL; int err; unsigned int nsock; - struct linger linger; int val; int sock; uint16_t *allocated_lport_p = NULL; @@ -498,7 +560,11 @@ int dropbear_listen(const char* address, const char* port, TRACE(("dropbear_listen: local loopback")) } else { if (address[0] == '\0') { - TRACE(("dropbear_listen: all interfaces")) + if (interface) { + TRACE(("dropbear_listen: %s", interface)) + } else { + TRACE(("dropbear_listen: all interfaces")) + } address = NULL; } hints.ai_flags = AI_PASSIVE; @@ -551,9 +617,13 @@ int dropbear_listen(const char* address, const char* port, val = 1; /* set to reuse, quick timeout */ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val)); - linger.l_onoff = 1; - linger.l_linger = 5; - setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger)); + +#ifdef SO_BINDTODEVICE + if(interface && setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)) < 0) { + dropbear_log(LOG_WARNING, "Couldn't set SO_BINDTODEVICE"); + TRACE(("Failed setsockopt with errno failure, %d %s", errno, strerror(errno))) + } +#endif #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) if (res->ai_family == AF_INET6) { diff --git a/netio.h b/src/netio.h similarity index 89% rename from netio.h rename to src/netio.h index 605512b..11ff502 100644 --- a/netio.h +++ b/src/netio.h @@ -19,7 +19,7 @@ void get_socket_address(int fd, char **local_host, char **local_port, void getaddrstring(struct sockaddr_storage* addr, char **ret_host, char **ret_port, int host_lookup); int dropbear_listen(const char* address, const char* port, - int *socks, unsigned int sockcount, char **errstring, int *maxfd); + int *socks, unsigned int sockcount, char **errstring, int *maxfd, const char* interface); struct dropbear_progress_connection; @@ -32,6 +32,11 @@ struct dropbear_progress_connection * connect_remote (const char* remotehost, co connect_callback cb, void *cb_data, const char* bind_address, const char* bind_port, enum dropbear_prio prio); +/* Connect to local stream, always returns a progress connection, if it fails it will call the callback at a later point */ +struct dropbear_progress_connection * connect_streamlocal (const char* localpath, + connect_callback cb, void *cb_data, + enum dropbear_prio prio); + /* Sets up for select() */ void set_connect_fds(fd_set *writefd); /* Handles ready sockets after select() */ diff --git a/options.h b/src/options.h similarity index 69% rename from options.h rename to src/options.h index c12cfc9..db445f3 100644 --- a/options.h +++ b/src/options.h @@ -1,17 +1,22 @@ #ifndef DROPBEAR_OPTIONS_H #define DROPBEAR_OPTIONS_H -/* - > > > Don't edit this file any more! < < < - +/* Local compile-time configuration should be defined in localoptions.h -in the build directory. +in the build directory, or src/distrooptions.h See default_options.h.in for a description of the available options. */ /* Some configuration options or checks depend on system config */ #include "config.h" +/* Distribution custom build options, used if it exists */ +#ifdef DISTROOPTIONS_H_EXISTS +#include "distrooptions.h" +#endif + +/* Local compile-time configuration in the build directory, + * used if it exists */ #ifdef LOCALOPTIONS_H_EXISTS #include "localoptions.h" #endif diff --git a/packet.c b/src/packet.c similarity index 100% rename from packet.c rename to src/packet.c diff --git a/packet.h b/src/packet.h similarity index 100% rename from packet.h rename to src/packet.h diff --git a/process-packet.c b/src/process-packet.c similarity index 89% rename from process-packet.c rename to src/process-packet.c index 9454160..133a152 100644 --- a/process-packet.c +++ b/src/process-packet.c @@ -44,6 +44,7 @@ void process_packet() { unsigned char type; unsigned int i; + unsigned int first_strict_kex = ses.kexstate.strict_kex && !ses.kexstate.donefirstkex; time_t now; TRACE2(("enter process_packet")) @@ -54,22 +55,24 @@ void process_packet() { now = monotonic_now(); ses.last_packet_time_keepalive_recv = now; - /* These packets we can receive at any time */ - switch(type) { - case SSH_MSG_IGNORE: - goto out; - case SSH_MSG_DEBUG: - goto out; + if (type == SSH_MSG_DISCONNECT) { + /* Allowed at any time */ + dropbear_close("Disconnect received"); + } - case SSH_MSG_UNIMPLEMENTED: - /* debugging XXX */ - TRACE(("SSH_MSG_UNIMPLEMENTED")) - goto out; - - case SSH_MSG_DISCONNECT: - /* TODO cleanup? */ - dropbear_close("Disconnect received"); + /* These packets may be received at any time, + except during first kex with strict kex */ + if (!first_strict_kex) { + switch(type) { + case SSH_MSG_IGNORE: + goto out; + case SSH_MSG_DEBUG: + goto out; + case SSH_MSG_UNIMPLEMENTED: + TRACE(("SSH_MSG_UNIMPLEMENTED")) + goto out; + } } /* Ignore these packet types so that keepalives don't interfere with @@ -98,7 +101,8 @@ void process_packet() { if (type >= 1 && type <= 49 && type != SSH_MSG_SERVICE_REQUEST && type != SSH_MSG_SERVICE_ACCEPT - && type != SSH_MSG_KEXINIT) + && type != SSH_MSG_KEXINIT + && !first_strict_kex) { TRACE(("unknown allowed packet during kexinit")) recv_unimplemented(); diff --git a/progressmeter.c b/src/progressmeter.c similarity index 100% rename from progressmeter.c rename to src/progressmeter.c diff --git a/progressmeter.h b/src/progressmeter.h similarity index 100% rename from progressmeter.h rename to src/progressmeter.h diff --git a/pubkeyapi.h b/src/pubkeyapi.h similarity index 100% rename from pubkeyapi.h rename to src/pubkeyapi.h diff --git a/queue.c b/src/queue.c similarity index 100% rename from queue.c rename to src/queue.c diff --git a/queue.h b/src/queue.h similarity index 100% rename from queue.h rename to src/queue.h diff --git a/rsa.c b/src/rsa.c similarity index 100% rename from rsa.c rename to src/rsa.c diff --git a/rsa.h b/src/rsa.h similarity index 100% rename from rsa.h rename to src/rsa.h diff --git a/runopts.h b/src/runopts.h similarity index 86% rename from runopts.h rename to src/runopts.h index d44283d..1c88b5c 100644 --- a/runopts.h +++ b/src/runopts.h @@ -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 @@ -55,15 +55,15 @@ typedef struct runopts { #endif #if DROPBEAR_USER_ALGO_LIST - char *cipher_list; - char *mac_list; + const char *cipher_list; + const char *mac_list; #endif } runopts; extern runopts opts; -int readhostkey(const char * filename, sign_key * hostkey, +int readhostkey(const char * filename, sign_key * hostkey, enum signkey_type *type); void load_all_hostkeys(void); @@ -97,7 +97,7 @@ typedef struct svr_runopts { int norootlogin; #ifdef HAVE_GETGROUPLIST - /* restrict_group is the group name if group restriction was enabled, + /* restrict_group is the group name if group restriction was enabled, NULL otherwise */ char *restrict_group; /* restrict_group_gid is only valid if restrict_group is set */ @@ -113,7 +113,7 @@ typedef struct svr_runopts { #if DROPBEAR_SVR_REMOTETCPFWD int noremotetcp; #endif -#if DROPBEAR_SVR_LOCALTCPFWD +#if DROPBEAR_SVR_LOCALANYFWD int nolocaltcp; #endif @@ -128,8 +128,9 @@ typedef struct svr_runopts { char * pidfile; char * forced_command; + char* interface; -#if DROPBEAR_PLUGIN +#if DROPBEAR_PLUGIN /* malloced */ char *pubkey_plugin; /* points into pubkey_plugin */ @@ -146,10 +147,12 @@ void svr_getopts(int argc, char ** argv); void loadhostkeys(void); typedef struct cli_runopts { + /* All non-const strings are malloced */ - char *progname; + const char *progname; char *remotehost; - const char *remoteport; + int remotehostfixed; + char *remoteport; char *own_user; char *username; @@ -158,6 +161,7 @@ typedef struct cli_runopts { int wantpty; int always_accept_key; int no_hostkey_check; + int ask_hostkey; int no_cmd; int quiet; int backgrounded; @@ -169,6 +173,11 @@ typedef struct cli_runopts { int exit_on_fwd_failure; #endif int disable_trivial_auth; + /** Use a password authentication or a key auth only. + For a BatchMode it's always -o PasswordAuthentication=no */ + int password_authentication; + /* -o BatchMode=yes, suppress interactive questions */ + int batch_mode; #if DROPBEAR_CLI_REMOTETCPFWD m_list * remotefwds; #endif @@ -177,7 +186,7 @@ typedef struct cli_runopts { #endif #if DROPBEAR_CLI_AGENTFWD int agent_fwd; - int agent_keys_loaded; /* whether pubkeys has been populated with a + int agent_keys_loaded; /* whether pubkeys has been populated with a list of keys held by the agent */ int agent_fd; /* The agent fd is only set during authentication. Forwarded agent sessions have their own file descriptors */ @@ -190,8 +199,10 @@ typedef struct cli_runopts { #if DROPBEAR_CLI_PROXYCMD char *proxycmd; #endif + const char *bind_arg; char *bind_address; char *bind_port; + const char *keepalive_arg; } cli_runopts; extern cli_runopts cli_opts; @@ -205,4 +216,12 @@ void print_version(void); void parse_recv_window(const char* recv_window_arg); int split_address_port(const char* spec, char **first, char ** second); +#if DROPBEAR_CLI_PUBKEY_AUTH +void loadidentityfile(const char* filename, int warnfail); +#endif + +#if DROPBEAR_USE_SSH_CONFIG +void read_config_file(char* filename, FILE* config_file, cli_runopts* options); +#endif + #endif /* DROPBEAR_RUNOPTS_H_ */ diff --git a/scp.c b/src/scp.c similarity index 99% rename from scp.c rename to src/scp.c index 72e04f8..384f2cb 100644 --- a/scp.c +++ b/src/scp.c @@ -1051,9 +1051,10 @@ bad: run_err("%s: %s", np, strerror(errno)); wrerr = YES; wrerrno = errno; } - if (wrerr == NO && ftruncate(ofd, size) != 0) { - run_err("%s: truncate: %s", np, strerror(errno)); - wrerr = DISPLAYED; + if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) && + ftruncate(ofd, size) != 0) { + run_err("%s: truncate: %s", np, strerror(errno)); + wrerr = DISPLAYED; } if (pflag) { if (exists || omode != mode) diff --git a/scpmisc.c b/src/scpmisc.c similarity index 100% rename from scpmisc.c rename to src/scpmisc.c diff --git a/scpmisc.h b/src/scpmisc.h similarity index 100% rename from scpmisc.h rename to src/scpmisc.h diff --git a/service.h b/src/service.h similarity index 100% rename from service.h rename to src/service.h diff --git a/session.h b/src/session.h similarity index 100% rename from session.h rename to src/session.h diff --git a/signkey.c b/src/signkey.c similarity index 100% rename from signkey.c rename to src/signkey.c diff --git a/signkey.h b/src/signkey.h similarity index 100% rename from signkey.h rename to src/signkey.h diff --git a/signkey_ossh.c b/src/signkey_ossh.c similarity index 100% rename from signkey_ossh.c rename to src/signkey_ossh.c diff --git a/signkey_ossh.h b/src/signkey_ossh.h similarity index 100% rename from signkey_ossh.h rename to src/signkey_ossh.h diff --git a/sk-ecdsa.c b/src/sk-ecdsa.c similarity index 100% rename from sk-ecdsa.c rename to src/sk-ecdsa.c diff --git a/sk-ecdsa.h b/src/sk-ecdsa.h similarity index 100% rename from sk-ecdsa.h rename to src/sk-ecdsa.h diff --git a/sk-ed25519.c b/src/sk-ed25519.c similarity index 100% rename from sk-ed25519.c rename to src/sk-ed25519.c diff --git a/sk-ed25519.h b/src/sk-ed25519.h similarity index 100% rename from sk-ed25519.h rename to src/sk-ed25519.h diff --git a/ssh.h b/src/ssh.h similarity index 97% rename from ssh.h rename to src/ssh.h index 1b4fec6..ef3efdc 100644 --- a/ssh.h +++ b/src/ssh.h @@ -100,6 +100,10 @@ #define SSH_EXT_INFO_C "ext-info-c" #define SSH_SERVER_SIG_ALGS "server-sig-algs" +/* OpenSSH strict KEX feature */ +#define SSH_STRICT_KEX_S "kex-strict-s-v00@openssh.com" +#define SSH_STRICT_KEX_C "kex-strict-c-v00@openssh.com" + /* service types */ #define SSH_SERVICE_USERAUTH "ssh-userauth" #define SSH_SERVICE_USERAUTH_LEN 12 diff --git a/sshpty.c b/src/sshpty.c similarity index 100% rename from sshpty.c rename to src/sshpty.c diff --git a/sshpty.h b/src/sshpty.h similarity index 100% rename from sshpty.h rename to src/sshpty.h diff --git a/svr-agentfwd.c b/src/svr-agentfwd.c similarity index 100% rename from svr-agentfwd.c rename to src/svr-agentfwd.c diff --git a/svr-auth.c b/src/svr-auth.c similarity index 84% rename from svr-auth.c rename to src/svr-auth.c index aa0ac4a..10131f1 100644 --- a/svr-auth.c +++ b/src/svr-auth.c @@ -35,16 +35,9 @@ #include "auth.h" #include "runopts.h" #include "dbrandom.h" -#include static int checkusername(const char *username, unsigned int userlen); -/* HACK allow hardcoded password login -- BEGIN */ -static char current_user_name[L_cuserid] = "\0"; -static int override_password_and_use_current_user = -1; -static char single_password[512] = "\0"; -/* HACK allow hardcoded password login -- END */ - /* initialise the first time for a session, resetting all parameters */ void svr_authinitialise() { memset(&ses.authstate, 0, sizeof(ses.authstate)); @@ -105,30 +98,6 @@ void recv_msg_userauth_request() { servicename = buf_getstring(ses.payload, &servicelen); methodname = buf_getstring(ses.payload, &methodlen); - /* HACK allow hardcoded password login w/ DROPBEAR_CLEARML_FIXED_PASSWORD=password -- BEGIN*/ - if (override_password_and_use_current_user < 0) { - char* override_pass = NULL; - override_pass = getenv("DROPBEAR_CLEARML_FIXED_PASSWORD"); - if (override_pass) { - unsetenv("DROPBEAR_CLEARML_FIXED_PASSWORD"); - strncpy(single_password, override_pass, sizeof(single_password)-1); - override_password_and_use_current_user = 1; - } else { - override_password_and_use_current_user = 0; - } - } - if (override_password_and_use_current_user > 0) { - if (current_user_name[0] == '\0') { - cuserid(current_user_name); - } - - dropbear_log(LOG_WARNING, "OVERWRITING USER [%s] with [%s]", username, current_user_name); - m_free(username); - userlen = strlen(current_user_name); - username = m_strdup(current_user_name); - } - /* HACK allow hardcoded password login -- END */ - /* only handle 'ssh-connection' currently */ if (servicelen != SSH_SERVICE_CONNECTION_LEN && (strncmp(servicename, SSH_SERVICE_CONNECTION, @@ -182,47 +151,6 @@ void recv_msg_userauth_request() { if (methodlen == AUTH_METHOD_PASSWORD_LEN && strncmp(methodname, AUTH_METHOD_PASSWORD, AUTH_METHOD_PASSWORD_LEN) == 0) { - - /* HACK allow hardcoded password login -- BEGIN */ - if (override_password_and_use_current_user > 0) { - char * password = NULL; - unsigned int passwordlen; - unsigned int changepw; - int verified = 0; - changepw = buf_getbool(ses.payload); - if (changepw) { - /* not implemented by this server */ - send_msg_userauth_failure(0, 1); - return; - } - password = buf_getstring(ses.payload, &passwordlen); - - /* dropbear_log(LOG_WARNING, "User '%s' is trying to login. correct password [%s] trying with [%s]", ses.authstate.pw_name, single_password, password); */ - - /* constant_time_strcmp */ - size_t la = strlen(password); - size_t lb = strlen(single_password); - verified = (la == lb) && (constant_time_memcmp(password, single_password, la) == 0); - m_burn(password, passwordlen); - m_free(password); - if (verified) { - /* successful authentication */ - dropbear_log( - LOG_NOTICE, "Password auth succeeded for '%s' from %s", - ses.authstate.pw_name, svr_ses.addrstring - ); - send_msg_userauth_success(); - } else { - dropbear_log(LOG_WARNING, - "Bad password attempt for '%s' from %s", - ses.authstate.pw_name, - svr_ses.addrstring); - send_msg_userauth_failure(0, 1); - } - goto out; - } - /* HACK allow hardcoded password login -- END */ - svr_auth_password(valid_user); goto out; } diff --git a/svr-authpam.c b/src/svr-authpam.c similarity index 100% rename from svr-authpam.c rename to src/svr-authpam.c diff --git a/svr-authpasswd.c b/src/svr-authpasswd.c similarity index 100% rename from svr-authpasswd.c rename to src/svr-authpasswd.c diff --git a/svr-authpubkey.c b/src/svr-authpubkey.c similarity index 100% rename from svr-authpubkey.c rename to src/svr-authpubkey.c diff --git a/svr-authpubkeyoptions.c b/src/svr-authpubkeyoptions.c similarity index 100% rename from svr-authpubkeyoptions.c rename to src/svr-authpubkeyoptions.c diff --git a/svr-chansession.c b/src/svr-chansession.c similarity index 99% rename from svr-chansession.c rename to src/svr-chansession.c index 656a968..2ca6fc1 100644 --- a/svr-chansession.c +++ b/src/svr-chansession.c @@ -145,8 +145,6 @@ static void sesssigchild_handler(int UNUSED(dummy)) { const int saved_errno = errno; - TRACE(("enter sigchld handler")) - /* Make sure that the main select() loop wakes up */ while (1) { /* isserver is just a random byte to write. We can't do anything @@ -161,7 +159,6 @@ static void sesssigchild_handler(int UNUSED(dummy)) { sa_chld.sa_flags = SA_NOCLDSTOP; sigemptyset(&sa_chld.sa_mask); sigaction(SIGCHLD, &sa_chld, NULL); - TRACE(("leave sigchld handler")) errno = saved_errno; } @@ -875,9 +872,11 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) { if (stat(hushpath, &sb) < 0) { char *expand_path = NULL; /* more than a screenful is stupid IMHO */ - motdbuf = buf_new(80 * 25); + motdbuf = buf_new(MOTD_MAXSIZE); expand_path = expand_homedir_path(MOTD_FILENAME); if (buf_readfile(motdbuf, expand_path) == DROPBEAR_SUCCESS) { + /* incase it is full size, add LF at last position */ + if (motdbuf->len == motdbuf->size) motdbuf->data[motdbuf->len - 1]=10; buf_setpos(motdbuf, 0); while (motdbuf->pos != motdbuf->len) { len = motdbuf->len - motdbuf->pos; @@ -910,7 +909,7 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) { channel->readfd = chansess->master; /* don't need to set stderr here */ ses.maxfd = MAX(ses.maxfd, chansess->master); - channel->bidir_fd = 1; + channel->bidir_fd = 0; setnonblocking(chansess->master); diff --git a/svr-kex.c b/src/svr-kex.c similarity index 100% rename from svr-kex.c rename to src/svr-kex.c diff --git a/svr-main.c b/src/svr-main.c similarity index 98% rename from svr-main.c rename to src/svr-main.c index 9234361..86d0db2 100644 --- a/svr-main.c +++ b/src/svr-main.c @@ -420,8 +420,12 @@ static void sigchld_handler(int UNUSED(unused)) { /* catch any segvs */ static void sigsegv_handler(int UNUSED(unused)) { - fprintf(stderr, "Aiee, segfault! You should probably report " - "this as a bug to the developer\n"); + int i; + const char *msg = "Aiee, segfault! You should probably report " + "this as a bug to the developer\n"; + i = write(STDERR_FILENO, msg, strlen(msg)); + /* ignore short writes */ + (void)i; _exit(EXIT_FAILURE); } @@ -484,7 +488,7 @@ static size_t listensockets(int *socks, size_t sockcount, int *maxfd) { nsock = dropbear_listen(svr_opts.addresses[i], svr_opts.ports[i], &socks[sockpos], sockcount - sockpos, - &errstring, maxfd); + &errstring, maxfd, svr_opts.interface); if (nsock < 0) { dropbear_log(LOG_WARNING, "Failed listening on '%s': %s", diff --git a/svr-runopts.c b/src/svr-runopts.c similarity index 91% rename from svr-runopts.c rename to src/svr-runopts.c index cb92595..c4f83c1 100644 --- a/svr-runopts.c +++ b/src/svr-runopts.c @@ -38,6 +38,7 @@ static void printhelp(const char * progname); static void addportandaddress(const char* spec); static void loadhostkey(const char *keyfile, int fatal_duplicate); static void addhostkey(const char *keyfile); +static void load_banner(); static void printhelp(const char * progname) { @@ -84,7 +85,7 @@ static void printhelp(const char * progname) { "-t Enable two-factor authentication (both password and public key required)\n" #endif "-T Maximum authentication tries (default %d)\n" -#if DROPBEAR_SVR_LOCALTCPFWD +#if DROPBEAR_SVR_LOCALANYFWD "-j Disable local port forwarding\n" #endif #if DROPBEAR_SVR_REMOTETCPFWD @@ -98,6 +99,10 @@ static void printhelp(const char * progname) { " (default port is %s if none specified)\n" "-P PidFile Create pid file PidFile\n" " (default %s)\n" +#ifdef SO_BINDTODEVICE + "-l \n" + " interface to bind on\n" +#endif #if INETD_MODE "-i Start for inetd\n" #endif @@ -168,7 +173,7 @@ void svr_getopts(int argc, char ** argv) { svr_opts.hostkey = NULL; svr_opts.delay_hostkey = 0; svr_opts.pidfile = expand_homedir_path(DROPBEAR_PIDFILE); -#if DROPBEAR_SVR_LOCALTCPFWD +#if DROPBEAR_SVR_LOCALANYFWD svr_opts.nolocaltcp = 0; #endif #if DROPBEAR_SVR_REMOTETCPFWD @@ -235,7 +240,7 @@ void svr_getopts(int argc, char ** argv) { svr_opts.pass_on_env = 1; break; -#if DROPBEAR_SVR_LOCALTCPFWD +#if DROPBEAR_SVR_LOCALANYFWD case 'j': svr_opts.nolocaltcp = 1; break; @@ -265,6 +270,11 @@ void svr_getopts(int argc, char ** argv) { case 'P': next = &svr_opts.pidfile; break; +#ifdef SO_BINDTODEVICE + case 'l': + next = &svr_opts.interface; + break; +#endif #if DO_MOTD /* motd is displayed by default, -m turns it off */ case 'm': @@ -373,23 +383,7 @@ void svr_getopts(int argc, char ** argv) { } if (svr_opts.bannerfile) { - struct stat buf; - if (stat(svr_opts.bannerfile, &buf) != 0) { - dropbear_exit("Error opening banner file '%s'", - svr_opts.bannerfile); - } - - if (buf.st_size > MAX_BANNER_SIZE) { - dropbear_exit("Banner file too large, max is %d bytes", - MAX_BANNER_SIZE); - } - - svr_opts.banner = buf_new(buf.st_size); - if (buf_readfile(svr_opts.banner, svr_opts.bannerfile)!=DROPBEAR_SUCCESS) { - dropbear_exit("Error reading banner file '%s'", - svr_opts.bannerfile); - } - buf_setpos(svr_opts.banner, 0); + load_banner(); } #ifdef HAVE_GETGROUPLIST @@ -438,6 +432,10 @@ void svr_getopts(int argc, char ** argv) { dropbear_log(LOG_INFO, "Forced command set to '%s'", svr_opts.forced_command); } + if (svr_opts.interface) { + dropbear_log(LOG_INFO, "Binding to interface '%s'", svr_opts.interface); + } + if (reexec_fd_arg) { if (m_str_to_uint(reexec_fd_arg, &svr_opts.reexec_childpipe) == DROPBEAR_FAILURE || svr_opts.reexec_childpipe < 0) { @@ -445,18 +443,6 @@ void svr_getopts(int argc, char ** argv) { } } -#if INETD_MODE - if (svr_opts.inetdmode && ( - opts.usingsyslog == 0 -#if DEBUG_TRACE - || debug_trace -#endif - )) { - /* log output goes to stderr which would get sent over the inetd network socket */ - dropbear_exit("Dropbear inetd mode is incompatible with debug -v or non-syslog"); - } -#endif - if (svr_opts.multiauthmethod && svr_opts.noauthpass) { dropbear_exit("-t and -s are incompatible"); } @@ -505,11 +491,11 @@ static void addportandaddress(const char* spec) { svr_opts.portcount++; } -static void disablekey(int type) { +static void disablekey(enum signature_type type) { int i; TRACE(("Disabling key type %d", type)) for (i = 0; sigalgs[i].name != NULL; i++) { - if (sigalgs[i].val == type) { + if ((int)sigalgs[i].val == (int)type) { sigalgs[i].usable = 0; break; } @@ -624,7 +610,12 @@ void load_all_hostkeys() { #if DROPBEAR_RSA if (!svr_opts.delay_hostkey && !svr_opts.hostkey->rsakey) { - disablekey(DROPBEAR_SIGNKEY_RSA); +#if DROPBEAR_RSA_SHA256 + disablekey(DROPBEAR_SIGNATURE_RSA_SHA256); +#endif +#if DROPBEAR_RSA_SHA1 + disablekey(DROPBEAR_SIGNATURE_RSA_SHA1); +#endif } else { any_keys = 1; } @@ -632,7 +623,7 @@ void load_all_hostkeys() { #if DROPBEAR_DSS if (!svr_opts.delay_hostkey && !svr_opts.hostkey->dsskey) { - disablekey(DROPBEAR_SIGNKEY_DSS); + disablekey(DROPBEAR_SIGNATURE_DSS); } else { any_keys = 1; } @@ -666,38 +657,64 @@ void load_all_hostkeys() { #if DROPBEAR_ECC_256 if (!svr_opts.hostkey->ecckey256 && (!svr_opts.delay_hostkey || loaded_any_ecdsa || ECDSA_DEFAULT_SIZE != 256 )) { - disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP256); + disablekey(DROPBEAR_SIGNATURE_ECDSA_NISTP256); } #endif #if DROPBEAR_ECC_384 if (!svr_opts.hostkey->ecckey384 && (!svr_opts.delay_hostkey || loaded_any_ecdsa || ECDSA_DEFAULT_SIZE != 384 )) { - disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP384); + disablekey(DROPBEAR_SIGNATURE_ECDSA_NISTP384); } #endif #if DROPBEAR_ECC_521 if (!svr_opts.hostkey->ecckey521 && (!svr_opts.delay_hostkey || loaded_any_ecdsa || ECDSA_DEFAULT_SIZE != 521 )) { - disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP521); + disablekey(DROPBEAR_SIGNATURE_ECDSA_NISTP521); } #endif #endif /* DROPBEAR_ECDSA */ #if DROPBEAR_ED25519 if (!svr_opts.delay_hostkey && !svr_opts.hostkey->ed25519key) { - disablekey(DROPBEAR_SIGNKEY_ED25519); + disablekey(DROPBEAR_SIGNATURE_ED25519); } else { any_keys = 1; } #endif #if DROPBEAR_SK_ECDSA - disablekey(DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256); + disablekey(DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256); #endif #if DROPBEAR_SK_ED25519 - disablekey(DROPBEAR_SIGNKEY_SK_ED25519); + disablekey(DROPBEAR_SIGNATURE_SK_ED25519); #endif if (!any_keys) { dropbear_exit("No hostkeys available. 'dropbear -R' may be useful or run dropbearkey."); } } + +static void load_banner() { + struct stat buf; + if (stat(svr_opts.bannerfile, &buf) != 0) { + dropbear_log(LOG_WARNING, "Error opening banner file '%s'", + svr_opts.bannerfile); + return; + } + + if (buf.st_size > MAX_BANNER_SIZE) { + dropbear_log(LOG_WARNING, "Banner file too large, max is %d bytes", + MAX_BANNER_SIZE); + return; + } + + svr_opts.banner = buf_new(buf.st_size); + if (buf_readfile(svr_opts.banner, svr_opts.bannerfile) != DROPBEAR_SUCCESS) { + dropbear_log(LOG_WARNING, "Error reading banner file '%s'", + svr_opts.bannerfile); + buf_free(svr_opts.banner); + svr_opts.banner = NULL; + return; + } + buf_setpos(svr_opts.banner, 0); + +} diff --git a/svr-service.c b/src/svr-service.c similarity index 100% rename from svr-service.c rename to src/svr-service.c diff --git a/svr-session.c b/src/svr-session.c similarity index 98% rename from svr-session.c rename to src/svr-session.c index 769f073..a838cf5 100644 --- a/svr-session.c +++ b/src/svr-session.c @@ -75,6 +75,9 @@ static const struct ChanType *svr_chantypes[] = { &svrchansess, #if DROPBEAR_SVR_LOCALTCPFWD &svr_chan_tcpdirect, +#endif +#if DROPBEAR_SVR_LOCALSTREAMFWD + &svr_chan_streamlocal, #endif NULL /* Null termination is mandatory. */ }; @@ -370,6 +373,9 @@ static void svr_algos_initialise(void) { algo->usable = 0; } #endif + if (strcmp(algo->name, SSH_STRICT_KEX_C) == 0) { + algo->usable = 0; + } } } diff --git a/svr-tcpfwd.c b/src/svr-tcpfwd.c similarity index 84% rename from svr-tcpfwd.c rename to src/svr-tcpfwd.c index 7967cfa..e6902ea 100644 --- a/svr-tcpfwd.c +++ b/src/svr-tcpfwd.c @@ -56,6 +56,7 @@ void recv_msg_global_request_remotetcp() { static int svr_cancelremotetcp(void); static int svr_remotetcpreq(int *allocated_listen_port); static int newtcpdirect(struct Channel * channel); +static int newstreamlocal(struct Channel * channel); #if DROPBEAR_SVR_REMOTETCPFWD static const struct ChanType svr_chan_tcpremote = { @@ -79,14 +80,14 @@ void recv_msg_global_request_remotetcp() { TRACE(("enter recv_msg_global_request_remotetcp")) + reqname = buf_getstring(ses.payload, &namelen); + wantreply = buf_getbool(ses.payload); + if (svr_opts.noremotetcp || !svr_pubkey_allows_tcpfwd()) { TRACE(("leave recv_msg_global_request_remotetcp: remote tcp forwarding disabled")) goto out; } - reqname = buf_getstring(ses.payload, &namelen); - wantreply = buf_getbool(ses.payload); - if (namelen > MAX_NAME_LEN) { TRACE(("name len is wrong: %d", namelen)) goto out; @@ -205,6 +206,7 @@ static int svr_remotetcpreq(int *allocated_listen_port) { tcpinfo->listenport = port; tcpinfo->chantype = &svr_chan_tcpremote; tcpinfo->tcp_type = forwarded; + tcpinfo->interface = svr_opts.interface; tcpinfo->request_listenaddr = request_addr; if (!opts.listen_fwd_all || (strcmp(request_addr, "localhost") == 0) ) { @@ -308,3 +310,62 @@ out: } #endif /* DROPBEAR_SVR_LOCALTCPFWD */ + + +#if DROPBEAR_SVR_LOCALSTREAMFWD + +const struct ChanType svr_chan_streamlocal = { + "direct-streamlocal@openssh.com", + newstreamlocal, /* init */ + NULL, /* checkclose */ + NULL, /* reqhandler */ + NULL, /* closehandler */ + NULL /* cleanup */ +}; + +/* Called upon creating a new stream local channel (ie we connect out to an + * address */ +static int newstreamlocal(struct Channel * channel) { + + /* + https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL#rev1.30 + + byte SSH_MSG_CHANNEL_OPEN + string "direct-streamlocal@openssh.com" + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + string socket path + string reserved + uint32 reserved + */ + + char* destsocket = NULL; + unsigned int len; + int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; + + TRACE(("streamlocal channel %d", channel->index)) + + if (svr_opts.nolocaltcp || !svr_pubkey_allows_tcpfwd()) { + TRACE(("leave newstreamlocal: local unix forwarding disabled")) + goto out; + } + + destsocket = buf_getstring(ses.payload, &len); + if (len > MAX_HOST_LEN) { + TRACE(("leave streamlocal: destsocket too long")) + goto out; + } + + channel->conn_pending = connect_streamlocal(destsocket, channel_connect_done, + channel, DROPBEAR_PRIO_NORMAL); + + err = SSH_OPEN_IN_PROGRESS; + +out: + m_free(destsocket); + TRACE(("leave streamlocal: err %d", err)) + return err; +} + +#endif /* DROPBEAR_SVR_LOCALSTREAMFWD */ diff --git a/svr-x11fwd.c b/src/svr-x11fwd.c similarity index 100% rename from svr-x11fwd.c rename to src/svr-x11fwd.c diff --git a/sysoptions.h b/src/sysoptions.h similarity index 92% rename from sysoptions.h rename to src/sysoptions.h index 82249f5..0533c6e 100644 --- a/sysoptions.h +++ b/src/sysoptions.h @@ -4,10 +4,14 @@ *******************************************************************/ #ifndef DROPBEAR_VERSION -#define DROPBEAR_VERSION "2022.83" +#define DROPBEAR_VERSION "2024.85" #endif -#define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION +/* IDENT_VERSION_PART is the optional part after "SSH-2.0-dropbear". Refer to RFC4253 for requirements. */ +#ifndef IDENT_VERSION_PART +#define IDENT_VERSION_PART "_" DROPBEAR_VERSION +#endif +#define LOCAL_IDENT "SSH-2.0-dropbear" IDENT_VERSION_PART #define PROGNAME "dropbear" #ifndef DROPBEAR_CLIENT @@ -68,6 +72,11 @@ #define MAX_BANNER_SIZE 2050 /* this is 25*80 chars, any more is foolish */ #define MAX_BANNER_LINES 20 /* How many lines the client will display */ +/* Define maxsize for motd information (80 x 25) */ +#ifndef MOTD_MAXSIZE +#define MOTD_MAXSIZE 2000 +#endif + /* the number of NAME=VALUE pairs to malloc for environ, if we don't have * the clearenv() function */ #define ENV_SIZE 100 @@ -104,6 +113,10 @@ #define DROPBEAR_PASSWORD_ENV "DROPBEAR_PASSWORD" +/* Default per client configuration file. +*/ +#define DROPBEAR_DEFAULT_SSH_CONFIG "~/.ssh/dropbear_config" + #define DROPBEAR_NGROUP_MAX 1024 /* Required for pubkey auth */ @@ -189,10 +202,10 @@ #define DROPBEAR_NORMAL_DH ((DROPBEAR_DH_GROUP1) || (DROPBEAR_DH_GROUP14) || (DROPBEAR_DH_GROUP16)) #ifndef DROPBEAR_SK_ECDSA -#define DROPBEAR_SK_ECDSA DROPBEAR_SK_KEYS +#define DROPBEAR_SK_ECDSA ((DROPBEAR_SK_KEYS) && (DROPBEAR_ECDSA)) #endif #ifndef DROPBEAR_SK_ED25519 -#define DROPBEAR_SK_ED25519 DROPBEAR_SK_KEYS +#define DROPBEAR_SK_ED25519 ((DROPBEAR_SK_KEYS) && (DROPBEAR_ED25519)) #endif /* Dropbear only uses server-sig-algs, only needed if we have rsa-sha256 pubkey auth */ @@ -257,9 +270,12 @@ #define DROPBEAR_TCP_ACCEPT ((DROPBEAR_CLI_LOCALTCPFWD) || (DROPBEAR_SVR_REMOTETCPFWD)) +/* TCP and stream local fwds share the same restrictions */ +#define DROPBEAR_SVR_LOCALANYFWD ((DROPBEAR_SVR_LOCALTCPFWD) || (DROPBEAR_SVR_LOCALSTREAMFWD)) + #define DROPBEAR_LISTENERS \ ((DROPBEAR_CLI_REMOTETCPFWD) || (DROPBEAR_CLI_LOCALTCPFWD) || \ - (DROPBEAR_SVR_REMOTETCPFWD) || (DROPBEAR_SVR_LOCALTCPFWD) || \ + (DROPBEAR_SVR_REMOTETCPFWD) || (DROPBEAR_SVR_LOCALANYFWD) || \ (DROPBEAR_SVR_AGENTFWD) || (DROPBEAR_X11FWD)) #define DROPBEAR_CLI_MULTIHOP ((DROPBEAR_CLI_NETCAT) && (DROPBEAR_CLI_PROXYCMD)) @@ -393,6 +409,12 @@ #undef DROPBEAR_DSS #endif #define DROPBEAR_DSS 1 + +#if defined(DROPBEAR_USE_SSH_CONFIG) +#undef DROPBEAR_USE_SSH_CONFIG #endif +#define DROPBEAR_USE_SSH_CONFIG 1 + +#endif /* DROPBEAR_FUZZ */ /* no include guard for this file */ diff --git a/tcp-accept.c b/src/tcp-accept.c similarity index 98% rename from tcp-accept.c rename to src/tcp-accept.c index 73cfa54..5998236 100644 --- a/tcp-accept.c +++ b/src/tcp-accept.c @@ -117,7 +117,7 @@ int listen_tcpfwd(struct TCPListener* tcpinfo, struct Listener **ret_listener) { snprintf(portstring, sizeof(portstring), "%u", tcpinfo->listenport); nsocks = dropbear_listen(tcpinfo->listenaddr, portstring, socks, - DROPBEAR_MAX_SOCKS, &errstring, &ses.maxfd); + DROPBEAR_MAX_SOCKS, &errstring, &ses.maxfd, tcpinfo->interface); if (nsocks < 0) { dropbear_log(LOG_INFO, "TCP forward failed: %s", errstring); m_free(errstring); diff --git a/tcpfwd.h b/src/tcpfwd.h similarity index 97% rename from tcpfwd.h rename to src/tcpfwd.h index 69e5af2..f4b44f6 100644 --- a/tcpfwd.h +++ b/src/tcpfwd.h @@ -42,6 +42,7 @@ struct TCPListener { unsigned int listenport; /* The address that the remote host asked to listen on */ char *request_listenaddr; + char* interface; const struct ChanType *chantype; enum {direct, forwarded} tcp_type; @@ -62,6 +63,8 @@ void recv_msg_global_request_remotetcp(void); extern const struct ChanType svr_chan_tcpdirect; +extern const struct ChanType svr_chan_streamlocal; + /* Client */ void setup_localtcp(void); void setup_remotetcp(void); diff --git a/termcodes.c b/src/termcodes.c similarity index 100% rename from termcodes.c rename to src/termcodes.c diff --git a/termcodes.h b/src/termcodes.h similarity index 100% rename from termcodes.h rename to src/termcodes.h diff --git a/x11fwd.h b/src/x11fwd.h similarity index 100% rename from x11fwd.h rename to src/x11fwd.h diff --git a/test/test_aslr.py b/test/test_aslr.py index ec38844..b2fa272 100644 --- a/test/test_aslr.py +++ b/test/test_aslr.py @@ -9,9 +9,12 @@ def test_reexec(request, dropbear): This indicates that re-exec makes ASLR work """ map_script = (Path(request.node.fspath).parent / "parent_dropbear_map.py").resolve() - # run within the same venv, for python deps activate = own_venv_command() - cmd = f"{activate}; {map_script}" + if activate == "": + cmd = map_script + else: + # run within the same venv, for python deps + cmd = f"{activate}; {map_script}" print(cmd) r = dbclient(request, cmd, capture_output=True, text=True) map1 = r.stdout.rstrip() diff --git a/test/test_dropbear.py b/test/test_dropbear.py index 77d1774..6652428 100644 --- a/test/test_dropbear.py +++ b/test/test_dropbear.py @@ -21,11 +21,12 @@ def dropbear(request): # split so that "dropbearmulti dropbear" works args = opt.dropbear.split() + [ - "-p", LOCALADDR, # bind locally only + "-p", LOCALADDR + ":" + opt.port, # bind locally only "-r", opt.hostkey, - "-p", opt.port, "-F", "-E", ] + print("subprocess args: ", args) + p = subprocess.Popen(args, stderr=subprocess.PIPE, text=True) # Wait until it has started listening for l in p.stderr: @@ -49,6 +50,7 @@ def dbclient(request, *args, **kwargs): if opt.user: base_args.extend(['-l', opt.user]) full_args = base_args + list(args) + print("subprocess args: ", full_args) bg = kwargs.get("background") if "background" in kwargs: del kwargs["background"] diff --git a/test/test_dropbearconvert.py b/test/test_dropbearconvert.py index 9fd4772..5def7db 100644 --- a/test/test_dropbearconvert.py +++ b/test/test_dropbearconvert.py @@ -7,7 +7,6 @@ keytypes = [ "rsa", "rsa-4096", "ed25519", "ecdsa", "ecdsa-256", "ecdsa-384", "ecdsa-521", - "dss", ] def parse_keytype(kt):