mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cafebe2d30 | ||
|
|
cc481a646d | ||
|
|
2634c4586b | ||
|
|
712d529164 | ||
|
|
2ad020ff30 | ||
|
|
0c62c0db7f | ||
|
|
2993eedaba | ||
|
|
c66f0e98c9 | ||
|
|
c8fcc08fe0 | ||
|
|
483b427335 | ||
|
|
27ffea3223 | ||
|
|
742e296115 | ||
|
|
0e43d68d81 | ||
|
|
bcb9d78d83 | ||
|
|
8da9646c83 | ||
|
|
da482ede60 | ||
|
|
f0495697e5 | ||
|
|
f9ced2c880 | ||
|
|
17e0c7e76f | ||
|
|
30adc15860 | ||
|
|
6138bdc62f | ||
|
|
e05945f67a | ||
|
|
3e640acd17 | ||
|
|
ae25761c7c | ||
|
|
e6152ccd7d | ||
|
|
8b0d31ab20 | ||
|
|
65f6e48a06 | ||
|
|
a7ef149463 | ||
|
|
043b0fbd1b | ||
|
|
110b55214b | ||
|
|
c08177a3af | ||
|
|
3c2436cd05 | ||
|
|
f3b72bfd18 | ||
|
|
f17400e738 | ||
|
|
8e6f73e879 | ||
|
|
7c2470ba3a | ||
|
|
cc59c08605 | ||
|
|
661d8ca225 | ||
|
|
41d4b4e7f7 | ||
|
|
dc016f900b | ||
|
|
4c8c879b38 | ||
|
|
210a983349 | ||
|
|
69e5709f75 | ||
|
|
2157d52352 | ||
|
|
846d38fe43 | ||
|
|
a8d6dac2c5 | ||
|
|
ee49a1b16d | ||
|
|
325d0c1d02 | ||
|
|
17f209f9b7 | ||
|
|
924d5a06a6 | ||
|
|
1bf7acc5bd | ||
|
|
8d0013bbe0 | ||
|
|
9262ffe861 | ||
|
|
1eb369272b | ||
|
|
c0ed29ea02 | ||
|
|
91ca561d7a | ||
|
|
ba260bd67b | ||
|
|
898bff3d4e | ||
|
|
67a8de30b7 | ||
|
|
6c571c54e5 | ||
|
|
d2bfa6aedc | ||
|
|
d0d1ede191 | ||
|
|
3c2f113a78 | ||
|
|
f193e95a3e | ||
|
|
03481aba06 | ||
|
|
8b0fdf8010 | ||
|
|
934cc87db3 | ||
|
|
ae94f64145 | ||
|
|
8552a0e9eb | ||
|
|
d20420e709 | ||
|
|
e8640bdca3 | ||
|
|
e4edbf2e57 | ||
|
|
5d60e5f312 | ||
|
|
38d7da5fe5 | ||
|
|
a6b2eeb190 | ||
|
|
e12ff23e7d | ||
|
|
007a5925dc | ||
|
|
d439ed26e4 | ||
|
|
f9ff3fa23d | ||
|
|
2c64335d9c | ||
|
|
286b6b9f80 | ||
|
|
220ba993a2 | ||
|
|
3c88d6536a | ||
|
|
f49b576e93 | ||
|
|
8ec9016585 | ||
|
|
15ea6d1106 | ||
|
|
24cfda9e3c | ||
|
|
121e6e6202 | ||
|
|
1b6e16ae7c | ||
|
|
b8352f8164 | ||
|
|
6aa065b1b4 | ||
|
|
6cf29061c2 | ||
|
|
f92f0777de | ||
|
|
9c70e4bed1 | ||
|
|
a51833c51a | ||
|
|
d852d69b50 | ||
|
|
1b603069db | ||
|
|
bf4058d1df | ||
|
|
4d716b6302 | ||
|
|
1260fbc5cd | ||
|
|
acd6a22a0c | ||
|
|
4e8a1da551 | ||
|
|
754dc50b93 | ||
|
|
c7cfa75e92 | ||
|
|
b070bcd570 | ||
|
|
037d26f055 | ||
|
|
cb252296c5 | ||
|
|
f37def57b0 | ||
|
|
1a208c460b | ||
|
|
34f24b1841 | ||
|
|
1a7b944917 | ||
|
|
3b400bd64e | ||
|
|
f74baa5830 | ||
|
|
4c5b8fb6d6 | ||
|
|
d5cc5eb25c | ||
|
|
9f642e2bd4 | ||
|
|
6ca24af24a | ||
|
|
400c7c161f | ||
|
|
5567c238a7 | ||
|
|
33eba22966 | ||
|
|
282fc81981 | ||
|
|
cc1b07dcf1 | ||
|
|
0e3e8db5bf | ||
|
|
17873e8c92 | ||
|
|
80e9281701 | ||
|
|
926c477188 | ||
|
|
d999575e34 | ||
|
|
5d095e9a27 | ||
|
|
49177312fb |
151
.github/workflows/build.yml
vendored
Normal file
151
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
# Can be used locally with https://github.com/nektos/act
|
||||
|
||||
name: BuildTest
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os || 'ubuntu-20.04' }}
|
||||
strategy:
|
||||
matrix:
|
||||
# Rather than a boolean False we use eg
|
||||
# runcheck: 'no'
|
||||
# Otherwise GH expressions will make a None var
|
||||
# compare with False. We want an undefined default of True.
|
||||
|
||||
# MULTI and NOWRITEV are passed as integers to the build
|
||||
include:
|
||||
- name: plain linux
|
||||
|
||||
- name: multi binary
|
||||
multi: 1
|
||||
|
||||
- name: bundled libtom, bionic , no writev()
|
||||
# test can use an older distro with bundled libtommath
|
||||
os: ubuntu-18.04
|
||||
configure_flags: --enable-bundled-libtom --enable-werror
|
||||
# NOWRITEV is unrelated, test here to save a job
|
||||
nowritev: 1
|
||||
# our tests expect >= python3.7
|
||||
runcheck: 'no'
|
||||
|
||||
- name: linux clang
|
||||
cc: clang
|
||||
|
||||
- name: macos 10.15
|
||||
os: macos-10.15
|
||||
cc: clang
|
||||
# OS X says daemon() and utmp are deprecated
|
||||
extracflags: -Wno-deprecated-declarations
|
||||
runcheck: 'no'
|
||||
apt: 'no'
|
||||
# fails with:
|
||||
# .../ranlib: file: libtomcrypt.a(cbc_setiv.o) has no symbols
|
||||
ranlib: ranlib -no_warning_for_no_symbols
|
||||
|
||||
- name: macos 11
|
||||
os: macos-11
|
||||
cc: clang
|
||||
extracflags: -Wno-deprecated-declarations
|
||||
runcheck: 'no'
|
||||
apt: 'no'
|
||||
ranlib: ranlib -no_warning_for_no_symbols
|
||||
|
||||
# # Fuzzers run standalone. A bit superfluous with cifuzz, but
|
||||
# # good to run the whole corpus to keep it working.
|
||||
# - name: fuzzing with address sanitizer
|
||||
# configure_flags: --enable-fuzz --disable-harden --enable-bundled-libtom --enable-werror
|
||||
# ldflags: -fsanitize=address
|
||||
# extracflags: -fsanitize=address
|
||||
# fuzz: True
|
||||
# cc: clang
|
||||
|
||||
# # Undefined Behaviour sanitizer
|
||||
# - name: fuzzing with undefined behaviour sanitizer
|
||||
# configure_flags: --enable-fuzz --disable-harden --enable-bundled-libtom --enable-werror
|
||||
# ldflags: -fsanitize=undefined
|
||||
# # don't fail with alignment due to https://github.com/libtom/libtomcrypt/issues/549
|
||||
# extracflags: -fsanitize=undefined -fno-sanitize-recover=undefined -fsanitize-recover=alignment
|
||||
# fuzz: True
|
||||
# cc: clang
|
||||
|
||||
env:
|
||||
MULTI: ${{ matrix.multi }}
|
||||
CC: ${{ matrix.cc || 'gcc' }}
|
||||
LDFLAGS: ${{ matrix.ldflags }}
|
||||
EXTRACFLAGS: ${{ matrix.extracflags }}
|
||||
CONFIGURE_FLAGS: ${{ matrix.configure_flags || '--enable-werror' }}
|
||||
# for fuzzing
|
||||
CXX: clang++
|
||||
RANLIB: ${{ matrix.ranlib || 'ranlib' }}
|
||||
|
||||
steps:
|
||||
- name: deps
|
||||
if: ${{ matrix.apt != 'no' }}
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install zlib1g-dev libtomcrypt-dev libtommath-dev mercurial python3-venv $CC
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: configure
|
||||
run: ./configure $CONFIGURE_FLAGS CFLAGS="-O2 -Wall -Wno-pointer-sign $EXTRACFLAGS" --prefix="$HOME/inst" || (cat config.log; exit 1)
|
||||
|
||||
- name: nowritev
|
||||
if: ${{ matrix.nowritev }}
|
||||
run: sed -i -e s/HAVE_WRITEV/DONT_HAVE_WRITEV/ config.h
|
||||
|
||||
- name: make
|
||||
run: make -j3
|
||||
|
||||
- name: multilink
|
||||
if: ${{ matrix.multi }}
|
||||
run: make multilink
|
||||
|
||||
- name: makefuzz
|
||||
run: make fuzzstandalone
|
||||
if: ${{ matrix.fuzz }}
|
||||
|
||||
# avoid concurrent install, osx/freebsd is racey (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208093)
|
||||
- name: make install
|
||||
run: make install
|
||||
|
||||
- name: keys
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear | grep ^ecdsa > ~/.ssh/authorized_keys
|
||||
chmod 700 ~ ~/.ssh ~/.ssh/authorized_keys
|
||||
ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
|
||||
|
||||
# upload config.log if something has failed
|
||||
- name: config.log
|
||||
if: ${{ !env.ACT && (failure() || cancelled()) }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: config.log
|
||||
path: config.log
|
||||
|
||||
- name: check
|
||||
if: ${{ matrix.runcheck != 'no' }}
|
||||
run: make check
|
||||
|
||||
# Sanity check that the binary runs
|
||||
- name: genrsa
|
||||
run: ~/inst/bin/dropbearkey -t rsa -f testrsa
|
||||
- name: gendss
|
||||
run: ~/inst/bin/dropbearkey -t dss -f testdss
|
||||
- name: genecdsa256
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256
|
||||
- name: genecdsa384
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384
|
||||
- name: genecdsa521
|
||||
run: ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521
|
||||
- name: gened25519
|
||||
run: ~/inst/bin/dropbearkey -t ed25519 -f tested25519
|
||||
|
||||
- name: fuzz
|
||||
if: ${{ matrix.fuzz }}
|
||||
run: ./fuzzers_test.sh
|
||||
30
.github/workflows/cifuzz.yml
vendored
Normal file
30
.github/workflows/cifuzz.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Runs fuzzers for a little while on pull requests.
|
||||
# From https://google.github.io/oss-fuzz/getting-started/continuous-integration/
|
||||
name: CIFuzz
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'dropbear'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'dropbear'
|
||||
fuzz-seconds: 1200
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -21,7 +21,8 @@
|
||||
/scp-progress
|
||||
Makefile
|
||||
config.h
|
||||
config.h.in
|
||||
configure
|
||||
default_options_guard.h
|
||||
tags
|
||||
.pytest*
|
||||
*.pyc
|
||||
/test/venv
|
||||
|
||||
2
.hgsigs
2
.hgsigs
@@ -27,3 +27,5 @@ fd1981f41c626a969f07b4823848deaefef3c8aa 0 iQIcBAABCgAGBQJW4W2TAAoJEESTFJTynGdzu
|
||||
07b0d56d186d7eeef4106137a3eba554959ba0e3 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlyWOo8ACgkQRJMUlPKcZ3O+MQ//c5oeDUvZuFiI4FHZqfIK/59YAciTP+9TQmoWDVSuOdkd9ZYJA7b7DCusqP2TWFEIl9M7i5hTLTMD21xuEQQtfOSP6EXpUw6JNdh/lsJs7EDlFANtwkdEozAQozFKnXbJEV3y9WldEWUlmPFjt4fJQIuG10SU7MTJHcSaQddJCh3I1//F4EvgRe+OqyrFwKekGiFdvfjcIFN3lQmk6K1Sc0MgyIO/VVZm/AQpBi0Dlg0yOl+EDcxxlmeSInbvLceWSP6op35I4dE5YWH1UetjzIsr5AIM15/k3viAKDDefY1EMAzK9b7YAF4BLw0a6XoQu0apvcWaALE/bJzWNSg/QbCm2JAZzk21WLLvR+AELzPfKXrHX3o0h51lpQ4rs7EWKUm43dJPoWkcFNOU+BDsNzffcJgChbRs48ut89DYLiGmSxhRxE77VPbA+klgTGdctOTLd8psseRlGYCuGe8zeota80bV9fUZ9WJZHwNgEWGowKUoTjy6l5k9OH3iQuQX3OXoy78ufRgWDulE7noVTMhXurQ8a0Jf2k/MW9dcnqGVkWitCFKPEvZwVmWyW2AWsdMcBJnFFGzDsNSxWTtCF9XcxieDO1IB8vGwYcb1TwEVuVzvR/wwvc3PgVikF+4Qv2NqdoQc1yn2PkocY2hwXyIZUAwz7erNumlTbeC/JK8=
|
||||
ebcdb893992d286d363e60f5353d6e1401e7084b 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAlybhXAACgkQRJMUlPKcZ3O7pQ//QuNJfBVa7ROaOJOR2H/xr6PRn1Fnc6rr/GCF9cqWrbGP6wNo24dRjcu5LxviqPvzfwRXIMXwVz8L/y61/sm6XcA7VFP4+MBoltfeUOdMbfBdtwEUo3WMBdP1w2q5GgYj8ZY6MawiLEqFba5aua7dokTNBOQM3Yebj+9I16MiWEaRSnuwYPoieHW2Fo6oftcIgs/GCXwT2xYzc0n3FpYAbK7u6sEkpL16EstV0Y/G70+X1/4Mg3GM96S5fl9Zbun47W7/+gT4AQVQjE+UnPNDudObAe+2BaOZLFvEbd7iJBBcqtjpBktuP58IEAb3A3srUCy49LNLWk43lj+PtoslK/U6TShKQ2vAgfd//bbn6ieXFJY8N+wYPpJo1m7zpTiEtS7J7wu6vkGGZlqUAj6MHXZj223CgazhSAlg/XFPs9oz3Y96c33Tnd4jB9iEXNNt5jzCAMImx2huSGgnP0JFAbcniq/ug5tl1VWaracvSuJl7fmf17DbmehsLbvtZBoMlePY7Ssfb5IokfVvptt4zRpRZnjtWfHCjtC6zYhtvXTmXH/bqWwx9MMjOf5WPfZoCMvXfMqdVI15FVbxU15WnqjvdvKUCkdz1aMFzxqc4MXgyvjtB9CvO/8WwBOJ2m2nDdiZfh8/H8SawYqEHgB61FX5xA5aXecgXcjQnqWDDxw=
|
||||
4877afd51e041eca7749cc46b57fd80aa23815b4 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl7nmREACgkQRJMUlPKcZ3PG1BAAnUl0/nTnQ3CMM3S72DT1JQ1eDxZa14r6r1xEPngU83hNNzmPcnfiMDts+Vz1M3PLxNNOXVVt/MTw04+V9joPhhSWEe8O1pd3lAqTPswL7hhIEbVwZwyFCuAV4iAm+tHKzKLjtjgZfMgij6XylOmw18VBw5R+suoOMclJqeHlJ5m0Mq2wRLDE+RdVCAkulTqhGYjJNQUXMMNPx/cxUo3NHsto9pWL3d1285vBByP6BQSaeYlO012InvJRlQuEkK3lnIyzq6voIc6+tMli0q9iyBz+2GIloBQNAnb6EGaXxqAOBW5NRc+/Oauiu8Yf/6JoFlkAIcPXmGRtxiAiynJImhiTaCFdgdxaXLFzjBvq+tcwVXvvNM52fOZ4Z3QgMDu6EgNWfma0lsg4T3ar2ml2/evuWeLVut5ZmYFHarTFX+/pTVy9nAZK/F5ROJM1prTNYI18PZV4qvULta8spGV2Be0rCkQQubp9RWdKHNGZE70lrX5OnNIwE/D3g2QE04243i0IGBwhlDEpYjqujLyHk8W6XE1CORx0hQ0fUjzKZsRvOB7XyMAFpQUVOhoMFcnk5XHDW6B/U7NAxzqNqO+gbHO/UIeuy/KOVlMNJCmtRL/HYNGZ6SCZbRpyX3d8Ow0sasNfJkZrT6a0Tf6lZktWOxtPkoEDLfuCzudzn4JxGQM=
|
||||
88f63b8b0f131f24aa90c9b852622b922b1ad738 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl71/sAACgkQRJMUlPKcZ3OlSQ/9GYLotOmsYK0gvSfWLYR9a8WGgT/4EU6RgAkMBLS9TBp0E3V4VUDralnqoId7hNO2cUkRS7boOM2g4/YRShah8gonSJa70lKjUpDeQUPuGwUYWLNKr9qxJtnAcd1rOE4WYxKEUfjPWHBbVsT3QIIdj1Zy31GDKZgELRBQeOyt62RdXYHMaMHHDgg2U/wO9bcRRe5G7mYJf7Vm8sAWyTZXvta2jORxgs4XxWe7xJ9Dj0lMSG5HmfvH5NrGHM1GK3pL0GREKj2+xNSFdkSeHIgSSoHM2qZTVSWtNfx0+fZaRBgvXPPYzDTTghj1mKEaPFoRzg/B8s+NmHupJftT1yyapKFjALo1N6eaPHRRSwVfmnoWSJLu4fwL8TK5wMJr9eGl3QgAnperQPEFT9UHJBIwZ1D+RMuI3pEESdHBJFAYIAyisJI6XyzMhLsysoShlHs6OjFcJ9jTe4pzg9pO+KaPbLYsBJxJUsrtHwV8P9CHxY6CEuKm0AZjYDopYhzLuAUjGJjYDf/C9vJ/xtTOqIm9nywfcFwqgLrmQFhNHHGyOJVr+y/cey1sT9E4/gBv9kor+6qSITALv2g0JTaOpzpkE0zbafUy2r777Wex4WNQEha6bYZFi2aiqxqqX93UHzv+YhmN8n9mlc21xoZMPNtAb2mSxx7rO+PScb5uflKOCYE=
|
||||
5879c5829e8569466386e7c64252b01b99705628 0 iQIzBAABCgAdFiEE9zR+8u4uB6JnYoypRJMUlPKcZ3MFAl+axlIACgkQRJMUlPKcZ3PZuhAAkzCj+lOt2hHigIHB0zkNUC9nRIE1TItJD4wqQ03nMY4ycBMsb74o1AHsQTtVG6sm2YGSmQuZ0VxG1iuW9nKTsM1hzB40G45i5waIEzxVG8PbZ2i6zLK2Xz2YQ+FBvIg1EKfH7Dyd3r4FqYxauGOQdrUiKwuc3H4r65HpUmT0tIypqahFoRmj1+K/ZSPak0+ZPL27VQ4b/Ts8QS7XwFYTZsMDovYNdFJmaMhBbBe33/zGFWBPk6NCJWrBd3jmJN/LhZp0a5T4fAZ6iA2WjXDWOSiWZaLLk49zM6WYrc4QihEj7ngecj/UUXKR/sWPva8+rHf9YQLZu2lc6IMABCpUkeKLFoJqzvnKGA2rhl1LpRcnNA30/7yJt0YhfFcKhBkjjSxiOH3v0qMPADHMo5poqCKH/x4TVGVyVgzCqcxd+AzsDu77fzfzbxlyQ7wp+VmwXmeHbPfuBc8u9HUBa6Fc4b667aDD26a2S9VKdRYuSp3DkOwCLJUmRqmw+sXKvXlPyxPMUxOi/4R5nbJacD5Js1AH7WH49pAFMJ6bDCQ8QEmOh+Qpqc3RzTBwt1CLl+zt0NLKDmRYSgAY9GZpuju7r+aj2Semjd7nwmq4Y5xtWCh673lea/n7JS0mtBWouVbGgMJErg7QjuqOS3oE77viLcGLpX9niDcGvCL/N3gE13A=
|
||||
|
||||
2
.hgtags
2
.hgtags
@@ -59,3 +59,5 @@ c31276613181c5cff7854e7ef586ace03424e55e DROPBEAR_2017.75
|
||||
6d1bbe7d5fa5827c7eae28bca044d691f7efa785 DROPBEAR_2019.77
|
||||
009d52ae26d35f3381c801e02318fa9be34be93c DROPBEAR_2019.78
|
||||
e2e4929d057b09422f2ea4556fb64209aff58161 DROPBEAR_2020.79
|
||||
73646de50f1351735c868d4874f058ff9ad62c96 DROPBEAR_2020.80
|
||||
4b984c42372d01fcc2fd487c58af6a5aa65eb88e DROPBEAR_2020.81
|
||||
|
||||
72
.travis.yml
72
.travis.yml
@@ -1,72 +0,0 @@
|
||||
language: c
|
||||
|
||||
git:
|
||||
depth: 3
|
||||
|
||||
# use focal which provides libtommath 1.20
|
||||
dist: focal
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- name: "plain linux"
|
||||
compiler: gcc
|
||||
env: WEXTRAFLAGS=-Werror
|
||||
- name: "multi binary"
|
||||
env: MULTI=1 WEXTRAFLAGS=-Werror
|
||||
- name: "bundled libtom, xenial, no writev()"
|
||||
# NOWRITEV is unrelated to libtom/xenial, test here to save a job
|
||||
env: CONFIGURE_FLAGS=--enable-bundled-libtom WEXTRAFLAGS=-Werror NOWRITEV=1
|
||||
# can use an older distro with bundled libtom
|
||||
dist: xenial
|
||||
- name: "linux clang"
|
||||
os: linux
|
||||
compiler: clang
|
||||
env: WEXTRAFLAGS=-Werror
|
||||
- name: "osx"
|
||||
os: osx
|
||||
compiler: clang
|
||||
# OS X says daemon() and utmp are deprecated
|
||||
env: WEXTRAFLAGS="-Wno-deprecated-declarations -Werror"
|
||||
# Note: the fuzzing malloc wrapper doesn't replace free() in system libtomcrypt, so need bundled.
|
||||
- name: "fuzzing"
|
||||
env: DO_FUZZ=1 CONFIGURE_FLAGS="--enable-fuzz --disable-harden --enable-bundled-libtom" WEXTRAFLAGS=-Werror LDFLAGS=-fsanitize=address EXTRACFLAGS=-fsanitize=address CXX=clang++
|
||||
compiler: clang
|
||||
|
||||
# container-based builds
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
|
||||
- zlib1g-dev
|
||||
- libtomcrypt-dev
|
||||
- libtommath-dev
|
||||
- mercurial
|
||||
|
||||
before_install:
|
||||
- if [ "$CC" = "clang" ]; then WEXTRAFLAGS="$WEXTRAFLAGS -Wno-error=incompatible-library-redeclaration" ; fi # workaround
|
||||
|
||||
install:
|
||||
- autoconf
|
||||
- autoheader
|
||||
- ./configure $CONFIGURE_FLAGS CFLAGS="-O2 -Wall -Wno-pointer-sign $WEXTRAFLAGS $EXTRACFLAGS" --prefix="$HOME/inst" || (cat config.log; exit 1)
|
||||
- if [ "$NOWRITEV" = "1" ]; then sed -i -e s/HAVE_WRITEV/DONT_HAVE_WRITEV/ config.h ; fi
|
||||
- make lint
|
||||
- make -j3
|
||||
- test -z $DO_FUZZ || make fuzzstandalone
|
||||
# avoid concurrent install, osx/freebsd is racey (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208093)
|
||||
- make install
|
||||
|
||||
script:
|
||||
- ~/inst/bin/dropbearkey -t rsa -f testrsa
|
||||
- ~/inst/bin/dropbearkey -t dss -f testdss
|
||||
- ~/inst/bin/dropbearkey -t ecdsa -f testec256 -s 256
|
||||
- ~/inst/bin/dropbearkey -t ecdsa -f testec384 -s 384
|
||||
- ~/inst/bin/dropbearkey -t ecdsa -f testec521 -s 521
|
||||
- ~/inst/bin/dropbearkey -t ed25519 -f tested25519
|
||||
- test -z $DO_FUZZ || ./fuzzers_test.sh
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- coverity
|
||||
|
||||
41
CHANGES
41
CHANGES
@@ -1,3 +1,22 @@
|
||||
2020.81 - 29 October 2020
|
||||
|
||||
- Fix regression in 2020.79 which prevented connecting with some SSH
|
||||
implementations. Increase MAX_PROPOSED_ALGO to 50, and print a log
|
||||
message if the limit is hit. This fixes interoperability with sshj
|
||||
library (used by PyCharm), and GoAnywhere.
|
||||
Reported by Pirmin Walthert and Piotr Jurkiewicz
|
||||
|
||||
- Fix building with non-GCC compilers, reported by Kazuo Kuroi
|
||||
|
||||
- Fix potential long delay in dbclient, found by OSS Fuzz
|
||||
|
||||
- Fix null pointer dereference crash, found by OSS Fuzz
|
||||
|
||||
- libtommath now uses the same random source as Dropbear (in 2020.79
|
||||
and 2020.80 used getrandom() separately)
|
||||
|
||||
- Some fuzzing improvements, start of a dbclient fuzzer
|
||||
|
||||
2020.80 - 26 June 2020
|
||||
|
||||
- Don't block authorized_keys logins with no-X11-forwarding or no-agent-forwarding
|
||||
@@ -215,7 +234,7 @@
|
||||
dropbear is running with -a (Allow connections to forwarded ports from any host)
|
||||
This could potentially allow arbitrary code execution as root by an authenticated user.
|
||||
Affects versions 2013.56 to 2016.74. Thanks to Mark Shepard for reporting the crash.
|
||||
CVE-2017-9078 https://secure.ucc.asn.au/hg/dropbear/rev/c8114a48837c
|
||||
CVE-2017-9078 https://hg.ucc.asn.au/dropbear/rev/c8114a48837c
|
||||
|
||||
- Security: Fix information disclosure with ~/.ssh/authorized_keys symlink.
|
||||
Dropbear parsed authorized_keys as root, even if it were a symlink. The fix
|
||||
@@ -227,7 +246,7 @@
|
||||
contents of that file.
|
||||
This information disclosure is to an already authenticated user.
|
||||
Thanks to Jann Horn of Google Project Zero for reporting this.
|
||||
CVE-2017-9079 https://secure.ucc.asn.au/hg/dropbear/rev/0d889b068123
|
||||
CVE-2017-9079 https://hg.ucc.asn.au/dropbear/rev/0d889b068123
|
||||
|
||||
- Generate hostkeys with dropbearkey atomically and flush to disk with fsync
|
||||
Thanks to Andrei Gherzan for a patch
|
||||
@@ -247,23 +266,23 @@
|
||||
run arbitrary code as the dbclient user. This could be a problem if scripts
|
||||
or webpages pass untrusted input to the dbclient program.
|
||||
CVE-2016-7406
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/b66a483f3dcb
|
||||
https://hg.ucc.asn.au/dropbear/rev/b66a483f3dcb
|
||||
|
||||
- Security: dropbearconvert import of OpenSSH keys could run arbitrary code as
|
||||
the local dropbearconvert user when parsing malicious key files
|
||||
CVE-2016-7407
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/34e6127ef02e
|
||||
https://hg.ucc.asn.au/dropbear/rev/34e6127ef02e
|
||||
|
||||
- Security: dbclient could run arbitrary code as the local dbclient user if
|
||||
particular -m or -c arguments are provided. This could be an issue where
|
||||
dbclient is used in scripts.
|
||||
CVE-2016-7408
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/eed9376a4ad6
|
||||
https://hg.ucc.asn.au/dropbear/rev/eed9376a4ad6
|
||||
|
||||
- Security: dbclient or dropbear server could expose process memory to the
|
||||
running user if compiled with DEBUG_TRACE and running with -v
|
||||
CVE-2016-7409
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/6a14b1f6dc04
|
||||
https://hg.ucc.asn.au/dropbear/rev/6a14b1f6dc04
|
||||
|
||||
The security issues were reported by an anonymous researcher working with
|
||||
Beyond Security's SecuriTeam Secure Disclosure www.beyondsecurity.com/ssd.html
|
||||
@@ -309,7 +328,7 @@
|
||||
|
||||
- Validate X11 forwarding input. Could allow bypass of authorized_keys command= restrictions,
|
||||
found by github.com/tintinweb. Thanks for Damien Miller for a patch. CVE-2016-3116
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/a3e8389e01ff
|
||||
https://hg.ucc.asn.au/dropbear/rev/a3e8389e01ff
|
||||
|
||||
2015.71 - 3 December 2015
|
||||
|
||||
@@ -590,11 +609,11 @@ kernels, from Steve Dover
|
||||
- Limit the size of decompressed payloads, avoids memory exhaustion denial
|
||||
of service
|
||||
Thanks to Logan Lamb for reporting and investigating it. CVE-2013-4421
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/0bf76f54de6f
|
||||
https://hg.ucc.asn.au/dropbear/rev/0bf76f54de6f
|
||||
|
||||
- Avoid disclosing existence of valid users through inconsistent delays
|
||||
Thanks to Logan Lamb for reporting. CVE-2013-4434
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/d7784616409a
|
||||
https://hg.ucc.asn.au/dropbear/rev/d7784616409a
|
||||
|
||||
- Update config.guess and config.sub for newer architectures
|
||||
|
||||
@@ -697,7 +716,7 @@ though probably will be soon
|
||||
This bug affects releases 0.52 onwards. Ref CVE-2012-0920.
|
||||
Thanks to Danny Fullerton of Mantor Organization for reporting
|
||||
the bug.
|
||||
https://secure.ucc.asn.au/hg/dropbear/rev/818108bf7749
|
||||
https://hg.ucc.asn.au/dropbear/rev/818108bf7749
|
||||
|
||||
- Compile fix, only apply IPV6 socket options if they are available in headers
|
||||
Thanks to Gustavo Zacarias for the patch
|
||||
@@ -741,7 +760,7 @@ though probably will be soon
|
||||
- New version numbering scheme.
|
||||
|
||||
Source repository has now migrated to Mercurial at
|
||||
https://secure.ucc.asn.au/hg/dropbear/graph/default
|
||||
https://hg.ucc.asn.au/dropbear/graph/default
|
||||
|
||||
0.53.1 - Wednesday 2 March 2011
|
||||
|
||||
|
||||
4
INSTALL
4
INSTALL
@@ -6,12 +6,12 @@ Basic Dropbear build instructions:
|
||||
localoptions.h should be located in the build directory if you are
|
||||
building out of tree.
|
||||
|
||||
- If using a Mercurial or Git checkout, "autoconf; autoheader"
|
||||
|
||||
- Configure for your system:
|
||||
./configure (optionally with --disable-zlib or --disable-syslog,
|
||||
or --help for other options)
|
||||
|
||||
(you'll need to first run "autoconf; autoheader" if you edit configure.ac)
|
||||
|
||||
- Compile:
|
||||
|
||||
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
|
||||
|
||||
69
Makefile.in
69
Makefile.in
@@ -35,8 +35,8 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
|
||||
signkey.o rsa.o dbrandom.o \
|
||||
queue.o \
|
||||
atomicio.o compat.o fake-rfc2553.o \
|
||||
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
|
||||
curve25519.o ed25519.o \
|
||||
ltc_prng.o ecc.o ecdsa.o sk-ecdsa.o crypto_desc.o \
|
||||
curve25519.o ed25519.o sk-ed25519.o \
|
||||
dbmalloc.o \
|
||||
gensignkey.o gendss.o genrsa.o gened25519.o
|
||||
|
||||
@@ -62,10 +62,9 @@ CONVERTOBJS=dropbearconvert.o keyimport.o
|
||||
SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
|
||||
|
||||
ifeq (@DROPBEAR_FUZZ@, 1)
|
||||
allobjs = $(COMMONOBJS) fuzz-common.o fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@
|
||||
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:=$(sort $(allobjs))
|
||||
|
||||
dropbearobjs=$(allobjs) svr-main.o
|
||||
dbclientobjs=$(allobjs) cli-main.o
|
||||
@@ -73,6 +72,7 @@ ifeq (@DROPBEAR_FUZZ@, 1)
|
||||
dropbearconvertobjs=$(allobjs) $(CONVERTOBJS)
|
||||
# CXX only set when fuzzing
|
||||
CXX=@CXX@
|
||||
FUZZ_CLEAN=fuzz-clean
|
||||
else
|
||||
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
|
||||
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
|
||||
@@ -236,7 +236,7 @@ $(STATIC_LTC): $(OPTION_HEADERS)
|
||||
$(STATIC_LTM): $(OPTION_HEADERS)
|
||||
$(MAKE) -C libtommath
|
||||
|
||||
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint
|
||||
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint check
|
||||
|
||||
ltc-clean:
|
||||
$(MAKE) -C libtomcrypt clean
|
||||
@@ -247,7 +247,7 @@ ltm-clean:
|
||||
sizes: dropbear
|
||||
objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn
|
||||
|
||||
clean: $(LIBTOM_CLEAN) thisclean
|
||||
clean: $(LIBTOM_CLEAN) $(FUZZ_CLEAN) thisclean
|
||||
|
||||
thisclean:
|
||||
-rm -f dropbear$(EXEEXT) dbclient$(EXEEXT) dropbearkey$(EXEEXT) \
|
||||
@@ -265,50 +265,46 @@ tidy:
|
||||
lint:
|
||||
cd $(srcdir); ./dropbear_lint.sh
|
||||
|
||||
check: lint
|
||||
make -C test
|
||||
|
||||
## Fuzzing targets
|
||||
|
||||
# list of fuzz targets
|
||||
FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519
|
||||
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_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
|
||||
FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \
|
||||
fuzz/fuzz-sshpacketmutator.o
|
||||
|
||||
list-fuzz-targets:
|
||||
@echo $(FUZZ_TARGETS)
|
||||
|
||||
# fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs
|
||||
fuzzstandalone: FUZZLIB=fuzz-harness.o
|
||||
fuzzstandalone: fuzz-harness.o fuzz-targets
|
||||
fuzzstandalone: FUZZLIB=fuzz/fuzz-harness.o
|
||||
fuzzstandalone: fuzz/fuzz-harness.o fuzz-targets
|
||||
|
||||
# exclude svr-main.o to avoid duplicate main
|
||||
svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs))
|
||||
|
||||
fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) fuzz-common.o
|
||||
|
||||
# build all the fuzzers. This will require fail to link unless built with
|
||||
# make fuzz-targets FUZZLIB=-lFuzzer.a
|
||||
# or similar - the library provides main().
|
||||
# Build all the fuzzers. Usually like
|
||||
# make fuzz-targets FUZZLIB=-lFuzzer.a
|
||||
# the library provides main(). Otherwise
|
||||
# make fuzzstandalone
|
||||
# provides a main in fuzz-harness.c
|
||||
fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
|
||||
|
||||
fuzzer-preauth: fuzzer-preauth.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
$(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS)
|
||||
$(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
# fuzzers that use the custom mutator - these expect a SSH network stream
|
||||
MUTATOR_FUZZERS=fuzzer-client fuzzer-client_nomaths \
|
||||
fuzzer-preauth fuzzer-preauth_nomaths fuzzer-postauth_nomaths
|
||||
|
||||
fuzzer-pubkey: fuzzer-pubkey.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-verify: fuzzer-verify.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-kexdh: fuzzer-kexdh.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-kexecdh: fuzzer-kexecdh.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
|
||||
fuzzer-kexcurve25519: fuzzer-kexcurve25519.o fuzz-harness.o
|
||||
$(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
|
||||
# Skip custom mutators for -fsanitize-memory since libfuzzer doesn't initialise memory
|
||||
# Pending fix for it https://github.com/google/oss-fuzz/issues/4605
|
||||
ifeq (,$(findstring fsanitize=memory, $(CFLAGS)))
|
||||
$(MUTATOR_FUZZERS): allobjs += fuzz/fuzz-sshpacketmutator.o
|
||||
endif
|
||||
|
||||
fuzzer-%.options: Makefile
|
||||
echo "[libfuzzer]" > $@
|
||||
@@ -326,3 +322,6 @@ fuzz-hostkeys:
|
||||
/usr/bin/xxd -i -a keye >> hostkeys.c
|
||||
/usr/bin/xxd -i -a keyd >> hostkeys.c
|
||||
/usr/bin/xxd -i -a keyed25519 >> hostkeys.c
|
||||
|
||||
fuzz-clean:
|
||||
-rm -f fuzz/*.o $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
|
||||
|
||||
1
auth.h
1
auth.h
@@ -30,7 +30,6 @@
|
||||
#include "chansession.h"
|
||||
|
||||
void svr_authinitialise(void);
|
||||
void cli_authinitialise(void);
|
||||
|
||||
/* Server functions */
|
||||
void recv_msg_userauth_request(void);
|
||||
|
||||
33
buffer.c
33
buffer.c
@@ -39,44 +39,30 @@
|
||||
|
||||
/* Create (malloc) a new buffer of size */
|
||||
buffer* buf_new(unsigned int size) {
|
||||
|
||||
buffer* buf;
|
||||
|
||||
if (size > BUF_MAX_SIZE) {
|
||||
dropbear_exit("buf->size too big");
|
||||
}
|
||||
|
||||
buf = (buffer*)m_malloc(sizeof(buffer)+size);
|
||||
|
||||
if (size > 0) {
|
||||
buf->data = (unsigned char*)buf + sizeof(buffer);
|
||||
} else {
|
||||
buf->data = NULL;
|
||||
}
|
||||
|
||||
buf->data = (unsigned char*)buf + sizeof(buffer);
|
||||
buf->size = size;
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* free the buffer's data and the buffer itself */
|
||||
void buf_free(buffer* buf) {
|
||||
|
||||
m_free(buf);
|
||||
}
|
||||
|
||||
/* overwrite the contents of the buffer to clear it */
|
||||
void buf_burn(const buffer* buf) {
|
||||
|
||||
m_burn(buf->data, buf->size);
|
||||
|
||||
}
|
||||
|
||||
/* resize a buffer, pos and len will be repositioned if required when
|
||||
* downsizing */
|
||||
buffer* buf_resize(buffer *buf, unsigned int newsize) {
|
||||
|
||||
if (newsize > BUF_MAX_SIZE) {
|
||||
dropbear_exit("buf->size too big");
|
||||
}
|
||||
@@ -139,18 +125,23 @@ void buf_incrwritepos(buffer* buf, unsigned int incr) {
|
||||
}
|
||||
}
|
||||
|
||||
/* increment the position by incr, negative values are allowed, to
|
||||
* decrement the pos*/
|
||||
void buf_incrpos(buffer* buf, int incr) {
|
||||
/* increment the position by incr */
|
||||
void buf_incrpos(buffer* buf, unsigned int incr) {
|
||||
if (incr > BUF_MAX_INCR
|
||||
|| incr < -BUF_MAX_INCR
|
||||
|| (unsigned int)((int)buf->pos + incr) > buf->len
|
||||
|| ((int)buf->pos + incr) < 0) {
|
||||
|| (buf->pos + incr) > buf->len) {
|
||||
dropbear_exit("Bad buf_incrpos");
|
||||
}
|
||||
buf->pos += incr;
|
||||
}
|
||||
|
||||
/* decrement the position by decr */
|
||||
void buf_decrpos(buffer* buf, unsigned int decr) {
|
||||
if (decr > buf->pos) {
|
||||
dropbear_exit("Bad buf_decrpos");
|
||||
}
|
||||
buf->pos -= decr;
|
||||
}
|
||||
|
||||
/* Get a byte from the buffer and increment the pos */
|
||||
unsigned char buf_getbyte(buffer* buf) {
|
||||
|
||||
|
||||
3
buffer.h
3
buffer.h
@@ -49,7 +49,8 @@ buffer* buf_newcopy(const buffer* buf);
|
||||
void buf_setlen(buffer* buf, unsigned int len);
|
||||
void buf_incrlen(buffer* buf, unsigned int incr);
|
||||
void buf_setpos(buffer* buf, unsigned int pos);
|
||||
void buf_incrpos(buffer* buf, int incr); /* -ve is ok, to go backwards */
|
||||
void buf_incrpos(buffer* buf, unsigned int incr);
|
||||
void buf_decrpos(buffer* buf, unsigned int decr);
|
||||
void buf_incrwritepos(buffer* buf, unsigned int incr);
|
||||
unsigned char buf_getbyte(buffer* buf);
|
||||
unsigned char buf_getbool(buffer* buf);
|
||||
|
||||
15
channel.h
15
channel.h
@@ -60,6 +60,9 @@ struct Channel {
|
||||
int readfd; /* read from insecure side, written to wire */
|
||||
int errfd; /* used like writefd or readfd, depending if it's client or server.
|
||||
Doesn't exactly belong here, but is cleaner here */
|
||||
int bidir_fd; /* a boolean indicating that writefd/readfd are the same
|
||||
file descriptor (bidirectional), such as a network socket or PTY.
|
||||
That is handled differently when closing FDs */
|
||||
circbuffer *writebuf; /* data from the wire, for local consumption. Can be
|
||||
initially NULL */
|
||||
circbuffer *extrabuf; /* extended-data for the program - used like writebuf
|
||||
@@ -68,6 +71,9 @@ struct Channel {
|
||||
/* whether close/eof messages have been exchanged */
|
||||
int sent_close, recv_close;
|
||||
int recv_eof, sent_eof;
|
||||
/* once flushing is set, readfd will close once no more data is available
|
||||
(not waiting for EOF) */
|
||||
int flushing;
|
||||
|
||||
struct dropbear_progress_connection *conn_pending;
|
||||
int initconn; /* used for TCP forwarding, whether the channel has been
|
||||
@@ -77,8 +83,6 @@ struct Channel {
|
||||
for this channel (and are awaiting a confirmation
|
||||
or failure). */
|
||||
|
||||
int flushing;
|
||||
|
||||
/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
|
||||
void (*read_mangler)(const struct Channel*, const unsigned char* bytes, int *len);
|
||||
|
||||
@@ -89,13 +93,12 @@ struct Channel {
|
||||
|
||||
struct ChanType {
|
||||
|
||||
int sepfds; /* Whether this channel has separate pipes for in/out or not */
|
||||
const char *name;
|
||||
/* Sets up the channel */
|
||||
int (*inithandler)(struct Channel*);
|
||||
/* Called to check whether a channel should close, separately from the FD being closed.
|
||||
/* Called to check whether a channel should close, separately from the FD being EOF.
|
||||
Used for noticing process exiting */
|
||||
int (*check_close)(const struct Channel*);
|
||||
int (*check_close)(struct Channel*);
|
||||
/* Handler for ssh_msg_channel_request */
|
||||
void (*reqhandler)(struct Channel*);
|
||||
/* Called prior to sending ssh_msg_channel_close, used for sending exit status */
|
||||
@@ -104,7 +107,7 @@ struct ChanType {
|
||||
void (*cleanup)(const struct Channel*);
|
||||
};
|
||||
|
||||
/* Callback for connect_remote */
|
||||
/* Callback for connect_remote. 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[]);
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
static int new_agent_chan(struct Channel * channel);
|
||||
|
||||
const struct ChanType cli_chan_agent = {
|
||||
0, /* sepfds */
|
||||
"auth-agent@openssh.com",
|
||||
new_agent_chan,
|
||||
NULL,
|
||||
@@ -94,6 +93,7 @@ static int new_agent_chan(struct Channel * channel) {
|
||||
|
||||
channel->readfd = fd;
|
||||
channel->writefd = fd;
|
||||
channel->bidir_fd = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,12 +32,6 @@
|
||||
#include "packet.h"
|
||||
#include "runopts.h"
|
||||
|
||||
void cli_authinitialise() {
|
||||
|
||||
memset(&ses.authstate, 0, sizeof(ses.authstate));
|
||||
}
|
||||
|
||||
|
||||
/* Send a "none" auth request to get available methods */
|
||||
void cli_auth_getmethods() {
|
||||
TRACE(("enter cli_auth_getmethods"))
|
||||
@@ -267,6 +261,9 @@ void recv_msg_userauth_success() {
|
||||
if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
|
||||
|
||||
TRACE(("received msg_userauth_success"))
|
||||
if (cli_opts.disable_trivial_auth && cli_ses.is_trivial_auth) {
|
||||
dropbear_exit("trivial authentication not allowed");
|
||||
}
|
||||
/* Note: in delayed-zlib mode, setting authdone here
|
||||
* will enable compression in the transport layer */
|
||||
ses.authstate.authdone = 1;
|
||||
|
||||
@@ -114,6 +114,7 @@ void recv_msg_userauth_info_request() {
|
||||
m_free(instruction);
|
||||
|
||||
for (i = 0; i < num_prompts; i++) {
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
unsigned int response_len = 0;
|
||||
prompt = buf_getstring(ses.payload, NULL);
|
||||
cleantext(prompt);
|
||||
|
||||
@@ -155,7 +155,7 @@ void cli_auth_password() {
|
||||
|
||||
encrypt_packet();
|
||||
m_burn(password, strlen(password));
|
||||
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
TRACE(("leave cli_auth_password"))
|
||||
}
|
||||
#endif /* DROPBEAR_CLI_PASSWORD_AUTH */
|
||||
|
||||
@@ -125,7 +125,7 @@ void recv_msg_userauth_pk_ok() {
|
||||
static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
|
||||
const buffer *data_buf) {
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
// TODO: rsa-sha256 agent
|
||||
/* TODO: rsa-sha256 agent */
|
||||
if (key->source == SIGNKEY_SOURCE_AGENT) {
|
||||
/* Format the agent signature ourselves, as buf_put_sign would. */
|
||||
buffer *sigblob;
|
||||
@@ -176,6 +176,7 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype,
|
||||
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
|
||||
cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf);
|
||||
buf_free(sigbuf); /* Nothing confidential in the buffer */
|
||||
cli_ses.is_trivial_auth = 0;
|
||||
}
|
||||
|
||||
encrypt_packet();
|
||||
|
||||
@@ -46,7 +46,6 @@ static int cli_init_netcat(struct Channel *channel);
|
||||
static void cli_tty_setup(void);
|
||||
|
||||
const struct ChanType clichansess = {
|
||||
0, /* sepfds */
|
||||
"session", /* name */
|
||||
cli_initchansess, /* inithandler */
|
||||
NULL, /* checkclosehandler */
|
||||
@@ -344,6 +343,7 @@ static int cli_init_stdpipe_sess(struct Channel *channel) {
|
||||
setnonblocking(STDERR_FILENO);
|
||||
|
||||
channel->extrabuf = cbuf_new(opts.recv_window);
|
||||
channel->bidir_fd = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,6 @@ static int cli_initchansess(struct Channel *channel) {
|
||||
#if DROPBEAR_CLI_NETCAT
|
||||
|
||||
static const struct ChanType cli_chan_netcat = {
|
||||
0, /* sepfds */
|
||||
"direct-tcpip",
|
||||
cli_init_netcat, /* inithandler */
|
||||
NULL,
|
||||
|
||||
13
cli-kex.c
13
cli-kex.c
@@ -46,6 +46,13 @@ void send_msg_kexdh_init() {
|
||||
TRACE(("send_msg_kexdh_init()"))
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
|
||||
switch (ses.newkeys->algo_kex->mode) {
|
||||
#if DROPBEAR_NORMAL_DH
|
||||
@@ -98,6 +105,12 @@ void recv_msg_kexdh_reply() {
|
||||
unsigned char* keyblob = NULL;
|
||||
|
||||
TRACE(("enter recv_msg_kexdh_reply"))
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing && fuzz.skip_kexmaths) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cli_ses.kex_state != KEXDH_INIT_SENT) {
|
||||
dropbear_exit("Received out-of-order kexdhreply");
|
||||
|
||||
59
cli-main.c
59
cli-main.c
@@ -31,9 +31,7 @@
|
||||
#include "dbrandom.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "netio.h"
|
||||
|
||||
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
|
||||
static void cli_dropbear_log(int priority, const char* format, va_list param);
|
||||
#include "fuzz.h"
|
||||
|
||||
#if DROPBEAR_CLI_PROXYCMD
|
||||
static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out);
|
||||
@@ -49,6 +47,7 @@ int main(int argc, char ** argv) {
|
||||
|
||||
int sock_in, sock_out;
|
||||
struct dropbear_progress_connection *progress = NULL;
|
||||
pid_t proxy_cmd_pid = 0;
|
||||
|
||||
_dropbear_exit = cli_dropbear_exit;
|
||||
_dropbear_log = cli_dropbear_log;
|
||||
@@ -73,7 +72,6 @@ int main(int argc, char ** argv) {
|
||||
dropbear_exit("signal() error");
|
||||
}
|
||||
|
||||
pid_t proxy_cmd_pid = 0;
|
||||
#if DROPBEAR_CLI_PROXYCMD
|
||||
if (cli_opts.proxycmd) {
|
||||
cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid);
|
||||
@@ -98,58 +96,6 @@ int main(int argc, char ** argv) {
|
||||
}
|
||||
#endif /* DBMULTI stuff */
|
||||
|
||||
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
char exitmsg[150];
|
||||
char fullmsg[300];
|
||||
|
||||
/* Note that exit message must be rendered before session cleanup */
|
||||
|
||||
/* Render the formatted exit message */
|
||||
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
|
||||
TRACE(("Exited, cleaning up: %s", exitmsg))
|
||||
|
||||
/* Add the prefix depending on session/auth state */
|
||||
if (!ses.init_done) {
|
||||
snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
|
||||
} else {
|
||||
snprintf(fullmsg, sizeof(fullmsg),
|
||||
"Connection to %s@%s:%s exited: %s",
|
||||
cli_opts.username, cli_opts.remotehost,
|
||||
cli_opts.remoteport, exitmsg);
|
||||
}
|
||||
|
||||
/* Do the cleanup first, since then the terminal will be reset */
|
||||
session_cleanup();
|
||||
/* Avoid printing onwards from terminal cruft */
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
dropbear_log(LOG_INFO, "%s", fullmsg);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static void cli_dropbear_log(int priority,
|
||||
const char* format, va_list param) {
|
||||
|
||||
char printbuf[1024];
|
||||
const char *name;
|
||||
|
||||
name = cli_opts.progname;
|
||||
if (!name) {
|
||||
name = "dbclient";
|
||||
}
|
||||
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
|
||||
#ifndef DISABLE_SYSLOG
|
||||
if (opts.usingsyslog) {
|
||||
syslog(priority, "%s", printbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "%s: %s\n", name, printbuf);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
static void exec_proxy_cmd(const void *user_data_cmd) {
|
||||
const char *cmd = user_data_cmd;
|
||||
char *usershell;
|
||||
@@ -199,4 +145,5 @@ static void kill_proxy_sighandler(int UNUSED(signo)) {
|
||||
kill_proxy_command();
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_CLI_PROXYCMD */
|
||||
|
||||
@@ -79,7 +79,7 @@ static void printhelp() {
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
"-R <[listenaddress:]listenport:remotehost:remoteport> Remote port forwarding\n"
|
||||
#endif
|
||||
"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
|
||||
"-W <receive_window_buffer> (default %d, larger may be faster, max 10MB)\n"
|
||||
"-K <keepalive> (0 is never, default %d)\n"
|
||||
"-I <idle_timeout> (0 is never, default %d)\n"
|
||||
#if DROPBEAR_CLI_NETCAT
|
||||
@@ -152,6 +152,7 @@ void cli_getopts(int argc, char ** argv) {
|
||||
#if DROPBEAR_CLI_ANYTCPFWD
|
||||
cli_opts.exit_on_fwd_failure = 0;
|
||||
#endif
|
||||
cli_opts.disable_trivial_auth = 0;
|
||||
#if DROPBEAR_CLI_LOCALTCPFWD
|
||||
cli_opts.localfwds = list_new();
|
||||
opts.listen_fwd_all = 0;
|
||||
@@ -450,12 +451,9 @@ void cli_getopts(int argc, char ** argv) {
|
||||
&& cli_opts.no_cmd == 0) {
|
||||
dropbear_exit("Command required for -f");
|
||||
}
|
||||
|
||||
|
||||
if (recv_window_arg) {
|
||||
opts.recv_window = atol(recv_window_arg);
|
||||
if (opts.recv_window == 0 || opts.recv_window > MAX_RECV_WINDOW) {
|
||||
dropbear_exit("Bad recv window '%s'", recv_window_arg);
|
||||
}
|
||||
parse_recv_window(recv_window_arg);
|
||||
}
|
||||
if (keepalive_arg) {
|
||||
unsigned int val;
|
||||
@@ -889,6 +887,7 @@ static void add_extendedopt(const char* origstr) {
|
||||
#if DROPBEAR_CLI_ANYTCPFWD
|
||||
"\tExitOnForwardFailure\n"
|
||||
#endif
|
||||
"\tDisableTrivialAuth\n"
|
||||
#ifndef DISABLE_SYSLOG
|
||||
"\tUseSyslog\n"
|
||||
#endif
|
||||
@@ -916,5 +915,10 @@ static void add_extendedopt(const char* origstr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (match_extendedopt(&optstr, "DisableTrivialAuth") == DROPBEAR_SUCCESS) {
|
||||
cli_opts.disable_trivial_auth = parse_flag_value(optstr);
|
||||
return;
|
||||
}
|
||||
|
||||
dropbear_log(LOG_WARNING, "Ignoring unknown configuration option '%s'", origstr);
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ static void cli_session_init(pid_t proxy_cmd_pid) {
|
||||
/* Auth */
|
||||
cli_ses.lastprivkey = NULL;
|
||||
cli_ses.lastauthtype = 0;
|
||||
cli_ses.is_trivial_auth = 1;
|
||||
|
||||
/* For printing "remote host closed" for the user */
|
||||
ses.remoteclosed = cli_remoteclosed;
|
||||
@@ -245,6 +246,9 @@ static void cli_sessionloop() {
|
||||
/* We've got the transport layer sorted, we now need to request
|
||||
* userauth */
|
||||
send_msg_service_request(SSH_SERVICE_USERAUTH);
|
||||
/* We aren't using any "implicit server authentication" methods,
|
||||
so don't need to wait for a response for SSH_SERVICE_USERAUTH
|
||||
before sending the auth messages (rfc4253 10) */
|
||||
cli_auth_getmethods();
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
TRACE(("leave cli_sessionloop: sent userauth methods req"))
|
||||
@@ -352,6 +356,11 @@ static void cli_session_cleanup(void) {
|
||||
(void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
|
||||
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
|
||||
|
||||
/* Don't leak */
|
||||
m_close(cli_ses.stdincopy);
|
||||
m_close(cli_ses.stdoutcopy);
|
||||
m_close(cli_ses.stderrcopy);
|
||||
|
||||
cli_tty_cleanup();
|
||||
if (cli_ses.server_sig_algs) {
|
||||
buf_free(cli_ses.server_sig_algs);
|
||||
@@ -403,7 +412,75 @@ void cleantext(char* dirtytext) {
|
||||
}
|
||||
|
||||
static void recv_msg_global_request_cli(void) {
|
||||
TRACE(("recv_msg_global_request_cli"))
|
||||
/* Send a proper rejection */
|
||||
send_msg_request_failure();
|
||||
unsigned int wantreply = 0;
|
||||
|
||||
buf_eatstring(ses.payload);
|
||||
wantreply = buf_getbool(ses.payload);
|
||||
|
||||
TRACE(("recv_msg_global_request_cli: want_reply: %u", wantreply));
|
||||
|
||||
if (wantreply) {
|
||||
/* Send a proper rejection */
|
||||
send_msg_request_failure();
|
||||
}
|
||||
}
|
||||
|
||||
void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
char exitmsg[150];
|
||||
char fullmsg[300];
|
||||
|
||||
/* Note that exit message must be rendered before session cleanup */
|
||||
|
||||
/* Render the formatted exit message */
|
||||
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
|
||||
TRACE(("Exited, cleaning up: %s", exitmsg))
|
||||
|
||||
/* Add the prefix depending on session/auth state */
|
||||
if (!ses.init_done) {
|
||||
snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
|
||||
} else {
|
||||
snprintf(fullmsg, sizeof(fullmsg),
|
||||
"Connection to %s@%s:%s exited: %s",
|
||||
cli_opts.username, cli_opts.remotehost,
|
||||
cli_opts.remoteport, exitmsg);
|
||||
}
|
||||
|
||||
/* Do the cleanup first, since then the terminal will be reset */
|
||||
session_cleanup();
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.do_jmp) {
|
||||
longjmp(fuzz.jmp, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Avoid printing onwards from terminal cruft */
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
dropbear_log(LOG_INFO, "%s", fullmsg);
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
void cli_dropbear_log(int priority, const char* format, va_list param) {
|
||||
|
||||
char printbuf[1024];
|
||||
const char *name;
|
||||
|
||||
name = cli_opts.progname;
|
||||
if (!name) {
|
||||
name = "dbclient";
|
||||
}
|
||||
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
|
||||
#ifndef DISABLE_SYSLOG
|
||||
if (opts.usingsyslog) {
|
||||
syslog(priority, "%s", printbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "%s: %s\n", name, printbuf);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
static int newtcpforwarded(struct Channel * channel);
|
||||
|
||||
const struct ChanType cli_chan_tcpremote = {
|
||||
1, /* sepfds */
|
||||
"forwarded-tcpip",
|
||||
newtcpforwarded,
|
||||
NULL,
|
||||
@@ -51,7 +50,6 @@ static int cli_localtcp(const char* listenaddr,
|
||||
const char* remoteaddr,
|
||||
unsigned int remoteport);
|
||||
static const struct ChanType cli_chan_tcplocal = {
|
||||
1, /* sepfds */
|
||||
"direct-tcpip",
|
||||
tcp_prio_inithandler,
|
||||
NULL,
|
||||
@@ -273,12 +271,12 @@ static int newtcpforwarded(struct Channel * channel) {
|
||||
origaddr, origport);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
|
||||
snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
|
||||
channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel, NULL, NULL);
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
|
||||
err = SSH_OPEN_IN_PROGRESS;
|
||||
|
||||
out:
|
||||
|
||||
@@ -239,6 +239,9 @@ algo_type ssh_nocompress[] = {
|
||||
algo_type sigalgs[] = {
|
||||
#if DROPBEAR_ED25519
|
||||
{"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL},
|
||||
#if DROPBEAR_SK_ED25519
|
||||
{"sk-ssh-ed25519@openssh.com", DROPBEAR_SIGNATURE_SK_ED25519, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
#if DROPBEAR_ECC_256
|
||||
@@ -250,6 +253,9 @@ algo_type sigalgs[] = {
|
||||
#if DROPBEAR_ECC_521
|
||||
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
{"sk-ecdsa-sha2-nistp256@openssh.com", DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_RSA
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
@@ -381,7 +387,7 @@ static void get_algolist(char* algolist, unsigned int algolist_len,
|
||||
}
|
||||
if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
|
||||
*ret_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ret_list will contain a list of the strings parsed out.
|
||||
We will have at least one string (even if it's just "") */
|
||||
@@ -392,11 +398,11 @@ static void get_algolist(char* algolist, unsigned int algolist_len,
|
||||
/* someone is trying something strange */
|
||||
*ret_count = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (algolist[i] == ',') {
|
||||
if (*ret_count >= max_count) {
|
||||
/* Too many */
|
||||
dropbear_exit("Too many remote algorithms");
|
||||
*ret_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,6 @@ static struct Channel* newchannel(unsigned int remotechan,
|
||||
newchan->readfd = FD_UNINIT;
|
||||
newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
|
||||
newchan->await_open = 0;
|
||||
newchan->flushing = 0;
|
||||
|
||||
newchan->writebuf = cbuf_new(opts.recv_window);
|
||||
newchan->recvwindow = opts.recv_window;
|
||||
@@ -284,24 +283,29 @@ static void check_close(struct Channel *channel) {
|
||||
channel->writebuf ? cbuf_getused(channel->writebuf) : 0,
|
||||
channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
|
||||
|
||||
if (!channel->flushing
|
||||
&& !channel->sent_close
|
||||
&& channel->type->check_close
|
||||
&& channel->type->check_close(channel))
|
||||
{
|
||||
channel->flushing = 1;
|
||||
}
|
||||
|
||||
/* if a type-specific check_close is defined we will only exit
|
||||
once that has been triggered. this is only used for a server "session"
|
||||
channel, to ensure that the shell has exited (and the exit status
|
||||
channel, to ensure that the shell has exited (and the exit status
|
||||
retrieved) before we close things up. */
|
||||
if (!channel->type->check_close
|
||||
if (!channel->type->check_close
|
||||
|| channel->sent_close
|
||||
|| channel->type->check_close(channel)) {
|
||||
close_allowed = 1;
|
||||
}
|
||||
|
||||
/* In flushing mode we close FDs as soon as pipes are empty.
|
||||
This is used to drain out FDs when the process exits, in the case
|
||||
where the FD doesn't have EOF - "sleep 10&echo hello" case */
|
||||
if (channel->flushing) {
|
||||
if (channel->readfd >= 0 && !fd_read_pending(channel->readfd)) {
|
||||
close_chan_fd(channel, channel->readfd, SHUT_RD);
|
||||
}
|
||||
if (ERRFD_IS_READ(channel)
|
||||
&& channel->errfd >= 0 && !fd_read_pending(channel->errfd)) {
|
||||
close_chan_fd(channel, channel->errfd, SHUT_RD);
|
||||
}
|
||||
}
|
||||
|
||||
if (channel->recv_close && !write_pending(channel) && close_allowed) {
|
||||
if (!channel->sent_close) {
|
||||
TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
|
||||
@@ -317,22 +321,6 @@ static void check_close(struct Channel *channel) {
|
||||
close_chan_fd(channel, channel->writefd, SHUT_WR);
|
||||
}
|
||||
|
||||
/* Special handling for flushing read data after an exit. We
|
||||
read regardless of whether the select FD was set,
|
||||
and if there isn't data available, the channel will get closed. */
|
||||
if (channel->flushing) {
|
||||
TRACE(("might send data, flushing"))
|
||||
if (channel->readfd >= 0 && channel->transwindow > 0) {
|
||||
TRACE(("send data readfd"))
|
||||
send_msg_channel_data(channel, 0);
|
||||
}
|
||||
if (ERRFD_IS_READ(channel) && channel->errfd >= 0
|
||||
&& channel->transwindow > 0) {
|
||||
TRACE(("send data errfd"))
|
||||
send_msg_channel_data(channel, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're not going to send any more data, send EOF */
|
||||
if (!channel->sent_eof
|
||||
&& channel->readfd == FD_CLOSED
|
||||
@@ -356,8 +344,7 @@ static void check_close(struct Channel *channel) {
|
||||
* if so, set up the channel properly. Otherwise, the channel is cleaned up, so
|
||||
* it is important that the channel reference isn't used after a call to this
|
||||
* function */
|
||||
void channel_connect_done(int result, int sock, void* user_data, const char* UNUSED(errstring)) {
|
||||
|
||||
void channel_connect_done(int result, int sock, void* user_data, const char* errstring) {
|
||||
struct Channel *channel = user_data;
|
||||
|
||||
TRACE(("enter channel_connect_done"))
|
||||
@@ -365,6 +352,7 @@ void channel_connect_done(int result, int sock, void* user_data, const char* UNU
|
||||
if (result == DROPBEAR_SUCCESS)
|
||||
{
|
||||
channel->readfd = channel->writefd = sock;
|
||||
channel->bidir_fd = 1;
|
||||
channel->conn_pending = NULL;
|
||||
send_msg_channel_open_confirmation(channel, channel->recvwindow,
|
||||
channel->recvmaxpacket);
|
||||
@@ -373,9 +361,9 @@ void channel_connect_done(int result, int sock, void* user_data, const char* UNU
|
||||
else
|
||||
{
|
||||
send_msg_channel_open_failure(channel->remotechan,
|
||||
SSH_OPEN_CONNECT_FAILED, "", "");
|
||||
SSH_OPEN_CONNECT_FAILED, errstring, "");
|
||||
remove_channel(channel);
|
||||
TRACE(("leave check_in_progress: fail"))
|
||||
TRACE(("leave check_in_progress: fail. internal errstring: %s", errstring))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -780,14 +768,6 @@ static void send_msg_channel_data(struct Channel *channel, int isextended) {
|
||||
channel->transwindow -= len;
|
||||
|
||||
encrypt_packet();
|
||||
|
||||
/* If we receive less data than we requested when flushing, we've
|
||||
reached the equivalent of EOF */
|
||||
if (channel->flushing && len < (ssize_t)maxlen)
|
||||
{
|
||||
TRACE(("closing from channel, flushing out."))
|
||||
close_chan_fd(channel, fd, SHUT_RD);
|
||||
}
|
||||
TRACE(("leave send_msg_channel_data"))
|
||||
}
|
||||
|
||||
@@ -1073,7 +1053,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
|
||||
|
||||
int closein = 0, closeout = 0;
|
||||
|
||||
if (channel->type->sepfds) {
|
||||
if (channel->bidir_fd) {
|
||||
TRACE(("SHUTDOWN(%d, %d)", fd, how))
|
||||
shutdown(fd, how);
|
||||
if (how == 0) {
|
||||
@@ -1103,7 +1083,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
|
||||
|
||||
/* if we called shutdown on it and all references are gone, then we
|
||||
* need to close() it to stop it lingering */
|
||||
if (channel->type->sepfds && channel->readfd == FD_CLOSED
|
||||
if (channel->bidir_fd && channel->readfd == FD_CLOSED
|
||||
&& channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
|
||||
TRACE(("CLOSE (finally) of %d", fd))
|
||||
m_close(fd);
|
||||
@@ -1136,6 +1116,7 @@ int send_msg_channel_open_init(int fd, const struct ChanType *type) {
|
||||
|
||||
chan->writefd = chan->readfd = fd;
|
||||
ses.maxfd = MAX(ses.maxfd, fd);
|
||||
chan->bidir_fd = 1;
|
||||
|
||||
chan->await_open = 1;
|
||||
|
||||
@@ -1152,7 +1133,7 @@ int send_msg_channel_open_init(int fd, const struct ChanType *type) {
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Confirmation that our channel open request (for forwardings) was
|
||||
/* Confirmation that our channel open request was
|
||||
* successful*/
|
||||
void recv_msg_channel_open_confirmation() {
|
||||
|
||||
|
||||
@@ -487,6 +487,12 @@ void recv_msg_kexinit() {
|
||||
TRACE(("continue recv_msg_kexinit: sent kexinit"))
|
||||
}
|
||||
|
||||
/* "Once a party has sent a SSH_MSG_KEXINIT message ...
|
||||
further SSH_MSG_KEXINIT messages MUST NOT be sent" */
|
||||
if (ses.kexstate.recvkexinit) {
|
||||
dropbear_exit("Unexpected KEXINIT");
|
||||
}
|
||||
|
||||
/* start the kex hash */
|
||||
local_ident_len = strlen(LOCAL_IDENT);
|
||||
remote_ident_len = strlen(ses.remoteident);
|
||||
|
||||
@@ -101,4 +101,20 @@ void print_version() {
|
||||
fprintf(stderr, "Dropbear v%s\n", DROPBEAR_VERSION);
|
||||
}
|
||||
|
||||
void parse_recv_window(const char* recv_window_arg) {
|
||||
int ret;
|
||||
unsigned int rw;
|
||||
|
||||
ret = m_str_to_uint(recv_window_arg, &rw);
|
||||
if (ret == DROPBEAR_FAILURE || rw == 0 || rw > MAX_RECV_WINDOW) {
|
||||
if (rw > MAX_RECV_WINDOW) {
|
||||
opts.recv_window = MAX_RECV_WINDOW;
|
||||
}
|
||||
dropbear_log(LOG_WARNING, "Bad recv window '%s', using %d",
|
||||
recv_window_arg, opts.recv_window);
|
||||
} else {
|
||||
opts.recv_window = rw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -465,6 +465,11 @@ static int ident_readln(int fd, char* buf, int count) {
|
||||
TRACE(("leave ident_readln: EOF"))
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
fuzz_dump(&in, 1);
|
||||
#endif
|
||||
|
||||
if (in == '\n') {
|
||||
/* end of ident string */
|
||||
break;
|
||||
|
||||
373
config.guess
vendored
373
config.guess
vendored
@@ -1,8 +1,8 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2019 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2021 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2019-03-04'
|
||||
timestamp='2021-01-25'
|
||||
|
||||
# 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
|
||||
@@ -27,12 +27,12 @@ timestamp='2019-03-04'
|
||||
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
|
||||
#
|
||||
# You can get the latest version of this script from:
|
||||
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||
# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
|
||||
#
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
|
||||
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
me=$(echo "$0" | sed -e 's,.*/,,')
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]
|
||||
@@ -50,7 +50,7 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright 1992-2019 Free Software Foundation, Inc.
|
||||
Copyright 1992-2021 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."
|
||||
@@ -99,9 +99,11 @@ tmp=
|
||||
trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
|
||||
|
||||
set_cc_for_build() {
|
||||
# prevent multiple calls if $tmp is already set
|
||||
test "$tmp" && return 0
|
||||
: "${TMPDIR=/tmp}"
|
||||
# shellcheck disable=SC2039
|
||||
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
|
||||
{ tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } ||
|
||||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
|
||||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
|
||||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
|
||||
@@ -129,16 +131,14 @@ if test -f /.attbin/uname ; then
|
||||
PATH=$PATH:/.attbin ; export PATH
|
||||
fi
|
||||
|
||||
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
|
||||
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
|
||||
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
|
||||
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
|
||||
UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown
|
||||
UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown
|
||||
UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown
|
||||
UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown
|
||||
|
||||
case "$UNAME_SYSTEM" in
|
||||
Linux|GNU|GNU/*)
|
||||
# If the system lacks a compiler, then just pick glibc.
|
||||
# We could probably try harder.
|
||||
LIBC=gnu
|
||||
LIBC=unknown
|
||||
|
||||
set_cc_for_build
|
||||
cat <<-EOF > "$dummy.c"
|
||||
@@ -147,17 +147,29 @@ Linux|GNU|GNU/*)
|
||||
LIBC=uclibc
|
||||
#elif defined(__dietlibc__)
|
||||
LIBC=dietlibc
|
||||
#else
|
||||
#elif defined(__GLIBC__)
|
||||
LIBC=gnu
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
/* First heuristic to detect musl libc. */
|
||||
#ifdef __DEFINED_va_list
|
||||
LIBC=musl
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
|
||||
eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')"
|
||||
|
||||
# If ldd exists, use it to detect musl libc.
|
||||
if command -v ldd >/dev/null && \
|
||||
ldd --version 2>&1 | grep -q ^musl
|
||||
then
|
||||
LIBC=musl
|
||||
# Second heuristic to detect musl libc.
|
||||
if [ "$LIBC" = unknown ] &&
|
||||
command -v ldd >/dev/null &&
|
||||
ldd --version 2>&1 | grep -q ^musl; then
|
||||
LIBC=musl
|
||||
fi
|
||||
|
||||
# If the system lacks a compiler, then just pick glibc.
|
||||
# We could probably try harder.
|
||||
if [ "$LIBC" = unknown ]; then
|
||||
LIBC=gnu
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
@@ -176,20 +188,20 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
#
|
||||
# Note: NetBSD doesn't particularly care about the vendor
|
||||
# portion of the name. We always set it to "unknown".
|
||||
sysctl="sysctl -n hw.machine_arch"
|
||||
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
|
||||
"/sbin/$sysctl" 2>/dev/null || \
|
||||
"/usr/sbin/$sysctl" 2>/dev/null || \
|
||||
echo unknown)`
|
||||
UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
|
||||
/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
|
||||
/usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
|
||||
echo unknown))
|
||||
case "$UNAME_MACHINE_ARCH" in
|
||||
aarch64eb) machine=aarch64_be-unknown ;;
|
||||
armeb) machine=armeb-unknown ;;
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
sh5el) machine=sh5le-unknown ;;
|
||||
earmv*)
|
||||
arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
|
||||
endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
|
||||
arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,')
|
||||
endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p')
|
||||
machine="${arch}${endian}"-unknown
|
||||
;;
|
||||
*) machine="$UNAME_MACHINE_ARCH"-unknown ;;
|
||||
@@ -220,7 +232,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
case "$UNAME_MACHINE_ARCH" in
|
||||
earm*)
|
||||
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
|
||||
abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
|
||||
abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr")
|
||||
;;
|
||||
esac
|
||||
# The OS release
|
||||
@@ -233,7 +245,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
release='-gnu'
|
||||
;;
|
||||
*)
|
||||
release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
|
||||
release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2)
|
||||
;;
|
||||
esac
|
||||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||
@@ -242,15 +254,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
echo "$machine-${os}${release}${abi-}"
|
||||
exit ;;
|
||||
*:Bitrig:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
||||
UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')
|
||||
echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
*:OpenBSD:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
||||
UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')
|
||||
echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
*:LibertyBSD:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
|
||||
UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//')
|
||||
echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
*:MidnightBSD:*:*)
|
||||
@@ -262,6 +274,9 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
*:SolidBSD:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
*:OS108:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
macppc:MirBSD:*:*)
|
||||
echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
@@ -271,26 +286,29 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
*:Sortix:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-sortix
|
||||
exit ;;
|
||||
*:Twizzler:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-twizzler
|
||||
exit ;;
|
||||
*:Redox:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-redox
|
||||
exit ;;
|
||||
mips:OSF1:*.*)
|
||||
echo mips-dec-osf1
|
||||
exit ;;
|
||||
echo mips-dec-osf1
|
||||
exit ;;
|
||||
alpha:OSF1:*:*)
|
||||
case $UNAME_RELEASE in
|
||||
*4.0)
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
||||
UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}')
|
||||
;;
|
||||
*5.*)
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
|
||||
UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}')
|
||||
;;
|
||||
esac
|
||||
# According to Compaq, /usr/sbin/psrinfo has been available on
|
||||
# OSF/1 and Tru64 systems produced since 1995. I hope that
|
||||
# covers most systems running today. This code pipes the CPU
|
||||
# types through head -n 1, so we only detect the type of CPU 0.
|
||||
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
|
||||
ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1)
|
||||
case "$ALPHA_CPU_TYPE" in
|
||||
"EV4 (21064)")
|
||||
UNAME_MACHINE=alpha ;;
|
||||
@@ -328,7 +346,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
|
||||
echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)"
|
||||
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
|
||||
exitcode=$?
|
||||
trap '' 0
|
||||
@@ -362,7 +380,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
exit ;;
|
||||
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
|
||||
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
|
||||
if test "`(/bin/universe) 2>/dev/null`" = att ; then
|
||||
if test "$( (/bin/universe) 2>/dev/null)" = att ; then
|
||||
echo pyramid-pyramid-sysv3
|
||||
else
|
||||
echo pyramid-pyramid-bsd
|
||||
@@ -375,17 +393,17 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
echo sparc-icl-nx6
|
||||
exit ;;
|
||||
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
|
||||
case `/usr/bin/uname -p` in
|
||||
case $(/usr/bin/uname -p) in
|
||||
sparc) echo sparc-icl-nx7; exit ;;
|
||||
esac ;;
|
||||
s390x:SunOS:*:*)
|
||||
echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
|
||||
echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
|
||||
exit ;;
|
||||
sun4H:SunOS:5.*:*)
|
||||
echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
|
||||
echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
|
||||
exit ;;
|
||||
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
|
||||
echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
|
||||
echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
|
||||
exit ;;
|
||||
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
|
||||
echo i386-pc-auroraux"$UNAME_RELEASE"
|
||||
@@ -396,7 +414,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
# If there is a compiler, see if it is configured for 64-bit objects.
|
||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||
# This test works for both compilers.
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if test "$CC_FOR_BUILD" != no_compiler_found; then
|
||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
@@ -404,30 +422,30 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
SUN_ARCH=x86_64
|
||||
fi
|
||||
fi
|
||||
echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
|
||||
echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
|
||||
exit ;;
|
||||
sun4*:SunOS:6*:*)
|
||||
# According to config.sub, this is the proper way to canonicalize
|
||||
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
|
||||
# it's likely to be more like Solaris than SunOS4.
|
||||
echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
|
||||
echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
|
||||
exit ;;
|
||||
sun4*:SunOS:*:*)
|
||||
case "`/usr/bin/arch -k`" in
|
||||
case "$(/usr/bin/arch -k)" in
|
||||
Series*|S4*)
|
||||
UNAME_RELEASE=`uname -v`
|
||||
UNAME_RELEASE=$(uname -v)
|
||||
;;
|
||||
esac
|
||||
# Japanese Language versions have a version number like `4.1.3-JL'.
|
||||
echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
|
||||
echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')"
|
||||
exit ;;
|
||||
sun3*:SunOS:*:*)
|
||||
echo m68k-sun-sunos"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
sun*:*:4.2BSD:*)
|
||||
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||
UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null)
|
||||
test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
|
||||
case "`/bin/arch`" in
|
||||
case "$(/bin/arch)" in
|
||||
sun3)
|
||||
echo m68k-sun-sunos"$UNAME_RELEASE"
|
||||
;;
|
||||
@@ -507,8 +525,8 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
|
||||
}
|
||||
EOF
|
||||
$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
|
||||
dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
|
||||
SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
|
||||
dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') &&
|
||||
SYSTEM_NAME=$("$dummy" "$dummyarg") &&
|
||||
{ echo "$SYSTEM_NAME"; exit; }
|
||||
echo mips-mips-riscos"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
@@ -535,11 +553,11 @@ EOF
|
||||
exit ;;
|
||||
AViiON:dgux:*:*)
|
||||
# DG/UX returns AViiON for all architectures
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
|
||||
UNAME_PROCESSOR=$(/usr/bin/uname -p)
|
||||
if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
|
||||
then
|
||||
if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
|
||||
[ "$TARGET_BINARY_INTERFACE"x = x ]
|
||||
if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
|
||||
test "$TARGET_BINARY_INTERFACE"x = x
|
||||
then
|
||||
echo m88k-dg-dgux"$UNAME_RELEASE"
|
||||
else
|
||||
@@ -563,17 +581,17 @@ EOF
|
||||
echo m68k-tektronix-bsd
|
||||
exit ;;
|
||||
*:IRIX*:*:*)
|
||||
echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
|
||||
echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')"
|
||||
exit ;;
|
||||
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
|
||||
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
|
||||
exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
|
||||
exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX '
|
||||
i*86:AIX:*:*)
|
||||
echo i386-ibm-aix
|
||||
exit ;;
|
||||
ia64:AIX:*:*)
|
||||
if [ -x /usr/bin/oslevel ] ; then
|
||||
IBM_REV=`/usr/bin/oslevel`
|
||||
if test -x /usr/bin/oslevel ; then
|
||||
IBM_REV=$(/usr/bin/oslevel)
|
||||
else
|
||||
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
|
||||
fi
|
||||
@@ -593,7 +611,7 @@ EOF
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
|
||||
if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy")
|
||||
then
|
||||
echo "$SYSTEM_NAME"
|
||||
else
|
||||
@@ -606,15 +624,15 @@ EOF
|
||||
fi
|
||||
exit ;;
|
||||
*:AIX:*:[4567])
|
||||
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
|
||||
IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }')
|
||||
if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
|
||||
IBM_ARCH=rs6000
|
||||
else
|
||||
IBM_ARCH=powerpc
|
||||
fi
|
||||
if [ -x /usr/bin/lslpp ] ; then
|
||||
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
|
||||
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
|
||||
if test -x /usr/bin/lslpp ; then
|
||||
IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |
|
||||
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)
|
||||
else
|
||||
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
|
||||
fi
|
||||
@@ -642,14 +660,14 @@ EOF
|
||||
echo m68k-hp-bsd4.4
|
||||
exit ;;
|
||||
9000/[34678]??:HP-UX:*:*)
|
||||
HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
|
||||
HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
|
||||
case "$UNAME_MACHINE" in
|
||||
9000/31?) HP_ARCH=m68000 ;;
|
||||
9000/[34]??) HP_ARCH=m68k ;;
|
||||
9000/[678][0-9][0-9])
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||
if test -x /usr/bin/getconf; then
|
||||
sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null)
|
||||
sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null)
|
||||
case "$sc_cpu_version" in
|
||||
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
|
||||
@@ -661,7 +679,7 @@ EOF
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
if [ "$HP_ARCH" = "" ]; then
|
||||
if test "$HP_ARCH" = ""; then
|
||||
set_cc_for_build
|
||||
sed 's/^ //' << EOF > "$dummy.c"
|
||||
|
||||
@@ -696,11 +714,11 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
(CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
|
||||
(CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy")
|
||||
test -z "$HP_ARCH" && HP_ARCH=hppa
|
||||
fi ;;
|
||||
esac
|
||||
if [ "$HP_ARCH" = hppa2.0w ]
|
||||
if test "$HP_ARCH" = hppa2.0w
|
||||
then
|
||||
set_cc_for_build
|
||||
|
||||
@@ -724,7 +742,7 @@ EOF
|
||||
echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
|
||||
exit ;;
|
||||
ia64:HP-UX:*:*)
|
||||
HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
|
||||
HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
|
||||
echo ia64-hp-hpux"$HPUX_REV"
|
||||
exit ;;
|
||||
3050*:HI-UX:*:*)
|
||||
@@ -754,7 +772,7 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
|
||||
$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") &&
|
||||
{ echo "$SYSTEM_NAME"; exit; }
|
||||
echo unknown-hitachi-hiuxwe2
|
||||
exit ;;
|
||||
@@ -774,7 +792,7 @@ EOF
|
||||
echo hppa1.0-hp-osf
|
||||
exit ;;
|
||||
i*86:OSF1:*:*)
|
||||
if [ -x /usr/sbin/sysversion ] ; then
|
||||
if test -x /usr/sbin/sysversion ; then
|
||||
echo "$UNAME_MACHINE"-unknown-osf1mk
|
||||
else
|
||||
echo "$UNAME_MACHINE"-unknown-osf1
|
||||
@@ -823,14 +841,14 @@ EOF
|
||||
echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
|
||||
exit ;;
|
||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
|
||||
FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)
|
||||
FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
|
||||
FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/')
|
||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
5000:UNIX_System_V:4.*:*)
|
||||
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
|
||||
FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
|
||||
FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/')
|
||||
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||
@@ -843,25 +861,25 @@ EOF
|
||||
echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
arm:FreeBSD:*:*)
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
UNAME_PROCESSOR=$(uname -p)
|
||||
set_cc_for_build
|
||||
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_PCS_VFP
|
||||
then
|
||||
echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi
|
||||
echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi
|
||||
else
|
||||
echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf
|
||||
echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf
|
||||
fi
|
||||
exit ;;
|
||||
*:FreeBSD:*:*)
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
UNAME_PROCESSOR=$(/usr/bin/uname -p)
|
||||
case "$UNAME_PROCESSOR" in
|
||||
amd64)
|
||||
UNAME_PROCESSOR=x86_64 ;;
|
||||
i386)
|
||||
UNAME_PROCESSOR=i586 ;;
|
||||
esac
|
||||
echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
|
||||
echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
|
||||
exit ;;
|
||||
i*:CYGWIN*:*)
|
||||
echo "$UNAME_MACHINE"-pc-cygwin
|
||||
@@ -897,15 +915,15 @@ EOF
|
||||
echo x86_64-pc-cygwin
|
||||
exit ;;
|
||||
prep*:SunOS:5.*:*)
|
||||
echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
|
||||
echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
|
||||
exit ;;
|
||||
*:GNU:*:*)
|
||||
# the GNU system
|
||||
echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
|
||||
echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')"
|
||||
exit ;;
|
||||
*:GNU/*:*:*)
|
||||
# other systems with GNU libc and userland
|
||||
echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
|
||||
echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC"
|
||||
exit ;;
|
||||
*:Minix:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-minix
|
||||
@@ -918,7 +936,7 @@ EOF
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
alpha:Linux:*:*)
|
||||
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
||||
case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in
|
||||
EV5) UNAME_MACHINE=alphaev5 ;;
|
||||
EV56) UNAME_MACHINE=alphaev56 ;;
|
||||
PCA56) UNAME_MACHINE=alphapca56 ;;
|
||||
@@ -977,6 +995,9 @@ EOF
|
||||
k1om:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
m32r*:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
@@ -1027,7 +1048,7 @@ EOF
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`"
|
||||
eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')"
|
||||
test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
|
||||
;;
|
||||
mips64el:Linux:*:*)
|
||||
@@ -1047,7 +1068,7 @@ EOF
|
||||
exit ;;
|
||||
parisc:Linux:*:* | hppa:Linux:*:*)
|
||||
# Look for CPU level
|
||||
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
|
||||
case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in
|
||||
PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
|
||||
PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
|
||||
*) echo hppa-unknown-linux-"$LIBC" ;;
|
||||
@@ -1065,7 +1086,7 @@ EOF
|
||||
ppcle:Linux:*:*)
|
||||
echo powerpcle-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
riscv32:Linux:*:* | riscv64:Linux:*:*)
|
||||
riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
exit ;;
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
@@ -1087,7 +1108,17 @@ EOF
|
||||
echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
|
||||
exit ;;
|
||||
x86_64:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
|
||||
set_cc_for_build
|
||||
LIBCABI=$LIBC
|
||||
if test "$CC_FOR_BUILD" != no_compiler_found; then
|
||||
if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_X32 >/dev/null
|
||||
then
|
||||
LIBCABI="$LIBC"x32
|
||||
fi
|
||||
fi
|
||||
echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI"
|
||||
exit ;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
|
||||
@@ -1127,7 +1158,7 @@ EOF
|
||||
echo "$UNAME_MACHINE"-pc-msdosdjgpp
|
||||
exit ;;
|
||||
i*86:*:4.*:*)
|
||||
UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
|
||||
UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//')
|
||||
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
|
||||
echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
|
||||
else
|
||||
@@ -1136,7 +1167,7 @@ EOF
|
||||
exit ;;
|
||||
i*86:*:5:[678]*)
|
||||
# UnixWare 7.x, OpenUNIX and OpenServer 6.
|
||||
case `/bin/uname -X | grep "^Machine"` in
|
||||
case $(/bin/uname -X | grep "^Machine") in
|
||||
*486*) UNAME_MACHINE=i486 ;;
|
||||
*Pentium) UNAME_MACHINE=i586 ;;
|
||||
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
|
||||
@@ -1145,10 +1176,10 @@ EOF
|
||||
exit ;;
|
||||
i*86:*:3.2:*)
|
||||
if test -f /usr/options/cb.name; then
|
||||
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
|
||||
UNAME_REL=$(sed -n 's/.*Version //p' </usr/options/cb.name)
|
||||
echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
|
||||
elif /bin/uname -X 2>/dev/null >/dev/null ; then
|
||||
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
|
||||
UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //'))
|
||||
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
|
||||
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
|
||||
&& UNAME_MACHINE=i586
|
||||
@@ -1198,7 +1229,7 @@ EOF
|
||||
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
|
||||
OS_REL=''
|
||||
test -r /etc/.relid \
|
||||
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
|
||||
&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
|
||||
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||
@@ -1209,7 +1240,7 @@ EOF
|
||||
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
|
||||
OS_REL='.3'
|
||||
test -r /etc/.relid \
|
||||
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
|
||||
&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
|
||||
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||
@@ -1242,7 +1273,7 @@ EOF
|
||||
exit ;;
|
||||
*:SINIX-*:*:*)
|
||||
if uname -p 2>/dev/null >/dev/null ; then
|
||||
UNAME_MACHINE=`(uname -p) 2>/dev/null`
|
||||
UNAME_MACHINE=$( (uname -p) 2>/dev/null)
|
||||
echo "$UNAME_MACHINE"-sni-sysv4
|
||||
else
|
||||
echo ns32k-sni-sysv
|
||||
@@ -1276,7 +1307,7 @@ EOF
|
||||
echo mips-sony-newsos6
|
||||
exit ;;
|
||||
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
|
||||
if [ -d /usr/nec ]; then
|
||||
if test -d /usr/nec; then
|
||||
echo mips-nec-sysv"$UNAME_RELEASE"
|
||||
else
|
||||
echo mips-unknown-sysv"$UNAME_RELEASE"
|
||||
@@ -1324,44 +1355,48 @@ EOF
|
||||
*:Rhapsody:*:*)
|
||||
echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
arm64:Darwin:*:*)
|
||||
echo aarch64-apple-darwin"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
*:Darwin:*:*)
|
||||
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
||||
set_cc_for_build
|
||||
if test "$UNAME_PROCESSOR" = unknown ; then
|
||||
UNAME_PROCESSOR=powerpc
|
||||
UNAME_PROCESSOR=$(uname -p)
|
||||
case $UNAME_PROCESSOR in
|
||||
unknown) UNAME_PROCESSOR=powerpc ;;
|
||||
esac
|
||||
if command -v xcode-select > /dev/null 2> /dev/null && \
|
||||
! xcode-select --print-path > /dev/null 2> /dev/null ; then
|
||||
# Avoid executing cc if there is no toolchain installed as
|
||||
# cc will be a stub that puts up a graphical alert
|
||||
# prompting the user to install developer tools.
|
||||
CC_FOR_BUILD=no_compiler_found
|
||||
else
|
||||
set_cc_for_build
|
||||
fi
|
||||
if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
case $UNAME_PROCESSOR in
|
||||
i386) UNAME_PROCESSOR=x86_64 ;;
|
||||
powerpc) UNAME_PROCESSOR=powerpc64 ;;
|
||||
esac
|
||||
fi
|
||||
# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
|
||||
if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_PPC >/dev/null
|
||||
then
|
||||
UNAME_PROCESSOR=powerpc
|
||||
fi
|
||||
if test "$CC_FOR_BUILD" != no_compiler_found; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
case $UNAME_PROCESSOR in
|
||||
i386) UNAME_PROCESSOR=x86_64 ;;
|
||||
powerpc) UNAME_PROCESSOR=powerpc64 ;;
|
||||
esac
|
||||
fi
|
||||
# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
|
||||
if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_PPC >/dev/null
|
||||
then
|
||||
UNAME_PROCESSOR=powerpc
|
||||
fi
|
||||
elif test "$UNAME_PROCESSOR" = i386 ; then
|
||||
# Avoid executing cc on OS X 10.9, as it ships with a stub
|
||||
# that puts up a graphical alert prompting to install
|
||||
# developer tools. Any system running Mac OS X 10.7 or
|
||||
# later (Darwin 11 and later) is required to have a 64-bit
|
||||
# processor. This is not true of the ARM version of Darwin
|
||||
# that Apple uses in portable devices.
|
||||
UNAME_PROCESSOR=x86_64
|
||||
# uname -m returns i386 or x86_64
|
||||
UNAME_PROCESSOR=$UNAME_MACHINE
|
||||
fi
|
||||
echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
UNAME_PROCESSOR=$(uname -p)
|
||||
if test "$UNAME_PROCESSOR" = x86; then
|
||||
UNAME_PROCESSOR=i386
|
||||
UNAME_MACHINE=pc
|
||||
@@ -1429,10 +1464,10 @@ EOF
|
||||
echo mips-sei-seiux"$UNAME_RELEASE"
|
||||
exit ;;
|
||||
*:DragonFly:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
|
||||
echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
|
||||
exit ;;
|
||||
*:*VMS:*:*)
|
||||
UNAME_MACHINE=`(uname -p) 2>/dev/null`
|
||||
UNAME_MACHINE=$( (uname -p) 2>/dev/null)
|
||||
case "$UNAME_MACHINE" in
|
||||
A*) echo alpha-dec-vms ; exit ;;
|
||||
I*) echo ia64-dec-vms ; exit ;;
|
||||
@@ -1442,13 +1477,13 @@ EOF
|
||||
echo i386-pc-xenix
|
||||
exit ;;
|
||||
i*86:skyos:*:*)
|
||||
echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
|
||||
echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')"
|
||||
exit ;;
|
||||
i*86:rdos:*:*)
|
||||
echo "$UNAME_MACHINE"-pc-rdos
|
||||
exit ;;
|
||||
i*86:AROS:*:*)
|
||||
echo "$UNAME_MACHINE"-pc-aros
|
||||
*:AROS:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-aros
|
||||
exit ;;
|
||||
x86_64:VMkernel:*:*)
|
||||
echo "$UNAME_MACHINE"-unknown-esx
|
||||
@@ -1468,6 +1503,14 @@ cat > "$dummy.c" <<EOF
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
|
||||
#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
|
||||
#include <signal.h>
|
||||
#if defined(_SIZE_T_) || defined(SIGLOST)
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
main ()
|
||||
{
|
||||
#if defined (sony)
|
||||
@@ -1492,7 +1535,7 @@ main ()
|
||||
#define __ARCHITECTURE__ "m68k"
|
||||
#endif
|
||||
int version;
|
||||
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
|
||||
version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null);
|
||||
if (version < 4)
|
||||
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
|
||||
else
|
||||
@@ -1554,19 +1597,24 @@ main ()
|
||||
#else
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
#endif
|
||||
#else
|
||||
#if defined(_SIZE_T_) || defined(SIGLOST)
|
||||
struct utsname un;
|
||||
uname (&un);
|
||||
printf ("vax-dec-ultrix%s\n", un.release); exit (0);
|
||||
#else
|
||||
printf ("vax-dec-ultrix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
|
||||
#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
|
||||
#include <signal.h>
|
||||
#if defined(_SIZE_T_) /* >= ULTRIX4 */
|
||||
printf ("mips-dec-ultrix4\n"); exit (0);
|
||||
#if defined(_SIZE_T_) || defined(SIGLOST)
|
||||
struct utsname *un;
|
||||
uname (&un);
|
||||
printf ("mips-dec-ultrix%s\n", un.release); exit (0);
|
||||
#else
|
||||
#if defined(ULTRIX3) || defined(ultrix3) || defined(SIGLOST)
|
||||
printf ("mips-dec-ultrix3\n"); exit (0);
|
||||
#endif
|
||||
printf ("mips-dec-ultrix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -1579,7 +1627,7 @@ main ()
|
||||
}
|
||||
EOF
|
||||
|
||||
$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` &&
|
||||
$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) &&
|
||||
{ echo "$SYSTEM_NAME"; exit; }
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
@@ -1604,9 +1652,15 @@ This script (version $timestamp), has failed to recognize the
|
||||
operating system you are using. If your script is old, overwrite *all*
|
||||
copies of config.guess and config.sub with the latest versions from:
|
||||
|
||||
https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||
https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
|
||||
and
|
||||
https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
|
||||
EOF
|
||||
|
||||
year=$(echo $timestamp | sed 's,-.*,,')
|
||||
# shellcheck disable=SC2003
|
||||
if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then
|
||||
cat >&2 <<EOF
|
||||
|
||||
If $0 has already been updated, send the following data and any
|
||||
information you think might be pertinent to config-patches@gnu.org to
|
||||
@@ -1614,26 +1668,27 @@ provide the necessary information to handle your system.
|
||||
|
||||
config.guess timestamp = $timestamp
|
||||
|
||||
uname -m = `(uname -m) 2>/dev/null || echo unknown`
|
||||
uname -r = `(uname -r) 2>/dev/null || echo unknown`
|
||||
uname -s = `(uname -s) 2>/dev/null || echo unknown`
|
||||
uname -v = `(uname -v) 2>/dev/null || echo unknown`
|
||||
uname -m = $( (uname -m) 2>/dev/null || echo unknown)
|
||||
uname -r = $( (uname -r) 2>/dev/null || echo unknown)
|
||||
uname -s = $( (uname -s) 2>/dev/null || echo unknown)
|
||||
uname -v = $( (uname -v) 2>/dev/null || echo unknown)
|
||||
|
||||
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
|
||||
/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
|
||||
/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null)
|
||||
/bin/uname -X = $( (/bin/uname -X) 2>/dev/null)
|
||||
|
||||
hostinfo = `(hostinfo) 2>/dev/null`
|
||||
/bin/universe = `(/bin/universe) 2>/dev/null`
|
||||
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
|
||||
/bin/arch = `(/bin/arch) 2>/dev/null`
|
||||
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
|
||||
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
|
||||
hostinfo = $( (hostinfo) 2>/dev/null)
|
||||
/bin/universe = $( (/bin/universe) 2>/dev/null)
|
||||
/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null)
|
||||
/bin/arch = $( (/bin/arch) 2>/dev/null)
|
||||
/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null)
|
||||
/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null)
|
||||
|
||||
UNAME_MACHINE = "$UNAME_MACHINE"
|
||||
UNAME_RELEASE = "$UNAME_RELEASE"
|
||||
UNAME_SYSTEM = "$UNAME_SYSTEM"
|
||||
UNAME_VERSION = "$UNAME_VERSION"
|
||||
EOF
|
||||
fi
|
||||
|
||||
exit 1
|
||||
|
||||
|
||||
453
config.h.in
Normal file
453
config.h.in
Normal file
@@ -0,0 +1,453 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Using AIX */
|
||||
#undef AIX
|
||||
|
||||
/* Broken getaddrinfo */
|
||||
#undef BROKEN_GETADDRINFO
|
||||
|
||||
/* Use bundled libtom */
|
||||
#undef BUNDLED_LIBTOM
|
||||
|
||||
/* lastlog file location */
|
||||
#undef CONF_LASTLOG_FILE
|
||||
|
||||
/* utmpx file location */
|
||||
#undef CONF_UTMPX_FILE
|
||||
|
||||
/* utmp file location */
|
||||
#undef CONF_UTMP_FILE
|
||||
|
||||
/* wtmpx file location */
|
||||
#undef CONF_WTMPX_FILE
|
||||
|
||||
/* wtmp file location */
|
||||
#undef CONF_WTMP_FILE
|
||||
|
||||
/* Disable use of lastlog() */
|
||||
#undef DISABLE_LASTLOG
|
||||
|
||||
/* Use PAM */
|
||||
#undef DISABLE_PAM
|
||||
|
||||
/* Disable use of pututline() */
|
||||
#undef DISABLE_PUTUTLINE
|
||||
|
||||
/* Disable use of pututxline() */
|
||||
#undef DISABLE_PUTUTXLINE
|
||||
|
||||
/* Using syslog */
|
||||
#undef DISABLE_SYSLOG
|
||||
|
||||
/* Disable use of utmp */
|
||||
#undef DISABLE_UTMP
|
||||
|
||||
/* Disable use of utmpx */
|
||||
#undef DISABLE_UTMPX
|
||||
|
||||
/* Disable use of wtmp */
|
||||
#undef DISABLE_WTMP
|
||||
|
||||
/* Disable use of wtmpx */
|
||||
#undef DISABLE_WTMPX
|
||||
|
||||
/* Use zlib */
|
||||
#undef DISABLE_ZLIB
|
||||
|
||||
/* Fuzzing */
|
||||
#undef DROPBEAR_FUZZ
|
||||
|
||||
/* External Public Key Authentication */
|
||||
#undef DROPBEAR_PLUGIN
|
||||
|
||||
/* Define to 1 if you have the `basename' function. */
|
||||
#undef HAVE_BASENAME
|
||||
|
||||
/* Define to 1 if you have the `clearenv' function. */
|
||||
#undef HAVE_CLEARENV
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define if gai_strerror() returns const char * */
|
||||
#undef HAVE_CONST_GAI_STRERROR_PROTO
|
||||
|
||||
/* crypt() function */
|
||||
#undef HAVE_CRYPT
|
||||
|
||||
/* Define to 1 if you have the <crypt.h> header file. */
|
||||
#undef HAVE_CRYPT_H
|
||||
|
||||
/* Define to 1 if you have the `daemon' function. */
|
||||
#undef HAVE_DAEMON
|
||||
|
||||
/* Use /dev/ptc & /dev/pts */
|
||||
#undef HAVE_DEV_PTS_AND_PTC
|
||||
|
||||
/* Define to 1 if you have the `endutent' function. */
|
||||
#undef HAVE_ENDUTENT
|
||||
|
||||
/* Define to 1 if you have the `endutxent' function. */
|
||||
#undef HAVE_ENDUTXENT
|
||||
|
||||
/* Define to 1 if you have the `explicit_bzero' function. */
|
||||
#undef HAVE_EXPLICIT_BZERO
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
/* Define to 1 if you have the `freeaddrinfo' function. */
|
||||
#undef HAVE_FREEADDRINFO
|
||||
|
||||
/* Define to 1 if you have the `gai_strerror' function. */
|
||||
#undef HAVE_GAI_STRERROR
|
||||
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#undef HAVE_GETADDRINFO
|
||||
|
||||
/* Define to 1 if you have the `getgrouplist' function. */
|
||||
#undef HAVE_GETGROUPLIST
|
||||
|
||||
/* Define to 1 if you have the `getnameinfo' function. */
|
||||
#undef HAVE_GETNAMEINFO
|
||||
|
||||
/* Define to 1 if you have the `getpass' function. */
|
||||
#undef HAVE_GETPASS
|
||||
|
||||
/* Define to 1 if you have the `getrandom' function. */
|
||||
#undef HAVE_GETRANDOM
|
||||
|
||||
/* Define to 1 if you have the `getspnam' function. */
|
||||
#undef HAVE_GETSPNAM
|
||||
|
||||
/* Define to 1 if you have the `getusershell' function. */
|
||||
#undef HAVE_GETUSERSHELL
|
||||
|
||||
/* Define to 1 if you have the `getutent' function. */
|
||||
#undef HAVE_GETUTENT
|
||||
|
||||
/* Define to 1 if you have the `getutid' function. */
|
||||
#undef HAVE_GETUTID
|
||||
|
||||
/* Define to 1 if you have the `getutline' function. */
|
||||
#undef HAVE_GETUTLINE
|
||||
|
||||
/* Define to 1 if you have the `getutxent' function. */
|
||||
#undef HAVE_GETUTXENT
|
||||
|
||||
/* Define to 1 if you have the `getutxid' function. */
|
||||
#undef HAVE_GETUTXID
|
||||
|
||||
/* Define to 1 if you have the `getutxline' function. */
|
||||
#undef HAVE_GETUTXLINE
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <lastlog.h> header file. */
|
||||
#undef HAVE_LASTLOG_H
|
||||
|
||||
/* Define to 1 if you have the <libgen.h> header file. */
|
||||
#undef HAVE_LIBGEN_H
|
||||
|
||||
/* Define to 1 if you have the `pam' library (-lpam). */
|
||||
#undef HAVE_LIBPAM
|
||||
|
||||
/* Define to 1 if you have the <libutil.h> header file. */
|
||||
#undef HAVE_LIBUTIL_H
|
||||
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#undef HAVE_LIBZ
|
||||
|
||||
/* Define to 1 if you have the <linux/pkt_sched.h> header file. */
|
||||
#undef HAVE_LINUX_PKT_SCHED_H
|
||||
|
||||
/* Have login() function */
|
||||
#undef HAVE_LOGIN
|
||||
|
||||
/* Define to 1 if you have the `logout' function. */
|
||||
#undef HAVE_LOGOUT
|
||||
|
||||
/* Define to 1 if you have the `logwtmp' function. */
|
||||
#undef HAVE_LOGWTMP
|
||||
|
||||
/* Define to 1 if you have the `mach_absolute_time' function. */
|
||||
#undef HAVE_MACH_ABSOLUTE_TIME
|
||||
|
||||
/* Define to 1 if you have the <mach/mach_time.h> header file. */
|
||||
#undef HAVE_MACH_MACH_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `memset_s' function. */
|
||||
#undef HAVE_MEMSET_S
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#undef HAVE_NETDB_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/in_systm.h> header file. */
|
||||
#undef HAVE_NETINET_IN_SYSTM_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||
#undef HAVE_NETINET_TCP_H
|
||||
|
||||
/* Have openpty() function */
|
||||
#undef HAVE_OPENPTY
|
||||
|
||||
/* Define to 1 if you have the `pam_fail_delay' function. */
|
||||
#undef HAVE_PAM_FAIL_DELAY
|
||||
|
||||
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
|
||||
#undef HAVE_PAM_PAM_APPL_H
|
||||
|
||||
/* Define to 1 if you have the <paths.h> header file. */
|
||||
#undef HAVE_PATHS_H
|
||||
|
||||
/* Define to 1 if you have the <pty.h> header file. */
|
||||
#undef HAVE_PTY_H
|
||||
|
||||
/* Define to 1 if you have the `putenv' function. */
|
||||
#undef HAVE_PUTENV
|
||||
|
||||
/* Define to 1 if you have the `pututline' function. */
|
||||
#undef HAVE_PUTUTLINE
|
||||
|
||||
/* Define to 1 if you have the `pututxline' function. */
|
||||
#undef HAVE_PUTUTXLINE
|
||||
|
||||
/* Define to 1 if you have the <security/pam_appl.h> header file. */
|
||||
#undef HAVE_SECURITY_PAM_APPL_H
|
||||
|
||||
/* Define to 1 if you have the `setutent' function. */
|
||||
#undef HAVE_SETUTENT
|
||||
|
||||
/* Define to 1 if you have the `setutxent' function. */
|
||||
#undef HAVE_SETUTXENT
|
||||
|
||||
/* Define to 1 if you have the <shadow.h> header file. */
|
||||
#undef HAVE_SHADOW_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strlcat' function. */
|
||||
#undef HAVE_STRLCAT
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#undef HAVE_STRLCPY
|
||||
|
||||
/* Define to 1 if you have the <stropts.h> header file. */
|
||||
#undef HAVE_STROPTS_H
|
||||
|
||||
/* Have struct addrinfo */
|
||||
#undef HAVE_STRUCT_ADDRINFO
|
||||
|
||||
/* Have struct in6_addr */
|
||||
#undef HAVE_STRUCT_IN6_ADDR
|
||||
|
||||
/* Have struct sockaddr_in6 */
|
||||
#undef HAVE_STRUCT_SOCKADDR_IN6
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_STORAGE
|
||||
|
||||
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
|
||||
|
||||
/* Define to 1 if `ut_addr' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_ADDR
|
||||
|
||||
/* Define to 1 if `ut_addr_v6' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_ADDR_V6
|
||||
|
||||
/* Define to 1 if `ut_host' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_HOST
|
||||
|
||||
/* Define to 1 if `ut_id' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_ID
|
||||
|
||||
/* Define to 1 if `ut_syslen' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_SYSLEN
|
||||
|
||||
/* Define to 1 if `ut_time' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_TIME
|
||||
|
||||
/* Define to 1 if `ut_tv' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_TV
|
||||
|
||||
/* Define to 1 if `ut_type' is a member of `struct utmpx'. */
|
||||
#undef HAVE_STRUCT_UTMPX_UT_TYPE
|
||||
|
||||
/* Define to 1 if `ut_addr' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_ADDR
|
||||
|
||||
/* Define to 1 if `ut_addr_v6' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_ADDR_V6
|
||||
|
||||
/* Define to 1 if `ut_exit' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_EXIT
|
||||
|
||||
/* Define to 1 if `ut_host' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_HOST
|
||||
|
||||
/* Define to 1 if `ut_id' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_ID
|
||||
|
||||
/* Define to 1 if `ut_pid' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_PID
|
||||
|
||||
/* Define to 1 if `ut_time' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_TIME
|
||||
|
||||
/* Define to 1 if `ut_tv' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_TV
|
||||
|
||||
/* Define to 1 if `ut_type' is a member of `struct utmp'. */
|
||||
#undef HAVE_STRUCT_UTMP_UT_TYPE
|
||||
|
||||
/* Define to 1 if you have the <sys/random.h> header file. */
|
||||
#undef HAVE_SYS_RANDOM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#undef HAVE_SYS_SELECT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
#undef HAVE_SYS_UIO_H
|
||||
|
||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define to 1 if the system has the type `uint16_t'. */
|
||||
#undef HAVE_UINT16_T
|
||||
|
||||
/* Define to 1 if the system has the type `uint32_t'. */
|
||||
#undef HAVE_UINT32_T
|
||||
|
||||
/* Define to 1 if the system has the type `uint8_t'. */
|
||||
#undef HAVE_UINT8_T
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `updwtmp' function. */
|
||||
#undef HAVE_UPDWTMP
|
||||
|
||||
/* Define to 1 if you have the <util.h> header file. */
|
||||
#undef HAVE_UTIL_H
|
||||
|
||||
/* Define to 1 if you have the `utmpname' function. */
|
||||
#undef HAVE_UTMPNAME
|
||||
|
||||
/* Define to 1 if you have the `utmpxname' function. */
|
||||
#undef HAVE_UTMPXNAME
|
||||
|
||||
/* Define to 1 if you have the <utmpx.h> header file. */
|
||||
#undef HAVE_UTMPX_H
|
||||
|
||||
/* Define to 1 if you have the <utmp.h> header file. */
|
||||
#undef HAVE_UTMP_H
|
||||
|
||||
/* Define to 1 if the system has the type `u_int16_t'. */
|
||||
#undef HAVE_U_INT16_T
|
||||
|
||||
/* Define to 1 if the system has the type `u_int32_t'. */
|
||||
#undef HAVE_U_INT32_T
|
||||
|
||||
/* Define to 1 if the system has the type `u_int8_t'. */
|
||||
#undef HAVE_U_INT8_T
|
||||
|
||||
/* Define to 1 if you have the `writev' function. */
|
||||
#undef HAVE_WRITEV
|
||||
|
||||
/* Define to 1 if you have the `_getpty' function. */
|
||||
#undef HAVE__GETPTY
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to the type of arg 1 for `select'. */
|
||||
#undef SELECT_TYPE_ARG1
|
||||
|
||||
/* Define to the type of args 2, 3 and 4 for `select'. */
|
||||
#undef SELECT_TYPE_ARG234
|
||||
|
||||
/* Define to the type of arg 5 for `select'. */
|
||||
#undef SELECT_TYPE_ARG5
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Use /dev/ptmx */
|
||||
#undef USE_DEV_PTMX
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Use GNU extensions if glibc */
|
||||
#undef _GNU_SOURCE
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef gid_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef mode_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* type to use in place of socklen_t if not defined */
|
||||
#undef socklen_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef uid_t
|
||||
665
config.sub
vendored
665
config.sub
vendored
File diff suppressed because it is too large
Load Diff
27
configure.ac
27
configure.ac
@@ -5,7 +5,7 @@
|
||||
# of the platform checks have been taken straight from OpenSSH's configure.ac
|
||||
# Huge thanks to them for dealing with the horrible platform-specifics :)
|
||||
|
||||
AC_PREREQ(2.59)
|
||||
AC_PREREQ([2.59])
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR(buffer.c)
|
||||
|
||||
@@ -16,6 +16,7 @@ if test -s "`which hg`" && test -d "$srcdir/.hg"; then
|
||||
fi
|
||||
|
||||
ORIGCFLAGS="$CFLAGS"
|
||||
LATE_CFLAGS=""
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
@@ -47,6 +48,9 @@ DB_TRYADDCFLAGS([-Wno-pointer-sign])
|
||||
AC_MSG_NOTICE([Checking if compiler '$CC' supports -fno-strict-overflow])
|
||||
DB_TRYADDCFLAGS([-fno-strict-overflow])
|
||||
|
||||
# needed for various extensions. define early before autoconf tests
|
||||
AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions if glibc])
|
||||
|
||||
STATIC=0
|
||||
AC_ARG_ENABLE(static,
|
||||
[ --enable-static Build static binaries],
|
||||
@@ -124,6 +128,17 @@ if test "$hardenbuild" -eq 1; then
|
||||
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(werror,
|
||||
[ --enable-werror Set -Werror when building],
|
||||
[
|
||||
if test "x$enableval" = "xyes"; then
|
||||
# -Werror shouldn't be set when configure runs tests.
|
||||
# We add it to the Makefile's CFLAGS
|
||||
LATE_CFLAGS+="$LATE_CFLAGS -Werror"
|
||||
AC_MSG_NOTICE(Enabling -Werror)
|
||||
fi
|
||||
], [])
|
||||
|
||||
# large file support is useful for scp
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
@@ -347,6 +362,7 @@ AC_ARG_ENABLE(fuzz,
|
||||
DROPBEAR_FUZZ=1
|
||||
# libfuzzer needs linking with c++ libraries
|
||||
AC_PROG_CXX
|
||||
mkdir -pv fuzz
|
||||
else
|
||||
AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing)
|
||||
AC_MSG_NOTICE(Disabling fuzzing)
|
||||
@@ -364,7 +380,6 @@ AC_SUBST(DROPBEAR_FUZZ)
|
||||
AC_SUBST(CXX)
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \
|
||||
crypt.h \
|
||||
@@ -379,7 +394,6 @@ AC_TYPE_UID_T
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
|
||||
AC_CHECK_TYPES([uint8_t, u_int8_t, uint16_t, u_int16_t, uint32_t, u_int32_t])
|
||||
AC_CHECK_TYPES([struct sockaddr_storage])
|
||||
@@ -859,8 +873,11 @@ if test $BUNDLED_LIBTOM = 1 ; then
|
||||
LIBTOM_FILES="libtomcrypt/Makefile libtommath/Makefile"
|
||||
fi
|
||||
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_CONFIG_FILES(Makefile $LIBTOM_FILES)
|
||||
# flags that should be set in Makefile but not for configure tests
|
||||
CFLAGS="$CFLAGS $LATE_CFLAGS"
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES(Makefile $LIBTOM_FILES test/Makefile)
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_NOTICE()
|
||||
|
||||
@@ -3,11 +3,18 @@
|
||||
#include "crypto_desc.h"
|
||||
#include "ltc_prng.h"
|
||||
#include "ecc.h"
|
||||
#include "dbrandom.h"
|
||||
|
||||
#if DROPBEAR_LTC_PRNG
|
||||
int dropbear_ltc_prng = -1;
|
||||
#endif
|
||||
|
||||
/* Wrapper for libtommath */
|
||||
static mp_err dropbear_rand_source(void* out, size_t size) {
|
||||
genrandom((unsigned char*)out, (unsigned int)size);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
|
||||
/* Register the compiled in ciphers.
|
||||
* This should be run before using any of the ciphers/hashes */
|
||||
@@ -67,6 +74,8 @@ void crypto_init() {
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_rand_source(dropbear_rand_source);
|
||||
|
||||
#if DROPBEAR_ECC
|
||||
ltc_mp = ltm_desc;
|
||||
dropbear_ecc_fill_dp();
|
||||
|
||||
23
dbclient.1
23
dbclient.1
@@ -19,7 +19,7 @@ dbclient \- lightweight SSH client
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B dbclient
|
||||
is a small SSH client
|
||||
is the client part of Dropbear SSH
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.TP
|
||||
@@ -44,27 +44,27 @@ from OpenSSH with dropbearconvert(1). The default path ~/.ssh/id_dropbear is use
|
||||
.TP
|
||||
.B \-L\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
|
||||
Local port forwarding.
|
||||
Forward the port
|
||||
Forward
|
||||
.I listenport
|
||||
on the local host through the SSH connection to port
|
||||
on the local host through the SSH connection to
|
||||
.I port
|
||||
on the host
|
||||
on
|
||||
.IR host .
|
||||
.TP
|
||||
.B \-R\fR [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
|
||||
Remote port forwarding.
|
||||
Forward the port
|
||||
Forward
|
||||
.I listenport
|
||||
on the remote host through the SSH connection to port
|
||||
on the remote host through the SSH connection to
|
||||
.I port
|
||||
on the host
|
||||
on
|
||||
.IR host .
|
||||
.TP
|
||||
.B \-l \fIuser
|
||||
Username.
|
||||
Login as
|
||||
.I user
|
||||
on the remote host.
|
||||
on the remote host. An alternative is to specify user@host.
|
||||
.TP
|
||||
.B \-t
|
||||
Allocate a PTY. This is the default when no command is given, it gives a full
|
||||
@@ -72,7 +72,7 @@ interactive remote session. The main effect is that keystrokes are sent remotely
|
||||
immediately as opposed to local line-based editing.
|
||||
.TP
|
||||
.B \-T
|
||||
Don't allocate a PTY. This is the default a command is given. See -t.
|
||||
Don't allocate a PTY. This is the default when a command is given. See -t.
|
||||
.TP
|
||||
.B \-N
|
||||
Don't request a remote shell or run any commands. Any command arguments are ignored.
|
||||
@@ -149,10 +149,13 @@ The following options have currently been implemented:
|
||||
.RS
|
||||
.TP
|
||||
.B ExitOnForwardFailure
|
||||
Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be “yes” or “no”. The default is “no”.
|
||||
Specifies whether dbclient should terminate the connection if it cannot set up all requested local and remote port forwardings. The argument must be "yes" or "no". The default is "no".
|
||||
.TP
|
||||
.B UseSyslog
|
||||
Send dbclient log messages to syslog in addition to stderr.
|
||||
.TP
|
||||
.B Port
|
||||
Specify a listening port, like the \fI-p\fR argument.
|
||||
.RE
|
||||
.TP
|
||||
.B \-s
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef DBMALLOC_H_
|
||||
#define DBMALLOC_H_
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdlib.h"
|
||||
#include "options.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void * m_malloc(size_t size);
|
||||
void * m_calloc(size_t nmemb, size_t size);
|
||||
|
||||
@@ -150,12 +150,12 @@ static void write_urandom()
|
||||
}
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
void fuzz_seed(void) {
|
||||
void fuzz_seed(const unsigned char* dat, unsigned int len) {
|
||||
hash_state hs;
|
||||
sha1_init(&hs);
|
||||
sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
|
||||
sha1_process(&hs, dat, len);
|
||||
sha1_done(&hs, hashpool);
|
||||
|
||||
counter = 0;
|
||||
donerandinit = 1;
|
||||
}
|
||||
|
||||
88
dbutil.c
88
dbutil.c
@@ -121,7 +121,6 @@ static void generic_dropbear_exit(int exitcode, const char* format,
|
||||
_dropbear_log(LOG_INFO, fmtbuf, param);
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
/* longjmp before cleaning up svr_opts */
|
||||
if (fuzz.do_jmp) {
|
||||
longjmp(fuzz.jmp, 1);
|
||||
}
|
||||
@@ -258,6 +257,12 @@ int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
|
||||
const int FDIN = 0;
|
||||
const int FDOUT = 1;
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing) {
|
||||
return fuzz_spawn_command(ret_writefd, ret_readfd, ret_errfd, ret_pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* redirect stdin/stdout/stderr */
|
||||
if (pipe(infds) != 0) {
|
||||
return DROPBEAR_FAILURE;
|
||||
@@ -380,20 +385,37 @@ void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
|
||||
|
||||
#if DEBUG_TRACE
|
||||
void printhex(const char * label, const unsigned char * buf, int len) {
|
||||
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
fprintf(stderr, "%s\n", label);
|
||||
for (i = 0; i < len; i++) {
|
||||
fprintf(stderr, "%02x", buf[i]);
|
||||
if (i % 16 == 15) {
|
||||
fprintf(stderr, "\n");
|
||||
/* for each 16 byte line */
|
||||
for (j = 0; j < len; j += 16) {
|
||||
const int linelen = MIN(16, len - j);
|
||||
|
||||
/* print hex digits */
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (i < linelen) {
|
||||
fprintf(stderr, "%02x", buf[j+i]);
|
||||
} else {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
// separator between pairs
|
||||
if (i % 2 ==1) {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
}
|
||||
else if (i % 2 == 1) {
|
||||
fprintf(stderr, " ");
|
||||
|
||||
/* print characters */
|
||||
fprintf(stderr, " ");
|
||||
for (i = 0; i < linelen; i++) {
|
||||
char c = buf[j+i];
|
||||
if (!isprint(c)) {
|
||||
c = '.';
|
||||
}
|
||||
fputc(c, stderr);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void printmpint(const char *label, mp_int *mp) {
|
||||
@@ -561,8 +583,15 @@ void disallow_core() {
|
||||
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */
|
||||
int m_str_to_uint(const char* str, unsigned int *val) {
|
||||
unsigned long l;
|
||||
errno = 0;
|
||||
l = strtoul(str, NULL, 10);
|
||||
char *endp;
|
||||
|
||||
l = strtoul(str, &endp, 10);
|
||||
|
||||
if (endp == str || *endp != '\0') {
|
||||
// parse error
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
/* The c99 spec doesn't actually seem to define EINVAL, but most platforms
|
||||
* I've looked at mention it in their manpage */
|
||||
if ((l == 0 && errno == EINVAL)
|
||||
@@ -580,11 +609,19 @@ otherwise home directory is prepended */
|
||||
char * expand_homedir_path(const char *inpath) {
|
||||
struct passwd *pw = NULL;
|
||||
if (inpath[0] != '/') {
|
||||
pw = getpwuid(getuid());
|
||||
if (pw && pw->pw_dir) {
|
||||
int len = strlen(inpath) + strlen(pw->pw_dir) + 2;
|
||||
char *homedir = getenv("HOME");
|
||||
|
||||
if (!homedir) {
|
||||
pw = getpwuid(getuid());
|
||||
if (pw) {
|
||||
homedir = pw->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (homedir) {
|
||||
int len = strlen(inpath) + strlen(homedir) + 2;
|
||||
char *buf = m_malloc(len);
|
||||
snprintf(buf, len, "%s/%s", pw->pw_dir, inpath);
|
||||
snprintf(buf, len, "%s/%s", homedir, inpath);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
@@ -686,3 +723,22 @@ void fsync_parent_dir(const char* fn) {
|
||||
m_free(fn_dir);
|
||||
#endif
|
||||
}
|
||||
|
||||
int fd_read_pending(int fd) {
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
|
||||
DROPBEAR_FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
while (1) {
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
if (select(fd+1, &fds, NULL, NULL, &timeout) < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return FD_ISSET(fd, &fds);
|
||||
}
|
||||
}
|
||||
|
||||
2
dbutil.h
2
dbutil.h
@@ -90,6 +90,8 @@ char * expand_homedir_path(const char *inpath);
|
||||
|
||||
void fsync_parent_dir(const char* fn);
|
||||
|
||||
int fd_read_pending(int fd);
|
||||
|
||||
#if DROPBEAR_MSAN
|
||||
/* FD_ZERO seems to leave some memory uninitialized. clear it to avoid false positives */
|
||||
#define DROPBEAR_FD_ZERO(fds) do { memset((fds), 0x0, sizeof(fd_set)); FD_ZERO(fds); } while(0)
|
||||
|
||||
12
debian/changelog
vendored
12
debian/changelog
vendored
@@ -1,3 +1,15 @@
|
||||
dropbear (2020.81-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Thu, 29 Oct 2020 22:51:57 +0800
|
||||
|
||||
dropbear (2020.80-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Johnston <matt@ucc.asn.au> Fri, 26 Jun 2020 22:51:57 +0800
|
||||
|
||||
dropbear (2020.79-0.1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
@@ -126,9 +126,11 @@ IMPORTANT: Some options will require "make clean" after changes */
|
||||
* code (either ECDSA or ECDH) increases binary size - around 30kB
|
||||
* on x86-64 */
|
||||
#define DROPBEAR_ECDSA 1
|
||||
#define DROPBEAR_SK_ECDSA 1
|
||||
/* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases
|
||||
binary size - around 7,5kB on x86-64 */
|
||||
#define DROPBEAR_ED25519 1
|
||||
#define DROPBEAR_SK_ED25519 1
|
||||
|
||||
/* RSA must be >=1024 */
|
||||
#define DROPBEAR_DEFAULT_RSA_SIZE 2048
|
||||
@@ -256,6 +258,12 @@ Homedir is prepended unless path begins with / */
|
||||
/* -T server option overrides */
|
||||
#define MAX_AUTH_TRIES 10
|
||||
|
||||
/* Delay introduced before closing an unauthenticated session (seconds).
|
||||
Disabled by default, can be set to say 30 seconds to reduce the speed
|
||||
of password brute forcing. Note that there is a risk of denial of
|
||||
service by setting this */
|
||||
#define UNAUTH_CLOSE_DELAY 0
|
||||
|
||||
/* The default file to store the daemon's process ID, for shutdown
|
||||
scripts etc. This can be overridden with the -P flag */
|
||||
#define DROPBEAR_PIDFILE "/var/run/dropbear.pid"
|
||||
|
||||
17
dropbear.8
17
dropbear.8
@@ -35,6 +35,12 @@ Don't fork into background.
|
||||
.B \-E
|
||||
Log to standard error rather than syslog.
|
||||
.TP
|
||||
.B \-e
|
||||
Pass on the server environment to all child processes. This is required, for example,
|
||||
if Dropbear is launched on the fly from a SLURM workload manager. The environment is not
|
||||
passed by default. Note that this could expose secrets in environment variables from
|
||||
the calling process - use with caution.
|
||||
.TP
|
||||
.B \-m
|
||||
Don't display the message of the day on login.
|
||||
.TP
|
||||
@@ -60,7 +66,7 @@ and TCP
|
||||
.I port.
|
||||
If just a port is given listen
|
||||
on all addresses.
|
||||
up to 10 can be specified (default 22 if none specified).
|
||||
Up to 10 can be specified (default 22 if none specified).
|
||||
.TP
|
||||
.B \-i
|
||||
Service program mode.
|
||||
@@ -86,7 +92,7 @@ Ensure that traffic is transmitted at a certain interval in seconds. This is
|
||||
useful for working around firewalls or routers that drop connections after
|
||||
a certain period of inactivity. The trade-off is that a session may be
|
||||
closed if there is a temporary lapse of network connectivity. A setting
|
||||
if 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
|
||||
of 0 disables keepalives. If no response is received for 3 consecutive keepalives the connection will be closed.
|
||||
.TP
|
||||
.B \-I \fIidle_timeout
|
||||
Disconnect the session if no traffic is transmitted or received for \fIidle_timeout\fR seconds.
|
||||
@@ -96,7 +102,8 @@ Set the number of authentication attempts allowed per connection. If unspecified
|
||||
.TP
|
||||
.B \-c \fIforced_command
|
||||
Disregard the command provided by the user and always run \fIforced_command\fR. This also
|
||||
overrides any authorized_keys command= option.
|
||||
overrides any authorized_keys command= option. The original command is saved in the
|
||||
SSH_ORIGINAL_COMMAND environment variable (see below).
|
||||
.TP
|
||||
.B \-V
|
||||
Print the version
|
||||
@@ -133,6 +140,10 @@ Don't allow X11 forwarding for this connection
|
||||
Disable PTY allocation. Note that a user can still obtain most of the
|
||||
same functionality with other means even if no-pty is set.
|
||||
|
||||
.TP
|
||||
.B restrict
|
||||
Applies all the no- restrictions listed above.
|
||||
|
||||
.TP
|
||||
.B command=\fR"\fIforced_command\fR"
|
||||
Disregard the command provided by the user and always run \fIforced_command\fR.
|
||||
|
||||
23
ecdsa.c
23
ecdsa.c
@@ -81,18 +81,25 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf) {
|
||||
struct dropbear_ecc_curve **curve;
|
||||
ecc_key *new_key = NULL;
|
||||
|
||||
/* string "ecdsa-sha2-[identifier]" */
|
||||
/* string "ecdsa-sha2-[identifier]" or "sk-ecdsa-sha2-nistp256@openssh.com" */
|
||||
key_ident = (unsigned char*)buf_getstring(buf, &key_ident_len);
|
||||
/* string "[identifier]" */
|
||||
identifier = (unsigned char*)buf_getstring(buf, &identifier_len);
|
||||
|
||||
if (key_ident_len != identifier_len + strlen("ecdsa-sha2-")) {
|
||||
TRACE(("Bad identifier lengths"))
|
||||
goto out;
|
||||
}
|
||||
if (memcmp(&key_ident[strlen("ecdsa-sha2-")], identifier, identifier_len) != 0) {
|
||||
TRACE(("mismatching identifiers"))
|
||||
goto out;
|
||||
if (strcmp (key_ident, "sk-ecdsa-sha2-nistp256@openssh.com") == 0) {
|
||||
if (strcmp (identifier, "nistp256") != 0) {
|
||||
TRACE(("mismatching identifiers"))
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (key_ident_len != identifier_len + strlen ("ecdsa-sha2-")) {
|
||||
TRACE(("Bad identifier lengths"))
|
||||
goto out;
|
||||
}
|
||||
if (memcmp(&key_ident[strlen ("ecdsa-sha2-")], identifier, identifier_len) != 0) {
|
||||
TRACE(("mismatching identifiers"))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (curve = dropbear_ecc_curves; *curve; curve++) {
|
||||
|
||||
17
ed25519.c
17
ed25519.c
@@ -38,14 +38,25 @@
|
||||
* The key will have the same format as buf_put_ed25519_key.
|
||||
* These should be freed with ed25519_key_free.
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key) {
|
||||
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key,
|
||||
enum signkey_type expect_keytype) {
|
||||
|
||||
unsigned int len;
|
||||
|
||||
unsigned int len, typelen;
|
||||
char *keytype = NULL;
|
||||
enum signkey_type buf_keytype;
|
||||
|
||||
TRACE(("enter buf_get_ed25519_pub_key"))
|
||||
dropbear_assert(key != NULL);
|
||||
|
||||
buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */
|
||||
/* consume and check the key string */
|
||||
keytype = buf_getstring(buf, &typelen);
|
||||
buf_keytype = signkey_type_from_name(keytype, typelen);
|
||||
m_free(keytype);
|
||||
if (buf_keytype != expect_keytype) {
|
||||
TRACE(("leave buf_get_ed25519_pub_key: mismatch key type"))
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
len = buf_getint(buf);
|
||||
if (len != CURVE25519_LEN || buf->len - buf->pos < len) {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "signkey.h"
|
||||
|
||||
#if DROPBEAR_ED25519
|
||||
|
||||
@@ -43,7 +44,8 @@ void buf_put_ed25519_sign(buffer* buf, const dropbear_ed25519_key *key, const bu
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
int buf_ed25519_verify(buffer * buf, const dropbear_ed25519_key *key, const buffer *data_buf);
|
||||
#endif
|
||||
int buf_get_ed25519_pub_key(buffer* buf, dropbear_ed25519_key *key);
|
||||
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key,
|
||||
enum signkey_type expect_keytype);
|
||||
int buf_get_ed25519_priv_key(buffer* buf, dropbear_ed25519_key *key);
|
||||
void buf_put_ed25519_pub_key(buffer* buf, const dropbear_ed25519_key *key);
|
||||
void buf_put_ed25519_priv_key(buffer* buf, const dropbear_ed25519_key *key);
|
||||
|
||||
209
fuzz-common.c
209
fuzz-common.c
@@ -1,209 +0,0 @@
|
||||
#include "includes.h"
|
||||
|
||||
#include "includes.h"
|
||||
#include "fuzz.h"
|
||||
#include "dbutil.h"
|
||||
#include "runopts.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "session.h"
|
||||
#include "dbrandom.h"
|
||||
#include "bignum.h"
|
||||
#include "fuzz-wrapfd.h"
|
||||
|
||||
struct dropbear_fuzz_options fuzz;
|
||||
|
||||
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param);
|
||||
static void load_fixed_hostkeys(void);
|
||||
|
||||
void fuzz_common_setup(void) {
|
||||
fuzz.fuzzing = 1;
|
||||
fuzz.wrapfds = 1;
|
||||
fuzz.do_jmp = 1;
|
||||
fuzz.input = m_malloc(sizeof(buffer));
|
||||
_dropbear_log = fuzz_dropbear_log;
|
||||
crypto_init();
|
||||
fuzz_seed();
|
||||
/* let any messages get flushed */
|
||||
setlinebuf(stdout);
|
||||
}
|
||||
|
||||
int fuzz_set_input(const uint8_t *Data, size_t Size) {
|
||||
|
||||
fuzz.input->data = (unsigned char*)Data;
|
||||
fuzz.input->size = Size;
|
||||
fuzz.input->len = Size;
|
||||
fuzz.input->pos = 0;
|
||||
|
||||
memset(&ses, 0x0, sizeof(ses));
|
||||
memset(&svr_ses, 0x0, sizeof(svr_ses));
|
||||
wrapfd_setup();
|
||||
|
||||
fuzz_seed();
|
||||
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
#if DEBUG_TRACE
|
||||
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param) {
|
||||
if (debug_trace) {
|
||||
char printbuf[1024];
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
fprintf(stderr, "%s\n", printbuf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void fuzz_dropbear_log(int UNUSED(priority), const char* UNUSED(format), va_list UNUSED(param)) {
|
||||
/* No print */
|
||||
}
|
||||
#endif /* DEBUG_TRACE */
|
||||
|
||||
void fuzz_svr_setup(void) {
|
||||
fuzz_common_setup();
|
||||
|
||||
_dropbear_exit = svr_dropbear_exit;
|
||||
|
||||
char *argv[] = {
|
||||
"-E",
|
||||
};
|
||||
|
||||
int argc = sizeof(argv) / sizeof(*argv);
|
||||
svr_getopts(argc, argv);
|
||||
|
||||
/* user lookups might be slow, cache it */
|
||||
fuzz.pw_name = m_strdup("person");
|
||||
fuzz.pw_dir = m_strdup("/tmp");
|
||||
fuzz.pw_shell = m_strdup("/bin/zsh");
|
||||
fuzz.pw_passwd = m_strdup("!!zzznope");
|
||||
|
||||
load_fixed_hostkeys();
|
||||
}
|
||||
|
||||
static void load_fixed_hostkeys(void) {
|
||||
#include "fuzz-hostkeys.c"
|
||||
|
||||
buffer *b = buf_new(3000);
|
||||
enum signkey_type type;
|
||||
|
||||
TRACE(("load fixed hostkeys"))
|
||||
|
||||
svr_opts.hostkey = new_sign_key();
|
||||
|
||||
buf_setlen(b, 0);
|
||||
buf_putbytes(b, keyr, keyr_len);
|
||||
buf_setpos(b, 0);
|
||||
type = DROPBEAR_SIGNKEY_RSA;
|
||||
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed rsa hostkey");
|
||||
}
|
||||
|
||||
buf_setlen(b, 0);
|
||||
buf_putbytes(b, keyd, keyd_len);
|
||||
buf_setpos(b, 0);
|
||||
type = DROPBEAR_SIGNKEY_DSS;
|
||||
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed dss hostkey");
|
||||
}
|
||||
|
||||
buf_setlen(b, 0);
|
||||
buf_putbytes(b, keye, keye_len);
|
||||
buf_setpos(b, 0);
|
||||
type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
||||
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed ecdsa hostkey");
|
||||
}
|
||||
|
||||
buf_setlen(b, 0);
|
||||
buf_putbytes(b, keyed25519, keyed25519_len);
|
||||
buf_setpos(b, 0);
|
||||
type = DROPBEAR_SIGNKEY_ED25519;
|
||||
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed ed25519 hostkey");
|
||||
}
|
||||
|
||||
buf_free(b);
|
||||
}
|
||||
|
||||
void fuzz_kex_fakealgos(void) {
|
||||
ses.newkeys->recv.crypt_mode = &dropbear_mode_none;
|
||||
}
|
||||
|
||||
void fuzz_get_socket_address(int UNUSED(fd), char **local_host, char **local_port,
|
||||
char **remote_host, char **remote_port, int UNUSED(host_lookup)) {
|
||||
if (local_host) {
|
||||
*local_host = m_strdup("fuzzlocalhost");
|
||||
}
|
||||
if (local_port) {
|
||||
*local_port = m_strdup("1234");
|
||||
}
|
||||
if (remote_host) {
|
||||
*remote_host = m_strdup("fuzzremotehost");
|
||||
}
|
||||
if (remote_port) {
|
||||
*remote_port = m_strdup("9876");
|
||||
}
|
||||
}
|
||||
|
||||
/* cut down version of svr_send_msg_kexdh_reply() that skips slow maths. Still populates structures */
|
||||
void fuzz_fake_send_kexdh_reply(void) {
|
||||
assert(!ses.dh_K);
|
||||
m_mp_alloc_init_multi(&ses.dh_K, NULL);
|
||||
mp_set_ul(ses.dh_K, 12345678uL);
|
||||
finish_kexhashbuf();
|
||||
}
|
||||
|
||||
int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) {
|
||||
static int once = 0;
|
||||
if (!once) {
|
||||
fuzz_svr_setup();
|
||||
fuzz.skip_kexmaths = skip_kexmaths;
|
||||
once = 1;
|
||||
}
|
||||
|
||||
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
get prefix. input format is
|
||||
string prefix
|
||||
uint32 wrapfd seed
|
||||
... to be extended later
|
||||
[bytes] ssh input stream
|
||||
*/
|
||||
|
||||
/* be careful to avoid triggering buffer.c assertions */
|
||||
if (fuzz.input->len < 8) {
|
||||
return 0;
|
||||
}
|
||||
size_t prefix_size = buf_getint(fuzz.input);
|
||||
if (prefix_size != 4) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t wrapseed = buf_getint(fuzz.input);
|
||||
wrapfd_setseed(wrapseed);
|
||||
|
||||
int fakesock = 20;
|
||||
wrapfd_add(fakesock, fuzz.input, PLAIN);
|
||||
|
||||
m_malloc_set_epoch(1);
|
||||
if (setjmp(fuzz.jmp) == 0) {
|
||||
svr_session(fakesock, fakesock);
|
||||
m_malloc_free_epoch(1, 0);
|
||||
} else {
|
||||
m_malloc_free_epoch(1, 1);
|
||||
TRACE(("dropbear_exit longjmped"))
|
||||
/* dropbear_exit jumped here */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const void* fuzz_get_algo(const algo_type *algos, const char* name) {
|
||||
const algo_type *t;
|
||||
for (t = algos; t->name; t++) {
|
||||
if (strcmp(t->name, name) == 0) {
|
||||
return t->data;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
#ifndef FUZZ_WRAPFD_H
|
||||
#define FUZZ_WRAPFD_H
|
||||
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
|
||||
enum wrapfd_mode {
|
||||
UNUSED = 0,
|
||||
PLAIN,
|
||||
INPROGRESS,
|
||||
RANDOMIN
|
||||
COMMONBUF, // using the common buffer
|
||||
DUMMY, // reads return fixed output, of random length
|
||||
};
|
||||
|
||||
void wrapfd_setup(void);
|
||||
// buf is a common buffer read by all wrapped FDs. doesn't take ownership of buf
|
||||
void wrapfd_setup(buffer *buf);
|
||||
void wrapfd_setseed(uint32_t seed);
|
||||
// doesn't take ownership of buf. buf is optional.
|
||||
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode);
|
||||
int wrapfd_new_fuzzinput(void);
|
||||
int wrapfd_new_dummy(void);
|
||||
|
||||
// called via #defines for read/write/select
|
||||
int wrapfd_read(int fd, void *out, size_t count);
|
||||
@@ -21,5 +22,6 @@ int wrapfd_write(int fd, const void* in, size_t count);
|
||||
int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
fd_set *exceptfds, struct timeval *timeout);
|
||||
int wrapfd_close(int fd);
|
||||
int fuzz_kill(pid_t pid, int sig);
|
||||
|
||||
#endif // FUZZ_WRAPFD_H
|
||||
|
||||
60
fuzz.h
60
fuzz.h
@@ -8,17 +8,24 @@
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "algo.h"
|
||||
#include "netio.h"
|
||||
#include "fuzz-wrapfd.h"
|
||||
|
||||
// once per process
|
||||
void fuzz_common_setup(void);
|
||||
void fuzz_svr_setup(void);
|
||||
void fuzz_cli_setup(void);
|
||||
|
||||
// constructor attribute so it runs before main(), including
|
||||
// in non-fuzzing mode.
|
||||
void fuzz_early_setup(void) __attribute__((constructor));
|
||||
|
||||
// must be called once per fuzz iteration.
|
||||
// returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
|
||||
int fuzz_set_input(const uint8_t *Data, size_t Size);
|
||||
|
||||
int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths);
|
||||
int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int postauth);
|
||||
int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths);
|
||||
const void* fuzz_get_algo(const algo_type *algos, const char* name);
|
||||
|
||||
// fuzzer functions that intrude into general code
|
||||
@@ -27,10 +34,18 @@ int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename,
|
||||
const char* algo, unsigned int algolen,
|
||||
const unsigned char* keyblob, unsigned int keybloblen);
|
||||
extern const char * const * fuzz_signkey_names;
|
||||
void fuzz_seed(void);
|
||||
void fuzz_seed(const unsigned char* dat, unsigned int len);
|
||||
void fuzz_svr_hook_preloop(void);
|
||||
|
||||
int fuzz_dropbear_listen(const char* address, const char* port,
|
||||
int *socks, unsigned int sockcount, char **errstring, int *maxfd);
|
||||
|
||||
// helpers
|
||||
void fuzz_get_socket_address(int fd, char **local_host, char **local_port,
|
||||
char **remote_host, char **remote_port, int host_lookup);
|
||||
void fuzz_fake_send_kexdh_reply(void);
|
||||
int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid);
|
||||
void fuzz_dump(const unsigned char* data, size_t len);
|
||||
|
||||
// fake IO wrappers
|
||||
#ifndef FUZZ_SKIP_WRAP
|
||||
@@ -39,6 +54,7 @@ void fuzz_fake_send_kexdh_reply(void);
|
||||
#define write(fd, buf, count) wrapfd_write(fd, buf, count)
|
||||
#define read(fd, buf, count) wrapfd_read(fd, buf, count)
|
||||
#define close(fd) wrapfd_close(fd)
|
||||
#define kill(pid, sig) fuzz_kill(pid, sig)
|
||||
#endif // FUZZ_SKIP_WRAP
|
||||
|
||||
struct dropbear_fuzz_options {
|
||||
@@ -52,21 +68,47 @@ struct dropbear_fuzz_options {
|
||||
|
||||
// whether to skip slow bignum maths
|
||||
int skip_kexmaths;
|
||||
// whether is svr_postauth mode
|
||||
int svr_postauth;
|
||||
|
||||
// dropbear_exit() jumps back
|
||||
int do_jmp;
|
||||
sigjmp_buf jmp;
|
||||
|
||||
uid_t pw_uid;
|
||||
gid_t pw_gid;
|
||||
char* pw_name;
|
||||
char* pw_dir;
|
||||
char* pw_shell;
|
||||
char* pw_passwd;
|
||||
// write out decrypted session data to this FD if it is set
|
||||
// flag - this needs to be set manually in cli-main.c etc
|
||||
int dumping;
|
||||
// the file descriptor
|
||||
int recv_dumpfd;
|
||||
|
||||
// avoid filling fuzzing logs, this points to /dev/null
|
||||
FILE *fake_stderr;
|
||||
};
|
||||
|
||||
extern struct dropbear_fuzz_options fuzz;
|
||||
|
||||
#endif // DROPBEAR_FUZZ
|
||||
/* guard for when fuzz.h is included by fuzz-common.c */
|
||||
#ifndef FUZZ_NO_REPLACE_STDERR
|
||||
|
||||
/* This is a bodge but seems to work.
|
||||
glibc stdio.h has the comment
|
||||
"C89/C99 say they're macros. Make them happy." */
|
||||
/* OS X has it as a macro */
|
||||
#ifdef stderr
|
||||
#undef stderr
|
||||
#endif
|
||||
#define stderr (fuzz.fake_stderr)
|
||||
|
||||
#endif /* FUZZ_NO_REPLACE_STDERR */
|
||||
|
||||
struct passwd* fuzz_getpwuid(uid_t uid);
|
||||
struct passwd* fuzz_getpwnam(const char *login);
|
||||
/* guard for when fuzz.h is included by fuzz-common.c */
|
||||
#ifndef FUZZ_NO_REPLACE_GETPW
|
||||
#define getpwnam(x) fuzz_getpwnam(x)
|
||||
#define getpwuid(x) fuzz_getpwuid(x)
|
||||
#endif // FUZZ_NO_REPLACE_GETPW
|
||||
|
||||
#endif /* DROPBEAR_FUZZ */
|
||||
|
||||
#endif /* DROPBEAR_FUZZ_H */
|
||||
|
||||
398
fuzz/fuzz-common.c
Normal file
398
fuzz/fuzz-common.c
Normal file
@@ -0,0 +1,398 @@
|
||||
#define FUZZ_NO_REPLACE_STDERR
|
||||
#define FUZZ_NO_REPLACE_GETPW
|
||||
#include "includes.h"
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
#include "runopts.h"
|
||||
#include "crypto_desc.h"
|
||||
#include "session.h"
|
||||
#include "dbrandom.h"
|
||||
#include "bignum.h"
|
||||
#include "atomicio.h"
|
||||
#include "fuzz-wrapfd.h"
|
||||
#include "fuzz.h"
|
||||
|
||||
struct dropbear_fuzz_options fuzz;
|
||||
|
||||
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param);
|
||||
static void load_fixed_hostkeys(void);
|
||||
static void load_fixed_client_key(void);
|
||||
|
||||
// This runs automatically before main, due to contructor attribute in fuzz.h
|
||||
void fuzz_early_setup(void) {
|
||||
/* Set stderr to point to normal stderr by default */
|
||||
fuzz.fake_stderr = stderr;
|
||||
}
|
||||
|
||||
void fuzz_common_setup(void) {
|
||||
disallow_core();
|
||||
fuzz.fuzzing = 1;
|
||||
fuzz.wrapfds = 1;
|
||||
fuzz.do_jmp = 1;
|
||||
fuzz.input = m_malloc(sizeof(buffer));
|
||||
_dropbear_log = fuzz_dropbear_log;
|
||||
crypto_init();
|
||||
fuzz_seed("start", 5);
|
||||
/* let any messages get flushed */
|
||||
setlinebuf(stdout);
|
||||
#if DEBUG_TRACE
|
||||
if (debug_trace)
|
||||
{
|
||||
fprintf(stderr, "Dropbear fuzzer: -v specified, not disabling stderr output\n");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (getenv("DROPBEAR_KEEP_STDERR")) {
|
||||
fprintf(stderr, "Dropbear fuzzer: DROPBEAR_KEEP_STDERR, not disabling stderr output\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Dropbear fuzzer: Disabling stderr output\n");
|
||||
fuzz.fake_stderr = fopen("/dev/null", "w");
|
||||
assert(fuzz.fake_stderr);
|
||||
}
|
||||
}
|
||||
|
||||
int fuzz_set_input(const uint8_t *Data, size_t Size) {
|
||||
|
||||
fuzz.input->data = (unsigned char*)Data;
|
||||
fuzz.input->size = Size;
|
||||
fuzz.input->len = Size;
|
||||
fuzz.input->pos = 0;
|
||||
|
||||
memset(&ses, 0x0, sizeof(ses));
|
||||
memset(&svr_ses, 0x0, sizeof(svr_ses));
|
||||
memset(&cli_ses, 0x0, sizeof(cli_ses));
|
||||
wrapfd_setup(fuzz.input);
|
||||
// printhex("input", fuzz.input->data, fuzz.input->len);
|
||||
|
||||
fuzz_seed(fuzz.input->data, MIN(fuzz.input->len, 16));
|
||||
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
#if DEBUG_TRACE
|
||||
static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param) {
|
||||
if (debug_trace) {
|
||||
char printbuf[1024];
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
fprintf(stderr, "%s\n", printbuf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void fuzz_dropbear_log(int UNUSED(priority), const char* UNUSED(format), va_list UNUSED(param)) {
|
||||
/* No print */
|
||||
}
|
||||
#endif /* DEBUG_TRACE */
|
||||
|
||||
void fuzz_svr_setup(void) {
|
||||
fuzz_common_setup();
|
||||
|
||||
_dropbear_exit = svr_dropbear_exit;
|
||||
|
||||
char *argv[] = {
|
||||
"dropbear",
|
||||
"-E",
|
||||
};
|
||||
|
||||
int argc = sizeof(argv) / sizeof(*argv);
|
||||
svr_getopts(argc, argv);
|
||||
|
||||
load_fixed_hostkeys();
|
||||
}
|
||||
|
||||
void fuzz_svr_hook_preloop() {
|
||||
if (fuzz.svr_postauth) {
|
||||
ses.authstate.authdone = 1;
|
||||
fill_passwd("root");
|
||||
}
|
||||
}
|
||||
|
||||
void fuzz_cli_setup(void) {
|
||||
fuzz_common_setup();
|
||||
|
||||
_dropbear_exit = cli_dropbear_exit;
|
||||
_dropbear_log = cli_dropbear_log;
|
||||
|
||||
char *argv[] = {
|
||||
"dbclient",
|
||||
"-y",
|
||||
"localhost",
|
||||
"uptime"
|
||||
};
|
||||
|
||||
int argc = sizeof(argv) / sizeof(*argv);
|
||||
cli_getopts(argc, argv);
|
||||
|
||||
load_fixed_client_key();
|
||||
/* Avoid password prompt */
|
||||
setenv(DROPBEAR_PASSWORD_ENV, "password", 1);
|
||||
}
|
||||
|
||||
#include "fuzz-hostkeys.c"
|
||||
|
||||
static void load_fixed_client_key(void) {
|
||||
|
||||
buffer *b = buf_new(3000);
|
||||
sign_key *key;
|
||||
enum signkey_type keytype;
|
||||
|
||||
key = new_sign_key();
|
||||
keytype = DROPBEAR_SIGNKEY_ANY;
|
||||
buf_putbytes(b, keyed25519, keyed25519_len);
|
||||
buf_setpos(b, 0);
|
||||
if (buf_get_priv_key(b, key, &keytype) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed ed25519 hostkey");
|
||||
}
|
||||
list_append(cli_opts.privkeys, key);
|
||||
|
||||
buf_free(b);
|
||||
}
|
||||
|
||||
static void load_fixed_hostkeys(void) {
|
||||
|
||||
buffer *b = buf_new(3000);
|
||||
enum signkey_type type;
|
||||
|
||||
TRACE(("load fixed hostkeys"))
|
||||
|
||||
svr_opts.hostkey = new_sign_key();
|
||||
|
||||
buf_setlen(b, 0);
|
||||
buf_putbytes(b, keyr, keyr_len);
|
||||
buf_setpos(b, 0);
|
||||
type = DROPBEAR_SIGNKEY_RSA;
|
||||
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed rsa hostkey");
|
||||
}
|
||||
|
||||
buf_setlen(b, 0);
|
||||
buf_putbytes(b, keyd, keyd_len);
|
||||
buf_setpos(b, 0);
|
||||
type = DROPBEAR_SIGNKEY_DSS;
|
||||
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed dss hostkey");
|
||||
}
|
||||
|
||||
buf_setlen(b, 0);
|
||||
buf_putbytes(b, keye, keye_len);
|
||||
buf_setpos(b, 0);
|
||||
type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
||||
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed ecdsa hostkey");
|
||||
}
|
||||
|
||||
buf_setlen(b, 0);
|
||||
buf_putbytes(b, keyed25519, keyed25519_len);
|
||||
buf_setpos(b, 0);
|
||||
type = DROPBEAR_SIGNKEY_ED25519;
|
||||
if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) {
|
||||
dropbear_exit("failed fixed ed25519 hostkey");
|
||||
}
|
||||
|
||||
buf_free(b);
|
||||
}
|
||||
|
||||
void fuzz_kex_fakealgos(void) {
|
||||
ses.newkeys->recv.crypt_mode = &dropbear_mode_none;
|
||||
ses.newkeys->recv.algo_mac = &dropbear_nohash;
|
||||
}
|
||||
|
||||
void fuzz_get_socket_address(int UNUSED(fd), char **local_host, char **local_port,
|
||||
char **remote_host, char **remote_port, int UNUSED(host_lookup)) {
|
||||
if (local_host) {
|
||||
*local_host = m_strdup("fuzzlocalhost");
|
||||
}
|
||||
if (local_port) {
|
||||
*local_port = m_strdup("1234");
|
||||
}
|
||||
if (remote_host) {
|
||||
*remote_host = m_strdup("fuzzremotehost");
|
||||
}
|
||||
if (remote_port) {
|
||||
*remote_port = m_strdup("9876");
|
||||
}
|
||||
}
|
||||
|
||||
/* cut down version of svr_send_msg_kexdh_reply() that skips slow maths. Still populates structures */
|
||||
void fuzz_fake_send_kexdh_reply(void) {
|
||||
assert(!ses.dh_K);
|
||||
m_mp_alloc_init_multi(&ses.dh_K, NULL);
|
||||
mp_set_ul(ses.dh_K, 12345678uL);
|
||||
finish_kexhashbuf();
|
||||
}
|
||||
|
||||
/* fake version of spawn_command() */
|
||||
int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
|
||||
*ret_writefd = wrapfd_new_dummy();
|
||||
*ret_readfd = wrapfd_new_dummy();
|
||||
if (ret_errfd) {
|
||||
*ret_errfd = wrapfd_new_dummy();
|
||||
}
|
||||
if (*ret_writefd == -1 || *ret_readfd == -1 || (ret_errfd && *ret_errfd == -1)) {
|
||||
m_close(*ret_writefd);
|
||||
m_close(*ret_readfd);
|
||||
if (ret_errfd) {
|
||||
m_close(*ret_errfd);
|
||||
}
|
||||
return DROPBEAR_FAILURE;
|
||||
} else {
|
||||
*ret_pid = 999;
|
||||
return DROPBEAR_SUCCESS;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Fake dropbear_listen, always returns failure for now.
|
||||
TODO make it sometimes return success with wrapfd_new_dummy() sockets.
|
||||
Making the listeners fake a new incoming connection will be harder. */
|
||||
/* Listen on address:port.
|
||||
* Special cases are address of "" listening on everything,
|
||||
* and address of NULL listening on localhost only.
|
||||
* Returns the number of sockets bound on success, or -1 on failure. On
|
||||
* failure, if errstring wasn't NULL, it'll be a newly malloced error
|
||||
* string.*/
|
||||
int fuzz_dropbear_listen(const char* UNUSED(address), const char* UNUSED(port),
|
||||
int *UNUSED(socks), unsigned int UNUSED(sockcount), char **errstring, int *UNUSED(maxfd)) {
|
||||
if (errstring) {
|
||||
*errstring = m_strdup("fuzzing can't listen (yet)");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int postauth) {
|
||||
static int once = 0;
|
||||
if (!once) {
|
||||
fuzz_svr_setup();
|
||||
fuzz.skip_kexmaths = skip_kexmaths;
|
||||
once = 1;
|
||||
}
|
||||
|
||||
fuzz.svr_postauth = postauth;
|
||||
|
||||
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t wrapseed;
|
||||
genrandom((void*)&wrapseed, sizeof(wrapseed));
|
||||
wrapfd_setseed(wrapseed);
|
||||
|
||||
int fakesock = wrapfd_new_fuzzinput();
|
||||
|
||||
m_malloc_set_epoch(1);
|
||||
fuzz.do_jmp = 1;
|
||||
if (setjmp(fuzz.jmp) == 0) {
|
||||
svr_session(fakesock, fakesock);
|
||||
m_malloc_free_epoch(1, 0);
|
||||
} else {
|
||||
fuzz.do_jmp = 0;
|
||||
m_malloc_free_epoch(1, 1);
|
||||
TRACE(("dropbear_exit longjmped"))
|
||||
/* dropbear_exit jumped here */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths) {
|
||||
static int once = 0;
|
||||
if (!once) {
|
||||
fuzz_cli_setup();
|
||||
fuzz.skip_kexmaths = skip_kexmaths;
|
||||
once = 1;
|
||||
}
|
||||
|
||||
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Allow to proceed sooner
|
||||
ses.kexstate.donefirstkex = 1;
|
||||
|
||||
uint32_t wrapseed;
|
||||
genrandom((void*)&wrapseed, sizeof(wrapseed));
|
||||
wrapfd_setseed(wrapseed);
|
||||
|
||||
int fakesock = wrapfd_new_fuzzinput();
|
||||
|
||||
m_malloc_set_epoch(1);
|
||||
fuzz.do_jmp = 1;
|
||||
if (setjmp(fuzz.jmp) == 0) {
|
||||
cli_session(fakesock, fakesock, NULL, 0);
|
||||
m_malloc_free_epoch(1, 0);
|
||||
} else {
|
||||
fuzz.do_jmp = 0;
|
||||
m_malloc_free_epoch(1, 1);
|
||||
TRACE(("dropbear_exit longjmped"))
|
||||
/* dropbear_exit jumped here */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const void* fuzz_get_algo(const algo_type *algos, const char* name) {
|
||||
const algo_type *t;
|
||||
for (t = algos; t->name; t++) {
|
||||
if (strcmp(t->name, name) == 0) {
|
||||
return t->data;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void fuzz_dump(const unsigned char* data, size_t len) {
|
||||
if (fuzz.dumping) {
|
||||
TRACE(("dump %zu", len))
|
||||
assert(atomicio(vwrite, fuzz.recv_dumpfd, (void*)data, len) == len);
|
||||
}
|
||||
}
|
||||
|
||||
static struct passwd pwd_root = {
|
||||
.pw_name = "root",
|
||||
.pw_passwd = "!",
|
||||
.pw_uid = 0,
|
||||
.pw_gid = 0,
|
||||
.pw_dir = "/root",
|
||||
.pw_shell = "/bin/sh",
|
||||
};
|
||||
|
||||
static struct passwd pwd_other = {
|
||||
.pw_name = "other",
|
||||
.pw_passwd = "!",
|
||||
.pw_uid = 100,
|
||||
.pw_gid = 100,
|
||||
.pw_dir = "/home/other",
|
||||
.pw_shell = "/bin/sh",
|
||||
};
|
||||
|
||||
|
||||
/* oss-fuzz runs fuzzers under minijail, without /etc/passwd.
|
||||
We provide sufficient values for the fuzzers to run */
|
||||
struct passwd* fuzz_getpwnam(const char *login) {
|
||||
if (!fuzz.fuzzing) {
|
||||
return getpwnam(login);
|
||||
}
|
||||
if (strcmp(login, pwd_other.pw_name) == 0) {
|
||||
return &pwd_other;
|
||||
}
|
||||
if (strcmp(login, pwd_root.pw_name) == 0) {
|
||||
return &pwd_root;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct passwd* fuzz_getpwuid(uid_t uid) {
|
||||
if (!fuzz.fuzzing) {
|
||||
return getpwuid(uid);
|
||||
}
|
||||
if (uid == pwd_other.pw_uid) {
|
||||
return &pwd_other;
|
||||
}
|
||||
if (uid == pwd_root.pw_uid) {
|
||||
return &pwd_root;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -7,15 +7,19 @@ extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
|
||||
int main(int argc, char ** argv) {
|
||||
int i;
|
||||
buffer *input = buf_new(100000);
|
||||
int quiet = 0;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
printf("arg %s\n", argv[i]);
|
||||
#if DEBUG_TRACE
|
||||
if (strcmp(argv[i], "-v") == 0) {
|
||||
debug_trace = 1;
|
||||
TRACE(("debug printing on"))
|
||||
}
|
||||
#endif
|
||||
if (strcmp(argv[i], "-q") == 0) {
|
||||
printf("Running quiet\n");
|
||||
quiet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int old_fuzz_wrapfds = 0;
|
||||
@@ -30,12 +34,19 @@ int main(int argc, char ** argv) {
|
||||
buf_readfile(input, fn);
|
||||
buf_setpos(input, 0);
|
||||
|
||||
/* Run twice to catch problems with statefulness */
|
||||
fuzz.wrapfds = old_fuzz_wrapfds;
|
||||
printf("Running %s once \n", fn);
|
||||
if (!quiet) {
|
||||
printf("Running %s once \n", fn);
|
||||
}
|
||||
LLVMFuzzerTestOneInput(input->data, input->len);
|
||||
printf("Running %s twice \n", fn);
|
||||
if (!quiet) {
|
||||
printf("Running %s twice \n", fn);
|
||||
}
|
||||
LLVMFuzzerTestOneInput(input->data, input->len);
|
||||
printf("Done %s\n", fn);
|
||||
if (!quiet) {
|
||||
printf("Done %s\n", fn);
|
||||
}
|
||||
|
||||
/* Disable wrapfd so it won't interfere with buf_readfile() above */
|
||||
old_fuzz_wrapfds = fuzz.wrapfds;
|
||||
@@ -46,3 +57,10 @@ int main(int argc, char ** argv) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Just to let it link
|
||||
size_t LLVMFuzzerMutate(uint8_t *UNUSED(Data), size_t UNUSED(Size), size_t UNUSED(MaxSize)) {
|
||||
printf("standalone fuzzer harness shouldn't call LLVMFuzzerMutate");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/* To be included in fuzz-common.c */
|
||||
|
||||
unsigned char keyr[] = {
|
||||
static unsigned char keyr[] = {
|
||||
0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00,
|
||||
0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xb1,
|
||||
0x06, 0x95, 0xc9, 0xa8, 0x38, 0xb9, 0x99, 0x91, 0xb5, 0x17, 0x39, 0xb9,
|
||||
@@ -69,8 +70,8 @@ unsigned char keyr[] = {
|
||||
0xb0, 0x9b, 0xea, 0x18, 0x77, 0xf6, 0x25, 0x02, 0xb4, 0x5e, 0x71, 0xea,
|
||||
0xa3
|
||||
};
|
||||
unsigned int keyr_len = 805;
|
||||
unsigned char keye[] = {
|
||||
static unsigned int keyr_len = 805;
|
||||
static unsigned char keye[] = {
|
||||
0x00, 0x00, 0x00, 0x13, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x73, 0x68,
|
||||
0x61, 0x32, 0x2d, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00,
|
||||
0x00, 0x00, 0x08, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00,
|
||||
@@ -84,8 +85,8 @@ unsigned char keye[] = {
|
||||
0x3c, 0x58, 0x28, 0x70, 0x9b, 0x23, 0x39, 0x51, 0xd7, 0xbc, 0xa7, 0x1a,
|
||||
0xf5, 0xb4, 0x23, 0xd3, 0xf6, 0x17, 0xa6, 0x9c, 0x02
|
||||
};
|
||||
unsigned int keye_len = 141;
|
||||
unsigned char keyd[] = {
|
||||
static unsigned int keye_len = 141;
|
||||
static unsigned char keyd[] = {
|
||||
0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00,
|
||||
0x00, 0x00, 0x81, 0x00, 0xb0, 0x02, 0x19, 0x8b, 0xf3, 0x46, 0xf9, 0xc5,
|
||||
0x47, 0x78, 0x3d, 0x7f, 0x04, 0x10, 0x0a, 0x43, 0x8e, 0x00, 0x9e, 0xa4,
|
||||
@@ -126,8 +127,8 @@ unsigned char keyd[] = {
|
||||
0x7b, 0xac, 0xaa, 0x0c, 0xa2, 0xca, 0x7b, 0xa8, 0xd4, 0xdf, 0x68, 0x56,
|
||||
0xf9, 0x39
|
||||
};
|
||||
unsigned int keyd_len = 458;
|
||||
unsigned char keyed25519[] = {
|
||||
static unsigned int keyd_len = 458;
|
||||
static unsigned char keyed25519[] = {
|
||||
0x00, 0x00, 0x00, 0x0b, 0x73, 0x73, 0x68, 0x2d, 0x65, 0x64, 0x32, 0x35,
|
||||
0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb3, 0x79, 0x06, 0xe5,
|
||||
0x9b, 0xe7, 0xe4, 0x6e, 0xec, 0xfe, 0xa5, 0x39, 0x21, 0x7c, 0xf6, 0x66,
|
||||
@@ -136,4 +137,4 @@ unsigned char keyed25519[] = {
|
||||
0xa4, 0xd5, 0xe9, 0x23, 0xfe, 0x8e, 0xd6, 0xd4, 0xf9, 0xb1, 0x11, 0x69,
|
||||
0x7c, 0x57, 0x52, 0x0e, 0x41, 0xdb, 0x1b, 0x12, 0x87, 0xfa, 0xc9
|
||||
};
|
||||
unsigned int keyed25519_len = 83;
|
||||
static unsigned int keyed25519_len = 83;
|
||||
306
fuzz/fuzz-sshpacketmutator.c
Normal file
306
fuzz/fuzz-sshpacketmutator.c
Normal file
@@ -0,0 +1,306 @@
|
||||
/* A mutator/crossover for SSH protocol streams.
|
||||
Attempts to mutate each SSH packet individually, keeping
|
||||
lengths intact.
|
||||
It will prepend a SSH-2.0-dbfuzz\r\n version string.
|
||||
|
||||
Linking this file to a binary will make libfuzzer pick up the custom mutator.
|
||||
|
||||
Care is taken to avoid memory allocation which would otherwise
|
||||
slow exec/s substantially */
|
||||
|
||||
#include "fuzz.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
|
||||
|
||||
static const char* FIXED_VERSION = "SSH-2.0-dbfuzz\r\n";
|
||||
static const char* FIXED_IGNORE_MSG =
|
||||
"\x00\x00\x00\x10\x06\x02\x00\x00\x00\x00\x11\x22\x33\x44\x55\x66";
|
||||
static const unsigned int FIXED_IGNORE_MSG_LEN = 16;
|
||||
#define MAX_FUZZ_PACKETS 500
|
||||
/* XXX This might need tuning */
|
||||
static const size_t MAX_OUT_SIZE = 50000;
|
||||
|
||||
/* Splits packets from an input stream buffer "inp".
|
||||
The initial SSH version identifier is discarded.
|
||||
If packets are not recognised it will increment until an uint32 of valid
|
||||
packet length is found. */
|
||||
|
||||
/* out_packets an array of num_out_packets*buffer, each of size RECV_MAX_PACKET_LEN */
|
||||
static void fuzz_get_packets(buffer *inp, buffer **out_packets, unsigned int *num_out_packets) {
|
||||
/* Skip any existing banner. Format is
|
||||
SSH-protoversion-softwareversion SP comments CR LF
|
||||
so we look for SSH-2. then a subsequent LF */
|
||||
unsigned char* version = memmem(inp->data, inp->len, "SSH-2.", strlen("SSH-2."));
|
||||
if (version) {
|
||||
buf_incrpos(inp, version - inp->data);
|
||||
unsigned char* newline = memchr(&inp->data[inp->pos], '\n', inp->len - inp->pos);
|
||||
if (newline) {
|
||||
buf_incrpos(inp, newline - &inp->data[inp->pos]+1);
|
||||
} else {
|
||||
/* Give up on any version string */
|
||||
buf_setpos(inp, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned int max_out_packets = *num_out_packets;
|
||||
*num_out_packets = 0;
|
||||
while (1) {
|
||||
if (inp->pos + 4 > inp->len) {
|
||||
/* End of input */
|
||||
break;
|
||||
}
|
||||
|
||||
if (*num_out_packets >= max_out_packets) {
|
||||
/* End of output */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read packet */
|
||||
unsigned int packet_len = buf_getint(inp);
|
||||
if (packet_len > RECV_MAX_PACKET_LEN-4) {
|
||||
/* Bad length, try skipping a single byte */
|
||||
buf_decrpos(inp, 3);
|
||||
continue;
|
||||
}
|
||||
packet_len = MIN(packet_len, inp->len - inp->pos);
|
||||
|
||||
/* Check the packet length makes sense */
|
||||
if (packet_len >= MIN_PACKET_LEN-4) {
|
||||
/* Copy to output buffer. We're reusing buffers */
|
||||
buffer* new_packet = out_packets[*num_out_packets];
|
||||
(*num_out_packets)++;
|
||||
buf_setlen(new_packet, 0);
|
||||
// packet_len doesn't include itself
|
||||
buf_putint(new_packet, packet_len);
|
||||
buf_putbytes(new_packet, buf_getptr(inp, packet_len), packet_len);
|
||||
}
|
||||
buf_incrpos(inp, packet_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mutate a packet buffer in-place.
|
||||
Returns DROPBEAR_FAILURE if it's too short */
|
||||
static int buf_llvm_mutate(buffer *buf) {
|
||||
int ret;
|
||||
/* Position it after packet_length and padding_length */
|
||||
const unsigned int offset = 5;
|
||||
buf_setpos(buf, 0);
|
||||
buf_incrwritepos(buf, offset);
|
||||
size_t max_size = buf->size - buf->pos;
|
||||
size_t new_size = LLVMFuzzerMutate(buf_getwriteptr(buf, max_size),
|
||||
buf->len - buf->pos, max_size);
|
||||
size_t new_total = new_size + 1 + 4;
|
||||
// Round down to a block size
|
||||
new_total = new_total - (new_total % dropbear_nocipher.blocksize);
|
||||
|
||||
if (new_total >= 16) {
|
||||
buf_setlen(buf, new_total);
|
||||
// Fix up the length fields
|
||||
buf_setpos(buf, 0);
|
||||
// packet_length doesn't include itself, does include padding_length byte
|
||||
buf_putint(buf, new_size+1);
|
||||
// always just put minimum padding length = 4
|
||||
buf_putbyte(buf, 4);
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
} else {
|
||||
// instead put a fake packet
|
||||
buf_setlen(buf, 0);
|
||||
buf_putbytes(buf, FIXED_IGNORE_MSG, FIXED_IGNORE_MSG_LEN);
|
||||
ret = DROPBEAR_FAILURE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Persistent buffers to avoid constant allocations */
|
||||
static buffer *oup;
|
||||
static buffer *alloc_packetA;
|
||||
static buffer *alloc_packetB;
|
||||
static buffer* packets1[MAX_FUZZ_PACKETS];
|
||||
static buffer* packets2[MAX_FUZZ_PACKETS];
|
||||
|
||||
/* Allocate buffers once at startup.
|
||||
'constructor' here so it runs before dbmalloc's interceptor */
|
||||
static void alloc_static_buffers() __attribute__((constructor));
|
||||
static void alloc_static_buffers() {
|
||||
|
||||
int i;
|
||||
oup = buf_new(MAX_OUT_SIZE);
|
||||
alloc_packetA = buf_new(RECV_MAX_PACKET_LEN);
|
||||
alloc_packetB = buf_new(RECV_MAX_PACKET_LEN);
|
||||
|
||||
for (i = 0; i < MAX_FUZZ_PACKETS; i++) {
|
||||
packets1[i] = buf_new(RECV_MAX_PACKET_LEN);
|
||||
}
|
||||
for (i = 0; i < MAX_FUZZ_PACKETS; i++) {
|
||||
packets2[i] = buf_new(RECV_MAX_PACKET_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
|
||||
size_t MaxSize, unsigned int Seed) {
|
||||
|
||||
buf_setlen(alloc_packetA, 0);
|
||||
buf_setlen(alloc_packetB, 0);
|
||||
buf_setlen(oup, 0);
|
||||
|
||||
unsigned int i;
|
||||
size_t ret_len;
|
||||
unsigned short randstate[3] = {0,0,0};
|
||||
memcpy(randstate, &Seed, sizeof(Seed));
|
||||
|
||||
// printhex("mutator input", Data, Size);
|
||||
|
||||
/* 0.1% chance straight llvm mutate */
|
||||
// if (nrand48(randstate) % 1000 == 0) {
|
||||
// ret_len = LLVMFuzzerMutate(Data, Size, MaxSize);
|
||||
// // printhex("mutator straight llvm", Data, ret_len);
|
||||
// return ret_len;
|
||||
// }
|
||||
|
||||
buffer inp_buf = {.data = Data, .size = Size, .len = Size, .pos = 0};
|
||||
buffer *inp = &inp_buf;
|
||||
|
||||
/* Parse packets */
|
||||
unsigned int num_packets = MAX_FUZZ_PACKETS;
|
||||
buffer **packets = packets1;
|
||||
fuzz_get_packets(inp, packets, &num_packets);
|
||||
|
||||
if (num_packets == 0) {
|
||||
// Make up a packet, writing direct to the buffer
|
||||
inp->size = MaxSize;
|
||||
buf_setlen(inp, 0);
|
||||
buf_putbytes(inp, FIXED_VERSION, strlen(FIXED_VERSION));
|
||||
buf_putbytes(inp, FIXED_IGNORE_MSG, FIXED_IGNORE_MSG_LEN);
|
||||
// printhex("mutator no input", Data, inp->len);
|
||||
return inp->len;
|
||||
}
|
||||
|
||||
/* Start output */
|
||||
/* Put a new banner to output */
|
||||
buf_putbytes(oup, FIXED_VERSION, strlen(FIXED_VERSION));
|
||||
|
||||
/* Iterate output */
|
||||
for (i = 0; i < num_packets+1; i++) {
|
||||
// These are pointers to output
|
||||
buffer *out_packetA = NULL, *out_packetB = NULL;
|
||||
buf_setlen(alloc_packetA, 0);
|
||||
buf_setlen(alloc_packetB, 0);
|
||||
|
||||
/* 2% chance each */
|
||||
const int optA = nrand48(randstate) % 50;
|
||||
if (optA == 0) {
|
||||
/* Copy another */
|
||||
unsigned int other = nrand48(randstate) % num_packets;
|
||||
out_packetA = packets[other];
|
||||
// printf("copy another %d / %d len %u\n", other, num_packets, out_packetA->len);
|
||||
}
|
||||
if (optA == 1) {
|
||||
/* Mutate another */
|
||||
unsigned int other = nrand48(randstate) % num_packets;
|
||||
out_packetA = alloc_packetA;
|
||||
buffer *from = packets[other];
|
||||
buf_putbytes(out_packetA, from->data, from->len);
|
||||
if (buf_llvm_mutate(out_packetA) == DROPBEAR_FAILURE) {
|
||||
out_packetA = NULL;
|
||||
}
|
||||
// printf("mutate another %d / %d len %u -> %u\n", other, num_packets, from->len, out_packetA->len);
|
||||
}
|
||||
|
||||
if (i < num_packets) {
|
||||
int optB = nrand48(randstate) % 100;
|
||||
if (optB == 1) {
|
||||
/* small chance of drop */
|
||||
/* Drop it */
|
||||
//printf("%d drop\n", i);
|
||||
} else {
|
||||
/* Odds of modification are proportional to packet position.
|
||||
First packet has 20% chance, last has 100% chance */
|
||||
int optC = nrand48(randstate) % 1000;
|
||||
int mutate_cutoff = MAX(200, (1000 * (i+1) / num_packets));
|
||||
if (optC < mutate_cutoff) {
|
||||
// // printf("%d mutate\n", i);
|
||||
out_packetB = alloc_packetB;
|
||||
buffer *from = packets[i];
|
||||
buf_putbytes(out_packetB, from->data, from->len);
|
||||
if (buf_llvm_mutate(out_packetB) == DROPBEAR_FAILURE) {
|
||||
out_packetB = from;
|
||||
}
|
||||
// printf("mutate self %d / %d len %u -> %u\n", i, num_packets, from->len, out_packetB->len);
|
||||
} else {
|
||||
/* Copy as-is */
|
||||
out_packetB = packets[i];
|
||||
// printf("%d as-is len %u\n", i, out_packetB->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (out_packetA && oup->len + out_packetA->len <= oup->size) {
|
||||
buf_putbytes(oup, out_packetA->data, out_packetA->len);
|
||||
}
|
||||
if (out_packetB && oup->len + out_packetB->len <= oup->size) {
|
||||
buf_putbytes(oup, out_packetB->data, out_packetB->len);
|
||||
}
|
||||
}
|
||||
|
||||
ret_len = MIN(MaxSize, oup->len);
|
||||
memcpy(Data, oup->data, ret_len);
|
||||
// printhex("mutator done", Data, ret_len);
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
|
||||
const uint8_t *Data2, size_t Size2,
|
||||
uint8_t *Out, size_t MaxOutSize,
|
||||
unsigned int Seed) {
|
||||
unsigned short randstate[3] = {0,0,0};
|
||||
memcpy(randstate, &Seed, sizeof(Seed));
|
||||
|
||||
unsigned int i;
|
||||
buffer inp_buf1 = {.data = (void*)Data1, .size = Size1, .len = Size1, .pos = 0};
|
||||
buffer *inp1 = &inp_buf1;
|
||||
buffer inp_buf2 = {.data = (void*)Data2, .size = Size2, .len = Size2, .pos = 0};
|
||||
buffer *inp2 = &inp_buf2;
|
||||
|
||||
unsigned int num_packets1 = MAX_FUZZ_PACKETS;
|
||||
fuzz_get_packets(inp1, packets1, &num_packets1);
|
||||
unsigned int num_packets2 = MAX_FUZZ_PACKETS;
|
||||
fuzz_get_packets(inp2, packets2, &num_packets2);
|
||||
|
||||
// fprintf(stderr, "input 1 %u packets\n", num_packets1);
|
||||
// printhex("crossover input1", Data1, Size1);
|
||||
// fprintf(stderr, "input 2 %u packets\n", num_packets2);
|
||||
// printhex("crossover input2", Data2, Size2);
|
||||
|
||||
buf_setlen(oup, 0);
|
||||
/* Put a new banner to output */
|
||||
buf_putbytes(oup, FIXED_VERSION, strlen(FIXED_VERSION));
|
||||
|
||||
if (num_packets1 == 0 && num_packets2 == 0) {
|
||||
buf_putbytes(oup, FIXED_IGNORE_MSG, FIXED_IGNORE_MSG_LEN);
|
||||
} else {
|
||||
unsigned int min_out = MIN(num_packets1, num_packets2);
|
||||
unsigned int max_out = num_packets1 + num_packets2;
|
||||
unsigned int num_out = min_out + nrand48(randstate) % (max_out-min_out+1);
|
||||
|
||||
for (i = 0; i < num_out; i++) {
|
||||
unsigned int choose = nrand48(randstate) % (num_packets1 + num_packets2);
|
||||
buffer *p = NULL;
|
||||
if (choose < num_packets1) {
|
||||
p = packets1[choose];
|
||||
} else {
|
||||
p = packets2[choose-num_packets1];
|
||||
}
|
||||
if (oup->len + p->len <= oup->size) {
|
||||
buf_putbytes(oup, p->data, p->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t ret_len = MIN(MaxOutSize, oup->len);
|
||||
memcpy(Out, oup->data, ret_len);
|
||||
// printhex("crossover output", Out, ret_len);
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
@@ -17,25 +17,33 @@ static const double CHANCE_WRITE2 = 0.5;
|
||||
|
||||
struct fdwrap {
|
||||
enum wrapfd_mode mode;
|
||||
buffer *buf;
|
||||
int closein;
|
||||
int closeout;
|
||||
};
|
||||
|
||||
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
|
||||
/* for quick selection of in-use descriptors */
|
||||
static int wrap_used[IOWRAP_MAXFD+1];
|
||||
static unsigned int nused;
|
||||
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1] = {{UNUSED, 0, 0}};
|
||||
static int wrapfd_maxfd = -1;
|
||||
static unsigned short rand_state[3];
|
||||
static buffer *input_buf;
|
||||
static int devnull_fd = -1;
|
||||
|
||||
void wrapfd_setup(void) {
|
||||
static void wrapfd_remove(int fd);
|
||||
|
||||
void wrapfd_setup(buffer *buf) {
|
||||
TRACE(("wrapfd_setup"))
|
||||
nused = 0;
|
||||
memset(wrap_fds, 0x0, sizeof(wrap_fds));
|
||||
memset(wrap_used, 0x0, sizeof(wrap_used));
|
||||
|
||||
// clean old ones
|
||||
int i;
|
||||
for (i = 0; i <= wrapfd_maxfd; i++) {
|
||||
if (wrap_fds[i].mode != UNUSED) {
|
||||
wrapfd_remove(i);
|
||||
}
|
||||
}
|
||||
wrapfd_maxfd = -1;
|
||||
|
||||
memset(rand_state, 0x0, sizeof(rand_state));
|
||||
wrapfd_setseed(50);
|
||||
input_buf = buf;
|
||||
}
|
||||
|
||||
void wrapfd_setseed(uint32_t seed) {
|
||||
@@ -43,39 +51,55 @@ void wrapfd_setseed(uint32_t seed) {
|
||||
nrand48(rand_state);
|
||||
}
|
||||
|
||||
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
|
||||
TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
|
||||
assert(fd >= 0);
|
||||
assert(fd <= IOWRAP_MAXFD);
|
||||
assert(wrap_fds[fd].mode == UNUSED);
|
||||
assert(buf || mode == RANDOMIN);
|
||||
int wrapfd_new_fuzzinput() {
|
||||
if (devnull_fd == -1) {
|
||||
devnull_fd = open("/dev/null", O_RDONLY);
|
||||
assert(devnull_fd != -1);
|
||||
}
|
||||
|
||||
wrap_fds[fd].mode = mode;
|
||||
wrap_fds[fd].buf = buf;
|
||||
int fd = dup(devnull_fd);
|
||||
assert(fd != -1);
|
||||
assert(wrap_fds[fd].mode == UNUSED);
|
||||
wrap_fds[fd].mode = COMMONBUF;
|
||||
wrap_fds[fd].closein = 0;
|
||||
wrap_fds[fd].closeout = 0;
|
||||
wrap_used[nused] = fd;
|
||||
wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
|
||||
|
||||
nused++;
|
||||
return fd;
|
||||
}
|
||||
|
||||
void wrapfd_remove(int fd) {
|
||||
unsigned int i, j;
|
||||
int wrapfd_new_dummy() {
|
||||
if (devnull_fd == -1) {
|
||||
devnull_fd = open("/dev/null", O_RDONLY);
|
||||
assert(devnull_fd != -1);
|
||||
}
|
||||
|
||||
int fd = dup(devnull_fd);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (fd > IOWRAP_MAXFD) {
|
||||
close(fd);
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
assert(wrap_fds[fd].mode == UNUSED);
|
||||
wrap_fds[fd].mode = DUMMY;
|
||||
wrap_fds[fd].closein = 0;
|
||||
wrap_fds[fd].closeout = 0;
|
||||
wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
static void wrapfd_remove(int fd) {
|
||||
TRACE(("wrapfd_remove %d", fd))
|
||||
assert(fd >= 0);
|
||||
assert(fd <= IOWRAP_MAXFD);
|
||||
assert(wrap_fds[fd].mode != UNUSED);
|
||||
wrap_fds[fd].mode = UNUSED;
|
||||
|
||||
|
||||
/* remove from used list */
|
||||
for (i = 0, j = 0; i < nused; i++) {
|
||||
if (wrap_used[i] != fd) {
|
||||
wrap_used[j] = wrap_used[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
nused--;
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int wrapfd_close(int fd) {
|
||||
@@ -89,7 +113,6 @@ int wrapfd_close(int fd) {
|
||||
|
||||
int wrapfd_read(int fd, void *out, size_t count) {
|
||||
size_t maxread;
|
||||
buffer *buf;
|
||||
|
||||
if (!fuzz.wrapfds) {
|
||||
return read(fd, out, count);
|
||||
@@ -115,18 +138,18 @@ int wrapfd_read(int fd, void *out, size_t count) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = wrap_fds[fd].buf;
|
||||
if (buf) {
|
||||
maxread = MIN(buf->len - buf->pos, count);
|
||||
if (input_buf && wrap_fds[fd].mode == COMMONBUF) {
|
||||
maxread = MIN(input_buf->len - input_buf->pos, count);
|
||||
/* returns 0 if buf is EOF, as intended */
|
||||
if (maxread > 0) {
|
||||
maxread = nrand48(rand_state) % maxread + 1;
|
||||
}
|
||||
memcpy(out, buf_getptr(buf, maxread), maxread);
|
||||
buf_incrpos(buf, maxread);
|
||||
memcpy(out, buf_getptr(input_buf, maxread), maxread);
|
||||
buf_incrpos(input_buf, maxread);
|
||||
return maxread;
|
||||
}
|
||||
|
||||
// return fixed output, of random length
|
||||
maxread = MIN(MAX_RANDOM_IN, count);
|
||||
maxread = nrand48(rand_state) % maxread + 1;
|
||||
memset(out, 0xef, maxread);
|
||||
@@ -175,8 +198,6 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
int ret = 0;
|
||||
int fdlist[IOWRAP_MAXFD+1];
|
||||
|
||||
memset(fdlist, 0x0, sizeof(fdlist));
|
||||
|
||||
if (!fuzz.wrapfds) {
|
||||
return select(nfds, readfds, writefds, exceptfds, timeout);
|
||||
}
|
||||
@@ -244,3 +265,15 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fuzz_kill(pid_t pid, int sig) {
|
||||
if (fuzz.fuzzing) {
|
||||
TRACE(("fuzz_kill ignoring pid %d signal %d", (pid), sig))
|
||||
if (sig >= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return kill(pid, sig);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fuzz.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
return fuzz_run_preauth(Data, Size, 0);
|
||||
return fuzz_run_client(Data, Size, 0);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fuzz.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
return fuzz_run_preauth(Data, Size, 1);
|
||||
return fuzz_run_client(Data, Size, 1);
|
||||
}
|
||||
|
||||
@@ -6,33 +6,30 @@
|
||||
#include "algo.h"
|
||||
#include "bignum.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
static int once = 0;
|
||||
static struct key_context* keep_newkeys = NULL;
|
||||
/* number of generated parameters is limited by the timeout for the first run.
|
||||
TODO move this to the libfuzzer initialiser function instead if the timeout
|
||||
doesn't apply there */
|
||||
#define NUM_PARAMS 20
|
||||
static struct kex_curve25519_param *curve25519_params[NUM_PARAMS];
|
||||
static struct key_context* keep_newkeys = NULL;
|
||||
/* An arbitrary limit */
|
||||
#define NUM_PARAMS 80
|
||||
static struct kex_curve25519_param *curve25519_params[NUM_PARAMS];
|
||||
|
||||
if (!once) {
|
||||
fuzz_common_setup();
|
||||
fuzz_svr_setup();
|
||||
static void setup() __attribute__((constructor));
|
||||
// Perform initial setup here to avoid hitting timeouts on first run
|
||||
static void setup() {
|
||||
fuzz_common_setup();
|
||||
fuzz_svr_setup();
|
||||
|
||||
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "curve25519-sha256");
|
||||
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ED25519;
|
||||
ses.newkeys = keep_newkeys;
|
||||
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "curve25519-sha256");
|
||||
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ED25519;
|
||||
ses.newkeys = keep_newkeys;
|
||||
|
||||
/* Pre-generate parameters */
|
||||
int i;
|
||||
for (i = 0; i < NUM_PARAMS; i++) {
|
||||
curve25519_params[i] = gen_kexcurve25519_param();
|
||||
}
|
||||
|
||||
once = 1;
|
||||
/* Pre-generate parameters */
|
||||
int i;
|
||||
for (i = 0; i < NUM_PARAMS; i++) {
|
||||
curve25519_params[i] = gen_kexcurve25519_param();
|
||||
}
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
|
||||
return 0;
|
||||
}
|
||||
@@ -6,33 +6,29 @@
|
||||
#include "algo.h"
|
||||
#include "bignum.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
static int once = 0;
|
||||
static struct key_context* keep_newkeys = NULL;
|
||||
/* number of generated parameters is limited by the timeout for the first run.
|
||||
TODO move this to the libfuzzer initialiser function instead if the timeout
|
||||
doesn't apply there */
|
||||
#define NUM_PARAMS 20
|
||||
static struct kex_dh_param *dh_params[NUM_PARAMS];
|
||||
static struct key_context* keep_newkeys = NULL;
|
||||
#define NUM_PARAMS 80
|
||||
static struct kex_dh_param *dh_params[NUM_PARAMS];
|
||||
|
||||
if (!once) {
|
||||
fuzz_common_setup();
|
||||
fuzz_svr_setup();
|
||||
static void setup() __attribute__((constructor));
|
||||
// Perform initial setup here to avoid hitting timeouts on first run
|
||||
static void setup() {
|
||||
fuzz_common_setup();
|
||||
fuzz_svr_setup();
|
||||
|
||||
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "diffie-hellman-group14-sha256");
|
||||
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
||||
ses.newkeys = keep_newkeys;
|
||||
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "diffie-hellman-group14-sha256");
|
||||
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
||||
ses.newkeys = keep_newkeys;
|
||||
|
||||
/* Pre-generate parameters */
|
||||
int i;
|
||||
for (i = 0; i < NUM_PARAMS; i++) {
|
||||
dh_params[i] = gen_kexdh_param();
|
||||
}
|
||||
|
||||
once = 1;
|
||||
/* Pre-generate parameters */
|
||||
int i;
|
||||
for (i = 0; i < NUM_PARAMS; i++) {
|
||||
dh_params[i] = gen_kexdh_param();
|
||||
}
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
|
||||
return 0;
|
||||
}
|
||||
@@ -6,38 +6,38 @@
|
||||
#include "algo.h"
|
||||
#include "bignum.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
static int once = 0;
|
||||
static const struct dropbear_kex *ecdh[3]; /* 256, 384, 521 */
|
||||
static struct key_context* keep_newkeys = NULL;
|
||||
/* number of generated parameters is limited by the timeout for the first run */
|
||||
#define NUM_PARAMS 80
|
||||
static struct kex_ecdh_param *ecdh_params[NUM_PARAMS];
|
||||
static const struct dropbear_kex *ecdh[3]; /* 256, 384, 521 */
|
||||
static struct key_context* keep_newkeys = NULL;
|
||||
/* number of generated parameters. An arbitrary limit, but will delay startup */
|
||||
#define NUM_PARAMS 80
|
||||
static struct kex_ecdh_param *ecdh_params[NUM_PARAMS];
|
||||
|
||||
if (!once) {
|
||||
fuzz_common_setup();
|
||||
fuzz_svr_setup();
|
||||
static void setup() __attribute__((constructor));
|
||||
// Perform initial setup here to avoid hitting timeouts on first run
|
||||
static void setup() {
|
||||
fuzz_common_setup();
|
||||
fuzz_svr_setup();
|
||||
|
||||
/* ses gets zeroed by fuzz_set_input */
|
||||
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
ecdh[0] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp256");
|
||||
ecdh[1] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp384");
|
||||
ecdh[2] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp521");
|
||||
assert(ecdh[0]);
|
||||
assert(ecdh[1]);
|
||||
assert(ecdh[2]);
|
||||
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
||||
ses.newkeys = keep_newkeys;
|
||||
/* ses gets zeroed by fuzz_set_input */
|
||||
keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
ecdh[0] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp256");
|
||||
ecdh[1] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp384");
|
||||
ecdh[2] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp521");
|
||||
assert(ecdh[0]);
|
||||
assert(ecdh[1]);
|
||||
assert(ecdh[2]);
|
||||
keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
||||
ses.newkeys = keep_newkeys;
|
||||
|
||||
/* Pre-generate parameters */
|
||||
int i;
|
||||
for (i = 0; i < NUM_PARAMS; i++) {
|
||||
ses.newkeys->algo_kex = ecdh[i % 3];
|
||||
ecdh_params[i] = gen_kexecdh_param();
|
||||
}
|
||||
|
||||
once = 1;
|
||||
/* Pre-generate parameters */
|
||||
int i;
|
||||
for (i = 0; i < NUM_PARAMS; i++) {
|
||||
ses.newkeys->algo_kex = ecdh[i % 3];
|
||||
ecdh_params[i] = gen_kexecdh_param();
|
||||
}
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
|
||||
if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
|
||||
return 0;
|
||||
6
fuzz/fuzzer-postauth_nomaths.c
Normal file
6
fuzz/fuzzer-postauth_nomaths.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "fuzz.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
return fuzz_run_server(Data, Size, 1, 1);
|
||||
}
|
||||
|
||||
6
fuzz/fuzzer-preauth.c
Normal file
6
fuzz/fuzzer-preauth.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "fuzz.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
return fuzz_run_server(Data, Size, 0, 0);
|
||||
}
|
||||
|
||||
6
fuzz/fuzzer-preauth_nomaths.c
Normal file
6
fuzz/fuzzer-preauth_nomaths.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "fuzz.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
return fuzz_run_server(Data, Size, 1, 0);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
unsigned int algolen;
|
||||
char* algoname = buf_getstring(keyblob, &algolen);
|
||||
|
||||
if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNKEY_NONE) {
|
||||
if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNATURE_NONE) {
|
||||
dropbear_exit("fuzzer imagined a bogus algorithm");
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
|
||||
result=0
|
||||
|
||||
test -d fuzzcorpus && hg --repository fuzzcorpus/ pull || hg clone https://secure.ucc.asn.au/hg/dropbear-fuzzcorpus fuzzcorpus || exit 1
|
||||
test -d fuzzcorpus && hg --repository fuzzcorpus/ pull || hg clone https://hg.ucc.asn.au/dropbear-fuzzcorpus fuzzcorpus || exit 1
|
||||
for f in `make list-fuzz-targets`; do
|
||||
./$f fuzzcorpus/$f/* || result=1
|
||||
# use xargs to split the too-long argument list
|
||||
# -q quiet because travis has a logfile limit
|
||||
echo fuzzcorpus/$f/* | xargs -n 1000 ./$f -q || result=1
|
||||
done
|
||||
|
||||
exit $result
|
||||
|
||||
@@ -25,9 +25,6 @@
|
||||
#ifndef DROPBEAR_INCLUDES_H_
|
||||
#define DROPBEAR_INCLUDES_H_
|
||||
|
||||
/* uclibc needs _GNU_SOURCE, maybe other things? */
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "options.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
@@ -637,7 +637,7 @@ static sign_key *openssh_read(const char *filename, const char * UNUSED(passphra
|
||||
buf_incrpos(blobbuf, 8);
|
||||
buf_eatstring(blobbuf);
|
||||
buf_eatstring(blobbuf);
|
||||
buf_incrpos(blobbuf, -SSH_SIGNKEY_ED25519_LEN-4);
|
||||
buf_decrpos(blobbuf, SSH_SIGNKEY_ED25519_LEN+4);
|
||||
if (buf_get_ed25519_priv_key(blobbuf, retkey->ed25519key)
|
||||
== DROPBEAR_SUCCESS) {
|
||||
errmsg = NULL;
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
|
||||
/* SPDX-License-Identifier: Unlicense */
|
||||
|
||||
mp_err(*s_mp_rand_source)(void *out, size_t size) = s_mp_rand_platform;
|
||||
/* Dropbear sets this separately, avoid platform code */
|
||||
mp_err(*s_mp_rand_source)(void *out, size_t size) = NULL;
|
||||
|
||||
void mp_rand_source(mp_err(*source)(void *out, size_t size))
|
||||
{
|
||||
s_mp_rand_source = (source == NULL) ? s_mp_rand_platform : source;
|
||||
/* Dropbear, don't reset to platform if source==NULL */
|
||||
s_mp_rand_source = source;
|
||||
}
|
||||
|
||||
mp_err mp_rand(mp_int *a, int digits)
|
||||
|
||||
@@ -1316,6 +1316,8 @@
|
||||
#undef BN_S_MP_KARATSUBA_SQR_C
|
||||
#undef BN_S_MP_TOOM_MUL_C
|
||||
#undef BN_S_MP_TOOM_SQR_C
|
||||
/* Dropbear uses its own random source */
|
||||
#undef BN_S_MP_RAND_PLATFORM_C
|
||||
|
||||
#include "dbmalloc.h"
|
||||
#define MP_MALLOC m_malloc
|
||||
|
||||
@@ -139,7 +139,7 @@ struct Listener * get_listener(int type, const void* typedata,
|
||||
struct Listener* listener;
|
||||
|
||||
for (i = 0, listener = ses.listeners[i]; i < ses.listensize; i++) {
|
||||
if (listener->type == type
|
||||
if (listener && listener->type == type
|
||||
&& match(typedata, listener->typedata)) {
|
||||
return listener;
|
||||
}
|
||||
|
||||
39
netio.c
39
netio.c
@@ -188,6 +188,13 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons
|
||||
|
||||
list_append(&ses.conn_pending, c);
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing) {
|
||||
c->errstring = m_strdup("fuzzing connect_remote always fails");
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
@@ -453,8 +460,16 @@ int dropbear_listen(const char* address, const char* port,
|
||||
struct linger linger;
|
||||
int val;
|
||||
int sock;
|
||||
|
||||
uint16_t *allocated_lport_p = NULL;
|
||||
int allocated_lport = 0;
|
||||
|
||||
TRACE(("enter dropbear_listen"))
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing) {
|
||||
return fuzz_dropbear_listen(address, port, socks, sockcount, errstring, maxfd);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
|
||||
@@ -490,20 +505,15 @@ int dropbear_listen(const char* address, const char* port,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* when listening on server-assigned-port 0
|
||||
/* When listening on server-assigned-port 0
|
||||
* the assigned ports may differ for address families (v4/v6)
|
||||
* causing problems for tcpip-forward
|
||||
* caller can do a get_socket_address to discover assigned-port
|
||||
* hence, use same port for all address families
|
||||
*/
|
||||
u_int16_t *allocated_lport_p = NULL;
|
||||
int allocated_lport = 0;
|
||||
|
||||
* causing problems for tcpip-forward.
|
||||
* Caller can do a get_socket_address to discover assigned-port
|
||||
* hence, use same port for all address families */
|
||||
allocated_lport = 0;
|
||||
nsock = 0;
|
||||
for (res = res0; res != NULL && nsock < sockcount;
|
||||
res = res->ai_next) {
|
||||
|
||||
if (allocated_lport > 0) {
|
||||
if (AF_INET == res->ai_family) {
|
||||
allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
|
||||
@@ -514,11 +524,8 @@ int dropbear_listen(const char* address, const char* port,
|
||||
}
|
||||
|
||||
/* Get a socket */
|
||||
socks[nsock] = socket(res->ai_family, res->ai_socktype,
|
||||
res->ai_protocol);
|
||||
|
||||
socks[nsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
sock = socks[nsock]; /* For clarity */
|
||||
|
||||
if (sock < 0) {
|
||||
err = errno;
|
||||
TRACE(("socket() failed"))
|
||||
@@ -542,7 +549,6 @@ int dropbear_listen(const char* address, const char* port,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
set_sock_nodelay(sock);
|
||||
|
||||
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
@@ -564,7 +570,6 @@ int dropbear_listen(const char* address, const char* port,
|
||||
}
|
||||
|
||||
*maxfd = MAX(*maxfd, sock);
|
||||
|
||||
nsock++;
|
||||
}
|
||||
|
||||
|
||||
5
packet.c
5
packet.c
@@ -344,7 +344,12 @@ void decrypt_packet() {
|
||||
if (checkmac() != DROPBEAR_SUCCESS) {
|
||||
dropbear_exit("Integrity error");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if DROPBEAR_FUZZ
|
||||
fuzz_dump(ses.readbuf->data, ses.readbuf->len);
|
||||
#endif
|
||||
|
||||
/* get padding length */
|
||||
buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
|
||||
|
||||
23
release.sh
23
release.sh
@@ -1,4 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
VERSION=$(echo '#include "sysoptions.h"\necho DROPBEAR_VERSION' | cpp - | sh)
|
||||
echo Releasing version "$VERSION" ...
|
||||
if ! head -n1 CHANGES | grep -q $VERSION ; then
|
||||
@@ -13,7 +16,11 @@ fi
|
||||
|
||||
head -n1 CHANGES
|
||||
|
||||
#sleep 3
|
||||
if tar --version | grep -q 'GNU tar'; then
|
||||
TAR=tar
|
||||
else
|
||||
TAR=gtar
|
||||
fi
|
||||
|
||||
RELDIR=$PWD/../dropbear-$VERSION
|
||||
ARCHIVE=${RELDIR}.tar.bz2
|
||||
@@ -29,13 +36,17 @@ fi
|
||||
|
||||
hg archive "$RELDIR" || exit 2
|
||||
|
||||
(cd "$RELDIR" && autoconf && autoheader) || exit 2
|
||||
|
||||
rm -r "$RELDIR/autom4te.cache" || exit 2
|
||||
|
||||
rm "$RELDIR/.hgtags"
|
||||
# .hg_archival.txt seems to differ between hg versions, isn't good for reproducibility
|
||||
rm "$RELDIR/.hg_archival.txt"
|
||||
|
||||
(cd "$RELDIR/.." && tar cjf $ARCHIVE `basename "$RELDIR"`) || exit 2
|
||||
RELDATE=$(head -n1 CHANGES | cut -d - -f 2)
|
||||
# timezone keeps it consistent, choose a plausible release time
|
||||
RELTIME="22:30:00 +0800"
|
||||
|
||||
# from https://reproducible-builds.org/docs/archives/
|
||||
TAROPTS="--sort=name --owner=0 --group=0 --numeric-owner"
|
||||
(cd "$RELDIR/.." && $TAR cjf $ARCHIVE $TAROPTS --mtime="$RELDATE $RELTIME" `basename "$RELDIR"`) || exit 2
|
||||
|
||||
ls -l $ARCHIVE
|
||||
openssl sha256 $ARCHIVE
|
||||
|
||||
@@ -130,6 +130,8 @@ typedef struct svr_runopts {
|
||||
char *pubkey_plugin_options;
|
||||
#endif
|
||||
|
||||
int pass_on_env;
|
||||
|
||||
} svr_runopts;
|
||||
|
||||
extern svr_runopts svr_opts;
|
||||
@@ -159,6 +161,7 @@ typedef struct cli_runopts {
|
||||
#if DROPBEAR_CLI_ANYTCPFWD
|
||||
int exit_on_fwd_failure;
|
||||
#endif
|
||||
int disable_trivial_auth;
|
||||
#if DROPBEAR_CLI_REMOTETCPFWD
|
||||
m_list * remotefwds;
|
||||
#endif
|
||||
@@ -192,5 +195,6 @@ void parse_ciphers_macs(void);
|
||||
#endif
|
||||
|
||||
void print_version(void);
|
||||
void parse_recv_window(const char* recv_window_arg);
|
||||
|
||||
#endif /* DROPBEAR_RUNOPTS_H_ */
|
||||
|
||||
7
scp.c
7
scp.c
@@ -185,7 +185,7 @@ arg_setup(char *host, char *remuser, char *cmd)
|
||||
}
|
||||
|
||||
int
|
||||
do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
|
||||
do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
|
||||
{
|
||||
int pin[2], pout[2], reserved[2];
|
||||
|
||||
@@ -532,8 +532,7 @@ toremote(char *targ, int argc, char **argv)
|
||||
bp = xmalloc(len);
|
||||
(void) snprintf(bp, len, "%s -t %s", cmd, targ);
|
||||
host = cleanhostname(thost);
|
||||
if (do_cmd(host, tuser, bp, &remin,
|
||||
&remout, argc) < 0)
|
||||
if (do_cmd(host, tuser, bp, &remin, &remout) < 0)
|
||||
exit(1);
|
||||
if (response() < 0)
|
||||
exit(1);
|
||||
@@ -584,7 +583,7 @@ tolocal(int argc, char **argv)
|
||||
len = strlen(src) + CMDNEEDS + 20;
|
||||
bp = xmalloc(len);
|
||||
(void) snprintf(bp, len, "%s -f %s", cmd, src);
|
||||
if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) {
|
||||
if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
|
||||
(void) xfree(bp);
|
||||
++errs;
|
||||
continue;
|
||||
|
||||
@@ -64,6 +64,8 @@ void svr_dropbear_log(int priority, const char* format, va_list param);
|
||||
/* Client */
|
||||
void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress, pid_t proxy_cmd_pid) ATTRIB_NORETURN;
|
||||
void cli_connected(int result, int sock, void* userdata, const char *errstring);
|
||||
void cli_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
|
||||
void cli_dropbear_log(int priority, const char* format, va_list param);
|
||||
void cleantext(char* dirtytext);
|
||||
void kill_proxy_command(void);
|
||||
|
||||
@@ -314,6 +316,7 @@ struct clientsession {
|
||||
|
||||
int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
|
||||
for the last type of auth we tried */
|
||||
int is_trivial_auth;
|
||||
int ignore_next_auth_response;
|
||||
#if DROPBEAR_CLI_INTERACT_AUTH
|
||||
int auth_interact_failed; /* flag whether interactive auth can still
|
||||
|
||||
74
signkey.c
74
signkey.c
@@ -28,6 +28,8 @@
|
||||
#include "buffer.h"
|
||||
#include "ssh.h"
|
||||
#include "ecdsa.h"
|
||||
#include "sk-ecdsa.h"
|
||||
#include "sk-ed25519.h"
|
||||
#include "rsa.h"
|
||||
#include "dss.h"
|
||||
#include "ed25519.h"
|
||||
@@ -43,9 +45,15 @@ static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = {
|
||||
"ecdsa-sha2-nistp256",
|
||||
"ecdsa-sha2-nistp384",
|
||||
"ecdsa-sha2-nistp521",
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
"sk-ecdsa-sha2-nistp256@openssh.com",
|
||||
#endif /* DROPBEAR_SK_ECDSA */
|
||||
#endif /* DROPBEAR_ECDSA */
|
||||
#if DROPBEAR_ED25519
|
||||
"ssh-ed25519",
|
||||
#if DROPBEAR_SK_ED25519
|
||||
"sk-ssh-ed25519@openssh.com",
|
||||
#endif /* DROPBEAR_SK_ED25519 */
|
||||
#endif /* DROPBEAR_ED25519 */
|
||||
/* "rsa-sha2-256" is special-cased below since it is only a signature name, not key type */
|
||||
};
|
||||
@@ -180,11 +188,17 @@ signkey_key_ptr(sign_key *key, enum signkey_type type) {
|
||||
switch (type) {
|
||||
#if DROPBEAR_ED25519
|
||||
case DROPBEAR_SIGNKEY_ED25519:
|
||||
#if DROPBEAR_SK_ED25519
|
||||
case DROPBEAR_SIGNKEY_SK_ED25519:
|
||||
#endif
|
||||
return (void**)&key->ed25519key;
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
#if DROPBEAR_ECC_256
|
||||
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
case DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256:
|
||||
#endif
|
||||
return (void**)&key->ecckey256;
|
||||
#endif
|
||||
#if DROPBEAR_ECC_384
|
||||
@@ -235,7 +249,7 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
*type = keytype;
|
||||
|
||||
/* Rewind the buffer back before "ssh-rsa" etc */
|
||||
buf_incrpos(buf, -len - 4);
|
||||
buf_decrpos(buf, len + 4);
|
||||
|
||||
#if DROPBEAR_DSS
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
||||
@@ -260,7 +274,11 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
if (signkey_is_ecdsa(keytype)) {
|
||||
if (signkey_is_ecdsa(keytype)
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
|| keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
|
||||
#endif
|
||||
) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck) {
|
||||
if (*eck) {
|
||||
@@ -276,10 +294,14 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
if (keytype == DROPBEAR_SIGNKEY_ED25519) {
|
||||
if (keytype == DROPBEAR_SIGNKEY_ED25519
|
||||
#if DROPBEAR_SK_ED25519
|
||||
|| keytype == DROPBEAR_SIGNKEY_SK_ED25519
|
||||
#endif
|
||||
) {
|
||||
ed25519_key_free(key->ed25519key);
|
||||
key->ed25519key = m_malloc(sizeof(*key->ed25519key));
|
||||
ret = buf_get_ed25519_pub_key(buf, key->ed25519key);
|
||||
ret = buf_get_ed25519_pub_key(buf, key->ed25519key, keytype);
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
m_free(key->ed25519key);
|
||||
key->ed25519key = NULL;
|
||||
@@ -287,6 +309,19 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
|
||||
if (0
|
||||
#if DROPBEAR_SK_ED25519
|
||||
|| keytype == DROPBEAR_SIGNKEY_SK_ED25519
|
||||
#endif
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
|| keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
|
||||
#endif
|
||||
) {
|
||||
key->sk_app = buf_getstring(buf, &key->sk_applen);
|
||||
}
|
||||
#endif
|
||||
|
||||
TRACE2(("leave buf_get_pub_key"))
|
||||
|
||||
return ret;
|
||||
@@ -316,7 +351,7 @@ int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
||||
*type = keytype;
|
||||
|
||||
/* Rewind the buffer back before "ssh-rsa" etc */
|
||||
buf_incrpos(buf, -len - 4);
|
||||
buf_decrpos(buf, len + 4);
|
||||
|
||||
#if DROPBEAR_DSS
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
||||
@@ -401,7 +436,11 @@ void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) {
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
if (type == DROPBEAR_SIGNKEY_ED25519) {
|
||||
if (type == DROPBEAR_SIGNKEY_ED25519
|
||||
#if DROPBEAR_SK_ED25519
|
||||
|| type == DROPBEAR_SIGNKEY_SK_ED25519
|
||||
#endif
|
||||
) {
|
||||
buf_put_ed25519_pub_key(pubkeys, key->ed25519key);
|
||||
}
|
||||
#endif
|
||||
@@ -495,6 +534,7 @@ void sign_key_free(sign_key *key) {
|
||||
#endif
|
||||
|
||||
m_free(key->filename);
|
||||
m_free(key->sk_app);
|
||||
|
||||
m_free(key);
|
||||
TRACE2(("leave sign_key_free"))
|
||||
@@ -568,7 +608,7 @@ static char * sign_key_sha1_fingerprint(const unsigned char* keyblob,
|
||||
buflen = 7 + 3*SHA1_HASH_SIZE;
|
||||
ret = (char*)m_malloc(buflen);
|
||||
|
||||
strcpy(ret, "sha1!! ");
|
||||
strcpy(ret, "sha1 ");
|
||||
|
||||
for (i = 0; i < SHA1_HASH_SIZE; i++) {
|
||||
unsigned int pos = 7 + 3*i;
|
||||
@@ -639,6 +679,7 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
|
||||
}
|
||||
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
|
||||
/* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE.
|
||||
* If FAILURE is returned, the position of
|
||||
* buf is undefined. If SUCCESS is returned, buf will be positioned after the
|
||||
@@ -652,6 +693,9 @@ int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype,
|
||||
|
||||
TRACE(("enter buf_verify"))
|
||||
|
||||
printhex("buf", buf->data, buf->pos);
|
||||
printhex("remw", &buf->data[buf->pos], buf->len-buf->pos);
|
||||
|
||||
buf_getint(buf); /* blob length */
|
||||
type_name = buf_getstring(buf, &type_name_len);
|
||||
sigtype = signature_type_from_name(type_name, type_name_len);
|
||||
@@ -695,6 +739,22 @@ int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype,
|
||||
return buf_ed25519_verify(buf, key->ed25519key, data_buf);
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
if (keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck && *eck) {
|
||||
return buf_sk_ecdsa_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_SK_ED25519
|
||||
if (keytype == DROPBEAR_SIGNKEY_SK_ED25519) {
|
||||
dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck && *eck) {
|
||||
return buf_sk_ed25519_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dropbear_exit("Non-matching signing type");
|
||||
return DROPBEAR_FAILURE;
|
||||
|
||||
19
signkey.h
19
signkey.h
@@ -44,9 +44,15 @@ enum signkey_type {
|
||||
DROPBEAR_SIGNKEY_ECDSA_NISTP256,
|
||||
DROPBEAR_SIGNKEY_ECDSA_NISTP384,
|
||||
DROPBEAR_SIGNKEY_ECDSA_NISTP521,
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256,
|
||||
#endif /* DROPBEAR_SK_ECDSA */
|
||||
#endif /* DROPBEAR_ECDSA */
|
||||
#if DROPBEAR_ED25519
|
||||
DROPBEAR_SIGNKEY_ED25519,
|
||||
#if DROPBEAR_SK_ED25519
|
||||
DROPBEAR_SIGNKEY_SK_ED25519,
|
||||
#endif
|
||||
#endif
|
||||
DROPBEAR_SIGNKEY_NUM_NAMED,
|
||||
DROPBEAR_SIGNKEY_ECDSA_KEYGEN = 70, /* just "ecdsa" for keygen */
|
||||
@@ -63,9 +69,15 @@ enum signature_type {
|
||||
DROPBEAR_SIGNATURE_ECDSA_NISTP256 = DROPBEAR_SIGNKEY_ECDSA_NISTP256,
|
||||
DROPBEAR_SIGNATURE_ECDSA_NISTP384 = DROPBEAR_SIGNKEY_ECDSA_NISTP384,
|
||||
DROPBEAR_SIGNATURE_ECDSA_NISTP521 = DROPBEAR_SIGNKEY_ECDSA_NISTP521,
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256 = DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256,
|
||||
#endif /* DROPBEAR_SK_ECDSA */
|
||||
#endif /* DROPBEAR_ECDSA */
|
||||
#if DROPBEAR_ED25519
|
||||
DROPBEAR_SIGNATURE_ED25519 = DROPBEAR_SIGNKEY_ED25519,
|
||||
#if DROPBEAR_SK_ED25519
|
||||
DROPBEAR_SIGNATURE_SK_ED25519 = DROPBEAR_SIGNKEY_SK_ED25519,
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_RSA_SHA1
|
||||
DROPBEAR_SIGNATURE_RSA_SHA1 = 100, /* ssh-rsa signature (sha1) */
|
||||
@@ -110,6 +122,12 @@ struct SIGN_key {
|
||||
#if DROPBEAR_ED25519
|
||||
struct dropbear_ED25519_Key * ed25519key;
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
|
||||
/* application ID for U2F/FIDO key types, a malloced string */
|
||||
char * sk_app;
|
||||
unsigned int sk_applen;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct SIGN_key sign_key;
|
||||
@@ -130,6 +148,7 @@ void sign_key_free(sign_key *key);
|
||||
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf);
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf);
|
||||
int sk_buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf, char* app, unsigned int applen);
|
||||
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen);
|
||||
#endif
|
||||
int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
|
||||
|
||||
47
sk-ecdsa.c
Normal file
47
sk-ecdsa.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "includes.h"
|
||||
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
|
||||
#include "dbutil.h"
|
||||
#include "ecc.h"
|
||||
#include "ecdsa.h"
|
||||
#include "sk-ecdsa.h"
|
||||
|
||||
int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf, const char* app, unsigned int applen) {
|
||||
hash_state hs;
|
||||
unsigned char subhash[SHA256_HASH_SIZE];
|
||||
buffer *sk_buffer = NULL, *sig_buffer = NULL;
|
||||
unsigned char flags;
|
||||
unsigned int counter;
|
||||
int ret;
|
||||
|
||||
TRACE(("buf_sk_ecdsa_verify"))
|
||||
|
||||
/* from https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.u2f */
|
||||
/* ecdsa signature to verify (r, s) */
|
||||
sig_buffer = buf_getbuf(buf);
|
||||
|
||||
flags = buf_getbyte (buf);
|
||||
counter = buf_getint (buf);
|
||||
/* create the message to be signed */
|
||||
sk_buffer = buf_new (2*SHA256_HASH_SIZE+5);
|
||||
sha256_init (&hs);
|
||||
sha256_process (&hs, app, applen);
|
||||
sha256_done (&hs, subhash);
|
||||
buf_putbytes (sk_buffer, subhash, sizeof (subhash));
|
||||
buf_putbyte (sk_buffer, flags);
|
||||
buf_putint (sk_buffer, counter);
|
||||
sha256_init (&hs);
|
||||
sha256_process (&hs, data_buf->data, data_buf->len);
|
||||
sha256_done (&hs, subhash);
|
||||
buf_putbytes (sk_buffer, subhash, sizeof (subhash));
|
||||
|
||||
ret = buf_ecdsa_verify(sig_buffer, key, sk_buffer);
|
||||
buf_free(sk_buffer);
|
||||
buf_free(sig_buffer);
|
||||
|
||||
TRACE(("leave buf_sk_ecdsa_verify, ret=%d", ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_SK_ECDSA */
|
||||
15
sk-ecdsa.h
Normal file
15
sk-ecdsa.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef DROPBEAR_SK_ECDSA_H_
|
||||
#define DROPBEAR_SK_ECDSA_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
|
||||
#include "buffer.h"
|
||||
#include "signkey.h"
|
||||
|
||||
int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf, const char* app, unsigned int applen);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* DROPBEAR_SK_ECDSA_H_ */
|
||||
61
sk-ed25519.c
Normal file
61
sk-ed25519.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "includes.h"
|
||||
|
||||
#if DROPBEAR_SK_ED25519
|
||||
|
||||
#include "dbutil.h"
|
||||
#include "buffer.h"
|
||||
#include "curve25519.h"
|
||||
#include "ed25519.h"
|
||||
|
||||
int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf, const char* app, unsigned int applen) {
|
||||
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
unsigned char *s;
|
||||
unsigned long slen;
|
||||
hash_state hs;
|
||||
unsigned char hash[SHA256_HASH_SIZE];
|
||||
buffer *sk_buffer = NULL;
|
||||
unsigned char flags;
|
||||
unsigned int counter;
|
||||
|
||||
TRACE(("enter buf_sk_ed25519_verify"))
|
||||
dropbear_assert(key != NULL);
|
||||
|
||||
slen = buf_getint(buf);
|
||||
if (slen != 64 || buf->len - buf->pos < slen) {
|
||||
TRACE(("leave buf_sk_ed25519_verify: bad size"))
|
||||
goto out;
|
||||
}
|
||||
s = buf_getptr(buf, slen);
|
||||
buf_incrpos(buf, slen);
|
||||
|
||||
flags = buf_getbyte (buf);
|
||||
counter = buf_getint (buf);
|
||||
sk_buffer = buf_new (2*SHA256_HASH_SIZE+5);
|
||||
sha256_init (&hs);
|
||||
sha256_process (&hs, app, applen);
|
||||
sha256_done (&hs, hash);
|
||||
buf_putbytes (sk_buffer, hash, sizeof (hash));
|
||||
buf_putbyte (sk_buffer, flags);
|
||||
buf_putint (sk_buffer, counter);
|
||||
sha256_init (&hs);
|
||||
sha256_process (&hs, data_buf->data, data_buf->len);
|
||||
sha256_done (&hs, hash);
|
||||
buf_putbytes (sk_buffer, hash, sizeof (hash));
|
||||
|
||||
if (dropbear_ed25519_verify(sk_buffer->data, sk_buffer->len,
|
||||
s, slen, key->pub) == 0) {
|
||||
/* signature is valid */
|
||||
TRACE(("leave buf_sk_ed25519_verify: success!"))
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
out:
|
||||
if (sk_buffer) {
|
||||
buf_free(sk_buffer);
|
||||
}
|
||||
TRACE(("leave buf_sk_ed25519_verify: ret %d", ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_SK_ED25519 */
|
||||
15
sk-ed25519.h
Normal file
15
sk-ed25519.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef DROPBEAR_SK_ED25519_H_
|
||||
#define DROPBEAR_SK_ED25519_H_
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#if DROPBEAR_SK_ED25519
|
||||
|
||||
#include "buffer.h"
|
||||
#include "ed25519.h"
|
||||
|
||||
int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf, const char* app, unsigned int applen);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* DROPBEAR_SK_ED25519_H_ */
|
||||
@@ -186,7 +186,6 @@ void svr_agentcleanup(struct ChanSess * chansess) {
|
||||
}
|
||||
|
||||
static const struct ChanType chan_svr_agent = {
|
||||
0, /* sepfds */
|
||||
"auth-agent@openssh.com",
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
/* This file (auth.c) handles authentication requests, passing it to the
|
||||
* particular type (auth-passwd, auth-pubkey). */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
|
||||
@@ -294,7 +294,7 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename,
|
||||
is_comment = 1;
|
||||
break;
|
||||
}
|
||||
buf_incrpos(line, -1);
|
||||
buf_decrpos(line, 1);
|
||||
break;
|
||||
}
|
||||
if (is_comment) {
|
||||
|
||||
@@ -166,6 +166,18 @@ int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filena
|
||||
ses.authstate.pubkey_options->no_pty_flag = 1;
|
||||
goto next_option;
|
||||
}
|
||||
if (match_option(options_buf, "restrict") == DROPBEAR_SUCCESS) {
|
||||
dropbear_log(LOG_WARNING, "Restrict option set");
|
||||
ses.authstate.pubkey_options->no_port_forwarding_flag = 1;
|
||||
#if DROPBEAR_SVR_AGENTFWD
|
||||
ses.authstate.pubkey_options->no_agent_forwarding_flag = 1;
|
||||
#endif
|
||||
#if DROPBEAR_X11FWD
|
||||
ses.authstate.pubkey_options->no_x11_forwarding_flag = 1;
|
||||
#endif
|
||||
ses.authstate.pubkey_options->no_pty_flag = 1;
|
||||
goto next_option;
|
||||
}
|
||||
if (match_option(options_buf, "command=\"") == DROPBEAR_SUCCESS) {
|
||||
int escaped = 0;
|
||||
const unsigned char* command_start = buf_getptr(options_buf, 0);
|
||||
|
||||
@@ -54,7 +54,7 @@ static void closechansess(const struct Channel *channel);
|
||||
static void cleanupchansess(const struct Channel *channel);
|
||||
static int newchansess(struct Channel *channel);
|
||||
static void chansessionrequest(struct Channel *channel);
|
||||
static int sesscheckclose(const struct Channel *channel);
|
||||
static int sesscheckclose(struct Channel *channel);
|
||||
|
||||
static void send_exitsignalstatus(const struct Channel *channel);
|
||||
static void send_msg_chansess_exitstatus(const struct Channel * channel,
|
||||
@@ -64,7 +64,6 @@ static void send_msg_chansess_exitsignal(const struct Channel * channel,
|
||||
static void get_termmodes(const struct ChanSess *chansess);
|
||||
|
||||
const struct ChanType svrchansess = {
|
||||
0, /* sepfds */
|
||||
"session", /* name */
|
||||
newchansess, /* inithandler */
|
||||
sesscheckclose, /* checkclosehandler */
|
||||
@@ -76,12 +75,26 @@ const struct ChanType svrchansess = {
|
||||
/* required to clear environment */
|
||||
extern char** environ;
|
||||
|
||||
static int sesscheckclose(const struct Channel *channel) {
|
||||
/* Returns whether the channel is ready to close. The child process
|
||||
must not be running (has never started, or has exited) */
|
||||
static int sesscheckclose(struct Channel *channel) {
|
||||
struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
|
||||
TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid))
|
||||
return chansess->exit.exitpid != -1;
|
||||
TRACE(("sesscheckclose, pid %d, exitpid %d", chansess->pid, chansess->exit.exitpid))
|
||||
|
||||
if (chansess->exit.exitpid != -1) {
|
||||
channel->flushing = 1;
|
||||
}
|
||||
return chansess->pid == 0 || chansess->exit.exitpid != -1;
|
||||
}
|
||||
|
||||
/* Handler for childs exiting, store the state for return to the client */
|
||||
|
||||
/* There's a particular race we have to watch out for: if the forked child
|
||||
* executes, exits, and this signal-handler is called, all before the parent
|
||||
* gets to run, then the childpids[] array won't have the pid in it. Hence we
|
||||
* use the svr_ses.lastexit struct to hold the exit, which is then compared by
|
||||
* the parent when it runs. This work correctly at least in the case of a
|
||||
* single shell spawned (ie the usual case) */
|
||||
void svr_chansess_checksignal(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
@@ -127,18 +140,9 @@ void svr_chansess_checksignal(void) {
|
||||
/* we use this to determine how pid exited */
|
||||
ex->exitsignal = -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Handler for childs exiting, store the state for return to the client */
|
||||
|
||||
/* There's a particular race we have to watch out for: if the forked child
|
||||
* executes, exits, and this signal-handler is called, all before the parent
|
||||
* gets to run, then the childpids[] array won't have the pid in it. Hence we
|
||||
* use the svr_ses.lastexit struct to hold the exit, which is then compared by
|
||||
* the parent when it runs. This work correctly at least in the case of a
|
||||
* single shell spawned (ie the usual case) */
|
||||
static void sesssigchild_handler(int UNUSED(dummy)) {
|
||||
struct sigaction sa_chld;
|
||||
|
||||
@@ -423,35 +427,37 @@ out:
|
||||
|
||||
/* Send a signal to a session's process as requested by the client*/
|
||||
static int sessionsignal(const struct ChanSess *chansess) {
|
||||
TRACE(("sessionsignal"))
|
||||
|
||||
int sig = 0;
|
||||
char* signame = NULL;
|
||||
int i;
|
||||
|
||||
if (chansess->pid == 0) {
|
||||
TRACE(("sessionsignal: done no pid"))
|
||||
/* haven't got a process pid yet */
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
signame = buf_getstring(ses.payload, NULL);
|
||||
|
||||
i = 0;
|
||||
while (signames[i].name != 0) {
|
||||
for (i = 0; signames[i].name != NULL; i++) {
|
||||
if (strcmp(signames[i].name, signame) == 0) {
|
||||
sig = signames[i].signal;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
m_free(signame);
|
||||
|
||||
TRACE(("sessionsignal: pid %d signal %d", (int)chansess->pid, sig))
|
||||
if (sig == 0) {
|
||||
/* failed */
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
if (kill(chansess->pid, sig) < 0) {
|
||||
TRACE(("sessionsignal: kill() errored"))
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
@@ -656,12 +662,13 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
|
||||
unsigned int cmdlen = 0;
|
||||
int ret;
|
||||
|
||||
TRACE(("enter sessioncommand"))
|
||||
TRACE(("enter sessioncommand %d", channel->index))
|
||||
|
||||
if (chansess->cmd != NULL) {
|
||||
if (chansess->pid != 0) {
|
||||
/* Note that only one command can _succeed_. The client might try
|
||||
* one command (which fails), then try another. Ie fallback
|
||||
* from sftp to scp */
|
||||
TRACE(("leave sessioncommand, already have a command"))
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
@@ -673,6 +680,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
|
||||
if (cmdlen > MAX_CMD_LEN) {
|
||||
m_free(chansess->cmd);
|
||||
/* TODO - send error - too long ? */
|
||||
TRACE(("leave sessioncommand, command too long %d", cmdlen))
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -685,6 +693,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
|
||||
#endif
|
||||
{
|
||||
m_free(chansess->cmd);
|
||||
TRACE(("leave sessioncommand, unknown subsystem"))
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -693,7 +702,11 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
|
||||
|
||||
/* take global command into account */
|
||||
if (svr_opts.forced_command) {
|
||||
chansess->original_command = chansess->cmd ? : m_strdup("");
|
||||
if (chansess->cmd) {
|
||||
chansess->original_command = chansess->cmd;
|
||||
} else {
|
||||
chansess->original_command = m_strdup("");
|
||||
}
|
||||
chansess->cmd = m_strdup(svr_opts.forced_command);
|
||||
} else {
|
||||
/* take public key option 'command' into account */
|
||||
@@ -737,6 +750,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
|
||||
if (ret == DROPBEAR_FAILURE) {
|
||||
m_free(chansess->cmd);
|
||||
}
|
||||
TRACE(("leave sessioncommand, ret %d", ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -758,6 +772,7 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) {
|
||||
ses.maxfd = MAX(ses.maxfd, channel->writefd);
|
||||
ses.maxfd = MAX(ses.maxfd, channel->readfd);
|
||||
ses.maxfd = MAX(ses.maxfd, channel->errfd);
|
||||
channel->bidir_fd = 0;
|
||||
|
||||
addchildpid(chansess, chansess->pid);
|
||||
|
||||
@@ -826,20 +841,28 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
|
||||
pty_make_controlling_tty(&chansess->slave, chansess->tty);
|
||||
|
||||
if ((dup2(chansess->slave, STDIN_FILENO) < 0) ||
|
||||
(dup2(chansess->slave, STDERR_FILENO) < 0) ||
|
||||
(dup2(chansess->slave, STDOUT_FILENO) < 0)) {
|
||||
TRACE(("leave ptycommand: error redirecting filedesc"))
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
close(chansess->slave);
|
||||
|
||||
/* write the utmp/wtmp login record - must be after changing the
|
||||
* terminal used for stdout with the dup2 above */
|
||||
* terminal used for stdout with the dup2 above, otherwise
|
||||
* the wtmp login will not be recorded */
|
||||
li = chansess_login_alloc(chansess);
|
||||
login_login(li);
|
||||
dropbear_log(LOG_WARNING, "bad thing happened");
|
||||
login_free_entry(li);
|
||||
|
||||
/* Can now dup2 stderr. Messages from login_login() have gone
|
||||
to the parent stderr */
|
||||
if (dup2(chansess->slave, STDERR_FILENO) < 0) {
|
||||
TRACE(("leave ptycommand: error redirecting filedesc"))
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
close(chansess->slave);
|
||||
|
||||
#if DO_MOTD
|
||||
if (svr_opts.domotd && !chansess->cmd) {
|
||||
/* don't show the motd if ~/.hushlogin exists */
|
||||
@@ -884,6 +907,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;
|
||||
|
||||
setnonblocking(chansess->master);
|
||||
|
||||
@@ -910,6 +934,7 @@ static void addchildpid(struct ChanSess *chansess, pid_t pid) {
|
||||
svr_ses.childpidsize++;
|
||||
}
|
||||
|
||||
TRACE(("addchildpid %d pid %d for chansess %p", i, pid, chansess))
|
||||
svr_ses.childpids[i].pid = pid;
|
||||
svr_ses.childpids[i].chansess = chansess;
|
||||
|
||||
@@ -920,6 +945,11 @@ static void addchildpid(struct ChanSess *chansess, pid_t pid) {
|
||||
static void execchild(const void *user_data) {
|
||||
const struct ChanSess *chansess = user_data;
|
||||
char *usershell = NULL;
|
||||
char *cp = NULL;
|
||||
char *envcp = getenv("LANG");
|
||||
if (envcp != NULL) {
|
||||
cp = m_strdup(envcp);
|
||||
}
|
||||
|
||||
/* with uClinux we'll have vfork()ed, so don't want to overwrite the
|
||||
* hostkey. can't think of a workaround to clear it */
|
||||
@@ -932,19 +962,21 @@ static void execchild(const void *user_data) {
|
||||
seedrandom();
|
||||
#endif
|
||||
|
||||
/* clear environment */
|
||||
/* clear environment if -e was not set */
|
||||
/* if we're debugging using valgrind etc, we need to keep the LD_PRELOAD
|
||||
* etc. This is hazardous, so should only be used for debugging. */
|
||||
if ( !svr_opts.pass_on_env) {
|
||||
#ifndef DEBUG_VALGRIND
|
||||
#ifdef HAVE_CLEARENV
|
||||
clearenv();
|
||||
clearenv();
|
||||
#else /* don't HAVE_CLEARENV */
|
||||
/* Yay for posix. */
|
||||
if (environ) {
|
||||
environ[0] = NULL;
|
||||
}
|
||||
/* Yay for posix. */
|
||||
if (environ) {
|
||||
environ[0] = NULL;
|
||||
}
|
||||
#endif /* HAVE_CLEARENV */
|
||||
#endif /* DEBUG_VALGRIND */
|
||||
}
|
||||
|
||||
#if DROPBEAR_SVR_MULTIUSER
|
||||
/* We can only change uid/gid as root ... */
|
||||
@@ -978,6 +1010,10 @@ static void execchild(const void *user_data) {
|
||||
addnewvar("HOME", ses.authstate.pw_dir);
|
||||
addnewvar("SHELL", get_user_shell());
|
||||
addnewvar("PATH", DEFAULT_PATH);
|
||||
if (cp != NULL) {
|
||||
addnewvar("LANG", cp);
|
||||
m_free(cp);
|
||||
}
|
||||
if (chansess->term != NULL) {
|
||||
addnewvar("TERM", chansess->term);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ static void printhelp(const char * progname) {
|
||||
"-R Create hostkeys as required\n"
|
||||
#endif
|
||||
"-F Don't fork into background\n"
|
||||
"-e Pass on server process environment to child process\n"
|
||||
#ifdef DISABLE_SYSLOG
|
||||
"(Syslog support not compiled in, using stderr)\n"
|
||||
#else
|
||||
@@ -99,7 +100,7 @@ static void printhelp(const char * progname) {
|
||||
#if INETD_MODE
|
||||
"-i Start for inetd\n"
|
||||
#endif
|
||||
"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
|
||||
"-W <receive_window_buffer> (default %d, larger may be faster, max 10MB)\n"
|
||||
"-K <keepalive> (0 is never, default %d, in seconds)\n"
|
||||
"-I <idle_timeout> (0 is never, default %d, in seconds)\n"
|
||||
#if DROPBEAR_PLUGIN
|
||||
@@ -173,6 +174,7 @@ void svr_getopts(int argc, char ** argv) {
|
||||
svr_opts.pubkey_plugin = NULL;
|
||||
svr_opts.pubkey_plugin_options = NULL;
|
||||
#endif
|
||||
svr_opts.pass_on_env = 0;
|
||||
|
||||
#ifndef DISABLE_ZLIB
|
||||
opts.compress_mode = DROPBEAR_COMPRESS_DELAYED;
|
||||
@@ -223,6 +225,10 @@ void svr_getopts(int argc, char ** argv) {
|
||||
opts.usingsyslog = 0;
|
||||
break;
|
||||
#endif
|
||||
case 'e':
|
||||
svr_opts.pass_on_env = 1;
|
||||
break;
|
||||
|
||||
#if DROPBEAR_SVR_LOCALTCPFWD
|
||||
case 'j':
|
||||
svr_opts.nolocaltcp = 1;
|
||||
@@ -379,12 +385,9 @@ void svr_getopts(int argc, char ** argv) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (recv_window_arg) {
|
||||
opts.recv_window = atol(recv_window_arg);
|
||||
if (opts.recv_window == 0 || opts.recv_window > MAX_RECV_WINDOW) {
|
||||
dropbear_exit("Bad recv window '%s'", recv_window_arg);
|
||||
}
|
||||
parse_recv_window(recv_window_arg);
|
||||
}
|
||||
|
||||
if (maxauthtries_arg) {
|
||||
@@ -396,7 +399,7 @@ void svr_getopts(int argc, char ** argv) {
|
||||
svr_opts.maxauthtries = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (keepalive_arg) {
|
||||
unsigned int val;
|
||||
if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) {
|
||||
@@ -665,6 +668,12 @@ void load_all_hostkeys() {
|
||||
any_keys = 1;
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_SK_ECDSA
|
||||
disablekey(DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256);
|
||||
#endif
|
||||
#if DROPBEAR_SK_ED25519
|
||||
disablekey(DROPBEAR_SIGNKEY_SK_ED25519);
|
||||
#endif
|
||||
|
||||
if (!any_keys) {
|
||||
dropbear_exit("No hostkeys available. 'dropbear -R' may be useful or run dropbearkey.");
|
||||
|
||||
@@ -195,8 +195,13 @@ void svr_session(int sock, int childpipe) {
|
||||
/* start off with key exchange */
|
||||
send_msg_kexinit();
|
||||
|
||||
/* Run the main for loop. NULL is for the dispatcher - only the client
|
||||
* code makes use of it */
|
||||
#if DROPBEAR_FUZZ
|
||||
if (fuzz.fuzzing) {
|
||||
fuzz_svr_hook_preloop();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Run the main for-loop. */
|
||||
session_loop(svr_chansess_checksignal);
|
||||
|
||||
/* Not reached */
|
||||
@@ -209,6 +214,7 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
char fullmsg[300];
|
||||
char fromaddr[60];
|
||||
int i;
|
||||
int add_delay = 0;
|
||||
|
||||
#if DROPBEAR_PLUGIN
|
||||
if ((ses.plugin_session != NULL)) {
|
||||
@@ -241,13 +247,33 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
snprintf(fullmsg, sizeof(fullmsg),
|
||||
"Exit before auth%s: (user '%s', %u fails): %s",
|
||||
fromaddr, ses.authstate.pw_name, ses.authstate.failcount, exitmsg);
|
||||
add_delay = 1;
|
||||
} else {
|
||||
/* before userauth */
|
||||
snprintf(fullmsg, sizeof(fullmsg), "Exit before auth%s: %s", fromaddr, exitmsg);
|
||||
add_delay = 1;
|
||||
}
|
||||
|
||||
dropbear_log(LOG_INFO, "%s", fullmsg);
|
||||
|
||||
/* To make it harder for attackers, introduce a delay to keep an
|
||||
* unauthenticated session open a bit longer, thus blocking a connection
|
||||
* slot until after the delay. Without this, while there is a limit on
|
||||
* the amount of attempts an attacker can make at the same time
|
||||
* (MAX_UNAUTH_PER_IP), the time taken by dropbear to handle one attempt
|
||||
* is still short and thus for each of the allowed parallel attempts
|
||||
* many attempts can be chained one after the other. The attempt rate is
|
||||
* then:
|
||||
* "MAX_UNAUTH_PER_IP / <process time of one attempt>".
|
||||
* With the delay, this rate becomes:
|
||||
* "MAX_UNAUTH_PER_IP / UNAUTH_CLOSE_DELAY".
|
||||
*/
|
||||
if ((add_delay != 0) && (UNAUTH_CLOSE_DELAY > 0)) {
|
||||
TRACE(("svr_dropbear_exit: start delay of %d seconds", UNAUTH_CLOSE_DELAY));
|
||||
sleep(UNAUTH_CLOSE_DELAY);
|
||||
TRACE(("svr_dropbear_exit: end delay of %d seconds", UNAUTH_CLOSE_DELAY));
|
||||
}
|
||||
|
||||
#if DROPBEAR_VFORK
|
||||
/* For uclinux only the main server process should cleanup - we don't want
|
||||
* forked children doing that */
|
||||
|
||||
19
svr-tcpfwd.c
19
svr-tcpfwd.c
@@ -39,8 +39,15 @@
|
||||
|
||||
/* This is better than SSH_MSG_UNIMPLEMENTED */
|
||||
void recv_msg_global_request_remotetcp() {
|
||||
TRACE(("recv_msg_global_request_remotetcp: remote tcp forwarding not compiled in"))
|
||||
unsigned int wantreply = 0;
|
||||
|
||||
TRACE(("recv_msg_global_request_remotetcp: remote tcp forwarding not compiled in"))
|
||||
|
||||
buf_eatstring(ses.payload);
|
||||
wantreply = buf_getbool(ses.payload);
|
||||
if (wantreply) {
|
||||
send_msg_request_failure();
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
@@ -52,7 +59,6 @@ static int newtcpdirect(struct Channel * channel);
|
||||
|
||||
#if DROPBEAR_SVR_REMOTETCPFWD
|
||||
static const struct ChanType svr_chan_tcpremote = {
|
||||
1, /* sepfds */
|
||||
"forwarded-tcpip",
|
||||
tcp_prio_inithandler,
|
||||
NULL,
|
||||
@@ -139,7 +145,7 @@ static int svr_cancelremotetcp() {
|
||||
TRACE(("enter cancelremotetcp"))
|
||||
|
||||
bindaddr = buf_getstring(ses.payload, &addrlen);
|
||||
if (addrlen > MAX_IP_LEN) {
|
||||
if (addrlen > MAX_HOST_LEN) {
|
||||
TRACE(("addr len too long: %d", addrlen))
|
||||
goto out;
|
||||
}
|
||||
@@ -174,7 +180,7 @@ static int svr_remotetcpreq(int *allocated_listen_port) {
|
||||
TRACE(("enter remotetcpreq"))
|
||||
|
||||
request_addr = buf_getstring(ses.payload, &addrlen);
|
||||
if (addrlen > MAX_IP_LEN) {
|
||||
if (addrlen > MAX_HOST_LEN) {
|
||||
TRACE(("addr len too long: %d", addrlen))
|
||||
goto out;
|
||||
}
|
||||
@@ -234,7 +240,6 @@ out:
|
||||
#if DROPBEAR_SVR_LOCALTCPFWD
|
||||
|
||||
const struct ChanType svr_chan_tcpdirect = {
|
||||
1, /* sepfds */
|
||||
"direct-tcpip",
|
||||
newtcpdirect, /* init */
|
||||
NULL, /* checkclose */
|
||||
@@ -284,10 +289,10 @@ static int newtcpdirect(struct Channel * channel) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
|
||||
snprintf(portstring, sizeof(portstring), "%u", destport);
|
||||
channel->conn_pending = connect_remote(desthost, portstring, channel_connect_done, channel, NULL, NULL);
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
|
||||
err = SSH_OPEN_IN_PROGRESS;
|
||||
|
||||
|
||||
@@ -211,7 +211,6 @@ static int x11_inithandler(struct Channel *channel) {
|
||||
}
|
||||
|
||||
static const struct ChanType chan_x11 = {
|
||||
0, /* sepfds */
|
||||
"x11",
|
||||
x11_inithandler, /* inithandler */
|
||||
NULL, /* checkclose */
|
||||
|
||||
15
sysoptions.h
15
sysoptions.h
@@ -4,7 +4,7 @@
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef DROPBEAR_VERSION
|
||||
#define DROPBEAR_VERSION "2020.79"
|
||||
#define DROPBEAR_VERSION "2020.81"
|
||||
#endif
|
||||
|
||||
#define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION
|
||||
@@ -50,7 +50,7 @@
|
||||
#define MIN_RSA_KEYLEN 1024
|
||||
#endif
|
||||
|
||||
#define MAX_BANNER_SIZE 2000 /* this is 25*80 chars, any more is foolish */
|
||||
#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 */
|
||||
|
||||
/* the number of NAME=VALUE pairs to malloc for environ, if we don't have
|
||||
@@ -86,9 +86,16 @@
|
||||
/* Required for pubkey auth */
|
||||
#define DROPBEAR_SIGNKEY_VERIFY ((DROPBEAR_SVR_PUBKEY_AUTH) || (DROPBEAR_CLIENT))
|
||||
|
||||
/* crypt(password) must take less time than the auth failure delay
|
||||
(250ms set in svr-auth.c). On Linux the delay depends on
|
||||
password length, 100 characters here was empirically derived.
|
||||
|
||||
If a longer password is allowed Dropbear cannot compensate
|
||||
for the crypt time which will expose which usernames exist */
|
||||
#define DROPBEAR_MAX_PASSWORD_LEN 100
|
||||
|
||||
#define SHA1_HASH_SIZE 20
|
||||
#define SHA256_HASH_SIZE 32
|
||||
#define MD5_HASH_SIZE 16
|
||||
#define MAX_HASH_SIZE 64 /* sha512 */
|
||||
|
||||
@@ -176,7 +183,7 @@ If you test it please contact the Dropbear author */
|
||||
explicitly specified for all protocols (just
|
||||
for algos) but seems valid */
|
||||
|
||||
#define MAX_PROPOSED_ALGO 20
|
||||
#define MAX_PROPOSED_ALGO 50
|
||||
|
||||
/* size/count limits */
|
||||
/* From transport rfc */
|
||||
@@ -190,7 +197,7 @@ If you test it please contact the Dropbear author */
|
||||
|
||||
#define RECV_WINDOWEXTEND (opts.recv_window / 3) /* We send a "window extend" every
|
||||
RECV_WINDOWEXTEND bytes */
|
||||
#define MAX_RECV_WINDOW (1024*1024) /* 1 MB should be enough */
|
||||
#define MAX_RECV_WINDOW (10*1024*1024) /* 10 MB should be enough */
|
||||
|
||||
#define MAX_CHANNELS 1000 /* simple mem restriction, includes each tcp/x11
|
||||
connection, so can't be _too_ small */
|
||||
|
||||
19
test/Makefile.in
Normal file
19
test/Makefile.in
Normal file
@@ -0,0 +1,19 @@
|
||||
srcdir=@srcdir@
|
||||
|
||||
all: test
|
||||
|
||||
test: venv/bin/pytest fakekey
|
||||
./venv/bin/pytest --hostkey=fakekey --dbclient=../dbclient --dropbear=../dropbear $(srcdir)
|
||||
|
||||
one: venv/bin/pytest fakekey
|
||||
./venv/bin/pytest --hostkey=fakekey --dbclient=../dbclient --dropbear=../dropbear $(srcdir) -k exit
|
||||
|
||||
fakekey:
|
||||
../dropbearkey -t ecdsa -f $@
|
||||
|
||||
venv/bin/pytest: $(srcdir)/requirements.txt
|
||||
python3 -m venv init venv
|
||||
./venv/bin/pip install --upgrade pip
|
||||
./venv/bin/pip install -r $(srcdir)/requirements.txt
|
||||
|
||||
.PHONY: test
|
||||
18
test/conftest.py
Normal file
18
test/conftest.py
Normal file
@@ -0,0 +1,18 @@
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--port", type=str, help="default is 2244 local, 22 remote")
|
||||
parser.addoption("--dbclient", type=str, default="../dbclient")
|
||||
parser.addoption("--dropbear", type=str, default="../dropbear")
|
||||
parser.addoption("--hostkey", type=str, help="required unless --remote")
|
||||
parser.addoption("--remote", type=str, help="remote host")
|
||||
parser.addoption("--user", type=str, help="optional username")
|
||||
|
||||
def pytest_configure(config):
|
||||
opt = config.option
|
||||
if not opt.hostkey and not opt.remote:
|
||||
raise Exception("--hostkey must be given")
|
||||
if not opt.port:
|
||||
if opt.remote:
|
||||
opt.port = "22"
|
||||
else:
|
||||
opt.port = "2244"
|
||||
|
||||
8
test/requirements.txt
Normal file
8
test/requirements.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
attrs==21.2.0
|
||||
iniconfig==1.1.1
|
||||
packaging==21.0
|
||||
pluggy==1.0.0
|
||||
py==1.10.0
|
||||
pyparsing==2.4.7
|
||||
pytest==6.2.5
|
||||
toml==0.10.2
|
||||
134
test/test_channels.py
Normal file
134
test/test_channels.py
Normal file
@@ -0,0 +1,134 @@
|
||||
from test_dropbear import *
|
||||
import signal
|
||||
import queue
|
||||
import socket
|
||||
|
||||
# Tests for various edge cases of SSH channels and connection service
|
||||
|
||||
def test_exitcode(request, dropbear):
|
||||
r = dbclient(request, "exit 44")
|
||||
assert r.returncode == 44
|
||||
|
||||
@pytest.mark.xfail(reason="Not yet implemented", strict=True)
|
||||
def test_signal(request, dropbear):
|
||||
r = dbclient(request, "kill -FPE $$")
|
||||
assert r.returncode == -signal.SIGFPE
|
||||
|
||||
@pytest.mark.parametrize("size", [0, 1, 2, 100, 5000, 200_000])
|
||||
def test_roundtrip(request, dropbear, size):
|
||||
dat = os.urandom(size)
|
||||
r = dbclient(request, "cat", input=dat, capture_output=True)
|
||||
r.check_returncode()
|
||||
assert r.stdout == dat
|
||||
|
||||
@pytest.mark.parametrize("size", [0, 1, 2, 100, 20001, 41234])
|
||||
def test_read_pty(request, dropbear, size):
|
||||
# testcase for
|
||||
# https://bugs.openwrt.org/index.php?do=details&task_id=1814
|
||||
# https://github.com/mkj/dropbear/pull/85
|
||||
# From Yousong Zhou
|
||||
# Fixed Oct 2021
|
||||
#
|
||||
#$ ssh -t my.router cat /tmp/bigfile | wc
|
||||
#Connection to my.router closed.
|
||||
# 0 1 14335 <- should be 20001
|
||||
|
||||
# Write the file. No newlines etc which could confuse ptys
|
||||
dat = random_alnum(size)
|
||||
r = dbclient(request, "tmpf=`mktemp`; echo $tmpf; cat > $tmpf", input=dat, capture_output=True, text=True)
|
||||
tmpf = r.stdout.rstrip()
|
||||
r.check_returncode()
|
||||
# Read with a pty, this is what is being tested.
|
||||
# Timing/buffering is subtle, we seem to need to cat a file from disk to hit it.
|
||||
m, s = pty.openpty()
|
||||
r = dbclient(request, "-t", f"cat {tmpf}; rm {tmpf}", stdin=s, capture_output=True)
|
||||
r.check_returncode()
|
||||
assert r.stdout.decode() == dat
|
||||
|
||||
@pytest.mark.parametrize("fd", [1, 2])
|
||||
def test_bg_sleep(request, fd, dropbear):
|
||||
# https://lists.ucc.asn.au/pipermail/dropbear/2006q1/000362.html
|
||||
# Rob Landley "Is this a bug?" 24 Mar 2006
|
||||
# dbclient user@system "sleep 10& echo hello"
|
||||
#
|
||||
# It should return right after printing hello, but it doesn't. It waits until
|
||||
# the child process exits.
|
||||
|
||||
# failure is TimeoutExpired
|
||||
redir = "" if fd == 1 else " >&2 "
|
||||
r = dbclient(request, f"sleep 10& echo hello {redir}",
|
||||
capture_output=True, timeout=2, text=True)
|
||||
r.check_returncode()
|
||||
st = r.stdout if fd == 1 else r.stderr
|
||||
|
||||
if fd == 2 and 'accepted unconditionally' in st:
|
||||
# ignore hostkey warning, a bit of a hack
|
||||
assert st.endswith("\n\nhello\n")
|
||||
else:
|
||||
assert st.rstrip() == "hello"
|
||||
|
||||
|
||||
def test_idle(request, dropbear):
|
||||
# Idle test, -I 1 should make it return before the 2 second timeout
|
||||
r = dbclient(request, "-I", "1", "echo zong; sleep 10",
|
||||
capture_output=True, timeout=2, text=True)
|
||||
r.check_returncode()
|
||||
assert r.stdout.rstrip() == "zong"
|
||||
|
||||
@pytest.mark.parametrize("size", [1, 4000, 40000])
|
||||
def test_netcat(request, dropbear, size):
|
||||
opt = request.config.option
|
||||
if opt.remote:
|
||||
pytest.xfail("don't know netcat address for remote")
|
||||
|
||||
dat1 = os.urandom(size)
|
||||
dat2 = os.urandom(size)
|
||||
with HandleTcp(3344, 1, dat2) as tcp:
|
||||
r = dbclient(request, "-B", "localhost:3344", input=dat1, capture_output=True)
|
||||
r.check_returncode()
|
||||
assert r.stdout == dat2
|
||||
assert tcp.inbound() == dat1
|
||||
|
||||
@pytest.mark.parametrize("size", [1, 4000, 40000])
|
||||
@pytest.mark.parametrize("fwd_flag", "LR")
|
||||
def test_tcpflushout(request, dropbear, size, fwd_flag):
|
||||
""" Tests that an opened TCP connection prevent a SSH session from being closed
|
||||
until that TCP connection has finished transferring
|
||||
"""
|
||||
opt = request.config.option
|
||||
if opt.remote:
|
||||
pytest.xfail("don't know address for remote")
|
||||
|
||||
dat1 = os.urandom(size)
|
||||
dat2 = os.urandom(size)
|
||||
q = queue.Queue()
|
||||
with HandleTcp(3344, timeout=1, response=q) as tcp:
|
||||
|
||||
r = dbclient(request, f"-{fwd_flag}", "7788:localhost:3344", "sleep 0.1; echo -n done",
|
||||
text=True, background=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
|
||||
# time to let the listener start
|
||||
time.sleep(0.1)
|
||||
# open a tcp connection
|
||||
c = socket.create_connection(("localhost", 7788))
|
||||
|
||||
# wait for the shell to finish. sleep a bit longer in case it exits.
|
||||
assert r.stdout.read(4) == "done"
|
||||
time.sleep(0.1)
|
||||
|
||||
# now the shell has finished, we can write on the tcp socket
|
||||
c.sendall(dat2)
|
||||
c.shutdown(socket.SHUT_WR)
|
||||
q.put(dat1)
|
||||
|
||||
# return a tcp response
|
||||
q.put(None)
|
||||
# check hasn't exited
|
||||
assert r.poll() == None
|
||||
|
||||
# read the response
|
||||
assert readall_socket(c) == dat1
|
||||
c.close()
|
||||
assert tcp.inbound() == dat2
|
||||
# check has exited, allow time for dbclient to exit
|
||||
time.sleep(0.1)
|
||||
assert r.poll() == 0
|
||||
114
test/test_dropbear.py
Normal file
114
test/test_dropbear.py
Normal file
@@ -0,0 +1,114 @@
|
||||
import subprocess
|
||||
import os
|
||||
import pty
|
||||
import tempfile
|
||||
import logging
|
||||
import time
|
||||
import socketserver
|
||||
import threading
|
||||
import queue
|
||||
|
||||
import pytest
|
||||
|
||||
LOCALADDR="127.0.5.5"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def dropbear(request):
|
||||
opt = request.config.option
|
||||
if opt.remote:
|
||||
yield None
|
||||
return
|
||||
|
||||
args = [opt.dropbear,
|
||||
"-p", LOCALADDR, # bind locally only
|
||||
"-r", opt.hostkey,
|
||||
"-p", opt.port,
|
||||
"-F", "-E",
|
||||
]
|
||||
p = subprocess.Popen(args, stderr=subprocess.PIPE, text=True)
|
||||
# Wait until it has started listening
|
||||
for l in p.stderr:
|
||||
if "Not backgrounding" in l:
|
||||
break
|
||||
# Check it's still running
|
||||
assert p.poll() is None
|
||||
# Ready
|
||||
yield p
|
||||
p.terminate()
|
||||
print("Terminated dropbear. Flushing output:")
|
||||
for l in p.stderr:
|
||||
print(l.rstrip())
|
||||
print("Done")
|
||||
|
||||
def dbclient(request, *args, **kwargs):
|
||||
opt = request.config.option
|
||||
host = opt.remote or LOCALADDR
|
||||
base_args = [opt.dbclient, "-y", host, "-p", opt.port]
|
||||
if opt.user:
|
||||
full_args.extend(['-l', opt.user])
|
||||
full_args = base_args + list(args)
|
||||
bg = kwargs.get("background")
|
||||
if "background" in kwargs:
|
||||
del kwargs["background"]
|
||||
if bg:
|
||||
return subprocess.Popen(full_args, **kwargs)
|
||||
else:
|
||||
kwargs.setdefault("timeout", 10)
|
||||
# wait for response
|
||||
return subprocess.run(full_args, **kwargs)
|
||||
|
||||
class HandleTcp(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||
""" Listens for a single incoming request, sends a response if given,
|
||||
and returns the inbound data.
|
||||
Reponse can be a queue object, in which case each item in the queue will
|
||||
be sent as a response, until it receives a None item.
|
||||
"""
|
||||
def __init__(self, port, timeout, response=None):
|
||||
super().__init__(('localhost', port), self.Handler)
|
||||
self.port = port
|
||||
self.timeout = timeout
|
||||
self.response = response
|
||||
self.sink = None
|
||||
|
||||
class Handler(socketserver.StreamRequestHandler):
|
||||
def handle(self):
|
||||
if isinstance(self.server.response, queue.Queue):
|
||||
while True:
|
||||
i = self.server.response.get()
|
||||
if i is None:
|
||||
break
|
||||
self.wfile.write(i)
|
||||
elif self.server.response:
|
||||
self.wfile.write(self.server.response)
|
||||
assert self.server.sink is None, ">1 request sent to handler"
|
||||
self.server.sink = self.rfile.read()
|
||||
|
||||
def __enter__(self):
|
||||
self.server_thread = threading.Thread(target=self.serve_forever)
|
||||
self.server_thread.daemon = True
|
||||
self.server_thread.start()
|
||||
return self
|
||||
|
||||
def __exit__(self, *exc_stuff):
|
||||
self.shutdown()
|
||||
self.server_thread.join()
|
||||
|
||||
def inbound(self):
|
||||
""" Returns the data sent to the socket """
|
||||
return self.sink
|
||||
|
||||
def readall_socket(sock):
|
||||
b = []
|
||||
while True:
|
||||
i = sock.recv(4096)
|
||||
if not i:
|
||||
break
|
||||
b.append(i)
|
||||
return b''.join(b)
|
||||
|
||||
# returns a str
|
||||
def random_alnum(size):
|
||||
r = os.urandom(500 + size*5)
|
||||
return bytes(i for i in r if bytes((i,)).isalnum())[:size].decode()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user