mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-07 02:39:48 +09:00
Compare commits
229 Commits
02cbd41b92
...
libssh-0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10e09e273f | ||
|
|
622421018b | ||
|
|
8977e246b6 | ||
|
|
8b66d037d5 | ||
|
|
63ff242131 | ||
|
|
610d7a09f9 | ||
|
|
89df759200 | ||
|
|
5846e57538 | ||
|
|
0870c8db28 | ||
|
|
4cef5e965a | ||
|
|
2c492ee179 | ||
|
|
cea841d71c | ||
|
|
62d3101c1f | ||
|
|
d7467498fd | ||
|
|
22492b69bb | ||
|
|
9bbb817c0c | ||
|
|
c618040967 | ||
|
|
8615c24647 | ||
|
|
a66b4a6eae | ||
|
|
c2c56bacab | ||
|
|
52ebecf81c | ||
|
|
4b935d0785 | ||
|
|
57b92b18d6 | ||
|
|
48f217176f | ||
|
|
e8474e1ba3 | ||
|
|
85ce922bc4 | ||
|
|
49ead8f08e | ||
|
|
0813b75799 | ||
|
|
29ad26db26 | ||
|
|
cd2bf21f9a | ||
|
|
ed8b7ea7a7 | ||
|
|
105835d542 | ||
|
|
479eca13aa | ||
|
|
994acfe2c5 | ||
|
|
968e09aae0 | ||
|
|
a006d34372 | ||
|
|
a669408201 | ||
|
|
c68a58575b | ||
|
|
e8dfbb85a2 | ||
|
|
dc1254d53e | ||
|
|
d08f1b2377 | ||
|
|
70565ac438 | ||
|
|
fc1a8bb455 | ||
|
|
b759ae557d | ||
|
|
6df2daea04 | ||
|
|
99760776d4 | ||
|
|
247a4a761c | ||
|
|
a30339d7b1 | ||
|
|
8dde4e1924 | ||
|
|
b1d9bff6ee | ||
|
|
a0f10b9860 | ||
|
|
7e40f13125 | ||
|
|
36273e708a | ||
|
|
41c63fa88d | ||
|
|
d726eca7d2 | ||
|
|
ad2797613e | ||
|
|
653e5ee117 | ||
|
|
d8b1b5e0cc | ||
|
|
7341615e2f | ||
|
|
f8ba2b0148 | ||
|
|
d26cc63dd5 | ||
|
|
e41dacbf10 | ||
|
|
e786bacb92 | ||
|
|
19e2521242 | ||
|
|
429d0422dc | ||
|
|
559ebc9ccb | ||
|
|
d7f18c468e | ||
|
|
f73dac8eed | ||
|
|
3c381565c9 | ||
|
|
833c3d3330 | ||
|
|
6d073f2746 | ||
|
|
fe83733a7c | ||
|
|
d3d7eeab75 | ||
|
|
8a037e9afe | ||
|
|
dd0aaec67e | ||
|
|
8b3b041096 | ||
|
|
e9e9190079 | ||
|
|
bc4afc1067 | ||
|
|
6a187990c1 | ||
|
|
ec5bd83e50 | ||
|
|
e818700734 | ||
|
|
9e20e180e6 | ||
|
|
e426664623 | ||
|
|
921efbeea1 | ||
|
|
03f8fcae84 | ||
|
|
ea639b0258 | ||
|
|
bb5bdac321 | ||
|
|
554fe06aeb | ||
|
|
298155da71 | ||
|
|
44ceeb4d53 | ||
|
|
0c725d7602 | ||
|
|
2461027f72 | ||
|
|
967082c207 | ||
|
|
1f7995ccea | ||
|
|
662fe00c15 | ||
|
|
0d86688da2 | ||
|
|
02f39b5e60 | ||
|
|
1bf87909e7 | ||
|
|
096416d306 | ||
|
|
019040f693 | ||
|
|
f1c5888553 | ||
|
|
8a5bdc3a21 | ||
|
|
3a77bb2992 | ||
|
|
b2ca8b07ec | ||
|
|
1bc9b20b1a | ||
|
|
b9a6fac062 | ||
|
|
2eee844025 | ||
|
|
be2084f9e2 | ||
|
|
cfa95d9ead | ||
|
|
1685c14024 | ||
|
|
7f12c572d3 | ||
|
|
2177c9e567 | ||
|
|
96bc6af2b3 | ||
|
|
ec33973319 | ||
|
|
512ac7620b | ||
|
|
d190053660 | ||
|
|
253658dce8 | ||
|
|
8ac8b19017 | ||
|
|
e8838f419b | ||
|
|
2b45e61f74 | ||
|
|
54bcce5aa2 | ||
|
|
1fb95070f2 | ||
|
|
438cc6df52 | ||
|
|
4aeb685b04 | ||
|
|
54a3da64ad | ||
|
|
e21ceae755 | ||
|
|
905049d1e1 | ||
|
|
2c03f3bd0b | ||
|
|
e218745d0e | ||
|
|
24c44e2c7a | ||
|
|
7fd953ef42 | ||
|
|
80c994ef72 | ||
|
|
5c5811bf7c | ||
|
|
27f3e955e8 | ||
|
|
54a0eb6846 | ||
|
|
8c17a79797 | ||
|
|
13363975d8 | ||
|
|
e8dccfe1dd | ||
|
|
bff436695b | ||
|
|
e3d0f60281 | ||
|
|
92eedd8f19 | ||
|
|
a29f98be26 | ||
|
|
53bc265987 | ||
|
|
d993088553 | ||
|
|
5d26b0967d | ||
|
|
0d52be0f5b | ||
|
|
fc66be08a1 | ||
|
|
13a2aa3a97 | ||
|
|
4a36e52bc4 | ||
|
|
01a92b5838 | ||
|
|
e5f72468b8 | ||
|
|
1761db6f97 | ||
|
|
73ea9a8922 | ||
|
|
78e79fbc35 | ||
|
|
990db53ee6 | ||
|
|
18b46a6e17 | ||
|
|
096996501b | ||
|
|
569164740d | ||
|
|
0da3fe245b | ||
|
|
b448c3ad98 | ||
|
|
02e0eaa104 | ||
|
|
82e76a15d1 | ||
|
|
bddbe2a76d | ||
|
|
e8322817a9 | ||
|
|
e0c2f2809b | ||
|
|
9bb91df20f | ||
|
|
783f2b97a8 | ||
|
|
8d05810255 | ||
|
|
1d29d4b627 | ||
|
|
787711a271 | ||
|
|
ddea657ba7 | ||
|
|
9ae46bc364 | ||
|
|
fd1563575f | ||
|
|
1f973320a8 | ||
|
|
4fc7ab4399 | ||
|
|
87bac425a0 | ||
|
|
0e637e3327 | ||
|
|
9b1f4e9bf6 | ||
|
|
630f335415 | ||
|
|
b7934ab370 | ||
|
|
0aaad9eb25 | ||
|
|
8fe4cabb26 | ||
|
|
1689b83d0f | ||
|
|
7c6105882b | ||
|
|
bb6d1b78dc | ||
|
|
5a884b8c5a | ||
|
|
90128929e7 | ||
|
|
a7d509ca50 | ||
|
|
d26f7253a9 | ||
|
|
3ad2a21d13 | ||
|
|
7f6b3fab4e | ||
|
|
cd7ccf93f0 | ||
|
|
5944124428 | ||
|
|
8c40b2491d | ||
|
|
3331b794bc | ||
|
|
02f1873b9e | ||
|
|
5da93db25a | ||
|
|
b18495b56b | ||
|
|
a96763b195 | ||
|
|
540257b421 | ||
|
|
b657eeb65e | ||
|
|
4a87515026 | ||
|
|
886ed379d8 | ||
|
|
9b9197d86b | ||
|
|
64e89affeb | ||
|
|
2c1ad3262a | ||
|
|
14ff31490f | ||
|
|
3db3511467 | ||
|
|
4c5da86f91 | ||
|
|
2564246024 | ||
|
|
146d1a620d | ||
|
|
19c43ff6b7 | ||
|
|
58a2943d42 | ||
|
|
54c5472b53 | ||
|
|
17e9cd70a5 | ||
|
|
cee5c9f404 | ||
|
|
43fb1d7c8d | ||
|
|
5c629f22f6 | ||
|
|
46e0703c6e | ||
|
|
cffa103378 | ||
|
|
ea6558b3a6 | ||
|
|
33e12317c3 | ||
|
|
d17c635617 | ||
|
|
dde5fd8d38 | ||
|
|
46e78aaa3a | ||
|
|
3107133d10 | ||
|
|
b9ccaf6e23 | ||
|
|
38b17e6e6e | ||
|
|
db0a1d6811 |
@@ -1,28 +0,0 @@
|
||||
---
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
UseTab: Never
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeElse: false
|
||||
BeforeWhile: false
|
||||
IndentCaseLabels: false
|
||||
IndentCaseBlocks: false
|
||||
ColumnLimit: 80
|
||||
AlignAfterOpenBracket: Align
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
BreakAfterReturnType: ExceptShortType
|
||||
AlwaysBreakAfterReturnType: AllDefinitions
|
||||
AlignEscapedNewlines: Left
|
||||
ForEachMacros: ['ssh_callbacks_iterate']
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
*.a
|
||||
*.o
|
||||
.*
|
||||
*.swp
|
||||
*~$
|
||||
cscope.*
|
||||
@@ -9,4 +10,3 @@ compile_commands.json
|
||||
tags
|
||||
/build
|
||||
/obj*
|
||||
doc/tags.xml
|
||||
|
||||
193
.gitlab-ci.yml
193
.gitlab-ci.yml
@@ -1,9 +1,9 @@
|
||||
---
|
||||
variables:
|
||||
BUILD_IMAGES_PROJECT: libssh/build-images
|
||||
CENTOS7_BUILD: buildenv-centos7
|
||||
CENTOS8_BUILD: buildenv-c8s
|
||||
CENTOS9_BUILD: buildenv-c9s
|
||||
CENTOS10_BUILD: buildenv-c10s
|
||||
FEDORA_BUILD: buildenv-fedora
|
||||
MINGW_BUILD: buildenv-mingw
|
||||
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
||||
@@ -16,23 +16,12 @@ stages:
|
||||
- test
|
||||
- analysis
|
||||
|
||||
# This is some black magic to select between branch pipelines and
|
||||
# merge request pipelines to avoid running same pipelines in twice
|
||||
workflow:
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"'
|
||||
when: never
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
|
||||
when: never
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
|
||||
.build:
|
||||
stage: build
|
||||
variables:
|
||||
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
|
||||
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON"
|
||||
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DGSSAPI_TESTING=ON -DWITH_BENCHMARKS=ON -DFUZZ_TESTING=ON"
|
||||
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON -DWITH_DSA=ON"
|
||||
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DWITH_BENCHMARKS=ON"
|
||||
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
|
||||
before_script: &build
|
||||
- uname -a
|
||||
@@ -48,11 +37,7 @@ workflow:
|
||||
make -j$(nproc) install
|
||||
# Do not use after_script as it does not make the targets fail
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
only:
|
||||
- merge_requests
|
||||
- branches
|
||||
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
@@ -75,6 +60,8 @@ workflow:
|
||||
.fedora:
|
||||
extends: .tests
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
|
||||
|
||||
.tumbleweed:
|
||||
extends: .tests
|
||||
@@ -83,7 +70,8 @@ workflow:
|
||||
.fips:
|
||||
extends: .tests
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
|
||||
# DSA is turned off in fips mode
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_DSA=OFF
|
||||
before_script:
|
||||
- *build
|
||||
- echo "# userspace fips" > /etc/system-fips
|
||||
@@ -96,54 +84,20 @@ workflow:
|
||||
- update-crypto-policies --set FIPS
|
||||
- update-crypto-policies --show
|
||||
|
||||
###############################################################################
|
||||
# Review #
|
||||
###############################################################################
|
||||
review:
|
||||
variables:
|
||||
GIT_DEPTH: 100
|
||||
stage: review
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- ERROR=0
|
||||
codespell --ignore-words-list=keypair,sorce,ned,nd,ue,pendin || ERROR=1;
|
||||
./.gitlab-ci/clang-format-check.sh || ERROR=1;
|
||||
./.gitlab-ci/git-check-signoff-trailer.sh ${CI_MERGE_REQUEST_DIFF_BASE_SHA} || ERROR=1;
|
||||
./.gitlab-ci/shellcheck.sh || ERROR=1;
|
||||
exit $ERROR
|
||||
# the format is not always matching our intentions
|
||||
allow_failure: true
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
only:
|
||||
- merge_requests
|
||||
|
||||
###############################################################################
|
||||
# CentOS builds #
|
||||
###############################################################################
|
||||
centos10s/openssl_3.5.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
|
||||
# pkd tests fail on CentOS7 docker images, so we don't use -DSERVER_TESTING=ON
|
||||
centos7/openssl_1.0.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD
|
||||
extends: .tests
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
|
||||
script:
|
||||
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
|
||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||
- cmake3 $CMAKE_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
centos10s/openssl_3.5.x/x86_64/fips:
|
||||
extends: .fips
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
|
||||
script:
|
||||
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
|
||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
|
||||
|
||||
centos9s/openssl_3.5.x/x86_64:
|
||||
centos9s/openssl_3.0.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||
extends: .tests
|
||||
variables:
|
||||
@@ -154,13 +108,7 @@ centos9s/openssl_3.5.x/x86_64:
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
centos9s/mbedtls_2.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||
extends: .tests
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF"
|
||||
|
||||
centos9s/openssl_3.5.x/x86_64/fips:
|
||||
centos9s/openssl_3.0.x/x86_64/fips:
|
||||
extends: .fips
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||
script:
|
||||
@@ -198,8 +146,7 @@ fedora/docs:
|
||||
extends: .build
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- cmake .. && make docs_coverage && make docs
|
||||
coverage: '/^Documentation coverage is \d+.\d+%/'
|
||||
- cmake .. && make docs
|
||||
|
||||
fedora/ninja:
|
||||
extends: .fedora
|
||||
@@ -207,73 +154,24 @@ fedora/ninja:
|
||||
script:
|
||||
- cmake -G Ninja $CMAKE_OPTIONS ../ && ninja && CTEST_OUTPUT_ON_FAILURE=1 ninja test
|
||||
|
||||
fedora/coverage:
|
||||
extends: .fedora
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_BUILD_TYPE=Debug -DWITH_COVERAGE=ON"
|
||||
script:
|
||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
make coverage_xml
|
||||
coverage: /^\s*lines:\s*\d+.\d+\%/
|
||||
artifacts:
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
expire_in: 1 week
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: obj/coverage_xml.xml
|
||||
|
||||
fedora/openssl_3.0.x/x86_64:
|
||||
extends: .fedora
|
||||
|
||||
fedora/openssl_3.0.x/x86_64/pkcs11-provider:
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
|
||||
extends: .fedora
|
||||
|
||||
fedora/openssl_3.0.x/x86_64/minimal:
|
||||
extends: .fedora
|
||||
variables:
|
||||
script:
|
||||
- cmake $CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_EXEC=OFF
|
||||
-DWITH_SFTP=OFF
|
||||
-DWITH_SERVER=OFF
|
||||
-DWITH_ZLIB=OFF
|
||||
-DWITH_PCAP=OFF
|
||||
-DWITH_DSA=OFF
|
||||
-DUNIT_TESTING=ON
|
||||
-DCLIENT_TESTING=ON
|
||||
-DWITH_GEX=OFF .. &&
|
||||
make -j$(nproc)
|
||||
|
||||
.valgrind:
|
||||
extends: .fedora
|
||||
stage: analysis
|
||||
script:
|
||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
make test_memcheck
|
||||
- cat Testing/Temporary/MemoryChecker.*.log | wc -l | grep "^0$"
|
||||
|
||||
# The PKCS#11 support is turned off as it brings dozens of memory issues from
|
||||
# engine_pkcs11 or openssl itself
|
||||
fedora/valgrind/openssl:
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=OFF
|
||||
extends: .valgrind
|
||||
|
||||
fedora/valgrind/mbedtls:
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_MBEDTLS=ON
|
||||
extends: .valgrind
|
||||
|
||||
fedora/valgrind/libgcrypt:
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_GCRYPT=ON
|
||||
extends: .valgrind
|
||||
|
||||
# Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite
|
||||
# so, this is only enabled for unit tests right now.
|
||||
# TODO: add -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
@@ -329,10 +227,10 @@ fedora/libgcrypt/x86_64:
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON"
|
||||
|
||||
fedora/mbedtls_2.x/x86_64:
|
||||
fedora/mbedtls/x86_64:
|
||||
extends: .fedora
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON "
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DSA=OFF"
|
||||
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
@@ -349,7 +247,7 @@ fedora/mingw64:
|
||||
-DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure -E torture_rand
|
||||
ctest --output-on-failure
|
||||
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
@@ -366,7 +264,7 @@ fedora/mingw32:
|
||||
-DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure -E torture_rand
|
||||
ctest --output-on-failure
|
||||
|
||||
|
||||
###############################################################################
|
||||
@@ -379,11 +277,6 @@ fedora/mingw32:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
before_script:
|
||||
- |
|
||||
# for merge requests
|
||||
if [[ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]]; then
|
||||
export CI_COMMIT_BEFORE_SHA="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
|
||||
fi
|
||||
# for branches run
|
||||
if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then
|
||||
export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
|
||||
fi
|
||||
@@ -394,11 +287,9 @@ fedora/mingw32:
|
||||
|
||||
export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA"
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
only:
|
||||
- merge_requests
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
@@ -410,7 +301,7 @@ fedora/csbuild/openssl_3.0.x:
|
||||
script:
|
||||
- csbuild
|
||||
--build-dir=obj-csbuild
|
||||
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@ && make clean && make -j$(nproc)"
|
||||
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_DSA=ON @SRCDIR@ && make clean && make -j$(nproc)"
|
||||
--git-commit-range $CI_COMMIT_RANGE
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
@@ -420,7 +311,7 @@ fedora/csbuild/libgcrypt:
|
||||
script:
|
||||
- csbuild
|
||||
--build-dir=obj-csbuild
|
||||
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_GCRYPT=ON @SRCDIR@ && make clean && make -j$(nproc)"
|
||||
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_GCRYPT=ON -DWITH_DSA=ON @SRCDIR@ && make clean && make -j$(nproc)"
|
||||
--git-commit-range $CI_COMMIT_RANGE
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
@@ -466,6 +357,8 @@ alpine/openssl_3.0.x/musl:
|
||||
###############################################################################
|
||||
tumbleweed/openssl_3.0.x/x86_64/gcc:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
|
||||
|
||||
tumbleweed/openssl_3.0.x/x86/gcc:
|
||||
extends: .tumbleweed
|
||||
@@ -477,13 +370,14 @@ tumbleweed/openssl_3.0.x/x86/gcc:
|
||||
-DWITH_SERVER=ON
|
||||
-DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON
|
||||
-DWITH_DSA=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc)
|
||||
|
||||
tumbleweed/openssl_3.0.x/x86_64/gcc7:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7"
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
|
||||
|
||||
tumbleweed/openssl_3.0.x/x86/gcc7:
|
||||
extends: .tumbleweed
|
||||
@@ -493,6 +387,7 @@ tumbleweed/openssl_3.0.x/x86/gcc7:
|
||||
-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
|
||||
$CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DWITH_DSA=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
@@ -500,12 +395,7 @@ tumbleweed/openssl_3.0.x/x86/gcc7:
|
||||
tumbleweed/openssl_3.0.x/x86_64/clang:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
|
||||
|
||||
tumbleweed/mbedtls-3.6.x/x86_64/gcc:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
|
||||
|
||||
tumbleweed/static-analysis:
|
||||
extends: .tests
|
||||
@@ -565,12 +455,8 @@ freebsd/openssl_1.1.1/x86_64:
|
||||
###############################################################################
|
||||
# Visual Studio builds #
|
||||
###############################################################################
|
||||
# 2024-05-13: These jobs run out of the stages as they take extremely long and
|
||||
# usually timeout with the update to Gitlab 17.0
|
||||
.vs:
|
||||
stage: analysis
|
||||
needs: []
|
||||
allow_failure: true
|
||||
stage: test
|
||||
cache:
|
||||
key: vcpkg.${CI_JOB_NAME}
|
||||
paths:
|
||||
@@ -581,10 +467,8 @@ freebsd/openssl_1.1.1/x86_64:
|
||||
- cmake --build .
|
||||
- ctest --output-on-failure
|
||||
tags:
|
||||
- saas-windows-medium-amd64
|
||||
only:
|
||||
- merge_requests
|
||||
- branches
|
||||
- windows
|
||||
- shared-windows
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
@@ -648,7 +532,7 @@ coverity:
|
||||
--form description="CI build"
|
||||
https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
- shared
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
@@ -662,3 +546,14 @@ coverity:
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/cov-int/*.txt
|
||||
|
||||
###############################################################################
|
||||
# Codespell #
|
||||
###############################################################################
|
||||
codespell:
|
||||
stage: review
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- codespell --ignore-words-list=keypair,sorce,ned,nd,ue
|
||||
tags:
|
||||
- shared
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Based on Github Action
|
||||
# https://github.com/yshui/git-clang-format-lint
|
||||
|
||||
diff=$(git-clang-format --diff --commit "$CI_MERGE_REQUEST_DIFF_BASE_SHA")
|
||||
[ "$diff" = "no modified files to format" ] && exit 0
|
||||
[ "$diff" = "clang-format did not modify any files" ] && exit 0
|
||||
|
||||
printf "You have introduced coding style breakages, suggested changes:\n\n"
|
||||
|
||||
echo "${diff}" | colordiff
|
||||
exit 1
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo "Usage: $0 UPSTREAM_COMMIT_SHA"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
failed=0
|
||||
|
||||
if [ -z "$CI_COMMIT_SHA" ]; then
|
||||
echo "CI_COMMIT_SHA is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CI_COMMIT_RANGE="$1..$CI_COMMIT_SHA"
|
||||
|
||||
red='\033[0;31m'
|
||||
blue='\033[0;34m'
|
||||
|
||||
echo -e "${blue}Checking commit range: $CI_COMMIT_RANGE"
|
||||
echo
|
||||
echo
|
||||
|
||||
for commit in $(git rev-list "$CI_COMMIT_RANGE"); do
|
||||
git show -s --format=%B "$commit" | grep "^Signed-off-by: " >/dev/null 2>&1
|
||||
ret=$?
|
||||
if [ $ret -eq 1 ]; then
|
||||
echo -e "${red} >>> Missing Signed-off-by trailer in commit $commit"
|
||||
failed=$(("$failed" + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo
|
||||
|
||||
exit $failed
|
||||
@@ -1,56 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Simplified and de-github-ed version of
|
||||
# https://github.com/ludeeus/action-shellcheck/blob/master/action.yaml
|
||||
|
||||
statuscode=0
|
||||
|
||||
declare -a filepaths
|
||||
shebangregex="^#! */[^ ]*/(env *)?[abk]*sh"
|
||||
set -f # temporarily disable globbing so that globs in inputs aren't expanded
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
filepaths+=("$file")
|
||||
done < <(find . \
|
||||
-type f \
|
||||
'(' \
|
||||
-name '*.bash' \
|
||||
-o -name '.bashrc' \
|
||||
-o -name 'bashrc' \
|
||||
-o -name '.bash_aliases' \
|
||||
-o -name '.bash_completion' \
|
||||
-o -name '.bash_login' \
|
||||
-o -name '.bash_logout' \
|
||||
-o -name '.bash_profile' \
|
||||
-o -name 'bash_profile' \
|
||||
-o -name '*.ksh' \
|
||||
-o -name 'suid_profile' \
|
||||
-o -name '*.zsh' \
|
||||
-o -name '.zlogin' \
|
||||
-o -name 'zlogin' \
|
||||
-o -name '.zlogout' \
|
||||
-o -name 'zlogout' \
|
||||
-o -name '.zprofile' \
|
||||
-o -name 'zprofile' \
|
||||
-o -name '.zsenv' \
|
||||
-o -name 'zsenv' \
|
||||
-o -name '.zshrc' \
|
||||
-o -name 'zshrc' \
|
||||
-o -name '*.sh' \
|
||||
-o -path '*/.profile' \
|
||||
-o -path '*/profile' \
|
||||
-o -name '*.shlib' \
|
||||
')' \
|
||||
-print0)
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
head -n1 "$file" | grep -Eqs "$shebangregex" || continue
|
||||
filepaths+=("$file")
|
||||
done < <(find . \
|
||||
-type f ! -name '*.*' -perm /111 \
|
||||
-print0)
|
||||
|
||||
shellcheck "${filepaths[@]}" || statuscode=$?
|
||||
|
||||
set +f # re-enable globbing
|
||||
|
||||
exit "$statuscode"
|
||||
@@ -1,10 +0,0 @@
|
||||
#
|
||||
# GitLeaks Repo Specific Configuration
|
||||
#
|
||||
# This allowlist is used to help Red Hat ignore false positives during its code
|
||||
# scans.
|
||||
|
||||
[allowlist]
|
||||
paths = [
|
||||
'''tests/*''',
|
||||
]
|
||||
103
CHANGELOG
103
CHANGELOG
@@ -1,105 +1,5 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
version 0.11.2 (released 2025-06-24)
|
||||
* Security:
|
||||
* CVE-2025-4877 - Write beyond bounds in binary to base64 conversion
|
||||
* CVE-2025-4878 - Use of uninitialized variable in privatekey_from_file()
|
||||
* CVE-2025-5318 - Likely read beyond bounds in sftp server handle management
|
||||
* CVE-2025-5351 - Double free in functions exporting keys
|
||||
* CVE-2025-5372 - ssh_kdf() returns a success code on certain failures
|
||||
* CVE-2025-5449 - Likely read beyond bounds in sftp server message decoding
|
||||
* CVE-2025-5987 - Invalid return code for chacha20 poly1305 with OpenSSL
|
||||
* Compatibility
|
||||
* Fixed compatibility with CPM.cmake
|
||||
* Compatibility with OpenSSH 10.0
|
||||
* Tests compatibility with new Dropbear releases
|
||||
* Removed p11-kit remoting from the pkcs11 testsuite
|
||||
* Bugfixes
|
||||
* Implement missing packet filter for DH GEX
|
||||
* Properly process the SSH2_MSG_DEBUG message
|
||||
* Allow escaping quotes in quoted arguments to ssh configuration
|
||||
* Do not fail with unknown match keywords in ssh configuration
|
||||
* Process packets before selecting signature algorithm during authentication
|
||||
* Do not fail hard when the SFTP status message is not sent by noncompliant
|
||||
servers
|
||||
|
||||
version 0.11.1 (released 2024-08-30)
|
||||
* Fixed default TTY modes that are set when stdin is not connected to tty (#270)
|
||||
* Fixed zlib cleanup procedure, which could crash on i386
|
||||
* Various test fixes improving their stability
|
||||
* Fixed cygwin build
|
||||
|
||||
version 0.11.0 (released 2024-07-31)
|
||||
* Deprecations and Removals:
|
||||
* Dropped support for DSA
|
||||
* Deprecated Blowfish cipher (will be removed in next release)
|
||||
* Deprecated SSH_BIND_OPTIONS_{RSA,ECDSA}KEY in favor of generic HOSTKEY
|
||||
* Removed the usage of deprecated OpenSSL APIs (Note: Minimum supported
|
||||
OpenSSL version is 1.1.1)
|
||||
* Disabled preauth compression (zlib) by default
|
||||
* Support for pkcs#11 engines are deprecated, pkcs11-provider is used instead
|
||||
* Deprecation of old async SFTP API
|
||||
* libgcrypt cryptographic backend is deprecated
|
||||
* Deprecation of knownhosts hashing
|
||||
* SFTP Improvements:
|
||||
* Added support for async SFTP IO
|
||||
* Added support for sftp_limits() and applied capping to SFTP read/write
|
||||
operations accordingly
|
||||
* Added sftp_home_directory() API support for sftp extension "home-directory"
|
||||
* Added sftp_lsetstat() API for lsetstat extensions
|
||||
* Added sftp_expand_path() to canonicalize path using expand-path@openssh.com
|
||||
extension
|
||||
* Implemented stat and realpath in sftpserver
|
||||
* Added sftp_readlink() API to support hardlink@openssh.com
|
||||
* New extensible callback based SFTP server
|
||||
* Introduced the posix-rename@openssh.com extension
|
||||
* New functions and features:
|
||||
* Added support for PKCS #11 provider for OpenSSL 3.0
|
||||
* Added testing for GSSAPI Authentication
|
||||
* Implemented proxy jump using libssh
|
||||
* Recategorized loglevels to show fatal errors and alignment with OpenSSH
|
||||
log levels
|
||||
* Added ssh_channel_request_pty_size_modes() API to set terminal modes for
|
||||
PTYs
|
||||
* Added function to check username syntax
|
||||
* Added support to check all keys in authorized_keys instead of one in
|
||||
example server implementation
|
||||
* Handled hostkey similar to OpenSSH
|
||||
* Added ssh_session_socket_close() API in order to not close socket passed
|
||||
through options on error conditions
|
||||
* Added option SSH_BIND_OPTIONS_IMPORT_KEY_STR to read user-supplied key
|
||||
string in ssh_bind_options_set()
|
||||
* Improved log handling around ssh_set_callbacks
|
||||
* Added ssh_set_error_invalid in ssh_options_set()
|
||||
* Prevented signature blob to start with 1 bit in libgcrypt
|
||||
* Added support to unbreak key comparison of Ed25519 keys imported from PEM
|
||||
or OpenSSH container
|
||||
* Added support to calculate missing CRT parameters when building RSA key
|
||||
* Added ssh_pki_export_privkey_base64_format() and
|
||||
ssh_pki_export_privkey_file_format() to support exporting keys in different
|
||||
formats (PEM, OpenSSH)
|
||||
* Added support to compare certificates and handle automatic certificate
|
||||
authentication
|
||||
* Added support to make compile-commands generation conditional
|
||||
* Built fuzzers for normal testing
|
||||
* Avoided passing other events to callbacks when called recursively
|
||||
* Added control master and path options
|
||||
* Refactored channel_rcv_data, check for errors and report more useful errors
|
||||
* Added support to connect to other host addresses than just the first one
|
||||
* Terminated the server properly when the MaxAuthTries is reached
|
||||
* Added support for no-more-sessions@openssh.com request in both client and
|
||||
server
|
||||
* Added callback to support forwarded-tcpip requests
|
||||
* Bumped minimal CMake version to 3.12
|
||||
* Added support for MBedTLS 3.6.x
|
||||
* Added support for +,-,^ modifiers in front of algorithm lists in options
|
||||
* Added callbacks for channel open response, and channel request response
|
||||
* Replaced chroot() from chroot_wrapper internal library with chroot()
|
||||
from priv_wrapper package
|
||||
* Added a placeholder for non-expanded identities
|
||||
* Improved handling of channel transfer window sizes
|
||||
|
||||
version 0.10.6 (released 2023-12-18)
|
||||
* Fix CVE-2023-6004: Command injection using proxycommand
|
||||
* Fix CVE-2023-48795: Potential downgrade attack using strict kex
|
||||
@@ -175,6 +75,9 @@ version 0.10.0 (released 2022-08-26)
|
||||
* Deprecated old pubkey, privatekey API
|
||||
* Avoided some needless large stack buffers to minimize memory footprint
|
||||
* Removed support for OpenSSL < 1.0.1
|
||||
* Fixed parsing username@host in login name
|
||||
* Free global init mutex in the destructor on Windows
|
||||
* Fixed PEM parsing in mbedtls to support both legacy and new PKCS8 formats
|
||||
|
||||
version 0.9.6 (released 2021-08-26)
|
||||
* CVE-2021-3634: Fix possible heap-buffer overflow when rekeying with
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.12.0)
|
||||
cmake_minimum_required(VERSION 3.3.0)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
|
||||
# Specify search path for CMake modules to be loaded by include()
|
||||
# and find_package()
|
||||
@@ -9,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
|
||||
project(libssh VERSION 0.11.2 LANGUAGES C)
|
||||
project(libssh VERSION 0.10.6 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -21,7 +22,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.10.2")
|
||||
set(LIBRARY_VERSION "4.9.6")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
@@ -48,12 +49,32 @@ endif (WITH_ZLIB)
|
||||
|
||||
if (WITH_GCRYPT)
|
||||
find_package(GCrypt 1.5.0 REQUIRED)
|
||||
message(WARNING "libgcrypt cryptographic backend is deprecated and will be removed in future releases.")
|
||||
if (NOT GCRYPT_FOUND)
|
||||
message(FATAL_ERROR "Could not find GCrypt")
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
elseif(WITH_MBEDTLS)
|
||||
find_package(MbedTLS REQUIRED)
|
||||
else()
|
||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||
endif()
|
||||
if (NOT MBEDTLS_FOUND)
|
||||
message(FATAL_ERROR "Could not find mbedTLS")
|
||||
endif (NOT MBEDTLS_FOUND)
|
||||
else (WITH_GCRYPT)
|
||||
find_package(OpenSSL 1.0.1)
|
||||
if (OPENSSL_FOUND)
|
||||
# On CMake < 3.16, OPENSSL_CRYPTO_LIBRARIES is usually a synonym for OPENSSL_CRYPTO_LIBRARY, but is not defined
|
||||
# when building on Windows outside of Cygwin. We provide the synonym here, if FindOpenSSL didn't define it already.
|
||||
if (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
|
||||
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
endif (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
|
||||
else (OPENSSL_FOUND)
|
||||
find_package(GCrypt)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
find_package(MbedTLS)
|
||||
if (NOT MBEDTLS_FOUND)
|
||||
message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
|
||||
endif (NOT MBEDTLS_FOUND)
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
endif (OPENSSL_FOUND)
|
||||
endif(WITH_GCRYPT)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
find_package(CMocka REQUIRED)
|
||||
@@ -68,6 +89,13 @@ if (WITH_GSSAPI)
|
||||
find_package(GSSAPI)
|
||||
endif (WITH_GSSAPI)
|
||||
|
||||
if (WITH_PKCS11_URI)
|
||||
find_package(softhsm)
|
||||
if (NOT SOFTHSM_FOUND)
|
||||
message(SEND_ERROR "Could not find softhsm module!")
|
||||
endif (NOT SOFTHSM_FOUND)
|
||||
endif (WITH_PKCS11_URI)
|
||||
|
||||
if (WITH_NACL)
|
||||
find_package(NaCl)
|
||||
if (NOT NACL_FOUND)
|
||||
@@ -75,6 +103,8 @@ if (WITH_NACL)
|
||||
endif (NOT NACL_FOUND)
|
||||
endif (WITH_NACL)
|
||||
|
||||
find_package(Argp)
|
||||
|
||||
# Disable symbol versioning in non UNIX platforms
|
||||
if (UNIX)
|
||||
find_package(ABIMap 0.3.1)
|
||||
@@ -86,10 +116,6 @@ endif (UNIX)
|
||||
include(ConfigureChecks.cmake)
|
||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
if (NOT HAVE_ARGP_PARSE)
|
||||
find_package(Argp)
|
||||
endif (NOT HAVE_ARGP_PARSE)
|
||||
|
||||
# check subdirectories
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(include)
|
||||
@@ -188,36 +214,16 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
endif(UPDATE_ABI)
|
||||
endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
|
||||
# Coverage
|
||||
if (WITH_COVERAGE)
|
||||
ENABLE_LANGUAGE(CXX)
|
||||
include(CodeCoverage)
|
||||
setup_target_for_coverage_lcov(
|
||||
NAME "coverage"
|
||||
EXECUTABLE make test
|
||||
DEPENDENCIES ssh tests)
|
||||
set(GCOVR_ADDITIONAL_ARGS --xml-pretty --exclude-unreachable-branches --print-summary)
|
||||
setup_target_for_coverage_gcovr_xml(
|
||||
NAME "coverage_xml"
|
||||
EXECUTABLE make test
|
||||
DEPENDENCIES ssh tests)
|
||||
endif (WITH_COVERAGE)
|
||||
|
||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET} VERBATIM)
|
||||
|
||||
get_directory_property(hasParent PARENT_DIRECTORY)
|
||||
if(NOT(hasParent))
|
||||
# Link compile database for clangd if we are the master project
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"${CMAKE_BINARY_DIR}/compile_commands.json"
|
||||
"${CMAKE_SOURCE_DIR}/compile_commands.json")
|
||||
endif()
|
||||
# Link compile database for clangd
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"${CMAKE_BINARY_DIR}/compile_commands.json"
|
||||
"${CMAKE_SOURCE_DIR}/compile_commands.json")
|
||||
|
||||
message(STATUS "********************************************")
|
||||
message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
||||
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "Coverage: ${WITH_COVERAGE}")
|
||||
message(STATUS "zlib support: ${WITH_ZLIB}")
|
||||
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
||||
message(STATUS "libmbedTLS support: ${WITH_MBEDTLS}")
|
||||
@@ -227,14 +233,13 @@ message(STATUS "Server support : ${WITH_SERVER}")
|
||||
message(STATUS "GSSAPI support : ${WITH_GSSAPI}")
|
||||
message(STATUS "GEX support : ${WITH_GEX}")
|
||||
message(STATUS "Support insecure none cipher and MAC : ${WITH_INSECURE_NONE}")
|
||||
message(STATUS "Support exec : ${WITH_EXEC}")
|
||||
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
|
||||
message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}")
|
||||
message(STATUS "Unit testing: ${UNIT_TESTING}")
|
||||
message(STATUS "Client code testing: ${CLIENT_TESTING}")
|
||||
message(STATUS "Blowfish cipher support: ${HAVE_BLOWFISH}")
|
||||
message(STATUS "Blowfish cipher support: ${WITH_BLOWFISH_CIPHER}")
|
||||
message(STATUS "PKCS #11 URI support: ${WITH_PKCS11_URI}")
|
||||
message(STATUS "With PKCS #11 provider support: ${WITH_PKCS11_PROVIDER}")
|
||||
message(STATUS "DSA support: ${WITH_DSA}")
|
||||
set(_SERVER_TESTING OFF)
|
||||
if (WITH_SERVER)
|
||||
set(_SERVER_TESTING ${SERVER_TESTING})
|
||||
|
||||
@@ -478,45 +478,6 @@ Macros like `STATUS_NOT_OK_RETURN` that change control flow (return/goto/etc)
|
||||
from within the macro are considered bad, because they look like function calls
|
||||
that never change control flow. Please do not introduce them.
|
||||
|
||||
### Switch/case indentation
|
||||
|
||||
The `case` should not be indented to avoid wasting too much horizontal space.
|
||||
When the case block contains local variables that need to be wrapped in braces,
|
||||
they should not be indented again either.
|
||||
|
||||
Good example:
|
||||
|
||||
switch (x) {
|
||||
case 0:
|
||||
do_stuff();
|
||||
break;
|
||||
case 1: {
|
||||
int y;
|
||||
do_stuff();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
do_other_stuff();
|
||||
break;
|
||||
}
|
||||
|
||||
Bad example:
|
||||
|
||||
switch (x) {
|
||||
case 0:
|
||||
do_stuff();
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
int y;
|
||||
do_stuff();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
do_other_stuff();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Have fun and happy libssh hacking!
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
|
||||
# SOURCE GENERATOR
|
||||
set(CPACK_SOURCE_GENERATOR "TXZ")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]bare/;/[.]git/;/[.]git;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
### NSIS INSTALLER
|
||||
|
||||
@@ -16,6 +16,7 @@ if (UNIX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS)
|
||||
@@ -42,13 +43,6 @@ if (UNIX)
|
||||
add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wmissing-field-initializers" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wsign-compare" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wold-style-definition" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=old-style-definition" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wimplicit-int" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=implicit-int" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wint-conversion" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=int-conversion" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=unused-variable" SUPPORTED_COMPILER_FLAGS)
|
||||
|
||||
check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT)
|
||||
if (REQUIRED_FLAGS_WFORMAT)
|
||||
@@ -92,12 +86,9 @@ if (UNIX)
|
||||
endif (WITH_STACK_PROTECTOR_STRONG)
|
||||
|
||||
if (NOT WINDOWS AND NOT CYGWIN)
|
||||
# apple m* chips do not support this option
|
||||
if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL arm64)
|
||||
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
|
||||
if (WITH_STACK_CLASH_PROTECTION)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
|
||||
endif()
|
||||
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
|
||||
if (WITH_STACK_CLASH_PROTECTION)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -44,8 +44,6 @@ int main(void){ return 0; }
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||
|
||||
# HEADER FILES
|
||||
check_function_exists(argp_parse HAVE_ARGP_PARSE)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ARGP_INCLUDE_DIR})
|
||||
check_include_file(argp.h HAVE_ARGP_H)
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
@@ -64,7 +62,6 @@ check_include_file(arpa/inet.h HAVE_ARPA_INET_H)
|
||||
check_include_file(byteswap.h HAVE_BYTESWAP_H)
|
||||
check_include_file(glob.h HAVE_GLOB_H)
|
||||
check_include_file(valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H)
|
||||
check_include_file(ifaddrs.h HAVE_IFADDRS_H)
|
||||
|
||||
if (WIN32)
|
||||
check_include_file(io.h HAVE_IO_H)
|
||||
@@ -78,32 +75,78 @@ endif (WIN32)
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto)
|
||||
|
||||
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
||||
if (NOT HAVE_OPENSSL_DES_H)
|
||||
message(FATAL_ERROR "Could not detect openssl/des.h")
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
|
||||
if (NOT HAVE_OPENSSL_AES_H)
|
||||
message(FATAL_ERROR "Could not detect openssl/aes.h")
|
||||
endif()
|
||||
|
||||
if (WITH_BLOWFISH_CIPHER)
|
||||
check_include_file(openssl/blowfish.h HAVE_BLOWFISH)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_KDF_CTX_new HAVE_OPENSSL_EVP_KDF_CTX_NEW)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_DigestVerify HAVE_OPENSSL_EVP_DIGESTVERIFY)
|
||||
|
||||
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_chacha20 HAVE_OPENSSL_EVP_CHACHA20)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_symbol_exists(EVP_PKEY_POLY1305 "openssl/evp.h" HAVE_OPENSSL_EVP_POLY1305)
|
||||
|
||||
if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND
|
||||
FOUND_OPENSSL_ED25519)
|
||||
set(HAVE_OPENSSL_ED25519 1)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519)
|
||||
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif()
|
||||
@@ -127,6 +170,12 @@ if (NOT WITH_GCRYPT AND NOT WITH_MBEDTLS)
|
||||
|
||||
endif ()
|
||||
|
||||
if (WITH_DSA)
|
||||
if (NOT WITH_MBEDTLS)
|
||||
set(HAVE_DSA 1)
|
||||
endif (NOT WITH_MBEDTLS)
|
||||
endif()
|
||||
|
||||
# FUNCTIONS
|
||||
|
||||
check_function_exists(isblank HAVE_ISBLANK)
|
||||
@@ -236,10 +285,6 @@ if (MBEDTLS_FOUND)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${MBEDTLS_INCLUDE_DIR}/mbedtls")
|
||||
check_include_file(chacha20.h HAVE_MBEDTLS_CHACHA20_H)
|
||||
check_include_file(poly1305.h HAVE_MBEDTLS_POLY1305_H)
|
||||
if (WITH_BLOWFISH_CIPHER)
|
||||
check_include_file(blowfish.h HAVE_BLOWFISH)
|
||||
endif()
|
||||
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
|
||||
endif (MBEDTLS_FOUND)
|
||||
@@ -444,22 +489,22 @@ if (WITH_PKCS11_URI)
|
||||
if (WITH_GCRYPT)
|
||||
message(FATAL_ERROR "PKCS #11 is not supported for gcrypt.")
|
||||
set(WITH_PKCS11_URI 0)
|
||||
elseif (WITH_MBEDTLS)
|
||||
endif()
|
||||
if (WITH_MBEDTLS)
|
||||
message(FATAL_ERROR "PKCS #11 is not supported for mbedcrypto")
|
||||
set(WITH_PKCS11_URI 0)
|
||||
elseif (OPENSSL_FOUND AND OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||
find_library(PKCS11_PROVIDER
|
||||
NAMES
|
||||
pkcs11.so
|
||||
PATH_SUFFIXES
|
||||
ossl-modules
|
||||
)
|
||||
if (NOT PKCS11_PROVIDER)
|
||||
set(WITH_PKCS11_PROVIDER 0)
|
||||
message(WARNING "Could not find pkcs11 provider! Falling back to engines")
|
||||
message(WARNING "The support for engines is deprecated in OpenSSL and will be removed from libssh in the future releases.")
|
||||
endif (NOT PKCS11_PROVIDER)
|
||||
endif ()
|
||||
endif()
|
||||
if (HAVE_OPENSSL AND NOT OPENSSL_VERSION VERSION_GREATER_EQUAL "1.1.1")
|
||||
message(FATAL_ERROR "PKCS #11 requires at least OpenSSL 1.1.1")
|
||||
set(WITH_PKCS11_URI 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_MBEDTLS)
|
||||
if (WITH_DSA)
|
||||
message(FATAL_ERROR "DSA is not supported with mbedTLS crypto")
|
||||
set(HAVE_DSA 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ENDIAN
|
||||
|
||||
@@ -5,18 +5,17 @@ option(WITH_SERVER "Build with SSH server support" ON)
|
||||
option(WITH_DEBUG_CRYPTO "Build with crypto debug output" OFF)
|
||||
option(WITH_DEBUG_PACKET "Build with packet debug output" OFF)
|
||||
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
|
||||
option(WITH_GCRYPT "Compile against libgcrypt (deprecated)" OFF)
|
||||
option(WITH_DSA "Build with DSA" OFF)
|
||||
option(WITH_GCRYPT "Compile against libgcrypt" OFF)
|
||||
option(WITH_MBEDTLS "Compile against libmbedtls" OFF)
|
||||
option(WITH_BLOWFISH_CIPHER "Compile with blowfish support" OFF)
|
||||
option(WITH_PCAP "Compile with Pcap generation support" ON)
|
||||
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
option(WITH_PKCS11_URI "Build with PKCS#11 URI support" OFF)
|
||||
option(WITH_PKCS11_PROVIDER "Use the PKCS#11 provider for accessing pkcs11 objects" OFF)
|
||||
option(UNIT_TESTING "Build with unit tests" OFF)
|
||||
option(CLIENT_TESTING "Build with client tests; requires openssh" OFF)
|
||||
option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF)
|
||||
option(GSSAPI_TESTING "Build with GSSAPI tests; requires krb5-server,krb5-libs and krb5-workstation" OFF)
|
||||
option(WITH_BENCHMARKS "Build benchmarks tools; enables unit testing and client tests" OFF)
|
||||
option(WITH_EXAMPLES "Build examples" ON)
|
||||
option(WITH_NACL "Build with libnacl (curve25519)" ON)
|
||||
@@ -24,7 +23,6 @@ option(WITH_SYMBOL_VERSIONING "Build with symbol versioning" ON)
|
||||
option(WITH_ABI_BREAK "Allow ABI break" OFF)
|
||||
option(WITH_GEX "Enable DH Group exchange mechanisms" ON)
|
||||
option(WITH_INSECURE_NONE "Enable insecure none cipher and MAC algorithms (not suitable for production!)" OFF)
|
||||
option(WITH_EXEC "Enable libssh to execute arbitrary commands from configuration files or options (match exec, proxy commands and OpenSSH-based proxy-jumps)." ON)
|
||||
option(FUZZ_TESTING "Build with fuzzer for the server and client (automatically enables none cipher!)" OFF)
|
||||
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
|
||||
|
||||
@@ -39,7 +37,7 @@ if (WITH_BENCHMARKS)
|
||||
set(CLIENT_TESTING ON)
|
||||
endif()
|
||||
|
||||
if (UNIT_TESTING OR CLIENT_TESTING OR SERVER_TESTING OR GSSAPI_TESTING)
|
||||
if (UNIT_TESTING OR CLIENT_TESTING OR SERVER_TESTING)
|
||||
set(BUILD_STATIC_LIB ON)
|
||||
endif()
|
||||
|
||||
@@ -62,7 +60,3 @@ endif (NOT GLOBAL_CLIENT_CONFIG)
|
||||
if (FUZZ_TESTING)
|
||||
set(WITH_INSECURE_NONE ON)
|
||||
endif (FUZZ_TESTING)
|
||||
|
||||
if (WIN32)
|
||||
set(WITH_EXEC 0)
|
||||
endif(WIN32)
|
||||
|
||||
10
INSTALL
10
INSTALL
@@ -7,13 +7,11 @@
|
||||
In order to build libssh, you need to install several components:
|
||||
|
||||
- A C compiler
|
||||
- [CMake](https://www.cmake.org) >= 3.12.0
|
||||
- [CMake](https://www.cmake.org) >= 3.3.0
|
||||
- [openssl](https://www.openssl.org) >= 1.0.1
|
||||
or
|
||||
- [gcrypt](https://www.gnu.org/directory/Security/libgcrypt.html) >= 1.4
|
||||
- [libz](https://www.zlib.net) >= 1.2
|
||||
- [openssl](https://www.openssl.org) >= 1.1.1
|
||||
or
|
||||
- [gcrypt](https://www.gnu.org/directory/Security/libgcrypt.html) >= 1.5
|
||||
or
|
||||
- [Mbed TLS](https://www.trustedfirmware.org/projects/mbed-tls/)
|
||||
|
||||
optional:
|
||||
- [cmocka](https://cmocka.org/) >= 1.1.0
|
||||
|
||||
@@ -116,10 +116,5 @@ function(ADD_CMOCKA_TEST _TARGET_NAME)
|
||||
add_test(${_TARGET_NAME}
|
||||
${TARGET_SYSTEM_EMULATOR} ${_TARGET_NAME}
|
||||
)
|
||||
if (WITH_COVERAGE)
|
||||
ENABLE_LANGUAGE(CXX)
|
||||
include(CodeCoverage)
|
||||
append_coverage_compiler_flags_to_target(${_TARGET_NAME})
|
||||
endif (WITH_COVERAGE)
|
||||
|
||||
endfunction (ADD_CMOCKA_TEST)
|
||||
|
||||
@@ -1,750 +0,0 @@
|
||||
# Copyright (c) 2012 - 2017, Lars Bilke
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# CHANGES:
|
||||
#
|
||||
# 2012-01-31, Lars Bilke
|
||||
# - Enable Code Coverage
|
||||
#
|
||||
# 2013-09-17, Joakim Söderberg
|
||||
# - Added support for Clang.
|
||||
# - Some additional usage instructions.
|
||||
#
|
||||
# 2016-02-03, Lars Bilke
|
||||
# - Refactored functions to use named parameters
|
||||
#
|
||||
# 2017-06-02, Lars Bilke
|
||||
# - Merged with modified version from github.com/ufz/ogs
|
||||
#
|
||||
# 2019-05-06, Anatolii Kurotych
|
||||
# - Remove unnecessary --coverage flag
|
||||
#
|
||||
# 2019-12-13, FeRD (Frank Dana)
|
||||
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
|
||||
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
|
||||
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
|
||||
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
|
||||
# - Set lcov basedir with -b argument
|
||||
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
|
||||
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
|
||||
# - Delete output dir, .info file on 'make clean'
|
||||
# - Remove Python detection, since version mismatches will break gcovr
|
||||
# - Minor cleanup (lowercase function names, update examples...)
|
||||
#
|
||||
# 2019-12-19, FeRD (Frank Dana)
|
||||
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
|
||||
#
|
||||
# 2020-01-19, Bob Apthorpe
|
||||
# - Added gfortran support
|
||||
#
|
||||
# 2020-02-17, FeRD (Frank Dana)
|
||||
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
|
||||
# in EXCLUDEs, and remove manual escaping from gcovr targets
|
||||
#
|
||||
# 2021-01-19, Robin Mueller
|
||||
# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
|
||||
# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
|
||||
# flags to the gcovr command
|
||||
#
|
||||
# 2020-05-04, Mihchael Davis
|
||||
# - Add -fprofile-abs-path to make gcno files contain absolute paths
|
||||
# - Fix BASE_DIRECTORY not working when defined
|
||||
# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
|
||||
#
|
||||
# 2021-05-10, Martin Stump
|
||||
# - Check if the generator is multi-config before warning about non-Debug builds
|
||||
#
|
||||
# 2022-02-22, Marko Wehle
|
||||
# - Change gcovr output from -o <filename> for --xml <filename> and --html <filename> output respectively.
|
||||
# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt".
|
||||
#
|
||||
# 2022-09-28, Sebastian Mueller
|
||||
# - fix append_coverage_compiler_flags_to_target to correctly add flags
|
||||
# - replace "-fprofile-arcs -ftest-coverage" with "--coverage" (equivalent)
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
#
|
||||
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
|
||||
# using a CMake option() to enable it just optionally):
|
||||
# include(CodeCoverage)
|
||||
#
|
||||
# 3. Append necessary compiler flags for all supported source files:
|
||||
# append_coverage_compiler_flags()
|
||||
# Or for specific target:
|
||||
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
|
||||
#
|
||||
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
|
||||
#
|
||||
# 4. If you need to exclude additional directories from the report, specify them
|
||||
# using full paths in the COVERAGE_EXCLUDES variable before calling
|
||||
# setup_target_for_coverage_*().
|
||||
# Example:
|
||||
# set(COVERAGE_EXCLUDES
|
||||
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
|
||||
# '/path/to/my/src/dir2/*')
|
||||
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
|
||||
# Example:
|
||||
# setup_target_for_coverage_lcov(
|
||||
# NAME coverage
|
||||
# EXECUTABLE testrunner
|
||||
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
|
||||
#
|
||||
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
|
||||
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
|
||||
# Example:
|
||||
# set(COVERAGE_EXCLUDES "dir1/*")
|
||||
# setup_target_for_coverage_gcovr_html(
|
||||
# NAME coverage
|
||||
# EXECUTABLE testrunner
|
||||
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
|
||||
# EXCLUDE "dir2/*")
|
||||
#
|
||||
# 5. Use the functions described below to create a custom make target which
|
||||
# runs your test executable and produces a code coverage report.
|
||||
#
|
||||
# 6. Build a Debug build:
|
||||
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
# make
|
||||
# make my_coverage_target
|
||||
#
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
|
||||
|
||||
# Check prereqs
|
||||
find_program( GCOV_PATH gcov )
|
||||
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
|
||||
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
|
||||
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
|
||||
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
|
||||
find_program( CPPFILT_PATH NAMES c++filt )
|
||||
|
||||
if(NOT GCOV_PATH)
|
||||
message(FATAL_ERROR "gcov not found! Aborting...")
|
||||
endif() # NOT GCOV_PATH
|
||||
|
||||
# Check supported compiler (Clang, GNU and Flang)
|
||||
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
foreach(LANG ${LANGUAGES})
|
||||
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
|
||||
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
|
||||
endif()
|
||||
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
|
||||
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
|
||||
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-update=atomic"
|
||||
CACHE INTERNAL "")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
|
||||
if(HAVE_cxx_fprofile_abs_path)
|
||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
||||
if(HAVE_c_fprofile_abs_path)
|
||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_Fortran_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_C_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE )
|
||||
mark_as_advanced(
|
||||
CMAKE_Fortran_FLAGS_COVERAGE
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||
|
||||
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
||||
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
||||
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||
link_libraries(gcov)
|
||||
endif()
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# setup_target_for_coverage_lcov(
|
||||
# NAME testrunner_coverage # New target name
|
||||
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES testrunner # Dependencies to build first
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||
# NO_DEMANGLE # Don't demangle C++ symbols
|
||||
# # even if c++filt is found
|
||||
# )
|
||||
function(setup_target_for_coverage_lcov)
|
||||
|
||||
set(options NO_DEMANGLE SONARQUBE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT LCOV_PATH)
|
||||
message(FATAL_ERROR "lcov not found! Aborting...")
|
||||
endif() # NOT LCOV_PATH
|
||||
|
||||
if(NOT GENHTML_PATH)
|
||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
endif() # NOT GENHTML_PATH
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||
set(LCOV_EXCLUDES "")
|
||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||
endif()
|
||||
list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES LCOV_EXCLUDES)
|
||||
|
||||
# Conditional arguments
|
||||
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
|
||||
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
|
||||
endif()
|
||||
|
||||
# Setting up commands which will be run to generate coverage data.
|
||||
# Cleanup lcov
|
||||
set(LCOV_CLEAN_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory .
|
||||
-b ${BASEDIR} --zerocounters
|
||||
)
|
||||
# Create baseline to make sure untouched files show up in the report
|
||||
set(LCOV_BASELINE_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b
|
||||
${BASEDIR} -o ${Coverage_NAME}.base
|
||||
)
|
||||
# Run tests
|
||||
set(LCOV_EXEC_TESTS_CMD
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
)
|
||||
# Capturing lcov counters and generating report
|
||||
set(LCOV_CAPTURE_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b
|
||||
${BASEDIR} --capture --output-file ${Coverage_NAME}.capture
|
||||
)
|
||||
# add baseline counters
|
||||
set(LCOV_BASELINE_COUNT_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base
|
||||
-a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total
|
||||
)
|
||||
# filter collected data to final coverage report
|
||||
set(LCOV_FILTER_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove
|
||||
${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info
|
||||
)
|
||||
# Generate HTML output
|
||||
set(LCOV_GEN_HTML_CMD
|
||||
${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o
|
||||
${Coverage_NAME} ${Coverage_NAME}.info
|
||||
)
|
||||
if(${Coverage_SONARQUBE})
|
||||
# Generate SonarQube output
|
||||
set(GCOVR_XML_CMD
|
||||
${GCOVR_PATH} --sonarqube ${Coverage_NAME}_sonarqube.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
||||
)
|
||||
set(GCOVR_XML_CMD_COMMAND
|
||||
COMMAND ${GCOVR_XML_CMD}
|
||||
)
|
||||
set(GCOVR_XML_CMD_BYPRODUCTS ${Coverage_NAME}_sonarqube.xml)
|
||||
set(GCOVR_XML_CMD_COMMENT COMMENT "SonarQube code coverage info report saved in ${Coverage_NAME}_sonarqube.xml.")
|
||||
endif()
|
||||
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
message(STATUS "Command to clean up lcov: ")
|
||||
string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}")
|
||||
message(STATUS "${LCOV_CLEAN_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to create baseline: ")
|
||||
string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}")
|
||||
message(STATUS "${LCOV_BASELINE_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to run the tests: ")
|
||||
string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to capture counters and generate report: ")
|
||||
string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}")
|
||||
message(STATUS "${LCOV_CAPTURE_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to add baseline counters: ")
|
||||
string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}")
|
||||
message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to filter collected data: ")
|
||||
string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}")
|
||||
message(STATUS "${LCOV_FILTER_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to generate lcov HTML output: ")
|
||||
string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}")
|
||||
message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}")
|
||||
|
||||
if(${Coverage_SONARQUBE})
|
||||
message(STATUS "Command to generate SonarQube XML output: ")
|
||||
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
|
||||
message(STATUS "${GCOVR_XML_CMD_SPACED}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Setup target
|
||||
add_custom_target(${Coverage_NAME}
|
||||
COMMAND ${LCOV_CLEAN_CMD}
|
||||
COMMAND ${LCOV_BASELINE_CMD}
|
||||
COMMAND ${LCOV_EXEC_TESTS_CMD}
|
||||
COMMAND ${LCOV_CAPTURE_CMD}
|
||||
COMMAND ${LCOV_BASELINE_COUNT_CMD}
|
||||
COMMAND ${LCOV_FILTER_CMD}
|
||||
COMMAND ${LCOV_GEN_HTML_CMD}
|
||||
${GCOVR_XML_CMD_COMMAND}
|
||||
|
||||
# Set output files as GENERATED (will be removed on 'make clean')
|
||||
BYPRODUCTS
|
||||
${Coverage_NAME}.base
|
||||
${Coverage_NAME}.capture
|
||||
${Coverage_NAME}.total
|
||||
${Coverage_NAME}.info
|
||||
${GCOVR_XML_CMD_BYPRODUCTS}
|
||||
${Coverage_NAME}/index.html
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
||||
)
|
||||
|
||||
# Show where to find the lcov info report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
|
||||
${GCOVR_XML_CMD_COMMENT}
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
endfunction() # setup_target_for_coverage_lcov
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# setup_target_for_coverage_gcovr_xml(
|
||||
# NAME ctest_coverage # New target name
|
||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES executable_target # Dependencies to build first
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||
# )
|
||||
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
||||
# GCVOR command.
|
||||
function(setup_target_for_coverage_gcovr_xml)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
endif() # NOT GCOVR_PATH
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||
set(GCOVR_EXCLUDES "")
|
||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||
endif()
|
||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||
|
||||
# Combine excludes to several -e arguments
|
||||
set(GCOVR_EXCLUDE_ARGS "")
|
||||
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||
endforeach()
|
||||
|
||||
# Set up commands which will be run to generate coverage data
|
||||
# Run tests
|
||||
set(GCOVR_XML_EXEC_TESTS_CMD
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
)
|
||||
# Running gcovr
|
||||
set(GCOVR_XML_CMD
|
||||
${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
|
||||
message(STATUS "Command to run tests: ")
|
||||
string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to generate gcovr XML coverage data: ")
|
||||
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
|
||||
message(STATUS "${GCOVR_XML_CMD_SPACED}")
|
||||
endif()
|
||||
|
||||
add_custom_target(${Coverage_NAME}
|
||||
COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
|
||||
COMMAND ${GCOVR_XML_CMD}
|
||||
|
||||
BYPRODUCTS ${Coverage_NAME}.xml
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
|
||||
)
|
||||
endfunction() # setup_target_for_coverage_gcovr_xml
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# setup_target_for_coverage_gcovr_html(
|
||||
# NAME ctest_coverage # New target name
|
||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES executable_target # Dependencies to build first
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||
# )
|
||||
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
||||
# GCVOR command.
|
||||
function(setup_target_for_coverage_gcovr_html)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
endif() # NOT GCOVR_PATH
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||
set(GCOVR_EXCLUDES "")
|
||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||
endif()
|
||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||
|
||||
# Combine excludes to several -e arguments
|
||||
set(GCOVR_EXCLUDE_ARGS "")
|
||||
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||
endforeach()
|
||||
|
||||
# Set up commands which will be run to generate coverage data
|
||||
# Run tests
|
||||
set(GCOVR_HTML_EXEC_TESTS_CMD
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
)
|
||||
# Create folder
|
||||
set(GCOVR_HTML_FOLDER_CMD
|
||||
${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
|
||||
)
|
||||
# Running gcovr
|
||||
set(GCOVR_HTML_CMD
|
||||
${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
|
||||
message(STATUS "Command to run tests: ")
|
||||
string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to create a folder: ")
|
||||
string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
|
||||
message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to generate gcovr HTML coverage data: ")
|
||||
string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
|
||||
message(STATUS "${GCOVR_HTML_CMD_SPACED}")
|
||||
endif()
|
||||
|
||||
add_custom_target(${Coverage_NAME}
|
||||
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
|
||||
COMMAND ${GCOVR_HTML_FOLDER_CMD}
|
||||
COMMAND ${GCOVR_HTML_CMD}
|
||||
|
||||
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Running gcovr to produce HTML code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
endfunction() # setup_target_for_coverage_gcovr_html
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# setup_target_for_coverage_fastcov(
|
||||
# NAME testrunner_coverage # New target name
|
||||
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES testrunner # Dependencies to build first
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude.
|
||||
# NO_DEMANGLE # Don't demangle C++ symbols
|
||||
# # even if c++filt is found
|
||||
# SKIP_HTML # Don't create html report
|
||||
# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths
|
||||
# )
|
||||
function(setup_target_for_coverage_fastcov)
|
||||
|
||||
set(options NO_DEMANGLE SKIP_HTML)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT FASTCOV_PATH)
|
||||
message(FATAL_ERROR "fastcov not found! Aborting...")
|
||||
endif()
|
||||
|
||||
if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH)
|
||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
endif()
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Collect excludes (Patterns, not paths, for fastcov)
|
||||
set(FASTCOV_EXCLUDES "")
|
||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES})
|
||||
list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES FASTCOV_EXCLUDES)
|
||||
|
||||
# Conditional arguments
|
||||
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
|
||||
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
|
||||
endif()
|
||||
|
||||
# Set up commands which will be run to generate coverage data
|
||||
set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
|
||||
|
||||
set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
|
||||
--search-directory ${BASEDIR}
|
||||
--process-gcno
|
||||
--output ${Coverage_NAME}.json
|
||||
--exclude ${FASTCOV_EXCLUDES}
|
||||
)
|
||||
|
||||
set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH}
|
||||
-C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info
|
||||
)
|
||||
|
||||
if(Coverage_SKIP_HTML)
|
||||
set(FASTCOV_HTML_CMD ";")
|
||||
else()
|
||||
set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS}
|
||||
-o ${Coverage_NAME} ${Coverage_NAME}.info
|
||||
)
|
||||
endif()
|
||||
|
||||
set(FASTCOV_POST_CMD ";")
|
||||
if(Coverage_POST_CMD)
|
||||
set(FASTCOV_POST_CMD ${Coverage_POST_CMD})
|
||||
endif()
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):")
|
||||
|
||||
message(" Running tests:")
|
||||
string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}")
|
||||
message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(" Capturing fastcov counters and generating report:")
|
||||
string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}")
|
||||
message(" ${FASTCOV_CAPTURE_CMD_SPACED}")
|
||||
|
||||
message(" Converting fastcov .json to lcov .info:")
|
||||
string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}")
|
||||
message(" ${FASTCOV_CONVERT_CMD_SPACED}")
|
||||
|
||||
if(NOT Coverage_SKIP_HTML)
|
||||
message(" Generating HTML report: ")
|
||||
string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}")
|
||||
message(" ${FASTCOV_HTML_CMD_SPACED}")
|
||||
endif()
|
||||
if(Coverage_POST_CMD)
|
||||
message(" Running post command: ")
|
||||
string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}")
|
||||
message(" ${FASTCOV_POST_CMD_SPACED}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Setup target
|
||||
add_custom_target(${Coverage_NAME}
|
||||
|
||||
# Cleanup fastcov
|
||||
COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
|
||||
--search-directory ${BASEDIR}
|
||||
--zerocounters
|
||||
|
||||
COMMAND ${FASTCOV_EXEC_TESTS_CMD}
|
||||
COMMAND ${FASTCOV_CAPTURE_CMD}
|
||||
COMMAND ${FASTCOV_CONVERT_CMD}
|
||||
COMMAND ${FASTCOV_HTML_CMD}
|
||||
COMMAND ${FASTCOV_POST_CMD}
|
||||
|
||||
# Set output files as GENERATED (will be removed on 'make clean')
|
||||
BYPRODUCTS
|
||||
${Coverage_NAME}.info
|
||||
${Coverage_NAME}.json
|
||||
${Coverage_NAME}/index.html # report directory
|
||||
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
|
||||
)
|
||||
|
||||
set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.")
|
||||
if(NOT Coverage_SKIP_HTML)
|
||||
string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.")
|
||||
endif()
|
||||
# Show where to find the fastcov info report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG}
|
||||
)
|
||||
|
||||
endfunction() # setup_target_for_coverage_fastcov
|
||||
|
||||
function(append_coverage_compiler_flags)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
||||
endfunction() # append_coverage_compiler_flags
|
||||
|
||||
# Setup coverage for specific library
|
||||
function(append_coverage_compiler_flags_to_target name)
|
||||
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
|
||||
target_compile_options(${name} PRIVATE ${_flag_list})
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(${name} PRIVATE gcov)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -50,28 +50,15 @@ file(READ ${HEADERS_LIST_FILE} HEADERS_LIST)
|
||||
|
||||
set(symbols)
|
||||
foreach(header ${HEADERS_LIST})
|
||||
file(READ ${header} header_content)
|
||||
|
||||
# Filter only lines containing the FILTER_PATTERN
|
||||
# separated from the function name with one optional newline
|
||||
string(REGEX MATCHALL
|
||||
"${FILTER_PATTERN}[^(\n]*\n?[^(\n]*[(]"
|
||||
contain_filter
|
||||
"${header_content}"
|
||||
)
|
||||
|
||||
# Remove the optional newline now
|
||||
string(REGEX REPLACE
|
||||
"(.+)\n?(.*)"
|
||||
"\\1\\2"
|
||||
oneline
|
||||
"${contain_filter}"
|
||||
file(STRINGS ${header} contain_filter
|
||||
REGEX "^.*${FILTER_PATTERN}.*[(]"
|
||||
)
|
||||
|
||||
# Remove function-like macros
|
||||
# and anything with two underscores that sounds suspicious
|
||||
foreach(line ${oneline})
|
||||
if (NOT ${line} MATCHES ".*(#[ ]*define|__)")
|
||||
foreach(line ${contain_filter})
|
||||
if (NOT ${line} MATCHES ".*#[ ]*define")
|
||||
list(APPEND not_macro ${line})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
@@ -220,12 +220,13 @@
|
||||
|
||||
# Search for python which is required
|
||||
if (ABIMap_FIND_REQURIED)
|
||||
find_package(Python REQUIRED)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
else()
|
||||
find_package(Python)
|
||||
find_package(PythonInterp)
|
||||
endif()
|
||||
|
||||
if (TARGET Python::Interpreter)
|
||||
|
||||
if (PYTHONINTERP_FOUND)
|
||||
# Search for abimap tool used to generate the map files
|
||||
find_program(ABIMAP_EXECUTABLE NAMES abimap DOC "path to the abimap executable")
|
||||
mark_as_advanced(ABIMAP_EXECUTABLE)
|
||||
|
||||
@@ -64,7 +64,7 @@ if (ARGP_LIBRARY)
|
||||
endif (ARGP_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Argp DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIR)
|
||||
find_package_handle_standard_args(ARGP DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIR)
|
||||
|
||||
# show the ARGP_INCLUDE_DIR and ARGP_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ARGP_INCLUDE_DIR ARGP_LIBRARIES)
|
||||
|
||||
@@ -39,15 +39,6 @@ find_path(GCRYPT_INCLUDE_DIR
|
||||
include
|
||||
)
|
||||
|
||||
find_path(GCRYPT_ERROR_INCLUDE_DIR
|
||||
NAMES
|
||||
gpg-error.h
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
find_library(GCRYPT_LIBRARY
|
||||
NAMES
|
||||
gcrypt
|
||||
@@ -65,10 +56,8 @@ find_library(GCRYPT_ERROR_LIBRARY
|
||||
libgpg-error6-0
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_ERROR_LIBRARY} ${GCRYPT_LIBRARY})
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY} ${GCRYPT_ERROR_LIBRARY})
|
||||
|
||||
if (GCRYPT_INCLUDE_DIR)
|
||||
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]")
|
||||
@@ -94,25 +83,5 @@ else (GCRYPT_VERSION)
|
||||
GCRYPT_LIBRARIES)
|
||||
endif (GCRYPT_VERSION)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS, GCRYPT_LIBRARIES and GCRYPT_ERROR_INCLUDE_DIR variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_ERROR_INCLUDE_DIR GCRYPT_LIBRARIES)
|
||||
|
||||
if(GCRYPT_FOUND)
|
||||
if(NOT TARGET libgcrypt::libgcrypt)
|
||||
add_library(libgcrypt::libgcrypt UNKNOWN IMPORTED)
|
||||
set_target_properties(libgcrypt::libgcrypt PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${GCRYPT_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES libgcrypt::libgcrypt
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION "${GCRYPT_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET libgpg-error::libgpg-error)
|
||||
add_library(libgpg-error::libgpg-error UNKNOWN IMPORTED)
|
||||
set_target_properties(libgpg-error::libgpg-error PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${GCRYPT_ERROR_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES libgpg-error::libgpg-error
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION "${GCRYPT_ERROR_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES)
|
||||
|
||||
@@ -34,7 +34,7 @@ set(_MBEDTLS_ROOT_HINTS_AND_PATHS
|
||||
|
||||
find_path(MBEDTLS_INCLUDE_DIR
|
||||
NAMES
|
||||
mbedtls/ssl.h
|
||||
mbedtls/config.h
|
||||
HINTS
|
||||
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
@@ -73,14 +73,6 @@ set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY}
|
||||
${MBEDTLS_X509_LIBRARY})
|
||||
|
||||
if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
|
||||
# mbedtls 2.8
|
||||
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
|
||||
"^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
|
||||
|
||||
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*"
|
||||
"\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
|
||||
elseif (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
|
||||
# mbedtls 3.6
|
||||
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
|
||||
"^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
|
||||
|
||||
@@ -101,8 +93,8 @@ if (MBEDTLS_VERSION)
|
||||
in the system variable MBEDTLS_ROOT_DIR"
|
||||
)
|
||||
else (MBEDTLS_VERSION)
|
||||
find_package_handle_standard_args(MbedTLS
|
||||
"Could NOT find mbedTLS, try to set the path to mbedTLS root folder in
|
||||
find_package_handle_standard_args(MBedTLS
|
||||
"Could NOT find mbedTLS, try to set the path to mbedLS root folder in
|
||||
the system variable MBEDTLS_ROOT_DIR"
|
||||
MBEDTLS_INCLUDE_DIR
|
||||
MBEDTLS_LIBRARIES)
|
||||
@@ -110,32 +102,3 @@ endif (MBEDTLS_VERSION)
|
||||
|
||||
# show the MBEDTLS_INCLUDE_DIRS and MBEDTLS_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES)
|
||||
|
||||
if(MBEDTLS_FOUND)
|
||||
if(NOT TARGET MbedTLS::mbedcrypto)
|
||||
add_library(MbedTLS::mbedcrypto UNKNOWN IMPORTED)
|
||||
set_target_properties(MbedTLS::mbedcrypto PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES MbedTLS::mbedcrypto
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION "${MBEDTLS_CRYPTO_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET MbedTLS::mbedx509)
|
||||
add_library(MbedTLS::mbedx509 UNKNOWN IMPORTED)
|
||||
set_target_properties(MbedTLS::mbedx509 PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES MbedTLS::mbedx509
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION "${MBEDTLS_X509_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET MbedTLS::mbedtls)
|
||||
add_library(MbedTLS::mbedtls UNKNOWN IMPORTED)
|
||||
set_target_properties(MbedTLS::mbedtls PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES MbedTLS::mbedtls
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION "${MBEDTLS_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -58,15 +58,15 @@
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#cmakedefine HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <ifaddrs.h> header file. */
|
||||
#cmakedefine HAVE_IFADDRS_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/aes.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_AES_H 1
|
||||
|
||||
/* Define to 1 if you have the <wspiapi.h> header file. */
|
||||
#cmakedefine HAVE_WSPIAPI_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/blowfish.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_BLOWFISH_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/des.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_DES_H 1
|
||||
|
||||
@@ -91,9 +91,21 @@
|
||||
/* Define to 1 if you have elliptic curve cryptography */
|
||||
#cmakedefine HAVE_ECC 1
|
||||
|
||||
/* Define to 1 if you have gl_flags as a glob_t struct member */
|
||||
/* Define to 1 if you have DSA */
|
||||
#cmakedefine HAVE_DSA 1
|
||||
|
||||
/* Define to 1 if you have gl_flags as a glob_t sturct member */
|
||||
#cmakedefine HAVE_GLOB_GL_FLAGS_MEMBER 1
|
||||
|
||||
/* Define to 1 if you have OpenSSL with Ed25519 support */
|
||||
#cmakedefine HAVE_OPENSSL_ED25519 1
|
||||
|
||||
/* Define to 1 if you have OpenSSL with X25519 support */
|
||||
#cmakedefine HAVE_OPENSSL_X25519 1
|
||||
|
||||
/* Define to 1 if you have OpenSSL with Poly1305 support */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_POLY1305 1
|
||||
|
||||
/* Define to 1 if you have gcrypt with ChaCha20/Poly1305 support */
|
||||
#cmakedefine HAVE_GCRYPT_CHACHA_POLY 1
|
||||
|
||||
@@ -108,6 +120,15 @@
|
||||
/* Define to 1 if you have the `FIPS_mode' function. */
|
||||
#cmakedefine HAVE_OPENSSL_FIPS_MODE 1
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestSign' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_DIGESTSIGN 1
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestVerify' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_DIGESTVERIFY 1
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_ia32cap_loc' function. */
|
||||
#cmakedefine HAVE_OPENSSL_IA32CAP_LOC 1
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#cmakedefine HAVE_SNPRINTF 1
|
||||
|
||||
@@ -180,9 +201,6 @@
|
||||
/* Define to 1 if you have the `cmocka_set_test_filter' function. */
|
||||
#cmakedefine HAVE_CMOCKA_SET_TEST_FILTER 1
|
||||
|
||||
/* Define to 1 if we have support for blowfish */
|
||||
#cmakedefine HAVE_BLOWFISH 1
|
||||
|
||||
/*************************** LIBRARIES ***************************/
|
||||
|
||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||
@@ -234,14 +252,9 @@
|
||||
/* Define to 1 if you want to enable DH group exchange algorithms */
|
||||
#cmakedefine WITH_GEX 1
|
||||
|
||||
/* Define to 1 if you want to enable insecure none cipher and MAC */
|
||||
/* Define to 1 if you want to enable none cipher and MAC */
|
||||
#cmakedefine WITH_INSECURE_NONE 1
|
||||
|
||||
/* Define to 1 if you want to allow libssh to execute arbitrary commands from
|
||||
* configuration files or options (match exec, proxy commands and OpenSSH-based
|
||||
* proxy-jumps). */
|
||||
#cmakedefine WITH_EXEC 1
|
||||
|
||||
/* Define to 1 if you want to enable blowfish cipher support */
|
||||
#cmakedefine WITH_BLOWFISH_CIPHER 1
|
||||
|
||||
@@ -263,9 +276,6 @@
|
||||
/* Define to 1 if you want to enable PKCS #11 URI support */
|
||||
#cmakedefine WITH_PKCS11_URI 1
|
||||
|
||||
/* Define to 1 if we want to build a support for PKCS #11 provider. */
|
||||
#cmakedefine WITH_PKCS11_PROVIDER 1
|
||||
|
||||
/*************************** ENDIAN *****************************/
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
|
||||
@@ -14,7 +14,6 @@ if (DOXYGEN_FOUND)
|
||||
set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
|
||||
set(DOXYGEN_MARKDOWN_SUPPORT YES)
|
||||
set(DOXYGEN_FULL_PATH_NAMES NO)
|
||||
set(DOXYGEN_GENERATE_TAGFILE "tags.xml")
|
||||
|
||||
set(DOXYGEN_PREDEFINED DOXYGEN
|
||||
WITH_SERVER
|
||||
@@ -36,44 +35,6 @@ if (DOXYGEN_FOUND)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderclosed.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderopen.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/js/striped_bg.js)
|
||||
set(DOXYGEN_EXCLUDE_PATTERNS */src/external/* fe25519.h ge25519.h sc25519.h
|
||||
blf.h)
|
||||
set(DOXYGEN_EXCLUDE_SYMBOLS_STRUCTS chacha20_poly1305_keysched,dh_ctx,dh_ctx,dh_keypair,error_struct,
|
||||
packet_struct,pem_get_password_struct,ssh_tokens_st,
|
||||
sftp_attributes_struct,sftp_client_message_struct,
|
||||
sftp_dir_struct,sftp_ext_struct,sftp_file_struct,sftp_message_struct,
|
||||
sftp_packet_struct,sftp_request_queue_struct,sftp_session_struct,
|
||||
sftp_status_message_struct,ssh_agent_state_struct,
|
||||
ssh_agent_struct,ssh_auth_auto_state_struct,ssh_auth_request,
|
||||
ssh_bind_config_keyword_table_s,ssh_bind_config_match_keyword_table_s,
|
||||
ssh_bind_struct,ssh_buffer_struct,ssh_channel_callbacks_struct,
|
||||
ssh_channel_read_termination_struct,ssh_channel_request,
|
||||
ssh_channel_request_open,ssh_channel_struct,ssh_cipher_struct,
|
||||
ssh_common_struct,ssh_config_keyword_table_s,
|
||||
ssh_config_match_keyword_table_s,ssh_connector_struct,
|
||||
ssh_counter_struct,ssh_crypto_struct,ssh_event_fd_wrapper,
|
||||
ssh_event_struct,ssh_global_request,ssh_gssapi_struct,ssh_hmac_struct,
|
||||
ssh_iterator,ssh_kbdint_struct,ssh_kex_struct,ssh_key_struct,
|
||||
ssh_knownhosts_entry,ssh_list,ssh_mac_ctx_struct,ssh_message_struct,
|
||||
ssh_packet_callbacks_struct,ssh_packet_header,ssh_poll_ctx_struct,
|
||||
ssh_poll_handle_struct,ssh_pollfd_struct,ssh_private_key_struct,
|
||||
ssh_public_key_struct,ssh_scp_struct,ssh_service_request,
|
||||
ssh_session_struct,ssh_signature_struct,ssh_socket_struct,
|
||||
ssh_string_struct,ssh_threads_callbacks_struct,ssh_timestamp,)
|
||||
set(DOXYGEN_EXCLUDE_SYMBOLS_MACRO SSH_FXP*,SSH_SOCKET*,SERVERBANNER,SOCKOPT_TYPE_ARG4,SSH_FILEXFER*,
|
||||
SSH_FXF*,SSH_S_*,SFTP_*,NSS_BUFLEN_PASSWD,CLOCK,MAX_LINE_SIZE,
|
||||
PKCS11_URI,KNOWNHOSTS_MAXTYPES,)
|
||||
set(DOXYGEN_EXCLUDE_SYMBOLS_TYPEDEFS sftp_attributes,sftp_client_message,sftp_dir,sftp_ext,sftp_file,
|
||||
sftp_message,sftp_packet,sftp_request_queue,sftp_session,
|
||||
sftp_status_message,sftp_statvfs_t,poll_fn,ssh_callback_int,
|
||||
ssh_callback_data,ssh_callback_int_int,ssh_message_callback,
|
||||
ssh_channel_callback_int,ssh_channel_callback_data,ssh_callbacks,
|
||||
ssh_gssapi_select_oid_callback,ssh_gssapi_accept_sec_ctx_callback,
|
||||
ssh_gssapi_verify_mic_callback,ssh_server_callbacks,ssh_socket_callbacks,
|
||||
ssh_packet_callbacks,ssh_channel_callbacks,ssh_bind,ssh_bind_callbacks,)
|
||||
set(DOXYGEN_EXCLUDE_SYMBOLS ${DOXYGEN_EXCLUDE_SYMBOLS_STRUCTS}
|
||||
${DOXYGEN_EXCLUDE_SYMBOLS_MACRO}
|
||||
${DOXYGEN_EXCLUDE_SYMBOLS_TYPEDEFS})
|
||||
|
||||
# This updates the Doxyfile if we do changes here
|
||||
set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in")
|
||||
@@ -84,8 +45,6 @@ if (DOXYGEN_FOUND)
|
||||
${CMAKE_SOURCE_DIR}/include/libssh
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_custom_target(docs_coverage COMMAND ${CMAKE_SOURCE_DIR}/doc/doc_coverage.sh ${CMAKE_BINARY_DIR})
|
||||
endif() # DOXYGEN_FOUND
|
||||
|
||||
endif() # CMAKE_VERSION
|
||||
|
||||
@@ -105,7 +105,7 @@ Here is a small example of password authentication:
|
||||
@code
|
||||
int authenticate_password(ssh_session session)
|
||||
{
|
||||
char *password = NULL;
|
||||
char *password;
|
||||
int rc;
|
||||
|
||||
password = getpass("Enter your password: ");
|
||||
@@ -218,7 +218,7 @@ int authenticate_kbdint(ssh_session session)
|
||||
rc = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
while (rc == SSH_AUTH_INFO)
|
||||
{
|
||||
const char *name = NULL, *instruction = NULL;
|
||||
const char *name, *instruction;
|
||||
int nprompts, iprompt;
|
||||
|
||||
name = ssh_userauth_kbdint_getname(session);
|
||||
@@ -231,7 +231,7 @@ int authenticate_kbdint(ssh_session session)
|
||||
printf("%s\n", instruction);
|
||||
for (iprompt = 0; iprompt < nprompts; iprompt++)
|
||||
{
|
||||
const char *prompt = NULL;
|
||||
const char *prompt;
|
||||
char echo;
|
||||
|
||||
prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
|
||||
@@ -251,7 +251,7 @@ int authenticate_kbdint(ssh_session session)
|
||||
}
|
||||
else
|
||||
{
|
||||
char *ptr = NULL;
|
||||
char *ptr;
|
||||
|
||||
ptr = getpass(prompt);
|
||||
if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0)
|
||||
@@ -354,7 +354,7 @@ The following example shows how to retrieve and dispose the issue banner:
|
||||
int display_banner(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
char *banner = NULL;
|
||||
char *banner;
|
||||
|
||||
/*
|
||||
*** Does not work without calling ssh_userauth_none() first ***
|
||||
|
||||
@@ -22,7 +22,7 @@ a SSH session that uses this channel:
|
||||
@code
|
||||
int show_remote_files(ssh_session session)
|
||||
{
|
||||
ssh_channel channel = NULL;
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# .doc_coverage.sh #
|
||||
# Script to detect overall documentation coverage of libssh. The script uses #
|
||||
# doxygen to generate the documentation then parses it's output. #
|
||||
# #
|
||||
# maintainer: Norbert Pocs <npocs@redhat.com> #
|
||||
################################################################################
|
||||
BUILD_DIR="$1"
|
||||
DOXYFILE_PATH="$BUILD_DIR/doc/Doxyfile.docs"
|
||||
INDEX_XML_PATH="$BUILD_DIR/doc/xml/index.xml"
|
||||
# filters
|
||||
F_EXCLUDE_FILES=' wrapper.h legacy.h crypto.h priv.h chacha.h curve25519.h '
|
||||
F_UNDOC_FUNC='(function).*is not documented'
|
||||
F_FUNC='kind="function"'
|
||||
F_HEADERS='libssh_8h_|group__libssh__'
|
||||
F_CUT_BEFORE='.*<name>'
|
||||
F_CUT_AFTER='<\/name><\/member>'
|
||||
# Doxygen options
|
||||
O_QUIET='QUIET=YES'
|
||||
O_GEN_XML='GENERATE_XML=YES'
|
||||
|
||||
# check if build dir given
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Please provide the build directory e.g.: ./build"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
# modify doxyfile to our needs:
|
||||
# QUIET - less output
|
||||
# GENERATE_XML - xml needed to inspect all the functions
|
||||
# (note: the options are needed to be on separate lines)
|
||||
# We want to exclude irrelevant files
|
||||
MOD_DOXYFILE=$(cat "$DOXYFILE_PATH"; echo "$O_QUIET"; echo "$O_GEN_XML")
|
||||
MOD_DOXYFILE=${MOD_DOXYFILE//EXCLUDE_PATTERNS.*=/EXCLUDE_PATTERNS=$F_EXCLUDE_FILES/g}
|
||||
|
||||
# call doxygen to get the warning messages
|
||||
# and also generate the xml for inspection
|
||||
DOXY_WARNINGS=$(echo "$MOD_DOXYFILE" | doxygen - 2>&1)
|
||||
|
||||
# get the number of undocumented functions
|
||||
UNDOC_FUNC=$(echo "$DOXY_WARNINGS" | grep -cE "$F_UNDOC_FUNC")
|
||||
|
||||
# filter out the lines consisting of functions of our interest
|
||||
FUNC_LINES=$(grep "$F_FUNC" "$INDEX_XML_PATH" | grep -E "$F_HEADERS")
|
||||
# cut the irrelevant information and leave just the function names
|
||||
ALL_FUNC=$(echo "$FUNC_LINES" | sed -e "s/$F_CUT_BEFORE//g" -e "s/$F_CUT_AFTER//")
|
||||
# remove duplicates and get the number of functions
|
||||
ALL_FUNC=$(echo "$ALL_FUNC" | sort - | uniq | wc -l)
|
||||
|
||||
# percentage of the documented functions
|
||||
awk "BEGIN {printf \"Documentation coverage is %.2f%\n\", 100 - (${UNDOC_FUNC}/${ALL_FUNC}*100)}"
|
||||
@@ -100,7 +100,7 @@ used to retrieve google's home page from the remote SSH server.
|
||||
@code
|
||||
int direct_forwarding(ssh_session session)
|
||||
{
|
||||
ssh_channel forwarding_channel = NULL;
|
||||
ssh_channel forwarding_channel;
|
||||
int rc = SSH_ERROR;
|
||||
char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n";
|
||||
int nbytes, nwritten;
|
||||
@@ -161,7 +161,7 @@ local libssh application, which handles them:
|
||||
int web_server(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
ssh_channel channel = NULL;
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
int port = 0;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
A SSH session goes through the following steps:
|
||||
|
||||
- Before connecting to the server, you can set up if you wish one or other
|
||||
server public key authentication, i.e. RSA, ED25519 or ECDSA. You can choose
|
||||
server public key authentication, i.e. DSA or RSA. You can choose
|
||||
cryptographic algorithms you trust and compression algorithms if any. You
|
||||
must of course set up the hostname.
|
||||
|
||||
@@ -15,7 +15,7 @@ A SSH session goes through the following steps:
|
||||
file.
|
||||
|
||||
- The client must authenticate: the classical ways are password, or
|
||||
public keys (from ecdsa, ed25519 and rsa key-pairs generated by openssh).
|
||||
public keys (from dsa and rsa key-pairs generated by openssh).
|
||||
If a SSH agent is running, it is possible to use it.
|
||||
|
||||
- Now that the user has been authenticated, you must open one or several
|
||||
@@ -79,7 +79,7 @@ Here is a small example of how to use it:
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session = NULL;
|
||||
ssh_session my_ssh_session;
|
||||
int verbosity = SSH_LOG_PROTOCOL;
|
||||
int port = 22;
|
||||
|
||||
@@ -126,7 +126,7 @@ Here's an example:
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session = NULL;
|
||||
ssh_session my_ssh_session;
|
||||
int rc;
|
||||
|
||||
my_ssh_session = ssh_new();
|
||||
@@ -190,8 +190,8 @@ int verify_knownhost(ssh_session session)
|
||||
ssh_key srv_pubkey = NULL;
|
||||
size_t hlen;
|
||||
char buf[10];
|
||||
char *hexa = NULL;
|
||||
char *p = NULL;
|
||||
char *hexa;
|
||||
char *p;
|
||||
int cmp;
|
||||
int rc;
|
||||
|
||||
@@ -317,9 +317,9 @@ The example below shows an authentication with password:
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session = NULL;
|
||||
ssh_session my_ssh_session;
|
||||
int rc;
|
||||
char *password = NULL;
|
||||
char *password;
|
||||
|
||||
// Open session and set options
|
||||
my_ssh_session = ssh_new();
|
||||
@@ -380,7 +380,7 @@ The example below shows how to execute a remote command:
|
||||
@code
|
||||
int show_remote_processes(ssh_session session)
|
||||
{
|
||||
ssh_channel channel = NULL;
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
|
||||
@@ -14,8 +14,8 @@ libssh is a Free Software / Open Source project. The libssh library
|
||||
is distributed under LGPL license. The libssh project has nothing to do with
|
||||
"libssh2", which is a completely different and independent project.
|
||||
|
||||
libssh can run on top of either libcrypto, mbedtls or libgcrypt (deprecated)
|
||||
general-purpose cryptographic libraries.
|
||||
libssh can run on top of either libgcrypt or libcrypto,
|
||||
two general-purpose cryptographic libraries.
|
||||
|
||||
This tutorial concentrates for its main part on the "client" side of libssh.
|
||||
To learn how to accept incoming SSH connections (how to write a SSH server),
|
||||
@@ -44,10 +44,6 @@ Table of contents:
|
||||
|
||||
@subpage libssh_tutor_threads
|
||||
|
||||
@subpage libssh_tutor_pkcs11
|
||||
|
||||
@subpage libssh_tutor_sftp_aio
|
||||
|
||||
@subpage libssh_tutor_todo
|
||||
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,7 @@ the interesting functions as you go.
|
||||
The libssh library provides:
|
||||
|
||||
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
|
||||
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256
|
||||
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256,ssh-dss
|
||||
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc
|
||||
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
|
||||
- <strong>MAC hashes</strong>: hmac-sha1, hmac-sha2-256, hmac-sha2-512, hmac-md5
|
||||
@@ -33,7 +33,7 @@ The libssh library provides:
|
||||
- <strong>Thread-safe</strong>: Just don't share sessions
|
||||
- <strong>Non-blocking</strong>: it can be used both blocking and non-blocking
|
||||
- <strong>Your sockets</strong>: the app hands over the socket, or uses libssh sockets
|
||||
- <b>OpenSSL</b>, <b>MBedTLS</b> or <b>gcrypt</b> (deprecated): builds with either
|
||||
- <b>OpenSSL</b> or <b>gcrypt</b>: builds with either
|
||||
|
||||
@section main-additional-features Additional Features
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ objects stored on the tokens can be uniquely identified is called PKCS #11 URI
|
||||
(Uniform Resource Identifier) and is defined in RFC 7512
|
||||
(https://tools.ietf.org/html/rfc7512).
|
||||
|
||||
# Pre-requisites (OpenSSL < 3.0):
|
||||
Pre-requisites:
|
||||
|
||||
OpenSSL 1.x defines an abstract layer called the "engine" to achieve
|
||||
cryptographic acceleration. The engine_pkcs11 module acts like an interface
|
||||
between the PKCS #11 modules and the OpenSSL application.
|
||||
OpenSSL defines an abstract layer called the "engine" to achieve cryptographic
|
||||
acceleration. The engine_pkcs11 module acts like an interface between the PKCS #11
|
||||
modules and the OpenSSL engine.
|
||||
|
||||
To build and use libssh with PKCS #11 support:
|
||||
1. Enable the cmake option: $ cmake -DWITH_PKCS11_URI=ON
|
||||
@@ -21,23 +21,6 @@ To build and use libssh with PKCS #11 support:
|
||||
3. Install and configure engine_pkcs11 (https://github.com/OpenSC/libp11).
|
||||
4. Plug in a working smart card or configure softhsm (https://www.opendnssec.org/softhsm).
|
||||
|
||||
@warning The support for Engines was deprecated in OpenSSL 3.0 so this approach
|
||||
is deprecated in libssh 0.11.x.
|
||||
|
||||
# Pre-requisites (OpenSSL 3.0.8+)
|
||||
|
||||
The OpenSSL 3.0 is deprecating usage of low-level engines in favor of high-level
|
||||
"providers" to provide alternative implementation of cryptographic operations
|
||||
or acceleration.
|
||||
|
||||
To build and use libssh with PKCS #11 support using OpenSSL providers:
|
||||
1. Install and configure pkcs11 provider (https://github.com/latchset/pkcs11-provider).
|
||||
2. Enable the cmake options: $ cmake -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
|
||||
3. Build with OpenSSL.
|
||||
4. Plug in a working smart card or configure softhsm (https://www.opendnssec.org/softhsm).
|
||||
|
||||
# New API functions
|
||||
|
||||
The functions ssh_pki_import_pubkey_file() and ssh_pki_import_privkey_file() that
|
||||
import the public and private keys from files respectively are now modified to support
|
||||
PKCS #11 URIs. These functions automatically detect if the provided filename is a file path
|
||||
@@ -48,7 +31,7 @@ corresponding to the PKCS #11 URI are loaded from the PKCS #11 device.
|
||||
If you wish to authenticate using public keys on your own, follow the steps mentioned under
|
||||
"Authentication with public keys" in Chapter 2 - A deeper insight into authentication.
|
||||
|
||||
The function pki_uri_import() is used to populate the public/private ssh_key from the
|
||||
The function pki_uri_import() is used to populate the public/private ssh_key from the
|
||||
engine with PKCS #11 URIs as the look up.
|
||||
|
||||
Here is a minimalistic example of public key authentication using PKCS #11 URIs:
|
||||
@@ -81,6 +64,4 @@ We recommend the users to provide a specific PKCS #11 URI so that it matches onl
|
||||
If the engine discovers multiple slots that could potentially contain the private keys referenced
|
||||
by the provided PKCS #11 URI, the engine will not try to authenticate.
|
||||
|
||||
For testing, the SoftHSM PKCS#11 library is used.
|
||||
|
||||
*/
|
||||
|
||||
114
doc/sftp.dox
114
doc/sftp.dox
@@ -139,7 +139,7 @@ Unlike its equivalent in the SCP subsystem, this function does NOT change the
|
||||
current directory to the newly created subdirectory.
|
||||
|
||||
|
||||
@subsection sftp_write Writing to a file on the remote computer
|
||||
@subsection sftp_write Copying a file to the remote computer
|
||||
|
||||
You handle the contents of a remote file just like you would do with a
|
||||
local file: you open the file in a given mode, move the file pointer in it,
|
||||
@@ -203,14 +203,16 @@ int sftp_helloworld(ssh_session session, sftp_session sftp)
|
||||
|
||||
@subsection sftp_read Reading a file from the remote computer
|
||||
|
||||
A synchronous read from a remote file is done using sftp_read(). This
|
||||
section describes how to download a remote file using sftp_read(). The
|
||||
next section will discuss more about synchronous/asynchronous read/write
|
||||
operations using libssh sftp API.
|
||||
The nice thing with reading a file over the network through SFTP is that it
|
||||
can be done both in a synchronous way or an asynchronous way. If you read the file
|
||||
asynchronously, your program can do something else while it waits for the
|
||||
results to come.
|
||||
|
||||
Synchronous read is done with sftp_read().
|
||||
|
||||
Files are normally transferred in chunks. A good chunk size is 16 KB. The following
|
||||
example transfers the remote file "/etc/profile" in 16 KB chunks. For each chunk we
|
||||
request, sftp_read() blocks till the data has been received:
|
||||
request, sftp_read blocks till the data has been received:
|
||||
|
||||
@code
|
||||
// Good chunk size
|
||||
@@ -271,39 +273,87 @@ int sftp_read_sync(ssh_session session, sftp_session sftp)
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection sftp_aio Performing an asynchronous read/write on a file on the remote computer
|
||||
Asynchronous read is done in two steps, first sftp_async_read_begin(), which
|
||||
returns a "request handle", and then sftp_async_read(), which uses that request handle.
|
||||
If the file has been opened in nonblocking mode, then sftp_async_read()
|
||||
might return SSH_AGAIN, which means that the request hasn't completed yet
|
||||
and that the function should be called again later on. Otherwise,
|
||||
sftp_async_read() waits for the data to come. To open a file in nonblocking mode,
|
||||
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
|
||||
|
||||
sftp_read() performs a "synchronous" read operation on a remote file.
|
||||
This means that sftp_read() will first request the server to read some
|
||||
data from the remote file and then would wait until the server response
|
||||
containing data to read (or an error) arrives at the client side.
|
||||
The example below reads a very big file in asynchronous, nonblocking, mode. Each
|
||||
time the data is not ready yet, a counter is incremented.
|
||||
|
||||
sftp_write() performs a "synchronous" write operation on a remote file.
|
||||
This means that sftp_write() will first request the server to write some
|
||||
data to the remote file and then would wait until the server response
|
||||
containing information about the status of the write operation arrives at the
|
||||
client side.
|
||||
@code
|
||||
// Good chunk size
|
||||
#define MAX_XFER_BUF_SIZE 16384
|
||||
|
||||
If your client program wants to do something other than waiting for the
|
||||
response after requesting a read/write, the synchronous sftp_read() and
|
||||
sftp_write() can't be used. In such a case the "asynchronous" sftp aio API
|
||||
should be used.
|
||||
int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type;
|
||||
sftp_file file;
|
||||
char buffer[MAX_XFER_BUF_SIZE];
|
||||
int async_request;
|
||||
int nbytes;
|
||||
long counter;
|
||||
int rc;
|
||||
|
||||
Please go through @ref libssh_tutor_sftp_aio for a detailed description
|
||||
of the sftp aio API.
|
||||
access_type = O_RDONLY;
|
||||
file = sftp_open(sftp, "some_very_big_file",
|
||||
access_type, 0);
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
sftp_file_set_nonblocking(file);
|
||||
|
||||
The sftp aio API provides two categories of functions :
|
||||
- sftp_aio_begin_*() : For requesting a read/write from the server.
|
||||
- sftp_aio_wait_*() : For waiting for the response of a previously
|
||||
issued read/write request from the server.
|
||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||
counter = 0L;
|
||||
usleep(10000);
|
||||
if (async_request >= 0) {
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||
async_request);
|
||||
} else {
|
||||
nbytes = -1;
|
||||
}
|
||||
|
||||
Hence, the client program can call sftp_aio_begin_*() to request a read/write
|
||||
and then can perform any number of operations (other than waiting) before
|
||||
calling sftp_aio_wait_*() for waiting for the response of the previously
|
||||
issued request.
|
||||
while (nbytes > 0 || nbytes == SSH_AGAIN) {
|
||||
if (nbytes > 0) {
|
||||
write(1, buffer, nbytes);
|
||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||
} else {
|
||||
counter++;
|
||||
}
|
||||
usleep(10000);
|
||||
|
||||
We call read/write operations performed in the manner described above as
|
||||
"asynchronous" read/write operations on a remote file.
|
||||
if (async_request >= 0) {
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||
async_request);
|
||||
} else {
|
||||
nbytes = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nbytes < 0) {
|
||||
fprintf(stderr, "Error while reading file: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
printf("The counter has reached value: %ld\n", counter);
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Can't close the read file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection sftp_ls Listing the contents of a directory
|
||||
|
||||
|
||||
705
doc/sftp_aio.dox
705
doc/sftp_aio.dox
@@ -1,705 +0,0 @@
|
||||
/**
|
||||
|
||||
@page libssh_tutor_sftp_aio Chapter 10: The SFTP asynchronous I/O
|
||||
|
||||
@section sftp_aio_api The SFTP asynchronous I/O
|
||||
|
||||
NOTE : Please read @ref libssh_tutor_sftp before reading this page. The
|
||||
synchronous sftp_read() and sftp_write() have been described there.
|
||||
|
||||
SFTP AIO stands for "SFTP Asynchronous Input/Output". This API contains
|
||||
functions which perform async read/write operations on remote files.
|
||||
|
||||
File transfers performed using the asynchronous sftp aio API can be
|
||||
significantly faster than the file transfers performed using the synchronous
|
||||
sftp read/write API (see sftp_read() and sftp_write()).
|
||||
|
||||
The sftp aio API functions are divided into two categories :
|
||||
- sftp_aio_begin_*() [see sftp_aio_begin_read(), sftp_aio_begin_write()]:
|
||||
These functions send a request for an i/o operation to the server and
|
||||
provide the caller an sftp aio handle corresponding to the sent request.
|
||||
|
||||
- sftp_aio_wait_*() [see sftp_aio_wait_read(), sftp_aio_wait_write()]:
|
||||
These functions wait for the server response corresponding to a previously
|
||||
issued request. Which request ? the request corresponding to the sftp aio
|
||||
handle supplied by the caller to these functions.
|
||||
|
||||
Conceptually, you can think of the sftp aio handle as a request identifier.
|
||||
|
||||
Technically, the sftp_aio_begin_*() functions dynamically allocate memory to
|
||||
store information about the i/o request they send and provide the caller a
|
||||
handle to this memory, we call this handle an sftp aio handle.
|
||||
|
||||
sftp_aio_wait_*() functions use the information stored in that memory (handled
|
||||
by the caller supplied sftp aio handle) to identify a request, and then they
|
||||
wait for that request's response. These functions also release the memory
|
||||
handled by the caller supplied sftp aio handle (except when they return
|
||||
SSH_AGAIN).
|
||||
|
||||
sftp_aio_free() can also be used to release the memory handled by an sftp aio
|
||||
handle but unlike the sftp_aio_wait_*() functions, it doesn't wait for a
|
||||
response. This should be used to release the memory corresponding to an sftp
|
||||
aio handle when some failure occurs. An example has been provided at the
|
||||
end of this page to show the usage of sftp_aio_free().
|
||||
|
||||
To begin with, this tutorial will provide basic examples that describe the
|
||||
usage of sftp aio API to perform a single read/write operation.
|
||||
|
||||
The later sections describe the usage of the sftp aio API to obtain faster file
|
||||
transfers as compared to the transfers performed using the synchronous sftp
|
||||
read/write API.
|
||||
|
||||
On encountering an error, the sftp aio API functions set the sftp and ssh
|
||||
errors just like any other libssh sftp API function. These errors can be
|
||||
obtained using sftp_get_error(), ssh_get_error() and ssh_get_error_code().
|
||||
The code examples provided on this page ignore error handling for the sake of
|
||||
brevity.
|
||||
|
||||
@subsection sftp_aio_read Using the sftp aio API for reading (a basic example)
|
||||
|
||||
For performing an async read operation on a sftp file (see sftp_open()),
|
||||
the first step is to call sftp_aio_begin_read() to send a read request to the
|
||||
server. The caller is provided an sftp aio handle corresponding to the sent
|
||||
read request.
|
||||
|
||||
The second step is to pass a pointer to this aio handle to
|
||||
sftp_aio_wait_read(), this function waits for the server response which
|
||||
indicates the success/failure of the read request. On success, the response
|
||||
indicates EOF or contains the data read from the sftp file.
|
||||
|
||||
The following code example shows how a read operation can be performed
|
||||
on an sftp file using the sftp aio API.
|
||||
|
||||
@code
|
||||
ssize_t read_chunk(sftp_file file, void *buf, size_t to_read)
|
||||
{
|
||||
ssize_t bytes_requested, bytes_read;
|
||||
|
||||
// Variable to store an sftp aio handle
|
||||
sftp_aio aio = NULL;
|
||||
|
||||
// Send a read request to the sftp server
|
||||
bytes_requested = sftp_aio_begin_read(file, to_read, &aio);
|
||||
if (bytes_requested == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
// Here its possible that (bytes_requested < to_read) as specified in
|
||||
// the function documentation of sftp_aio_begin_read()
|
||||
|
||||
// Wait for the response of the read request corresponding to the
|
||||
// sftp aio handle stored in the aio variable.
|
||||
bytes_read = sftp_aio_wait_read(&aio, buf, to_read);
|
||||
if (bytes_read == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection sftp_aio_write Using the sftp aio API for writing (a basic example)
|
||||
|
||||
For performing an async write operation on a sftp file (see sftp_open()),
|
||||
the first step is to call sftp_aio_begin_write() to send a write request to
|
||||
the server. The caller is provided an sftp aio handle corresponding to the
|
||||
sent write request.
|
||||
|
||||
The second step is to pass a pointer to this aio handle to
|
||||
sftp_aio_wait_write(), this function waits for the server response which
|
||||
indicates the success/failure of the write request.
|
||||
|
||||
The following code example shows how a write operation can be performed on an
|
||||
sftp file using the sftp aio API.
|
||||
|
||||
@code
|
||||
ssize_t write_chunk(sftp_file file, void *buf, size_t to_write)
|
||||
{
|
||||
ssize_t bytes_requested, bytes_written;
|
||||
|
||||
// Variable to store an sftp aio handle
|
||||
sftp_aio aio = NULL;
|
||||
|
||||
// Send a write request to the sftp server
|
||||
bytes_requested = sftp_aio_begin_write(file, buf, to_write, &aio);
|
||||
if (bytes_requested == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
// Here its possible that (bytes_requested < to_write) as specified in
|
||||
// the function documentation of sftp_aio_begin_write()
|
||||
|
||||
// Wait for the response of the write request corresponding to
|
||||
// the sftp aio handle stored in the aio variable.
|
||||
bytes_written = sftp_aio_wait_write(&aio);
|
||||
if (bytes_written == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection sftp_aio_actual_use Using the sftp aio API to speed up a transfer
|
||||
|
||||
The above examples were provided to introduce the sftp aio API.
|
||||
This is not how the sftp aio API is intended to be used, because the
|
||||
above usage offers no advantage over the synchronous sftp read/write API
|
||||
which does the same thing i.e issue a request and then immediately wait for
|
||||
its response.
|
||||
|
||||
The facility that the sftp aio API provides is that the user can do
|
||||
anything between issuing a request and getting the corresponding response.
|
||||
Any number of operations can be performed after calling sftp_aio_begin_*()
|
||||
[which issues a request] and before calling sftp_aio_wait_*() [which waits
|
||||
for a response]
|
||||
|
||||
The code can leverage this feature by calling sftp_aio_begin_*() multiple times
|
||||
to issue multiple requests before calling sftp_aio_wait_*() to wait for the
|
||||
response of an earlier issued request. This approach will keep a certain number
|
||||
of requests outstanding at the client side.
|
||||
|
||||
After issuing those requests, while the client code does something else (for
|
||||
example waiting for an outstanding request's response, processing an obtained
|
||||
response, issuing another request or any other operation the client wants
|
||||
to perform), at the same time :
|
||||
|
||||
- Some of those outstanding requests may be travelling over the
|
||||
network towards the server.
|
||||
|
||||
- Some of the outstanding requests may have reached the server and may
|
||||
be queued for processing at the server side.
|
||||
|
||||
- Some of the outstanding requests may have been processed and the
|
||||
corresponding responses may be travelling over the network towards the
|
||||
client.
|
||||
|
||||
- Some of the responses corresponding to the outstanding requests may
|
||||
have already reached the client side.
|
||||
|
||||
Clearly in this case, operations that the client performs and operations
|
||||
involved in transfer/processing of a outstanding request can occur in
|
||||
parallel. Also, operations involved in transfer/processing of two or more
|
||||
outstanding requests may also occur in parallel (for example when one request
|
||||
travels to the server, another request's response may be incoming towards the
|
||||
client). Such kind of parallelism makes the overall transfer faster as compared
|
||||
to a transfer performed using the synchronous sftp read/write API.
|
||||
|
||||
When the synchronous sftp read/write API is used to perform a transfer,
|
||||
a strict sequence is followed:
|
||||
|
||||
- The client issues a single read/write request.
|
||||
- Then waits for its response.
|
||||
- On obtaining the response, the client processes it.
|
||||
- After the processing ends, the client issues the next read/write request.
|
||||
|
||||
A file transfer performed in this manner would be slower than the case where
|
||||
multiple read/write requests are kept outstanding at the client side. Because
|
||||
here at any given time, operations related to transfer/processing of only one
|
||||
request/response pair occurs. This is in contrast to the multiple outstanding
|
||||
requests scenario where operations related to transfer/processing of multiple
|
||||
request/response pairs may occur at the same time.
|
||||
|
||||
Although it's true that keeping multiple requests outstanding can speed up a
|
||||
transfer, those outstanding requests come at a cost of increased memory
|
||||
consumption both at the client side and the server side. Hence care must be
|
||||
taken to use a reasonable limit for the number of requests kept outstanding.
|
||||
|
||||
The further sections provide code examples to show how uploads/downloads
|
||||
can be performed using the sftp aio API and the concept of outstanding requests
|
||||
discussed in this section. In those code examples, error handling has been
|
||||
ignored and at some places pseudo code has been used for the sake of brevity.
|
||||
|
||||
The complete code for performing uploads/downloads using the sftp aio API,
|
||||
can be found at https://gitlab.com/libssh/libssh-mirror/-/tree/master.
|
||||
|
||||
- libssh benchmarks for uploads performed using the sftp aio API [See
|
||||
tests/benchmarks/bench_sftp.c]
|
||||
- libssh benchmarks for downloads performed using the sftp aio API. [See
|
||||
tests/benchmarks/bench_sftp.c]
|
||||
- libssh sftp ft API code for performing a local to remote transfer (upload).
|
||||
[See src/sftp_ft.c]
|
||||
- libssh sftp ft API code for performing a remote to local transfer
|
||||
(download). [See src/sftp_ft.c]
|
||||
|
||||
@subsection sftp_aio_cap Capping applied by the sftp aio API
|
||||
|
||||
Before the code examples for uploads and downloads, its important
|
||||
to know about the capping applied by the sftp aio API.
|
||||
|
||||
sftp_aio_begin_read() caps the number of bytes the caller can request
|
||||
to read from the remote file. That cap is the value of the max_read_length
|
||||
field of the sftp_limits_t returned by sftp_limits(). Say that cap is LIM
|
||||
and the caller passes x as the number of bytes to read to
|
||||
sftp_aio_begin_read(), then (assuming no error occurs) :
|
||||
|
||||
- if x <= LIM, then sftp_aio_begin_read() will request the server
|
||||
to read x bytes from the remote file, and will return x.
|
||||
|
||||
- if x > LIM, then sftp_aio_begin_read() will request the server
|
||||
to read LIM bytes from the remote file and will return LIM.
|
||||
|
||||
Hence to request server to read x bytes (> LIM), the caller would have
|
||||
to call sftp_aio_begin_read() multiple times, typically in a loop and
|
||||
break out of the loop when the summation of return values of the multiple
|
||||
sftp_aio_begin_read() calls becomes equal to x.
|
||||
|
||||
For the sake of simplicity, the code example for download in the upcoming
|
||||
section would always ask sftp_aio_begin_read() to read x <= LIM bytes,
|
||||
so that its return value is guaranteed to be x, unless an error occurs.
|
||||
|
||||
Similarly, sftp_aio_begin_write() caps the number of bytes the caller
|
||||
can request to write to the remote file. That cap is the value of
|
||||
max_write_length field of the sftp_limits_t returned by sftp_limits().
|
||||
Say that cap is LIM and the caller passes x as the number of bytes to
|
||||
write to sftp_aio_begin_write(), then (assuming no error occurs) :
|
||||
|
||||
- if x <= LIM, then sftp_aio_begin_write() will request the server
|
||||
to write x bytes to the remote file, and will return x.
|
||||
|
||||
- if x > LIM, then sftp_aio_begin_write() will request the server
|
||||
to write LIM bytes to the remote file and will return LIM.
|
||||
|
||||
Hence to request server to write x bytes (> LIM), the caller would have
|
||||
to call sftp_aio_begin_write() multiple times, typically in a loop and
|
||||
break out of the loop when the summation of return values of the multiple
|
||||
sftp_aio_begin_write() calls becomes equal to x.
|
||||
|
||||
For the sake of simplicity, the code example for upload in the upcoming
|
||||
section would always ask sftp_aio_begin_write() to write x <= LIM bytes,
|
||||
so that its return value is guaranteed to be x, unless an error occurs.
|
||||
|
||||
@subsection sftp_aio_download_example Performing a download using the sftp aio API
|
||||
|
||||
Terminologies used in the following code snippets :
|
||||
|
||||
- sftp : The sftp_session opened using sftp_new() and initialised using
|
||||
sftp_init()
|
||||
|
||||
- file : The sftp file handle of the remote file to download data
|
||||
from. (See sftp_open())
|
||||
|
||||
- file_size : the size of the sftp file to download. This size can be obtained
|
||||
by statting the remote file to download (e.g by using sftp_stat())
|
||||
|
||||
- We will need to maintain a queue which will be used to store the sftp aio
|
||||
handles corresponding to the outstanding requests.
|
||||
|
||||
First, we issue the read requests while ensuring that their count
|
||||
doesn't exceed a particular limit decided by us, and the number of bytes
|
||||
requested don't exceed the size of the file to download.
|
||||
|
||||
@code
|
||||
sftp_aio aio = NULL;
|
||||
|
||||
// Chunk size to use for the transfer
|
||||
size_t chunk_size;
|
||||
|
||||
// For the limits structure that would be used
|
||||
// by the code to set the chunk size
|
||||
sftp_limits_t lim = NULL;
|
||||
|
||||
// Max number of requests to keep outstanding at a time
|
||||
size_t in_flight_requests = 5;
|
||||
|
||||
// Number of bytes for which requests have been sent
|
||||
size_t total_bytes_requested = 0;
|
||||
|
||||
// Number of bytes which have been downloaded
|
||||
size_t bytes_downloaded = 0;
|
||||
|
||||
// Buffer to use for the download
|
||||
char *buffer = NULL;
|
||||
|
||||
// Helper variables
|
||||
size_t to_read;
|
||||
ssize_t bytes_requested;
|
||||
|
||||
// Get the sftp limits
|
||||
lim = sftp_limits(sftp);
|
||||
if (lim == NULL) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
// Set the chunk size for download = the max limit for reading
|
||||
// The reason for this has been given in the "Capping applied by
|
||||
// the sftp aio API" section (Its to make the code simpler)
|
||||
//
|
||||
// Assigning a size_t type variable a uint64_t type value here,
|
||||
// theoretically could cause an overflow, but practically
|
||||
// max_read_length would never exceed SIZE_MAX so its okay.
|
||||
chunk_size = lim->max_read_length;
|
||||
|
||||
buffer = malloc(chunk_size);
|
||||
if (buffer == NULL) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
... // Code to open the remote file (to download) using sftp_open().
|
||||
... // Code to stat the remote file's file size.
|
||||
... // Code to open the local file in which downloaded data is to be stored.
|
||||
... // Code to initialize the queue which will be used to store sftp aio
|
||||
// handles.
|
||||
|
||||
for (i = 0;
|
||||
i < in_flight_requests && total_bytes_requested < file_size;
|
||||
++i) {
|
||||
to_read = file_size - total_bytes_requested;
|
||||
if (to_read > chunk_size) {
|
||||
to_read = chunk_size;
|
||||
}
|
||||
|
||||
// Issue a read request
|
||||
bytes_requested = sftp_aio_begin_read(file, to_read, &aio);
|
||||
if (bytes_requested == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
if ((size_t)bytes_requested < to_read) {
|
||||
// Should not happen for this code, as the to_read is <=
|
||||
// max limit for reading (chunk size), so there is no reason
|
||||
// for sftp_aio_begin_read() to return a lesser value.
|
||||
}
|
||||
|
||||
total_bytes_requested += (size_t)bytes_requested;
|
||||
|
||||
// Pseudo code
|
||||
ENQUEUE aio in the queue;
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
At this point, at max in_flight_requests number of requests may be
|
||||
outstanding. Now we wait for the response corresponding to the earliest
|
||||
issued outstanding request.
|
||||
|
||||
On getting that response, we issue another read request if there are
|
||||
still some bytes in the sftp file (to download) for which we haven't sent the
|
||||
read request. (This happens when total_bytes_requested < file_size)
|
||||
|
||||
This issuing of another read request (under a condition) is done to
|
||||
keep the number of outstanding requests equal to the value of the
|
||||
in_flight_requests variable.
|
||||
|
||||
This process has to be repeated for every remaining outstanding request.
|
||||
|
||||
@code
|
||||
while (the queue is not empty) {
|
||||
// Pseudo code
|
||||
aio = DEQUEUE an sftp aio handle from the queue of sftp aio handles;
|
||||
|
||||
// Wait for the response of the request corresponding to the aio
|
||||
bytes_read = sftp_aio_wait_read(&aio, buffer, chunk_size);
|
||||
if (bytes_read == SSH_ERROR) {
|
||||
//handle error
|
||||
}
|
||||
|
||||
bytes_downloaded += bytes_read;
|
||||
if (bytes_read != chunk_size && bytes_downloaded != file_size) {
|
||||
// A short read encountered on the remote file before reaching EOF,
|
||||
// short read before reaching EOF should never happen for the sftp aio
|
||||
// API which respects the max limit for reading. This probably
|
||||
// indicates a bad server.
|
||||
}
|
||||
|
||||
// Pseudo code
|
||||
WRITE bytes_read bytes from the buffer into the local file
|
||||
in which downloaded data is to be stored ;
|
||||
|
||||
if (total_bytes_requested == file_size) {
|
||||
// no need to issue more read requests
|
||||
continue;
|
||||
}
|
||||
|
||||
// else issue a read request
|
||||
to_read = file_size - total_bytes_requested;
|
||||
if (to_read > chunk_size) {
|
||||
to_read = chunk_size;
|
||||
}
|
||||
|
||||
bytes_requested = sftp_aio_begin_read(file, to_read, &aio);
|
||||
if (bytes_requested == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
if ((size_t)bytes_requested < to_read) {
|
||||
// Should not happen for this code, as the to_read is <=
|
||||
// max limit for reading (chunk size), so there is no reason
|
||||
// for sftp_aio_begin_read() to return a lesser value.
|
||||
}
|
||||
|
||||
total_bytes_requested += bytes_requested;
|
||||
|
||||
// Pseudo code
|
||||
ENQUEUE aio in the queue;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
sftp_limits_free(lim);
|
||||
|
||||
... // Code to destroy the queue which was used to store the sftp aio
|
||||
// handles.
|
||||
@endcode
|
||||
|
||||
After exiting the while (the queue is not empty) loop, the download
|
||||
would've been complete (assuming no error occurs).
|
||||
|
||||
@subsection sftp_aio_upload_example Performing an upload using the sftp aio API
|
||||
|
||||
Terminologies used in the following code snippets :
|
||||
|
||||
- sftp : The sftp_session opened using sftp_new() and initialised using
|
||||
sftp_init()
|
||||
|
||||
- file : The sftp file handle of the remote file in which uploaded data
|
||||
is to be stored. (See sftp_open())
|
||||
|
||||
- file_size : The size of the local file to upload. This size can be
|
||||
obtained by statting the local file to upload (e.g by using stat())
|
||||
|
||||
- We will need maintain a queue which will be used to store the sftp aio
|
||||
handles corresponding to the outstanding requests.
|
||||
|
||||
First, we issue the write requests while ensuring that their count
|
||||
doesn't exceed a particular limit decided by us, and the number of bytes
|
||||
requested to write don't exceed the size of the file to upload.
|
||||
|
||||
@code
|
||||
sftp_aio aio = NULL;
|
||||
|
||||
// The chunk size to use for the transfer
|
||||
size_t chunk_size;
|
||||
|
||||
// For the limits structure that would be used by
|
||||
// the code to set the chunk size
|
||||
sftp_limits_t lim = NULL;
|
||||
|
||||
// Max number of requests to keep outstanding at a time
|
||||
size_t in_flight_requests = 5;
|
||||
|
||||
// Total number of bytes for which write requests have been sent
|
||||
size_t total_bytes_requested = 0;
|
||||
|
||||
// Buffer to use for the upload
|
||||
char *buffer = NULL;
|
||||
|
||||
// Helper variables
|
||||
size_t to_write;
|
||||
ssize_t bytes_requested;
|
||||
|
||||
// Get the sftp limits
|
||||
lim = sftp_limits(sftp);
|
||||
if (lim == NULL) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
// Set the chunk size for upload = the max limit for writing.
|
||||
// The reason for this has been given in the "Capping applied by
|
||||
// the sftp aio API" section (Its to make the code simpler)
|
||||
//
|
||||
// Assigning a size_t type variable a uint64_t type value here,
|
||||
// theoretically could cause an overflow, but practically
|
||||
// max_write_length would never exceed SIZE_MAX so its okay.
|
||||
chunk_size = lim->max_write_length;
|
||||
|
||||
buffer = malloc(chunk_size);
|
||||
if (buffer == NULL) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
... // Code to open the local file (to upload) [e.g using open(), fopen()].
|
||||
... // Code to stat the local file's file size [e.g using stat()].
|
||||
... // Code to open the remote file in which uploaded data will be stored [see
|
||||
// sftp_open()].
|
||||
... // Code to initialize the queue which will be used to store sftp aio
|
||||
// handles.
|
||||
|
||||
for (i = 0;
|
||||
i < in_flight_requests && total_bytes_requested < file_size;
|
||||
++i) {
|
||||
to_write = file_size - total_bytes_requested;
|
||||
if (to_write > chunk_size) {
|
||||
to_write = chunk_size;
|
||||
}
|
||||
|
||||
// Pseudo code
|
||||
READ to_write bytes from the local file (to upload) into the buffer;
|
||||
|
||||
bytes_requested = sftp_aio_begin_write(file, buffer, to_write, &aio);
|
||||
if (bytes_requested == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
if ((size_t)bytes_requested < to_write) {
|
||||
// Should not happen for this code, as the to_write is <=
|
||||
// max limit for writing (chunk size), so there is no reason
|
||||
// for sftp_aio_begin_write() to return a lesser value.
|
||||
}
|
||||
|
||||
total_bytes_requested += (size_t)bytes_requested;
|
||||
|
||||
// Pseudo code
|
||||
ENQUEUE aio in the queue;
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
At this point, at max in_flight_requests number of requests may be
|
||||
outstanding. Now we wait for the response corresponding to the earliest
|
||||
issued outstanding request.
|
||||
|
||||
On getting that response, we issue another write request if there are
|
||||
still some bytes in the local file (to upload) for which we haven't sent
|
||||
the write request. (This happens when total_bytes_requested < file_size)
|
||||
|
||||
This issuing of another write request (under a condition) is done to
|
||||
keep the number of outstanding requests equal to the value of the
|
||||
in_flight_requests variable.
|
||||
|
||||
This process has to be repeated for every remaining outstanding request.
|
||||
|
||||
@code
|
||||
while (the queue is not empty) {
|
||||
// Pseudo code
|
||||
aio = DEQUEUE an sftp aio handle from the queue of sftp aio handles;
|
||||
|
||||
// Wait for the response of the request corresponding to the aio
|
||||
bytes_written = sftp_aio_wait_write(&aio);
|
||||
if (bytes_written == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
// sftp_aio_wait_write() won't report a short write, so no need
|
||||
// to check for a short write here.
|
||||
|
||||
if (total_bytes_requested == file_size) {
|
||||
// no need to issue more write requests
|
||||
continue;
|
||||
}
|
||||
|
||||
// else issue a write request
|
||||
to_write = file_size - total_bytes_requested;
|
||||
if (to_write > chunk_size) {
|
||||
to_write = chunk_size;
|
||||
}
|
||||
|
||||
// Pseudo code
|
||||
READ to_write bytes from the local file (to upload) into a buffer;
|
||||
|
||||
bytes_requested = sftp_aio_begin_write(file, buffer, to_write, &aio);
|
||||
if (bytes_requested == SSH_ERROR) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
if ((size_t)bytes_requested < to_write) {
|
||||
// Should not happen for this code, as the to_write is <=
|
||||
// max limit for writing (chunk size), so there is no reason
|
||||
// for sftp_aio_begin_write() to return a lesser value.
|
||||
}
|
||||
|
||||
total_bytes_requested += (size_t)bytes_requested;
|
||||
|
||||
// Pseudo code
|
||||
ENQUEUE aio in the queue;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
... // Code to destroy the queue which was used to store the sftp aio
|
||||
// handles.
|
||||
@endcode
|
||||
|
||||
After exiting the while (the queue is not empty) loop, the upload
|
||||
would've been complete (assuming no error occurs).
|
||||
|
||||
@subsection sftp_aio_free Example showing the usage of sftp_aio_free()
|
||||
|
||||
The purpose of sftp_aio_free() was discussed at the beginning of this page,
|
||||
the following code example shows how it can be used during cleanup.
|
||||
|
||||
@code
|
||||
void print_sftp_error(sftp_session sftp)
|
||||
{
|
||||
if (sftp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "sftp error : %d\n", sftp_get_error(sftp));
|
||||
fprintf(stderr, "ssh error : %s\n", ssh_get_error(sftp->session));
|
||||
}
|
||||
|
||||
// Returns 0 on success, -1 on error
|
||||
int write_strings(sftp_file file)
|
||||
{
|
||||
const char * strings[] = {
|
||||
"This is the first string",
|
||||
"This is the second string",
|
||||
"This is the third string",
|
||||
"This is the fourth string"
|
||||
};
|
||||
|
||||
size_t string_count = sizeof(strings) / sizeof(strings[0]);
|
||||
size_t i;
|
||||
|
||||
sftp_session sftp = NULL;
|
||||
sftp_aio aio = NULL;
|
||||
|
||||
int rc;
|
||||
|
||||
if (file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
... // Code to initialize the queue which will be used to store sftp aio
|
||||
// handles
|
||||
|
||||
sftp = file->sftp;
|
||||
for (i = 0; i < string_count; ++i) {
|
||||
rc = sftp_aio_begin_write(file,
|
||||
strings[i],
|
||||
strlen(strings[i]),
|
||||
&aio);
|
||||
if (rc == SSH_ERROR) {
|
||||
print_sftp_error(sftp);
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Pseudo code
|
||||
ENQUEUE aio in the queue of sftp aio handles
|
||||
}
|
||||
|
||||
for (i = 0; i < string_count; ++i) {
|
||||
// Pseudo code
|
||||
aio = DEQUEUE an sftp aio handle from the queue of sftp aio handles;
|
||||
|
||||
rc = sftp_aio_wait_write(&aio);
|
||||
if (rc == SSH_ERROR) {
|
||||
print_sftp_error(sftp);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
... // Code to destroy the queue in which sftp aio handles were
|
||||
// stored
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
||||
while (queue is not empty) {
|
||||
// Pseudo code
|
||||
aio = DEQUEUE an sftp aio handle from the queue of sftp aio handles;
|
||||
|
||||
sftp_aio_free(aio);
|
||||
}
|
||||
|
||||
... // Code to destroy the queue in which sftp aio handles were
|
||||
// stored.
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
*/
|
||||
@@ -26,7 +26,7 @@ The code sample below achieves these tasks:
|
||||
@code
|
||||
int shell_session(ssh_session session)
|
||||
{
|
||||
ssh_channel channel = NULL;
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
@@ -65,17 +65,8 @@ to as a "pty", for "pseudo-teletype". The remote processes won't see the
|
||||
difference with a real text-oriented terminal.
|
||||
|
||||
If needed, you request the pty with the function ssh_channel_request_pty().
|
||||
If you want define its dimensions (number of rows and columns),
|
||||
call ssh_channel_request_pty_size() instead. It's also possible to change
|
||||
the dimensions after creating the pty with ssh_channel_change_pty_size().
|
||||
|
||||
These two functions configure the pty using the same terminal modes that
|
||||
stdin has. If stdin isn't a TTY, they use default modes that configure
|
||||
the pty with in canonical mode and e.g. preserving CR and LF characters.
|
||||
If you want to change the terminal modes used by the pty (e.g. to change
|
||||
CRLF handling), use ssh_channel_request_pty_size_modes(). This function
|
||||
accepts an additional "modes" buffer that is expected to contain encoded
|
||||
terminal modes according to RFC 4254 section 8.
|
||||
Then you define its dimensions (number of rows and columns)
|
||||
with ssh_channel_change_pty_size().
|
||||
|
||||
Be your session interactive or not, the next step is to request a
|
||||
shell with ssh_channel_request_shell().
|
||||
|
||||
@@ -29,12 +29,6 @@ if (UNIX AND NOT WIN32)
|
||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||
target_compile_options(samplesftp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(samplesftp ssh::ssh)
|
||||
|
||||
if (WITH_SERVER)
|
||||
add_executable(sample_sftpserver sample_sftpserver.c ${examples_SRCS})
|
||||
target_compile_options(sample_sftpserver PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(sample_sftpserver ssh::ssh ${ARGP_LIBRARIES})
|
||||
endif (WITH_SERVER)
|
||||
endif (WITH_SFTP)
|
||||
|
||||
add_executable(ssh-client ssh_client.c ${examples_SRCS})
|
||||
|
||||
@@ -30,8 +30,8 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
||||
|
||||
err = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
while (err == SSH_AUTH_INFO) {
|
||||
const char *instruction = NULL;
|
||||
const char *name = NULL;
|
||||
const char *instruction;
|
||||
const char *name;
|
||||
char buffer[128];
|
||||
int i, n;
|
||||
|
||||
@@ -48,8 +48,8 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
const char *answer = NULL;
|
||||
const char *prompt = NULL;
|
||||
const char *answer;
|
||||
const char *prompt;
|
||||
char echo;
|
||||
|
||||
prompt = ssh_userauth_kbdint_getprompt(session, i, &echo);
|
||||
@@ -58,7 +58,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
||||
}
|
||||
|
||||
if (echo) {
|
||||
char *p = NULL;
|
||||
char *p;
|
||||
|
||||
printf("%s", prompt);
|
||||
|
||||
@@ -143,7 +143,7 @@ int authenticate_console(ssh_session session)
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *banner = NULL;
|
||||
char *banner;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
|
||||
@@ -22,7 +22,7 @@ clients must be made or how a client should react.
|
||||
#include <stdio.h>
|
||||
|
||||
ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
ssh_session session = NULL;
|
||||
ssh_session session;
|
||||
int auth=0;
|
||||
|
||||
session=ssh_new();
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include "examples_common.h"
|
||||
|
||||
int main(void) {
|
||||
ssh_session session = NULL;
|
||||
ssh_channel channel = NULL;
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int rbytes, wbytes, total = 0;
|
||||
int rc;
|
||||
|
||||
@@ -27,14 +27,14 @@ int main(void)
|
||||
rv = ssh_pki_generate(SSH_KEYTYPE_ED25519, 0, &key);
|
||||
if (rv != SSH_OK) {
|
||||
fprintf(stderr, "Failed to generate private key");
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write it to a file testkey in the current directory */
|
||||
/* Write it to a file testkey in the current dirrectory */
|
||||
rv = ssh_pki_export_privkey_file(key, NULL, NULL, NULL, "testkey");
|
||||
if (rv != SSH_OK) {
|
||||
fprintf(stderr, "Failed to write private key file");
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -38,7 +38,6 @@ struct arguments_st {
|
||||
unsigned long bits;
|
||||
char *file;
|
||||
char *passphrase;
|
||||
char *format;
|
||||
int action_list;
|
||||
};
|
||||
|
||||
@@ -53,6 +52,7 @@ static struct argp_option options[] = {
|
||||
"Accepted values are: "
|
||||
"1024, 2048, 3072 (default), 4096, and 8192 for TYPE=\"rsa\"; "
|
||||
"256 (default), 384, and 521 for TYPE=\"ecdsa\"; "
|
||||
"1024 (default) and 2048 for TYPE=\"dsa\"; "
|
||||
"can be omitted for TYPE=\"ed25519\" "
|
||||
"(it will be ignored if provided).\n",
|
||||
.group = 0
|
||||
@@ -86,7 +86,7 @@ static struct argp_option options[] = {
|
||||
.flags = 0,
|
||||
.doc = "The type of the key to be generated. "
|
||||
"Accepted values are: "
|
||||
"\"rsa\", \"ecdsa\", and \"ed25519\".\n",
|
||||
"\"rsa\", \"ecdsa\", \"ed25519\", and \"dsa\".\n",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
@@ -97,16 +97,6 @@ static struct argp_option options[] = {
|
||||
.doc = "List the Fingerprint of the given key\n",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "format",
|
||||
.key = 'm',
|
||||
.arg = "FORMAT",
|
||||
.flags = 0,
|
||||
.doc = "Write the file in specific format. The supported values are "
|
||||
"'PEM'and 'OpenSSH' file format. By default Ed25519 "
|
||||
"keys are exported in OpenSSH format and others in PEM.\n",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
/* End of the options */
|
||||
0
|
||||
@@ -163,6 +153,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
|
||||
if (!strcmp(arg, "rsa")) {
|
||||
arguments->type = SSH_KEYTYPE_RSA;
|
||||
}
|
||||
else if (!strcmp(arg, "dsa")) {
|
||||
arguments->type = SSH_KEYTYPE_DSS;
|
||||
}
|
||||
else if (!strcmp(arg, "ecdsa")) {
|
||||
arguments->type = SSH_KEYTYPE_ECDSA;
|
||||
}
|
||||
@@ -179,9 +172,6 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
|
||||
case 'l':
|
||||
arguments->action_list = 1;
|
||||
break;
|
||||
case 'm':
|
||||
arguments->format = strdup(arg);
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num > 0) {
|
||||
/* Too many arguments. */
|
||||
@@ -263,6 +253,29 @@ static int validate_args(struct arguments_st *args)
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS:
|
||||
switch (args->bits) {
|
||||
case 0:
|
||||
/* If not provided, use default value */
|
||||
args->bits = 1024;
|
||||
break;
|
||||
case 1024:
|
||||
case 2048:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Invalid bits parameter provided\n");
|
||||
rc = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (args->file == NULL) {
|
||||
args->file = strdup("id_dsa");
|
||||
if (args->file == NULL) {
|
||||
rc = ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
/* Ignore value and overwrite with a zero */
|
||||
@@ -310,7 +323,6 @@ list_fingerprint(char *file)
|
||||
rc = ssh_get_publickey_hash(key, SSH_PUBLICKEY_HASH_SHA256, &hash, &hlen);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Failed to get key fingerprint\n");
|
||||
ssh_key_free(key);
|
||||
return;
|
||||
}
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
@@ -397,36 +409,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Write the private key */
|
||||
if (arguments.format != NULL) {
|
||||
if (strcasecmp(arguments.format, "PEM") == 0) {
|
||||
rc = ssh_pki_export_privkey_file_format(key,
|
||||
arguments.passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
arguments.file,
|
||||
SSH_FILE_FORMAT_PEM);
|
||||
} else if (strcasecmp(arguments.format, "OpenSSH") == 0) {
|
||||
rc = ssh_pki_export_privkey_file_format(key,
|
||||
arguments.passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
arguments.file,
|
||||
SSH_FILE_FORMAT_OPENSSH);
|
||||
} else {
|
||||
rc = ssh_pki_export_privkey_file_format(key,
|
||||
arguments.passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
arguments.file,
|
||||
SSH_FILE_FORMAT_DEFAULT);
|
||||
}
|
||||
} else {
|
||||
rc = ssh_pki_export_privkey_file(key,
|
||||
arguments.passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
arguments.file);
|
||||
}
|
||||
rc = ssh_pki_export_privkey_file(key, arguments.passphrase, NULL, NULL,
|
||||
arguments.file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Error: Failed to write private key file");
|
||||
goto end;
|
||||
|
||||
@@ -38,7 +38,7 @@ int verify_knownhost(ssh_session session)
|
||||
char buf[10];
|
||||
unsigned char *hash = NULL;
|
||||
size_t hlen;
|
||||
ssh_key srv_pubkey = NULL;
|
||||
ssh_key srv_pubkey;
|
||||
int rc;
|
||||
|
||||
rc = ssh_get_server_publickey(session, &srv_pubkey);
|
||||
|
||||
@@ -26,9 +26,9 @@ program.
|
||||
#define BUF_SIZE 16384
|
||||
#endif
|
||||
|
||||
static char **sources = NULL;
|
||||
static char **sources;
|
||||
static int nsources;
|
||||
static char *destination = NULL;
|
||||
static char *destination;
|
||||
static int verbosity = 0;
|
||||
|
||||
struct location {
|
||||
@@ -114,10 +114,9 @@ static void location_free(struct location *loc)
|
||||
}
|
||||
}
|
||||
|
||||
static struct location *parse_location(char *loc)
|
||||
{
|
||||
struct location *location = NULL;
|
||||
char *ptr = NULL;
|
||||
static struct location *parse_location(char *loc) {
|
||||
struct location *location;
|
||||
char *ptr;
|
||||
|
||||
location = malloc(sizeof(struct location));
|
||||
if (location == NULL) {
|
||||
@@ -230,11 +229,11 @@ static int open_location(struct location *loc, int flag) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else if (loc->path != NULL) {
|
||||
} else {
|
||||
loc->file = fopen(loc->path, flag == READ ? "r":"w");
|
||||
if (!loc->file) {
|
||||
if (errno == EISDIR) {
|
||||
if (chdir(loc->path)) {
|
||||
if (loc->path != NULL && chdir(loc->path)) {
|
||||
fprintf(stderr,
|
||||
"Error changing directory to %s: %s\n",
|
||||
loc->path, strerror(errno));
|
||||
|
||||
@@ -35,8 +35,8 @@ clients must be made or how a client should react.
|
||||
static int authenticated=0;
|
||||
static int tries = 0;
|
||||
static int error = 0;
|
||||
static ssh_channel chan = NULL;
|
||||
static char *username = NULL;
|
||||
static ssh_channel chan=NULL;
|
||||
static char *username;
|
||||
static ssh_gssapi_creds client_creds = NULL;
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
@@ -142,12 +142,20 @@ static struct argp_option options[] = {
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa host key (deprecated alias to 'k').",
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
@@ -172,11 +180,15 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'r':
|
||||
/* deprecated */
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
@@ -204,12 +216,11 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_event mainloop = NULL;
|
||||
ssh_session client_session = NULL;
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_event mainloop;
|
||||
ssh_session client_session;
|
||||
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
@@ -220,13 +231,13 @@ int main(int argc, char **argv)
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
char host[128]="";
|
||||
char *ptr = NULL;
|
||||
char *ptr;
|
||||
int i,r, rc;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, "sshd_rsa");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, "sshd_rsa");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
@@ -337,3 +348,4 @@ int main(int argc, char **argv)
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,515 +0,0 @@
|
||||
/* This is a sample implementation of a libssh based SSH server */
|
||||
/*
|
||||
Copyright 2014 Audrius Butkevicius
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/sftp.h>
|
||||
#include <libssh/sftpserver.h>
|
||||
|
||||
#include <poll.h>
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_LIBUTIL_H
|
||||
#include <libutil.h>
|
||||
#endif
|
||||
#ifdef HAVE_PTY_H
|
||||
#include <pty.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UTMP_H
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTIL_H
|
||||
#include <util.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* below are for sftp */
|
||||
#include <sys/statvfs.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define USER "myuser"
|
||||
#define PASS "mypassword"
|
||||
#define BUF_SIZE 1048576
|
||||
#define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR)
|
||||
|
||||
static void set_default_keys(ssh_bind sshbind,
|
||||
int rsa_already_set,
|
||||
int ecdsa_already_set)
|
||||
{
|
||||
if (!rsa_already_set)
|
||||
{
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
|
||||
KEYS_FOLDER "ssh_host_rsa_key");
|
||||
}
|
||||
if (!ecdsa_already_set)
|
||||
{
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
|
||||
KEYS_FOLDER "ssh_host_ecdsa_key");
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
|
||||
KEYS_FOLDER "ssh_host_ed25519_key");
|
||||
}
|
||||
#define DEF_STR_SIZE 1024
|
||||
char authorizedkeys[DEF_STR_SIZE] = {0};
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh sftp server example " SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "Sftp server implemented with libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0},
|
||||
{.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set a host key. Can be used multiple times. "
|
||||
"Implies no default keys.",
|
||||
.group = 0},
|
||||
{.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0},
|
||||
{.name = "ecdsakey",
|
||||
.key = 'e',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the ecdsa key.",
|
||||
.group = 0},
|
||||
{.name = "authorizedkeys",
|
||||
.key = 'a',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the authorized keys file.",
|
||||
.group = 0},
|
||||
{.name = "no-default-keys",
|
||||
.key = 'n',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Do not set default key locations.",
|
||||
.group = 0},
|
||||
{.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0},
|
||||
{NULL, 0, NULL, 0, NULL, 0}};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure. */
|
||||
ssh_bind sshbind = state->input;
|
||||
static int no_default_keys = 0;
|
||||
static int rsa_already_set = 0, ecdsa_already_set = 0;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 'n':
|
||||
no_default_keys = 1;
|
||||
break;
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
/* We can't track the types of keys being added with this
|
||||
option, so let's ensure we keep the keys we're adding
|
||||
by just not setting the default keys */
|
||||
no_default_keys = 1;
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
rsa_already_set = 1;
|
||||
break;
|
||||
case 'e':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
ecdsa_already_set = 1;
|
||||
break;
|
||||
case 'a':
|
||||
strncpy(authorizedkeys, arg, DEF_STR_SIZE - 1);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
|
||||
"3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1)
|
||||
{
|
||||
/* Too many arguments. */
|
||||
argp_usage(state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1)
|
||||
{
|
||||
/* Not enough arguments. */
|
||||
argp_usage(state);
|
||||
}
|
||||
|
||||
if (!no_default_keys)
|
||||
{
|
||||
set_default_keys(sshbind,
|
||||
rsa_already_set,
|
||||
ecdsa_already_set);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
/* A userdata struct for channel. */
|
||||
struct channel_data_struct
|
||||
{
|
||||
/* Event which is used to poll the above descriptors. */
|
||||
ssh_event event;
|
||||
sftp_session sftp;
|
||||
};
|
||||
|
||||
/* A userdata struct for session. */
|
||||
struct session_data_struct
|
||||
{
|
||||
/* Pointer to the channel the session will allocate. */
|
||||
ssh_channel channel;
|
||||
int auth_attempts;
|
||||
int authenticated;
|
||||
};
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *pass, void *userdata)
|
||||
{
|
||||
struct session_data_struct *sdata = (struct session_data_struct *)userdata;
|
||||
|
||||
(void)session;
|
||||
|
||||
if (strcmp(user, USER) == 0 && strcmp(pass, PASS) == 0)
|
||||
{
|
||||
sdata->authenticated = 1;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
sdata->auth_attempts++;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int auth_publickey(ssh_session session,
|
||||
const char *user,
|
||||
struct ssh_key_struct *pubkey,
|
||||
char signature_state,
|
||||
void *userdata)
|
||||
{
|
||||
struct session_data_struct *sdata = (struct session_data_struct *)userdata;
|
||||
|
||||
(void)session;
|
||||
(void)user;
|
||||
|
||||
if (signature_state == SSH_PUBLICKEY_STATE_NONE)
|
||||
{
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
if (signature_state != SSH_PUBLICKEY_STATE_VALID)
|
||||
{
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
// valid so far. Now look through authorized keys for a match
|
||||
if (authorizedkeys[0])
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
int result;
|
||||
struct stat buf;
|
||||
|
||||
if (stat(authorizedkeys, &buf) == 0)
|
||||
{
|
||||
result = ssh_pki_import_pubkey_file(authorizedkeys, &key);
|
||||
if ((result != SSH_OK) || (key == NULL))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Unable to import public key file %s\n",
|
||||
authorizedkeys);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ssh_key_cmp(key, pubkey, SSH_KEY_CMP_PUBLIC);
|
||||
ssh_key_free(key);
|
||||
if (result == 0)
|
||||
{
|
||||
sdata->authenticated = 1;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no matches
|
||||
sdata->authenticated = 0;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static ssh_channel channel_open(ssh_session session, void *userdata)
|
||||
{
|
||||
struct session_data_struct *sdata = (struct session_data_struct *)userdata;
|
||||
|
||||
sdata->channel = ssh_channel_new(session);
|
||||
return sdata->channel;
|
||||
}
|
||||
|
||||
static void handle_session(ssh_event event, ssh_session session)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* Our struct holding information about the channel. */
|
||||
struct channel_data_struct cdata = {
|
||||
.sftp = NULL,
|
||||
};
|
||||
|
||||
/* Our struct holding information about the session. */
|
||||
struct session_data_struct sdata = {
|
||||
.channel = NULL,
|
||||
.auth_attempts = 0,
|
||||
.authenticated = 0,
|
||||
};
|
||||
|
||||
struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.userdata = &(cdata.sftp),
|
||||
.channel_data_function = sftp_channel_default_data_callback,
|
||||
.channel_subsystem_request_function = sftp_channel_default_subsystem_request,
|
||||
};
|
||||
|
||||
struct ssh_server_callbacks_struct server_cb = {
|
||||
.userdata = &sdata,
|
||||
.auth_password_function = auth_password,
|
||||
.channel_open_request_session_function = channel_open,
|
||||
};
|
||||
|
||||
if (authorizedkeys[0])
|
||||
{
|
||||
server_cb.auth_pubkey_function = auth_publickey;
|
||||
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY);
|
||||
}
|
||||
else
|
||||
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD);
|
||||
|
||||
ssh_callbacks_init(&server_cb);
|
||||
ssh_callbacks_init(&channel_cb);
|
||||
|
||||
ssh_set_server_callbacks(session, &server_cb);
|
||||
|
||||
if (ssh_handle_key_exchange(session) != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "%s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
ssh_event_add_session(event, session);
|
||||
|
||||
n = 0;
|
||||
while (sdata.authenticated == 0 || sdata.channel == NULL) {
|
||||
/* If the user has used up all attempts, or if he hasn't been able to
|
||||
* authenticate in 10 seconds (n * 100ms), disconnect. */
|
||||
if (sdata.auth_attempts >= 3 || n >= 100) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ssh_event_dopoll(event, 100) == SSH_ERROR) {
|
||||
fprintf(stderr, "%s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
ssh_set_channel_callbacks(sdata.channel, &channel_cb);
|
||||
|
||||
do {
|
||||
/* Poll the main event which takes care of the session, the channel and
|
||||
* even our child process's stdout/stderr (once it's started). */
|
||||
if (ssh_event_dopoll(event, -1) == SSH_ERROR) {
|
||||
ssh_channel_close(sdata.channel);
|
||||
}
|
||||
|
||||
/* If child process's stdout/stderr has been registered with the event,
|
||||
* or the child process hasn't started yet, continue. */
|
||||
if (cdata.event != NULL) {
|
||||
continue;
|
||||
}
|
||||
/* FIXME The server keeps hanging in the poll above when the client
|
||||
* closes the channel */
|
||||
} while (ssh_channel_is_open(sdata.channel));
|
||||
|
||||
ssh_channel_send_eof(sdata.channel);
|
||||
ssh_channel_close(sdata.channel);
|
||||
|
||||
/* Wait up to 5 seconds for the client to terminate the session. */
|
||||
for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) {
|
||||
ssh_event_dopoll(event, 100);
|
||||
}
|
||||
}
|
||||
|
||||
/* SIGCHLD handler for cleaning up dead children. */
|
||||
static void sigchld_handler(int signo)
|
||||
{
|
||||
(void)signo;
|
||||
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_session session = NULL;
|
||||
ssh_event event = NULL;
|
||||
struct sigaction sa;
|
||||
int rc;
|
||||
|
||||
/* Set up SIGCHLD handler. */
|
||||
sa.sa_handler = sigchld_handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
|
||||
if (sigaction(SIGCHLD, &sa, NULL) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to register SIGCHLD handler\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_init();
|
||||
if (rc < 0)
|
||||
{
|
||||
fprintf(stderr, "ssh_init failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sshbind = ssh_bind_new();
|
||||
if (sshbind == NULL)
|
||||
{
|
||||
fprintf(stderr, "ssh_bind_new failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
argp_parse(&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
set_default_keys(sshbind, 0, 0);
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
if (ssh_bind_listen(sshbind) < 0)
|
||||
{
|
||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
session = ssh_new();
|
||||
if (session == NULL)
|
||||
{
|
||||
fprintf(stderr, "Failed to allocate session\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Blocks until there is a new incoming connection. */
|
||||
if (ssh_bind_accept(sshbind, session) != SSH_ERROR)
|
||||
{
|
||||
switch (fork())
|
||||
{
|
||||
case 0:
|
||||
/* Remove the SIGCHLD handler inherited from parent. */
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
/* Remove socket binding, which allows us to restart the
|
||||
* parent process, without terminating existing sessions. */
|
||||
ssh_bind_free(sshbind);
|
||||
|
||||
event = ssh_event_new();
|
||||
if (event != NULL)
|
||||
{
|
||||
/* Blocks until the SSH session ends by either
|
||||
* child process exiting, or client disconnecting. */
|
||||
handle_session(event, session);
|
||||
ssh_event_free(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Could not create polling context\n");
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
|
||||
exit(0);
|
||||
case -1:
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||
}
|
||||
/* Since the session has been passed to a child fork, do some cleaning
|
||||
* up at the parent process. */
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
}
|
||||
|
||||
exit:
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
@@ -33,13 +33,16 @@ clients must be made or how a client should react.
|
||||
#define BUF_SIZE 65536
|
||||
#endif
|
||||
|
||||
static int verbosity;
|
||||
static char *destination;
|
||||
|
||||
static void do_sftp(ssh_session session) {
|
||||
sftp_session sftp = sftp_new(session);
|
||||
sftp_dir dir;
|
||||
sftp_attributes file;
|
||||
sftp_statvfs_t sftpstatvfs;
|
||||
struct statvfs sysstatvfs;
|
||||
sftp_file source;
|
||||
sftp_file fichier;
|
||||
sftp_file to;
|
||||
int len = 1;
|
||||
unsigned int i;
|
||||
@@ -186,8 +189,8 @@ static void do_sftp(ssh_session session) {
|
||||
/* the small buffer size was intended to stress the library. of course, you
|
||||
* can use a buffer till 20kbytes without problem */
|
||||
|
||||
source = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
||||
if (!source) {
|
||||
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
||||
if (!fichier) {
|
||||
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
@@ -198,16 +201,16 @@ static void do_sftp(ssh_session session) {
|
||||
if (!to) {
|
||||
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_close(source);
|
||||
sftp_close(fichier);
|
||||
goto end;
|
||||
}
|
||||
|
||||
while ((len = sftp_read(source, data, 4096)) > 0) {
|
||||
while ((len = sftp_read(fichier, data, 4096)) > 0) {
|
||||
if (sftp_write(to, data, len) != len) {
|
||||
fprintf(stderr, "Error writing %d bytes: %s\n",
|
||||
len, ssh_get_error(session));
|
||||
sftp_close(to);
|
||||
sftp_close(source);
|
||||
sftp_close(fichier);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
@@ -217,10 +220,10 @@ static void do_sftp(ssh_session session) {
|
||||
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
|
||||
}
|
||||
|
||||
sftp_close(source);
|
||||
sftp_close(fichier);
|
||||
sftp_close(to);
|
||||
printf("file closed\n");
|
||||
to = sftp_open(sftp, "/tmp/large_file", O_WRONLY|O_CREAT, 0644);
|
||||
printf("fichiers ferm\n");
|
||||
to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644);
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
len = sftp_write(to, data, sizeof(data));
|
||||
@@ -241,63 +244,50 @@ static void usage(const char *argv0) {
|
||||
fprintf(stderr, "Usage : %s [-v] remotehost\n"
|
||||
"sample sftp test client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -l user : log in as user\n"
|
||||
" -p port : connect to port\n"
|
||||
" -v : increase log verbosity\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
char *destination = NULL;
|
||||
int auth = 0;
|
||||
int state;
|
||||
static int opts(int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
ssh_init();
|
||||
session = ssh_new();
|
||||
while ((i = getopt(argc, argv, "v")) != -1) {
|
||||
switch(i) {
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown option %c\n", optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr,
|
||||
"Error parsing command line: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
destination = argv[optind];
|
||||
if (destination == NULL) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ssh_session session;
|
||||
|
||||
if (opts(argc, argv) < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (argc < 1) {
|
||||
usage(argv[0]);
|
||||
|
||||
session = connect_ssh(destination, NULL, verbosity);
|
||||
if (session == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
destination = argv[1];
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, destination) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (ssh_connect(session)) {
|
||||
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
|
||||
state = verify_knownhost(session);
|
||||
if (state != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auth = authenticate_console(session);
|
||||
if (auth != SSH_AUTH_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do_sftp(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -172,12 +172,20 @@ static struct argp_option options[] = {
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key (deprecated alias for 'k').",
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
@@ -210,10 +218,15 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'r':
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
@@ -244,11 +257,10 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_event mainloop = NULL;
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_event mainloop;
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_none_function = auth_none,
|
||||
@@ -266,7 +278,8 @@ int main(int argc, char **argv)
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
@@ -340,3 +353,4 @@ int main(int argc, char **argv)
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,12 +112,20 @@ static struct argp_option options[] = {
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key (deprecated alias for 'k').",
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
@@ -143,10 +151,15 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
port = atoi(arg);
|
||||
break;
|
||||
case 'r':
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
@@ -174,8 +187,8 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
static const char *name = NULL;
|
||||
static const char *instruction = NULL;
|
||||
static const char *name;
|
||||
static const char *instruction;
|
||||
static const char *prompts[2];
|
||||
static char echo[] = { 1, 0 };
|
||||
|
||||
@@ -279,12 +292,11 @@ static int authenticate(ssh_session session) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_message message = NULL;
|
||||
ssh_channel chan = NULL;
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_message message;
|
||||
ssh_channel chan=0;
|
||||
char buf[BUF_SIZE];
|
||||
int auth=0;
|
||||
int shell=0;
|
||||
@@ -294,8 +306,10 @@ int main(int argc, char **argv)
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
|
||||
KEYS_FOLDER "ssh_host_rsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
|
||||
KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
|
||||
KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
@@ -412,3 +426,4 @@ int main(int argc, char **argv)
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ static int fetch_files(ssh_session session){
|
||||
int size;
|
||||
char buffer[BUF_SIZE];
|
||||
int mode;
|
||||
char *filename = NULL;
|
||||
char *filename;
|
||||
int r;
|
||||
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
|
||||
if(ssh_scp_init(scp) != SSH_OK){
|
||||
@@ -167,7 +167,7 @@ static int fetch_files(ssh_session session){
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session = NULL;
|
||||
ssh_session session;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
session=connect_ssh(host,NULL,verbosity);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define LIMIT 0x100000000UL
|
||||
|
||||
int main(void) {
|
||||
ssh_session session = NULL;
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[1024*1024];
|
||||
int rc;
|
||||
@@ -47,7 +47,7 @@ int main(void) {
|
||||
if(total > LIMIT)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (rc < 0) {
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -53,7 +53,7 @@ static struct termios terminal;
|
||||
|
||||
static char *pcap_file = NULL;
|
||||
|
||||
static char *proxycommand = NULL;
|
||||
static char *proxycommand;
|
||||
|
||||
static int auth_callback(const char *prompt,
|
||||
char *buf,
|
||||
@@ -94,6 +94,7 @@ static void usage(void)
|
||||
"Options :\n"
|
||||
" -l user : log in as user\n"
|
||||
" -p port : connect to port\n"
|
||||
" -d : use DSS to verify host public key\n"
|
||||
" -r : use RSA to verify host public key\n"
|
||||
" -F file : parse configuration file instead of default one\n"
|
||||
#ifdef WITH_PCAP
|
||||
@@ -251,7 +252,7 @@ static void select_loop(ssh_session session,ssh_channel channel)
|
||||
|
||||
static void shell(ssh_session session)
|
||||
{
|
||||
ssh_channel channel = NULL;
|
||||
ssh_channel channel;
|
||||
struct termios terminal_local;
|
||||
int interactive=isatty(0);
|
||||
|
||||
@@ -297,41 +298,25 @@ static void shell(ssh_session session)
|
||||
static void batch_shell(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
char *buffer = NULL;
|
||||
size_t i, s, n;
|
||||
char buffer[PATH_MAX];
|
||||
size_t i;
|
||||
int s = 0;
|
||||
|
||||
for (i = 0; i < MAXCMD && cmds[i]; ++i) {
|
||||
s += snprintf(buffer + s, sizeof(buffer) - s, "%s ", cmds[i]);
|
||||
}
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < MAXCMD && cmds[i]; ++i) {
|
||||
/* Including space after cmds[i] */
|
||||
n += strlen(cmds[i]) + 1;
|
||||
}
|
||||
/* Trailing \0 */
|
||||
n += 1;
|
||||
|
||||
buffer = malloc(n);
|
||||
if (buffer == NULL) {
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
s = 0;
|
||||
for (i = 0; i < MAXCMD && cmds[i]; ++i) {
|
||||
s += snprintf(buffer + s, n - s, "%s ", cmds[i]);
|
||||
}
|
||||
|
||||
ssh_channel_open_session(channel);
|
||||
if (ssh_channel_request_exec(channel, buffer)) {
|
||||
printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session));
|
||||
free(buffer);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
free(buffer);
|
||||
select_loop(session, channel);
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
@@ -339,7 +324,7 @@ static void batch_shell(ssh_session session)
|
||||
static int client(ssh_session session)
|
||||
{
|
||||
int auth = 0;
|
||||
char *banner = NULL;
|
||||
char *banner;
|
||||
int state;
|
||||
|
||||
if (user) {
|
||||
@@ -423,7 +408,7 @@ static void cleanup_pcap(void)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_session session;
|
||||
|
||||
ssh_init();
|
||||
session = ssh_new();
|
||||
|
||||
@@ -45,10 +45,36 @@ The goal is to show the API in action.
|
||||
#define BUF_SIZE 1048576
|
||||
#endif
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR)
|
||||
#define SFTP_SERVER_PATH "/usr/lib/sftp-server"
|
||||
#define AUTH_KEYS_MAX_LINE_SIZE 2048
|
||||
|
||||
static void set_default_keys(ssh_bind sshbind,
|
||||
int rsa_already_set,
|
||||
int dsa_already_set,
|
||||
int ecdsa_already_set) {
|
||||
if (!rsa_already_set) {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
|
||||
KEYS_FOLDER "ssh_host_rsa_key");
|
||||
}
|
||||
if (!dsa_already_set) {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
|
||||
KEYS_FOLDER "ssh_host_dsa_key");
|
||||
}
|
||||
if (!ecdsa_already_set) {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY,
|
||||
KEYS_FOLDER "ssh_host_ecdsa_key");
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
|
||||
KEYS_FOLDER "ssh_host_ed25519_key");
|
||||
}
|
||||
#define DEF_STR_SIZE 1024
|
||||
char authorizedkeys[DEF_STR_SIZE] = {0};
|
||||
char username[128] = "myuser";
|
||||
@@ -83,12 +109,20 @@ static struct argp_option options[] = {
|
||||
"Implies no default keys.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key (deprecated alias for 'k').",
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
@@ -96,7 +130,7 @@ static struct argp_option options[] = {
|
||||
.key = 'e',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the ecdsa key (deprecated alias for 'k').",
|
||||
.doc = "Set the ecdsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
@@ -123,6 +157,14 @@ static struct argp_option options[] = {
|
||||
.doc = "Set expected password.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "no-default-keys",
|
||||
.key = 'n',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Do not set default key locations.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
@@ -135,53 +177,75 @@ static struct argp_option options[] = {
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t
|
||||
parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure. */
|
||||
ssh_bind sshbind = state->input;
|
||||
static int no_default_keys = 0;
|
||||
static int rsa_already_set = 0, dsa_already_set = 0, ecdsa_already_set = 0;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'e':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'a':
|
||||
strncpy(authorizedkeys, arg, DEF_STR_SIZE - 1);
|
||||
break;
|
||||
case 'u':
|
||||
strncpy(username, arg, sizeof(username) - 1);
|
||||
break;
|
||||
case 'P':
|
||||
strncpy(password, arg, sizeof(password) - 1);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage(state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
case 'n':
|
||||
no_default_keys = 1;
|
||||
break;
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
dsa_already_set = 1;
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
/* We can't track the types of keys being added with this
|
||||
option, so let's ensure we keep the keys we're adding
|
||||
by just not setting the default keys */
|
||||
no_default_keys = 1;
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
rsa_already_set = 1;
|
||||
break;
|
||||
case 'e':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, arg);
|
||||
ecdsa_already_set = 1;
|
||||
break;
|
||||
case 'a':
|
||||
strncpy(authorizedkeys, arg, DEF_STR_SIZE-1);
|
||||
break;
|
||||
case 'u':
|
||||
strncpy(username, arg, sizeof(username) - 1);
|
||||
break;
|
||||
case 'P':
|
||||
strncpy(password, arg, sizeof(password) - 1);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
|
||||
"3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
|
||||
if (!no_default_keys) {
|
||||
set_default_keys(sshbind,
|
||||
rsa_already_set,
|
||||
dsa_already_set,
|
||||
ecdsa_already_set);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -189,17 +253,21 @@ parse_opt(int key, char *arg, struct argp_state *state)
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#else
|
||||
static int
|
||||
parse_opt(int argc, char **argv, ssh_bind sshbind)
|
||||
{
|
||||
static int parse_opt(int argc, char **argv, ssh_bind sshbind) {
|
||||
int no_default_keys = 0;
|
||||
int rsa_already_set = 0;
|
||||
int dsa_already_set = 0;
|
||||
int ecdsa_already_set = 0;
|
||||
int key;
|
||||
|
||||
while((key = getopt(argc, argv, "a:e:k:p:P:r:u:v")) != -1) {
|
||||
if (key == 'p') {
|
||||
while((key = getopt(argc, argv, "a:d:e:k:np:P:r:u:v")) != -1) {
|
||||
if (key == 'n') {
|
||||
no_default_keys = 1;
|
||||
} else if (key == 'p') {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, optarg);
|
||||
} else if (key == 'd') {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, optarg);
|
||||
dsa_already_set = 1;
|
||||
} else if (key == 'k') {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
|
||||
/* We can't track the types of keys being added with this
|
||||
@@ -207,10 +275,10 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
|
||||
by just not setting the default keys */
|
||||
no_default_keys = 1;
|
||||
} else if (key == 'r') {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, optarg);
|
||||
rsa_already_set = 1;
|
||||
} else if (key == 'e') {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, optarg);
|
||||
ecdsa_already_set = 1;
|
||||
} else if (key == 'a') {
|
||||
strncpy(authorizedkeys, optarg, DEF_STR_SIZE-1);
|
||||
@@ -231,12 +299,14 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
|
||||
"libssh %s -- a Secure Shell protocol implementation\n"
|
||||
"\n"
|
||||
" -a, --authorizedkeys=FILE Set the authorized keys file.\n"
|
||||
" -e, --ecdsakey=FILE Set the ecdsa key (deprecated alias for 'k').\n"
|
||||
" -d, --dsakey=FILE Set the dsa key.\n"
|
||||
" -e, --ecdsakey=FILE Set the ecdsa key.\n"
|
||||
" -k, --hostkey=FILE Set a host key. Can be used multiple times.\n"
|
||||
" Implies no default keys.\n"
|
||||
" -n, --no-default-keys Do not set default key locations.\n"
|
||||
" -p, --port=PORT Set the port to bind.\n"
|
||||
" -P, --pass=PASSWORD Set expected password.\n"
|
||||
" -r, --rsakey=FILE Set the rsa key (deprecated alias for 'k').\n"
|
||||
" -r, --rsakey=FILE Set the rsa key.\n"
|
||||
" -u, --user=USERNAME Set expected username.\n"
|
||||
" -v, --verbose Get verbose output.\n"
|
||||
" -?, --help Give this help list\n"
|
||||
@@ -259,6 +329,7 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
|
||||
if (!no_default_keys) {
|
||||
set_default_keys(sshbind,
|
||||
rsa_already_set,
|
||||
dsa_already_set,
|
||||
ecdsa_already_set);
|
||||
}
|
||||
|
||||
@@ -292,74 +363,49 @@ struct session_data_struct {
|
||||
int authenticated;
|
||||
};
|
||||
|
||||
static int
|
||||
data_function(ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *data,
|
||||
uint32_t len,
|
||||
int is_stderr,
|
||||
void *userdata)
|
||||
{
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||
static int data_function(ssh_session session, ssh_channel channel, void *data,
|
||||
uint32_t len, int is_stderr, void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)is_stderr;
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) is_stderr;
|
||||
|
||||
if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return write(cdata->child_stdin, (char *)data, len);
|
||||
return write(cdata->child_stdin, (char *) data, len);
|
||||
}
|
||||
|
||||
static int
|
||||
pty_request(ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *term,
|
||||
int cols,
|
||||
int rows,
|
||||
int py,
|
||||
int px,
|
||||
void *userdata)
|
||||
{
|
||||
static int pty_request(ssh_session session, ssh_channel channel,
|
||||
const char *term, int cols, int rows, int py, int px,
|
||||
void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||
int rc;
|
||||
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)term;
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) term;
|
||||
|
||||
cdata->winsize->ws_row = rows;
|
||||
cdata->winsize->ws_col = cols;
|
||||
cdata->winsize->ws_xpixel = px;
|
||||
cdata->winsize->ws_ypixel = py;
|
||||
|
||||
rc = openpty(&cdata->pty_master,
|
||||
&cdata->pty_slave,
|
||||
NULL,
|
||||
NULL,
|
||||
cdata->winsize);
|
||||
if (rc != 0) {
|
||||
if (openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL,
|
||||
cdata->winsize) != 0) {
|
||||
fprintf(stderr, "Failed to open pty\n");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
pty_resize(ssh_session session,
|
||||
ssh_channel channel,
|
||||
int cols,
|
||||
int rows,
|
||||
int py,
|
||||
int px,
|
||||
void *userdata)
|
||||
{
|
||||
static int pty_resize(ssh_session session, ssh_channel channel, int cols,
|
||||
int rows, int py, int px, void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void) session;
|
||||
(void) channel;
|
||||
|
||||
cdata->winsize->ws_row = rows;
|
||||
cdata->winsize->ws_col = cols;
|
||||
@@ -373,36 +419,30 @@ pty_resize(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int
|
||||
exec_pty(const char *mode,
|
||||
const char *command,
|
||||
struct channel_data_struct *cdata)
|
||||
{
|
||||
cdata->pid = fork();
|
||||
switch (cdata->pid) {
|
||||
case -1:
|
||||
close(cdata->pty_master);
|
||||
close(cdata->pty_slave);
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
return SSH_ERROR;
|
||||
case 0:
|
||||
close(cdata->pty_master);
|
||||
if (login_tty(cdata->pty_slave) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
execl("/bin/sh", "sh", mode, command, NULL);
|
||||
exit(0);
|
||||
default:
|
||||
close(cdata->pty_slave);
|
||||
/* pty fd is bi-directional */
|
||||
cdata->child_stdout = cdata->child_stdin = cdata->pty_master;
|
||||
static int exec_pty(const char *mode, const char *command,
|
||||
struct channel_data_struct *cdata) {
|
||||
switch(cdata->pid = fork()) {
|
||||
case -1:
|
||||
close(cdata->pty_master);
|
||||
close(cdata->pty_slave);
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
return SSH_ERROR;
|
||||
case 0:
|
||||
close(cdata->pty_master);
|
||||
if (login_tty(cdata->pty_slave) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
execl("/bin/sh", "sh", mode, command, NULL);
|
||||
exit(0);
|
||||
default:
|
||||
close(cdata->pty_slave);
|
||||
/* pty fd is bi-directional */
|
||||
cdata->child_stdout = cdata->child_stdin = cdata->pty_master;
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
exec_nopty(const char *command, struct channel_data_struct *cdata)
|
||||
{
|
||||
static int exec_nopty(const char *command, struct channel_data_struct *cdata) {
|
||||
int in[2], out[2], err[2];
|
||||
|
||||
/* Do the plumbing to be able to talk with the child process. */
|
||||
@@ -416,24 +456,23 @@ exec_nopty(const char *command, struct channel_data_struct *cdata)
|
||||
goto stderr_failed;
|
||||
}
|
||||
|
||||
cdata->pid = fork();
|
||||
switch (cdata->pid) {
|
||||
case -1:
|
||||
goto fork_failed;
|
||||
case 0:
|
||||
/* Finish the plumbing in the child process. */
|
||||
close(in[1]);
|
||||
close(out[0]);
|
||||
close(err[0]);
|
||||
dup2(in[0], STDIN_FILENO);
|
||||
dup2(out[1], STDOUT_FILENO);
|
||||
dup2(err[1], STDERR_FILENO);
|
||||
close(in[0]);
|
||||
close(out[1]);
|
||||
close(err[1]);
|
||||
/* exec the requested command. */
|
||||
execl("/bin/sh", "sh", "-c", command, NULL);
|
||||
exit(0);
|
||||
switch(cdata->pid = fork()) {
|
||||
case -1:
|
||||
goto fork_failed;
|
||||
case 0:
|
||||
/* Finish the plumbing in the child process. */
|
||||
close(in[1]);
|
||||
close(out[0]);
|
||||
close(err[0]);
|
||||
dup2(in[0], STDIN_FILENO);
|
||||
dup2(out[1], STDOUT_FILENO);
|
||||
dup2(err[1], STDERR_FILENO);
|
||||
close(in[0]);
|
||||
close(out[1]);
|
||||
close(err[1]);
|
||||
/* exec the requested command. */
|
||||
execl("/bin/sh", "sh", "-c", command, NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close(in[0]);
|
||||
@@ -459,18 +498,15 @@ stdin_failed:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int
|
||||
exec_request(ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *command,
|
||||
void *userdata)
|
||||
{
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||
static int exec_request(ssh_session session, ssh_channel channel,
|
||||
const char *command, void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||
|
||||
(void)session;
|
||||
(void)channel;
|
||||
|
||||
if (cdata->pid > 0) {
|
||||
(void) session;
|
||||
(void) channel;
|
||||
|
||||
if(cdata->pid > 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -480,15 +516,14 @@ exec_request(ssh_session session,
|
||||
return exec_nopty(command, cdata);
|
||||
}
|
||||
|
||||
static int
|
||||
shell_request(ssh_session session, ssh_channel channel, void *userdata)
|
||||
{
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||
static int shell_request(ssh_session session, ssh_channel channel,
|
||||
void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void) session;
|
||||
(void) channel;
|
||||
|
||||
if (cdata->pid > 0) {
|
||||
if(cdata->pid > 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -499,28 +534,20 @@ shell_request(ssh_session session, ssh_channel channel, void *userdata)
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
subsystem_request(ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *subsystem,
|
||||
void *userdata)
|
||||
{
|
||||
/* subsystem requests behave similarly to exec requests. */
|
||||
static int subsystem_request(ssh_session session, ssh_channel channel,
|
||||
const char *subsystem, void *userdata) {
|
||||
/* subsystem requests behave simillarly to exec requests. */
|
||||
if (strcmp(subsystem, "sftp") == 0) {
|
||||
return exec_request(session, channel, SFTP_SERVER_PATH, userdata);
|
||||
}
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int
|
||||
auth_password(ssh_session session,
|
||||
const char *user,
|
||||
const char *pass,
|
||||
void *userdata)
|
||||
{
|
||||
struct session_data_struct *sdata = (struct session_data_struct *)userdata;
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *pass, void *userdata) {
|
||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||
|
||||
(void)session;
|
||||
(void) session;
|
||||
|
||||
if (strcmp(user, username) == 0 && strcmp(pass, password) == 0) {
|
||||
sdata->authenticated = 1;
|
||||
@@ -531,26 +558,16 @@ auth_password(ssh_session session,
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int
|
||||
auth_publickey(ssh_session session,
|
||||
const char *user,
|
||||
struct ssh_key_struct *pubkey,
|
||||
char signature_state,
|
||||
void *userdata)
|
||||
static int auth_publickey(ssh_session session,
|
||||
const char *user,
|
||||
struct ssh_key_struct *pubkey,
|
||||
char signature_state,
|
||||
void *userdata)
|
||||
{
|
||||
struct session_data_struct *sdata = (struct session_data_struct *)userdata;
|
||||
ssh_key key = NULL;
|
||||
FILE *fp = NULL;
|
||||
char line[AUTH_KEYS_MAX_LINE_SIZE] = {0};
|
||||
char *p = NULL;
|
||||
const char *q = NULL;
|
||||
unsigned int lineno = 0;
|
||||
int result;
|
||||
int i;
|
||||
enum ssh_keytypes_e type;
|
||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||
|
||||
(void)user;
|
||||
(void)session;
|
||||
(void) user;
|
||||
(void) session;
|
||||
|
||||
if (signature_state == SSH_PUBLICKEY_STATE_NONE) {
|
||||
return SSH_AUTH_SUCCESS;
|
||||
@@ -560,107 +577,45 @@ auth_publickey(ssh_session session,
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
fp = fopen(authorizedkeys, "r");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Error: opening authorized keys file %s failed, reason: %s\n",
|
||||
authorizedkeys, strerror(errno));
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
// valid so far. Now look through authorized keys for a match
|
||||
if (authorizedkeys[0]) {
|
||||
ssh_key key = NULL;
|
||||
int result;
|
||||
struct stat buf;
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
lineno++;
|
||||
|
||||
/* Skip leading whitespace and ignore comments */
|
||||
p = line;
|
||||
|
||||
for (i = 0; i < AUTH_KEYS_MAX_LINE_SIZE; i++) {
|
||||
if (!isspace((int)p[i])) {
|
||||
break;
|
||||
if (stat(authorizedkeys, &buf) == 0) {
|
||||
result = ssh_pki_import_pubkey_file( authorizedkeys, &key );
|
||||
if ((result != SSH_OK) || (key==NULL)) {
|
||||
fprintf(stderr,
|
||||
"Unable to import public key file %s\n",
|
||||
authorizedkeys);
|
||||
} else {
|
||||
result = ssh_key_cmp( key, pubkey, SSH_KEY_CMP_PUBLIC );
|
||||
ssh_key_free(key);
|
||||
if (result == 0) {
|
||||
sdata->authenticated = 1;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= AUTH_KEYS_MAX_LINE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"warning: The line %d in %s too long! Skipping.\n",
|
||||
lineno,
|
||||
authorizedkeys);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p[i] == '#' || p[i] == '\0' || p[i] == '\n') {
|
||||
continue;
|
||||
}
|
||||
|
||||
q = &p[i];
|
||||
for (; i < AUTH_KEYS_MAX_LINE_SIZE; i++) {
|
||||
if (isspace((int)p[i])) {
|
||||
p[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
type = ssh_key_type_from_name(q);
|
||||
|
||||
i++;
|
||||
if (i >= AUTH_KEYS_MAX_LINE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"warning: The line %d in %s too long! Skipping.\n",
|
||||
lineno,
|
||||
authorizedkeys);
|
||||
continue;
|
||||
}
|
||||
|
||||
q = &p[i];
|
||||
for (; i < AUTH_KEYS_MAX_LINE_SIZE; i++) {
|
||||
if (isspace((int)p[i])) {
|
||||
p[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = ssh_pki_import_pubkey_base64(q, type, &key);
|
||||
if (result != SSH_OK) {
|
||||
fprintf(stderr,
|
||||
"Warning: Cannot import key on line no. %d in authorized keys file: %s\n",
|
||||
lineno,
|
||||
authorizedkeys);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = ssh_key_cmp(key, pubkey, SSH_KEY_CMP_PUBLIC);
|
||||
ssh_key_free(key);
|
||||
if (result == 0) {
|
||||
sdata->authenticated = 1;
|
||||
fclose(fp);
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
}
|
||||
if (ferror(fp) != 0) {
|
||||
fprintf(stderr,
|
||||
"Error: Reading from authorized keys file %s failed, reason: %s\n",
|
||||
authorizedkeys, strerror(errno));
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
/* no matches */
|
||||
// no matches
|
||||
sdata->authenticated = 0;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static ssh_channel
|
||||
channel_open(ssh_session session, void *userdata)
|
||||
{
|
||||
struct session_data_struct *sdata = (struct session_data_struct *)userdata;
|
||||
static ssh_channel channel_open(ssh_session session, void *userdata) {
|
||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||
|
||||
sdata->channel = ssh_channel_new(session);
|
||||
return sdata->channel;
|
||||
}
|
||||
|
||||
static int
|
||||
process_stdout(socket_t fd, int revents, void *userdata)
|
||||
{
|
||||
static int process_stdout(socket_t fd, int revents, void *userdata) {
|
||||
char buf[BUF_SIZE];
|
||||
int n = -1;
|
||||
ssh_channel channel = (ssh_channel)userdata;
|
||||
ssh_channel channel = (ssh_channel) userdata;
|
||||
|
||||
if (channel != NULL && (revents & POLLIN) != 0) {
|
||||
n = read(fd, buf, BUF_SIZE);
|
||||
@@ -672,12 +627,10 @@ process_stdout(socket_t fd, int revents, void *userdata)
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
process_stderr(socket_t fd, int revents, void *userdata)
|
||||
{
|
||||
static int process_stderr(socket_t fd, int revents, void *userdata) {
|
||||
char buf[BUF_SIZE];
|
||||
int n = -1;
|
||||
ssh_channel channel = (ssh_channel)userdata;
|
||||
ssh_channel channel = (ssh_channel) userdata;
|
||||
|
||||
if (channel != NULL && (revents & POLLIN) != 0) {
|
||||
n = read(fd, buf, BUF_SIZE);
|
||||
@@ -689,9 +642,7 @@ process_stderr(socket_t fd, int revents, void *userdata)
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_session(ssh_event event, ssh_session session)
|
||||
{
|
||||
static void handle_session(ssh_event event, ssh_session session) {
|
||||
int n;
|
||||
int rc = 0;
|
||||
|
||||
@@ -804,8 +755,8 @@ handle_session(ssh_event event, ssh_session session)
|
||||
ssh_channel_close(sdata.channel);
|
||||
}
|
||||
}
|
||||
} while (ssh_channel_is_open(sdata.channel) &&
|
||||
(cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0));
|
||||
} while(ssh_channel_is_open(sdata.channel) &&
|
||||
(cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0));
|
||||
|
||||
close(cdata.pty_master);
|
||||
close(cdata.child_stdin);
|
||||
@@ -838,14 +789,12 @@ handle_session(ssh_event event, ssh_session session)
|
||||
|
||||
#ifdef WITH_FORK
|
||||
/* SIGCHLD handler for cleaning up dead children. */
|
||||
static void sigchld_handler(int signo)
|
||||
{
|
||||
(void)signo;
|
||||
static void sigchld_handler(int signo) {
|
||||
(void) signo;
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
}
|
||||
#else
|
||||
static void *session_thread(void *arg)
|
||||
{
|
||||
static void *session_thread(void *arg) {
|
||||
ssh_session session = arg;
|
||||
ssh_event event;
|
||||
|
||||
@@ -864,10 +813,9 @@ static void *session_thread(void *arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_session session = NULL;
|
||||
int main(int argc, char **argv) {
|
||||
ssh_bind sshbind;
|
||||
ssh_session session;
|
||||
int rc;
|
||||
#ifdef WITH_FORK
|
||||
struct sigaction sa;
|
||||
@@ -905,8 +853,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
rc = ssh_bind_listen(sshbind);
|
||||
if (rc < 0) {
|
||||
if(ssh_bind_listen(sshbind) < 0) {
|
||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
@@ -921,36 +868,34 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Blocks until there is a new incoming connection. */
|
||||
rc = ssh_bind_accept(sshbind, session);
|
||||
if (rc != SSH_ERROR) {
|
||||
if(ssh_bind_accept(sshbind, session) != SSH_ERROR) {
|
||||
#ifdef WITH_FORK
|
||||
ssh_event event;
|
||||
|
||||
pid_t pid = fork();
|
||||
switch (pid) {
|
||||
case 0:
|
||||
/* Remove the SIGCHLD handler inherited from parent. */
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
/* Remove socket binding, which allows us to restart the
|
||||
* parent process, without terminating existing sessions. */
|
||||
ssh_bind_free(sshbind);
|
||||
switch(fork()) {
|
||||
case 0:
|
||||
/* Remove the SIGCHLD handler inherited from parent. */
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
/* Remove socket binding, which allows us to restart the
|
||||
* parent process, without terminating existing sessions. */
|
||||
ssh_bind_free(sshbind);
|
||||
|
||||
event = ssh_event_new();
|
||||
if (event != NULL) {
|
||||
/* Blocks until the SSH session ends by either
|
||||
* child process exiting, or client disconnecting. */
|
||||
handle_session(event, session);
|
||||
ssh_event_free(event);
|
||||
} else {
|
||||
fprintf(stderr, "Could not create polling context\n");
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
event = ssh_event_new();
|
||||
if (event != NULL) {
|
||||
/* Blocks until the SSH session ends by either
|
||||
* child process exiting, or client disconnecting. */
|
||||
handle_session(event, session);
|
||||
ssh_event_free(event);
|
||||
} else {
|
||||
fprintf(stderr, "Could not create polling context\n");
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
|
||||
exit(0);
|
||||
case -1:
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
exit(0);
|
||||
case -1:
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
}
|
||||
#else
|
||||
pthread_t tid;
|
||||
|
||||
@@ -15,7 +15,7 @@ clients must be made or how a client should react.
|
||||
|
||||
/*
|
||||
Example:
|
||||
./sshd_direct-tcpip -v -p 2022 -r serverkey.rsa 127.0.0.1
|
||||
./sshd_direct-tcpip -v -p 2022 -d serverkey.dsa -r serverkey.rsa 127.0.0.1
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -94,9 +94,6 @@ cleanup_push(struct cleanup_node_struct** head_ref,
|
||||
{
|
||||
// Allocate memory for node
|
||||
struct cleanup_node_struct *new_node = malloc(sizeof *new_node);
|
||||
if (new_node == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (*head_ref != NULL) {
|
||||
new_node->next = *head_ref;
|
||||
@@ -361,7 +358,7 @@ my_fd_data_function(UNUSED_PARAM(socket_t fd),
|
||||
{
|
||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||
ssh_channel channel = event_fd_data->channel;
|
||||
ssh_session session = NULL;
|
||||
ssh_session session;
|
||||
int len, i, wr;
|
||||
char buf[BUF_SIZE];
|
||||
int blocking;
|
||||
@@ -455,8 +452,8 @@ open_tcp_socket(ssh_message msg)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int forwardsock = -1;
|
||||
struct hostent *host = NULL;
|
||||
const char *dest_hostname = NULL;
|
||||
struct hostent *host;
|
||||
const char *dest_hostname;
|
||||
int dest_port;
|
||||
|
||||
forwardsock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
@@ -499,8 +496,8 @@ message_callback(UNUSED_PARAM(ssh_session session),
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
ssh_channel channel;
|
||||
int socket_fd, *pFd = NULL;
|
||||
struct ssh_channel_callbacks_struct *cb_chan = NULL;
|
||||
int socket_fd, *pFd;
|
||||
struct ssh_channel_callbacks_struct *cb_chan;
|
||||
struct event_fd_data_struct *event_fd_data;
|
||||
|
||||
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d",
|
||||
@@ -526,7 +523,7 @@ message_callback(UNUSED_PARAM(ssh_session session),
|
||||
}
|
||||
|
||||
pFd = malloc(sizeof *pFd);
|
||||
cb_chan = calloc(1, sizeof *cb_chan);
|
||||
cb_chan = malloc(sizeof *cb_chan);
|
||||
event_fd_data = malloc(sizeof *event_fd_data);
|
||||
if (pFd == NULL || cb_chan == NULL || event_fd_data == NULL) {
|
||||
SAFE_FREE(pFd);
|
||||
@@ -589,12 +586,20 @@ static struct argp_option options[] = {
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key (deprecated alias for 'k').",
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
@@ -621,10 +626,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'r':
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "1");
|
||||
break;
|
||||
@@ -655,8 +665,8 @@ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_password_function = auth_password,
|
||||
@@ -675,7 +685,8 @@ main(int argc, char **argv)
|
||||
session = ssh_new();
|
||||
mainloop = ssh_event_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
|
||||
@@ -39,7 +39,7 @@ clients must be made or how a client should react.
|
||||
#define BUF_SIZE 4096
|
||||
#endif
|
||||
|
||||
char *host = NULL;
|
||||
char *host;
|
||||
const char *desthost="localhost";
|
||||
const char *port="22";
|
||||
|
||||
@@ -193,7 +193,7 @@ static void forwarding(ssh_session session){
|
||||
|
||||
static int client(ssh_session session){
|
||||
int auth=0;
|
||||
char *banner = NULL;
|
||||
char *banner;
|
||||
int state;
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
|
||||
@@ -246,7 +246,7 @@ void cleanup_pcap(void)
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session = NULL;
|
||||
ssh_session session;
|
||||
|
||||
session = ssh_new();
|
||||
|
||||
|
||||
@@ -20,13 +20,6 @@ if (WITH_SERVER)
|
||||
${libssh_HDRS}
|
||||
server.h
|
||||
)
|
||||
|
||||
if (WITH_SFTP)
|
||||
set(libssh_HDRS
|
||||
${libssh_HDRS}
|
||||
sftpserver.h
|
||||
)
|
||||
endif (WITH_SFTP)
|
||||
endif (WITH_SERVER)
|
||||
|
||||
install(
|
||||
|
||||
@@ -39,9 +39,11 @@ struct ssh_bind_struct {
|
||||
char *wanted_methods[SSH_KEX_METHODS];
|
||||
char *banner;
|
||||
char *ecdsakey;
|
||||
char *dsakey;
|
||||
char *rsakey;
|
||||
char *ed25519key;
|
||||
ssh_key ecdsa;
|
||||
ssh_key dsa;
|
||||
ssh_key rsa;
|
||||
ssh_key ed25519;
|
||||
char *bindaddr;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: blf.h,v 1.8 2021/11/29 01:04:45 djm Exp $ */
|
||||
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
|
||||
/*
|
||||
* Blowfish - a fast block cipher designed by Bruce Schneier
|
||||
*
|
||||
@@ -13,7 +13,10 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Niels Provos.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
|
||||
@@ -42,6 +42,10 @@ int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len);
|
||||
|
||||
void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len);
|
||||
int ssh_buffer_allocate_size(struct ssh_buffer_struct *buffer, uint32_t len);
|
||||
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
size_t argc,
|
||||
va_list ap);
|
||||
int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
size_t argc,
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -139,26 +138,6 @@ typedef ssh_channel (*ssh_channel_open_request_x11_callback) (ssh_session sessio
|
||||
typedef ssh_channel (*ssh_channel_open_request_auth_agent_callback) (ssh_session session,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH new channel open "forwarded-tcpip" request. This
|
||||
* happens when the server forwards an incoming TCP connection on a port it was
|
||||
* previously requested to listen on. This is a client-side API
|
||||
* @param session current session handler
|
||||
* @param destination_address the address that the TCP connection connected to
|
||||
* @param destination_port the port that the TCP connection connected to
|
||||
* @param originator_address the originator IP address
|
||||
* @param originator_port the originator port
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns a valid ssh_channel handle if the request is to be allowed
|
||||
* @returns NULL if the request should not be allowed
|
||||
* @warning The channel pointer returned by this callback must be closed by the
|
||||
* application.
|
||||
*/
|
||||
typedef ssh_channel (*ssh_channel_open_request_forwarded_tcpip_callback) (ssh_session session,
|
||||
const char *destination_address, int destination_port,
|
||||
const char *originator_address, int originator_port,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* The structure to replace libssh functions with appropriate callbacks.
|
||||
*/
|
||||
@@ -192,11 +171,6 @@ struct ssh_callbacks_struct {
|
||||
/** This function will be called when an incoming "auth-agent" request is received.
|
||||
*/
|
||||
ssh_channel_open_request_auth_agent_callback channel_open_request_auth_agent_function;
|
||||
/**
|
||||
* This function will be called when an incoming "forwarded-tcpip"
|
||||
* request is received.
|
||||
*/
|
||||
ssh_channel_open_request_forwarded_tcpip_callback channel_open_request_forwarded_tcpip_function;
|
||||
};
|
||||
typedef struct ssh_callbacks_struct *ssh_callbacks;
|
||||
|
||||
@@ -283,7 +257,6 @@ typedef ssh_channel (*ssh_channel_open_request_session_callback) (ssh_session se
|
||||
|
||||
/*
|
||||
* @brief handle the beginning of a GSSAPI authentication, server side.
|
||||
* Callback should select the oid and also acquire the server credential.
|
||||
* @param session current session handler
|
||||
* @param user the username of the client
|
||||
* @param n_oid number of available oids
|
||||
@@ -366,7 +339,6 @@ struct ssh_server_callbacks_struct {
|
||||
*/
|
||||
ssh_channel_open_request_session_callback channel_open_request_session_function;
|
||||
/** This function will be called when a new gssapi authentication is attempted.
|
||||
* This should select the oid and acquire credential for the server.
|
||||
*/
|
||||
ssh_gssapi_select_oid_callback gssapi_select_oid_function;
|
||||
/** This function will be called when a gssapi token comes in.
|
||||
@@ -825,28 +797,6 @@ typedef int (*ssh_channel_write_wontblock_callback) (ssh_session session,
|
||||
uint32_t bytes,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel open callback. Called when a channel open succeeds or fails.
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param is_success is 1 when the open succeeds, and 0 otherwise.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_open_resp_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
bool is_success,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel request response callback. Called when a response to the pending request is received.
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_request_resp_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
|
||||
struct ssh_channel_callbacks_struct {
|
||||
/** DON'T SET THIS use ssh_callbacks_init() instead. */
|
||||
size_t size;
|
||||
@@ -914,14 +864,6 @@ struct ssh_channel_callbacks_struct {
|
||||
* not to block.
|
||||
*/
|
||||
ssh_channel_write_wontblock_callback channel_write_wontblock_function;
|
||||
/**
|
||||
* This functions will be called when the channel has received a channel open confirmation or failure.
|
||||
*/
|
||||
ssh_channel_open_resp_callback channel_open_response_function;
|
||||
/**
|
||||
* This functions will be called when the channel has received the response to the pending request.
|
||||
*/
|
||||
ssh_channel_request_resp_callback channel_request_response_function;
|
||||
};
|
||||
|
||||
typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks;
|
||||
@@ -1058,7 +1000,6 @@ LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);
|
||||
* @see ssh_threads_set_callbacks
|
||||
*/
|
||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Set the logging callback function.
|
||||
@@ -1076,45 +1017,7 @@ LIBSSH_API int ssh_set_log_callback(ssh_logging_callback cb);
|
||||
*/
|
||||
LIBSSH_API ssh_logging_callback ssh_get_log_callback(void);
|
||||
|
||||
/**
|
||||
* @brief SSH proxyjump before connection callback. Called before calling
|
||||
* ssh_connect()
|
||||
* @param session Jump session handler
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
typedef int (*ssh_jump_before_connection_callback)(ssh_session session,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH proxyjump verify knownhost callback. Verify the host.
|
||||
* If not specified default function will be used.
|
||||
* @param session Jump session handler
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
typedef int (*ssh_jump_verify_knownhost_callback)(ssh_session session,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH proxyjump user authentication callback. Authenticate the user.
|
||||
* @param session Jump session handler
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
typedef int (*ssh_jump_authenticate_callback)(ssh_session session,
|
||||
void *userdata);
|
||||
|
||||
struct ssh_jump_callbacks_struct {
|
||||
void *userdata;
|
||||
ssh_jump_before_connection_callback before_connection;
|
||||
ssh_jump_verify_knownhost_callback verify_knownhost;
|
||||
ssh_jump_authenticate_callback authenticate;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -80,12 +80,7 @@ struct ssh_channel_struct {
|
||||
ssh_buffer stdout_buffer;
|
||||
ssh_buffer stderr_buffer;
|
||||
void *userarg;
|
||||
struct {
|
||||
bool status;
|
||||
uint32_t code;
|
||||
char *signal;
|
||||
bool core_dumped;
|
||||
} exit;
|
||||
int exit_status;
|
||||
enum ssh_channel_request_state_e request_state;
|
||||
struct ssh_list *callbacks; /* list of ssh_channel_callbacks */
|
||||
|
||||
|
||||
@@ -62,10 +62,6 @@ enum ssh_config_opcode_e {
|
||||
SOC_PUBKEYACCEPTEDKEYTYPES,
|
||||
SOC_REKEYLIMIT,
|
||||
SOC_IDENTITYAGENT,
|
||||
SOC_IDENTITIESONLY,
|
||||
SOC_CONTROLMASTER,
|
||||
SOC_CONTROLPATH,
|
||||
SOC_CERTIFICATE,
|
||||
|
||||
SOC_MAX /* Keep this one last in the list */
|
||||
};
|
||||
|
||||
@@ -30,9 +30,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
char *ssh_config_get_cmd(char **str);
|
||||
|
||||
char *ssh_config_get_token(char **str);
|
||||
@@ -52,32 +49,14 @@ int ssh_config_get_yesno(char **str, int notfound);
|
||||
* be stored or NULL if we do not care about the result.
|
||||
* @param[out] port Pointer to the location, where the new port will
|
||||
* be stored or NULL if we do not care about the result.
|
||||
* @param[in] ignore_port Set to true if we should not attempt to parse
|
||||
* port number.
|
||||
*
|
||||
* @returns SSH_OK if the provided string is in format of SSH URI,
|
||||
* SSH_ERROR on failure
|
||||
*/
|
||||
int ssh_config_parse_uri(const char *tok,
|
||||
char **username,
|
||||
char **hostname,
|
||||
char **port,
|
||||
bool ignore_port);
|
||||
|
||||
/**
|
||||
* @brief: Parse the ProxyJump configuration line and if parsing,
|
||||
* stores the result in the configuration option
|
||||
*
|
||||
* @param[in] session The ssh session
|
||||
* @param[in] s The string to be parsed.
|
||||
* @param[in] do_parsing Whether to parse or not.
|
||||
*
|
||||
* @returns SSH_OK if the provided string is formatted and parsed correctly
|
||||
* SSH_ERROR on failure
|
||||
*/
|
||||
int ssh_config_parse_proxy_jump(ssh_session session,
|
||||
const char *s,
|
||||
bool do_parsing);
|
||||
char **username,
|
||||
char **hostname,
|
||||
char **port);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -86,9 +86,9 @@ enum ssh_key_exchange_e {
|
||||
|
||||
enum ssh_cipher_e {
|
||||
SSH_NO_CIPHER=0,
|
||||
#ifdef HAVE_BLOWFISH
|
||||
#ifdef WITH_BLOWFISH_CIPHER
|
||||
SSH_BLOWFISH_CBC,
|
||||
#endif /* HAVE_BLOWFISH */
|
||||
#endif /* WITH_BLOWFISH_CIPHER */
|
||||
SSH_3DES_CBC,
|
||||
SSH_AES128_CBC,
|
||||
SSH_AES192_CBC,
|
||||
@@ -111,7 +111,11 @@ struct ssh_crypto_struct {
|
||||
#endif /* WITH_GEX */
|
||||
#ifdef HAVE_ECDH
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys
|
||||
* https://github.com/openssl/openssl/pull/16624
|
||||
* #if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
*/
|
||||
#if 1
|
||||
EC_KEY *ecdh_privkey;
|
||||
#else
|
||||
EVP_PKEY *ecdh_privkey;
|
||||
@@ -223,8 +227,9 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
||||
size_t requested_len);
|
||||
|
||||
int secure_memcmp(const void *s1, const void *s2, size_t n);
|
||||
|
||||
void compress_cleanup(struct ssh_crypto_struct *crypto);
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
ENGINE *pki_get_engine(void);
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@
|
||||
#define GSSAPI_H_
|
||||
|
||||
#include "config.h"
|
||||
#ifdef WITH_GSSAPI
|
||||
#include "session.h"
|
||||
#include <gssapi/gssapi.h>
|
||||
|
||||
/* all OID begin with the tag identifier + length */
|
||||
#define SSH_OID_TAG 06
|
||||
@@ -35,32 +33,6 @@ typedef struct ssh_gssapi_struct *ssh_gssapi;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** current state of an GSSAPI authentication */
|
||||
enum ssh_gssapi_state_e {
|
||||
SSH_GSSAPI_STATE_NONE, /* no status */
|
||||
SSH_GSSAPI_STATE_RCV_TOKEN, /* Expecting a token */
|
||||
SSH_GSSAPI_STATE_RCV_MIC, /* Expecting a MIC */
|
||||
};
|
||||
|
||||
struct ssh_gssapi_struct{
|
||||
enum ssh_gssapi_state_e state; /* current state */
|
||||
struct gss_OID_desc_struct mech; /* mechanism being elected for auth */
|
||||
gss_cred_id_t server_creds; /* credentials of server */
|
||||
gss_cred_id_t client_creds; /* creds delegated by the client */
|
||||
gss_ctx_id_t ctx; /* the authentication context */
|
||||
gss_name_t client_name; /* Identity of the client */
|
||||
char *user; /* username of client */
|
||||
char *canonic_user; /* canonic form of the client's username */
|
||||
char *service; /* name of the service */
|
||||
struct {
|
||||
gss_name_t server_name; /* identity of server */
|
||||
OM_uint32 flags; /* flags used for init context */
|
||||
gss_OID oid; /* mech being used for authentication */
|
||||
gss_cred_id_t creds; /* creds used to initialize context */
|
||||
gss_cred_id_t client_deleg_creds; /* delegated creds (const, not freeable) */
|
||||
} client;
|
||||
};
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server);
|
||||
@@ -72,15 +44,10 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response);
|
||||
|
||||
|
||||
int ssh_gssapi_init(ssh_session session);
|
||||
void ssh_gssapi_log_error(int verb, const char *msg_a, int maj_stat, int min_stat);
|
||||
int ssh_gssapi_auth_mic(ssh_session session);
|
||||
void ssh_gssapi_free(ssh_session session);
|
||||
char *ssh_gssapi_name_to_char(gss_name_t name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WITH_GSSAPI */
|
||||
#endif /* GSSAPI_H */
|
||||
|
||||
@@ -45,10 +45,6 @@ int ssh_kex_select_methods(ssh_session session);
|
||||
int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name);
|
||||
char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list);
|
||||
char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list);
|
||||
char *ssh_add_to_default_algos(enum ssh_kex_types_e algo, const char *list);
|
||||
char *ssh_remove_from_default_algos(enum ssh_kex_types_e algo,
|
||||
const char *list);
|
||||
char *ssh_prefix_default_algos(enum ssh_kex_types_e algo, const char *list);
|
||||
char **ssh_space_tokenize(const char *chain);
|
||||
int ssh_get_kex1(ssh_session session);
|
||||
char *ssh_find_matching(const char *in_d, const char *what_d);
|
||||
|
||||
@@ -29,22 +29,36 @@ struct ssh_public_key_struct {
|
||||
int type;
|
||||
const char *type_c; /* Don't free it ! it is static */
|
||||
#if defined(HAVE_LIBGCRYPT)
|
||||
gcry_sexp_t dsa_pub;
|
||||
gcry_sexp_t rsa_pub;
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
DSA *dsa_pub;
|
||||
RSA *rsa_pub;
|
||||
#else /* OPENSSL_VERSION_NUMBER */
|
||||
EVP_PKEY *key_pub;
|
||||
#endif
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
mbedtls_pk_context *rsa_pub;
|
||||
void *dsa_pub;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ssh_private_key_struct {
|
||||
int type;
|
||||
#if defined(HAVE_LIBGCRYPT)
|
||||
gcry_sexp_t dsa_priv;
|
||||
gcry_sexp_t rsa_priv;
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
DSA *dsa_priv;
|
||||
RSA *rsa_priv;
|
||||
#else
|
||||
EVP_PKEY *key_priv;
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
mbedtls_pk_context *rsa_priv;
|
||||
void *dsa_priv;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -25,14 +25,13 @@
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ec.h>
|
||||
|
||||
typedef EVP_MD_CTX* SHACTX;
|
||||
typedef EVP_MD_CTX* SHA256CTX;
|
||||
@@ -54,15 +53,8 @@ typedef EVP_MD_CTX* HMACCTX;
|
||||
#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
|
||||
#endif
|
||||
|
||||
/* Use ssh_crypto_free() to release memory allocated by bignum_bn2dec(),
|
||||
bignum_bn2hex() and other functions that use crypto-library functions that
|
||||
are documented to allocate memory that needs to be de-allocate with
|
||||
OPENSSL_free. */
|
||||
#define ssh_crypto_free(x) OPENSSL_free(x)
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
typedef BIGNUM* bignum;
|
||||
typedef const BIGNUM* const_bignum;
|
||||
typedef BN_CTX* bignum_CTX;
|
||||
@@ -119,17 +111,6 @@ typedef BN_CTX* bignum_CTX;
|
||||
#define ssh_fips_mode() false
|
||||
#endif
|
||||
|
||||
ssh_string pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p);
|
||||
int pki_key_ecgroup_name_to_nid(const char *group);
|
||||
|
||||
#if defined(WITH_PKCS11_URI)
|
||||
#if defined(WITH_PKCS11_PROVIDER)
|
||||
int pki_load_pkcs11_provider(void);
|
||||
#else
|
||||
ENGINE *pki_get_engine(void);
|
||||
#endif
|
||||
#endif /* WITH_PKCS11_PROVIDER */
|
||||
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
#endif /* LIBCRYPTO_H_ */
|
||||
|
||||
@@ -48,8 +48,6 @@ typedef gcry_md_hd_t HMACCTX;
|
||||
|
||||
#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
|
||||
|
||||
#define ssh_crypto_free(x) gcry_free(x)
|
||||
|
||||
typedef gcry_mpi_t bignum;
|
||||
typedef const struct gcry_mpi *const_bignum;
|
||||
typedef void* bignum_CTX;
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <mbedtls/cipher.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/platform.h>
|
||||
|
||||
typedef mbedtls_md_context_t *SHACTX;
|
||||
typedef mbedtls_md_context_t *SHA256CTX;
|
||||
@@ -59,8 +58,6 @@ typedef mbedtls_md_context_t *HMACCTX;
|
||||
|
||||
#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
|
||||
|
||||
#define ssh_crypto_free(x) mbedtls_free(x)
|
||||
|
||||
typedef mbedtls_mpi *bignum;
|
||||
typedef const mbedtls_mpi *const_bignum;
|
||||
typedef void* bignum_CTX;
|
||||
@@ -81,7 +78,7 @@ extern "C" {
|
||||
|
||||
bignum ssh_mbedcry_bn_new(void);
|
||||
void ssh_mbedcry_bn_free(bignum num);
|
||||
char *ssh_mbedcry_bn2num(const_bignum num, int radix);
|
||||
unsigned char *ssh_mbedcry_bn2num(const_bignum num, int radix);
|
||||
int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom);
|
||||
int ssh_mbedcry_is_bit_set(bignum num, size_t pos);
|
||||
int ssh_mbedcry_rand_range(bignum dest, bignum max);
|
||||
@@ -107,7 +104,7 @@ int ssh_mbedcry_hex2bn(bignum *dest, char *data);
|
||||
} while(0)
|
||||
#define bignum_bn2dec(num) ssh_mbedcry_bn2num(num, 10)
|
||||
#define bignum_dec2bn(data, bn) mbedtls_mpi_read_string(bn, 10, data)
|
||||
#define bignum_bn2hex(num, dest) (*dest)=(unsigned char *)ssh_mbedcry_bn2num(num, 16)
|
||||
#define bignum_bn2hex(num, dest) (*dest)=ssh_mbedcry_bn2num(num, 16)
|
||||
#define bignum_hex2bn(data, dest) ssh_mbedcry_hex2bn(dest, data)
|
||||
#define bignum_rand(rnd, bits) ssh_mbedcry_rand((rnd), (bits), 0, 1)
|
||||
#define bignum_rand_range(rnd, max) ssh_mbedcry_rand_range(rnd, max)
|
||||
@@ -129,7 +126,7 @@ int ssh_mbedcry_hex2bn(bignum *dest, char *data);
|
||||
*(dest) = bignum_new(); \
|
||||
} \
|
||||
if (*(dest) != NULL) { \
|
||||
mbedtls_mpi_copy(*(dest), orig); \
|
||||
mbedtls_mpi_copy(orig, *(dest)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-2025 by Aris Adamantiadis and the libssh team
|
||||
* Copyright (c) 2003-2023 by Aris Adamantiadis and the libssh team
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -50,13 +50,18 @@
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* Visual Studio hasn't inttypes.h so it doesn't know uint32_t */
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef int mode_t;
|
||||
#else /* _MSC_VER */
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
@@ -191,8 +196,7 @@ enum ssh_global_requests_e {
|
||||
SSH_GLOBAL_REQUEST_UNKNOWN=0,
|
||||
SSH_GLOBAL_REQUEST_TCPIP_FORWARD,
|
||||
SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD,
|
||||
SSH_GLOBAL_REQUEST_KEEPALIVE,
|
||||
SSH_GLOBAL_REQUEST_NO_MORE_SESSIONS
|
||||
SSH_GLOBAL_REQUEST_KEEPALIVE
|
||||
};
|
||||
|
||||
enum ssh_publickey_state_e {
|
||||
@@ -273,12 +277,12 @@ enum ssh_error_types_e {
|
||||
/* some types for keys */
|
||||
enum ssh_keytypes_e{
|
||||
SSH_KEYTYPE_UNKNOWN=0,
|
||||
SSH_KEYTYPE_DSS=1, /* deprecated */
|
||||
SSH_KEYTYPE_DSS=1,
|
||||
SSH_KEYTYPE_RSA,
|
||||
SSH_KEYTYPE_RSA1,
|
||||
SSH_KEYTYPE_ECDSA, /* deprecated */
|
||||
SSH_KEYTYPE_ED25519,
|
||||
SSH_KEYTYPE_DSS_CERT01, /* deprecated */
|
||||
SSH_KEYTYPE_DSS_CERT01,
|
||||
SSH_KEYTYPE_RSA_CERT01,
|
||||
SSH_KEYTYPE_ECDSA_P256,
|
||||
SSH_KEYTYPE_ECDSA_P384,
|
||||
@@ -295,8 +299,7 @@ enum ssh_keytypes_e{
|
||||
|
||||
enum ssh_keycmp_e {
|
||||
SSH_KEY_CMP_PUBLIC = 0,
|
||||
SSH_KEY_CMP_PRIVATE = 1,
|
||||
SSH_KEY_CMP_CERTIFICATE = 2,
|
||||
SSH_KEY_CMP_PRIVATE
|
||||
};
|
||||
|
||||
#define SSH_ADDRSTRLEN 46
|
||||
@@ -325,16 +328,16 @@ enum {
|
||||
/** No logging at all
|
||||
*/
|
||||
SSH_LOG_NOLOG=0,
|
||||
/** Only unrecoverable errors
|
||||
/** Only warnings
|
||||
*/
|
||||
SSH_LOG_WARNING,
|
||||
/** Information for the users
|
||||
/** High level protocol information
|
||||
*/
|
||||
SSH_LOG_PROTOCOL,
|
||||
/** Debug information, to see what is going on
|
||||
/** Lower level protocol infomations, packet level
|
||||
*/
|
||||
SSH_LOG_PACKET,
|
||||
/** Trace information and recoverable error messages
|
||||
/** Every function path
|
||||
*/
|
||||
SSH_LOG_FUNCTIONS
|
||||
};
|
||||
@@ -350,7 +353,7 @@ enum {
|
||||
|
||||
/** No logging at all */
|
||||
#define SSH_LOG_NONE 0
|
||||
/** Show only fatal warnings */
|
||||
/** Show only warnings */
|
||||
#define SSH_LOG_WARN 1
|
||||
/** Get some information what's going on */
|
||||
#define SSH_LOG_INFO 2
|
||||
@@ -361,64 +364,50 @@ enum {
|
||||
|
||||
/** @} */
|
||||
|
||||
enum ssh_control_master_options_e {
|
||||
SSH_CONTROL_MASTER_NO,
|
||||
SSH_CONTROL_MASTER_AUTO,
|
||||
SSH_CONTROL_MASTER_YES,
|
||||
SSH_CONTROL_MASTER_ASK,
|
||||
SSH_CONTROL_MASTER_AUTOASK
|
||||
};
|
||||
|
||||
enum ssh_options_e {
|
||||
SSH_OPTIONS_HOST,
|
||||
SSH_OPTIONS_PORT,
|
||||
SSH_OPTIONS_PORT_STR,
|
||||
SSH_OPTIONS_FD,
|
||||
SSH_OPTIONS_USER,
|
||||
SSH_OPTIONS_SSH_DIR,
|
||||
SSH_OPTIONS_IDENTITY,
|
||||
SSH_OPTIONS_ADD_IDENTITY,
|
||||
SSH_OPTIONS_KNOWNHOSTS,
|
||||
SSH_OPTIONS_TIMEOUT,
|
||||
SSH_OPTIONS_TIMEOUT_USEC,
|
||||
SSH_OPTIONS_SSH1,
|
||||
SSH_OPTIONS_SSH2,
|
||||
SSH_OPTIONS_LOG_VERBOSITY,
|
||||
SSH_OPTIONS_LOG_VERBOSITY_STR,
|
||||
SSH_OPTIONS_CIPHERS_C_S,
|
||||
SSH_OPTIONS_CIPHERS_S_C,
|
||||
SSH_OPTIONS_COMPRESSION_C_S,
|
||||
SSH_OPTIONS_COMPRESSION_S_C,
|
||||
SSH_OPTIONS_PROXYCOMMAND,
|
||||
SSH_OPTIONS_BINDADDR,
|
||||
SSH_OPTIONS_STRICTHOSTKEYCHECK,
|
||||
SSH_OPTIONS_COMPRESSION,
|
||||
SSH_OPTIONS_COMPRESSION_LEVEL,
|
||||
SSH_OPTIONS_KEY_EXCHANGE,
|
||||
SSH_OPTIONS_HOSTKEYS,
|
||||
SSH_OPTIONS_GSSAPI_SERVER_IDENTITY,
|
||||
SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY,
|
||||
SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS,
|
||||
SSH_OPTIONS_HMAC_C_S,
|
||||
SSH_OPTIONS_HMAC_S_C,
|
||||
SSH_OPTIONS_PASSWORD_AUTH,
|
||||
SSH_OPTIONS_PUBKEY_AUTH,
|
||||
SSH_OPTIONS_KBDINT_AUTH,
|
||||
SSH_OPTIONS_GSSAPI_AUTH,
|
||||
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
|
||||
SSH_OPTIONS_NODELAY,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
SSH_OPTIONS_PROCESS_CONFIG,
|
||||
SSH_OPTIONS_REKEY_DATA,
|
||||
SSH_OPTIONS_REKEY_TIME,
|
||||
SSH_OPTIONS_RSA_MIN_SIZE,
|
||||
SSH_OPTIONS_IDENTITY_AGENT,
|
||||
SSH_OPTIONS_IDENTITIES_ONLY,
|
||||
SSH_OPTIONS_CONTROL_MASTER,
|
||||
SSH_OPTIONS_CONTROL_PATH,
|
||||
SSH_OPTIONS_CERTIFICATE,
|
||||
SSH_OPTIONS_PROXYJUMP,
|
||||
SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND,
|
||||
SSH_OPTIONS_HOST,
|
||||
SSH_OPTIONS_PORT,
|
||||
SSH_OPTIONS_PORT_STR,
|
||||
SSH_OPTIONS_FD,
|
||||
SSH_OPTIONS_USER,
|
||||
SSH_OPTIONS_SSH_DIR,
|
||||
SSH_OPTIONS_IDENTITY,
|
||||
SSH_OPTIONS_ADD_IDENTITY,
|
||||
SSH_OPTIONS_KNOWNHOSTS,
|
||||
SSH_OPTIONS_TIMEOUT,
|
||||
SSH_OPTIONS_TIMEOUT_USEC,
|
||||
SSH_OPTIONS_SSH1,
|
||||
SSH_OPTIONS_SSH2,
|
||||
SSH_OPTIONS_LOG_VERBOSITY,
|
||||
SSH_OPTIONS_LOG_VERBOSITY_STR,
|
||||
SSH_OPTIONS_CIPHERS_C_S,
|
||||
SSH_OPTIONS_CIPHERS_S_C,
|
||||
SSH_OPTIONS_COMPRESSION_C_S,
|
||||
SSH_OPTIONS_COMPRESSION_S_C,
|
||||
SSH_OPTIONS_PROXYCOMMAND,
|
||||
SSH_OPTIONS_BINDADDR,
|
||||
SSH_OPTIONS_STRICTHOSTKEYCHECK,
|
||||
SSH_OPTIONS_COMPRESSION,
|
||||
SSH_OPTIONS_COMPRESSION_LEVEL,
|
||||
SSH_OPTIONS_KEY_EXCHANGE,
|
||||
SSH_OPTIONS_HOSTKEYS,
|
||||
SSH_OPTIONS_GSSAPI_SERVER_IDENTITY,
|
||||
SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY,
|
||||
SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS,
|
||||
SSH_OPTIONS_HMAC_C_S,
|
||||
SSH_OPTIONS_HMAC_S_C,
|
||||
SSH_OPTIONS_PASSWORD_AUTH,
|
||||
SSH_OPTIONS_PUBKEY_AUTH,
|
||||
SSH_OPTIONS_KBDINT_AUTH,
|
||||
SSH_OPTIONS_GSSAPI_AUTH,
|
||||
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
|
||||
SSH_OPTIONS_NODELAY,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
SSH_OPTIONS_PROCESS_CONFIG,
|
||||
SSH_OPTIONS_REKEY_DATA,
|
||||
SSH_OPTIONS_REKEY_TIME,
|
||||
SSH_OPTIONS_RSA_MIN_SIZE,
|
||||
SSH_OPTIONS_IDENTITY_AGENT,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -456,19 +445,8 @@ LIBSSH_API int ssh_blocking_flush(ssh_session session, int timeout);
|
||||
LIBSSH_API ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||
LIBSSH_API int ssh_channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||
LIBSSH_API int ssh_channel_close(ssh_channel channel);
|
||||
#define SSH_CHANNEL_FREE(x) \
|
||||
do { \
|
||||
if ((x) != NULL) { \
|
||||
ssh_channel_free(x); \
|
||||
(x) = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
LIBSSH_API void ssh_channel_free(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_get_exit_state(ssh_channel channel,
|
||||
uint32_t *pexit_code,
|
||||
char **pexit_signal,
|
||||
int *pcore_dumped);
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_channel_get_exit_status(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_get_exit_status(ssh_channel channel);
|
||||
LIBSSH_API ssh_session ssh_channel_get_session(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_is_closed(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_is_eof(ssh_channel channel);
|
||||
@@ -492,8 +470,6 @@ LIBSSH_API int ssh_channel_request_exec(ssh_channel channel, const char *cmd);
|
||||
LIBSSH_API int ssh_channel_request_pty(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_request_pty_size(ssh_channel channel, const char *term,
|
||||
int cols, int rows);
|
||||
LIBSSH_API int ssh_channel_request_pty_size_modes(ssh_channel channel, const char *term,
|
||||
int cols, int rows, const unsigned char* modes, size_t modes_len);
|
||||
LIBSSH_API int ssh_channel_request_shell(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_request_send_signal(ssh_channel channel, const char *signum);
|
||||
LIBSSH_API int ssh_channel_request_send_break(ssh_channel channel, uint32_t length);
|
||||
@@ -557,7 +533,6 @@ LIBSSH_API socket_t ssh_get_fd(ssh_session session);
|
||||
LIBSSH_API char *ssh_get_hexa(const unsigned char *what, size_t len);
|
||||
LIBSSH_API char *ssh_get_issue_banner(ssh_session session);
|
||||
LIBSSH_API int ssh_get_openssh_version(ssh_session session);
|
||||
LIBSSH_API int ssh_request_no_more_sessions(ssh_session session);
|
||||
|
||||
LIBSSH_API int ssh_get_server_publickey(ssh_session session, ssh_key *key);
|
||||
|
||||
@@ -701,12 +676,6 @@ typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
||||
|
||||
/** @} */
|
||||
|
||||
enum ssh_file_format_e {
|
||||
SSH_FILE_FORMAT_DEFAULT = 0,
|
||||
SSH_FILE_FORMAT_OPENSSH,
|
||||
SSH_FILE_FORMAT_PEM,
|
||||
};
|
||||
|
||||
LIBSSH_API ssh_key ssh_key_new(void);
|
||||
#define SSH_KEY_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0)
|
||||
@@ -733,13 +702,6 @@ LIBSSH_API int ssh_pki_export_privkey_base64(const ssh_key privkey,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
char **b64_key);
|
||||
LIBSSH_API int
|
||||
ssh_pki_export_privkey_base64_format(const ssh_key privkey,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
char **b64_key,
|
||||
enum ssh_file_format_e format);
|
||||
LIBSSH_API int ssh_pki_import_privkey_file(const char *filename,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
@@ -750,13 +712,6 @@ LIBSSH_API int ssh_pki_export_privkey_file(const ssh_key privkey,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
const char *filename);
|
||||
LIBSSH_API int
|
||||
ssh_pki_export_privkey_file_format(const ssh_key privkey,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
const char *filename,
|
||||
enum ssh_file_format_e format);
|
||||
|
||||
LIBSSH_API int ssh_pki_copy_cert_to_privkey(const ssh_key cert_key,
|
||||
ssh_key privkey);
|
||||
@@ -812,8 +767,10 @@ LIBSSH_API int ssh_userauth_try_publickey(ssh_session session,
|
||||
LIBSSH_API int ssh_userauth_publickey(ssh_session session,
|
||||
const char *username,
|
||||
const ssh_key privkey);
|
||||
#ifndef _WIN32
|
||||
LIBSSH_API int ssh_userauth_agent(ssh_session session,
|
||||
const char *username);
|
||||
#endif
|
||||
LIBSSH_API int ssh_userauth_publickey_auto_get_current_identity(ssh_session session,
|
||||
char** value);
|
||||
LIBSSH_API int ssh_userauth_publickey_auto(ssh_session session,
|
||||
|
||||
@@ -498,22 +498,8 @@ public:
|
||||
return_throwable;
|
||||
}
|
||||
|
||||
/*
|
||||
* @deprecated Please use getExitState()
|
||||
*/
|
||||
int getExitStatus() {
|
||||
uint32_t exit_status = (uint32_t)-1;
|
||||
ssh_channel_get_exit_state(channel, &exit_status, NULL, NULL);
|
||||
return exit_status;
|
||||
}
|
||||
void_throwable getExitState(uint32_t & pexit_code,
|
||||
char **pexit_signal,
|
||||
int & pcore_dumped) {
|
||||
ssh_throw(ssh_channel_get_exit_state(channel,
|
||||
&pexit_code,
|
||||
pexit_signal,
|
||||
&pcore_dumped));
|
||||
return_throwable;
|
||||
int getExitStatus(){
|
||||
return ssh_channel_get_exit_status(channel);
|
||||
}
|
||||
Session &getSession(){
|
||||
return *session;
|
||||
@@ -601,12 +587,9 @@ public:
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0,
|
||||
const unsigned char* modes=NULL, size_t modes_len=0){
|
||||
void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0){
|
||||
int err;
|
||||
if(term != NULL && cols != 0 && rows != 0 && modes != NULL)
|
||||
err=ssh_channel_request_pty_size_modes(channel,term,cols,rows,modes,modes_len);
|
||||
else if(term != NULL && cols != 0 && rows != 0)
|
||||
if(term != NULL && cols != 0 && rows != 0)
|
||||
err=ssh_channel_request_pty_size(channel,term,cols,rows);
|
||||
else
|
||||
err=ssh_channel_request_pty(channel);
|
||||
|
||||
@@ -21,22 +21,6 @@
|
||||
#ifndef MISC_H_
|
||||
#define MISC_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# ifndef _SSIZE_T_DEFINED
|
||||
# undef ssize_t
|
||||
# include <BaseTsd.h>
|
||||
typedef _W64 SSIZE_T ssize_t;
|
||||
# define _SSIZE_T_DEFINED
|
||||
# endif /* _SSIZE_T_DEFINED */
|
||||
# endif /* _MSC_VER */
|
||||
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -66,12 +50,6 @@ struct ssh_iterator {
|
||||
const void *data;
|
||||
};
|
||||
|
||||
struct ssh_jump_info_struct {
|
||||
char *hostname;
|
||||
char *username;
|
||||
int port;
|
||||
};
|
||||
|
||||
struct ssh_timestamp {
|
||||
long seconds;
|
||||
long useconds;
|
||||
@@ -107,14 +85,13 @@ const void *_ssh_list_pop_head(struct ssh_list *list);
|
||||
#define ssh_list_pop_head(type, ssh_list)\
|
||||
((type)_ssh_list_pop_head(ssh_list))
|
||||
|
||||
#define SSH_LIST_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_list_free(x); (x) = NULL; } } while(0)
|
||||
|
||||
int ssh_make_milliseconds(unsigned long sec, unsigned long usec);
|
||||
void ssh_timestamp_init(struct ssh_timestamp *ts);
|
||||
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout);
|
||||
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
|
||||
|
||||
int ssh_match_group(const char *group, const char *object);
|
||||
|
||||
void uint64_inc(unsigned char *counter);
|
||||
|
||||
void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len);
|
||||
@@ -127,14 +104,7 @@ int ssh_tmpname(char *name);
|
||||
|
||||
char *ssh_strreplace(const char *src, const char *pattern, const char *repl);
|
||||
|
||||
ssize_t ssh_readn(int fd, void *buf, size_t nbytes);
|
||||
ssize_t ssh_writen(int fd, const void *buf, size_t nbytes);
|
||||
|
||||
int ssh_check_hostname_syntax(const char *hostname);
|
||||
int ssh_check_username_syntax(const char *username);
|
||||
|
||||
void ssh_proxyjumps_free(struct ssh_list *proxy_jump_list);
|
||||
bool ssh_libssh_proxy_jumps(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -29,12 +29,9 @@ int ssh_config_parse_file(ssh_session session, const char *filename);
|
||||
int ssh_config_parse_string(ssh_session session, const char *input);
|
||||
int ssh_options_set_algo(ssh_session session,
|
||||
enum ssh_kex_types_e algo,
|
||||
const char *list,
|
||||
char **place);
|
||||
const char *list);
|
||||
int ssh_options_apply(ssh_session session);
|
||||
|
||||
char *ssh_options_get_algo(ssh_session session, enum ssh_kex_types_e algo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -58,7 +58,6 @@ extern "C" {
|
||||
SSH_PACKET_CALLBACK(ssh_packet_unimplemented);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_ignore_callback);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_debug_callback);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_dh_reply);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_newkeys);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_service_accept);
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
#include "libssh/crypto.h"
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
#if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ED25519)
|
||||
/* If using OpenSSL implementation, define the signature length which would be
|
||||
* defined in libssh/ed25519.h otherwise */
|
||||
#define ED25519_SIG_LEN 64
|
||||
@@ -57,24 +57,40 @@ struct ssh_key_struct {
|
||||
const char *type_c; /* Don't free it ! it is static */
|
||||
int ecdsa_nid;
|
||||
#if defined(HAVE_LIBGCRYPT)
|
||||
gcry_sexp_t dsa;
|
||||
gcry_sexp_t rsa;
|
||||
gcry_sexp_t ecdsa;
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
mbedtls_pk_context *pk;
|
||||
mbedtls_pk_context *rsa;
|
||||
mbedtls_ecdsa_context *ecdsa;
|
||||
void *dsa;
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
DSA *dsa;
|
||||
RSA *rsa;
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys
|
||||
* https://github.com/openssl/openssl/pull/16624
|
||||
* Move into the #if above
|
||||
*/
|
||||
# if defined(HAVE_OPENSSL_ECC)
|
||||
EC_KEY *ecdsa;
|
||||
# else
|
||||
void *ecdsa;
|
||||
# endif /* HAVE_OPENSSL_EC_H */
|
||||
/* This holds either ENGINE key for PKCS#11 support or just key in
|
||||
* high-level format */
|
||||
* high-level format required by OpenSSL 3.0 */
|
||||
EVP_PKEY *key;
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ED25519)
|
||||
uint8_t *ed25519_pubkey;
|
||||
uint8_t *ed25519_privkey;
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#ifndef HAVE_LIBCRYPTO
|
||||
#else
|
||||
ed25519_pubkey *ed25519_pubkey;
|
||||
ed25519_privkey *ed25519_privkey;
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
#endif
|
||||
ssh_string sk_application;
|
||||
ssh_buffer cert;
|
||||
void *cert;
|
||||
enum ssh_keytypes_e cert_type;
|
||||
};
|
||||
|
||||
@@ -83,15 +99,16 @@ struct ssh_signature_struct {
|
||||
enum ssh_digest_e hash_type;
|
||||
const char *type_c;
|
||||
#if defined(HAVE_LIBGCRYPT)
|
||||
gcry_sexp_t dsa_sig;
|
||||
gcry_sexp_t rsa_sig;
|
||||
gcry_sexp_t ecdsa_sig;
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
ssh_string rsa_sig;
|
||||
struct mbedtls_ecdsa_sig ecdsa_sig;
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#ifndef HAVE_LIBCRYPTO
|
||||
#if !defined(HAVE_LIBCRYPTO) || !defined(HAVE_OPENSSL_ED25519)
|
||||
ed25519_signature *ed25519_sig;
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#endif
|
||||
ssh_string raw_sig;
|
||||
|
||||
/* Security Key specific additions */
|
||||
@@ -121,11 +138,12 @@ enum ssh_digest_e ssh_key_hash_from_name(const char *name);
|
||||
((t) >= SSH_KEYTYPE_ECDSA_P256 && (t) <= SSH_KEYTYPE_ECDSA_P521)
|
||||
|
||||
#define is_cert_type(kt)\
|
||||
((kt) == SSH_KEYTYPE_RSA_CERT01 ||\
|
||||
(kt) == SSH_KEYTYPE_SK_ECDSA_CERT01 ||\
|
||||
(kt) == SSH_KEYTYPE_SK_ED25519_CERT01 ||\
|
||||
((kt) >= SSH_KEYTYPE_ECDSA_P256_CERT01 &&\
|
||||
(kt) <= SSH_KEYTYPE_ED25519_CERT01))
|
||||
((kt) == SSH_KEYTYPE_DSS_CERT01 ||\
|
||||
(kt) == SSH_KEYTYPE_RSA_CERT01 ||\
|
||||
(kt) == SSH_KEYTYPE_SK_ECDSA_CERT01 ||\
|
||||
(kt) == SSH_KEYTYPE_SK_ED25519_CERT01 ||\
|
||||
((kt) >= SSH_KEYTYPE_ECDSA_P256_CERT01 &&\
|
||||
(kt) <= SSH_KEYTYPE_ED25519_CERT01))
|
||||
|
||||
/* SSH Signature Functions */
|
||||
ssh_signature ssh_signature_new(void);
|
||||
@@ -153,10 +171,6 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
|
||||
int ssh_pki_import_cert_blob(const ssh_string cert_blob,
|
||||
ssh_key *pkey);
|
||||
|
||||
/* SSH Private Key Functions */
|
||||
int ssh_pki_export_privkey_blob(const ssh_key key,
|
||||
ssh_string *pblob);
|
||||
|
||||
|
||||
/* SSH Signing Functions */
|
||||
ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf,
|
||||
|
||||
@@ -38,6 +38,8 @@ int bcrypt_pbkdf(const char *pass,
|
||||
|
||||
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
|
||||
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
|
||||
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
|
||||
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
|
||||
#define ECDSA_HEADER_BEGIN "-----BEGIN EC PRIVATE KEY-----"
|
||||
#define ECDSA_HEADER_END "-----END EC PRIVATE KEY-----"
|
||||
#define OPENSSH_HEADER_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----"
|
||||
@@ -63,6 +65,7 @@ enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
|
||||
/* SSH Key Functions */
|
||||
ssh_key pki_key_dup(const ssh_key key, int demote);
|
||||
int pki_key_generate_rsa(ssh_key key, int parameter);
|
||||
int pki_key_generate_dss(ssh_key key, int parameter);
|
||||
int pki_key_generate_ecdsa(ssh_key key, int parameter);
|
||||
int pki_key_generate_ed25519(ssh_key key);
|
||||
|
||||
@@ -88,13 +91,24 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
ssh_key *pkey);
|
||||
|
||||
/* SSH Public Key Functions */
|
||||
int pki_pubkey_build_dss(ssh_key key,
|
||||
ssh_string p,
|
||||
ssh_string q,
|
||||
ssh_string g,
|
||||
ssh_string pubkey);
|
||||
int pki_pubkey_build_rsa(ssh_key key,
|
||||
ssh_string e,
|
||||
ssh_string n);
|
||||
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e);
|
||||
ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type);
|
||||
ssh_string pki_publickey_to_blob(const ssh_key key);
|
||||
|
||||
/* SSH Private Key Functions */
|
||||
int pki_privkey_build_dss(ssh_key key,
|
||||
ssh_string p,
|
||||
ssh_string q,
|
||||
ssh_string g,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey);
|
||||
int pki_privkey_build_rsa(ssh_key key,
|
||||
ssh_string n,
|
||||
ssh_string e,
|
||||
@@ -106,6 +120,7 @@ int pki_privkey_build_ecdsa(ssh_key key,
|
||||
int nid,
|
||||
ssh_string e,
|
||||
ssh_string exp);
|
||||
ssh_string pki_publickey_to_blob(const ssh_key key);
|
||||
|
||||
/* SSH Signature Functions */
|
||||
ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
@@ -131,18 +146,15 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type);
|
||||
#ifndef HAVE_LIBCRYPTO
|
||||
int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig,
|
||||
const unsigned char *hash, size_t hlen);
|
||||
int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig,
|
||||
const unsigned char *hash, size_t hlen);
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
int pki_ed25519_key_cmp(const ssh_key k1,
|
||||
const ssh_key k2,
|
||||
enum ssh_keycmp_e what);
|
||||
int pki_ed25519_key_dup(ssh_key new_key, const ssh_key key);
|
||||
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key);
|
||||
int pki_ed25519_private_key_to_blob(ssh_buffer buffer, const ssh_key privkey);
|
||||
ssh_string pki_ed25519_signature_to_blob(ssh_signature sig);
|
||||
int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob);
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
|
||||
@@ -47,10 +47,6 @@
|
||||
# endif
|
||||
#endif /* !defined(HAVE_STRTOULL) */
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -166,20 +162,6 @@ int ssh_gettimeofday(struct timeval *__p, void *__t);
|
||||
|
||||
#define _XCLOSESOCKET closesocket
|
||||
|
||||
# ifdef HAVE_IO_H
|
||||
# include <io.h>
|
||||
# undef open
|
||||
# define open _open
|
||||
# undef close
|
||||
# define close _close
|
||||
# undef read
|
||||
# define read _read
|
||||
# undef write
|
||||
# define write _write
|
||||
# undef unlink
|
||||
# define unlink _unlink
|
||||
# endif /* HAVE_IO_H */
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
#include <unistd.h>
|
||||
@@ -274,10 +256,6 @@ void ssh_log_common(struct ssh_common_struct *common,
|
||||
const char *function,
|
||||
const char *format, ...) PRINTF_ATTRIBUTE(4, 5);
|
||||
|
||||
void _ssh_remove_legacy_log_cb(void);
|
||||
|
||||
/* log.c */
|
||||
void _ssh_reset_log_cb(void);
|
||||
|
||||
/* ERROR HANDLING */
|
||||
|
||||
@@ -312,7 +290,6 @@ int ssh_auth_reply_success(ssh_session session, int partial);
|
||||
/* client.c */
|
||||
|
||||
int ssh_send_banner(ssh_session session, int is_server);
|
||||
void ssh_session_socket_close(ssh_session session);
|
||||
|
||||
/* connect.c */
|
||||
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
@@ -330,12 +307,6 @@ int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
|
||||
int match_pattern_list(const char *string, const char *pattern,
|
||||
size_t len, int dolower);
|
||||
int match_hostname(const char *host, const char *pattern, unsigned int len);
|
||||
#ifndef _WIN32
|
||||
int match_cidr_address_list(const char *address,
|
||||
const char *addrlist,
|
||||
int sa_family);
|
||||
#endif
|
||||
int match_group(const char *group, const char *object);
|
||||
|
||||
/* connector.c */
|
||||
int ssh_connector_set_event(ssh_connector connector, ssh_event event);
|
||||
@@ -384,7 +355,6 @@ void explicit_bzero(void *s, size_t n);
|
||||
*/
|
||||
#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
|
||||
|
||||
#ifndef __VA_NARG__
|
||||
/**
|
||||
* Get the argument count of variadic arguments
|
||||
*/
|
||||
@@ -416,7 +386,6 @@ void explicit_bzero(void *s, size_t n);
|
||||
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
|
||||
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
||||
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
#endif
|
||||
|
||||
#define CLOSE_SOCKET(s) do { if ((s) != SSH_INVALID_SOCKET) { _XCLOSESOCKET(s); (s) = SSH_INVALID_SOCKET;} } while(0)
|
||||
|
||||
@@ -469,10 +438,6 @@ bool is_ssh_initialized(void);
|
||||
#define SSH_ERRNO_MSG_MAX 1024
|
||||
char *ssh_strerror(int err_num, char *buf, size_t buflen);
|
||||
|
||||
/** 55 defined options (5 bytes each) + terminator */
|
||||
#define SSH_TTY_MODES_MAX_BUFSIZE (55 * 5 + 1)
|
||||
int encode_current_tty_opts(unsigned char *buf, size_t buflen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -36,29 +36,28 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
enum ssh_bind_options_e {
|
||||
SSH_BIND_OPTIONS_BINDADDR,
|
||||
SSH_BIND_OPTIONS_BINDPORT,
|
||||
SSH_BIND_OPTIONS_BINDPORT_STR,
|
||||
SSH_BIND_OPTIONS_HOSTKEY,
|
||||
SSH_BIND_OPTIONS_DSAKEY, /* deprecated */
|
||||
SSH_BIND_OPTIONS_RSAKEY, /* deprecated */
|
||||
SSH_BIND_OPTIONS_BANNER,
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY,
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
|
||||
SSH_BIND_OPTIONS_ECDSAKEY, /* deprecated */
|
||||
SSH_BIND_OPTIONS_IMPORT_KEY,
|
||||
SSH_BIND_OPTIONS_KEY_EXCHANGE,
|
||||
SSH_BIND_OPTIONS_CIPHERS_C_S,
|
||||
SSH_BIND_OPTIONS_CIPHERS_S_C,
|
||||
SSH_BIND_OPTIONS_HMAC_C_S,
|
||||
SSH_BIND_OPTIONS_HMAC_S_C,
|
||||
SSH_BIND_OPTIONS_CONFIG_DIR,
|
||||
SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES,
|
||||
SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS,
|
||||
SSH_BIND_OPTIONS_PROCESS_CONFIG,
|
||||
SSH_BIND_OPTIONS_MODULI,
|
||||
SSH_BIND_OPTIONS_RSA_MIN_SIZE,
|
||||
SSH_BIND_OPTIONS_IMPORT_KEY_STR,
|
||||
SSH_BIND_OPTIONS_BINDADDR,
|
||||
SSH_BIND_OPTIONS_BINDPORT,
|
||||
SSH_BIND_OPTIONS_BINDPORT_STR,
|
||||
SSH_BIND_OPTIONS_HOSTKEY,
|
||||
SSH_BIND_OPTIONS_DSAKEY,
|
||||
SSH_BIND_OPTIONS_RSAKEY,
|
||||
SSH_BIND_OPTIONS_BANNER,
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY,
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
|
||||
SSH_BIND_OPTIONS_ECDSAKEY,
|
||||
SSH_BIND_OPTIONS_IMPORT_KEY,
|
||||
SSH_BIND_OPTIONS_KEY_EXCHANGE,
|
||||
SSH_BIND_OPTIONS_CIPHERS_C_S,
|
||||
SSH_BIND_OPTIONS_CIPHERS_S_C,
|
||||
SSH_BIND_OPTIONS_HMAC_C_S,
|
||||
SSH_BIND_OPTIONS_HMAC_S_C,
|
||||
SSH_BIND_OPTIONS_CONFIG_DIR,
|
||||
SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES,
|
||||
SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS,
|
||||
SSH_BIND_OPTIONS_PROCESS_CONFIG,
|
||||
SSH_BIND_OPTIONS_MODULI,
|
||||
SSH_BIND_OPTIONS_RSA_MIN_SIZE,
|
||||
};
|
||||
|
||||
typedef struct ssh_bind_struct* ssh_bind;
|
||||
@@ -223,9 +222,6 @@ LIBSSH_API int ssh_server_init_kex(ssh_session session);
|
||||
/**
|
||||
* @brief Free a ssh servers bind.
|
||||
*
|
||||
* Note that this will also free options that have been set on the bind,
|
||||
* including keys set with SSH_BIND_OPTIONS_IMPORT_KEY.
|
||||
*
|
||||
* @param ssh_bind_o The ssh server bind to free.
|
||||
*/
|
||||
LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o);
|
||||
@@ -296,7 +292,7 @@ LIBSSH_API const char *ssh_message_auth_user(ssh_message msg);
|
||||
*
|
||||
* @param[in] msg The message to get the password from.
|
||||
*
|
||||
* @return The password or NULL if an error occurred.
|
||||
* @return The username or NULL if an error occurred.
|
||||
*
|
||||
* @see ssh_message_get()
|
||||
* @see ssh_message_type()
|
||||
|
||||
@@ -71,18 +71,15 @@ enum ssh_pending_call_e {
|
||||
};
|
||||
|
||||
/* libssh calls may block an undefined amount of time */
|
||||
#define SSH_SESSION_FLAG_BLOCKING 0x0001
|
||||
#define SSH_SESSION_FLAG_BLOCKING 1
|
||||
|
||||
/* Client successfully authenticated */
|
||||
#define SSH_SESSION_FLAG_AUTHENTICATED 0x0002
|
||||
|
||||
/* Do not accept new session channels (no-more-sessions@openssh.com) */
|
||||
#define SSH_SESSION_FLAG_NO_MORE_SESSIONS 0x0004
|
||||
#define SSH_SESSION_FLAG_AUTHENTICATED 2
|
||||
|
||||
/* The KEXINIT message can be sent first by either of the parties so this flag
|
||||
* indicates that the message was already sent to make sure it is sent and avoid
|
||||
* sending it twice during key exchange to simplify the state machine. */
|
||||
#define SSH_SESSION_FLAG_KEXINIT_SENT 0x0008
|
||||
#define SSH_SESSION_FLAG_KEXINIT_SENT 4
|
||||
|
||||
/* The current SSH2 session implements the "strict KEX" feature and should behave
|
||||
* differently on SSH2_MSG_NEWKEYS. */
|
||||
@@ -112,7 +109,6 @@ enum ssh_pending_call_e {
|
||||
#define SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS 0x2
|
||||
#define SSH_OPT_EXP_FLAG_PROXYCOMMAND 0x4
|
||||
#define SSH_OPT_EXP_FLAG_IDENTITY 0x8
|
||||
#define SSH_OPT_EXP_FLAG_CONTROL_PATH 0x10
|
||||
|
||||
/* extensions flags */
|
||||
/* negotiation enabled */
|
||||
@@ -140,7 +136,6 @@ struct ssh_session_struct {
|
||||
uint32_t send_seq;
|
||||
uint32_t recv_seq;
|
||||
struct ssh_timestamp last_rekey_time;
|
||||
bool proxy_root;
|
||||
|
||||
int connected;
|
||||
/* !=0 when the user got a session handle */
|
||||
@@ -213,6 +208,7 @@ struct ssh_session_struct {
|
||||
/* server host keys */
|
||||
struct {
|
||||
ssh_key rsa_key;
|
||||
ssh_key dsa_key;
|
||||
ssh_key ecdsa_key;
|
||||
ssh_key ed25519_key;
|
||||
/* The type of host key wanted by client */
|
||||
@@ -238,10 +234,6 @@ struct ssh_session_struct {
|
||||
struct {
|
||||
struct ssh_list *identity;
|
||||
struct ssh_list *identity_non_exp;
|
||||
struct ssh_list *certificate;
|
||||
struct ssh_list *certificate_non_exp;
|
||||
struct ssh_list *proxy_jumps;
|
||||
struct ssh_list *proxy_jumps_user_cb;
|
||||
char *username;
|
||||
char *host;
|
||||
char *bindaddr; /* bind the client to an ip addr */
|
||||
@@ -251,6 +243,8 @@ struct ssh_session_struct {
|
||||
char *wanted_methods[SSH_KEX_METHODS];
|
||||
char *pubkey_accepted_types;
|
||||
char *ProxyCommand;
|
||||
char *custombanner;
|
||||
char *moduli_file;
|
||||
char *agent_socket;
|
||||
unsigned long timeout; /* seconds */
|
||||
unsigned long timeout_usec;
|
||||
@@ -269,17 +263,7 @@ struct ssh_session_struct {
|
||||
uint64_t rekey_data;
|
||||
uint32_t rekey_time;
|
||||
int rsa_min_size;
|
||||
bool identities_only;
|
||||
int control_master;
|
||||
char *control_path;
|
||||
} opts;
|
||||
|
||||
/* server options */
|
||||
struct {
|
||||
char *custombanner;
|
||||
char *moduli_file;
|
||||
} server_opts;
|
||||
|
||||
/* counters */
|
||||
ssh_counter socket_counter;
|
||||
ssh_counter raw_counter;
|
||||
|
||||
@@ -77,8 +77,6 @@ typedef struct sftp_request_queue_struct* sftp_request_queue;
|
||||
typedef struct sftp_session_struct* sftp_session;
|
||||
typedef struct sftp_status_message_struct* sftp_status_message;
|
||||
typedef struct sftp_statvfs_struct* sftp_statvfs_t;
|
||||
typedef struct sftp_limits_struct* sftp_limits_t;
|
||||
typedef struct sftp_aio_struct* sftp_aio;
|
||||
|
||||
struct sftp_session_struct {
|
||||
ssh_session session;
|
||||
@@ -92,7 +90,6 @@ struct sftp_session_struct {
|
||||
void **handles;
|
||||
sftp_ext ext;
|
||||
sftp_packet read_packet;
|
||||
sftp_limits_t limits;
|
||||
};
|
||||
|
||||
struct sftp_packet_struct {
|
||||
@@ -203,16 +200,6 @@ struct sftp_statvfs_struct {
|
||||
uint64_t f_namemax; /** maximum filename length */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SFTP limits structure.
|
||||
*/
|
||||
struct sftp_limits_struct {
|
||||
uint64_t max_packet_length; /** maximum number of bytes in a single sftp packet */
|
||||
uint64_t max_read_length; /** maximum length in a SSH_FXP_READ packet */
|
||||
uint64_t max_write_length; /** maximum length in a SSH_FXP_WRITE packet */
|
||||
uint64_t max_open_handles; /** maximum number of active handles allowed by server */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new sftp session.
|
||||
*
|
||||
@@ -489,18 +476,13 @@ LIBSSH_API void sftp_file_set_blocking(sftp_file handle);
|
||||
/**
|
||||
* @brief Read from a file using an opened sftp file handle.
|
||||
*
|
||||
* This function caps the length a user is allowed to read from an sftp file.
|
||||
*
|
||||
* The value used for the cap is same as the value of the max_read_length
|
||||
* field of the sftp_limits_t returned by sftp_limits().
|
||||
*
|
||||
* @param file The opened sftp file handle to be read from.
|
||||
*
|
||||
* @param buf Pointer to buffer to receive read data.
|
||||
*
|
||||
* @param count Size of the buffer in bytes.
|
||||
*
|
||||
* @return Number of bytes read, < 0 on error with ssh and sftp
|
||||
* @return Number of bytes written, < 0 on error with ssh and sftp
|
||||
* error set.
|
||||
*
|
||||
* @see sftp_get_error()
|
||||
@@ -538,8 +520,7 @@ LIBSSH_API ssize_t sftp_read(sftp_file file, void *buf, size_t count);
|
||||
* @see sftp_async_read()
|
||||
* @see sftp_open()
|
||||
*/
|
||||
SSH_DEPRECATED LIBSSH_API int sftp_async_read_begin(sftp_file file,
|
||||
uint32_t len);
|
||||
LIBSSH_API int sftp_async_read_begin(sftp_file file, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief Wait for an asynchronous read to complete and save the data.
|
||||
@@ -564,19 +545,11 @@ SSH_DEPRECATED LIBSSH_API int sftp_async_read_begin(sftp_file file,
|
||||
*
|
||||
* @see sftp_async_read_begin()
|
||||
*/
|
||||
SSH_DEPRECATED LIBSSH_API int sftp_async_read(sftp_file file,
|
||||
void *data,
|
||||
uint32_t len,
|
||||
uint32_t id);
|
||||
LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Write to a file using an opened sftp file handle.
|
||||
*
|
||||
* This function caps the length a user is allowed to write to an sftp file.
|
||||
*
|
||||
* The value used for the cap is same as the value of the max_write_length
|
||||
* field of the sftp_limits_t returned by sftp_limits().
|
||||
*
|
||||
* @param file Open sftp file handle to write to.
|
||||
*
|
||||
* @param buf Pointer to buffer to write data.
|
||||
@@ -592,229 +565,6 @@ SSH_DEPRECATED LIBSSH_API int sftp_async_read(sftp_file file,
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_write(sftp_file file, const void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory corresponding to a sftp aio handle.
|
||||
*
|
||||
* This function deallocates memory corresponding to the aio handle returned
|
||||
* by the sftp_aio_begin_*() functions. Users can use this function to free
|
||||
* memory corresponding to an aio handle for an outstanding async i/o request
|
||||
* on encountering some error.
|
||||
*
|
||||
* @param aio sftp aio handle corresponding to which memory has
|
||||
* to be deallocated.
|
||||
*
|
||||
* @see sftp_aio_begin_read()
|
||||
* @see sftp_aio_wait_read()
|
||||
* @see sftp_aio_begin_write()
|
||||
* @see sftp_aio_wait_write()
|
||||
*/
|
||||
LIBSSH_API void sftp_aio_free(sftp_aio aio);
|
||||
#define SFTP_AIO_FREE(x) \
|
||||
do { if(x != NULL) {sftp_aio_free(x); x = NULL;} } while(0)
|
||||
|
||||
/**
|
||||
* @brief Start an asynchronous read from a file using an opened sftp
|
||||
* file handle.
|
||||
*
|
||||
* Its goal is to avoid the slowdowns related to the request/response pattern
|
||||
* of a synchronous read. To do so, you must call 2 functions :
|
||||
*
|
||||
* sftp_aio_begin_read() and sftp_aio_wait_read().
|
||||
*
|
||||
* - The first step is to call sftp_aio_begin_read(). This function sends a
|
||||
* read request to the sftp server, dynamically allocates memory to store
|
||||
* information about the sent request and provides the caller an sftp aio
|
||||
* handle to that memory.
|
||||
*
|
||||
* - The second step is to call sftp_aio_wait_read() and pass it the address
|
||||
* of a location storing the sftp aio handle provided by
|
||||
* sftp_aio_begin_read().
|
||||
*
|
||||
* These two functions do not close the open sftp file handle passed to
|
||||
* sftp_aio_begin_read() irrespective of whether they fail or not.
|
||||
*
|
||||
* It is the responsibility of the caller to ensure that the open sftp file
|
||||
* handle passed to sftp_aio_begin_read() must not be closed before the
|
||||
* corresponding call to sftp_aio_wait_read(). After sftp_aio_wait_read()
|
||||
* returns, it is caller's decision whether to immediately close the file by
|
||||
* calling sftp_close() or to keep it open and perform some more operations
|
||||
* on it.
|
||||
*
|
||||
* This function caps the length a user is allowed to read from an sftp file,
|
||||
* the value of len parameter after capping is returned on success.
|
||||
*
|
||||
* The value used for the cap is same as the value of the max_read_length
|
||||
* field of the sftp_limits_t returned by sftp_limits().
|
||||
*
|
||||
* @param file The opened sftp file handle to be read from.
|
||||
*
|
||||
* @param len Number of bytes to read.
|
||||
*
|
||||
* @param aio Pointer to a location where the sftp aio handle
|
||||
* (corresponding to the sent request) should be stored.
|
||||
*
|
||||
* @returns On success, the number of bytes the server is
|
||||
* requested to read (value of len parameter after
|
||||
* capping). On error, SSH_ERROR with sftp and ssh
|
||||
* errors set.
|
||||
*
|
||||
* @warning When calling this function, the internal file offset is
|
||||
* updated corresponding to the number of bytes requested
|
||||
* to read.
|
||||
*
|
||||
* @warning A call to sftp_aio_begin_read() sends a request to
|
||||
* the server. When the server answers, libssh allocates
|
||||
* memory to store it until sftp_aio_wait_read() is called.
|
||||
* Not calling sftp_aio_wait_read() will lead to memory
|
||||
* leaks.
|
||||
*
|
||||
* @see sftp_aio_wait_read()
|
||||
* @see sftp_aio_free()
|
||||
* @see sftp_open()
|
||||
* @see sftp_close()
|
||||
* @see sftp_get_error()
|
||||
* @see ssh_get_error()
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_aio_begin_read(sftp_file file,
|
||||
size_t len,
|
||||
sftp_aio *aio);
|
||||
|
||||
/**
|
||||
* @brief Wait for an asynchronous read to complete and store the read data
|
||||
* in the supplied buffer.
|
||||
*
|
||||
* A pointer to an sftp aio handle should be passed while calling
|
||||
* this function. Except when the return value is SSH_AGAIN,
|
||||
* this function releases the memory corresponding to the supplied
|
||||
* aio handle and assigns NULL to that aio handle using the passed
|
||||
* pointer to that handle.
|
||||
*
|
||||
* If the file is opened in non-blocking mode and the request hasn't been
|
||||
* executed yet, this function returns SSH_AGAIN and must be called again
|
||||
* using the same sftp aio handle.
|
||||
*
|
||||
* @param aio Pointer to the sftp aio handle returned by
|
||||
* sftp_aio_begin_read().
|
||||
*
|
||||
* @param buf Pointer to the buffer in which read data will be stored.
|
||||
*
|
||||
* @param buf_size Size of the buffer in bytes. It should be bigger or
|
||||
* equal to the length parameter of the
|
||||
* sftp_aio_begin_read() call.
|
||||
*
|
||||
* @return Number of bytes read, 0 on EOF, SSH_ERROR if an error
|
||||
* occurred, SSH_AGAIN if the file is opened in nonblocking
|
||||
* mode and the request hasn't been executed yet.
|
||||
*
|
||||
* @warning A call to this function with an invalid sftp aio handle
|
||||
* may never return.
|
||||
*
|
||||
* @see sftp_aio_begin_read()
|
||||
* @see sftp_aio_free()
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_aio_wait_read(sftp_aio *aio,
|
||||
void *buf,
|
||||
size_t buf_size);
|
||||
|
||||
/**
|
||||
* @brief Start an asynchronous write to a file using an opened sftp
|
||||
* file handle.
|
||||
*
|
||||
* Its goal is to avoid the slowdowns related to the request/response pattern
|
||||
* of a synchronous write. To do so, you must call 2 functions :
|
||||
*
|
||||
* sftp_aio_begin_write() and sftp_aio_wait_write().
|
||||
*
|
||||
* - The first step is to call sftp_aio_begin_write(). This function sends a
|
||||
* write request to the sftp server, dynamically allocates memory to store
|
||||
* information about the sent request and provides the caller an sftp aio
|
||||
* handle to that memory.
|
||||
*
|
||||
* - The second step is to call sftp_aio_wait_write() and pass it the address
|
||||
* of a location storing the sftp aio handle provided by
|
||||
* sftp_aio_begin_write().
|
||||
*
|
||||
* These two functions do not close the open sftp file handle passed to
|
||||
* sftp_aio_begin_write() irrespective of whether they fail or not.
|
||||
*
|
||||
* It is the responsibility of the caller to ensure that the open sftp file
|
||||
* handle passed to sftp_aio_begin_write() must not be closed before the
|
||||
* corresponding call to sftp_aio_wait_write(). After sftp_aio_wait_write()
|
||||
* returns, it is caller's decision whether to immediately close the file by
|
||||
* calling sftp_close() or to keep it open and perform some more operations
|
||||
* on it.
|
||||
*
|
||||
* This function caps the length a user is allowed to write to an sftp file,
|
||||
* the value of len parameter after capping is returned on success.
|
||||
*
|
||||
* The value used for the cap is same as the value of the max_write_length
|
||||
* field of the sftp_limits_t returned by sftp_limits().
|
||||
*
|
||||
* @param file The opened sftp file handle to write to.
|
||||
*
|
||||
* @param buf Pointer to the buffer containing data to write.
|
||||
*
|
||||
* @param len Number of bytes to write.
|
||||
*
|
||||
* @param aio Pointer to a location where the sftp aio handle
|
||||
* (corresponding to the sent request) should be stored.
|
||||
*
|
||||
* @returns On success, the number of bytes the server is
|
||||
* requested to write (value of len parameter after
|
||||
* capping). On error, SSH_ERROR with sftp and ssh errors
|
||||
* set.
|
||||
*
|
||||
* @warning When calling this function, the internal file offset is
|
||||
* updated corresponding to the number of bytes requested
|
||||
* to write.
|
||||
*
|
||||
* @warning A call to sftp_aio_begin_write() sends a request to
|
||||
* the server. When the server answers, libssh allocates
|
||||
* memory to store it until sftp_aio_wait_write() is
|
||||
* called. Not calling sftp_aio_wait_write() will lead to
|
||||
* memory leaks.
|
||||
*
|
||||
* @see sftp_aio_wait_write()
|
||||
* @see sftp_aio_free()
|
||||
* @see sftp_open()
|
||||
* @see sftp_close()
|
||||
* @see sftp_get_error()
|
||||
* @see ssh_get_error()
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_aio_begin_write(sftp_file file,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
sftp_aio *aio);
|
||||
|
||||
/**
|
||||
* @brief Wait for an asynchronous write to complete.
|
||||
*
|
||||
* A pointer to an sftp aio handle should be passed while calling
|
||||
* this function. Except when the return value is SSH_AGAIN,
|
||||
* this function releases the memory corresponding to the supplied
|
||||
* aio handle and assigns NULL to that aio handle using the passed
|
||||
* pointer to that handle.
|
||||
*
|
||||
* If the file is opened in non-blocking mode and the request hasn't
|
||||
* been executed yet, this function returns SSH_AGAIN and must be called
|
||||
* again using the same sftp aio handle.
|
||||
*
|
||||
* @param aio Pointer to the sftp aio handle returned by
|
||||
* sftp_aio_begin_write().
|
||||
*
|
||||
* @return Number of bytes written on success, SSH_ERROR
|
||||
* if an error occurred, SSH_AGAIN if the file is
|
||||
* opened in nonblocking mode and the request hasn't
|
||||
* been executed yet.
|
||||
*
|
||||
* @warning A call to this function with an invalid sftp aio handle
|
||||
* may never return.
|
||||
*
|
||||
* @see sftp_aio_begin_write()
|
||||
* @see sftp_aio_free()
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_aio_wait_write(sftp_aio *aio);
|
||||
|
||||
/**
|
||||
* @brief Seek to a specific location in a file.
|
||||
*
|
||||
@@ -855,7 +605,8 @@ LIBSSH_API unsigned long sftp_tell(sftp_file file);
|
||||
* @param file Open sftp file handle.
|
||||
*
|
||||
* @return The offset of the current byte relative to the beginning
|
||||
* of the file associated with the file descriptor.
|
||||
* of the file associated with the file descriptor. < 0 on
|
||||
* error.
|
||||
*/
|
||||
LIBSSH_API uint64_t sftp_tell64(sftp_file file);
|
||||
|
||||
@@ -948,29 +699,6 @@ LIBSSH_API int sftp_rename(sftp_session sftp, const char *original, const char
|
||||
*/
|
||||
LIBSSH_API int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr);
|
||||
|
||||
/**
|
||||
* @brief This request is like setstat (excluding mode and size) but sets file
|
||||
* attributes on symlinks themselves.
|
||||
*
|
||||
* Note, that this function can only set time values using 32 bit values due to
|
||||
* the restrictions in the SFTP protocol version 3 implemented by libssh.
|
||||
* The support for 64 bit time values was introduced in SFTP version 5, which is
|
||||
* not implemented by libssh nor any major SFTP servers.
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @param file The symbolic link which attributes should be changed.
|
||||
*
|
||||
* @param attr The file attributes structure with the attributes set
|
||||
* which should be changed.
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*
|
||||
* @see sftp_get_error()
|
||||
*/
|
||||
LIBSSH_API int
|
||||
sftp_lsetstat(sftp_session sftp, const char *file, sftp_attributes attr);
|
||||
|
||||
/**
|
||||
* @brief Change the file owner and group
|
||||
*
|
||||
@@ -1051,22 +779,6 @@ LIBSSH_API int sftp_symlink(sftp_session sftp, const char *target, const char *d
|
||||
*/
|
||||
LIBSSH_API char *sftp_readlink(sftp_session sftp, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Create a hard link.
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @param oldpath Specifies the pathname of the file for
|
||||
* which the new hardlink is to be created.
|
||||
*
|
||||
* @param newpath Specifies the pathname of the hardlink to be created.
|
||||
*
|
||||
* @return 0 on success, -1 on error with ssh and sftp error set.
|
||||
*
|
||||
* @see sftp_get_error()
|
||||
*/
|
||||
LIBSSH_API int sftp_hardlink(sftp_session sftp, const char *oldpath, const char *newpath);
|
||||
|
||||
/**
|
||||
* @brief Get information about a mounted file system.
|
||||
*
|
||||
@@ -1114,24 +826,6 @@ LIBSSH_API void sftp_statvfs_free(sftp_statvfs_t statvfs_o);
|
||||
*/
|
||||
LIBSSH_API int sftp_fsync(sftp_file file);
|
||||
|
||||
/**
|
||||
* @brief Get information about the various limits the server might impose.
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @return A limits structure or NULL on error.
|
||||
*
|
||||
* @see sftp_get_error()
|
||||
*/
|
||||
LIBSSH_API sftp_limits_t sftp_limits(sftp_session sftp);
|
||||
|
||||
/**
|
||||
* @brief Free the memory of an allocated limits.
|
||||
*
|
||||
* @param limits The limits to free.
|
||||
*/
|
||||
LIBSSH_API void sftp_limits_free(sftp_limits_t limits);
|
||||
|
||||
/**
|
||||
* @brief Canonicalize a sftp path.
|
||||
*
|
||||
@@ -1154,40 +848,6 @@ LIBSSH_API char *sftp_canonicalize_path(sftp_session sftp, const char *path);
|
||||
*/
|
||||
LIBSSH_API int sftp_server_version(sftp_session sftp);
|
||||
|
||||
/**
|
||||
* @brief Canonicalize path using expand-path@openssh.com extension
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @param path The path to be canonicalized.
|
||||
*
|
||||
* @return A pointer to the newly allocated canonicalized path,
|
||||
* NULL on error. The caller needs to free the memory
|
||||
* using ssh_string_free_char().
|
||||
*/
|
||||
LIBSSH_API char *sftp_expand_path(sftp_session sftp, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Get the specified user's home directory
|
||||
*
|
||||
* This calls the "home-directory" extension. You should check if the extension
|
||||
* is supported using:
|
||||
*
|
||||
* @code
|
||||
* int supported = sftp_extension_supported(sftp, "home-directory", "1");
|
||||
* @endcode
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @param username username of the user whose home directory is requested.
|
||||
*
|
||||
* @return On success, a newly allocated string containing the
|
||||
* absolute real-path of the home directory of the user.
|
||||
* NULL on error. The caller needs to free the memory
|
||||
* using ssh_string_free_char().
|
||||
*/
|
||||
LIBSSH_API char *sftp_home_directory(sftp_session sftp, const char *username);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
/**
|
||||
* @brief Create a new sftp server session.
|
||||
@@ -1207,7 +867,7 @@ LIBSSH_API sftp_session sftp_server_new(ssh_session session, ssh_channel chan);
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
SSH_DEPRECATED LIBSSH_API int sftp_server_init(sftp_session sftp);
|
||||
LIBSSH_API int sftp_server_init(sftp_session sftp);
|
||||
|
||||
/**
|
||||
* @brief Close and deallocate a sftp server session.
|
||||
|
||||
@@ -32,49 +32,6 @@ int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr);
|
||||
sftp_attributes sftp_parse_attr(sftp_session session,
|
||||
ssh_buffer buf,
|
||||
int expectname);
|
||||
/**
|
||||
* @brief Reply to the SSH_FXP_INIT message with the SSH_FXP_VERSION message
|
||||
*
|
||||
* @param client_msg The pointer to client message.
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*
|
||||
* @see sftp_get_error()
|
||||
*/
|
||||
int sftp_reply_version(sftp_client_message client_msg);
|
||||
/**
|
||||
* @brief Decode the data from channel buffer into sftp read_packet.
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @param data The pointer to the data buffer of channel.
|
||||
* @param len The data buffer length
|
||||
*
|
||||
* @return Length of data decoded.
|
||||
*/
|
||||
int sftp_decode_channel_data_to_packet(sftp_session sftp, void *data, uint32_t len);
|
||||
|
||||
void sftp_set_error(sftp_session sftp, int errnum);
|
||||
|
||||
void sftp_message_free(sftp_message msg);
|
||||
|
||||
int sftp_read_and_dispatch(sftp_session sftp);
|
||||
|
||||
sftp_message sftp_dequeue(sftp_session sftp, uint32_t id);
|
||||
|
||||
/*
|
||||
* Assigns a new SFTP ID for new requests and assures there is no collision
|
||||
* between them.
|
||||
* Returns a new ID ready to use in a request
|
||||
*/
|
||||
static inline uint32_t sftp_get_new_id(sftp_session session)
|
||||
{
|
||||
return ++session->id_counter;
|
||||
}
|
||||
|
||||
sftp_status_message parse_status_msg(sftp_message msg);
|
||||
|
||||
void status_msg_free(sftp_status_message status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2022 Zeyu Sheng <shengzeyu19_98@163.com>
|
||||
* Copyright (c) 2023 Red Hat, Inc.
|
||||
*
|
||||
* Authors: Jakub Jelen <jjelen@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SFTP_SERVER_H
|
||||
#define SFTP_SERVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/sftp.h"
|
||||
|
||||
/**
|
||||
* @defgroup libssh_sftp_server The libssh SFTP server API
|
||||
*
|
||||
* @brief SFTP server handling functions
|
||||
*
|
||||
* TODO
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define SSH_SFTP_CALLBACK(name) \
|
||||
static int name(sftp_client_message message)
|
||||
|
||||
typedef int (*sftp_server_message_callback)(sftp_client_message message);
|
||||
|
||||
struct sftp_message_handler
|
||||
{
|
||||
const char *name;
|
||||
const char *extended_name;
|
||||
uint8_t type;
|
||||
|
||||
sftp_server_message_callback cb;
|
||||
};
|
||||
|
||||
LIBSSH_API int sftp_channel_default_subsystem_request(ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *subsystem,
|
||||
void *userdata);
|
||||
LIBSSH_API int sftp_channel_default_data_callback(ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *data,
|
||||
uint32_t len,
|
||||
int is_stderr,
|
||||
void *userdata);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SFTP_SERVER_H */
|
||||
@@ -37,11 +37,10 @@ void ssh_socket_set_fd(ssh_socket s, socket_t fd);
|
||||
socket_t ssh_socket_get_fd(ssh_socket s);
|
||||
void ssh_socket_set_connected(ssh_socket s, struct ssh_poll_handle_struct *p);
|
||||
int ssh_socket_unix(ssh_socket s, const char *path);
|
||||
#if WITH_EXEC
|
||||
void ssh_execute_command(const char *command, socket_t in, socket_t out);
|
||||
#ifndef _WIN32
|
||||
int ssh_socket_connect_proxycommand(ssh_socket s, const char *command);
|
||||
#endif
|
||||
int ssh_socket_connect_proxyjump(ssh_socket s);
|
||||
void ssh_socket_close(ssh_socket s);
|
||||
int ssh_socket_write(ssh_socket s,const void *buffer, uint32_t len);
|
||||
int ssh_socket_is_open(ssh_socket s);
|
||||
|
||||
@@ -49,11 +49,6 @@ char *ssh_remove_duplicates(const char *list);
|
||||
|
||||
char *ssh_append_without_duplicates(const char *list,
|
||||
const char *appended_list);
|
||||
char *ssh_prefix_without_duplicates(const char *list,
|
||||
const char *prefixed_list);
|
||||
char *ssh_remove_all_matching(const char *list,
|
||||
const char *remove_list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1 +1 @@
|
||||
4.10.2
|
||||
4.9.6
|
||||
@@ -1,445 +0,0 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_aio_begin_read
|
||||
sftp_aio_begin_write
|
||||
sftp_aio_free
|
||||
sftp_aio_wait_read
|
||||
sftp_aio_wait_write
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_channel_default_data_callback
|
||||
sftp_channel_default_subsystem_request
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_expand_path
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_hardlink
|
||||
sftp_home_directory
|
||||
sftp_init
|
||||
sftp_limits
|
||||
sftp_limits_free
|
||||
sftp_lsetstat
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_state
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_port
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_pty_size_modes
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_dup
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_base64_format
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_file_format
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_request_no_more_sessions
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_issue_banner
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_set_disconnect_message
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_publickey_auto_get_current_identity
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_vlog
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
@@ -1,445 +0,0 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_aio_begin_read
|
||||
sftp_aio_begin_write
|
||||
sftp_aio_free
|
||||
sftp_aio_wait_read
|
||||
sftp_aio_wait_write
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_channel_default_data_callback
|
||||
sftp_channel_default_subsystem_request
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_expand_path
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_hardlink
|
||||
sftp_home_directory
|
||||
sftp_init
|
||||
sftp_limits
|
||||
sftp_limits_free
|
||||
sftp_lsetstat
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_state
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_port
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_pty_size_modes
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_dup
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_base64_format
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_file_format
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_request_no_more_sessions
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_issue_banner
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_set_disconnect_message
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_publickey_auto_get_current_identity
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_vlog
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
@@ -1,445 +0,0 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_aio_begin_read
|
||||
sftp_aio_begin_write
|
||||
sftp_aio_free
|
||||
sftp_aio_wait_read
|
||||
sftp_aio_wait_write
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_channel_default_data_callback
|
||||
sftp_channel_default_subsystem_request
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_expand_path
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_hardlink
|
||||
sftp_home_directory
|
||||
sftp_init
|
||||
sftp_limits
|
||||
sftp_limits_free
|
||||
sftp_lsetstat
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_state
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_port
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_pty_size_modes
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_dup
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_base64_format
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_file_format
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_request_no_more_sessions
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_issue_banner
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_set_disconnect_message
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_publickey_auto_get_current_identity
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_vlog
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
@@ -9,20 +9,50 @@ set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_REQUIRED_LIBRARIES}
|
||||
)
|
||||
|
||||
if (TARGET OpenSSL::Crypto)
|
||||
list(APPEND LIBSSH_LINK_LIBRARIES OpenSSL::Crypto)
|
||||
endif ()
|
||||
if (OPENSSL_CRYPTO_LIBRARIES)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (TARGET MbedTLS::mbedcrypto)
|
||||
list(APPEND LIBSSH_LINK_LIBRARIES MbedTLS::mbedcrypto)
|
||||
endif ()
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
${OPENSSL_CRYPTO_LIBRARIES}
|
||||
)
|
||||
endif (OPENSSL_CRYPTO_LIBRARIES)
|
||||
|
||||
if (TARGET libgcrypt::libgcrypt)
|
||||
list(APPEND LIBSSH_LINK_LIBRARIES ${GCRYPT_LIBRARIES})
|
||||
endif ()
|
||||
if (MBEDTLS_CRYPTO_LIBRARY)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
${MBEDTLS_INCLUDE_DIR}
|
||||
)
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
${MBEDTLS_CRYPTO_LIBRARY}
|
||||
)
|
||||
endif (MBEDTLS_CRYPTO_LIBRARY)
|
||||
|
||||
if (GCRYPT_LIBRARIES)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
${GCRYPT_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
${GCRYPT_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (WITH_ZLIB)
|
||||
list(APPEND LIBSSH_LINK_LIBRARIES ZLIB::ZLIB)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
${ZLIB_LIBRARY}
|
||||
)
|
||||
endif (WITH_ZLIB)
|
||||
|
||||
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
@@ -56,7 +86,7 @@ if (MINGW AND Threads_FOUND)
|
||||
)
|
||||
endif()
|
||||
|
||||
# The ws2_32 needs to be last for mingw to build
|
||||
# This needs to be last for mingw to build
|
||||
# https://gitlab.com/libssh/libssh-mirror/-/issues/84
|
||||
if (WIN32)
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
@@ -91,7 +121,6 @@ set(libssh_SRCS
|
||||
ecdh.c
|
||||
error.c
|
||||
getpass.c
|
||||
gzip.c
|
||||
init.c
|
||||
kdf.c
|
||||
kex.c
|
||||
@@ -115,7 +144,6 @@ set(libssh_SRCS
|
||||
socket.c
|
||||
string.c
|
||||
threads.c
|
||||
ttyopts.c
|
||||
wrapper.c
|
||||
external/bcrypt_pbkdf.c
|
||||
external/blowfish.c
|
||||
@@ -211,22 +239,33 @@ else (WITH_GCRYPT)
|
||||
libcrypto.c
|
||||
dh_crypto.c
|
||||
)
|
||||
if (NOT HAVE_OPENSSL_EVP_CHACHA20)
|
||||
if (NOT HAVE_OPENSSL_ED25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
pki_ed25519.c
|
||||
external/ed25519.c
|
||||
external/fe25519.c
|
||||
external/ge25519.c
|
||||
external/sc25519.c
|
||||
)
|
||||
endif (NOT HAVE_OPENSSL_ED25519)
|
||||
if (NOT (HAVE_OPENSSL_EVP_CHACHA20 AND HAVE_OPENSSL_EVP_POLY1305))
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
external/chacha.c
|
||||
external/poly1305.c
|
||||
chachapoly.c
|
||||
)
|
||||
endif (NOT HAVE_OPENSSL_EVP_CHACHA20)
|
||||
endif (NOT (HAVE_OPENSSL_EVP_CHACHA20 AND HAVE_OPENSSL_EVP_POLY1305))
|
||||
if(OPENSSL_VERSION VERSION_LESS "1.1.0")
|
||||
set(libssh_SRCS ${libssh_SRCS} libcrypto-compat.c)
|
||||
endif()
|
||||
endif (WITH_GCRYPT)
|
||||
|
||||
if (WITH_SFTP)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
sftp.c
|
||||
sftp_common.c
|
||||
sftp_aio.c
|
||||
)
|
||||
|
||||
if (WITH_SERVER)
|
||||
@@ -253,6 +292,13 @@ if (WITH_GEX)
|
||||
)
|
||||
endif (WITH_GEX)
|
||||
|
||||
if (WITH_ZLIB)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
gzip.c
|
||||
)
|
||||
endif(WITH_ZLIB)
|
||||
|
||||
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
@@ -261,7 +307,7 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
|
||||
if (NOT WITH_NACL)
|
||||
if (NOT HAVE_LIBCRYPTO)
|
||||
if (NOT HAVE_LIBCRYPTO OR NOT HAVE_OPENSSL_ED25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
external/curve25519_ref.c
|
||||
@@ -312,7 +358,6 @@ endif ()
|
||||
target_include_directories(ssh
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${libssh_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${libssh_BINARY_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${LIBSSH_PRIVATE_INCLUDE_DIRS})
|
||||
|
||||
@@ -336,8 +381,6 @@ endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
|
||||
set_target_properties(ssh
|
||||
PROPERTIES
|
||||
C_STANDARD
|
||||
99
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
SOVERSION
|
||||
@@ -354,10 +397,6 @@ if (MINGW)
|
||||
target_link_libraries(ssh PRIVATE "-Wl,--enable-stdcall-fixup")
|
||||
target_compile_definitions(ssh PRIVATE "_POSIX_SOURCE")
|
||||
endif ()
|
||||
if (WITH_COVERAGE)
|
||||
include(CodeCoverage)
|
||||
append_coverage_compiler_flags_to_target(ssh)
|
||||
endif (WITH_COVERAGE)
|
||||
|
||||
|
||||
install(TARGETS ssh
|
||||
@@ -382,7 +421,6 @@ if (BUILD_STATIC_LIB)
|
||||
target_include_directories(ssh-static
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${libssh_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${libssh_BINARY_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${LIBSSH_PRIVATE_INCLUDE_DIRS})
|
||||
target_link_libraries(ssh-static
|
||||
@@ -410,9 +448,6 @@ if (BUILD_STATIC_LIB)
|
||||
if (WIN32)
|
||||
target_compile_definitions(ssh-static PUBLIC "LIBSSH_STATIC")
|
||||
endif (WIN32)
|
||||
if (WITH_COVERAGE)
|
||||
append_coverage_compiler_flags_to_target(ssh-static)
|
||||
endif (WITH_COVERAGE)
|
||||
endif (BUILD_STATIC_LIB)
|
||||
|
||||
message(STATUS "Threads_FOUND=${Threads_FOUND}")
|
||||
|
||||
43
src/agent.c
43
src/agent.c
@@ -275,19 +275,19 @@ static int agent_talk(struct ssh_session_struct *session,
|
||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||
|
||||
len = ssh_buffer_get_len(request);
|
||||
SSH_LOG(SSH_LOG_TRACE, "Request length: %" PRIu32, len);
|
||||
SSH_LOG(SSH_LOG_TRACE, "Request length: %u", len);
|
||||
PUSH_BE_U32(payload, 0, len);
|
||||
|
||||
/* send length and then the request packet */
|
||||
if (atomicio(session->agent, payload, 4, 0) == 4) {
|
||||
if (atomicio(session->agent, ssh_buffer_get(request), len, 0)
|
||||
!= len) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "atomicio sending request failed: %s",
|
||||
strerror(errno));
|
||||
SSH_LOG(SSH_LOG_WARN, "atomicio sending request failed: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"atomicio sending request length failed: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
return -1;
|
||||
@@ -295,27 +295,27 @@ static int agent_talk(struct ssh_session_struct *session,
|
||||
|
||||
/* wait for response, read the length of the response packet */
|
||||
if (atomicio(session->agent, payload, 4, 1) != 4) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "atomicio read response length failed: %s",
|
||||
strerror(errno));
|
||||
SSH_LOG(SSH_LOG_WARN, "atomicio read response length failed: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = PULL_BE_U32(payload, 0);
|
||||
if (len > 256 * 1024) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Authentication response too long: %" PRIu32, len);
|
||||
"Authentication response too long: %u", len);
|
||||
return -1;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_TRACE, "Response length: %" PRIu32, len);
|
||||
SSH_LOG(SSH_LOG_TRACE, "Response length: %u", len);
|
||||
|
||||
payload = ssh_buffer_allocate(reply, len);
|
||||
if (payload == NULL) {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Not enough space");
|
||||
SSH_LOG(SSH_LOG_WARN, "Not enough space");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (atomicio(session->agent, payload, len, 1) != len) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Error reading response from authentication socket.");
|
||||
/* Rollback the unused space */
|
||||
ssh_buffer_pass_bytes_end(reply, len);
|
||||
@@ -363,7 +363,7 @@ uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session)
|
||||
rc = ssh_buffer_get_u8(reply, (uint8_t *) &type);
|
||||
if (rc != sizeof(uint8_t)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad authentication reply size: %" PRIu32, rc);
|
||||
"Bad authentication reply size: %d", rc);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return 0;
|
||||
}
|
||||
@@ -371,7 +371,7 @@ uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session)
|
||||
type = bswap_32(type);
|
||||
#endif
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Answer type: %d, expected answer: %d",
|
||||
type, SSH2_AGENT_IDENTITIES_ANSWER);
|
||||
|
||||
@@ -404,7 +404,9 @@ uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssh_buffer_free(session->agent->ident);
|
||||
if (session->agent->ident) {
|
||||
ssh_buffer_reinit(session->agent->ident);
|
||||
}
|
||||
session->agent->ident = reply;
|
||||
|
||||
return session->agent->count;
|
||||
@@ -422,9 +424,8 @@ ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session,
|
||||
|
||||
/* caller has to free comment */
|
||||
ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
|
||||
char **comment)
|
||||
{
|
||||
struct ssh_key_struct *key = NULL;
|
||||
char **comment) {
|
||||
struct ssh_key_struct *key;
|
||||
struct ssh_string_struct *blob = NULL;
|
||||
struct ssh_string_struct *tmp = NULL;
|
||||
int rc;
|
||||
@@ -493,10 +494,10 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
const ssh_key pubkey,
|
||||
struct ssh_buffer_struct *data)
|
||||
{
|
||||
ssh_buffer request = NULL;
|
||||
ssh_buffer reply = NULL;
|
||||
ssh_string key_blob = NULL;
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_buffer request;
|
||||
ssh_buffer reply;
|
||||
ssh_string key_blob;
|
||||
ssh_string sig_blob;
|
||||
unsigned int type = 0;
|
||||
unsigned int flags = 0;
|
||||
uint32_t dlen;
|
||||
@@ -590,7 +591,7 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
#endif
|
||||
|
||||
if (agent_failed(type)) {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Agent reports failure in signing the key");
|
||||
SSH_LOG(SSH_LOG_WARN, "Agent reports failure in signing the key");
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return NULL;
|
||||
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
|
||||
|
||||
562
src/auth.c
562
src/auth.c
@@ -72,7 +72,7 @@ static int ssh_userauth_request_service(ssh_session session)
|
||||
|
||||
rc = ssh_service_request(session, "ssh-userauth");
|
||||
if ((rc != SSH_OK) && (rc != SSH_AGAIN)) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Failed to request \"ssh-userauth\" service");
|
||||
}
|
||||
|
||||
@@ -195,15 +195,14 @@ static int ssh_userauth_get_response(ssh_session session)
|
||||
*
|
||||
* This banner should be shown to user prior to authentication
|
||||
*/
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_banner)
|
||||
{
|
||||
ssh_string banner = NULL;
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_banner) {
|
||||
ssh_string banner;
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
banner = ssh_buffer_get_ssh_string(packet);
|
||||
if (banner == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Invalid SSH_USERAUTH_BANNER packet");
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
@@ -241,7 +240,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure) {
|
||||
|
||||
if (partial) {
|
||||
session->auth.state = SSH_AUTH_STATE_PARTIAL;
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Partial success for '%s'. Authentication that can continue: %s",
|
||||
current_method,
|
||||
auth_methods);
|
||||
@@ -251,7 +250,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure) {
|
||||
"Access denied for '%s'. Authentication that can continue: %s",
|
||||
current_method,
|
||||
auth_methods);
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"%s",
|
||||
ssh_get_error(session));
|
||||
|
||||
@@ -522,17 +521,6 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Note, that this is intentionally before checking the signature type
|
||||
* compatibility to make sure the possible EXT_INFO packet is processed,
|
||||
* extensions recorded and the right signature type is used below
|
||||
*/
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
} else if (rc == SSH_ERROR) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
|
||||
if (sig_type_c == NULL) {
|
||||
@@ -556,13 +544,19 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
} else if (rc == SSH_ERROR) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* public key */
|
||||
rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "Trying signature type %s", sig_type_c);
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
@@ -657,17 +651,6 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Note, that this is intentionally before checking the signature type
|
||||
* compatibility to make sure the possible EXT_INFO packet is processed,
|
||||
* extensions recorded and the right signature type is used below
|
||||
*/
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
} else if (rc == SSH_ERROR) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Cert auth requires presenting the cert type name (*-cert@openssh.com) */
|
||||
key_type = privkey->cert != NULL ? privkey->cert_type : privkey->type;
|
||||
|
||||
@@ -694,13 +677,19 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
} else if (rc == SSH_ERROR) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* get public key or cert */
|
||||
rc = ssh_pki_export_pubkey_blob(privkey, &str);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "Sending signature type %s", sig_type_c);
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
@@ -765,23 +754,18 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
bool allowed;
|
||||
int rc;
|
||||
|
||||
switch (session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_AGENT:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Bad call during pending SSH call in %s",
|
||||
__func__);
|
||||
return SSH_ERROR;
|
||||
switch(session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_AGENT:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Bad call during pending SSH call in ssh_userauth_try_publickey");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Note, that this is intentionally before checking the signature type
|
||||
* compatibility to make sure the possible EXT_INFO packet is processed,
|
||||
* extensions recorded and the right signature type is used below
|
||||
*/
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
@@ -823,14 +807,14 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
@@ -874,7 +858,6 @@ fail:
|
||||
enum ssh_agent_state_e {
|
||||
SSH_AGENT_STATE_NONE = 0,
|
||||
SSH_AGENT_STATE_PUBKEY,
|
||||
SSH_AGENT_STATE_CERT,
|
||||
SSH_AGENT_STATE_AUTH
|
||||
};
|
||||
|
||||
@@ -922,12 +905,7 @@ int ssh_userauth_agent(ssh_session session,
|
||||
const char *username)
|
||||
{
|
||||
int rc = SSH_AUTH_ERROR;
|
||||
struct ssh_agent_state_struct *state = NULL;
|
||||
ssh_key *configKeys = NULL;
|
||||
ssh_key *configCerts = NULL;
|
||||
size_t configKeysCount = 0;
|
||||
size_t configCertsCount = 0;
|
||||
size_t i;
|
||||
struct ssh_agent_state_struct *state;
|
||||
|
||||
if (session == NULL) {
|
||||
return SSH_AUTH_ERROR;
|
||||
@@ -944,7 +922,7 @@ int ssh_userauth_agent(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
ZERO_STRUCTP(session->agent_state);
|
||||
session->agent_state->state = SSH_AGENT_STATE_NONE;
|
||||
session->agent_state->state=SSH_AGENT_STATE_NONE;
|
||||
}
|
||||
|
||||
state = session->agent_state;
|
||||
@@ -956,230 +934,62 @@ int ssh_userauth_agent(ssh_session session,
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
if (session->opts.identities_only) {
|
||||
/*
|
||||
* Read keys mentioned in the config, so we can check if key from agent
|
||||
* is in there.
|
||||
*/
|
||||
size_t identityLen = ssh_list_count(session->opts.identity);
|
||||
size_t certsLen = ssh_list_count(session->opts.certificate);
|
||||
struct ssh_iterator *it = ssh_list_get_iterator(session->opts.identity);
|
||||
|
||||
configKeys = malloc(identityLen * sizeof(ssh_key));
|
||||
configCerts = malloc((certsLen + identityLen) * sizeof(ssh_key));
|
||||
if (configKeys == NULL || configCerts == NULL) {
|
||||
free(configKeys);
|
||||
free(configCerts);
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
while (it != NULL && configKeysCount < identityLen) {
|
||||
const char *privkeyFile = it->data;
|
||||
size_t certPathLen;
|
||||
char *certFile = NULL;
|
||||
ssh_key pubkey = NULL;
|
||||
ssh_key cert = NULL;
|
||||
|
||||
/*
|
||||
* Read the private key file listed in the config, but we're only
|
||||
* interested in the public key. Don't try to decrypt private key.
|
||||
*/
|
||||
rc = ssh_pki_import_pubkey_file(privkeyFile, &pubkey);
|
||||
if (rc == SSH_OK) {
|
||||
configKeys[configKeysCount++] = pubkey;
|
||||
} else {
|
||||
char *pubkeyFile = NULL;
|
||||
size_t pubkeyPathLen = strlen(privkeyFile) + sizeof(".pub");
|
||||
|
||||
SSH_KEY_FREE(pubkey);
|
||||
|
||||
/*
|
||||
* If we couldn't get the public key from the private key file,
|
||||
* try a .pub file instead.
|
||||
*/
|
||||
pubkeyFile = malloc(pubkeyPathLen);
|
||||
if (!pubkeyFile) {
|
||||
ssh_set_error_oom(session);
|
||||
rc = SSH_AUTH_ERROR;
|
||||
goto done;
|
||||
}
|
||||
snprintf(pubkeyFile, pubkeyPathLen, "%s.pub", privkeyFile);
|
||||
rc = ssh_pki_import_pubkey_file(pubkeyFile, &pubkey);
|
||||
free(pubkeyFile);
|
||||
if (rc == SSH_OK) {
|
||||
configKeys[configKeysCount++] = pubkey;
|
||||
} else if (pubkey) {
|
||||
SSH_KEY_FREE(pubkey);
|
||||
}
|
||||
}
|
||||
/* Now try to see if there is a certificate with default name
|
||||
* do not merge it yet with the key as we need to try first the
|
||||
* non-certified key */
|
||||
certPathLen = strlen(privkeyFile) + sizeof("-cert.pub");
|
||||
certFile = malloc(certPathLen);
|
||||
if (!certFile) {
|
||||
ssh_set_error_oom(session);
|
||||
rc = SSH_AUTH_ERROR;
|
||||
goto done;
|
||||
}
|
||||
snprintf(certFile, certPathLen, "%s-cert.pub", privkeyFile);
|
||||
rc = ssh_pki_import_cert_file(certFile, &cert);
|
||||
free(certFile);
|
||||
if (rc == SSH_OK) {
|
||||
configCerts[configCertsCount++] = cert;
|
||||
} else if (cert) {
|
||||
SSH_KEY_FREE(cert);
|
||||
}
|
||||
|
||||
it = it->next;
|
||||
}
|
||||
/* And now load separately-listed certificates. */
|
||||
it = ssh_list_get_iterator(session->opts.certificate);
|
||||
while (it != NULL && configCertsCount < certsLen + identityLen) {
|
||||
const char *certFile = it->data;
|
||||
ssh_key cert = NULL;
|
||||
|
||||
rc = ssh_pki_import_cert_file(certFile, &cert);
|
||||
if (rc == SSH_OK) {
|
||||
configCerts[configCertsCount++] = cert;
|
||||
} else if (cert) {
|
||||
SSH_KEY_FREE(cert);
|
||||
}
|
||||
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
while (state->pubkey != NULL) {
|
||||
if (state->state == SSH_AGENT_STATE_NONE) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Trying identity %s",
|
||||
state->comment);
|
||||
if (session->opts.identities_only) {
|
||||
/* Check if this key is one of the keys listed in the config */
|
||||
bool found_key = false;
|
||||
for (i = 0; i < configKeysCount; i++) {
|
||||
int cmp = ssh_key_cmp(state->pubkey,
|
||||
configKeys[i],
|
||||
SSH_KEY_CMP_PUBLIC);
|
||||
if (cmp == 0) {
|
||||
found_key = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* or in separate certificates */
|
||||
for (i = 0; i < configCertsCount; i++) {
|
||||
int cmp = ssh_key_cmp(state->pubkey,
|
||||
configCerts[i],
|
||||
SSH_KEY_CMP_PUBLIC);
|
||||
if (cmp == 0) {
|
||||
found_key = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_key) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Identities only is enabled and identity %s was "
|
||||
"not listed in config, skipping",
|
||||
state->comment);
|
||||
SSH_STRING_FREE_CHAR(state->comment);
|
||||
state->comment = NULL;
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
state->pubkey = ssh_agent_get_next_ident(
|
||||
session, &state->comment);
|
||||
|
||||
if (state->pubkey == NULL) {
|
||||
rc = SSH_AUTH_DENIED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
"Trying identity %s", state->comment);
|
||||
}
|
||||
if (state->state == SSH_AGENT_STATE_NONE ||
|
||||
state->state == SSH_AGENT_STATE_PUBKEY ||
|
||||
state->state == SSH_AGENT_STATE_CERT) {
|
||||
state->state == SSH_AGENT_STATE_PUBKEY) {
|
||||
rc = ssh_userauth_try_publickey(session, username, state->pubkey);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
ssh_agent_state_free(state);
|
||||
ssh_agent_state_free (state);
|
||||
session->agent_state = NULL;
|
||||
goto done;
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_AGAIN) {
|
||||
state->state = (state->state == SSH_AGENT_STATE_NONE ?
|
||||
SSH_AGENT_STATE_PUBKEY : state->state);
|
||||
goto done;
|
||||
state->state = SSH_AGENT_STATE_PUBKEY;
|
||||
return rc;
|
||||
} else if (rc != SSH_AUTH_SUCCESS) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Public key of %s refused by server",
|
||||
state->comment);
|
||||
if (state->state == SSH_AGENT_STATE_PUBKEY) {
|
||||
for (i = 0; i < configCertsCount; i++) {
|
||||
int cmp = ssh_key_cmp(state->pubkey,
|
||||
configCerts[i],
|
||||
SSH_KEY_CMP_PUBLIC);
|
||||
if (cmp == 0) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Retry with matching certificate");
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
state->pubkey = ssh_key_dup(configCerts[i]);
|
||||
state->state = SSH_AGENT_STATE_CERT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
"Public key of %s refused by server", state->comment);
|
||||
SSH_STRING_FREE_CHAR(state->comment);
|
||||
state->comment = NULL;
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
state->pubkey = ssh_agent_get_next_ident(session,
|
||||
&state->comment);
|
||||
ssh_key_free(state->pubkey);
|
||||
state->pubkey = ssh_agent_get_next_ident(session, &state->comment);
|
||||
state->state = SSH_AGENT_STATE_NONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Public key of %s accepted by server",
|
||||
state->comment);
|
||||
"Public key of %s accepted by server", state->comment);
|
||||
state->state = SSH_AGENT_STATE_AUTH;
|
||||
}
|
||||
if (state->state == SSH_AGENT_STATE_AUTH) {
|
||||
rc = ssh_userauth_agent_publickey(session, username, state->pubkey);
|
||||
if (rc == SSH_AUTH_AGAIN) {
|
||||
goto done;
|
||||
}
|
||||
if (rc == SSH_AUTH_AGAIN)
|
||||
return rc;
|
||||
SSH_STRING_FREE_CHAR(state->comment);
|
||||
state->comment = NULL;
|
||||
if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_PARTIAL) {
|
||||
ssh_agent_state_free(session->agent_state);
|
||||
ssh_agent_state_free (session->agent_state);
|
||||
session->agent_state = NULL;
|
||||
goto done;
|
||||
return rc;
|
||||
} else if (rc != SSH_AUTH_SUCCESS) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Server accepted public key but refused the signature");
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
state->pubkey = ssh_agent_get_next_ident(session,
|
||||
&state->comment);
|
||||
ssh_key_free(state->pubkey);
|
||||
state->pubkey = ssh_agent_get_next_ident(session, &state->comment);
|
||||
state->state = SSH_AGENT_STATE_NONE;
|
||||
continue;
|
||||
}
|
||||
ssh_agent_state_free (session->agent_state);
|
||||
session->agent_state = NULL;
|
||||
rc = SSH_AUTH_SUCCESS;
|
||||
goto done;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ssh_agent_state_free (session->agent_state);
|
||||
session->agent_state = NULL;
|
||||
done:
|
||||
for (i = 0; i < configKeysCount; i++) {
|
||||
ssh_key_free(configKeys[i]);
|
||||
}
|
||||
free(configKeys);
|
||||
for (i = 0; i < configCertsCount; i++) {
|
||||
ssh_key_free(configCerts[i]);
|
||||
}
|
||||
free(configCerts);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1187,8 +997,6 @@ enum ssh_auth_auto_state_e {
|
||||
SSH_AUTH_AUTO_STATE_NONE = 0,
|
||||
SSH_AUTH_AUTO_STATE_PUBKEY,
|
||||
SSH_AUTH_AUTO_STATE_KEY_IMPORTED,
|
||||
SSH_AUTH_AUTO_STATE_CERTIFICATE_FILE,
|
||||
SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION,
|
||||
SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED
|
||||
};
|
||||
|
||||
@@ -1197,8 +1005,6 @@ struct ssh_auth_auto_state_struct {
|
||||
struct ssh_iterator *it;
|
||||
ssh_key privkey;
|
||||
ssh_key pubkey;
|
||||
ssh_key cert;
|
||||
struct ssh_iterator *cert_it;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1233,8 +1039,7 @@ int ssh_userauth_publickey_auto_get_current_identity(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->auth.auto_state != NULL &&
|
||||
session->auth.auto_state->it != NULL) {
|
||||
if (session->auth.auto_state != NULL && session->auth.auto_state->it != NULL) {
|
||||
id = session->auth.auto_state->it->data;
|
||||
}
|
||||
|
||||
@@ -1278,9 +1083,6 @@ int ssh_userauth_publickey_auto_get_current_identity(ssh_session session,
|
||||
* @note Most server implementations do not permit changing the username during
|
||||
* authentication. The username should only be set with ssh_options_set() only
|
||||
* before you connect to the server.
|
||||
*
|
||||
* The OpenSSH iterates over the identities and first try the plain public key
|
||||
* and then the certificate if it is in place.
|
||||
*/
|
||||
int ssh_userauth_publickey_auto(ssh_session session,
|
||||
const char *username,
|
||||
@@ -1288,7 +1090,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
{
|
||||
ssh_auth_callback auth_fn = NULL;
|
||||
void *auth_data = NULL;
|
||||
struct ssh_auth_auto_state_struct *state = NULL;
|
||||
struct ssh_auth_auto_state_struct *state;
|
||||
int rc;
|
||||
|
||||
if (session == NULL) {
|
||||
@@ -1319,7 +1121,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
rc = ssh_userauth_agent(session, username);
|
||||
if (rc == SSH_AUTH_SUCCESS ||
|
||||
rc == SSH_AUTH_PARTIAL ||
|
||||
rc == SSH_AUTH_AGAIN) {
|
||||
rc == SSH_AUTH_AGAIN ) {
|
||||
return rc;
|
||||
}
|
||||
state->state = SSH_AUTH_AUTO_STATE_PUBKEY;
|
||||
@@ -1334,9 +1136,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
|
||||
if (state->state == SSH_AUTH_AUTO_STATE_PUBKEY) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Trying to authenticate with %s",
|
||||
privkey_file);
|
||||
state->cert = NULL;
|
||||
"Trying to authenticate with %s", privkey_file);
|
||||
state->privkey = NULL;
|
||||
state->pubkey = NULL;
|
||||
|
||||
@@ -1349,165 +1149,86 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
if (pub_uri_from_priv == NULL) {
|
||||
return SSH_ERROR;
|
||||
} else {
|
||||
snprintf(pubkey_file,
|
||||
sizeof(pubkey_file),
|
||||
"%s",
|
||||
snprintf(pubkey_file, sizeof(pubkey_file), "%s",
|
||||
pub_uri_from_priv);
|
||||
SAFE_FREE(pub_uri_from_priv);
|
||||
}
|
||||
} else
|
||||
#endif /* WITH_PKCS11_URI */
|
||||
{
|
||||
snprintf(pubkey_file,
|
||||
sizeof(pubkey_file),
|
||||
"%s.pub",
|
||||
privkey_file);
|
||||
snprintf(pubkey_file, sizeof(pubkey_file), "%s.pub", privkey_file);
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_pubkey_file(pubkey_file, &state->pubkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to import public key: %s",
|
||||
pubkey_file);
|
||||
SSH_FATAL,
|
||||
"Failed to import public key: %s",
|
||||
pubkey_file);
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return SSH_AUTH_ERROR;
|
||||
} else if (rc == SSH_EOF) {
|
||||
/* Read the private key and save the public key to file */
|
||||
rc = ssh_pki_import_privkey_file(privkey_file,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data,
|
||||
&state->privkey);
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data,
|
||||
&state->privkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to read private key: %s",
|
||||
privkey_file);
|
||||
state->it = state->it->next;
|
||||
SSH_FATAL,
|
||||
"Failed to read private key: %s",
|
||||
privkey_file);
|
||||
state->it=state->it->next;
|
||||
continue;
|
||||
} else if (rc == SSH_EOF) {
|
||||
/* If the file doesn't exist, continue */
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Private key %s doesn't exist.",
|
||||
privkey_file);
|
||||
state->it = state->it->next;
|
||||
state->it=state->it->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = ssh_pki_export_privkey_to_pubkey(state->privkey,
|
||||
&state->pubkey);
|
||||
rc = ssh_pki_export_privkey_to_pubkey(state->privkey, &state->pubkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_KEY_FREE(state->privkey);
|
||||
ssh_key_free(state->privkey);
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_pki_export_pubkey_file(state->pubkey, pubkey_file);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Could not write public key to file: %s",
|
||||
pubkey_file);
|
||||
}
|
||||
}
|
||||
state->state = SSH_AUTH_AUTO_STATE_KEY_IMPORTED;
|
||||
}
|
||||
if (state->state == SSH_AUTH_AUTO_STATE_KEY_IMPORTED ||
|
||||
state->state == SSH_AUTH_AUTO_STATE_CERTIFICATE_FILE ||
|
||||
state->state == SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION) {
|
||||
ssh_key k = state->pubkey;
|
||||
if (state->state != SSH_AUTH_AUTO_STATE_KEY_IMPORTED) {
|
||||
k = state->cert;
|
||||
}
|
||||
rc = ssh_userauth_try_publickey(session, username, k);
|
||||
if (state->state == SSH_AUTH_AUTO_STATE_KEY_IMPORTED) {
|
||||
rc = ssh_userauth_try_publickey(session, username, state->pubkey);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Public key authentication error for %s",
|
||||
privkey_file);
|
||||
SSH_KEY_FREE(state->cert);
|
||||
SSH_KEY_FREE(state->privkey);
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
ssh_key_free(state->privkey);
|
||||
state->privkey = NULL;
|
||||
ssh_key_free(state->pubkey);
|
||||
state->pubkey = NULL;
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_AGAIN) {
|
||||
return rc;
|
||||
} else if (rc != SSH_AUTH_SUCCESS) {
|
||||
int r; /* do not reuse `rc` as it is used to return from here */
|
||||
SSH_KEY_FREE(state->cert);
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Public key for %s%s refused by server",
|
||||
privkey_file,
|
||||
(state->state != SSH_AUTH_AUTO_STATE_KEY_IMPORTED
|
||||
? " (with certificate)" : ""));
|
||||
/* Try certificate file by appending -cert.pub (if present) */
|
||||
if (state->state == SSH_AUTH_AUTO_STATE_KEY_IMPORTED) {
|
||||
char cert_file[PATH_MAX] = {0};
|
||||
ssh_key cert = NULL;
|
||||
|
||||
snprintf(cert_file,
|
||||
sizeof(cert_file),
|
||||
"%s-cert.pub",
|
||||
privkey_file);
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Trying to load the certificate %s (default path)",
|
||||
cert_file);
|
||||
r = ssh_pki_import_cert_file(cert_file, &cert);
|
||||
if (r == SSH_OK) {
|
||||
/* TODO check the pubkey and certs match */
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Certificate loaded %s. Retry the authentication.",
|
||||
cert_file);
|
||||
state->state = SSH_AUTH_AUTO_STATE_CERTIFICATE_FILE;
|
||||
SSH_KEY_FREE(state->cert);
|
||||
state->cert = cert;
|
||||
/* try to authenticate with this certificate */
|
||||
continue;
|
||||
}
|
||||
/* if the file does not exists, try configuration options */
|
||||
state->state = SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION;
|
||||
}
|
||||
/* Try certificate files loaded through options */
|
||||
if (state->state == SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION) {
|
||||
SSH_KEY_FREE(state->cert);
|
||||
if (state->cert_it == NULL) {
|
||||
state->cert_it = ssh_list_get_iterator(session->opts.certificate);
|
||||
}
|
||||
while (state->cert_it != NULL) {
|
||||
const char *cert_file = state->cert_it->data;
|
||||
ssh_key cert = NULL;
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Trying to load the certificate %s (options)",
|
||||
cert_file);
|
||||
r = ssh_pki_import_cert_file(cert_file, &cert);
|
||||
if (r == SSH_OK) {
|
||||
int cmp = ssh_key_cmp(cert,
|
||||
state->pubkey,
|
||||
SSH_KEY_CMP_PUBLIC);
|
||||
if (cmp != 0) {
|
||||
state->cert_it = state->cert_it->next;
|
||||
SSH_KEY_FREE(cert);
|
||||
continue; /* with next cert */
|
||||
}
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Found matching certificate %s in options. Retry the authentication.",
|
||||
cert_file);
|
||||
state->cert = cert;
|
||||
cert = NULL;
|
||||
state->state = SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION;
|
||||
/* try to authenticate with this identity */
|
||||
break; /* try this cert */
|
||||
}
|
||||
/* continue with next identity */
|
||||
}
|
||||
if (state->cert != NULL) {
|
||||
continue; /* retry with the certificate */
|
||||
}
|
||||
}
|
||||
SSH_KEY_FREE(state->cert);
|
||||
SSH_KEY_FREE(state->privkey);
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
state->it = state->it->next;
|
||||
"Public key for %s refused by server",
|
||||
privkey_file);
|
||||
ssh_key_free(state->privkey);
|
||||
state->privkey = NULL;
|
||||
ssh_key_free(state->pubkey);
|
||||
state->pubkey = NULL;
|
||||
state->it=state->it->next;
|
||||
state->state = SSH_AUTH_AUTO_STATE_PUBKEY;
|
||||
continue;
|
||||
}
|
||||
@@ -1517,25 +1238,25 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
/* Public key has been accepted by the server */
|
||||
if (state->privkey == NULL) {
|
||||
rc = ssh_pki_import_privkey_file(privkey_file,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data,
|
||||
&state->privkey);
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data,
|
||||
&state->privkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_KEY_FREE(state->cert);
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
ssh_key_free(state->pubkey);
|
||||
state->pubkey=NULL;
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to read private key: %s",
|
||||
privkey_file);
|
||||
state->it = state->it->next;
|
||||
SSH_FATAL,
|
||||
"Failed to read private key: %s",
|
||||
privkey_file);
|
||||
state->it=state->it->next;
|
||||
state->state = SSH_AUTH_AUTO_STATE_PUBKEY;
|
||||
continue;
|
||||
} else if (rc == SSH_EOF) {
|
||||
/* If the file doesn't exist, continue */
|
||||
SSH_KEY_FREE(state->cert);
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
ssh_key_free(state->pubkey);
|
||||
state->pubkey = NULL;
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Private key %s doesn't exist.",
|
||||
privkey_file);
|
||||
state->it = state->it->next;
|
||||
@@ -1543,33 +1264,16 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (state->cert != NULL && !is_cert_type(state->privkey->cert_type)) {
|
||||
rc = ssh_pki_copy_cert_to_privkey(state->cert, state->privkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_KEY_FREE(state->cert);
|
||||
SSH_KEY_FREE(state->privkey);
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to copy cert to private key");
|
||||
state->it = state->it->next;
|
||||
state->state = SSH_AUTH_AUTO_STATE_PUBKEY;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_userauth_publickey(session, username, state->privkey);
|
||||
if (rc != SSH_AUTH_AGAIN && rc != SSH_AUTH_DENIED) {
|
||||
bool cert_used = (state->cert != NULL);
|
||||
SSH_KEY_FREE(state->cert);
|
||||
SSH_KEY_FREE(state->privkey);
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
ssh_key_free(state->privkey);
|
||||
ssh_key_free(state->pubkey);
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
if (rc == SSH_AUTH_SUCCESS) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Successfully authenticated using %s%s",
|
||||
privkey_file,
|
||||
(cert_used ? " and certificate" : ""));
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Successfully authenticated using %s",
|
||||
privkey_file);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -1577,19 +1281,18 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
return rc;
|
||||
}
|
||||
|
||||
SSH_KEY_FREE(state->cert);
|
||||
SSH_KEY_FREE(state->privkey);
|
||||
SSH_KEY_FREE(state->pubkey);
|
||||
ssh_key_free(state->privkey);
|
||||
ssh_key_free(state->pubkey);
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"The server accepted the public key but refused the signature");
|
||||
state->it = state->it->next;
|
||||
state->state = SSH_AUTH_AUTO_STATE_PUBKEY;
|
||||
/* continue */
|
||||
}
|
||||
}
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Access denied: Tried every public key, none matched");
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Tried every public key, none matched");
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
@@ -1695,7 +1398,7 @@ int ssh_userauth_agent_pubkey(ssh_session session,
|
||||
const char *username,
|
||||
ssh_public_key publickey)
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
ssh_key key;
|
||||
int rc;
|
||||
|
||||
key = ssh_key_new();
|
||||
@@ -1706,23 +1409,21 @@ int ssh_userauth_agent_pubkey(ssh_session session,
|
||||
key->type = publickey->type;
|
||||
key->type_c = ssh_key_type_to_char(key->type);
|
||||
key->flags = SSH_KEY_FLAG_PUBLIC;
|
||||
#if defined(HAVE_LIBMBEDCRYPTO)
|
||||
key->pk = publickey->rsa_pub;
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
key->key = publickey->key_pub;
|
||||
#else
|
||||
#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
key->dsa = publickey->dsa_pub;
|
||||
key->rsa = publickey->rsa_pub;
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
#else
|
||||
key->key = publickey->key_pub;
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
rc = ssh_userauth_agent_publickey(session, username, key);
|
||||
|
||||
#if defined(HAVE_LIBMBEDCRYPTO)
|
||||
key->pk = NULL;
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
key->key = NULL;
|
||||
#else
|
||||
#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
key->dsa = NULL;
|
||||
key->rsa = NULL;
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
#else
|
||||
key->key = NULL;
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
ssh_key_free(key);
|
||||
|
||||
return rc;
|
||||
@@ -1979,10 +1680,10 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"%" PRIu32 " keyboard-interactive prompts", nprompts);
|
||||
"%d keyboard-interactive prompts", nprompts);
|
||||
if (nprompts > KBDINT_MAX_PROMPT) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Too much prompts requested by the server: %" PRIu32 " (0x%.4" PRIx32 ")",
|
||||
"Too much prompts requested by the server: %u (0x%.4x)",
|
||||
nprompts, nprompts);
|
||||
ssh_kbdint_free(session->kbdint);
|
||||
session->kbdint = NULL;
|
||||
@@ -2227,8 +1928,7 @@ int ssh_userauth_kbdint_getnanswers(ssh_session session)
|
||||
*
|
||||
* @param[in] i index The number of the ith answer.
|
||||
*
|
||||
* @return The answer string, or NULL if the answer is not
|
||||
* available. Do not free the string.
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
const char *ssh_userauth_kbdint_getanswer(ssh_session session, unsigned int i)
|
||||
{
|
||||
@@ -2334,7 +2034,7 @@ int ssh_userauth_gssapi(ssh_session session)
|
||||
} else if (rc == SSH_ERROR) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Authenticating with gssapi-with-mic");
|
||||
SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi-with-mic");
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_GSSAPI_MIC;
|
||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
|
||||
271
src/base64.c
271
src/base64.c
@@ -29,9 +29,6 @@
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
|
||||
/* Do not allow encoding more than 256MB of data */
|
||||
#define BASE64_MAX_INPUT_LEN 256 * 1024 * 1024
|
||||
|
||||
static
|
||||
const uint8_t alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
@@ -60,120 +57,119 @@ static int get_equals(char *string);
|
||||
* @returns A buffer containing the decoded string, NULL if something went
|
||||
* wrong (e.g. incorrect char).
|
||||
*/
|
||||
ssh_buffer base64_to_bin(const char *source)
|
||||
{
|
||||
ssh_buffer buffer = NULL;
|
||||
unsigned char block[3];
|
||||
char *base64 = NULL;
|
||||
char *ptr = NULL;
|
||||
size_t len;
|
||||
int equals;
|
||||
ssh_buffer base64_to_bin(const char *source) {
|
||||
ssh_buffer buffer = NULL;
|
||||
unsigned char block[3];
|
||||
char *base64;
|
||||
char *ptr;
|
||||
size_t len;
|
||||
int equals;
|
||||
|
||||
base64 = strdup(source);
|
||||
if (base64 == NULL) {
|
||||
return NULL;
|
||||
base64 = strdup(source);
|
||||
if (base64 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = base64;
|
||||
|
||||
/* Get the number of equals signs, which mirrors the padding */
|
||||
equals = get_equals(ptr);
|
||||
if (equals > 2) {
|
||||
SAFE_FREE(base64);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
SAFE_FREE(base64);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* The base64 buffer often contains sensitive data. Make sure we don't leak
|
||||
* sensitive data
|
||||
*/
|
||||
ssh_buffer_set_secure(buffer);
|
||||
|
||||
len = strlen(ptr);
|
||||
while (len > 4) {
|
||||
if (_base64_to_bin(block, ptr, 3) < 0) {
|
||||
goto error;
|
||||
}
|
||||
ptr = base64;
|
||||
|
||||
/* Get the number of equals signs, which mirrors the padding */
|
||||
equals = get_equals(ptr);
|
||||
if (equals > 2) {
|
||||
SAFE_FREE(base64);
|
||||
return NULL;
|
||||
if (ssh_buffer_add_data(buffer, block, 3) < 0) {
|
||||
goto error;
|
||||
}
|
||||
len -= 4;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
SAFE_FREE(base64);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* The base64 buffer often contains sensitive data. Make sure we don't leak
|
||||
* sensitive data
|
||||
*/
|
||||
ssh_buffer_set_secure(buffer);
|
||||
|
||||
len = strlen(ptr);
|
||||
while (len > 4) {
|
||||
if (_base64_to_bin(block, ptr, 3) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (ssh_buffer_add_data(buffer, block, 3) < 0) {
|
||||
goto error;
|
||||
}
|
||||
len -= 4;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Depending on the number of bytes resting, there are 3 possibilities
|
||||
* from the RFC.
|
||||
*/
|
||||
switch (len) {
|
||||
/*
|
||||
* Depending on the number of bytes resting, there are 3 possibilities
|
||||
* from the RFC.
|
||||
*/
|
||||
switch (len) {
|
||||
/*
|
||||
* (1) The final quantum of encoding input is an integral multiple of
|
||||
* 24 bits. Here, the final unit of encoded output will be an integral
|
||||
* multiple of 4 characters with no "=" padding
|
||||
*/
|
||||
case 4:
|
||||
if (equals != 0) {
|
||||
goto error;
|
||||
}
|
||||
if (_base64_to_bin(block, ptr, 3) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (ssh_buffer_add_data(buffer, block, 3) < 0) {
|
||||
goto error;
|
||||
}
|
||||
SAFE_FREE(base64);
|
||||
if (equals != 0) {
|
||||
goto error;
|
||||
}
|
||||
if (_base64_to_bin(block, ptr, 3) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (ssh_buffer_add_data(buffer, block, 3) < 0) {
|
||||
goto error;
|
||||
}
|
||||
SAFE_FREE(base64);
|
||||
|
||||
return buffer;
|
||||
return buffer;
|
||||
/*
|
||||
* (2) The final quantum of encoding input is exactly 8 bits; here, the
|
||||
* final unit of encoded output will be two characters followed by
|
||||
* two "=" padding characters.
|
||||
*/
|
||||
case 2:
|
||||
if (equals != 2) {
|
||||
goto error;
|
||||
}
|
||||
if (equals != 2){
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (_base64_to_bin(block, ptr, 1) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (ssh_buffer_add_data(buffer, block, 1) < 0) {
|
||||
goto error;
|
||||
}
|
||||
SAFE_FREE(base64);
|
||||
if (_base64_to_bin(block, ptr, 1) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (ssh_buffer_add_data(buffer, block, 1) < 0) {
|
||||
goto error;
|
||||
}
|
||||
SAFE_FREE(base64);
|
||||
|
||||
return buffer;
|
||||
return buffer;
|
||||
/*
|
||||
* The final quantum of encoding input is exactly 16 bits. Here, the final
|
||||
* unit of encoded output will be three characters followed by one "="
|
||||
* padding character.
|
||||
*/
|
||||
case 3:
|
||||
if (equals != 1) {
|
||||
goto error;
|
||||
}
|
||||
if (_base64_to_bin(block, ptr, 2) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (ssh_buffer_add_data(buffer, block, 2) < 0) {
|
||||
goto error;
|
||||
}
|
||||
SAFE_FREE(base64);
|
||||
|
||||
return buffer;
|
||||
default:
|
||||
/* 4,3,2 are the only padding size allowed */
|
||||
if (equals != 1) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (_base64_to_bin(block, ptr, 2) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (ssh_buffer_add_data(buffer,block,2) < 0) {
|
||||
goto error;
|
||||
}
|
||||
SAFE_FREE(base64);
|
||||
|
||||
return buffer;
|
||||
default:
|
||||
/* 4,3,2 are the only padding size allowed */
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
SAFE_FREE(base64);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
SAFE_FREE(base64);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define BLOCK(letter, n) do {ptr = strchr((const char *)alphabet, source[n]); \
|
||||
@@ -183,62 +179,59 @@ error:
|
||||
} while(0)
|
||||
|
||||
/* Returns 0 if ok, -1 if not (ie invalid char into the stuff) */
|
||||
static int to_block4(unsigned long *block, const char *source, int num)
|
||||
{
|
||||
const char *ptr = NULL;
|
||||
unsigned int i;
|
||||
|
||||
*block = 0;
|
||||
if (num < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLOCK(A, 0); /* 6 bit */
|
||||
BLOCK(B, 1); /* 12 bit */
|
||||
|
||||
if (num < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLOCK(C, 2); /* 18 bit */
|
||||
|
||||
if (num < 3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLOCK(D, 3); /* 24 bit */
|
||||
static int to_block4(unsigned long *block, const char *source, int num) {
|
||||
const char *ptr = NULL;
|
||||
unsigned int i;
|
||||
|
||||
*block = 0;
|
||||
if (num < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLOCK(A, 0); /* 6 bit */
|
||||
BLOCK(B,1); /* 12 bit */
|
||||
|
||||
if (num < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLOCK(C, 2); /* 18 bit */
|
||||
|
||||
if (num < 3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLOCK(D, 3); /* 24 bit */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* num = numbers of final bytes to be decoded */
|
||||
static int _base64_to_bin(unsigned char dest[3], const char *source, int num)
|
||||
{
|
||||
unsigned long block;
|
||||
static int _base64_to_bin(unsigned char dest[3], const char *source, int num) {
|
||||
unsigned long block;
|
||||
|
||||
if (to_block4(&block, source, num) < 0) {
|
||||
return -1;
|
||||
}
|
||||
dest[0] = GET_A(block);
|
||||
dest[1] = GET_B(block);
|
||||
dest[2] = GET_C(block);
|
||||
if (to_block4(&block, source, num) < 0) {
|
||||
return -1;
|
||||
}
|
||||
dest[0] = GET_A(block);
|
||||
dest[1] = GET_B(block);
|
||||
dest[2] = GET_C(block);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Count the number of "=" signs and replace them by zeroes */
|
||||
static int get_equals(char *string)
|
||||
{
|
||||
char *ptr = string;
|
||||
int num = 0;
|
||||
static int get_equals(char *string) {
|
||||
char *ptr = string;
|
||||
int num = 0;
|
||||
|
||||
while ((ptr = strchr(ptr, '=')) != NULL) {
|
||||
num++;
|
||||
*ptr = '\0';
|
||||
ptr++;
|
||||
}
|
||||
while ((ptr=strchr(ptr,'=')) != NULL) {
|
||||
num++;
|
||||
*ptr = '\0';
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return num;
|
||||
return num;
|
||||
}
|
||||
|
||||
/* thanks sysk for debugging my mess :) */
|
||||
@@ -281,15 +274,7 @@ uint8_t *bin_to_base64(const uint8_t *source, size_t len)
|
||||
{
|
||||
uint8_t *base64 = NULL;
|
||||
uint8_t *ptr = NULL;
|
||||
size_t flen = 0;
|
||||
|
||||
/* Set the artificial upper limit for the input. Otherwise on 32b arch, the
|
||||
* following line could overflow for sizes larger than SIZE_MAX / 4 */
|
||||
if (len > BASE64_MAX_INPUT_LEN) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flen = len + (3 - (len % 3)); /* round to upper 3 multiple */
|
||||
size_t flen = len + (3 - (len % 3)); /* round to upper 3 multiple */
|
||||
flen = (4 * flen) / 3 + 1;
|
||||
|
||||
base64 = malloc(flen);
|
||||
@@ -298,7 +283,7 @@ uint8_t *bin_to_base64(const uint8_t *source, size_t len)
|
||||
}
|
||||
ptr = base64;
|
||||
|
||||
while (len > 0) {
|
||||
while(len > 0){
|
||||
_bin_to_base64(ptr, source, len > 3 ? 3 : len);
|
||||
ptr += 4;
|
||||
if (len < 3) {
|
||||
|
||||
10
src/bignum.c
10
src/bignum.c
@@ -70,7 +70,7 @@ bignum ssh_make_string_bn(ssh_string string)
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Importing a %zu bits, %zu bytes object ...",
|
||||
"Importing a %zu bits, %zu bytes object ...\n",
|
||||
len * 8, len);
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
@@ -88,5 +88,11 @@ void ssh_print_bignum(const char *name, const_bignum num)
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s value: %s", name,
|
||||
(hex == NULL) ? "(null)" : (char *)hex);
|
||||
ssh_crypto_free(hex);
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
SAFE_FREE(hex);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
OPENSSL_free(hex);
|
||||
#elif defined HAVE_LIBMBEDCRYPTO
|
||||
SAFE_FREE(hex);
|
||||
#endif
|
||||
}
|
||||
|
||||
256
src/bind.c
256
src/bind.c
@@ -74,7 +74,7 @@
|
||||
static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
|
||||
int port) {
|
||||
char port_c[6];
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo *ai;
|
||||
struct addrinfo hints;
|
||||
int opt = 1;
|
||||
socket_t s;
|
||||
@@ -132,9 +132,8 @@ static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
|
||||
return s;
|
||||
}
|
||||
|
||||
ssh_bind ssh_bind_new(void)
|
||||
{
|
||||
ssh_bind ptr = NULL;
|
||||
ssh_bind ssh_bind_new(void) {
|
||||
ssh_bind ptr;
|
||||
|
||||
ptr = calloc(1, sizeof(struct ssh_bind_struct));
|
||||
if (ptr == NULL) {
|
||||
@@ -150,6 +149,15 @@ ssh_bind ssh_bind_new(void)
|
||||
static int ssh_bind_import_keys(ssh_bind sshbind) {
|
||||
int rc;
|
||||
|
||||
if (sshbind->ecdsakey == NULL &&
|
||||
sshbind->dsakey == NULL &&
|
||||
sshbind->rsakey == NULL &&
|
||||
sshbind->ed25519key == NULL) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"ECDSA, ED25519, DSA, or RSA host key file must be set");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) {
|
||||
rc = ssh_pki_import_privkey_file(sshbind->ecdsakey,
|
||||
@@ -173,6 +181,30 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
if (sshbind->dsa == NULL && sshbind->dsakey != NULL) {
|
||||
rc = ssh_pki_import_privkey_file(sshbind->dsakey,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&sshbind->dsa);
|
||||
if (rc == SSH_ERROR || rc == SSH_EOF) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Failed to import private DSA host key");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (ssh_key_type(sshbind->dsa) != SSH_KEYTYPE_DSS) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"The DSA host key has the wrong type: %d",
|
||||
ssh_key_type(sshbind->dsa));
|
||||
ssh_key_free(sshbind->dsa);
|
||||
sshbind->dsa = NULL;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sshbind->rsa == NULL && sshbind->rsakey != NULL) {
|
||||
rc = ssh_pki_import_privkey_file(sshbind->rsakey,
|
||||
NULL,
|
||||
@@ -219,120 +251,94 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
|
||||
}
|
||||
|
||||
int ssh_bind_listen(ssh_bind sshbind) {
|
||||
const char *host = NULL;
|
||||
socket_t fd;
|
||||
int rc;
|
||||
const char *host;
|
||||
socket_t fd;
|
||||
int rc;
|
||||
|
||||
/* Apply global bind configurations, if it hasn't been applied before */
|
||||
rc = ssh_bind_options_parse_config(sshbind, NULL);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,"Could not parse global config");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (sshbind->rsa == NULL &&
|
||||
sshbind->dsa == NULL &&
|
||||
sshbind->ecdsa == NULL &&
|
||||
sshbind->ed25519 == NULL) {
|
||||
rc = ssh_bind_import_keys(sshbind);
|
||||
if (rc != SSH_OK) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set default hostkey paths if no hostkey was found before */
|
||||
if (sshbind->ecdsakey == NULL &&
|
||||
sshbind->rsakey == NULL &&
|
||||
sshbind->ed25519key == NULL) {
|
||||
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
|
||||
host = sshbind->bindaddr;
|
||||
if (host == NULL) {
|
||||
host = "0.0.0.0";
|
||||
}
|
||||
|
||||
sshbind->ecdsakey = strdup("/etc/ssh/ssh_host_ecdsa_key");
|
||||
sshbind->rsakey = strdup("/etc/ssh/ssh_host_rsa_key");
|
||||
sshbind->ed25519key = strdup("/etc/ssh/ssh_host_ed25519_key");
|
||||
}
|
||||
fd = bind_socket(sshbind, host, sshbind->bindport);
|
||||
if (fd == SSH_INVALID_SOCKET) {
|
||||
ssh_key_free(sshbind->dsa);
|
||||
sshbind->dsa = NULL;
|
||||
ssh_key_free(sshbind->rsa);
|
||||
sshbind->rsa = NULL;
|
||||
/* XXX should this clear also other structures that were allocated */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Apply global bind configurations, if it hasn't been applied before */
|
||||
rc = ssh_bind_options_parse_config(sshbind, NULL);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL, "Could not parse global config");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (listen(fd, 10) < 0) {
|
||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"Listening to socket %d: %s",
|
||||
fd, ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
CLOSE_SOCKET(fd);
|
||||
ssh_key_free(sshbind->dsa);
|
||||
sshbind->dsa = NULL;
|
||||
ssh_key_free(sshbind->rsa);
|
||||
sshbind->rsa = NULL;
|
||||
/* XXX should this clear also other structures that were allocated */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set default hostkey paths if no hostkey was found before */
|
||||
if (sshbind->ecdsakey == NULL &&
|
||||
sshbind->rsakey == NULL &&
|
||||
sshbind->ed25519key == NULL) {
|
||||
|
||||
sshbind->ecdsakey = strdup("/etc/ssh/ssh_host_ecdsa_key");
|
||||
sshbind->rsakey = strdup("/etc/ssh/ssh_host_rsa_key");
|
||||
sshbind->ed25519key = strdup("/etc/ssh/ssh_host_ed25519_key");
|
||||
}
|
||||
|
||||
if (sshbind->rsa == NULL &&
|
||||
sshbind->ecdsa == NULL &&
|
||||
sshbind->ed25519 == NULL) {
|
||||
rc = ssh_bind_import_keys(sshbind);
|
||||
if (rc != SSH_OK) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
|
||||
host = sshbind->bindaddr;
|
||||
if (host == NULL) {
|
||||
host = "0.0.0.0";
|
||||
}
|
||||
|
||||
fd = bind_socket(sshbind, host, sshbind->bindport);
|
||||
if (fd == SSH_INVALID_SOCKET) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (listen(fd, 10) < 0) {
|
||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||
ssh_set_error(sshbind,
|
||||
SSH_FATAL,
|
||||
"Listening to socket %d: %s",
|
||||
fd,
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
CLOSE_SOCKET(fd);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
sshbind->bindfd = fd;
|
||||
sshbind->bindfd = fd;
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Using app-provided bind socket");
|
||||
SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks, void *userdata)
|
||||
{
|
||||
if (sshbind == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (callbacks == NULL) {
|
||||
ssh_set_error_invalid(sshbind);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)) {
|
||||
ssh_set_error(sshbind,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
sshbind->bind_callbacks = callbacks;
|
||||
sshbind->bind_callbacks_userdata = userdata;
|
||||
return 0;
|
||||
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
||||
void *userdata){
|
||||
if (sshbind == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (callbacks == NULL) {
|
||||
ssh_set_error_invalid(sshbind);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
|
||||
ssh_set_error(sshbind,SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
sshbind->bind_callbacks = callbacks;
|
||||
sshbind->bind_callbacks_userdata=userdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief callback being called by poll when an event happens
|
||||
*
|
||||
*/
|
||||
static int ssh_bind_poll_callback(ssh_poll_handle sshpoll, socket_t fd, int revents, void *user)
|
||||
{
|
||||
ssh_bind sshbind = (ssh_bind)user;
|
||||
(void)sshpoll;
|
||||
(void)fd;
|
||||
static int ssh_bind_poll_callback(ssh_poll_handle sshpoll,
|
||||
socket_t fd, int revents, void *user){
|
||||
ssh_bind sshbind=(ssh_bind)user;
|
||||
(void)sshpoll;
|
||||
(void)fd;
|
||||
|
||||
if (revents & POLLIN) {
|
||||
/* new incoming connection */
|
||||
if (ssh_callbacks_exists(sshbind->bind_callbacks, incoming_connection)) {
|
||||
sshbind->bind_callbacks->incoming_connection(sshbind,
|
||||
sshbind->bind_callbacks_userdata);
|
||||
}
|
||||
if(revents & POLLIN){
|
||||
/* new incoming connection */
|
||||
if(ssh_callbacks_exists(sshbind->bind_callbacks,incoming_connection)){
|
||||
sshbind->bind_callbacks->incoming_connection(sshbind,
|
||||
sshbind->bind_callbacks_userdata);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@@ -360,24 +366,20 @@ ssh_poll_handle ssh_bind_get_poll(ssh_bind sshbind)
|
||||
return sshbind->poll;
|
||||
}
|
||||
|
||||
void ssh_bind_set_blocking(ssh_bind sshbind, int blocking)
|
||||
{
|
||||
sshbind->blocking = blocking ? 1 : 0;
|
||||
void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) {
|
||||
sshbind->blocking = blocking ? 1 : 0;
|
||||
}
|
||||
|
||||
socket_t ssh_bind_get_fd(ssh_bind sshbind)
|
||||
{
|
||||
return sshbind->bindfd;
|
||||
socket_t ssh_bind_get_fd(ssh_bind sshbind) {
|
||||
return sshbind->bindfd;
|
||||
}
|
||||
|
||||
void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd)
|
||||
{
|
||||
sshbind->bindfd = fd;
|
||||
void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) {
|
||||
sshbind->bindfd = fd;
|
||||
}
|
||||
|
||||
void ssh_bind_fd_toaccept(ssh_bind sshbind)
|
||||
{
|
||||
sshbind->toaccept = 1;
|
||||
void ssh_bind_fd_toaccept(ssh_bind sshbind) {
|
||||
sshbind->toaccept = 1;
|
||||
}
|
||||
|
||||
void ssh_bind_free(ssh_bind sshbind){
|
||||
@@ -399,10 +401,13 @@ void ssh_bind_free(ssh_bind sshbind){
|
||||
SAFE_FREE(sshbind->config_dir);
|
||||
SAFE_FREE(sshbind->pubkey_accepted_key_types);
|
||||
|
||||
SAFE_FREE(sshbind->dsakey);
|
||||
SAFE_FREE(sshbind->rsakey);
|
||||
SAFE_FREE(sshbind->ecdsakey);
|
||||
SAFE_FREE(sshbind->ed25519key);
|
||||
|
||||
ssh_key_free(sshbind->dsa);
|
||||
sshbind->dsa = NULL;
|
||||
ssh_key_free(sshbind->rsa);
|
||||
sshbind->rsa = NULL;
|
||||
ssh_key_free(sshbind->ecdsa);
|
||||
@@ -433,6 +438,13 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Apply global bind configurations, if it hasn't been applied before */
|
||||
rc = ssh_bind_options_parse_config(sshbind, NULL);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,"Could not parse global config");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->server = 1;
|
||||
|
||||
/* Copy options from bind to session */
|
||||
@@ -463,7 +475,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
} else {
|
||||
char *p = NULL;
|
||||
char *p;
|
||||
/* If something was set to the session prior to calling this
|
||||
* function, keep only what is allowed by the options set in
|
||||
* sshbind */
|
||||
@@ -481,16 +493,16 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
|
||||
session->common.log_verbosity = sshbind->common.log_verbosity;
|
||||
|
||||
if (sshbind->banner != NULL) {
|
||||
session->server_opts.custombanner = strdup(sshbind->banner);
|
||||
if (session->server_opts.custombanner == NULL) {
|
||||
session->opts.custombanner = strdup(sshbind->banner);
|
||||
if (session->opts.custombanner == NULL) {
|
||||
ssh_set_error_oom(sshbind);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (sshbind->moduli_file != NULL) {
|
||||
session->server_opts.moduli_file = strdup(sshbind->moduli_file);
|
||||
if (session->server_opts.moduli_file == NULL) {
|
||||
session->opts.moduli_file = strdup(sshbind->moduli_file);
|
||||
if (session->opts.moduli_file == NULL) {
|
||||
ssh_set_error_oom(sshbind);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -519,6 +531,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
|
||||
* only using ssh_bind_accept_fd to manage sockets ourselves.
|
||||
*/
|
||||
if (sshbind->rsa == NULL &&
|
||||
sshbind->dsa == NULL &&
|
||||
sshbind->ecdsa == NULL &&
|
||||
sshbind->ed25519 == NULL) {
|
||||
rc = ssh_bind_import_keys(sshbind);
|
||||
@@ -535,6 +548,15 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_DSA
|
||||
if (sshbind->dsa) {
|
||||
session->srv.dsa_key = ssh_key_dup(sshbind->dsa);
|
||||
if (session->srv.dsa_key == NULL) {
|
||||
ssh_set_error_oom(sshbind);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (sshbind->rsa) {
|
||||
session->srv.rsa_key = ssh_key_dup(sshbind->rsa);
|
||||
|
||||
@@ -200,7 +200,7 @@ local_parse_file(ssh_bind bind,
|
||||
uint8_t *seen,
|
||||
unsigned int depth)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
FILE *f;
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
int rv;
|
||||
@@ -363,7 +363,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
if (p && (*parser_flags & PARSING)) {
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set Hostkey value '%s'",
|
||||
count, p);
|
||||
}
|
||||
@@ -374,7 +374,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
if (p && (*parser_flags & PARSING)) {
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDADDR, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set ListenAddress value '%s'",
|
||||
count, p);
|
||||
}
|
||||
@@ -385,7 +385,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
if (p && (*parser_flags & PARSING)) {
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT_STR, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set Port value '%s'",
|
||||
count, p);
|
||||
}
|
||||
@@ -396,7 +396,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
if (p && (*parser_flags & PARSING)) {
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_C_S, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set C->S Ciphers value '%s'",
|
||||
count, p);
|
||||
break;
|
||||
@@ -404,7 +404,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_S_C, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set S->C Ciphers value '%s'",
|
||||
count, p);
|
||||
}
|
||||
@@ -415,7 +415,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
if (p && (*parser_flags & PARSING)) {
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_C_S, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set C->S MAC value '%s'",
|
||||
count, p);
|
||||
break;
|
||||
@@ -423,7 +423,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_S_C, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set S->C MAC value '%s'",
|
||||
count, p);
|
||||
}
|
||||
@@ -437,10 +437,10 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
if (strcasecmp(p, "quiet") == 0) {
|
||||
value = SSH_LOG_NONE;
|
||||
} else if (strcasecmp(p, "fatal") == 0 ||
|
||||
strcasecmp(p, "error")== 0) {
|
||||
value = SSH_LOG_WARN;
|
||||
} else if (strcasecmp(p, "verbose") == 0 ||
|
||||
strcasecmp(p, "error")== 0 ||
|
||||
strcasecmp(p, "info") == 0) {
|
||||
value = SSH_LOG_WARN;
|
||||
} else if (strcasecmp(p, "verbose") == 0) {
|
||||
value = SSH_LOG_INFO;
|
||||
} else if (strcasecmp(p, "DEBUG") == 0 ||
|
||||
strcasecmp(p, "DEBUG1") == 0) {
|
||||
@@ -453,7 +453,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY,
|
||||
&value);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set LogLevel value '%s'",
|
||||
count, p);
|
||||
}
|
||||
@@ -465,7 +465,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
if (p && (*parser_flags & PARSING)) {
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_KEY_EXCHANGE, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set KexAlgorithms value '%s'",
|
||||
count, p);
|
||||
}
|
||||
@@ -540,13 +540,13 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
/* Skip one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL || p[0] == '\0') {
|
||||
SSH_LOG(SSH_LOG_TRACE, "line %d: Match keyword "
|
||||
SSH_LOG(SSH_LOG_WARN, "line %d: Match keyword "
|
||||
"'%s' requires argument\n", count, p2);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
args++;
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Unsupported Match keyword '%s', ignoring\n",
|
||||
count,
|
||||
p2);
|
||||
@@ -576,7 +576,7 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
rc = ssh_bind_options_set(bind,
|
||||
SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set PubKeyAcceptedKeyTypes value '%s'",
|
||||
count, p);
|
||||
}
|
||||
@@ -588,26 +588,26 @@ ssh_bind_config_parse_line(ssh_bind bind,
|
||||
rc = ssh_bind_options_set(bind,
|
||||
SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, p);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"line %d: Failed to set HostkeyAlgorithms value '%s'",
|
||||
count, p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIND_CFG_NOT_ALLOWED_IN_MATCH:
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Option not allowed in Match block: %s, line: %d",
|
||||
SSH_LOG(SSH_LOG_WARN, "Option not allowed in Match block: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
case BIND_CFG_UNKNOWN:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown option: %s, line: %d",
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
case BIND_CFG_UNSUPPORTED:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unsupported option: %s, line: %d",
|
||||
SSH_LOG(SSH_LOG_WARN, "Unsupported option: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
case BIND_CFG_NA:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Option not applicable: %s, line: %d",
|
||||
SSH_LOG(SSH_LOG_WARN, "Option not applicable: %s, line: %d",
|
||||
keyword, count);
|
||||
break;
|
||||
default:
|
||||
@@ -626,7 +626,7 @@ int ssh_bind_config_parse_file(ssh_bind bind, const char *filename)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
FILE *f = NULL;
|
||||
FILE *f;
|
||||
uint32_t parser_flags;
|
||||
int rv;
|
||||
|
||||
|
||||
26
src/buffer.c
26
src/buffer.c
@@ -371,8 +371,7 @@ int ssh_buffer_allocate_size(struct ssh_buffer_struct *buffer,
|
||||
*/
|
||||
void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
void *ptr;
|
||||
buffer_verify(buffer);
|
||||
|
||||
if (buffer->used + len < len) {
|
||||
@@ -853,7 +852,7 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
break;
|
||||
case 'S':
|
||||
string = va_arg(ap, ssh_string);
|
||||
needed_size += sizeof(uint32_t) + ssh_string_len(string);
|
||||
needed_size += 4 + ssh_string_len(string);
|
||||
string = NULL;
|
||||
break;
|
||||
case 's':
|
||||
@@ -881,7 +880,7 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
cstring = NULL;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid buffer format %c", *p);
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
if (rc != SSH_OK){
|
||||
@@ -920,14 +919,13 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
* SSH_ERROR on error
|
||||
* @see ssh_buffer_add_format() for format list values.
|
||||
*/
|
||||
static int
|
||||
ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
size_t argc,
|
||||
va_list ap)
|
||||
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
size_t argc,
|
||||
va_list ap)
|
||||
{
|
||||
int rc = SSH_ERROR;
|
||||
const char *p = NULL;
|
||||
const char *p;
|
||||
union {
|
||||
uint8_t byte;
|
||||
uint16_t word;
|
||||
@@ -936,7 +934,7 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
ssh_string string;
|
||||
void *data;
|
||||
} o;
|
||||
char *cstring = NULL;
|
||||
char *cstring;
|
||||
bignum b;
|
||||
size_t len;
|
||||
size_t count;
|
||||
@@ -1011,7 +1009,7 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
cstring = NULL;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid buffer format %c", *p);
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
if (rc != SSH_OK){
|
||||
@@ -1095,7 +1093,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
va_list ap)
|
||||
{
|
||||
int rc = SSH_ERROR;
|
||||
const char *p = format, *last = NULL;
|
||||
const char *p = format, *last;
|
||||
union {
|
||||
uint8_t *byte;
|
||||
uint16_t *word;
|
||||
@@ -1243,7 +1241,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
rc = SSH_OK;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid buffer format %c", *p);
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
|
||||
}
|
||||
if (rc != SSH_OK) {
|
||||
break;
|
||||
|
||||
@@ -45,15 +45,6 @@ static void ssh_legacy_log_callback(int priority,
|
||||
log_fn(session, priority, buffer, log_data);
|
||||
}
|
||||
|
||||
void
|
||||
_ssh_remove_legacy_log_cb(void)
|
||||
{
|
||||
if (ssh_get_log_callback() == ssh_legacy_log_callback) {
|
||||
_ssh_reset_log_cb();
|
||||
ssh_set_log_userdata(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -122,7 +113,7 @@ int ssh_add_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
|
||||
|
||||
int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
|
||||
{
|
||||
struct ssh_iterator *it = NULL;
|
||||
struct ssh_iterator *it;
|
||||
|
||||
if (channel == NULL || channel->callbacks == NULL){
|
||||
return SSH_ERROR;
|
||||
|
||||
@@ -42,7 +42,7 @@ static int chacha20_set_encrypt_key(struct ssh_cipher_struct *cipher,
|
||||
void *key,
|
||||
void *IV)
|
||||
{
|
||||
struct chacha20_poly1305_keysched *sched = NULL;
|
||||
struct chacha20_poly1305_keysched *sched;
|
||||
uint8_t *u8key = key;
|
||||
(void)IV;
|
||||
|
||||
|
||||
911
src/channels.c
911
src/channels.c
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user