mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 20:30:38 +09:00
Compare commits
271 Commits
libssh-0.1
...
09155adb19
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09155adb19 | ||
|
|
95f8cbc7f0 | ||
|
|
3423399f98 | ||
|
|
ccbec9c275 | ||
|
|
ed52c88a03 | ||
|
|
0f0ac314d2 | ||
|
|
95e4c39e8a | ||
|
|
8c89633a45 | ||
|
|
8069679033 | ||
|
|
c2e9d39dbe | ||
|
|
ab44f606b2 | ||
|
|
444982b38a | ||
|
|
3df61a4e86 | ||
|
|
961c79637c | ||
|
|
7eefbbd478 | ||
|
|
c4c28c6473 | ||
|
|
08a32ac381 | ||
|
|
62762bbbc9 | ||
|
|
ab3e08c2b5 | ||
|
|
809898b980 | ||
|
|
51bd08027e | ||
|
|
0b4b71cc11 | ||
|
|
5d3ef7261c | ||
|
|
9817392e26 | ||
|
|
168302b9d6 | ||
|
|
82c8bbc504 | ||
|
|
1ea1782036 | ||
|
|
c17112f070 | ||
|
|
28c0056bca | ||
|
|
7e4f08e22a | ||
|
|
aeb0b2ec6f | ||
|
|
67cf8e3702 | ||
|
|
309f36fa83 | ||
|
|
7a2a743a39 | ||
|
|
ccb8cf88c8 | ||
|
|
b43392c31d | ||
|
|
5fc65e7270 | ||
|
|
8310b8cc2b | ||
|
|
b0063b52d8 | ||
|
|
33a947dcb0 | ||
|
|
72c282434b | ||
|
|
ba9642882d | ||
|
|
a6b73219e2 | ||
|
|
e2afe196d8 | ||
|
|
32833b40bc | ||
|
|
bc4804aa9b | ||
|
|
acb158e827 | ||
|
|
faf9caafc6 | ||
|
|
8dc29f140b | ||
|
|
7501ca1e08 | ||
|
|
2eb2af4426 | ||
|
|
5d27f69494 | ||
|
|
6fc1bf6901 | ||
|
|
a85813e6e6 | ||
|
|
f039edd85d | ||
|
|
1229ad650b | ||
|
|
937552aed2 | ||
|
|
f6709b03e6 | ||
|
|
96595d1674 | ||
|
|
c799a18d89 | ||
|
|
babd891e82 | ||
|
|
320e5154b2 | ||
|
|
986e0c593f | ||
|
|
d38007c4be | ||
|
|
c22bfa792f | ||
|
|
926d45b6dd | ||
|
|
681a5aaa26 | ||
|
|
e322e8f50c | ||
|
|
a4118ddc06 | ||
|
|
db7f101d1c | ||
|
|
ae8881dfe5 | ||
|
|
00f09acbec | ||
|
|
74eb01f26d | ||
|
|
4f239f79c6 | ||
|
|
b8e587e498 | ||
|
|
b314fd3e04 | ||
|
|
d1ad796496 | ||
|
|
e2064b743d | ||
|
|
6d2a3e4eb6 | ||
|
|
7c34fa783d | ||
|
|
2a2c714dfa | ||
|
|
12baa5200a | ||
|
|
f2b64abcbd | ||
|
|
4135154b6d | ||
|
|
ca4c874a9e | ||
|
|
c7b6ffad0e | ||
|
|
c1fb0d872d | ||
|
|
3a167a89b5 | ||
|
|
dfa9421e01 | ||
|
|
efc5bc633f | ||
|
|
3a4ba8b763 | ||
|
|
47db54b7c1 | ||
|
|
d1c2d3db9d | ||
|
|
dcb65fe584 | ||
|
|
d758990d39 | ||
|
|
bfae56634c | ||
|
|
3d0226cadc | ||
|
|
0bcd7d12d8 | ||
|
|
bd10ec1162 | ||
|
|
69c169e4cb | ||
|
|
f0b9db586b | ||
|
|
c735b44f83 | ||
|
|
3b4b8033de | ||
|
|
0068fdd594 | ||
|
|
344235c954 | ||
|
|
d00f7b1bf9 | ||
|
|
b14018ecab | ||
|
|
5e47b1c1c2 | ||
|
|
9ce885b168 | ||
|
|
184dad101d | ||
|
|
04a58919f8 | ||
|
|
b106211d92 | ||
|
|
af10857aa3 | ||
|
|
f3b389d112 | ||
|
|
18e7423e70 | ||
|
|
8c8d3ceef7 | ||
|
|
0d0ed4b1f8 | ||
|
|
8dc234c909 | ||
|
|
2e686c5cea | ||
|
|
d3706d5940 | ||
|
|
d92a057090 | ||
|
|
1434f24911 | ||
|
|
cce600f980 | ||
|
|
95150b1137 | ||
|
|
65b2591b91 | ||
|
|
a5e9529ca7 | ||
|
|
49a355c272 | ||
|
|
84d02e7440 | ||
|
|
0b91ba779c | ||
|
|
d02163546d | ||
|
|
a93e84efb9 | ||
|
|
a59d587060 | ||
|
|
6c4e4a9e1c | ||
|
|
aa681c268e | ||
|
|
fe381d6aa4 | ||
|
|
1f76cc0c6a | ||
|
|
bf2b8954e8 | ||
|
|
7e3935e7d2 | ||
|
|
d38b471fd8 | ||
|
|
735a4368c2 | ||
|
|
a25f9d211d | ||
|
|
3a52bf1679 | ||
|
|
f7bdd779d6 | ||
|
|
8ef249a4a4 | ||
|
|
d9da8f212d | ||
|
|
9613e9508d | ||
|
|
6b9a6529bd | ||
|
|
b14cde6d2a | ||
|
|
e01c32f41e | ||
|
|
dd6a711354 | ||
|
|
c1a7de78d1 | ||
|
|
9735f074ba | ||
|
|
b2b56151c0 | ||
|
|
de7903a633 | ||
|
|
a089513e40 | ||
|
|
ec9d7d13fd | ||
|
|
f14568262a | ||
|
|
257e8eb2c1 | ||
|
|
99fcd56135 | ||
|
|
8922e43578 | ||
|
|
e36ca61e36 | ||
|
|
02c092d3d9 | ||
|
|
520f758902 | ||
|
|
12b8eed093 | ||
|
|
3372c2ad78 | ||
|
|
6b83aa9a40 | ||
|
|
7f045e2d91 | ||
|
|
2b916b3b88 | ||
|
|
a10553ae57 | ||
|
|
d1ce336ae3 | ||
|
|
79ac8b85d8 | ||
|
|
9a9cafeed5 | ||
|
|
a0a5292692 | ||
|
|
1a64c577f6 | ||
|
|
c03d0d4823 | ||
|
|
d5456931cc | ||
|
|
dc18b41357 | ||
|
|
0f5dec7fb7 | ||
|
|
0cda1c0e83 | ||
|
|
1ea9708409 | ||
|
|
39fcaac3ca | ||
|
|
dab51d8e20 | ||
|
|
4becc8eb82 | ||
|
|
3468cc0dc5 | ||
|
|
4bd8d8d362 | ||
|
|
083a4781d8 | ||
|
|
7e3263d995 | ||
|
|
fbf02d5936 | ||
|
|
16fd55b4b2 | ||
|
|
799557384d | ||
|
|
c6be50cc97 | ||
|
|
af90168624 | ||
|
|
9dbd1ec80b | ||
|
|
9b9a2ea97d | ||
|
|
e9b76ff1bd | ||
|
|
e9046fc069 | ||
|
|
0cd749a533 | ||
|
|
e795849299 | ||
|
|
d887e1320a | ||
|
|
9eaa7a6394 | ||
|
|
4af88c84d4 | ||
|
|
00fce9cb6c | ||
|
|
a547b7f115 | ||
|
|
8bf908a56f | ||
|
|
b7018c17c7 | ||
|
|
a15c977cdc | ||
|
|
91e228b08b | ||
|
|
cbcd6d6f46 | ||
|
|
49b0c859f9 | ||
|
|
79ba546cde | ||
|
|
0ea982d4ec | ||
|
|
c043122655 | ||
|
|
5da8963c1d | ||
|
|
f3d80833fe | ||
|
|
874b75429f | ||
|
|
f8a6b1e2b3 | ||
|
|
5b9b901e48 | ||
|
|
2966a4a33c | ||
|
|
867630750c | ||
|
|
9a40d51162 | ||
|
|
259721e523 | ||
|
|
4bc40a47a3 | ||
|
|
f0b55391a8 | ||
|
|
d2e5b69b02 | ||
|
|
2971e122d0 | ||
|
|
e2524538f6 | ||
|
|
d0ecb5388c | ||
|
|
72b6fad284 | ||
|
|
258c2eef3b | ||
|
|
a02268a254 | ||
|
|
f16b3539da | ||
|
|
0306581f1c | ||
|
|
d8f00aca20 | ||
|
|
e0aa182e7e | ||
|
|
0e756306f0 | ||
|
|
904c3e024c | ||
|
|
b58cb9f72b | ||
|
|
861590192f | ||
|
|
9ad2f6b3b1 | ||
|
|
ef8e90863b | ||
|
|
d29ed23010 | ||
|
|
46d7417620 | ||
|
|
c73a8a824e | ||
|
|
7712c7d0f9 | ||
|
|
d7a0cbcfbb | ||
|
|
cb0237e85b | ||
|
|
5b0f480acd | ||
|
|
629ba3fd34 | ||
|
|
48d474f78c | ||
|
|
e298600303 | ||
|
|
8295945011 | ||
|
|
8363929104 | ||
|
|
71e1baeb5f | ||
|
|
82b363f294 | ||
|
|
8fb2c5d2fd | ||
|
|
9ce53b6972 | ||
|
|
7b89ff760a | ||
|
|
362ab3a684 | ||
|
|
ea97d41bbb | ||
|
|
c85268c38b | ||
|
|
c9cfeb9b83 | ||
|
|
deedc0e108 | ||
|
|
57073d588a | ||
|
|
d416ef533f | ||
|
|
2743b510ac | ||
|
|
41d370864e | ||
|
|
7e4ea0d111 | ||
|
|
b0b2e8fefd | ||
|
|
b804aa9286 | ||
|
|
ab10f5c2f7 | ||
|
|
9634668258 |
@@ -22,8 +22,8 @@ BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
# TODO with Clang 19, replace the below with
|
||||
# BreakAfterReturnType: ExceptShortType
|
||||
BreakAfterReturnType: ExceptShortType
|
||||
AlwaysBreakAfterReturnType: AllDefinitions
|
||||
AlignEscapedNewlines: Left
|
||||
ForEachMacros: ['ssh_callbacks_iterate']
|
||||
AlignConsecutiveMacros: 'Consecutive'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ tags
|
||||
/build
|
||||
/obj*
|
||||
doc/tags.xml
|
||||
.DS_Store
|
||||
|
||||
166
.gitlab-ci.yml
166
.gitlab-ci.yml
@@ -3,6 +3,7 @@ variables:
|
||||
BUILD_IMAGES_PROJECT: libssh/build-images
|
||||
CENTOS8_BUILD: buildenv-c8s
|
||||
CENTOS9_BUILD: buildenv-c9s
|
||||
CENTOS10_BUILD: buildenv-c10s
|
||||
FEDORA_BUILD: buildenv-fedora
|
||||
MINGW_BUILD: buildenv-mingw
|
||||
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
||||
@@ -26,13 +27,17 @@ workflow:
|
||||
when: never
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
|
||||
.build:
|
||||
stage: build
|
||||
.build_options:
|
||||
variables:
|
||||
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
|
||||
CMAKE_DEFAULT_DEBUG_OPTIONS: "-DCMAKE_C_FLAGS='-O0 -g -ggdb' -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_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
|
||||
|
||||
.build:
|
||||
extends: .build_options
|
||||
stage: build
|
||||
before_script: &build
|
||||
- uname -a
|
||||
- cat /etc/os-release
|
||||
@@ -74,8 +79,6 @@ workflow:
|
||||
.fedora:
|
||||
extends: .tests
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
|
||||
|
||||
.tumbleweed:
|
||||
extends: .tests
|
||||
@@ -107,7 +110,7 @@ review:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- ERROR=0
|
||||
codespell --ignore-words-list=keypair,sorce,ned,nd,ue || ERROR=1;
|
||||
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;
|
||||
@@ -122,7 +125,29 @@ review:
|
||||
###############################################################################
|
||||
# CentOS builds #
|
||||
###############################################################################
|
||||
centos9s/openssl_3.0.x/x86_64:
|
||||
centos10s/openssl_3.5.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_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 .. &&
|
||||
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:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||
extends: .tests
|
||||
variables:
|
||||
@@ -139,7 +164,7 @@ centos9s/mbedtls_2.x/x86_64:
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF"
|
||||
|
||||
centos9s/openssl_3.0.x/x86_64/fips:
|
||||
centos9s/openssl_3.5.x/x86_64/fips:
|
||||
extends: .fips
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||
script:
|
||||
@@ -204,15 +229,15 @@ fedora/coverage:
|
||||
coverage_format: cobertura
|
||||
path: obj/coverage_xml.xml
|
||||
|
||||
fedora/openssl_3.0.x/x86_64:
|
||||
fedora/openssl_3.x/x86_64:
|
||||
extends: .fedora
|
||||
|
||||
fedora/openssl_3.0.x/x86_64/pkcs11-provider:
|
||||
fedora/openssl_3.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:
|
||||
fedora/openssl_3.x/x86_64/minimal:
|
||||
extends: .fedora
|
||||
variables:
|
||||
script:
|
||||
@@ -328,7 +353,7 @@ fedora/mingw64:
|
||||
-DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
ctest --output-on-failure -E torture_rand
|
||||
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
@@ -345,7 +370,7 @@ fedora/mingw32:
|
||||
-DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
ctest --output-on-failure -E torture_rand
|
||||
|
||||
|
||||
###############################################################################
|
||||
@@ -384,7 +409,7 @@ fedora/mingw32:
|
||||
paths:
|
||||
- obj-csbuild/
|
||||
|
||||
fedora/csbuild/openssl_3.0.x:
|
||||
fedora/csbuild/openssl_3.x:
|
||||
extends: .csbuild
|
||||
script:
|
||||
- csbuild
|
||||
@@ -414,6 +439,62 @@ fedora/csbuild/mbedtls:
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
|
||||
###############################################################################
|
||||
# Fedora abidiff #
|
||||
###############################################################################
|
||||
|
||||
fedora/abidiff:
|
||||
stage: analysis
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
CMAKE_OPTIONS: $CMAKE_DEFAULT_DEBUG_OPTIONS $CMAKE_BUILD_OPTIONS
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
before_script:
|
||||
- uname -a
|
||||
- cat /etc/os-release
|
||||
- mount
|
||||
- df -h
|
||||
- cat /proc/swaps
|
||||
- free -h
|
||||
- |
|
||||
# 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
|
||||
|
||||
# Check if the commit exists in this branch
|
||||
# This is not the case for a force push
|
||||
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
|
||||
|
||||
- mkdir -p obj-${CI_COMMIT_BEFORE_SHA}
|
||||
- mkdir -p obj-${CI_COMMIT_SHA}
|
||||
|
||||
- export INSTALL_DIR1=$(pwd)/install/${CI_COMMIT_BEFORE_SHA}
|
||||
- export INSTALL_DIR2=$(pwd)/install/${CI_COMMIT_SHA}
|
||||
script:
|
||||
- git checkout ${CI_COMMIT_BEFORE_SHA}
|
||||
- pushd obj-${CI_COMMIT_BEFORE_SHA}
|
||||
- cmake ${CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR1} .. &&
|
||||
make -j$(nproc) && make -j$(nproc) install
|
||||
- popd
|
||||
- ls -l ${INSTALL_DIR1}/lib*/
|
||||
- git checkout ${CI_COMMIT_SHA}
|
||||
- pushd obj-${CI_COMMIT_SHA}
|
||||
- cmake ${CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR2} .. &&
|
||||
make -j$(nproc) && make -j$(nproc) install
|
||||
- popd
|
||||
- ls -l ${INSTALL_DIR2}/lib*/
|
||||
- ./.gitlab-ci/checkabi.sh ${INSTALL_DIR1} ${INSTALL_DIR2}
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
except:
|
||||
- tags
|
||||
only:
|
||||
- merge_requests
|
||||
|
||||
###############################################################################
|
||||
# Ubuntu builds #
|
||||
@@ -426,7 +507,7 @@ ubuntu/openssl_3.0.x/x86_64:
|
||||
###############################################################################
|
||||
# Alpine builds #
|
||||
###############################################################################
|
||||
alpine/openssl_3.0.x/musl:
|
||||
alpine/openssl_3.x/musl:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$ALPINE_BUILD
|
||||
extends: .tests
|
||||
script:
|
||||
@@ -443,10 +524,10 @@ alpine/openssl_3.0.x/musl:
|
||||
###############################################################################
|
||||
# Tumbleweed builds #
|
||||
###############################################################################
|
||||
tumbleweed/openssl_3.0.x/x86_64/gcc:
|
||||
tumbleweed/openssl_3.x/x86_64/gcc:
|
||||
extends: .tumbleweed
|
||||
|
||||
tumbleweed/openssl_3.0.x/x86/gcc:
|
||||
tumbleweed/openssl_3.x/x86/gcc:
|
||||
extends: .tumbleweed
|
||||
script:
|
||||
- cmake
|
||||
@@ -459,12 +540,12 @@ tumbleweed/openssl_3.0.x/x86/gcc:
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc)
|
||||
|
||||
tumbleweed/openssl_3.0.x/x86_64/gcc7:
|
||||
tumbleweed/openssl_3.x/x86_64/gcc7:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7"
|
||||
|
||||
tumbleweed/openssl_3.0.x/x86/gcc7:
|
||||
tumbleweed/openssl_3.x/x86/gcc7:
|
||||
extends: .tumbleweed
|
||||
script:
|
||||
- cmake
|
||||
@@ -476,7 +557,7 @@ tumbleweed/openssl_3.0.x/x86/gcc7:
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
tumbleweed/openssl_3.0.x/x86_64/clang:
|
||||
tumbleweed/openssl_3.x/x86_64/clang:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
|
||||
@@ -486,6 +567,11 @@ tumbleweed/mbedtls-3.6.x/x86_64/gcc:
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
|
||||
|
||||
tumbleweed/mbedtls-3.6.x/x86_64/clang:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
|
||||
|
||||
tumbleweed/static-analysis:
|
||||
extends: .tests
|
||||
stage: analysis
|
||||
@@ -547,9 +633,7 @@ freebsd/openssl_1.1.1/x86_64:
|
||||
# 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:
|
||||
@@ -641,3 +725,41 @@ coverity:
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/cov-int/*.txt
|
||||
|
||||
###############################################################################
|
||||
# MacOS #
|
||||
###############################################################################
|
||||
.macos:
|
||||
tags:
|
||||
- saas-macos-medium-m1
|
||||
image: macos-14-xcode-15
|
||||
before_script:
|
||||
- echo "MacOS runner started"
|
||||
- brew update
|
||||
- brew install cmake openssl cmocka doxygen
|
||||
- mkdir obj && cd obj
|
||||
only:
|
||||
- branches@libssh/libssh-mirror
|
||||
- branches@cryptomilk/libssh-mirror
|
||||
- branches@jjelen/libssh-mirror
|
||||
- branches@marco.fortina/libssh-mirror
|
||||
|
||||
# TODO add -DFUZZ_TESTING=ON clang cant find _LLVMFuzzerInitialize on arm64
|
||||
macos-m1:
|
||||
extends: .macos
|
||||
variables:
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
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"
|
||||
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
|
||||
stage: test
|
||||
script:
|
||||
- cmake $CMAKE_OPTIONS .. &&
|
||||
make -j$(sysctl -n hw.logicalcpu) &&
|
||||
ctest --output-on-failure
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
42
.gitlab-ci/checkabi.sh
Executable file
42
.gitlab-ci/checkabi.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
INSTALL_DIR1=${1}
|
||||
INSTALL_DIR2=${2}
|
||||
|
||||
abidiff \
|
||||
--headers-dir1 "${INSTALL_DIR1}/include/libssh/" \
|
||||
--headers-dir2 "${INSTALL_DIR2}/include/libssh/" \
|
||||
"${INSTALL_DIR1}/lib64/libssh.so" \
|
||||
"${INSTALL_DIR2}/lib64/libssh.so" \
|
||||
--fail-no-debug-info
|
||||
abiret=$?
|
||||
|
||||
ABIDIFF_ERROR=$(((abiret & 0x01) != 0))
|
||||
ABIDIFF_USAGE_ERROR=$(((abiret & 0x02) != 0))
|
||||
ABIDIFF_ABI_CHANGE=$(((abiret & 0x04) != 0))
|
||||
ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$(((abiret & 0x08) != 0))
|
||||
ABIDIFF_UNKNOWN_BIT_SET=$(((abiret & 0xf0) != 0))
|
||||
|
||||
if [ $ABIDIFF_ERROR -ne 0 ]; then
|
||||
echo "abidiff reported ABIDIFF_ERROR."
|
||||
exit 1
|
||||
fi
|
||||
if [ $ABIDIFF_USAGE_ERROR -ne 0 ]; then
|
||||
echo "abidiff reported ABIDIFF_USAGE_ERROR."
|
||||
exit 1
|
||||
fi
|
||||
if [ $ABIDIFF_UNKNOWN_BIT_SET -ne 0 ]; then
|
||||
echo "abidiff reported ABIDIFF_UNKNOWN_BIT_SET."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $ABIDIFF_ABI_INCOMPATIBLE_CHANGE -ne 0 ]; then
|
||||
echo "abidiff result ABIDIFF_ABI_INCOMPATIBLE_CHANGE, this breaks the API!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $ABIDIFF_ABI_CHANGE -ne 0 ]; then
|
||||
echo "Ignoring abidiff result ABI_CHANGE"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
16
.gitlab/merge_request_templates/default.md
Normal file
16
.gitlab/merge_request_templates/default.md
Normal file
@@ -0,0 +1,16 @@
|
||||
Add a description of the new feature/bug fix. Reference any relevant bugs.
|
||||
|
||||
## Checklist
|
||||
* [ ] Commits have `Signed-off-by:` with name/author being identical to the commit author
|
||||
* [ ] Code modified for feature
|
||||
* [ ] Test suite updated with functionality tests
|
||||
* [ ] Test suite updated with negative tests
|
||||
* [ ] Documentation updated
|
||||
* [ ] The project pipelines timeout is [extended](https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run) at least to 2 hours.
|
||||
|
||||
## Reviewer's checklist:
|
||||
* [ ] Any issues marked for closing are addressed
|
||||
* [ ] There is a test suite reasonably covering new functionality or modifications
|
||||
* [ ] Function naming, parameters, return values, types, etc., are consistent and according to [CONTRIBUTING.md](https://gitlab.com/libssh/libssh-mirror/-/blob/master/CONTRIBUTING.md)
|
||||
* [ ] This feature/change has adequate documentation added
|
||||
* [ ] No obvious mistakes in the code
|
||||
@@ -9,7 +9,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
|
||||
project(libssh VERSION 0.11.00 LANGUAGES C CXX)
|
||||
project(libssh VERSION 0.11.00 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -41,6 +41,8 @@ macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source buil
|
||||
# Copy library files to a lib sub-directory
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
||||
|
||||
set(LIBSSSH_PC_REQUIRES_PRIVATE "")
|
||||
|
||||
# search for libraries
|
||||
if (WITH_ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
@@ -66,6 +68,7 @@ find_package(Threads)
|
||||
|
||||
if (WITH_GSSAPI)
|
||||
find_package(GSSAPI)
|
||||
list(APPEND LIBSSH_PC_REQUIRES_PRIVATE ${GSSAPI_PC_REQUIRES})
|
||||
endif (WITH_GSSAPI)
|
||||
|
||||
if (WITH_NACL)
|
||||
@@ -190,6 +193,7 @@ endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
|
||||
# Coverage
|
||||
if (WITH_COVERAGE)
|
||||
ENABLE_LANGUAGE(CXX)
|
||||
include(CodeCoverage)
|
||||
setup_target_for_coverage_lcov(
|
||||
NAME "coverage"
|
||||
@@ -248,9 +252,15 @@ message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
|
||||
message(STATUS "Symbol versioning: ${WITH_SYMBOL_VERSIONING}")
|
||||
message(STATUS "Allow ABI break: ${WITH_ABI_BREAK}")
|
||||
message(STATUS "Release is final: ${WITH_FINAL}")
|
||||
if (WITH_HERMETIC_USR)
|
||||
message(STATUS "User global client config: ${USR_GLOBAL_CLIENT_CONFIG}")
|
||||
endif ()
|
||||
message(STATUS "Global client config: ${GLOBAL_CLIENT_CONFIG}")
|
||||
if (WITH_SERVER)
|
||||
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
|
||||
if (WITH_HERMETIC_USR)
|
||||
message(STATUS "User global bind config: ${USR_GLOBAL_BIND_CONFIG}")
|
||||
endif ()
|
||||
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
|
||||
endif()
|
||||
message(STATUS "********************************************")
|
||||
|
||||
|
||||
@@ -117,6 +117,25 @@ libssh Developer's Certificate of Origin for each patch, or inside each
|
||||
patch. Just the sign-off message is all that is required once we've
|
||||
received the initial email.
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
Contributing patches through Merge Request workflow on Gitlab allows us to run
|
||||
various checks on various configuration as part of Gitlab CI. Unfortunately,
|
||||
some pipelines are slower (as they involve building dependencies) so the default
|
||||
timeout of 1 hour needs to be extended at least to 2 hours. This can be done in
|
||||
project settings of your libssh fork:
|
||||
|
||||
https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run
|
||||
|
||||
Otherwise you will encounter errors like these, usually on visualstudio builds:
|
||||
|
||||
```
|
||||
ERROR: Job failed: execution took longer than 1h0m0s seconds
|
||||
The script exceeded the maximum execution time set for the job
|
||||
```
|
||||
|
||||
Note, that the built dependencies are cached so after successful build in your
|
||||
namespace, the rebuilds should be much faster.
|
||||
|
||||
# Coding conventions in the libssh tree
|
||||
|
||||
@@ -517,6 +536,37 @@ Bad example:
|
||||
break;
|
||||
}
|
||||
|
||||
## ABI Versioning and Symbol Management
|
||||
|
||||
To maintain [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) stability
|
||||
and ensure backward compatibility, libssh uses **symbol versioning** to track and manage
|
||||
exported functions and variables. This allows libssh to introduce new symbols or modify
|
||||
existing functions in an ABI-compatible way.
|
||||
|
||||
When introducing a new symbol:
|
||||
|
||||
1. Use the `LIBSSH_API` macro to mark the symbol as part of the public API.
|
||||
2. If you have [abimap](https://github.com/ansasaki/abimap) installed, the new symbols are
|
||||
automatically generated in the `src/libssh_dev.map` file in the **build** directory and used automatically for building the updated library. But, depending on the version of `abimap` under use, you may face linker errors like: `unable to find version dependency LIBSSH_4_9_0`. In this case, you need to manually replace the existing `src/libssh.map` file with the generated `libssh_dev.map` file to update the symbol versioning.
|
||||
3. If you do not have abimap installed, the modified/added symbols must manually be added to the
|
||||
`src/libssh.map` file. The symbols must be added in the following format (assuming that 4_10_0 is the latest released version):
|
||||
|
||||
```
|
||||
LIBSSH_AFTER_4_10_0
|
||||
{
|
||||
global:
|
||||
new_function;
|
||||
new_variable;
|
||||
} LIBSSH_4_10_0;
|
||||
```
|
||||
4. After following either of the above steps, the library can be successfully built and
|
||||
tested without any linker errors.
|
||||
|
||||
5. When submitting the patch, make sure that any new symbols have been added to `libssh.map` as described in step 3, so that the new additions may not be excluded from the next release due to human error.
|
||||
|
||||
Also, to maintain ABI compatibility, existing symbols must not be removed. Instead, they can
|
||||
be marked as deprecated using the `LIBSSH_DEPRECATED` macro. This allows the symbol to be
|
||||
removed in a future release without breaking the ABI.
|
||||
|
||||
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$;/[.]git/;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]bare/;/[.]git/;/[.]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,7 +16,6 @@ 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)
|
||||
@@ -49,6 +48,7 @@ if (UNIX)
|
||||
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,9 +92,12 @@ if (UNIX)
|
||||
endif (WITH_STACK_PROTECTOR_STRONG)
|
||||
|
||||
if (NOT WINDOWS AND NOT CYGWIN)
|
||||
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")
|
||||
# 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()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ 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)
|
||||
@@ -225,6 +226,7 @@ if (GCRYPT_FOUND)
|
||||
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
||||
if (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
|
||||
set(HAVE_GCRYPT_CHACHA_POLY 1)
|
||||
set(HAVE_GCRYPT_CURVE25519 1)
|
||||
endif (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
@@ -235,6 +237,13 @@ 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 (MBEDTLS_VERSION VERSION_LESS "3.0.0")
|
||||
check_symbol_exists(MBEDTLS_ECP_DP_CURVE25519_ENABLED "config.h" HAVE_MBEDTLS_CURVE25519)
|
||||
else()
|
||||
check_symbol_exists(MBEDTLS_ECP_DP_CURVE25519_ENABLED "mbedtls_config.h" HAVE_MBEDTLS_CURVE25519)
|
||||
endif()
|
||||
|
||||
|
||||
if (WITH_BLOWFISH_CIPHER)
|
||||
check_include_file(blowfish.h HAVE_BLOWFISH)
|
||||
endif()
|
||||
|
||||
@@ -27,6 +27,7 @@ option(WITH_INSECURE_NONE "Enable insecure none cipher and MAC algorithms (not s
|
||||
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)
|
||||
option(WITH_HERMETIC_USR "Build with support for hermetic /usr/" OFF)
|
||||
|
||||
if (WITH_ZLIB)
|
||||
set(WITH_LIBZ ON)
|
||||
@@ -59,6 +60,11 @@ if (NOT GLOBAL_CLIENT_CONFIG)
|
||||
set(GLOBAL_CLIENT_CONFIG "/etc/ssh/ssh_config")
|
||||
endif (NOT GLOBAL_CLIENT_CONFIG)
|
||||
|
||||
if (WITH_HERMETIC_USR)
|
||||
set(USR_GLOBAL_BIND_CONFIG "/usr${GLOBAL_BIND_CONFIG}")
|
||||
set(USR_GLOBAL_CLIENT_CONFIG "/usr${GLOBAL_CLIENT_CONFIG}")
|
||||
endif (WITH_HERMETIC_USR)
|
||||
|
||||
if (FUZZ_TESTING)
|
||||
set(WITH_INSECURE_NONE ON)
|
||||
endif (FUZZ_TESTING)
|
||||
|
||||
6
INSTALL
6
INSTALL
@@ -38,14 +38,16 @@ First, you need to configure the compilation, using CMake. Go inside the
|
||||
`build` dir. Create it if it doesn't exist.
|
||||
|
||||
GNU/Linux, MacOS X, MSYS/MinGW:
|
||||
|
||||
cmake -DUNIT_TESTING=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
|
||||
make
|
||||
|
||||
On Windows you should choose a makefile generator with -G or use
|
||||
|
||||
cmake-gui.exe ..
|
||||
|
||||
To enable building tests use -DUNIT_TESTING=ON. For this, the
|
||||
[cmocka](https://cmocka.org) dependency is required.
|
||||
|
||||
To enable additional client tests against a local OpenSSH server, add the
|
||||
compile option -DCLIENT_TESTING=ON. These tests require an OpenSSH
|
||||
server package and some wrapper libraries (see optional requirements) to
|
||||
|
||||
@@ -117,6 +117,7 @@ function(ADD_CMOCKA_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)
|
||||
|
||||
@@ -39,6 +39,15 @@ 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
|
||||
@@ -56,8 +65,10 @@ find_library(GCRYPT_ERROR_LIBRARY
|
||||
libgpg-error6-0
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY} ${GCRYPT_ERROR_LIBRARY})
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_ERROR_LIBRARY} ${GCRYPT_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]")
|
||||
@@ -83,5 +94,25 @@ else (GCRYPT_VERSION)
|
||||
GCRYPT_LIBRARIES)
|
||||
endif (GCRYPT_VERSION)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES)
|
||||
# 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()
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
# GSSAPI_INCLUDE_DIR - the GSSAPI include directory
|
||||
# GSSAPI_LIBRARIES - Link these to use GSSAPI
|
||||
# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI
|
||||
# GSSAPI_PC_REQUIRES - pkg-config module name if found, needed for
|
||||
# Requires.private for static linking
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
|
||||
@@ -24,12 +26,23 @@
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
set(_mit_modname "mit-krb5-gssapi")
|
||||
set(_heimdal_modname "heimdal-gssapi")
|
||||
|
||||
if(NOT _GSSAPI_ROOT_HINTS AND NOT _GSSAPI_ROOT_PATHS)
|
||||
find_package(PkgConfig QUIET)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(_GSSAPI ${_mit_modname} ${_heimdal_modname})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_path(GSSAPI_ROOT_DIR
|
||||
NAMES
|
||||
include/gssapi.h
|
||||
include/gssapi/gssapi.h
|
||||
HINTS
|
||||
${_GSSAPI_ROOT_HINTS}
|
||||
"${_GSSAPI_INCLUDEDIR}"
|
||||
PATHS
|
||||
${_GSSAPI_ROOT_PATHS}
|
||||
)
|
||||
@@ -317,9 +330,15 @@ endif (GSSAPI_FLAVOR_HEIMDAL)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
|
||||
|
||||
if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
|
||||
set(GSSAPI_FOUND TRUE)
|
||||
endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
|
||||
if(GSSAPI_FOUND)
|
||||
if(_GSSAPI_FOUND) # via pkg-config
|
||||
if (GSSAPI_FLAVOR_MIT)
|
||||
set(GSSAPI_PC_REQUIRES ${_mit_modname})
|
||||
elseif (GSSAPI_FLAVOR_HEIMDAL)
|
||||
set(GSSAPI_PC_REQUIRES ${_heimdal_modname})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)
|
||||
# show the GSSAPI_INCLUDE_DIR and GSSAPI_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GSSAPI_INCLUDE_DIR GSSAPI_LIBRARIES)
|
||||
|
||||
@@ -72,21 +72,23 @@ find_library(MBEDTLS_X509_LIBRARY
|
||||
set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY}
|
||||
${MBEDTLS_X509_LIBRARY})
|
||||
|
||||
# mbedtls 2.8
|
||||
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]+).*"
|
||||
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
|
||||
endif()
|
||||
|
||||
# mbedtls 3.6
|
||||
if (NOT MBEDTLS_VERSION AND MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
|
||||
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.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]+).*"
|
||||
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+\\.[0-9]+\\.[0-9]+).*$"
|
||||
"\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if (MBEDTLS_VERSION)
|
||||
@@ -110,3 +112,32 @@ 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()
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
#cmakedefine SOURCEDIR "${SOURCEDIR}"
|
||||
|
||||
/* Global bind configuration file path */
|
||||
#cmakedefine USR_GLOBAL_BIND_CONFIG "${USR_GLOBAL_BIND_CONFIG}"
|
||||
#cmakedefine GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}"
|
||||
|
||||
/* Global client configuration file path */
|
||||
#cmakedefine USR_GLOBAL_CLIENT_CONFIG "${USR_GLOBAL_CLIENT_CONFIG}"
|
||||
#cmakedefine GLOBAL_CLIENT_CONFIG "${GLOBAL_CLIENT_CONFIG}"
|
||||
|
||||
/************************** HEADER FILES *************************/
|
||||
@@ -58,6 +60,9 @@
|
||||
/* 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
|
||||
|
||||
@@ -82,6 +87,9 @@
|
||||
/* Define to 1 if you have elliptic curve cryptography in openssl */
|
||||
#cmakedefine HAVE_OPENSSL_ECC 1
|
||||
|
||||
/* Define to 1 if mbedTLS supports curve25519 */
|
||||
#cmakedefine HAVE_MBEDTLS_CURVE25519 1
|
||||
|
||||
/* Define to 1 if you have elliptic curve cryptography in gcrypt */
|
||||
#cmakedefine HAVE_GCRYPT_ECC 1
|
||||
|
||||
@@ -94,6 +102,9 @@
|
||||
/* Define to 1 if you have gcrypt with ChaCha20/Poly1305 support */
|
||||
#cmakedefine HAVE_GCRYPT_CHACHA_POLY 1
|
||||
|
||||
/* Define to 1 if you have gcrypt with curve25519 support */
|
||||
#cmakedefine HAVE_GCRYPT_CURVE25519
|
||||
|
||||
/*************************** FUNCTIONS ***************************/
|
||||
|
||||
/* Define to 1 if you have the `EVP_chacha20' function. */
|
||||
|
||||
@@ -105,7 +105,7 @@ Here is a small example of password authentication:
|
||||
@code
|
||||
int authenticate_password(ssh_session session)
|
||||
{
|
||||
char *password;
|
||||
char *password = NULL;
|
||||
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, *instruction;
|
||||
const char *name = NULL, *instruction = NULL;
|
||||
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;
|
||||
const char *prompt = NULL;
|
||||
char echo;
|
||||
|
||||
prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
|
||||
@@ -251,7 +251,7 @@ int authenticate_kbdint(ssh_session session)
|
||||
}
|
||||
else
|
||||
{
|
||||
char *ptr;
|
||||
char *ptr = NULL;
|
||||
|
||||
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;
|
||||
char *banner = NULL;
|
||||
|
||||
/*
|
||||
*** 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;
|
||||
ssh_channel channel = NULL;
|
||||
int rc;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
@@ -91,4 +91,10 @@ that it used:
|
||||
}
|
||||
@endcode
|
||||
|
||||
Warning: In a single channel, only ONE command can be executed!
|
||||
If you want to executed multiple commands, allocate separate channels for
|
||||
them or consider opening interactive shell.
|
||||
Attempting to run multiple consecutive commands in one channel will fail.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
ssh_channel forwarding_channel = NULL;
|
||||
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;
|
||||
ssh_channel channel = NULL;
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
int port = 0;
|
||||
|
||||
@@ -79,7 +79,7 @@ Here is a small example of how to use it:
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
ssh_session my_ssh_session = NULL;
|
||||
int verbosity = SSH_LOG_PROTOCOL;
|
||||
int port = 22;
|
||||
|
||||
@@ -126,7 +126,7 @@ Here's an example:
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
ssh_session my_ssh_session = NULL;
|
||||
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;
|
||||
char *p;
|
||||
char *hexa = NULL;
|
||||
char *p = NULL;
|
||||
int cmp;
|
||||
int rc;
|
||||
|
||||
@@ -317,9 +317,9 @@ The example below shows an authentication with password:
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
ssh_session my_ssh_session = NULL;
|
||||
int rc;
|
||||
char *password;
|
||||
char *password = NULL;
|
||||
|
||||
// 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;
|
||||
ssh_channel channel = NULL;
|
||||
int rc;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
|
||||
@@ -19,7 +19,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>Key Exchange Methods</strong>: <i>sntrup761x25519-sha512@openssh.com, 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>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
|
||||
|
||||
@@ -81,10 +81,6 @@ 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. But it has some issues with
|
||||
OpenSSL initialization/cleanup when used with OpenSSL 3.0 so we are using it
|
||||
indirectly through a p11-kit remoting as described in the following article:
|
||||
|
||||
https://p11-glue.github.io/p11-glue/p11-kit/manual/remoting.html
|
||||
For testing, the SoftHSM PKCS#11 library is used.
|
||||
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,7 @@ The code sample below achieves these tasks:
|
||||
@code
|
||||
int shell_session(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
ssh_channel channel = NULL;
|
||||
int rc;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
|
||||
@@ -303,7 +303,6 @@ span.lineno {
|
||||
padding-right: 4px;
|
||||
text-align: right;
|
||||
color: black;
|
||||
height: 100px;
|
||||
white-space: pre;
|
||||
border-right: 3px solid #1d7567;
|
||||
background-color: #323232; }
|
||||
|
||||
@@ -30,9 +30,11 @@ if (UNIX AND NOT WIN32)
|
||||
target_compile_options(samplesftp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(samplesftp ssh::ssh)
|
||||
|
||||
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})
|
||||
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;
|
||||
const char *name;
|
||||
const char *instruction = NULL;
|
||||
const char *name = NULL;
|
||||
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;
|
||||
const char *prompt;
|
||||
const char *answer = NULL;
|
||||
const char *prompt = NULL;
|
||||
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;
|
||||
char *p = NULL;
|
||||
|
||||
printf("%s", prompt);
|
||||
|
||||
@@ -66,7 +66,6 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
if ((p = strchr(buffer, '\n'))) {
|
||||
*p = '\0';
|
||||
}
|
||||
@@ -75,7 +74,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
memset(buffer, 0, strlen(buffer));
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
} else {
|
||||
if (password && strstr(prompt, "Password:")) {
|
||||
answer = password;
|
||||
@@ -143,11 +142,11 @@ int authenticate_console(ssh_session session)
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *banner;
|
||||
char *banner = NULL;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
|
||||
error(session);
|
||||
return rc;
|
||||
}
|
||||
@@ -156,7 +155,7 @@ int authenticate_console(ssh_session session)
|
||||
while (rc != SSH_AUTH_SUCCESS) {
|
||||
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
|
||||
rc = ssh_userauth_gssapi(session);
|
||||
if(rc == SSH_AUTH_ERROR) {
|
||||
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
@@ -166,7 +165,7 @@ int authenticate_console(ssh_session session)
|
||||
// Try to authenticate with public key first
|
||||
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
@@ -206,7 +205,7 @@ int authenticate_console(ssh_session session)
|
||||
// Try to authenticate with keyboard interactive";
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||
rc = authenticate_kbdint(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
@@ -221,7 +220,7 @@ int authenticate_console(ssh_session session)
|
||||
// Try to authenticate with password
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD) {
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
|
||||
@@ -21,47 +21,50 @@ clients must be made or how a client should react.
|
||||
#include "examples_common.h"
|
||||
#include <stdio.h>
|
||||
|
||||
ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
ssh_session session;
|
||||
int auth=0;
|
||||
ssh_session connect_ssh(const char *host, const char *user, int verbosity)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
int auth = 0;
|
||||
|
||||
session=ssh_new();
|
||||
if (session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(user != NULL){
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
session = ssh_new();
|
||||
if (session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
if (user != NULL) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
if (ssh_connect(session)) {
|
||||
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
if (verify_knownhost(session) < 0) {
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
auth = authenticate_console(session);
|
||||
if (auth == SSH_AUTH_SUCCESS) {
|
||||
return session;
|
||||
} else if (auth == SSH_AUTH_DENIED) {
|
||||
fprintf(stderr, "Authentication failed\n");
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error while authenticating : %s\n",
|
||||
ssh_get_error(session));
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
if(verify_knownhost(session)<0){
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
if(auth==SSH_AUTH_SUCCESS){
|
||||
return session;
|
||||
} else if(auth==SSH_AUTH_DENIED){
|
||||
fprintf(stderr,"Authentication failed\n");
|
||||
} else {
|
||||
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ clients must be made or how a client should react.
|
||||
#include <libssh/libssh.h>
|
||||
|
||||
/** Zero a structure */
|
||||
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
|
||||
#define ZERO_STRUCT(x) memset(&(x), 0, sizeof(x))
|
||||
|
||||
int authenticate_console(ssh_session session);
|
||||
int authenticate_kbdint(ssh_session session, const char *password);
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include "examples_common.h"
|
||||
|
||||
int main(void) {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
ssh_session session = NULL;
|
||||
ssh_channel channel = NULL;
|
||||
char buffer[256];
|
||||
int rbytes, wbytes, total = 0;
|
||||
int rc;
|
||||
|
||||
@@ -350,7 +350,12 @@ int main(int argc, char *argv[])
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (arguments.action_list && arguments.file) {
|
||||
if (arguments.file == NULL) {
|
||||
fprintf(stderr, "Error: Missing argument file\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (arguments.action_list) {
|
||||
list_fingerprint(arguments.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;
|
||||
ssh_key srv_pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
rc = ssh_get_server_publickey(session, &srv_pubkey);
|
||||
|
||||
@@ -26,9 +26,9 @@ program.
|
||||
#define BUF_SIZE 16384
|
||||
#endif
|
||||
|
||||
static char **sources;
|
||||
static char **sources = NULL;
|
||||
static int nsources;
|
||||
static char *destination;
|
||||
static char *destination = NULL;
|
||||
static int verbosity = 0;
|
||||
|
||||
struct location {
|
||||
@@ -114,9 +114,14 @@ static void location_free(struct location *loc)
|
||||
}
|
||||
}
|
||||
|
||||
static struct location *parse_location(char *loc) {
|
||||
struct location *location;
|
||||
char *ptr;
|
||||
static struct location *parse_location(char *loc)
|
||||
{
|
||||
struct location *location = NULL;
|
||||
char *ptr = NULL;
|
||||
|
||||
if (loc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
location = malloc(sizeof(struct location));
|
||||
if (location == NULL) {
|
||||
|
||||
@@ -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;
|
||||
static ssh_channel chan = NULL;
|
||||
static char *username = NULL;
|
||||
static ssh_gssapi_creds client_creds = NULL;
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
@@ -204,11 +204,12 @@ 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;
|
||||
ssh_bind sshbind;
|
||||
ssh_event mainloop;
|
||||
ssh_session client_session;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_event mainloop = NULL;
|
||||
ssh_session client_session = NULL;
|
||||
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
@@ -219,7 +220,7 @@ int main(int argc, char **argv){
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
char host[128]="";
|
||||
char *ptr;
|
||||
char *ptr = NULL;
|
||||
int i,r, rc;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
@@ -336,4 +337,3 @@ int main(int argc, char **argv){
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -244,10 +244,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;
|
||||
ssh_bind sshbind;
|
||||
ssh_event mainloop;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_event mainloop = NULL;
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_none_function = auth_none,
|
||||
@@ -339,4 +340,3 @@ int main(int argc, char **argv){
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,8 +174,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;
|
||||
static const char *instruction;
|
||||
static const char *name = NULL;
|
||||
static const char *instruction = NULL;
|
||||
static const char *prompts[2];
|
||||
static char echo[] = { 1, 0 };
|
||||
|
||||
@@ -279,11 +279,12 @@ static int authenticate(ssh_session session) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_message message;
|
||||
ssh_channel chan=0;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_bind sshbind = NULL;
|
||||
ssh_message message = NULL;
|
||||
ssh_channel chan = NULL;
|
||||
char buf[BUF_SIZE];
|
||||
int auth=0;
|
||||
int shell=0;
|
||||
@@ -411,4 +412,3 @@ int main(int argc, char **argv){
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,151 +32,163 @@ static const char *createcommand =
|
||||
"cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
|
||||
static char *host = NULL;
|
||||
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [options] host\n"
|
||||
"sample tiny scp downloader client - libssh-%s\n"
|
||||
"This program will create files in /tmp and try to fetch them\n",
|
||||
// "Options :\n",
|
||||
// " -r : use RSA to verify host public key\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
static void usage(const char *argv0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage : %s [options] host\n"
|
||||
"sample tiny scp downloader client - libssh-%s\n"
|
||||
"This program will create files in /tmp and try to fetch them\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
static int opts(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
host = argv[optind];
|
||||
if (host == NULL)
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create_files(ssh_session session)
|
||||
{
|
||||
ssh_channel channel = ssh_channel_new(session);
|
||||
char buffer[1];
|
||||
int rc;
|
||||
|
||||
if (channel == NULL) {
|
||||
fprintf(stderr, "Error creating channel: %s\n", ssh_get_error(session));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (ssh_channel_open_session(channel) != SSH_OK) {
|
||||
fprintf(stderr, "Error creating channel: %s\n", ssh_get_error(session));
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (ssh_channel_request_exec(channel, createcommand) != SSH_OK) {
|
||||
fprintf(stderr,
|
||||
"Error executing command: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while (!ssh_channel_is_eof(channel)) {
|
||||
rc = ssh_channel_read(channel, buffer, 1, 1);
|
||||
if (rc != 1) {
|
||||
fprintf(stderr, "Error reading from channel\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = write(1, buffer, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
static int fetch_files(ssh_session session)
|
||||
{
|
||||
int size;
|
||||
char buffer[BUF_SIZE];
|
||||
int mode;
|
||||
char *filename = NULL;
|
||||
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) {
|
||||
fprintf(stderr, "error initializing scp: %s\n", ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
host = argv[optind];
|
||||
if(host == NULL)
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
|
||||
do {
|
||||
r = ssh_scp_pull_request(scp);
|
||||
switch (r) {
|
||||
case SSH_SCP_REQUEST_NEWFILE:
|
||||
size = ssh_scp_request_get_size(scp);
|
||||
filename = strdup(ssh_scp_request_get_filename(scp));
|
||||
mode = ssh_scp_request_get_permissions(scp);
|
||||
printf("downloading file %s, size %d, perms 0%o\n",
|
||||
filename,
|
||||
size,
|
||||
mode);
|
||||
free(filename);
|
||||
ssh_scp_accept_request(scp);
|
||||
r = ssh_scp_read(scp, buffer, sizeof(buffer));
|
||||
if (r == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"Error reading scp: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("done\n");
|
||||
break;
|
||||
case SSH_ERROR:
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
case SSH_SCP_REQUEST_WARNING:
|
||||
fprintf(stderr, "Warning: %s\n", ssh_scp_request_get_warning(scp));
|
||||
break;
|
||||
case SSH_SCP_REQUEST_NEWDIR:
|
||||
filename = strdup(ssh_scp_request_get_filename(scp));
|
||||
mode = ssh_scp_request_get_permissions(scp);
|
||||
printf("downloading directory %s, perms 0%o\n", filename, mode);
|
||||
free(filename);
|
||||
ssh_scp_accept_request(scp);
|
||||
break;
|
||||
case SSH_SCP_REQUEST_ENDDIR:
|
||||
printf("End of directory\n");
|
||||
break;
|
||||
case SSH_SCP_REQUEST_EOF:
|
||||
printf("End of requests\n");
|
||||
goto end;
|
||||
}
|
||||
} while (1);
|
||||
end:
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create_files(ssh_session session){
|
||||
ssh_channel channel=ssh_channel_new(session);
|
||||
char buffer[1];
|
||||
int rc;
|
||||
|
||||
if(channel == NULL){
|
||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(ssh_channel_open_session(channel) != SSH_OK){
|
||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
|
||||
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while(!ssh_channel_is_eof(channel)){
|
||||
rc = ssh_channel_read(channel,buffer,1,1);
|
||||
if (rc != 1) {
|
||||
fprintf(stderr, "Error reading from channel\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = write(1, buffer, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
|
||||
static int fetch_files(ssh_session session){
|
||||
int size;
|
||||
char buffer[BUF_SIZE];
|
||||
int mode;
|
||||
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){
|
||||
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
|
||||
do {
|
||||
|
||||
r=ssh_scp_pull_request(scp);
|
||||
switch(r){
|
||||
case SSH_SCP_REQUEST_NEWFILE:
|
||||
size=ssh_scp_request_get_size(scp);
|
||||
filename=strdup(ssh_scp_request_get_filename(scp));
|
||||
mode=ssh_scp_request_get_permissions(scp);
|
||||
printf("downloading file %s, size %d, perms 0%o\n",filename,size,mode);
|
||||
free(filename);
|
||||
ssh_scp_accept_request(scp);
|
||||
r=ssh_scp_read(scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("done\n");
|
||||
break;
|
||||
case SSH_ERROR:
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
case SSH_SCP_REQUEST_WARNING:
|
||||
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
|
||||
break;
|
||||
case SSH_SCP_REQUEST_NEWDIR:
|
||||
filename=strdup(ssh_scp_request_get_filename(scp));
|
||||
mode=ssh_scp_request_get_permissions(scp);
|
||||
printf("downloading directory %s, perms 0%o\n",filename,mode);
|
||||
free(filename);
|
||||
ssh_scp_accept_request(scp);
|
||||
break;
|
||||
case SSH_SCP_REQUEST_ENDDIR:
|
||||
printf("End of directory\n");
|
||||
break;
|
||||
case SSH_SCP_REQUEST_EOF:
|
||||
printf("End of requests\n");
|
||||
goto end;
|
||||
}
|
||||
} while (1);
|
||||
end:
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
session=connect_ssh(host,NULL,verbosity);
|
||||
if(session == NULL)
|
||||
return EXIT_FAILURE;
|
||||
create_files(session);
|
||||
fetch_files(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
if (opts(argc, argv) < 0)
|
||||
return EXIT_FAILURE;
|
||||
session = connect_ssh(host, NULL, verbosity);
|
||||
if (session == NULL)
|
||||
return EXIT_FAILURE;
|
||||
create_files(session);
|
||||
fetch_files(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,60 +5,60 @@
|
||||
|
||||
#define LIMIT 0x100000000UL
|
||||
|
||||
int main(void) {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[1024*1024];
|
||||
int rc;
|
||||
uint64_t total=0;
|
||||
uint64_t lastshown=4096;
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc < 0) {
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
|
||||
if (rc < 0) {
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
|
||||
total += rc;
|
||||
if(total/2 >= lastshown){
|
||||
printf("written %llx\n", (long long unsigned int) total);
|
||||
lastshown=total;
|
||||
int main(void)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
ssh_channel channel = NULL;
|
||||
char buffer[1024 * 1024] = {0};
|
||||
int rc;
|
||||
uint64_t total = 0;
|
||||
uint64_t lastshown = 4096;
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
return 1;
|
||||
}
|
||||
if(total > LIMIT)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc < 0) {
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
|
||||
if (rc < 0) {
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
|
||||
total += rc;
|
||||
if (total / 2 >= lastshown) {
|
||||
printf("written %llx\n", (long long unsigned int)total);
|
||||
lastshown = total;
|
||||
}
|
||||
if (total > LIMIT)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
printf("error : %s\n", ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
|
||||
ssh_disconnect(session);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <stddef.h>
|
||||
@@ -231,7 +232,7 @@ static void _logging_callback(int priority, const char *function,
|
||||
|
||||
milliseconds = _current_timestamp();
|
||||
|
||||
fprintf(fp, "[%s.%jd, %d] %s: %s\n", buf, milliseconds, priority,
|
||||
fprintf(fp, "[%s.%" PRId64 ", %d] %s: %s\n", buf, milliseconds, priority,
|
||||
function, buffer);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ static struct termios terminal;
|
||||
|
||||
static char *pcap_file = NULL;
|
||||
|
||||
static char *proxycommand;
|
||||
static char *proxycommand = NULL;
|
||||
|
||||
static int auth_callback(const char *prompt,
|
||||
char *buf,
|
||||
@@ -251,7 +251,7 @@ static void select_loop(ssh_session session,ssh_channel channel)
|
||||
|
||||
static void shell(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
ssh_channel channel = NULL;
|
||||
struct termios terminal_local;
|
||||
int interactive=isatty(0);
|
||||
|
||||
@@ -339,7 +339,7 @@ static void batch_shell(ssh_session session)
|
||||
static int client(ssh_session session)
|
||||
{
|
||||
int auth = 0;
|
||||
char *banner;
|
||||
char *banner = NULL;
|
||||
int state;
|
||||
|
||||
if (user) {
|
||||
@@ -423,7 +423,7 @@ static void cleanup_pcap(void)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session;
|
||||
ssh_session session = NULL;
|
||||
|
||||
ssh_init();
|
||||
session = ssh_new();
|
||||
|
||||
@@ -192,9 +192,6 @@ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
static int
|
||||
parse_opt(int argc, char **argv, ssh_bind sshbind)
|
||||
{
|
||||
int no_default_keys = 0;
|
||||
int rsa_already_set = 0;
|
||||
int ecdsa_already_set = 0;
|
||||
int key;
|
||||
|
||||
while((key = getopt(argc, argv, "a:e:k:p:P:r:u:v")) != -1) {
|
||||
@@ -202,16 +199,10 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, optarg);
|
||||
} 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
|
||||
option, so let's ensure we keep the keys we're adding
|
||||
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);
|
||||
rsa_already_set = 1;
|
||||
} else if (key == 'e') {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
|
||||
ecdsa_already_set = 1;
|
||||
} else if (key == 'a') {
|
||||
strncpy(authorizedkeys, optarg, DEF_STR_SIZE-1);
|
||||
} else if (key == 'u') {
|
||||
@@ -256,12 +247,6 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, argv[optind]);
|
||||
|
||||
if (!no_default_keys) {
|
||||
set_default_keys(sshbind,
|
||||
rsa_already_set,
|
||||
ecdsa_already_set);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
@@ -361,7 +361,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;
|
||||
ssh_session session = NULL;
|
||||
int len, i, wr;
|
||||
char buf[BUF_SIZE];
|
||||
int blocking;
|
||||
@@ -455,8 +455,8 @@ open_tcp_socket(ssh_message msg)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int forwardsock = -1;
|
||||
struct hostent *host;
|
||||
const char *dest_hostname;
|
||||
struct hostent *host = NULL;
|
||||
const char *dest_hostname = NULL;
|
||||
int dest_port;
|
||||
|
||||
forwardsock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
@@ -499,8 +499,8 @@ message_callback(UNUSED_PARAM(ssh_session session),
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
ssh_channel channel;
|
||||
int socket_fd, *pFd;
|
||||
struct ssh_channel_callbacks_struct *cb_chan;
|
||||
int socket_fd, *pFd = NULL;
|
||||
struct ssh_channel_callbacks_struct *cb_chan = NULL;
|
||||
struct event_fd_data_struct *event_fd_data;
|
||||
|
||||
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d",
|
||||
@@ -655,8 +655,8 @@ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_session session = NULL;
|
||||
ssh_bind sshbind = NULL;
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_password_function = auth_password,
|
||||
|
||||
@@ -39,223 +39,237 @@ clients must be made or how a client should react.
|
||||
#define BUF_SIZE 4096
|
||||
#endif
|
||||
|
||||
char *host;
|
||||
const char *desthost="localhost";
|
||||
const char *port="22";
|
||||
char *host = NULL;
|
||||
const char *desthost = "localhost";
|
||||
const char *port = "22";
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
#include <libssh/pcap.h>
|
||||
char *pcap_file=NULL;
|
||||
char *pcap_file = NULL;
|
||||
#endif
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
|
||||
exit(1);
|
||||
fprintf(stderr,
|
||||
"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
static int opts(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"P:"))!=-1){
|
||||
switch(i){
|
||||
while ((i = getopt(argc, argv, "P:")) != -1) {
|
||||
switch (i) {
|
||||
#ifdef WITH_PCAP
|
||||
case 'P':
|
||||
pcap_file=optarg;
|
||||
break;
|
||||
case 'P':
|
||||
pcap_file = optarg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage();
|
||||
default:
|
||||
fprintf(stderr, "unknown option %c\n", optopt);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if(optind < argc)
|
||||
host=argv[optind++];
|
||||
if(optind < argc)
|
||||
desthost=argv[optind++];
|
||||
if(optind < argc)
|
||||
port=argv[optind++];
|
||||
if(host==NULL)
|
||||
if (optind < argc)
|
||||
host = argv[optind++];
|
||||
if (optind < argc)
|
||||
desthost = argv[optind++];
|
||||
if (optind < argc)
|
||||
port = argv[optind++];
|
||||
if (host == NULL)
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void select_loop(ssh_session session,ssh_channel channel){
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[BUF_SIZE];
|
||||
/* channels will be set to the channels to poll.
|
||||
* outchannels will contain the result of the poll
|
||||
*/
|
||||
ssh_channel channels[2], outchannels[2];
|
||||
int lus;
|
||||
int eof=0;
|
||||
int maxfd;
|
||||
int ret;
|
||||
while(channel){
|
||||
do{
|
||||
static void select_loop(ssh_session session, ssh_channel channel)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[BUF_SIZE];
|
||||
/* channels will be set to the channels to poll.
|
||||
* outchannels will contain the result of the poll
|
||||
*/
|
||||
ssh_channel channels[2], outchannels[2];
|
||||
int lus;
|
||||
int eof = 0;
|
||||
int maxfd;
|
||||
int ret;
|
||||
while (channel) {
|
||||
do {
|
||||
int fd;
|
||||
|
||||
ZERO_STRUCT(fds);
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
timeout.tv_usec=0;
|
||||
FD_ZERO(&fds);
|
||||
if (!eof)
|
||||
FD_SET(0, &fds);
|
||||
timeout.tv_sec = 30;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
fd = ssh_get_fd(session);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Error getting the session file descriptor: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr,
|
||||
"Error getting the session file descriptor: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
FD_SET(fd, &fds);
|
||||
maxfd = fd + 1;
|
||||
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||
if(ret==EINTR)
|
||||
continue;
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(outchannels[0]){
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){
|
||||
lus = ssh_channel_read(channel,buffer,sizeof(buffer),0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else {
|
||||
ret = write(1, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to stdin: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */
|
||||
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else {
|
||||
ret = write(2, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to stderr: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
channels[0] = channel; // set the first channel we want to read from
|
||||
channels[1] = NULL;
|
||||
ret = ssh_select(channels, outchannels, maxfd, &fds, &timeout);
|
||||
if (ret == EINTR)
|
||||
continue;
|
||||
if (FD_ISSET(0, &fds)) {
|
||||
lus = read(0, buffer, sizeof(buffer));
|
||||
if (lus)
|
||||
ssh_channel_write(channel, buffer, lus);
|
||||
else {
|
||||
eof = 1;
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if (channel && ssh_channel_is_closed(channel)) {
|
||||
ssh_channel_free(channel);
|
||||
channel = NULL;
|
||||
channels[0] = NULL;
|
||||
}
|
||||
if (outchannels[0]) {
|
||||
while (channel && ssh_channel_is_open(channel) &&
|
||||
ssh_channel_poll(channel, 0)) {
|
||||
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (lus == -1) {
|
||||
fprintf(stderr,
|
||||
"Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
}
|
||||
if (lus == 0) {
|
||||
ssh_channel_free(channel);
|
||||
channel = channels[0] = NULL;
|
||||
} else {
|
||||
ret = write(1, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr,
|
||||
"Error writing to stdin: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (channel && ssh_channel_is_open(channel) &&
|
||||
ssh_channel_poll(channel, 1)) { /* stderr */
|
||||
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
|
||||
if (lus == -1) {
|
||||
fprintf(stderr,
|
||||
"Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if (lus == 0) {
|
||||
ssh_channel_free(channel);
|
||||
channel = channels[0] = NULL;
|
||||
} else {
|
||||
ret = write(2, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr,
|
||||
"Error writing to stderr: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (channel && ssh_channel_is_closed(channel)) {
|
||||
ssh_channel_free(channel);
|
||||
channel = NULL;
|
||||
}
|
||||
} while (ret == EINTR || ret == SSH_EINTR);
|
||||
}
|
||||
}
|
||||
|
||||
static void forwarding(ssh_session session){
|
||||
static void forwarding(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
int r;
|
||||
channel = ssh_channel_new(session);
|
||||
r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22);
|
||||
if(r<0) {
|
||||
printf("error forwarding port : %s\n",ssh_get_error(session));
|
||||
if (r < 0) {
|
||||
printf("error forwarding port : %s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
select_loop(session,channel);
|
||||
select_loop(session, channel);
|
||||
}
|
||||
|
||||
static int client(ssh_session session){
|
||||
int auth=0;
|
||||
char *banner;
|
||||
int state;
|
||||
static int client(ssh_session session)
|
||||
{
|
||||
int auth = 0;
|
||||
char *banner = NULL;
|
||||
int state;
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
|
||||
return -1;
|
||||
ssh_options_parse_config(session, NULL);
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0)
|
||||
return -1;
|
||||
ssh_options_parse_config(session, NULL);
|
||||
|
||||
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;
|
||||
ssh_userauth_none(session, NULL);
|
||||
banner=ssh_get_issue_banner(session);
|
||||
if(banner){
|
||||
printf("%s\n",banner);
|
||||
free(banner);
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
if(auth != SSH_AUTH_SUCCESS){
|
||||
return -1;
|
||||
}
|
||||
forwarding(session);
|
||||
return 0;
|
||||
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;
|
||||
ssh_userauth_none(session, NULL);
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n", banner);
|
||||
free(banner);
|
||||
}
|
||||
auth = authenticate_console(session);
|
||||
if (auth != SSH_AUTH_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
forwarding(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
ssh_pcap_file pcap;
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
void set_pcap(ssh_session session)
|
||||
{
|
||||
if (!pcap_file)
|
||||
return;
|
||||
pcap = ssh_pcap_file_new();
|
||||
if (ssh_pcap_file_open(pcap, pcap_file) == SSH_ERROR) {
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap = NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session, pcap);
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(void)
|
||||
{
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap = NULL;
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
|
||||
session = ssh_new();
|
||||
|
||||
if(ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr, "error parsing command line :%s\n",
|
||||
ssh_get_error(session));
|
||||
usage();
|
||||
if (ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr,
|
||||
"error parsing command line :%s\n",
|
||||
ssh_get_error(session));
|
||||
usage();
|
||||
}
|
||||
opts(argc,argv);
|
||||
opts(argc, argv);
|
||||
#ifdef WITH_PCAP
|
||||
set_pcap(session);
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,7 @@ extern "C" {
|
||||
|
||||
bignum ssh_make_string_bn(ssh_string string);
|
||||
ssh_string ssh_make_bignum_string(bignum num);
|
||||
ssh_string ssh_make_padded_bignum_string(bignum num, size_t pad_len);
|
||||
void ssh_print_bignum(const char *which, const_bignum num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -113,6 +113,17 @@ typedef void (*ssh_status_callback) (ssh_session session, float status,
|
||||
typedef void (*ssh_global_request_callback) (ssh_session session,
|
||||
ssh_message message, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH connect status callback. These are functions that report the
|
||||
* status of the connection i,e. a function indicating the completed percentage
|
||||
* of the connection
|
||||
* steps.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @param status Percentage of connection status, going from 0.0 to 1.0
|
||||
* once connection is done.
|
||||
*/
|
||||
typedef void (*ssh_connect_status_callback)(void *userdata, float status);
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH new channel open X11 request. This happens when the server
|
||||
* sends back an X11 connection attempt. This is a client-side API
|
||||
@@ -181,7 +192,7 @@ struct ssh_callbacks_struct {
|
||||
* This function gets called during connection time to indicate the
|
||||
* percentage of connection steps completed.
|
||||
*/
|
||||
void (*connect_status_function)(void *userdata, float status);
|
||||
ssh_connect_status_callback connect_status_function;
|
||||
/**
|
||||
* This function will be called each time a global request is received.
|
||||
*/
|
||||
@@ -325,6 +336,28 @@ typedef int (*ssh_gssapi_accept_sec_ctx_callback) (ssh_session session,
|
||||
typedef int (*ssh_gssapi_verify_mic_callback) (ssh_session session,
|
||||
ssh_string mic, void *mic_buffer, size_t mic_buffer_size, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH new channel open "direct-tcpip" request. This
|
||||
* happens when the client forwards an incoming TCP connection on a port it
|
||||
* wants to forward to the destination. This is a server-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_direct_tcpip_callback)(
|
||||
ssh_session session,
|
||||
const char *destination_address,
|
||||
int destination_port,
|
||||
const char *originator_address,
|
||||
int originator_port,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* This structure can be used to implement a libssh server, with appropriate callbacks.
|
||||
@@ -375,6 +408,12 @@ struct ssh_server_callbacks_struct {
|
||||
/* This function will be called when a MIC needs to be verified.
|
||||
*/
|
||||
ssh_gssapi_verify_mic_callback gssapi_verify_mic_function;
|
||||
/**
|
||||
* This function will be called when an incoming "direct-tcpip"
|
||||
* request is received.
|
||||
*/
|
||||
ssh_channel_open_request_direct_tcpip_callback
|
||||
channel_open_request_direct_tcpip_function;
|
||||
};
|
||||
typedef struct ssh_server_callbacks_struct *ssh_server_callbacks;
|
||||
|
||||
|
||||
@@ -45,10 +45,11 @@
|
||||
#ifdef HAVE_OPENSSL_ECDH_H
|
||||
#include <openssl/ecdh.h>
|
||||
#endif
|
||||
#include "libssh/curve25519.h"
|
||||
#include "libssh/dh.h"
|
||||
#include "libssh/ecdh.h"
|
||||
#include "libssh/kex.h"
|
||||
#include "libssh/curve25519.h"
|
||||
#include "libssh/sntrup761.h"
|
||||
|
||||
#define DIGEST_MAX_LEN 64
|
||||
|
||||
@@ -56,32 +57,34 @@
|
||||
#define AES_GCM_IVLEN 12
|
||||
|
||||
enum ssh_key_exchange_e {
|
||||
/* diffie-hellman-group1-sha1 */
|
||||
SSH_KEX_DH_GROUP1_SHA1=1,
|
||||
/* diffie-hellman-group14-sha1 */
|
||||
SSH_KEX_DH_GROUP14_SHA1,
|
||||
/* diffie-hellman-group1-sha1 */
|
||||
SSH_KEX_DH_GROUP1_SHA1 = 1,
|
||||
/* diffie-hellman-group14-sha1 */
|
||||
SSH_KEX_DH_GROUP14_SHA1,
|
||||
#ifdef WITH_GEX
|
||||
/* diffie-hellman-group-exchange-sha1 */
|
||||
SSH_KEX_DH_GEX_SHA1,
|
||||
/* diffie-hellman-group-exchange-sha256 */
|
||||
SSH_KEX_DH_GEX_SHA256,
|
||||
/* diffie-hellman-group-exchange-sha1 */
|
||||
SSH_KEX_DH_GEX_SHA1,
|
||||
/* diffie-hellman-group-exchange-sha256 */
|
||||
SSH_KEX_DH_GEX_SHA256,
|
||||
#endif /* WITH_GEX */
|
||||
/* ecdh-sha2-nistp256 */
|
||||
SSH_KEX_ECDH_SHA2_NISTP256,
|
||||
/* ecdh-sha2-nistp384 */
|
||||
SSH_KEX_ECDH_SHA2_NISTP384,
|
||||
/* ecdh-sha2-nistp521 */
|
||||
SSH_KEX_ECDH_SHA2_NISTP521,
|
||||
/* curve25519-sha256@libssh.org */
|
||||
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
|
||||
/* curve25519-sha256 */
|
||||
SSH_KEX_CURVE25519_SHA256,
|
||||
/* diffie-hellman-group16-sha512 */
|
||||
SSH_KEX_DH_GROUP16_SHA512,
|
||||
/* diffie-hellman-group18-sha512 */
|
||||
SSH_KEX_DH_GROUP18_SHA512,
|
||||
/* diffie-hellman-group14-sha256 */
|
||||
SSH_KEX_DH_GROUP14_SHA256,
|
||||
/* ecdh-sha2-nistp256 */
|
||||
SSH_KEX_ECDH_SHA2_NISTP256,
|
||||
/* ecdh-sha2-nistp384 */
|
||||
SSH_KEX_ECDH_SHA2_NISTP384,
|
||||
/* ecdh-sha2-nistp521 */
|
||||
SSH_KEX_ECDH_SHA2_NISTP521,
|
||||
/* curve25519-sha256@libssh.org */
|
||||
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
|
||||
/* curve25519-sha256 */
|
||||
SSH_KEX_CURVE25519_SHA256,
|
||||
/* diffie-hellman-group16-sha512 */
|
||||
SSH_KEX_DH_GROUP16_SHA512,
|
||||
/* diffie-hellman-group18-sha512 */
|
||||
SSH_KEX_DH_GROUP18_SHA512,
|
||||
/* diffie-hellman-group14-sha256 */
|
||||
SSH_KEX_DH_GROUP14_SHA256,
|
||||
/* sntrup761x25519-sha512@openssh.com */
|
||||
SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM,
|
||||
};
|
||||
|
||||
enum ssh_cipher_e {
|
||||
@@ -125,9 +128,20 @@ struct ssh_crypto_struct {
|
||||
ssh_string ecdh_server_pubkey;
|
||||
#endif
|
||||
#ifdef HAVE_CURVE25519
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
EVP_PKEY *curve25519_privkey;
|
||||
#elif defined(HAVE_GCRYPT_CURVE25519)
|
||||
gcry_sexp_t curve25519_privkey;
|
||||
#else
|
||||
ssh_curve25519_privkey curve25519_privkey;
|
||||
#endif
|
||||
ssh_curve25519_pubkey curve25519_client_pubkey;
|
||||
ssh_curve25519_pubkey curve25519_server_pubkey;
|
||||
#endif
|
||||
#ifdef HAVE_SNTRUP761
|
||||
ssh_sntrup761_privkey sntrup761_privkey;
|
||||
ssh_sntrup761_pubkey sntrup761_client_pubkey;
|
||||
ssh_sntrup761_ciphertext sntrup761_ciphertext;
|
||||
#endif
|
||||
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
||||
size_t session_id_len;
|
||||
@@ -223,9 +237,8 @@ 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);
|
||||
#if defined(HAVE_LIBCRYPTO) && !defined(WITH_PKCS11_PROVIDER)
|
||||
ENGINE *pki_get_engine(void);
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
void compress_cleanup(struct ssh_crypto_struct *crypto);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned c
|
||||
typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE];
|
||||
typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
|
||||
|
||||
int ssh_curve25519_init(ssh_session session);
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k);
|
||||
int ssh_curve25519_create_k(ssh_session session, ssh_curve25519_pubkey k);
|
||||
|
||||
int ssh_client_curve25519_init(ssh_session session);
|
||||
void ssh_client_curve25519_remove_callbacks(ssh_session session);
|
||||
|
||||
@@ -52,10 +52,10 @@ 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);
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo);
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo);
|
||||
const char *ssh_kex_get_fips_methods(uint32_t algo);
|
||||
const char *ssh_kex_get_description(uint32_t algo);
|
||||
const char *ssh_kex_get_supported_method(enum ssh_kex_types_e type);
|
||||
const char *ssh_kex_get_default_methods(enum ssh_kex_types_e type);
|
||||
const char *ssh_kex_get_fips_methods(enum ssh_kex_types_e type);
|
||||
const char *ssh_kex_get_description(enum ssh_kex_types_e type);
|
||||
char *ssh_client_select_hostkeys(ssh_session session);
|
||||
int ssh_send_rekex(ssh_session session);
|
||||
int server_set_kex(ssh_session session);
|
||||
|
||||
@@ -121,6 +121,15 @@ typedef BN_CTX* bignum_CTX;
|
||||
|
||||
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_ */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-2024 by Aris Adamantiadis and the libssh team
|
||||
* Copyright (c) 2003-2025 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
|
||||
@@ -49,9 +49,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef int mode_t;
|
||||
@@ -850,6 +851,7 @@ LIBSSH_API char *ssh_string_to_char(ssh_string str);
|
||||
#define SSH_STRING_FREE_CHAR(x) \
|
||||
do { if ((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0)
|
||||
LIBSSH_API void ssh_string_free_char(char *s);
|
||||
LIBSSH_API int ssh_string_cmp(ssh_string s1, ssh_string s2);
|
||||
|
||||
LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo,
|
||||
int verify);
|
||||
@@ -874,6 +876,7 @@ LIBSSH_API const char* ssh_get_cipher_in(ssh_session session);
|
||||
LIBSSH_API const char* ssh_get_cipher_out(ssh_session session);
|
||||
LIBSSH_API const char* ssh_get_hmac_in(ssh_session session);
|
||||
LIBSSH_API const char* ssh_get_hmac_out(ssh_session session);
|
||||
LIBSSH_API const char *ssh_get_supported_methods(enum ssh_kex_types_e type);
|
||||
|
||||
LIBSSH_API ssh_buffer ssh_buffer_new(void);
|
||||
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
|
||||
@@ -886,6 +889,27 @@ LIBSSH_API void *ssh_buffer_get(ssh_buffer buffer);
|
||||
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
|
||||
LIBSSH_API int ssh_session_set_disconnect_message(ssh_session session, const char *message);
|
||||
|
||||
/* SSHSIG hashes data independently from the key used, so we use a new enum
|
||||
to avoid confusion. See
|
||||
https://gitlab.com/jas/ietf-sshsig-format/-/blob/cc70a225cbd695d5a6f20aaebdb4b92b0818e43a/ietf-sshsig-format.md#L137
|
||||
*/
|
||||
enum sshsig_digest_e {
|
||||
SSHSIG_DIGEST_SHA2_256 = 0,
|
||||
SSHSIG_DIGEST_SHA2_512 = 1,
|
||||
};
|
||||
|
||||
LIBSSH_API int sshsig_sign(const void *data,
|
||||
size_t data_length,
|
||||
ssh_key privkey,
|
||||
const char *sig_namespace,
|
||||
enum sshsig_digest_e hash_alg,
|
||||
char **signature);
|
||||
LIBSSH_API int sshsig_verify(const void *data,
|
||||
size_t data_length,
|
||||
const char *signature,
|
||||
const char *sig_namespace,
|
||||
ssh_key *sign_key);
|
||||
|
||||
#ifndef LIBSSH_LEGACY_0_4
|
||||
#include "libssh/legacy.h"
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@ struct ssh_auth_request {
|
||||
int method;
|
||||
char *password;
|
||||
struct ssh_key_struct *pubkey;
|
||||
struct ssh_key_struct *server_pubkey;
|
||||
char *sigtype;
|
||||
enum ssh_publickey_state_e signature_state;
|
||||
char kbdint_response;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ssh_config_parse(ssh_session session, FILE *fp, bool global);
|
||||
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,
|
||||
|
||||
@@ -58,6 +58,7 @@ 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);
|
||||
|
||||
@@ -51,6 +51,15 @@
|
||||
#define SSH_KEY_FLAG_PRIVATE 0x0002
|
||||
#define SSH_KEY_FLAG_PKCS11_URI 0x0004
|
||||
|
||||
/* Constants matching the Lightweight Secure Shell Signature Format */
|
||||
/* https://datatracker.ietf.org/doc/draft-josefsson-sshsig-format */
|
||||
#define SSHSIG_VERSION 0x01
|
||||
#define SSHSIG_MAGIC_PREAMBLE "SSHSIG"
|
||||
#define SSHSIG_MAGIC_PREAMBLE_LEN (sizeof(SSHSIG_MAGIC_PREAMBLE) - 1)
|
||||
#define SSHSIG_BEGIN_SIGNATURE "-----BEGIN SSH SIGNATURE-----"
|
||||
#define SSHSIG_END_SIGNATURE "-----END SSH SIGNATURE-----"
|
||||
#define SSHSIG_LINE_LENGTH 76
|
||||
|
||||
struct ssh_key_struct {
|
||||
enum ssh_keytypes_e type;
|
||||
int flags;
|
||||
@@ -63,11 +72,12 @@ struct ssh_key_struct {
|
||||
mbedtls_pk_context *pk;
|
||||
mbedtls_ecdsa_context *ecdsa;
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
/* This holds either ENGINE key for PKCS#11 support or just key in
|
||||
* high-level format */
|
||||
/* This holds either ENGINE/PROVIDER key for PKCS#11 support
|
||||
* or just key in high-level format */
|
||||
EVP_PKEY *key;
|
||||
/* keep this around for FIPS mode so we can parse the public keys. We won't
|
||||
* be able to use them nor use the private keys though */
|
||||
uint8_t *ed25519_pubkey;
|
||||
uint8_t *ed25519_privkey;
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#ifndef HAVE_LIBCRYPTO
|
||||
ed25519_pubkey *ed25519_pubkey;
|
||||
|
||||
@@ -148,6 +148,7 @@ int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob);
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey);
|
||||
int pki_pubkey_build_ed25519(ssh_key key, ssh_string pubkey);
|
||||
|
||||
/* PKI Container OpenSSH */
|
||||
ssh_key ssh_pki_openssh_pubkey_import(const char *text_key);
|
||||
|
||||
@@ -30,10 +30,11 @@
|
||||
#define _LIBSSH_PRIV_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
#if !defined(HAVE_STRTOULL)
|
||||
# if defined(HAVE___STRTOULL)
|
||||
@@ -164,6 +165,9 @@ int ssh_gettimeofday(struct timeval *__p, void *__t);
|
||||
|
||||
#define gettimeofday ssh_gettimeofday
|
||||
|
||||
struct tm *ssh_localtime(const time_t *timer, struct tm *result);
|
||||
# define localtime_r ssh_localtime
|
||||
|
||||
#define _XCLOSESOCKET closesocket
|
||||
|
||||
# ifdef HAVE_IO_H
|
||||
@@ -329,7 +333,7 @@ int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
|
||||
/* match.c */
|
||||
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);
|
||||
int match_hostname(const char *host, const char *pattern, size_t len);
|
||||
#ifndef _WIN32
|
||||
int match_cidr_address_list(const char *address,
|
||||
const char *addrlist,
|
||||
@@ -353,10 +357,10 @@ int ssh_connector_remove_event(ssh_connector connector);
|
||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
|
||||
|
||||
/** Zero a structure */
|
||||
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
|
||||
#define ZERO_STRUCT(x) memset(&(x), 0, sizeof(x))
|
||||
|
||||
/** Zero a structure given a pointer to the structure */
|
||||
#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
|
||||
#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((x), 0, sizeof(*(x))); } while(0)
|
||||
|
||||
/** Get the size of an array */
|
||||
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||
@@ -365,6 +369,17 @@ int ssh_connector_remove_event(ssh_connector connector);
|
||||
void explicit_bzero(void *s, size_t n);
|
||||
#endif /* !HAVE_EXPLICIT_BZERO */
|
||||
|
||||
void burn_free(void *ptr, size_t len);
|
||||
|
||||
/** Free memory space after zeroing it */
|
||||
#define BURN_FREE(x, len) \
|
||||
do { \
|
||||
if ((x) != NULL) { \
|
||||
burn_free((x), (len)); \
|
||||
(x) = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* This is a hack to fix warnings. The idea is to use this everywhere that we
|
||||
* get the "discarding const" warning by the compiler. That doesn't actually
|
||||
@@ -384,6 +399,7 @@ 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
|
||||
*/
|
||||
@@ -415,6 +431,7 @@ 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)
|
||||
|
||||
|
||||
@@ -120,6 +120,8 @@ enum ssh_pending_call_e {
|
||||
/* server-sig-algs extension */
|
||||
#define SSH_EXT_SIG_RSA_SHA256 0x02
|
||||
#define SSH_EXT_SIG_RSA_SHA512 0x04
|
||||
/* Host-bound public key authentication extension */
|
||||
#define SSH_EXT_PUBLICKEY_HOSTBOUND 0x08
|
||||
|
||||
/* members that are common to ssh_session and ssh_bind */
|
||||
struct ssh_common_struct {
|
||||
|
||||
@@ -79,6 +79,7 @@ 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;
|
||||
typedef struct sftp_name_id_map_struct *sftp_name_id_map;
|
||||
|
||||
struct sftp_session_struct {
|
||||
ssh_session session;
|
||||
@@ -213,6 +214,22 @@ struct sftp_limits_struct {
|
||||
uint64_t max_open_handles; /** maximum number of active handles allowed by server */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SFTP names map structure to store the mapping between ids and names.
|
||||
*
|
||||
* This is mainly for the use of sftp_get_users_groups_by_id() function.
|
||||
*/
|
||||
struct sftp_name_id_map_struct {
|
||||
/** @brief Count of name-id pairs in the map */
|
||||
uint32_t count;
|
||||
|
||||
/** @brief Array of ids, ids[i] mapped to names[i] */
|
||||
uint32_t *ids;
|
||||
|
||||
/** @brief Array of names, names[i] mapped to ids[i] */
|
||||
char **names;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new sftp session.
|
||||
*
|
||||
@@ -220,24 +237,30 @@ struct sftp_limits_struct {
|
||||
* with the server inside of the provided ssh session. This function call is
|
||||
* usually followed by the sftp_init(), which initializes SFTP protocol itself.
|
||||
*
|
||||
* @param session The ssh session to use.
|
||||
* @param session The ssh session to use. The session *must* be in
|
||||
* blocking mode since most `sftp_*` functions do not
|
||||
* support the non-blocking API.
|
||||
*
|
||||
* @return A new sftp session or NULL on error.
|
||||
*
|
||||
* @see sftp_free()
|
||||
* @see sftp_init()
|
||||
* @see ssh_set_blocking()
|
||||
*/
|
||||
LIBSSH_API sftp_session sftp_new(ssh_session session);
|
||||
|
||||
/**
|
||||
* @brief Start a new sftp session with an existing channel.
|
||||
*
|
||||
* @param session The ssh session to use.
|
||||
* @param session The ssh session to use. The session *must* be in
|
||||
* blocking mode since most `sftp_*` functions do not
|
||||
* support the non-blocking API.
|
||||
* @param channel An open session channel with subsystem already allocated
|
||||
*
|
||||
* @return A new sftp session or NULL on error.
|
||||
*
|
||||
* @see sftp_free()
|
||||
* @see ssh_set_blocking()
|
||||
*/
|
||||
LIBSSH_API sftp_session sftp_new_channel(ssh_session session, ssh_channel channel);
|
||||
|
||||
@@ -1188,6 +1211,58 @@ LIBSSH_API char *sftp_expand_path(sftp_session sftp, const char *path);
|
||||
*/
|
||||
LIBSSH_API char *sftp_home_directory(sftp_session sftp, const char *username);
|
||||
|
||||
/**
|
||||
* @brief Create a new sftp_name_id_map struct.
|
||||
*
|
||||
* @param count The number of ids/names to store in the map.
|
||||
*
|
||||
* @return A pointer to the newly allocated sftp_name_id_map
|
||||
* struct.
|
||||
*/
|
||||
LIBSSH_API sftp_name_id_map sftp_name_id_map_new(uint32_t count);
|
||||
|
||||
/**
|
||||
* @brief Free the memory of an allocated `sftp_name_id_map` struct.
|
||||
*
|
||||
* @param map A pointer to the `sftp_name_id_map` struct to free.
|
||||
*/
|
||||
LIBSSH_API void sftp_name_id_map_free(sftp_name_id_map map);
|
||||
|
||||
/**
|
||||
* @brief Retrieves usernames and group names based on provided user and group
|
||||
* IDs.
|
||||
*
|
||||
* The retrieved names are stored in the `names` field of the
|
||||
* `sftp_name_id_map` structure. In case a uid or gid is not found, an empty
|
||||
* string is stored.
|
||||
*
|
||||
* This calls the "users-groups-by-id@openssh.com" extension.
|
||||
* You should check if the extension is supported using:
|
||||
*
|
||||
* @code
|
||||
* int supported = sftp_extension_supported(sftp,
|
||||
* "users-groups-by-id@openssh.com", "1");
|
||||
* @endcode
|
||||
*
|
||||
* @param sftp The SFTP session handle.
|
||||
*
|
||||
* @param users_map A pointer to a `sftp_name_id_map` struct with the user
|
||||
* IDs. Can be NULL if only group names are needed.
|
||||
*
|
||||
* @param groups_map A pointer to a `sftp_name_id_map` struct with the group
|
||||
* IDs. Can be NULL if only user names are needed.
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*
|
||||
* @note The caller needs to free the memory used for
|
||||
* the maps later using `sftp_name_id_map_free()`.
|
||||
*
|
||||
* @see sftp_get_error()
|
||||
*/
|
||||
LIBSSH_API int sftp_get_users_groups_by_id(sftp_session sftp,
|
||||
sftp_name_id_map users_map,
|
||||
sftp_name_id_map groups_map);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
/**
|
||||
* @brief Create a new sftp server session.
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef SFTP_PRIV_H
|
||||
#define SFTP_PRIV_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -62,6 +64,39 @@ int sftp_read_and_dispatch(sftp_session sftp);
|
||||
|
||||
sftp_message sftp_dequeue(sftp_session sftp, uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Receive the response of an sftp request
|
||||
*
|
||||
* In blocking mode, if the response hasn't arrived at the time of call, this
|
||||
* function waits for the response to arrive.
|
||||
*
|
||||
* @param sftp The sftp session via which the request was sent.
|
||||
*
|
||||
* @param id The request identifier of the request whose
|
||||
* corresponding response is required.
|
||||
*
|
||||
* @param blocking Flag to indicate the operating mode. true indicates
|
||||
* blocking mode and false indicates non-blocking mode
|
||||
*
|
||||
* @param msg_ptr Pointer to the location to store the response message.
|
||||
* In case of success, the message is allocated
|
||||
* dynamically and must be freed (using
|
||||
* sftp_message_free()) by the caller after usage. In case
|
||||
* of failure, this is left untouched.
|
||||
*
|
||||
* @returns SSH_OK on success
|
||||
* @returns SSH_ERROR on failure with the sftp and ssh errors set
|
||||
* @returns SSH_AGAIN in case of non-blocking mode if the response hasn't
|
||||
* arrived yet.
|
||||
*
|
||||
* @warning In blocking mode, this may block indefinitely for an invalid request
|
||||
* identifier.
|
||||
*/
|
||||
int sftp_recv_response_msg(sftp_session sftp,
|
||||
uint32_t id,
|
||||
bool blocking,
|
||||
sftp_message *msg_ptr);
|
||||
|
||||
/*
|
||||
* Assigns a new SFTP ID for new requests and assures there is no collision
|
||||
* between them.
|
||||
|
||||
@@ -29,6 +29,10 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/sftp.h"
|
||||
|
||||
/**
|
||||
* @defgroup libssh_sftp_server The libssh SFTP server API
|
||||
*
|
||||
|
||||
86
include/libssh/sntrup761.h
Normal file
86
include/libssh/sntrup761.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013 by Aris Adamantiadis <aris@badcode.be>
|
||||
* Copyright (c) 2023 Simon Josefsson <simon@josefsson.org>
|
||||
* Copyright (c) 2025 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,
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* 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 SNTRUP761_H_
|
||||
#define SNTRUP761_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "curve25519.h"
|
||||
#include "libssh.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CURVE25519
|
||||
#define HAVE_SNTRUP761 1
|
||||
#endif
|
||||
|
||||
extern void crypto_hash_sha512(unsigned char *out,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen);
|
||||
|
||||
/*
|
||||
* Derived from public domain source, written by (in alphabetical order):
|
||||
* - Daniel J. Bernstein
|
||||
* - Chitchanok Chuengsatiansup
|
||||
* - Tanja Lange
|
||||
* - Christine van Vredendaal
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SNTRUP761_SECRETKEY_SIZE 1763
|
||||
#define SNTRUP761_PUBLICKEY_SIZE 1158
|
||||
#define SNTRUP761_CIPHERTEXT_SIZE 1039
|
||||
#define SNTRUP761_SIZE 32
|
||||
|
||||
typedef void sntrup761_random_func(void *ctx, size_t length, uint8_t *dst);
|
||||
|
||||
void sntrup761_keypair(uint8_t *pk,
|
||||
uint8_t *sk,
|
||||
void *random_ctx,
|
||||
sntrup761_random_func *random);
|
||||
void sntrup761_enc(uint8_t *c,
|
||||
uint8_t *k,
|
||||
const uint8_t *pk,
|
||||
void *random_ctx,
|
||||
sntrup761_random_func *random);
|
||||
void sntrup761_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk);
|
||||
|
||||
typedef unsigned char ssh_sntrup761_pubkey[SNTRUP761_PUBLICKEY_SIZE];
|
||||
typedef unsigned char ssh_sntrup761_privkey[SNTRUP761_SECRETKEY_SIZE];
|
||||
typedef unsigned char ssh_sntrup761_ciphertext[SNTRUP761_CIPHERTEXT_SIZE];
|
||||
|
||||
int ssh_client_sntrup761x25519_init(ssh_session session);
|
||||
void ssh_client_sntrup761x25519_remove_callbacks(ssh_session session);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
void ssh_server_sntrup761x25519_init(ssh_session session);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SNTRUP761_H_ */
|
||||
@@ -129,6 +129,7 @@ int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, EVP_PKEY **pkey,
|
||||
int evp_dup_dsa_pkey(const ssh_key key, ssh_key new_key, int demote);
|
||||
int evp_dup_rsa_pkey(const ssh_key key, ssh_key new_key, int demote);
|
||||
int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote);
|
||||
int evp_dup_ed25519_pkey(const ssh_key key, ssh_key new_key, int demote);
|
||||
#endif /* HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -8,3 +8,4 @@ Description: The SSH Library
|
||||
Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lssh
|
||||
Cflags: -I${includedir}
|
||||
Requires.private: @LIBSSH_PC_REQUIRES_PRIVATE@
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
set(LIBSSH_PUBLIC_INCLUDE_DIRS ${libssh_SOURCE_DIR}/include)
|
||||
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${libssh_BINARY_DIR}/include
|
||||
${libssh_BINARY_DIR}
|
||||
)
|
||||
|
||||
@@ -12,27 +13,13 @@ if (TARGET OpenSSL::Crypto)
|
||||
list(APPEND LIBSSH_LINK_LIBRARIES OpenSSL::Crypto)
|
||||
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 (TARGET MbedTLS::mbedcrypto)
|
||||
list(APPEND LIBSSH_LINK_LIBRARIES MbedTLS::mbedcrypto)
|
||||
endif ()
|
||||
|
||||
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 (TARGET libgcrypt::libgcrypt)
|
||||
list(APPEND LIBSSH_LINK_LIBRARIES ${GCRYPT_LIBRARIES})
|
||||
endif ()
|
||||
|
||||
if (WITH_ZLIB)
|
||||
list(APPEND LIBSSH_LINK_LIBRARIES ZLIB::ZLIB)
|
||||
@@ -100,10 +87,12 @@ set(libssh_SRCS
|
||||
connector.c
|
||||
crypto_common.c
|
||||
curve25519.c
|
||||
sntrup761.c
|
||||
dh.c
|
||||
ecdh.c
|
||||
error.c
|
||||
getpass.c
|
||||
gzip.c
|
||||
init.c
|
||||
kdf.c
|
||||
kex.c
|
||||
@@ -186,6 +175,13 @@ if (WITH_GCRYPT)
|
||||
chachapoly.c
|
||||
)
|
||||
endif (NOT HAVE_GCRYPT_CHACHA_POLY)
|
||||
|
||||
if (HAVE_GCRYPT_CURVE25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
curve25519_gcrypt.c
|
||||
)
|
||||
endif(HAVE_GCRYPT_CURVE25519)
|
||||
elseif (WITH_MBEDTLS)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
@@ -202,6 +198,7 @@ elseif (WITH_MBEDTLS)
|
||||
external/fe25519.c
|
||||
external/ge25519.c
|
||||
external/sc25519.c
|
||||
external/sntrup761.c
|
||||
)
|
||||
if (NOT (HAVE_MBEDTLS_CHACHA20_H AND HAVE_MBEDTLS_POLY1305_H))
|
||||
set(libssh_SRCS
|
||||
@@ -211,17 +208,24 @@ elseif (WITH_MBEDTLS)
|
||||
chachapoly.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (HAVE_MBEDTLS_CURVE25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
curve25519_mbedcrypto.c
|
||||
)
|
||||
endif(HAVE_MBEDTLS_CURVE25519)
|
||||
else (WITH_GCRYPT)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
threads/libcrypto.c
|
||||
pki_crypto.c
|
||||
ecdh_crypto.c
|
||||
curve25519_crypto.c
|
||||
getrandom_crypto.c
|
||||
md_crypto.c
|
||||
libcrypto.c
|
||||
dh_crypto.c
|
||||
external/sntrup761.c
|
||||
)
|
||||
if (NOT HAVE_OPENSSL_EVP_CHACHA20)
|
||||
set(libssh_SRCS
|
||||
@@ -265,13 +269,6 @@ 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}
|
||||
@@ -280,9 +277,10 @@ 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 HAVE_MBEDTLS_CURVE25519 OR HAVE_GCRYPT_CURVE25519))
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
curve25519_fallback.c
|
||||
external/curve25519_ref.c
|
||||
)
|
||||
endif()
|
||||
@@ -355,6 +353,8 @@ endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
|
||||
set_target_properties(ssh
|
||||
PROPERTIES
|
||||
C_STANDARD
|
||||
99
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
SOVERSION
|
||||
|
||||
25
src/agent.c
25
src/agent.c
@@ -422,8 +422,9 @@ 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;
|
||||
char **comment)
|
||||
{
|
||||
struct ssh_key_struct *key = NULL;
|
||||
struct ssh_string_struct *blob = NULL;
|
||||
struct ssh_string_struct *tmp = NULL;
|
||||
int rc;
|
||||
@@ -492,13 +493,14 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
const ssh_key pubkey,
|
||||
struct ssh_buffer_struct *data)
|
||||
{
|
||||
ssh_buffer request;
|
||||
ssh_buffer reply;
|
||||
ssh_string key_blob;
|
||||
ssh_string sig_blob;
|
||||
ssh_buffer request = NULL;
|
||||
ssh_buffer reply = NULL;
|
||||
ssh_string key_blob = NULL;
|
||||
ssh_string sig_blob = NULL;
|
||||
unsigned int type = 0;
|
||||
unsigned int flags = 0;
|
||||
uint32_t dlen;
|
||||
size_t request_len;
|
||||
int rc;
|
||||
|
||||
request = ssh_buffer_new();
|
||||
@@ -524,11 +526,14 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
* - 2 x uint32_t
|
||||
* - 1 x ssh_string (uint8_t + data)
|
||||
*/
|
||||
rc = ssh_buffer_allocate_size(request,
|
||||
sizeof(uint8_t) * 2 +
|
||||
sizeof(uint32_t) * 2 +
|
||||
ssh_string_len(key_blob));
|
||||
request_len = sizeof(uint8_t) * 2 +
|
||||
sizeof(uint32_t) * 2 +
|
||||
ssh_string_len(key_blob);
|
||||
/* this can't overflow the uint32_t as the
|
||||
* STRING_SIZE_MAX is (UINT32_MAX >> 8) + 1 */
|
||||
rc = ssh_buffer_allocate_size(request, (uint32_t)request_len);
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(key_blob);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
272
src/auth.c
272
src/auth.c
@@ -195,8 +195,9 @@ 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;
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_banner)
|
||||
{
|
||||
ssh_string banner = NULL;
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
@@ -462,6 +463,108 @@ fail:
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Adds the server's public key to the authentication request.
|
||||
*
|
||||
* This function is used internally when the hostbound public key authentication
|
||||
* extension is enabled. It export the server's public key and adds it to the
|
||||
* authentication buffer.
|
||||
*
|
||||
* @param[in] session The SSH session.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*/
|
||||
static int add_hostbound_pubkey(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
ssh_string server_pubkey_s = NULL;
|
||||
|
||||
if (session == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->current_crypto == NULL ||
|
||||
session->current_crypto->server_pubkey == NULL) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid session or server public key");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_pki_export_pubkey_blob(session->current_crypto->server_pubkey,
|
||||
&server_pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, server_pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
SSH_STRING_FREE(server_pubkey_s);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Build a public key authentication request.
|
||||
*
|
||||
* This helper function creates a SSH2_MSG_USERAUTH_REQUEST message for public
|
||||
* key authentication and adds the server's public key if the hostbound
|
||||
* extension is enabled.
|
||||
*
|
||||
* @param[in] session The SSH session.
|
||||
* @param[in] username The username, may be NULL.
|
||||
* @param[in] auth_type Authentication type (0 for key offer, 1 for actual
|
||||
* auth).
|
||||
* @param[in] sig_type_c The signature algorithm name.
|
||||
* @param[in] pubkey_s The public key string.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*/
|
||||
static int build_pubkey_auth_request(ssh_session session,
|
||||
const char *username,
|
||||
int has_signature,
|
||||
const char *sig_type_c,
|
||||
ssh_string pubkey_s)
|
||||
{
|
||||
int rc;
|
||||
const char *auth_method = "publickey";
|
||||
|
||||
if (session->extensions & SSH_EXT_PUBLICKEY_HOSTBOUND) {
|
||||
auth_method = "publickey-hostbound-v00@openssh.com";
|
||||
}
|
||||
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bsssbsS",
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
auth_method,
|
||||
has_signature, /* private key? */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
if (rc < 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->extensions & SSH_EXT_PUBLICKEY_HOSTBOUND) {
|
||||
rc = add_hostbound_pubkey(session);
|
||||
if (rc < 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to authenticate with the given public key.
|
||||
*
|
||||
@@ -508,29 +611,42 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
switch(session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_OFFER_PUBKEY:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Wrong state (%d) during pending SSH call",
|
||||
session->pending_call_state);
|
||||
return SSH_AUTH_ERROR;
|
||||
switch (session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_OFFER_PUBKEY:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Wrong state (%d) during pending SSH call",
|
||||
session->pending_call_state);
|
||||
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) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
rc = ssh_key_algorithm_allowed(session, sig_type_c);
|
||||
if (!rc) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
@@ -538,19 +654,15 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
}
|
||||
allowed = ssh_key_size_allowed(session, pubkey);
|
||||
if (!allowed) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"The '%s' key type of size %d is not allowed by "
|
||||
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(pubkey));
|
||||
"RSA_MIN_SIZE",
|
||||
sig_type_c,
|
||||
ssh_key_size(pubkey));
|
||||
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) {
|
||||
@@ -558,20 +670,10 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
}
|
||||
|
||||
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,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
0, /* private key ? */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
rc = build_pubkey_auth_request(session, username, 0, sig_type_c, pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
@@ -640,16 +742,28 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
switch(session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_PUBKEY:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Bad call during pending SSH call in ssh_userauth_try_publickey");
|
||||
return SSH_AUTH_ERROR;
|
||||
switch (session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_PUBKEY:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(
|
||||
session,
|
||||
SSH_FATAL,
|
||||
"Bad call during pending SSH call in ssh_userauth_try_publickey");
|
||||
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) */
|
||||
@@ -658,13 +772,15 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, key_type);
|
||||
if (sig_type_c == NULL) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
rc = ssh_key_algorithm_allowed(session, sig_type_c);
|
||||
if (!rc) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
@@ -672,19 +788,15 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
}
|
||||
allowed = ssh_key_size_allowed(session, privkey);
|
||||
if (!allowed) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"The '%s' key type of size %d is not allowed by "
|
||||
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(privkey));
|
||||
"RSA_MIN_SIZE",
|
||||
sig_type_c,
|
||||
ssh_key_size(privkey));
|
||||
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) {
|
||||
@@ -692,16 +804,7 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
}
|
||||
|
||||
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,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
sig_type_c, /* algo */
|
||||
str /* public key or cert */
|
||||
);
|
||||
rc = build_pubkey_auth_request(session, username, 1, sig_type_c, str);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -769,6 +872,10 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
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;
|
||||
@@ -785,14 +892,16 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
/* 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) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
rc = ssh_key_algorithm_allowed(session, sig_type_c);
|
||||
if (!rc) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
@@ -801,27 +910,21 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
}
|
||||
allowed = ssh_key_size_allowed(session, pubkey);
|
||||
if (!allowed) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"The '%s' key type of size %d is not allowed by "
|
||||
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(pubkey));
|
||||
"RSA_MIN_SIZE",
|
||||
sig_type_c,
|
||||
ssh_key_size(pubkey));
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
rc = build_pubkey_auth_request(session, username, 1, sig_type_c, pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
|
||||
/* sign the buffer with the private key */
|
||||
sig_blob = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
|
||||
@@ -879,7 +982,7 @@ void ssh_agent_state_free(void *data)
|
||||
if (state) {
|
||||
SSH_STRING_FREE_CHAR(state->comment);
|
||||
ssh_key_free(state->pubkey);
|
||||
free (state);
|
||||
free(state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,8 +1008,7 @@ void ssh_agent_state_free(void *data)
|
||||
* authentication. The username should only be set with ssh_options_set() only
|
||||
* before you connect to the server.
|
||||
*/
|
||||
int ssh_userauth_agent(ssh_session session,
|
||||
const char *username)
|
||||
int ssh_userauth_agent(ssh_session session, const char *username)
|
||||
{
|
||||
int rc = SSH_AUTH_ERROR;
|
||||
struct ssh_agent_state_struct *state = NULL;
|
||||
@@ -1682,7 +1784,7 @@ int ssh_userauth_agent_pubkey(ssh_session session,
|
||||
const char *username,
|
||||
ssh_public_key publickey)
|
||||
{
|
||||
ssh_key key;
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
key = ssh_key_new();
|
||||
|
||||
15
src/base64.c
15
src/base64.c
@@ -29,6 +29,9 @@
|
||||
#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"
|
||||
@@ -183,7 +186,7 @@ error:
|
||||
static int to_block4(unsigned long *block, const char *source, int num)
|
||||
{
|
||||
const char *ptr = NULL;
|
||||
unsigned int i;
|
||||
size_t i;
|
||||
|
||||
*block = 0;
|
||||
if (num < 1) {
|
||||
@@ -278,7 +281,15 @@ uint8_t *bin_to_base64(const uint8_t *source, size_t len)
|
||||
{
|
||||
uint8_t *base64 = NULL;
|
||||
uint8_t *ptr = NULL;
|
||||
size_t flen = len + (3 - (len % 3)); /* round to upper 3 multiple */
|
||||
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 */
|
||||
flen = (4 * flen) / 3 + 1;
|
||||
|
||||
base64 = malloc(flen);
|
||||
|
||||
73
src/bignum.c
73
src/bignum.c
@@ -27,40 +27,52 @@
|
||||
#include "libssh/bignum.h"
|
||||
#include "libssh/string.h"
|
||||
|
||||
ssh_string ssh_make_bignum_string(bignum num) {
|
||||
ssh_string ptr = NULL;
|
||||
size_t pad = 0;
|
||||
size_t len = bignum_num_bytes(num);
|
||||
size_t bits = bignum_num_bits(num);
|
||||
static ssh_string make_bignum_string(bignum num, size_t pad_to_len)
|
||||
{
|
||||
ssh_string ptr = NULL;
|
||||
size_t pad = 0;
|
||||
size_t len = bignum_num_bytes(num);
|
||||
size_t bits = bignum_num_bits(num);
|
||||
|
||||
if (len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the first bit is set we have a negative number */
|
||||
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
|
||||
pad++;
|
||||
}
|
||||
if (pad_to_len == 0) {
|
||||
/* If the first bit is set we have a negative number */
|
||||
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
|
||||
pad++;
|
||||
}
|
||||
} else {
|
||||
if (len > pad_to_len) {
|
||||
return NULL;
|
||||
}
|
||||
pad = pad_to_len - len;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"%zu bits, %zu bytes, %zu padding",
|
||||
bits, len, pad);
|
||||
SSH_LOG(SSH_LOG_TRACE, "%zu bits, %zu bytes, %zu padding", bits, len, pad);
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
ptr = ssh_string_new(len + pad);
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = ssh_string_new(len + pad);
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We have a negative number so we need a leading zero */
|
||||
if (pad) {
|
||||
ptr->data[0] = 0;
|
||||
}
|
||||
/* We have a negative number so we need a leading zero */
|
||||
if (pad) {
|
||||
memset(ptr->data, 0, pad);
|
||||
}
|
||||
|
||||
bignum_bn2bin(num, len, ptr->data + pad);
|
||||
bignum_bn2bin(num, len, ptr->data + pad);
|
||||
|
||||
return ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ssh_string ssh_make_bignum_string(bignum num)
|
||||
{
|
||||
return make_bignum_string(num, 0);
|
||||
}
|
||||
|
||||
ssh_string ssh_make_padded_bignum_string(bignum num, size_t pad_len)
|
||||
{
|
||||
return make_bignum_string(num, pad_len);
|
||||
}
|
||||
|
||||
bignum ssh_make_string_bn(ssh_string string)
|
||||
@@ -71,10 +83,11 @@ bignum ssh_make_string_bn(ssh_string string)
|
||||
#ifdef DEBUG_CRYPTO
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Importing a %zu bits, %zu bytes object ...",
|
||||
len * 8, len);
|
||||
len * 8,
|
||||
len);
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
bignum_bin2bn(string->data, len, &bn);
|
||||
bignum_bin2bn(string->data, (int)len, &bn);
|
||||
|
||||
return bn;
|
||||
}
|
||||
@@ -86,7 +99,9 @@ void ssh_print_bignum(const char *name, const_bignum num)
|
||||
if (num != NULL) {
|
||||
bignum_bn2hex(num, &hex);
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s value: %s", name,
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"%s value: %s",
|
||||
name,
|
||||
(hex == NULL) ? "(null)" : (char *)hex);
|
||||
ssh_crypto_free(hex);
|
||||
}
|
||||
|
||||
11
src/bind.c
11
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;
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo hints;
|
||||
int opt = 1;
|
||||
socket_t s;
|
||||
@@ -132,8 +132,9 @@ static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
|
||||
return s;
|
||||
}
|
||||
|
||||
ssh_bind ssh_bind_new(void) {
|
||||
ssh_bind ptr;
|
||||
ssh_bind ssh_bind_new(void)
|
||||
{
|
||||
ssh_bind ptr = NULL;
|
||||
|
||||
ptr = calloc(1, sizeof(struct ssh_bind_struct));
|
||||
if (ptr == NULL) {
|
||||
@@ -218,7 +219,7 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
|
||||
}
|
||||
|
||||
int ssh_bind_listen(ssh_bind sshbind) {
|
||||
const char *host;
|
||||
const char *host = NULL;
|
||||
socket_t fd;
|
||||
int rc;
|
||||
|
||||
@@ -462,7 +463,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
} else {
|
||||
char *p;
|
||||
char *p = NULL;
|
||||
/* If something was set to the session prior to calling this
|
||||
* function, keep only what is allowed by the options set in
|
||||
* sshbind */
|
||||
|
||||
@@ -200,7 +200,7 @@ local_parse_file(ssh_bind bind,
|
||||
uint8_t *seen,
|
||||
unsigned int depth)
|
||||
{
|
||||
FILE *f;
|
||||
FILE *f = NULL;
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
int rv;
|
||||
@@ -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;
|
||||
FILE *f = NULL;
|
||||
uint32_t parser_flags;
|
||||
int rv;
|
||||
|
||||
@@ -669,7 +669,8 @@ int ssh_bind_config_parse_string(ssh_bind bind, const char *input)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
const char *c = input, *line_start = input;
|
||||
unsigned int line_num = 0, line_len;
|
||||
unsigned int line_num = 0;
|
||||
size_t line_len;
|
||||
uint32_t parser_flags;
|
||||
int rv;
|
||||
|
||||
@@ -698,8 +699,10 @@ int ssh_bind_config_parse_string(ssh_bind bind, const char *input)
|
||||
}
|
||||
line_len = c - line_start;
|
||||
if (line_len > MAX_LINE_SIZE - 1) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Line %u too long: %u characters",
|
||||
line_num, line_len);
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Line %u too long: %zu characters",
|
||||
line_num,
|
||||
line_len);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(line, line_start, line_len);
|
||||
|
||||
105
src/buffer.c
105
src/buffer.c
@@ -371,7 +371,8 @@ int ssh_buffer_allocate_size(struct ssh_buffer_struct *buffer,
|
||||
*/
|
||||
void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len)
|
||||
{
|
||||
void *ptr;
|
||||
void *ptr = NULL;
|
||||
|
||||
buffer_verify(buffer);
|
||||
|
||||
if (buffer->used + len < len) {
|
||||
@@ -406,20 +407,26 @@ void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len)
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
int ssh_buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
|
||||
struct ssh_string_struct *string) {
|
||||
uint32_t len = 0;
|
||||
int
|
||||
ssh_buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
|
||||
struct ssh_string_struct *string)
|
||||
{
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
if (string == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (string == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = ssh_string_len(string);
|
||||
if (ssh_buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
len = ssh_string_len(string) + sizeof(uint32_t);
|
||||
/* this can't overflow the uint32_t as the
|
||||
* STRING_SIZE_MAX is (UINT32_MAX >> 8) + 1 */
|
||||
rc = ssh_buffer_add_data(buffer, string, (uint32_t)len);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -822,6 +829,7 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
const char *p = NULL;
|
||||
ssh_string string = NULL;
|
||||
char *cstring = NULL;
|
||||
bignum b = NULL;
|
||||
size_t needed_size = 0;
|
||||
size_t len;
|
||||
size_t count;
|
||||
@@ -852,7 +860,7 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
break;
|
||||
case 'S':
|
||||
string = va_arg(ap, ssh_string);
|
||||
needed_size += 4 + ssh_string_len(string);
|
||||
needed_size += sizeof(uint32_t) + ssh_string_len(string);
|
||||
string = NULL;
|
||||
break;
|
||||
case 's':
|
||||
@@ -866,13 +874,18 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
va_arg(ap, void *);
|
||||
count++; /* increase argument count */
|
||||
break;
|
||||
case 'F':
|
||||
case 'B':
|
||||
va_arg(ap, bignum);
|
||||
/*
|
||||
* Use a fixed size for a bignum
|
||||
* (they should normally be around 32)
|
||||
*/
|
||||
needed_size += 64;
|
||||
b = va_arg(ap, bignum);
|
||||
if (*p == 'F') {
|
||||
/* For padded bignum, we know the exact length */
|
||||
len = va_arg(ap, size_t);
|
||||
count++; /* increase argument count */
|
||||
needed_size += sizeof(uint32_t) + len;
|
||||
} else {
|
||||
/* The bignum bytes + 1 for possible padding */
|
||||
needed_size += sizeof(uint32_t) + bignum_num_bytes(b) + 1;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
cstring = va_arg(ap, char *);
|
||||
@@ -926,7 +939,7 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
va_list ap)
|
||||
{
|
||||
int rc = SSH_ERROR;
|
||||
const char *p;
|
||||
const char *p = NULL;
|
||||
union {
|
||||
uint8_t byte;
|
||||
uint16_t word;
|
||||
@@ -935,7 +948,7 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
ssh_string string;
|
||||
void *data;
|
||||
} o;
|
||||
char *cstring;
|
||||
char *cstring = NULL;
|
||||
bignum b;
|
||||
size_t len;
|
||||
size_t count;
|
||||
@@ -978,24 +991,40 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
case 's':
|
||||
cstring = va_arg(ap, char *);
|
||||
len = strlen(cstring);
|
||||
rc = ssh_buffer_add_u32(buffer, htonl(len));
|
||||
if (len > UINT32_MAX) {
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
o.dword = (uint32_t)len;
|
||||
rc = ssh_buffer_add_u32(buffer, htonl(o.dword));
|
||||
if (rc == SSH_OK){
|
||||
rc = ssh_buffer_add_data(buffer, cstring, len);
|
||||
rc = ssh_buffer_add_data(buffer, cstring, o.dword);
|
||||
}
|
||||
cstring = NULL;
|
||||
break;
|
||||
case 'P':
|
||||
len = va_arg(ap, size_t);
|
||||
if (len > UINT32_MAX) {
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
o.data = va_arg(ap, void *);
|
||||
count++; /* increase argument count */
|
||||
|
||||
rc = ssh_buffer_add_data(buffer, o.data, len);
|
||||
rc = ssh_buffer_add_data(buffer, o.data, (uint32_t)len);
|
||||
o.data = NULL;
|
||||
break;
|
||||
case 'F':
|
||||
case 'B':
|
||||
b = va_arg(ap, bignum);
|
||||
o.string = ssh_make_bignum_string(b);
|
||||
if (*p == 'F') {
|
||||
len = va_arg(ap, size_t);
|
||||
count++; /* increase argument count */
|
||||
o.string = ssh_make_padded_bignum_string(b, len);
|
||||
} else {
|
||||
o.string = ssh_make_bignum_string(b);
|
||||
}
|
||||
if(o.string == NULL){
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
@@ -1006,7 +1035,11 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
case 't':
|
||||
cstring = va_arg(ap, char *);
|
||||
len = strlen(cstring);
|
||||
rc = ssh_buffer_add_data(buffer, cstring, len);
|
||||
if (len > UINT32_MAX) {
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
rc = ssh_buffer_add_data(buffer, cstring, (uint32_t)len);
|
||||
cstring = NULL;
|
||||
break;
|
||||
default:
|
||||
@@ -1047,6 +1080,8 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
* 'P': size_t, void * (len of data, pointer to data)
|
||||
* only pushes data.
|
||||
* 'B': bignum (pushed as SSH string)
|
||||
* 'F': bignum, size_t (bignum, padded to fixed length,
|
||||
* pushed as SSH string)
|
||||
* @returns SSH_OK on success
|
||||
* SSH_ERROR on error
|
||||
* @warning when using 'P' with a constant size (e.g. 8), do not
|
||||
@@ -1094,7 +1129,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
va_list ap)
|
||||
{
|
||||
int rc = SSH_ERROR;
|
||||
const char *p = format, *last;
|
||||
const char *p = format, *last = NULL;
|
||||
union {
|
||||
uint8_t *byte;
|
||||
uint16_t *word;
|
||||
@@ -1186,28 +1221,28 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
if (rlen != 4){
|
||||
break;
|
||||
}
|
||||
len = ntohl(u32len);
|
||||
if (len > max_len - 1) {
|
||||
u32len = ntohl(u32len);
|
||||
if (u32len > max_len - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_validate_length(buffer, len);
|
||||
rc = ssh_buffer_validate_length(buffer, u32len);
|
||||
if (rc != SSH_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
*o.cstring = malloc(len + 1);
|
||||
*o.cstring = malloc(u32len + 1);
|
||||
if (*o.cstring == NULL){
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
rlen = ssh_buffer_get_data(buffer, *o.cstring, len);
|
||||
if (rlen != len){
|
||||
rlen = ssh_buffer_get_data(buffer, *o.cstring, u32len);
|
||||
if (rlen != u32len) {
|
||||
SAFE_FREE(*o.cstring);
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
(*o.cstring)[len] = '\0';
|
||||
(*o.cstring)[u32len] = '\0';
|
||||
o.cstring = NULL;
|
||||
rc = SSH_OK;
|
||||
break;
|
||||
@@ -1232,7 +1267,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
rlen = ssh_buffer_get_data(buffer, *o.data, len);
|
||||
rlen = ssh_buffer_get_data(buffer, *o.data, (uint32_t)len);
|
||||
if (rlen != len){
|
||||
SAFE_FREE(*o.data);
|
||||
rc = SSH_ERROR;
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "libssh/callbacks.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#define is_callback_valid(session, cb) \
|
||||
(cb->size <= 0 || cb->size > 1024 * sizeof(void *))
|
||||
(cb->size > 0 || cb->size <= 1024 * sizeof(void *))
|
||||
|
||||
/* LEGACY */
|
||||
static void ssh_legacy_log_callback(int priority,
|
||||
@@ -45,8 +45,7 @@ static void ssh_legacy_log_callback(int priority,
|
||||
log_fn(session, priority, buffer, log_data);
|
||||
}
|
||||
|
||||
void
|
||||
_ssh_remove_legacy_log_cb(void)
|
||||
void _ssh_remove_legacy_log_cb(void)
|
||||
{
|
||||
if (ssh_get_log_callback() == ssh_legacy_log_callback) {
|
||||
_ssh_reset_log_cb();
|
||||
@@ -54,26 +53,27 @@ _ssh_remove_legacy_log_cb(void)
|
||||
}
|
||||
}
|
||||
|
||||
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb)
|
||||
{
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (is_callback_valid(session, cb)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
};
|
||||
session->common.callbacks = cb;
|
||||
if (!is_callback_valid(session, cb)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
};
|
||||
session->common.callbacks = cb;
|
||||
|
||||
/* LEGACY */
|
||||
if (ssh_get_log_callback() == NULL && cb->log_function) {
|
||||
ssh_set_log_callback(ssh_legacy_log_callback);
|
||||
ssh_set_log_userdata(session);
|
||||
}
|
||||
/* LEGACY */
|
||||
if (ssh_get_log_callback() == NULL && cb->log_function) {
|
||||
ssh_set_log_callback(ssh_legacy_log_callback);
|
||||
ssh_set_log_userdata(session);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssh_add_set_channel_callbacks(ssh_channel channel,
|
||||
@@ -84,11 +84,11 @@ static int ssh_add_set_channel_callbacks(ssh_channel channel,
|
||||
int rc;
|
||||
|
||||
if (channel == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session = channel->session;
|
||||
|
||||
if (is_callback_valid(session, cb)) {
|
||||
if (!is_callback_valid(session, cb)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
@@ -96,7 +96,7 @@ static int ssh_add_set_channel_callbacks(ssh_channel channel,
|
||||
};
|
||||
if (channel->callbacks == NULL) {
|
||||
channel->callbacks = ssh_list_new();
|
||||
if (channel->callbacks == NULL){
|
||||
if (channel->callbacks == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -122,14 +122,14 @@ 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;
|
||||
struct ssh_iterator *it = NULL;
|
||||
|
||||
if (channel == NULL || channel->callbacks == NULL){
|
||||
if (channel == NULL || channel->callbacks == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
it = ssh_list_find(channel->callbacks, cb);
|
||||
if (it == NULL){
|
||||
if (it == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -138,19 +138,19 @@ int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb)
|
||||
{
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb){
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (is_callback_valid(session, cb)) {
|
||||
if (!is_callback_valid(session, cb)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
};
|
||||
session->server_callbacks = cb;
|
||||
session->server_callbacks = cb;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ static int chacha20_set_encrypt_key(struct ssh_cipher_struct *cipher,
|
||||
void *key,
|
||||
void *IV)
|
||||
{
|
||||
struct chacha20_poly1305_keysched *sched;
|
||||
struct chacha20_poly1305_keysched *sched = NULL;
|
||||
uint8_t *u8key = key;
|
||||
(void)IV;
|
||||
|
||||
|
||||
1719
src/channels.c
1719
src/channels.c
File diff suppressed because it is too large
Load Diff
75
src/client.c
75
src/client.c
@@ -47,6 +47,12 @@
|
||||
#include "libssh/pki.h"
|
||||
#include "libssh/kex.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef HAVE_PTHREAD
|
||||
extern int proxy_disconnect;
|
||||
#endif /* HAVE_PTHREAD */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#define set_status(session, status) do {\
|
||||
if (session->common.callbacks && session->common.callbacks->connect_status_function) \
|
||||
session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \
|
||||
@@ -220,7 +226,7 @@ int ssh_send_banner(ssh_session session, int server)
|
||||
terminator);
|
||||
}
|
||||
|
||||
rc = ssh_socket_write(session->socket, buffer, strlen(buffer));
|
||||
rc = ssh_socket_write(session->socket, buffer, (uint32_t)strlen(buffer));
|
||||
if (rc == SSH_ERROR) {
|
||||
goto end;
|
||||
}
|
||||
@@ -229,8 +235,8 @@ int ssh_send_banner(ssh_session session, int server)
|
||||
ssh_pcap_context_write(session->pcap_ctx,
|
||||
SSH_PCAP_DIR_OUT,
|
||||
buffer,
|
||||
strlen(buffer),
|
||||
strlen(buffer));
|
||||
(uint32_t)strlen(buffer),
|
||||
(uint32_t)strlen(buffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -248,45 +254,52 @@ end:
|
||||
*/
|
||||
int dh_handshake(ssh_session session)
|
||||
{
|
||||
int rc = SSH_AGAIN;
|
||||
int rc = SSH_AGAIN;
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "dh_handshake_state = %d, kex_type = %d",
|
||||
session->dh_handshake_state, session->next_crypto->kex_type);
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"dh_handshake_state = %d, kex_type = %d",
|
||||
session->dh_handshake_state,
|
||||
session->next_crypto->kex_type);
|
||||
|
||||
switch (session->dh_handshake_state) {
|
||||
switch (session->dh_handshake_state) {
|
||||
case DH_STATE_INIT:
|
||||
switch(session->next_crypto->kex_type){
|
||||
switch (session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc = ssh_client_dh_init(session);
|
||||
break;
|
||||
rc = ssh_client_dh_init(session);
|
||||
break;
|
||||
#ifdef WITH_GEX
|
||||
case SSH_KEX_DH_GEX_SHA1:
|
||||
case SSH_KEX_DH_GEX_SHA256:
|
||||
rc = ssh_client_dhgex_init(session);
|
||||
break;
|
||||
rc = ssh_client_dhgex_init(session);
|
||||
break;
|
||||
#endif /* WITH_GEX */
|
||||
#ifdef HAVE_ECDH
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP384:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
rc = ssh_client_ecdh_init(session);
|
||||
break;
|
||||
rc = ssh_client_ecdh_init(session);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_CURVE25519
|
||||
case SSH_KEX_CURVE25519_SHA256:
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
rc = ssh_client_curve25519_init(session);
|
||||
break;
|
||||
rc = ssh_client_curve25519_init(session);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_SNTRUP761
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
rc = ssh_client_sntrup761x25519_init(session);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
case DH_STATE_INIT_SENT:
|
||||
/* wait until ssh_packet_dh_reply is called */
|
||||
break;
|
||||
@@ -294,15 +307,17 @@ int dh_handshake(ssh_session session)
|
||||
/* wait until ssh_packet_newkeys is called */
|
||||
break;
|
||||
case DH_STATE_FINISHED:
|
||||
return SSH_OK;
|
||||
return SSH_OK;
|
||||
default:
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid state in dh_handshake(): %d",
|
||||
session->dh_handshake_state);
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid state in dh_handshake(): %d",
|
||||
session->dh_handshake_state);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ssh_service_request_termination(void *s)
|
||||
@@ -765,8 +780,6 @@ ssh_session_set_disconnect_message(ssh_session session, const char *message)
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
extern int proxy_disconnect;
|
||||
|
||||
/**
|
||||
* @brief Disconnect from a session (client or server).
|
||||
*
|
||||
@@ -781,7 +794,7 @@ extern int proxy_disconnect;
|
||||
void
|
||||
ssh_disconnect(ssh_session session)
|
||||
{
|
||||
struct ssh_iterator *it;
|
||||
struct ssh_iterator *it = NULL;
|
||||
int rc;
|
||||
|
||||
if (session == NULL) {
|
||||
@@ -789,12 +802,14 @@ ssh_disconnect(ssh_session session)
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef HAVE_PTHREAD
|
||||
/* Only send the disconnect to all other threads when the root session calls
|
||||
* ssh_disconnect() */
|
||||
if (session->proxy_root) {
|
||||
proxy_disconnect = 1;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_PTHREAD */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
if (session->disconnect_message == NULL) {
|
||||
session->disconnect_message = strdup("Bye Bye") ;
|
||||
@@ -889,7 +904,7 @@ error:
|
||||
*/
|
||||
const char *ssh_copyright(void)
|
||||
{
|
||||
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2024 "
|
||||
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2025 "
|
||||
"Aris Adamantiadis, Andreas Schneider "
|
||||
"and libssh contributors. "
|
||||
"Distributed under the LGPL, please refer to COPYING "
|
||||
|
||||
115
src/config.c
115
src/config.c
@@ -39,10 +39,12 @@
|
||||
# include <errno.h>
|
||||
# include <signal.h>
|
||||
# include <sys/wait.h>
|
||||
# include <ifaddrs.h>
|
||||
# include <net/if.h>
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/config_parser.h"
|
||||
#include "libssh/config.h"
|
||||
@@ -130,9 +132,9 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
||||
{ "verifyhostkeydns", SOC_UNSUPPORTED},
|
||||
{ "visualhostkey", SOC_UNSUPPORTED},
|
||||
{ "clearallforwardings", SOC_NA},
|
||||
{ "controlmaster", SOC_CONTROLMASTER},
|
||||
{ "controlmaster", SOC_NA},
|
||||
{ "controlpersist", SOC_NA},
|
||||
{ "controlpath", SOC_CONTROLPATH},
|
||||
{ "controlpath", SOC_NA},
|
||||
{ "dynamicforward", SOC_NA},
|
||||
{ "escapechar", SOC_NA},
|
||||
{ "exitonforwardfailure", SOC_NA},
|
||||
@@ -209,7 +211,7 @@ local_parse_file(ssh_session session,
|
||||
unsigned int depth,
|
||||
bool global)
|
||||
{
|
||||
FILE *f;
|
||||
FILE *f = NULL;
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
int rv;
|
||||
@@ -639,7 +641,7 @@ ssh_config_make_absolute(ssh_session session,
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
/**
|
||||
* @brief Checks if host address matches the local network specified.
|
||||
*
|
||||
@@ -730,7 +732,7 @@ ssh_match_localnetwork(const char *addrlist, bool negate)
|
||||
|
||||
return (found == (negate ? 0 : 1));
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_IFADDRS_H */
|
||||
|
||||
static int
|
||||
ssh_config_parse_line(ssh_session session,
|
||||
@@ -892,9 +894,11 @@ ssh_config_parse_line(ssh_session session,
|
||||
/* Here we match only one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL || p[0] == '\0') {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"line %d: ERROR - Match user keyword "
|
||||
"requires argument", count);
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"line %d: ERROR - Match localuser keyword "
|
||||
"requires argument",
|
||||
count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
@@ -955,7 +959,6 @@ ssh_config_parse_line(ssh_session session,
|
||||
args++;
|
||||
break;
|
||||
|
||||
#ifndef _WIN32
|
||||
case MATCH_LOCALNETWORK:
|
||||
/* Here we match only one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
@@ -968,6 +971,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
rv = match_cidr_address_list(NULL, p, -1);
|
||||
if (rv == -1) {
|
||||
ssh_set_error(session,
|
||||
@@ -992,23 +996,31 @@ ssh_config_parse_line(ssh_session session,
|
||||
}
|
||||
|
||||
result &= rv;
|
||||
#else /* HAVE_IFADDRS_H */
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"line %d: ERROR - match localnetwork "
|
||||
"not supported on this platform",
|
||||
count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
#endif /* HAVE_IFADDRS_H */
|
||||
args++;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case MATCH_UNKNOWN:
|
||||
default:
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"ERROR - Unknown argument '%s' for Match keyword", p);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Unknown argument '%s' for Match keyword. Not matching",
|
||||
p);
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
} while (p != NULL && p[0] != '\0');
|
||||
if (args == 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"ERROR - Match keyword requires an argument");
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"ERROR - Match keyword requires an argument. Not matching");
|
||||
result = 0;
|
||||
}
|
||||
*parsing = result;
|
||||
break;
|
||||
@@ -1439,6 +1451,32 @@ ssh_config_parse_line(ssh_session session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @brief Parse configuration from a file pointer
|
||||
*
|
||||
* @params[in] session The ssh session
|
||||
* @params[in] fp A valid file pointer
|
||||
* @params[in] global Whether the config is global or not
|
||||
*
|
||||
* @returns 0 on successful parsing the configuration file, -1 on error
|
||||
*/
|
||||
int ssh_config_parse(ssh_session session, FILE *fp, bool global)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
int parsing, rv;
|
||||
|
||||
parsing = 1;
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
count++;
|
||||
rv = ssh_config_parse_line(session, line, count, &parsing, 0, global);
|
||||
if (rv < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @brief Parse configuration file and set the options to the given session
|
||||
*
|
||||
* @params[in] session The ssh session
|
||||
@@ -1448,36 +1486,32 @@ ssh_config_parse_line(ssh_session session,
|
||||
*/
|
||||
int ssh_config_parse_file(ssh_session session, const char *filename)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
FILE *f;
|
||||
int parsing, rv;
|
||||
FILE *fp = NULL;
|
||||
int rv;
|
||||
bool global = 0;
|
||||
|
||||
f = fopen(filename, "r");
|
||||
if (f == NULL) {
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = strcmp(filename, GLOBAL_CLIENT_CONFIG);
|
||||
#ifdef USR_GLOBAL_CLIENT_CONFIG
|
||||
if (rv != 0) {
|
||||
rv = strcmp(filename, USR_GLOBAL_CLIENT_CONFIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rv == 0) {
|
||||
global = true;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Reading configuration data from %s", filename);
|
||||
|
||||
parsing = 1;
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
count++;
|
||||
rv = ssh_config_parse_line(session, line, count, &parsing, 0, global);
|
||||
if (rv < 0) {
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
rv = ssh_config_parse(session, fp, global);
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
fclose(fp);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* @brief Parse configuration string and set the options to the given session
|
||||
@@ -1492,7 +1526,8 @@ int ssh_config_parse_string(ssh_session session, const char *input)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
const char *c = input, *line_start = input;
|
||||
unsigned int line_num = 0, line_len;
|
||||
unsigned int line_num = 0;
|
||||
size_t line_len;
|
||||
int parsing, rv;
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Reading configuration data from string:");
|
||||
@@ -1514,8 +1549,10 @@ int ssh_config_parse_string(ssh_session session, const char *input)
|
||||
}
|
||||
line_len = c - line_start;
|
||||
if (line_len > MAX_LINE_SIZE - 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Line %u too long: %u characters",
|
||||
line_num, line_len);
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Line %u too long: %zu characters",
|
||||
line_num,
|
||||
line_len);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(line, line_start, line_len);
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
*/
|
||||
char *ssh_config_get_cmd(char **str)
|
||||
{
|
||||
register char *c;
|
||||
char *r;
|
||||
register char *c = NULL;
|
||||
char *r = NULL;
|
||||
|
||||
/* Ignore leading spaces */
|
||||
for (c = *str; *c; c++) {
|
||||
@@ -67,7 +67,7 @@ out:
|
||||
*/
|
||||
char *ssh_config_get_token(char **str)
|
||||
{
|
||||
register char *c;
|
||||
register char *c = NULL;
|
||||
bool had_equal = false;
|
||||
char *r = NULL;
|
||||
|
||||
@@ -82,6 +82,13 @@ char *ssh_config_get_token(char **str)
|
||||
if (*c == '\"') {
|
||||
for (r = ++c; *c; c++) {
|
||||
if (*c == '\"' || *c == '\n') {
|
||||
if (*c == '\"' && r != c && *(c - 1) == '\\') {
|
||||
/* Escaped quote: Move the remaining one char left */
|
||||
int remaining_len = strlen(c);
|
||||
memmove(c - 1, c, remaining_len);
|
||||
c[remaining_len - 1] = '\0';
|
||||
continue;
|
||||
}
|
||||
*c = '\0';
|
||||
c++;
|
||||
break;
|
||||
@@ -116,7 +123,7 @@ out:
|
||||
|
||||
long ssh_config_get_long(char **str, long notfound)
|
||||
{
|
||||
char *p, *endp;
|
||||
char *p = NULL, *endp = NULL;
|
||||
long i;
|
||||
|
||||
p = ssh_config_get_token(str);
|
||||
@@ -133,7 +140,7 @@ long ssh_config_get_long(char **str, long notfound)
|
||||
|
||||
const char *ssh_config_get_str_tok(char **str, const char *def)
|
||||
{
|
||||
char *p;
|
||||
char *p = NULL;
|
||||
|
||||
p = ssh_config_get_token(str);
|
||||
if (p && *p) {
|
||||
@@ -145,7 +152,7 @@ const char *ssh_config_get_str_tok(char **str, const char *def)
|
||||
|
||||
int ssh_config_get_yesno(char **str, int notfound)
|
||||
{
|
||||
const char *p;
|
||||
const char *p = NULL;
|
||||
|
||||
p = ssh_config_get_str_tok(str, NULL);
|
||||
if (p == NULL) {
|
||||
|
||||
@@ -189,8 +189,8 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
}
|
||||
|
||||
if (bind_addr) {
|
||||
struct addrinfo *bind_ai;
|
||||
struct addrinfo *bind_itr;
|
||||
struct addrinfo *bind_ai = NULL;
|
||||
struct addrinfo *bind_itr = NULL;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr);
|
||||
|
||||
@@ -209,7 +209,8 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
bind_itr != NULL;
|
||||
bind_itr = bind_itr->ai_next)
|
||||
{
|
||||
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
|
||||
rc = bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Binding local address: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
|
||||
@@ -264,17 +264,17 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
||||
}
|
||||
connector->in_available = 1; /* Don't poll on it */
|
||||
return;
|
||||
} else if (r> 0) {
|
||||
} else if (r > 0) {
|
||||
/* loop around ssh_channel_write in case our window reduced due to a race */
|
||||
while (total != r){
|
||||
if (connector->out_flags & SSH_CONNECTOR_STDOUT) {
|
||||
w = ssh_channel_write(connector->out_channel,
|
||||
buffer + total,
|
||||
r - total);
|
||||
(uint32_t)(r - total));
|
||||
} else {
|
||||
w = ssh_channel_write_stderr(connector->out_channel,
|
||||
buffer + total,
|
||||
r - total);
|
||||
(uint32_t)(r - total));
|
||||
}
|
||||
if (w == SSH_ERROR) {
|
||||
return;
|
||||
@@ -294,7 +294,7 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
||||
while (total < r) {
|
||||
w = ssh_connector_fd_write(connector,
|
||||
buffer + total,
|
||||
r - total);
|
||||
(uint32_t)(r - total));
|
||||
if (w < 0) {
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
return;
|
||||
@@ -340,8 +340,9 @@ ssh_connector_fd_out_cb(ssh_connector connector)
|
||||
} else if (r > 0) {
|
||||
/* loop around write in case the write blocks even for CHUNKSIZE bytes */
|
||||
while (total != r) {
|
||||
w = ssh_connector_fd_write(connector, buffer + total,
|
||||
r - total);
|
||||
w = ssh_connector_fd_write(connector,
|
||||
buffer + total,
|
||||
(uint32_t)(r - total));
|
||||
if (w < 0) {
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
return;
|
||||
@@ -476,9 +477,11 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
||||
ssh_connector_except_channel(connector, connector->out_channel);
|
||||
}
|
||||
} else if (connector->out_fd != SSH_INVALID_SOCKET) {
|
||||
w = ssh_connector_fd_write(connector, data, len);
|
||||
if (w < 0)
|
||||
ssize_t ws = ssh_connector_fd_write(connector, data, len);
|
||||
if (ws < 0) {
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
}
|
||||
w = (int)ws;
|
||||
} else {
|
||||
ssh_set_error(session, SSH_FATAL, "output socket or channel closed");
|
||||
return SSH_ERROR;
|
||||
@@ -627,8 +630,9 @@ error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ssh_connector_remove_event(ssh_connector connector) {
|
||||
ssh_session session;
|
||||
int ssh_connector_remove_event(ssh_connector connector)
|
||||
{
|
||||
ssh_session session = NULL;
|
||||
|
||||
if (connector->in_poll != NULL) {
|
||||
ssh_event_remove_poll(connector->event, connector->in_poll);
|
||||
|
||||
340
src/curve25519.c
340
src/curve25519.c
@@ -26,119 +26,43 @@
|
||||
#include "libssh/curve25519.h"
|
||||
#ifdef HAVE_CURVE25519
|
||||
|
||||
#ifdef WITH_NACL
|
||||
#include "nacl/crypto_scalarmult_curve25519.h"
|
||||
#endif
|
||||
|
||||
#include "libssh/ssh2.h"
|
||||
#include "libssh/bignum.h"
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/dh.h"
|
||||
#include "libssh/pki.h"
|
||||
#include "libssh/bignum.h"
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/ssh2.h"
|
||||
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply);
|
||||
|
||||
static ssh_packet_callback dh_client_callbacks[] = {
|
||||
ssh_packet_client_curve25519_reply
|
||||
ssh_packet_client_curve25519_reply,
|
||||
};
|
||||
|
||||
static struct ssh_packet_callbacks_struct ssh_curve25519_client_callbacks = {
|
||||
.start = SSH2_MSG_KEX_ECDH_REPLY,
|
||||
.n_callbacks = 1,
|
||||
.callbacks = dh_client_callbacks,
|
||||
.user = NULL
|
||||
.user = NULL,
|
||||
};
|
||||
|
||||
static int ssh_curve25519_init(ssh_session session)
|
||||
int ssh_curve25519_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
int rc;
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t pubkey_len = CURVE25519_PUBKEY_SIZE;
|
||||
size_t pkey_len = CURVE25519_PRIVKEY_SIZE;
|
||||
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_log_hexdump("Session server cookie",
|
||||
session->next_crypto->server_kex.cookie,
|
||||
16);
|
||||
ssh_log_hexdump("Session client cookie",
|
||||
session->next_crypto->client_kex.cookie,
|
||||
16);
|
||||
#endif
|
||||
|
||||
rc = EVP_PKEY_keygen_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 keygen: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_keygen(pctx, &pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate X25519 keys: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
rc = EVP_PKEY_get_raw_public_key(pkey,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
&pubkey_len);
|
||||
} else {
|
||||
rc = EVP_PKEY_get_raw_public_key(pkey,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
&pubkey_len);
|
||||
}
|
||||
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get X25519 raw public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_get_raw_private_key(pkey,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
&pkey_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get X25519 raw private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
EVP_PKEY_free(pkey);
|
||||
#else
|
||||
rc = ssh_get_random(session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE, 1);
|
||||
if (rc != 1) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
} else {
|
||||
crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
}
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
return SSH_OK;
|
||||
rc = curve25519_do_create_k(session, k);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@@ -180,193 +104,120 @@ void ssh_client_curve25519_remove_callbacks(ssh_session session)
|
||||
static int ssh_curve25519_build_k(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey k;
|
||||
int rc;
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
||||
size_t shared_key_len = sizeof(k);
|
||||
int rc, ret = SSH_ERROR;
|
||||
|
||||
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE);
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
rc = ssh_curve25519_create_k(session, k);
|
||||
if (rc != SSH_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 key derivation: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
} else {
|
||||
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
}
|
||||
if (pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 public key EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to set peer X25519 public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive(pctx, k, &shared_key_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to derive X25519 shared secret: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
ret = SSH_OK;
|
||||
out:
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_free(pubkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (ret == SSH_ERROR) {
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
if (session->server) {
|
||||
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||
session->next_crypto->curve25519_client_pubkey);
|
||||
} else {
|
||||
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||
session->next_crypto->curve25519_server_pubkey);
|
||||
}
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, &session->next_crypto->shared_secret);
|
||||
bignum_bin2bn(k,
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
&session->next_crypto->shared_secret);
|
||||
if (session->next_crypto->shared_secret == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_log_hexdump("Session server cookie",
|
||||
session->next_crypto->server_kex.cookie, 16);
|
||||
ssh_log_hexdump("Session client cookie",
|
||||
session->next_crypto->client_kex.cookie, 16);
|
||||
ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
|
||||
* a SSH_MSG_NEWKEYS
|
||||
*/
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
|
||||
ssh_string q_s_string = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
ssh_string signature = NULL;
|
||||
int rc;
|
||||
(void)type;
|
||||
(void)user;
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply)
|
||||
{
|
||||
ssh_string q_s_string = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
ssh_string signature = NULL;
|
||||
int rc;
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
ssh_client_curve25519_remove_callbacks(session);
|
||||
ssh_client_curve25519_remove_callbacks(session);
|
||||
|
||||
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if (pubkey_blob == NULL) {
|
||||
ssh_set_error(session,SSH_FATAL, "No public key in packet");
|
||||
goto error;
|
||||
}
|
||||
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if (pubkey_blob == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No public key in packet");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to import next public key");
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to import next public key");
|
||||
goto error;
|
||||
}
|
||||
|
||||
q_s_string = ssh_buffer_get_ssh_string(packet);
|
||||
if (q_s_string == NULL) {
|
||||
ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet");
|
||||
goto error;
|
||||
}
|
||||
if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){
|
||||
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
|
||||
(int)ssh_string_len(q_s_string));
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
goto error;
|
||||
}
|
||||
memcpy(session->next_crypto->curve25519_server_pubkey, ssh_string_data(q_s_string), CURVE25519_PUBKEY_SIZE);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
q_s_string = ssh_buffer_get_ssh_string(packet);
|
||||
if (q_s_string == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No Q_S ECC point in packet");
|
||||
goto error;
|
||||
}
|
||||
if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Incorrect size for server Curve25519 public key: %zu",
|
||||
ssh_string_len(q_s_string));
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
goto error;
|
||||
}
|
||||
memcpy(session->next_crypto->curve25519_server_pubkey,
|
||||
ssh_string_data(q_s_string),
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
|
||||
signature = ssh_buffer_get_ssh_string(packet);
|
||||
if (signature == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No signature in packet");
|
||||
goto error;
|
||||
}
|
||||
session->next_crypto->dh_server_signature = signature;
|
||||
signature=NULL; /* ownership changed */
|
||||
/* TODO: verify signature now instead of waiting for NEWKEYS */
|
||||
if (ssh_curve25519_build_k(session) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||
goto error;
|
||||
}
|
||||
signature = ssh_buffer_get_ssh_string(packet);
|
||||
if (signature == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No signature in packet");
|
||||
goto error;
|
||||
}
|
||||
session->next_crypto->dh_server_signature = signature;
|
||||
signature = NULL; /* ownership changed */
|
||||
/* TODO: verify signature now instead of waiting for NEWKEYS */
|
||||
if (ssh_curve25519_build_k(session) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Send the MSG_NEWKEYS */
|
||||
rc = ssh_packet_send_newkeys(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||
/* Send the MSG_NEWKEYS */
|
||||
rc = ssh_packet_send_newkeys(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init);
|
||||
|
||||
static ssh_packet_callback dh_server_callbacks[]= {
|
||||
ssh_packet_server_curve25519_init
|
||||
static ssh_packet_callback dh_server_callbacks[] = {
|
||||
ssh_packet_server_curve25519_init,
|
||||
};
|
||||
|
||||
static struct ssh_packet_callbacks_struct ssh_curve25519_server_callbacks = {
|
||||
.start = SSH2_MSG_KEX_ECDH_INIT,
|
||||
.n_callbacks = 1,
|
||||
.callbacks = dh_server_callbacks,
|
||||
.user = NULL
|
||||
.user = NULL,
|
||||
};
|
||||
|
||||
/** @internal
|
||||
* @brief sets up the curve25519-sha256@libssh.org kex callbacks
|
||||
*/
|
||||
void ssh_server_curve25519_init(ssh_session session){
|
||||
void ssh_server_curve25519_init(ssh_session session)
|
||||
{
|
||||
/* register the packet callbacks */
|
||||
ssh_packet_set_callbacks(session, &ssh_curve25519_server_callbacks);
|
||||
}
|
||||
@@ -374,7 +225,8 @@ void ssh_server_curve25519_init(ssh_session session){
|
||||
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a
|
||||
* SSH_MSG_KEXDH_REPLY
|
||||
*/
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
|
||||
{
|
||||
/* ECDH keys */
|
||||
ssh_string q_c_string = NULL;
|
||||
ssh_string q_s_string = NULL;
|
||||
@@ -393,10 +245,10 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
/* Extract the client pubkey from the init packet */
|
||||
q_c_string = ssh_buffer_get_ssh_string(packet);
|
||||
if (q_c_string == NULL) {
|
||||
ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
|
||||
ssh_set_error(session, SSH_FATAL, "No Q_C ECC point in packet");
|
||||
goto error;
|
||||
}
|
||||
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
|
||||
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Incorrect size for server Curve25519 public key: %zu",
|
||||
@@ -405,7 +257,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
}
|
||||
|
||||
memcpy(session->next_crypto->curve25519_client_pubkey,
|
||||
ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
|
||||
ssh_string_data(q_c_string),
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
|
||||
/* Build server's key pair */
|
||||
@@ -447,8 +300,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
}
|
||||
|
||||
/* add host's public key */
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer,
|
||||
server_pubkey_blob);
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, server_pubkey_blob);
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
@@ -509,7 +361,7 @@ error:
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
|
||||
158
src/curve25519_crypto.c
Normal file
158
src/curve25519_crypto.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* curve25519_crypto.c - Curve25519 ECDH functions for key exchange (OpenSSL)
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
|
||||
*
|
||||
* The SSH 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, version 2.1 of the License.
|
||||
*
|
||||
* The SSH 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 the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey *pubkey_loc = NULL;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t pubkey_len = CURVE25519_PUBKEY_SIZE;
|
||||
int rc;
|
||||
|
||||
if (session->server) {
|
||||
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
} else {
|
||||
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_keygen_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 keygen: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_keygen(pctx, &pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate X25519 keys: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_get_raw_public_key(pkey, *pubkey_loc, &pubkey_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get X25519 raw public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->next_crypto->curve25519_privkey = pkey;
|
||||
pkey = NULL;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
|
||||
int rc, ret = SSH_ERROR;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
||||
size_t shared_key_len = CURVE25519_PUBKEY_SIZE;
|
||||
|
||||
if (session->server) {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
} else {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
}
|
||||
|
||||
pkey = session->next_crypto->curve25519_privkey;
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 key derivation: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519,
|
||||
NULL,
|
||||
*peer_pubkey_loc,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 public key EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to set peer X25519 public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive(pctx, k, &shared_key_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to derive X25519 shared secret: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
EVP_PKEY_free(pubkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return ret;
|
||||
}
|
||||
73
src/curve25519_fallback.c
Normal file
73
src/curve25519_fallback.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* curve25519_fallback.c - Curve25519 ECDH functions for key exchange
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
|
||||
*
|
||||
* The SSH 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, version 2.1 of the License.
|
||||
*
|
||||
* The SSH 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 the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#ifdef WITH_NACL
|
||||
#include "nacl/crypto_scalarmult_curve25519.h"
|
||||
#endif
|
||||
|
||||
int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey *pubkey_loc = NULL;
|
||||
int rc;
|
||||
|
||||
if (session->server) {
|
||||
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
} else {
|
||||
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
}
|
||||
|
||||
rc = ssh_get_random(session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE,
|
||||
1);
|
||||
if (rc != 1) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
crypto_scalarmult_base(*pubkey_loc,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
|
||||
|
||||
if (session->server) {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
} else {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
}
|
||||
|
||||
crypto_scalarmult(k,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
*peer_pubkey_loc);
|
||||
return SSH_OK;
|
||||
}
|
||||
199
src/curve25519_gcrypt.c
Normal file
199
src/curve25519_gcrypt.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* curve25519_gcrypt.c - Curve25519 ECDH functions for key exchange (Gcrypt)
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
|
||||
* Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.com>
|
||||
*
|
||||
* The SSH 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, version 2.1 of the License.
|
||||
*
|
||||
* The SSH 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 the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey *pubkey_loc = NULL;
|
||||
gcry_error_t gcry_err;
|
||||
gcry_sexp_t param = NULL, keypair_sexp = NULL;
|
||||
ssh_string pubkey = NULL;
|
||||
const char *pubkey_data = NULL;
|
||||
int ret = SSH_ERROR;
|
||||
|
||||
if (session->server) {
|
||||
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
} else {
|
||||
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
}
|
||||
|
||||
gcry_err =
|
||||
gcry_sexp_build(¶m, NULL, "(genkey (ecdh (curve Curve25519)))");
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create keypair sexp: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
gcry_err = gcry_pk_genkey(&keypair_sexp, param);
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate keypair: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Extract the public key */
|
||||
pubkey = ssh_sexp_extract_mpi(keypair_sexp,
|
||||
"q",
|
||||
GCRYMPI_FMT_USG,
|
||||
GCRYMPI_FMT_STD);
|
||||
if (pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to extract public key: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Store the public key in the session */
|
||||
/* The first byte should be 0x40 indicating that the point is compressed, so
|
||||
* we skip storing it */
|
||||
pubkey_data = (char *)ssh_string_data(pubkey);
|
||||
if (ssh_string_len(pubkey) != CURVE25519_PUBKEY_SIZE + 1 ||
|
||||
pubkey_data[0] != 0x40) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Invalid public key with length: %zu",
|
||||
ssh_string_len(pubkey));
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(*pubkey_loc, pubkey_data + 1, CURVE25519_PUBKEY_SIZE);
|
||||
|
||||
/* Store the private key */
|
||||
session->next_crypto->curve25519_privkey = keypair_sexp;
|
||||
keypair_sexp = NULL;
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
ssh_string_burn(pubkey);
|
||||
SSH_STRING_FREE(pubkey);
|
||||
gcry_sexp_release(param);
|
||||
gcry_sexp_release(keypair_sexp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
|
||||
gcry_error_t gcry_err;
|
||||
gcry_sexp_t pubkey_sexp = NULL, privkey_data_sexp = NULL,
|
||||
result_sexp = NULL;
|
||||
ssh_string shared_secret = NULL, privkey = NULL;
|
||||
char *shared_secret_data = NULL;
|
||||
int ret = SSH_ERROR;
|
||||
|
||||
if (session->server) {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
} else {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
}
|
||||
|
||||
gcry_err = gcry_sexp_build(
|
||||
&pubkey_sexp,
|
||||
NULL,
|
||||
"(key-data(public-key (ecdh (curve Curve25519) (q %b))))",
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
*peer_pubkey_loc);
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create peer public key sexp: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
privkey = ssh_sexp_extract_mpi(session->next_crypto->curve25519_privkey,
|
||||
"d",
|
||||
GCRYMPI_FMT_USG,
|
||||
GCRYMPI_FMT_STD);
|
||||
if (privkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to extract private key");
|
||||
goto out;
|
||||
}
|
||||
|
||||
gcry_err = gcry_sexp_build(&privkey_data_sexp,
|
||||
NULL,
|
||||
"(data(flags raw)(value %b))",
|
||||
ssh_string_len(privkey),
|
||||
ssh_string_data(privkey));
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create private key sexp: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
gcry_err = gcry_pk_encrypt(&result_sexp, privkey_data_sexp, pubkey_sexp);
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to compute shared secret: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
shared_secret = ssh_sexp_extract_mpi(result_sexp,
|
||||
"s",
|
||||
GCRYMPI_FMT_USG,
|
||||
GCRYMPI_FMT_USG);
|
||||
if (shared_secret == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to extract shared secret");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy the shared secret to the output buffer */
|
||||
/* The first byte should be 0x40 indicating that it is a compressed point,
|
||||
* so we skip it */
|
||||
shared_secret_data = (char *)ssh_string_data(shared_secret);
|
||||
if (ssh_string_len(shared_secret) != CURVE25519_PUBKEY_SIZE + 1 ||
|
||||
shared_secret_data[0] != 0x40) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Invalid shared secret with length: %zu",
|
||||
ssh_string_len(shared_secret));
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(k, shared_secret_data + 1, CURVE25519_PUBKEY_SIZE);
|
||||
|
||||
ret = SSH_OK;
|
||||
gcry_sexp_release(session->next_crypto->curve25519_privkey);
|
||||
session->next_crypto->curve25519_privkey = NULL;
|
||||
|
||||
out:
|
||||
ssh_string_burn(shared_secret);
|
||||
SSH_STRING_FREE(shared_secret);
|
||||
ssh_string_burn(privkey);
|
||||
SSH_STRING_FREE(privkey);
|
||||
gcry_sexp_release(privkey_data_sexp);
|
||||
gcry_sexp_release(pubkey_sexp);
|
||||
gcry_sexp_release(result_sexp);
|
||||
return ret;
|
||||
}
|
||||
189
src/curve25519_mbedcrypto.c
Normal file
189
src/curve25519_mbedcrypto.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* curve25519_mbedcrypto.c - Curve25519 ECDH functions for key exchange
|
||||
* (MbedTLS)
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
|
||||
* Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.com>
|
||||
*
|
||||
* The SSH 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, version 2.1 of the License.
|
||||
*
|
||||
* The SSH 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 the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "mbedcrypto-compat.h"
|
||||
|
||||
#include <mbedtls/ecdh.h>
|
||||
#include <mbedtls/error.h>
|
||||
|
||||
int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey *pubkey_loc = NULL;
|
||||
mbedtls_ecdh_context ecdh_ctx;
|
||||
mbedtls_ecdh_params *ecdh_params = NULL;
|
||||
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
|
||||
int rc, ret = SSH_ERROR;
|
||||
char error_buf[128];
|
||||
|
||||
if (session->server) {
|
||||
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
} else {
|
||||
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
}
|
||||
|
||||
ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
|
||||
|
||||
mbedtls_ecdh_init(&ecdh_ctx);
|
||||
rc = mbedtls_ecdh_setup(&ecdh_ctx, MBEDTLS_ECP_DP_CURVE25519);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to setup X25519 context: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ecdh_params = &MBEDTLS_ECDH_PARAMS(ecdh_ctx);
|
||||
|
||||
rc = mbedtls_ecdh_gen_public(&ecdh_params->MBEDTLS_ECDH_PRIVATE(grp),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Q),
|
||||
mbedtls_ctr_drbg_random,
|
||||
ctr_drbg);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate X25519 keypair: %s",
|
||||
error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_write_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
|
||||
session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to write X25519 private key: %s",
|
||||
error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_write_binary_le(
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Q).MBEDTLS_ECDH_PRIVATE(X),
|
||||
*pubkey_loc,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to write X25519 public key: %s",
|
||||
error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
mbedtls_ecdh_free(&ecdh_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
|
||||
int rc, ret = SSH_ERROR;
|
||||
mbedtls_ecdh_context ecdh_ctx;
|
||||
mbedtls_ecdh_params *ecdh_params = NULL;
|
||||
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
|
||||
char error_buf[128];
|
||||
|
||||
if (session->server) {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
} else {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
}
|
||||
|
||||
ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
|
||||
|
||||
mbedtls_ecdh_init(&ecdh_ctx);
|
||||
rc = mbedtls_ecdh_setup(&ecdh_ctx, MBEDTLS_ECP_DP_CURVE25519);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to setup X25519 context: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ecdh_params = &MBEDTLS_ECDH_PARAMS(ecdh_ctx);
|
||||
|
||||
rc = mbedtls_mpi_read_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
|
||||
session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to read private key: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_read_binary_le(
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp).MBEDTLS_ECDH_PRIVATE(X),
|
||||
*peer_pubkey_loc,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to read peer public key: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_lset(
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp).MBEDTLS_ECDH_PRIVATE(Z),
|
||||
1);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to set Z coordinate: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_ecdh_compute_shared(&ecdh_params->MBEDTLS_ECDH_PRIVATE(grp),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(z),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
|
||||
mbedtls_ctr_drbg_random,
|
||||
ctr_drbg);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to compute shared secret: %s",
|
||||
error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_write_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(z),
|
||||
k,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to write shared secret: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
mbedtls_ecdh_free(&ecdh_ctx);
|
||||
return ret;
|
||||
}
|
||||
14
src/dh-gex.c
14
src/dh-gex.c
@@ -416,6 +416,9 @@ static int ssh_retrieve_dhgroup_file(FILE *moduli,
|
||||
do {
|
||||
firstbyte = getc(moduli);
|
||||
} while(firstbyte != '\n' && firstbyte != EOF);
|
||||
if (firstbyte == EOF) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (firstbyte == EOF) {
|
||||
@@ -439,6 +442,9 @@ static int ssh_retrieve_dhgroup_file(FILE *moduli,
|
||||
do {
|
||||
firstbyte = getc(moduli);
|
||||
} while(firstbyte != '\n' && firstbyte != EOF);
|
||||
if (firstbyte == EOF) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -571,12 +577,12 @@ error:
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_dhgex_request);
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_dhgex_init);
|
||||
|
||||
static ssh_packet_callback dhgex_server_callbacks[]= {
|
||||
NULL, /* SSH_MSG_KEX_DH_GEX_REQUEST_OLD */
|
||||
NULL, /* SSH_MSG_KEX_DH_GEX_GROUP */
|
||||
static ssh_packet_callback dhgex_server_callbacks[] = {
|
||||
NULL, /* SSH_MSG_KEX_DH_GEX_REQUEST_OLD */
|
||||
NULL, /* SSH_MSG_KEX_DH_GEX_GROUP */
|
||||
ssh_packet_server_dhgex_init, /* SSH_MSG_KEX_DH_GEX_INIT */
|
||||
NULL, /* SSH_MSG_KEX_DH_GEX_REPLY */
|
||||
ssh_packet_server_dhgex_request /* SSH_MSG_GEX_DH_GEX_REQUEST */
|
||||
ssh_packet_server_dhgex_request /* SSH_MSG_KEX_DH_GEX_REQUEST */
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ done:
|
||||
*/
|
||||
int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
||||
{
|
||||
struct dh_ctx *ctx;
|
||||
struct dh_ctx *ctx = NULL;
|
||||
int rc;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
@@ -592,7 +592,7 @@ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote,
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
*dest = BN_bin2bn(kstring, klen, NULL);
|
||||
*dest = BN_bin2bn(kstring, (int)klen, NULL);
|
||||
if (*dest == NULL) {
|
||||
rc = SSH_ERROR;
|
||||
goto done;
|
||||
|
||||
@@ -444,7 +444,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init)
|
||||
ssh_string q_c_string = NULL;
|
||||
ssh_string q_s_string = NULL;
|
||||
/* SSH host keys (rsa, ed25519 and ecdsa) */
|
||||
ssh_key privkey;
|
||||
ssh_key privkey = NULL;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
|
||||
@@ -132,9 +132,9 @@ int ecdh_build_k(ssh_session session)
|
||||
#else
|
||||
size_t k_len = 0;
|
||||
enum ssh_key_exchange_e kex_type = session->next_crypto->kex_type;
|
||||
ssh_string s;
|
||||
ssh_string s = NULL;
|
||||
#endif
|
||||
ssh_string pubkey_raw;
|
||||
ssh_string pubkey_raw = NULL;
|
||||
gcry_sexp_t pubkey = NULL;
|
||||
ssh_string privkey = NULL;
|
||||
int rc = SSH_ERROR;
|
||||
@@ -267,12 +267,12 @@ int ecdh_build_k(ssh_session session)
|
||||
SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
gpg_error_t err;
|
||||
/* ECDH keys */
|
||||
ssh_string q_c_string;
|
||||
ssh_string q_s_string;
|
||||
ssh_string q_c_string = NULL;
|
||||
ssh_string q_s_string = NULL;
|
||||
gcry_sexp_t param = NULL;
|
||||
gcry_sexp_t key = NULL;
|
||||
/* SSH host keys (rsa, ed25519 and ecdsa) */
|
||||
ssh_key privkey;
|
||||
ssh_key privkey = NULL;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
|
||||
1060
src/external/sntrup761.c
vendored
Normal file
1060
src/external/sntrup761.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -47,7 +47,7 @@ int ssh_gcry_dec2bn(bignum *bn, const char *data) {
|
||||
|
||||
char *ssh_gcry_bn2dec(bignum bn) {
|
||||
bignum bndup, num, ten;
|
||||
char *ret;
|
||||
char *ret = NULL;
|
||||
int count, count2;
|
||||
int size, rsize;
|
||||
char decnum;
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
*/
|
||||
static int ssh_gets(const char *prompt, char *buf, size_t len, int verify)
|
||||
{
|
||||
char *tmp;
|
||||
char *tmp = NULL;
|
||||
char *ptr = NULL;
|
||||
int ok = 0;
|
||||
|
||||
@@ -63,7 +63,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify)
|
||||
fprintf(stdout, "%s", prompt);
|
||||
}
|
||||
fflush(stdout);
|
||||
if (fgets(tmp, len, stdin) == NULL) {
|
||||
if (fgets(tmp, (int)len, stdin) == NULL) {
|
||||
free(tmp);
|
||||
return 0;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify)
|
||||
}
|
||||
|
||||
if (verify) {
|
||||
char *key_string;
|
||||
char *key_string = NULL;
|
||||
|
||||
key_string = calloc(1, len);
|
||||
if (key_string == NULL) {
|
||||
@@ -87,7 +87,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify)
|
||||
|
||||
fprintf(stdout, "\nVerifying, please re-enter. %s", prompt);
|
||||
fflush(stdout);
|
||||
if (! fgets(key_string, len, stdin)) {
|
||||
if (!fgets(key_string, (int)len, stdin)) {
|
||||
explicit_bzero(key_string, len);
|
||||
SAFE_FREE(key_string);
|
||||
clearerr(stdin);
|
||||
|
||||
28
src/gssapi.c
28
src/gssapi.c
@@ -159,7 +159,7 @@ ssh_gssapi_handle_userauth(ssh_session session, const char *user,
|
||||
gss_name_t server_name; /* local server fqdn */
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
size_t i;
|
||||
char *ptr;
|
||||
char *ptr = NULL;
|
||||
gss_OID_set supported; /* oids supported by server */
|
||||
gss_OID_set both_supported; /* oids supported by both client and server */
|
||||
gss_OID_set selected; /* oid selected for authentication */
|
||||
@@ -313,7 +313,7 @@ ssh_gssapi_name_to_char(gss_name_t name)
|
||||
{
|
||||
gss_buffer_desc buffer;
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
char *ptr;
|
||||
char *ptr = NULL;
|
||||
maj_stat = gss_display_name(&min_stat, name, &buffer, NULL);
|
||||
ssh_gssapi_log_error(SSH_LOG_DEBUG,
|
||||
"converting name",
|
||||
@@ -331,9 +331,10 @@ ssh_gssapi_name_to_char(gss_name_t name)
|
||||
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
||||
ssh_string token;
|
||||
char *hexa;
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server)
|
||||
{
|
||||
ssh_string token = NULL;
|
||||
char *hexa = NULL;
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_name_t client_name = GSS_C_NO_NAME;
|
||||
@@ -357,7 +358,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
||||
}
|
||||
|
||||
if (ssh_callbacks_exists(session->server_callbacks, gssapi_accept_sec_ctx_function)){
|
||||
ssh_string out_token=NULL;
|
||||
ssh_string out_token = NULL;
|
||||
rc = session->server_callbacks->gssapi_accept_sec_ctx_function(session,
|
||||
token, &out_token, session->server_callbacks->userdata);
|
||||
if (rc == SSH_ERROR){
|
||||
@@ -473,7 +474,7 @@ static ssh_buffer ssh_gssapi_build_mic(ssh_session session)
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_mic)
|
||||
{
|
||||
ssh_string mic_token;
|
||||
ssh_string mic_token = NULL;
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER;
|
||||
@@ -635,7 +636,7 @@ static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
|
||||
gss_name_t client_id = GSS_C_NO_NAME;
|
||||
gss_OID oid;
|
||||
unsigned int i;
|
||||
char *ptr;
|
||||
char *ptr = NULL;
|
||||
int ret;
|
||||
|
||||
if (session->gssapi->client.client_deleg_creds == NULL) {
|
||||
@@ -837,11 +838,11 @@ static gss_OID ssh_gssapi_oid_from_string(ssh_string oid_s)
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){
|
||||
int rc;
|
||||
ssh_string oid_s;
|
||||
ssh_string oid_s = NULL;
|
||||
gss_uint32 maj_stat, min_stat;
|
||||
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
||||
char *hexa;
|
||||
char *hexa = NULL;
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
@@ -956,10 +957,11 @@ static int ssh_gssapi_send_mic(ssh_session session)
|
||||
return ssh_packet_send(session);
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client)
|
||||
{
|
||||
int rc;
|
||||
ssh_string token;
|
||||
char *hexa;
|
||||
ssh_string token = NULL;
|
||||
char *hexa = NULL;
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER;
|
||||
(void)user;
|
||||
|
||||
44
src/gzip.c
44
src/gzip.c
@@ -26,13 +26,15 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#ifdef WITH_ZLIB
|
||||
#include <zlib.h>
|
||||
|
||||
#ifndef BLOCKSIZE
|
||||
#define BLOCKSIZE 4092
|
||||
#endif
|
||||
@@ -50,6 +52,7 @@ initcompress(ssh_session session, int level)
|
||||
|
||||
status = deflateInit(stream, level);
|
||||
if (status != Z_OK) {
|
||||
deflateEnd(stream);
|
||||
SAFE_FREE(stream);
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
@@ -158,6 +161,7 @@ initdecompress(ssh_session session)
|
||||
|
||||
status = inflateInit(stream);
|
||||
if (status != Z_OK) {
|
||||
inflateEnd(stream);
|
||||
SAFE_FREE(stream);
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
@@ -258,3 +262,41 @@ decompress_buffer(ssh_session session, ssh_buffer buf, size_t maxlen)
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
compress_cleanup(struct ssh_crypto_struct *crypto)
|
||||
{
|
||||
if (crypto->compress_out_ctx) {
|
||||
deflateEnd(crypto->compress_out_ctx);
|
||||
}
|
||||
SAFE_FREE(crypto->compress_out_ctx);
|
||||
|
||||
if (crypto->compress_in_ctx) {
|
||||
inflateEnd(crypto->compress_in_ctx);
|
||||
}
|
||||
SAFE_FREE(crypto->compress_in_ctx);
|
||||
}
|
||||
#else /* WITH_ZLIB */
|
||||
|
||||
int
|
||||
compress_buffer(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_buffer buf))
|
||||
{
|
||||
/* without zlib compiled in, this should never happen */
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
decompress_buffer(UNUSED_PARAM(ssh_session session),
|
||||
UNUSED_PARAM(ssh_buffer buf),
|
||||
UNUSED_PARAM(size_t maxlen))
|
||||
{
|
||||
/* without zlib compiled in, this should never happen */
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
compress_cleanup(UNUSED_PARAM(struct ssh_crypto_struct *crypto))
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
#endif /* WITH_ZLIB */
|
||||
|
||||
144
src/kex.c
144
src/kex.c
@@ -40,6 +40,7 @@
|
||||
#include "libssh/ssh2.h"
|
||||
#include "libssh/string.h"
|
||||
#include "libssh/curve25519.h"
|
||||
#include "libssh/sntrup761.h"
|
||||
#include "libssh/knownhosts.h"
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/pki.h"
|
||||
@@ -95,6 +96,12 @@
|
||||
#define CURVE25519 ""
|
||||
#endif /* HAVE_CURVE25519 */
|
||||
|
||||
#ifdef HAVE_SNTRUP761
|
||||
#define SNTRUP761X25519 "sntrup761x25519-sha512@openssh.com,"
|
||||
#else
|
||||
#define SNTRUP761X25519 ""
|
||||
#endif /* HAVE_SNTRUP761 */
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
#define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
|
||||
#define EC_HOSTKEYS "ecdsa-sha2-nistp521," \
|
||||
@@ -159,6 +166,7 @@
|
||||
|
||||
#define DEFAULT_KEY_EXCHANGE \
|
||||
CURVE25519 \
|
||||
SNTRUP761X25519 \
|
||||
ECDH \
|
||||
"diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \
|
||||
GEX_SHA256 \
|
||||
@@ -267,38 +275,58 @@ static const char *ssh_kex_descriptions[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo)
|
||||
const char *ssh_kex_get_default_methods(enum ssh_kex_types_e type)
|
||||
{
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
if (type >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return default_methods[algo];
|
||||
return default_methods[type];
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo)
|
||||
const char *ssh_kex_get_supported_method(enum ssh_kex_types_e type)
|
||||
{
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
if (type >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return supported_methods[algo];
|
||||
return supported_methods[type];
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_description(uint32_t algo) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
const char *ssh_kex_get_description(enum ssh_kex_types_e type)
|
||||
{
|
||||
if (type >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ssh_kex_descriptions[algo];
|
||||
return ssh_kex_descriptions[type];
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_fips_methods(uint32_t algo) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
const char *ssh_kex_get_fips_methods(enum ssh_kex_types_e type)
|
||||
{
|
||||
if (type >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fips_methods[algo];
|
||||
return fips_methods[type];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a list of supported algorithms of a given type. This respects the
|
||||
* FIPS mode status.
|
||||
*
|
||||
* @param[in] type The type of the algorithm to query (SSH_KEX, SSH_MAC_C_S,
|
||||
* ...).
|
||||
*
|
||||
* @return The list of supported methods as comma-separated string, or NULL for
|
||||
* unknown type.
|
||||
*/
|
||||
const char *ssh_get_supported_methods(enum ssh_kex_types_e type)
|
||||
{
|
||||
if (ssh_fips_mode()) {
|
||||
return ssh_kex_get_fips_methods(type);
|
||||
} else {
|
||||
return ssh_kex_get_supported_method(type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,7 +341,7 @@ static int cmp_first_kex_algo(const char *client_str,
|
||||
size_t client_kex_len;
|
||||
size_t server_kex_len;
|
||||
|
||||
char *colon;
|
||||
char *colon = NULL;
|
||||
|
||||
int is_wrong = 1;
|
||||
|
||||
@@ -351,7 +379,6 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
int server_kex = session->server;
|
||||
ssh_string str = NULL;
|
||||
char *strings[SSH_KEX_METHODS] = {0};
|
||||
char *rsa_sig_ext = NULL;
|
||||
int rc = SSH_ERROR;
|
||||
size_t len;
|
||||
|
||||
@@ -577,6 +604,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
*/
|
||||
if ((session->extensions & SSH_EXT_SIG_RSA_SHA256) &&
|
||||
(session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
|
||||
char *rsa_sig_ext = NULL;
|
||||
session->extensions &= ~(SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512);
|
||||
rsa_sig_ext = ssh_find_matching("rsa-sha2-512,rsa-sha2-256",
|
||||
hostkeys);
|
||||
@@ -751,7 +779,7 @@ char *ssh_client_select_hostkeys(ssh_session session)
|
||||
int ssh_set_client_kex(ssh_session session)
|
||||
{
|
||||
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
|
||||
const char *wanted;
|
||||
const char *wanted = NULL;
|
||||
int ok;
|
||||
int i;
|
||||
|
||||
@@ -894,6 +922,8 @@ kex_select_kex_type(const char *kex)
|
||||
return SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
|
||||
} else if (strcmp(kex, "curve25519-sha256") == 0) {
|
||||
return SSH_KEX_CURVE25519_SHA256;
|
||||
} else if (strcmp(kex, "sntrup761x25519-sha512@openssh.com") == 0) {
|
||||
return SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM;
|
||||
}
|
||||
/* should not happen. We should be getting only valid names at this stage */
|
||||
return 0;
|
||||
@@ -933,6 +963,11 @@ static void revert_kex_callbacks(ssh_session session)
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
ssh_client_curve25519_remove_callbacks(session);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_SNTRUP761
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
ssh_client_sntrup761x25519_remove_callbacks(session);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1042,7 +1077,7 @@ int ssh_send_kex(ssh_session session)
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bP",
|
||||
SSH2_MSG_KEXINIT,
|
||||
16,
|
||||
(size_t)16,
|
||||
kex->cookie); /* cookie */
|
||||
if (rc != SSH_OK)
|
||||
goto error;
|
||||
@@ -1340,6 +1375,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
|
||||
buf = ssh_buffer_new();
|
||||
if (buf == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1348,6 +1384,9 @@ int ssh_make_sessionid(ssh_session session)
|
||||
session->clientbanner,
|
||||
session->serverbanner);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to pack client and server banner");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1361,20 +1400,26 @@ int ssh_make_sessionid(ssh_session session)
|
||||
|
||||
rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to get next server pubkey blob");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"dPdPS",
|
||||
ssh_buffer_get_len(client_hash),
|
||||
ssh_buffer_get_len(client_hash),
|
||||
(size_t)ssh_buffer_get_len(client_hash),
|
||||
ssh_buffer_get(client_hash),
|
||||
ssh_buffer_get_len(server_hash),
|
||||
ssh_buffer_get_len(server_hash),
|
||||
(size_t)ssh_buffer_get_len(server_hash),
|
||||
ssh_buffer_get(server_hash),
|
||||
server_pubkey_blob);
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to pack hashes and pubkey blob");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1399,6 +1444,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
client_pubkey,
|
||||
server_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to pack DH pubkeys");
|
||||
goto error;
|
||||
}
|
||||
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
@@ -1434,6 +1480,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
client_pubkey,
|
||||
server_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to pack DH GEX params");
|
||||
goto error;
|
||||
}
|
||||
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
@@ -1456,6 +1503,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
session->next_crypto->ecdh_client_pubkey,
|
||||
session->next_crypto->ecdh_server_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to pack ECDH pubkeys");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
@@ -1466,18 +1514,54 @@ int ssh_make_sessionid(ssh_session session)
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"dPdP",
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_server_pubkey);
|
||||
(size_t)CURVE25519_PUBKEY_SIZE,
|
||||
session->next_crypto->curve25519_server_pubkey);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to pack Curve25519 pubkeys");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
#endif /* HAVE_CURVE25519 */
|
||||
#ifdef HAVE_SNTRUP761
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"dPPdPP",
|
||||
SNTRUP761_PUBLICKEY_SIZE + CURVE25519_PUBKEY_SIZE,
|
||||
(size_t)SNTRUP761_PUBLICKEY_SIZE,
|
||||
session->next_crypto->sntrup761_client_pubkey,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
SNTRUP761_CIPHERTEXT_SIZE + CURVE25519_PUBKEY_SIZE,
|
||||
(size_t)SNTRUP761_CIPHERTEXT_SIZE,
|
||||
session->next_crypto->sntrup761_ciphertext,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE,
|
||||
session->next_crypto->curve25519_server_pubkey);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to pack SNTRU Prime params");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
#endif /* HAVE_SNTRUP761 */
|
||||
}
|
||||
if (session->next_crypto->kex_type == SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM) {
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"F",
|
||||
session->next_crypto->shared_secret,
|
||||
SHA512_DIGEST_LEN);
|
||||
} else {
|
||||
rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
|
||||
}
|
||||
rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to pack shared secret");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1532,6 +1616,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
|
||||
session->next_crypto->digest_type = SSH_KDF_SHA512;
|
||||
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
|
||||
@@ -1668,7 +1753,12 @@ int ssh_generate_session_keys(ssh_session session)
|
||||
size_t intkey_srv_to_cli_len = 0;
|
||||
int rc = -1;
|
||||
|
||||
k_string = ssh_make_bignum_string(crypto->shared_secret);
|
||||
if (session->next_crypto->kex_type == SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM) {
|
||||
k_string = ssh_make_padded_bignum_string(crypto->shared_secret,
|
||||
SHA512_DIGEST_LEN);
|
||||
} else {
|
||||
k_string = ssh_make_bignum_string(crypto->shared_secret);
|
||||
}
|
||||
if (k_string == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
|
||||
@@ -79,8 +79,8 @@ static struct ssh_tokens_st *ssh_get_knownhost_line(FILE **file,
|
||||
const char **found_type)
|
||||
{
|
||||
char buffer[MAX_LINE_SIZE] = {0};
|
||||
char *ptr;
|
||||
struct ssh_tokens_st *tokens;
|
||||
char *ptr = NULL;
|
||||
struct ssh_tokens_st *tokens = NULL;
|
||||
|
||||
if (*file == NULL) {
|
||||
*file = fopen(filename,"r");
|
||||
@@ -149,7 +149,7 @@ static struct ssh_tokens_st *ssh_get_knownhost_line(FILE **file,
|
||||
static int check_public_key(ssh_session session, char **tokens) {
|
||||
ssh_string pubkey_blob = NULL;
|
||||
ssh_buffer pubkey_buffer;
|
||||
char *pubkey_64;
|
||||
char *pubkey_64 = NULL;
|
||||
int rc;
|
||||
|
||||
/* ssh-rsa, ssh-ed25519, .. */
|
||||
@@ -205,11 +205,11 @@ static int match_hashed_host(const char *host, const char *sourcehash)
|
||||
* hash := HMAC_SHA1(key=salt,data=host)
|
||||
*/
|
||||
unsigned char buffer[256] = {0};
|
||||
ssh_buffer salt;
|
||||
ssh_buffer hash;
|
||||
HMACCTX mac;
|
||||
char *source;
|
||||
char *b64hash;
|
||||
ssh_buffer salt = NULL;
|
||||
ssh_buffer hash = NULL;
|
||||
HMACCTX mac = NULL;
|
||||
char *source = NULL;
|
||||
char *b64hash = NULL;
|
||||
int match, rc;
|
||||
size_t size;
|
||||
|
||||
@@ -304,14 +304,14 @@ static int match_hashed_host(const char *host, const char *sourcehash)
|
||||
int ssh_is_server_known(ssh_session session)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
char *host;
|
||||
char *hostport;
|
||||
const char *type;
|
||||
char *host = NULL;
|
||||
char *hostport = NULL;
|
||||
const char *type = NULL;
|
||||
int match;
|
||||
int i = 0;
|
||||
char *files[3];
|
||||
char *files[3] = {0};
|
||||
|
||||
struct ssh_tokens_st *tokens;
|
||||
struct ssh_tokens_st *tokens = NULL;
|
||||
|
||||
int ret = SSH_SERVER_NOT_KNOWN;
|
||||
|
||||
@@ -443,12 +443,13 @@ int ssh_is_server_known(ssh_session session)
|
||||
* @deprecated Please use ssh_session_export_known_hosts_entry()
|
||||
* @brief This function is deprecated.
|
||||
*/
|
||||
char * ssh_dump_knownhost(ssh_session session) {
|
||||
char *ssh_dump_knownhost(ssh_session session)
|
||||
{
|
||||
ssh_key server_pubkey = NULL;
|
||||
char *host;
|
||||
char *hostport;
|
||||
char *buffer;
|
||||
char *b64_key;
|
||||
char *host = NULL;
|
||||
char *hostport = NULL;
|
||||
char *buffer = NULL;
|
||||
char *b64_key = NULL;
|
||||
int rc;
|
||||
|
||||
if (session->opts.host == NULL) {
|
||||
@@ -513,9 +514,9 @@ char * ssh_dump_knownhost(ssh_session session) {
|
||||
*/
|
||||
int ssh_write_knownhost(ssh_session session)
|
||||
{
|
||||
FILE *file;
|
||||
FILE *file = NULL;
|
||||
char *buffer = NULL;
|
||||
char *dir;
|
||||
char *dir = NULL;
|
||||
int rc;
|
||||
|
||||
if (session->opts.knownhosts == NULL) {
|
||||
|
||||
@@ -61,7 +61,7 @@ static int hash_hostname(const char *name,
|
||||
size_t *hash_size)
|
||||
{
|
||||
int rc;
|
||||
HMACCTX mac_ctx;
|
||||
HMACCTX mac_ctx = NULL;
|
||||
|
||||
mac_ctx = hmac_init(salt, salt_size, SSH_HMAC_SHA1);
|
||||
if (mac_ctx == NULL) {
|
||||
@@ -81,8 +81,8 @@ static int hash_hostname(const char *name,
|
||||
|
||||
static int match_hashed_hostname(const char *host, const char *hashed_host)
|
||||
{
|
||||
char *hashed;
|
||||
char *b64_hash;
|
||||
char *hashed = NULL;
|
||||
char *b64_hash = NULL;
|
||||
ssh_buffer salt = NULL;
|
||||
ssh_buffer hash = NULL;
|
||||
unsigned char hashed_buf[256] = {0};
|
||||
@@ -171,7 +171,7 @@ static int known_hosts_read_line(FILE *fp,
|
||||
size_t *buf_len,
|
||||
size_t *lineno)
|
||||
{
|
||||
while (fgets(buf, buf_size, fp) != NULL) {
|
||||
while (fgets(buf, (int)buf_size, fp) != NULL) {
|
||||
size_t len;
|
||||
if (buf[0] == '\0') {
|
||||
continue;
|
||||
@@ -229,7 +229,7 @@ static int ssh_known_hosts_read_entries(const char *match,
|
||||
char line[MAX_LINE_SIZE];
|
||||
size_t lineno = 0;
|
||||
size_t len = 0;
|
||||
FILE *fp;
|
||||
FILE *fp = NULL;
|
||||
int rc;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
@@ -288,7 +288,7 @@ static int ssh_known_hosts_read_entries(const char *match,
|
||||
for (it = ssh_list_get_iterator(*entries);
|
||||
it != NULL;
|
||||
it = it->next) {
|
||||
struct ssh_knownhosts_entry *entry2;
|
||||
struct ssh_knownhosts_entry *entry2 = NULL;
|
||||
int cmp;
|
||||
entry2 = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
||||
cmp = ssh_known_hosts_entries_compare(entry, entry2);
|
||||
@@ -312,8 +312,8 @@ error:
|
||||
|
||||
static char *ssh_session_get_host_port(ssh_session session)
|
||||
{
|
||||
char *host_port;
|
||||
char *host;
|
||||
char *host_port = NULL;
|
||||
char *host = NULL;
|
||||
|
||||
if (session->opts.host == NULL) {
|
||||
ssh_set_error(session,
|
||||
@@ -530,7 +530,7 @@ char *ssh_known_hosts_get_algorithms_names(ssh_session session)
|
||||
char *host_port = NULL;
|
||||
size_t count;
|
||||
bool needcomma = false;
|
||||
char *names;
|
||||
char *names = NULL;
|
||||
|
||||
int rc;
|
||||
|
||||
@@ -638,7 +638,7 @@ int ssh_known_hosts_parse_line(const char *hostname,
|
||||
{
|
||||
struct ssh_knownhosts_entry *e = NULL;
|
||||
char *known_host = NULL;
|
||||
char *p;
|
||||
char *p = NULL;
|
||||
char *save_tok = NULL;
|
||||
enum ssh_keytypes_e key_type;
|
||||
int match = 0;
|
||||
|
||||
45
src/legacy.c
45
src/legacy.c
@@ -48,7 +48,7 @@ int ssh_auth_list(ssh_session session) {
|
||||
int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
|
||||
int type, ssh_string publickey)
|
||||
{
|
||||
ssh_key key;
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
(void) type; /* unused */
|
||||
@@ -70,7 +70,7 @@ int ssh_userauth_pubkey(ssh_session session,
|
||||
ssh_string publickey,
|
||||
ssh_private_key privatekey)
|
||||
{
|
||||
ssh_key key;
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
(void) publickey; /* unused */
|
||||
@@ -376,10 +376,11 @@ void publickey_free(ssh_public_key key) {
|
||||
SAFE_FREE(key);
|
||||
}
|
||||
|
||||
ssh_public_key publickey_from_privatekey(ssh_private_key prv) {
|
||||
struct ssh_public_key_struct *p;
|
||||
ssh_key privkey;
|
||||
ssh_key pubkey;
|
||||
ssh_public_key publickey_from_privatekey(ssh_private_key prv)
|
||||
{
|
||||
struct ssh_public_key_struct *p = NULL;
|
||||
ssh_key privkey = NULL;
|
||||
ssh_key pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
privkey = ssh_key_new();
|
||||
@@ -423,8 +424,8 @@ ssh_private_key privatekey_from_file(ssh_session session,
|
||||
const char *passphrase) {
|
||||
ssh_auth_callback auth_fn = NULL;
|
||||
void *auth_data = NULL;
|
||||
ssh_private_key privkey;
|
||||
ssh_key key;
|
||||
ssh_private_key privkey = NULL;
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
(void) type; /* unused */
|
||||
@@ -440,7 +441,7 @@ ssh_private_key privatekey_from_file(ssh_session session,
|
||||
auth_fn,
|
||||
auth_data,
|
||||
&key);
|
||||
if (rc == SSH_ERROR) {
|
||||
if (rc != SSH_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -492,7 +493,7 @@ void privatekey_free(ssh_private_key prv) {
|
||||
|
||||
ssh_string publickey_from_file(ssh_session session, const char *filename,
|
||||
int *type) {
|
||||
ssh_key key;
|
||||
ssh_key key = NULL;
|
||||
ssh_string key_str = NULL;
|
||||
int rc;
|
||||
|
||||
@@ -525,9 +526,10 @@ int ssh_type_from_name(const char *name) {
|
||||
return ssh_key_type_from_name(name);
|
||||
}
|
||||
|
||||
ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) {
|
||||
struct ssh_public_key_struct *pubkey;
|
||||
ssh_key key;
|
||||
ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s)
|
||||
{
|
||||
struct ssh_public_key_struct *pubkey = NULL;
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
(void) session; /* unused */
|
||||
@@ -562,9 +564,10 @@ ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) {
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
ssh_string publickey_to_string(ssh_public_key pubkey) {
|
||||
ssh_key key;
|
||||
ssh_string key_blob;
|
||||
ssh_string publickey_to_string(ssh_public_key pubkey)
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
ssh_string key_blob = NULL;
|
||||
int rc;
|
||||
|
||||
if (pubkey == NULL) {
|
||||
@@ -609,11 +612,11 @@ int ssh_publickey_to_file(ssh_session session,
|
||||
ssh_string pubkey,
|
||||
int type)
|
||||
{
|
||||
FILE *fp;
|
||||
char *user;
|
||||
FILE *fp = NULL;
|
||||
char *user = NULL;
|
||||
char buffer[1024];
|
||||
char host[256];
|
||||
unsigned char *pubkey_64;
|
||||
unsigned char *pubkey_64 = NULL;
|
||||
size_t len;
|
||||
int rc;
|
||||
if(session==NULL)
|
||||
@@ -680,9 +683,9 @@ int ssh_try_publickey_from_file(ssh_session session,
|
||||
const char *keyfile,
|
||||
ssh_string *publickey,
|
||||
int *type) {
|
||||
char *pubkey_file;
|
||||
char *pubkey_file = NULL;
|
||||
size_t len;
|
||||
ssh_string pubkey_string;
|
||||
ssh_string pubkey_string = NULL;
|
||||
int pubkey_type;
|
||||
|
||||
if (session == NULL || keyfile == NULL || publickey == NULL || type == NULL) {
|
||||
|
||||
159
src/libcrypto.c
159
src/libcrypto.c
@@ -49,8 +49,9 @@
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/hmac.h>
|
||||
#else
|
||||
#include <openssl/param_build.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/param_build.h>
|
||||
#include <openssl/provider.h>
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
#include <openssl/rand.h>
|
||||
#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER)
|
||||
@@ -96,7 +97,37 @@ void ssh_reseed(void){
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER)
|
||||
#if defined(WITH_PKCS11_URI)
|
||||
#if defined(WITH_PKCS11_PROVIDER)
|
||||
static OSSL_PROVIDER *provider = NULL;
|
||||
static bool pkcs11_provider_failed = false;
|
||||
|
||||
int pki_load_pkcs11_provider(void)
|
||||
{
|
||||
if (OSSL_PROVIDER_available(NULL, "pkcs11") == 1) {
|
||||
/* the provider is already available.
|
||||
* Loaded through a configuration file? */
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
if (pkcs11_provider_failed) {
|
||||
/* the loading failed previously -- do not retry */
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
provider = OSSL_PROVIDER_try_load(NULL, "pkcs11", 1);
|
||||
if (provider != NULL) {
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to load the pkcs11 provider: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
/* Do not attempt to load it again */
|
||||
pkcs11_provider_failed = true;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#else
|
||||
static ENGINE *engine = NULL;
|
||||
|
||||
ENGINE *pki_get_engine(void)
|
||||
@@ -128,7 +159,8 @@ ENGINE *pki_get_engine(void)
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
#endif /* defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) */
|
||||
#endif /* defined(WITH_PKCS11_PROVIDER) */
|
||||
#endif /* defined(WITH_PKCS11_URI) */
|
||||
|
||||
#ifdef HAVE_OPENSSL_EVP_KDF_CTX
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
@@ -168,7 +200,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||
uint8_t key_type, unsigned char *output,
|
||||
size_t requested_len)
|
||||
{
|
||||
int rc = -1;
|
||||
int ret = SSH_ERROR, rv;
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
EVP_KDF_CTX *ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF);
|
||||
#else
|
||||
@@ -202,81 +234,86 @@ int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD,
|
||||
rv = EVP_KDF_ctrl(ctx,
|
||||
EVP_KDF_CTRL_SET_MD,
|
||||
sshkdf_digest_to_md(crypto->digest_type));
|
||||
if (rc != 1) {
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key, key_len);
|
||||
if (rc != 1) {
|
||||
rv = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key, key_len);
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH,
|
||||
crypto->secret_hash, crypto->digest_len);
|
||||
if (rc != 1) {
|
||||
rv = EVP_KDF_ctrl(ctx,
|
||||
EVP_KDF_CTRL_SET_SSHKDF_XCGHASH,
|
||||
crypto->secret_hash,
|
||||
crypto->digest_len);
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, key_type);
|
||||
if (rc != 1) {
|
||||
rv = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, key_type);
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
|
||||
crypto->session_id, crypto->session_id_len);
|
||||
if (rc != 1) {
|
||||
rv = EVP_KDF_ctrl(ctx,
|
||||
EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
|
||||
crypto->session_id,
|
||||
crypto->session_id_len);
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = EVP_KDF_derive(ctx, output, requested_len);
|
||||
if (rc != 1) {
|
||||
rv = EVP_KDF_derive(ctx, output, requested_len);
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_DIGEST,
|
||||
md, strlen(md));
|
||||
if (rc != 1) {
|
||||
rc = -1;
|
||||
rv = OSSL_PARAM_BLD_push_utf8_string(param_bld,
|
||||
OSSL_KDF_PARAM_DIGEST,
|
||||
md,
|
||||
strlen(md));
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_KEY,
|
||||
key, key_len);
|
||||
if (rc != 1) {
|
||||
rc = -1;
|
||||
rv = OSSL_PARAM_BLD_push_octet_string(param_bld,
|
||||
OSSL_KDF_PARAM_KEY,
|
||||
key,
|
||||
key_len);
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = OSSL_PARAM_BLD_push_octet_string(param_bld,
|
||||
rv = OSSL_PARAM_BLD_push_octet_string(param_bld,
|
||||
OSSL_KDF_PARAM_SSHKDF_XCGHASH,
|
||||
crypto->secret_hash,
|
||||
crypto->digest_len);
|
||||
if (rc != 1) {
|
||||
rc = -1;
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = OSSL_PARAM_BLD_push_octet_string(param_bld,
|
||||
rv = OSSL_PARAM_BLD_push_octet_string(param_bld,
|
||||
OSSL_KDF_PARAM_SSHKDF_SESSION_ID,
|
||||
crypto->session_id,
|
||||
crypto->session_id_len);
|
||||
if (rc != 1) {
|
||||
rc = -1;
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_SSHKDF_TYPE,
|
||||
(const char*)&key_type, 1);
|
||||
if (rc != 1) {
|
||||
rc = -1;
|
||||
rv = OSSL_PARAM_BLD_push_utf8_string(param_bld,
|
||||
OSSL_KDF_PARAM_SSHKDF_TYPE,
|
||||
(const char *)&key_type,
|
||||
1);
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
params = OSSL_PARAM_BLD_to_param(param_bld);
|
||||
if (params == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_KDF_derive(ctx, output, requested_len, params);
|
||||
if (rc != 1) {
|
||||
rc = -1;
|
||||
rv = EVP_KDF_derive(ctx, output, requested_len, params);
|
||||
if (rv != 1) {
|
||||
goto out;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
@@ -284,8 +321,8 @@ out:
|
||||
OSSL_PARAM_free(params);
|
||||
#endif
|
||||
EVP_KDF_CTX_free(ctx);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -312,7 +349,7 @@ HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, len);
|
||||
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, (int)len);
|
||||
if (pkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@@ -598,7 +635,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
(unsigned char *)out + aadlen,
|
||||
&tmplen,
|
||||
(unsigned char *)in + aadlen,
|
||||
(int)len - aadlen);
|
||||
(int)(len - aadlen));
|
||||
outlen = tmplen;
|
||||
if (rc != 1 || outlen != (int)len - aadlen) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptUpdate failed");
|
||||
@@ -616,7 +653,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_GET_TAG,
|
||||
authlen,
|
||||
(int)authlen,
|
||||
(unsigned char *)tag);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_GET_TAG failed");
|
||||
@@ -654,7 +691,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
/* set tag for authentication */
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_SET_TAG,
|
||||
authlen,
|
||||
(int)authlen,
|
||||
(unsigned char *)complete_packet + aadlen + encrypted_size);
|
||||
if (rc == 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_TAG failed");
|
||||
@@ -679,7 +716,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
(unsigned char *)out,
|
||||
&outlen,
|
||||
(unsigned char *)complete_packet + aadlen,
|
||||
encrypted_size /* already subtracted aadlen */);
|
||||
(int)encrypted_size /* already subtracted aadlen */);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptUpdate failed");
|
||||
return SSH_ERROR;
|
||||
@@ -794,9 +831,9 @@ chacha20_poly1305_set_key(struct ssh_cipher_struct *cipher,
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CIPHER_CTX_new failed");
|
||||
goto out;
|
||||
}
|
||||
ret = EVP_EncryptInit_ex(ctx->header_evp, EVP_chacha20(), NULL,
|
||||
rv = EVP_EncryptInit_ex(ctx->header_evp, EVP_chacha20(), NULL,
|
||||
u8key + CHACHA20_KEYLEN, NULL);
|
||||
if (ret != 1) {
|
||||
if (rv != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherInit failed");
|
||||
goto out;
|
||||
}
|
||||
@@ -961,7 +998,7 @@ chacha20_poly1305_aead_decrypt_length(struct ssh_cipher_struct *cipher,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rv = EVP_CipherUpdate(ctx->header_evp, out, &outlen, in, len);
|
||||
rv = EVP_CipherUpdate(ctx->header_evp, out, &outlen, in, (int)len);
|
||||
if (rv != 1 || outlen != sizeof(uint32_t)) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
|
||||
return SSH_ERROR;
|
||||
@@ -1048,9 +1085,11 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
/* Decrypt the message */
|
||||
rv = EVP_CipherUpdate(ctx->main_evp, out, &len,
|
||||
rv = EVP_CipherUpdate(ctx->main_evp,
|
||||
out,
|
||||
&len,
|
||||
(uint8_t *)complete_packet + sizeof(uint32_t),
|
||||
encrypted_size);
|
||||
(int)encrypted_size);
|
||||
if (rv != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
|
||||
goto out;
|
||||
@@ -1117,7 +1156,7 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
out_packet->payload,
|
||||
&outlen,
|
||||
in_packet->payload,
|
||||
len - sizeof(uint32_t));
|
||||
(int)(len - sizeof(uint32_t)));
|
||||
if (ret != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
|
||||
return;
|
||||
@@ -1397,6 +1436,14 @@ void ssh_crypto_finalize(void)
|
||||
engine = NULL;
|
||||
}
|
||||
#endif
|
||||
#if defined(WITH_PKCS11_URI)
|
||||
#if defined(WITH_PKCS11_PROVIDER)
|
||||
if (provider != NULL) {
|
||||
OSSL_PROVIDER_unload(provider);
|
||||
provider = NULL;
|
||||
}
|
||||
#endif /* WITH_PKCS11_PROVIDER */
|
||||
#endif /* WITH_PKCS11_URI */
|
||||
|
||||
libcrypto_initialized = 0;
|
||||
}
|
||||
@@ -1541,6 +1588,12 @@ int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote)
|
||||
{
|
||||
return evp_dup_pkey("EC", key, demote, new_key);
|
||||
}
|
||||
|
||||
int evp_dup_ed25519_pkey(const ssh_key key, ssh_key new_key, int demote)
|
||||
{
|
||||
return evp_dup_pkey("ED25519", key, demote, new_key);
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
ssh_string
|
||||
|
||||
@@ -966,7 +966,8 @@ int ssh_crypto_init(void)
|
||||
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
|
||||
if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P, 0)) {
|
||||
gcry_control(GCRYCTL_INIT_SECMEM, 4096);
|
||||
gcry_control(GCRYCTL_USE_SECURE_RNDPOOL);
|
||||
gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0);
|
||||
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ cipher_init(struct ssh_cipher_struct *cipher,
|
||||
void *IV)
|
||||
{
|
||||
const mbedtls_cipher_info_t *cipher_info = NULL;
|
||||
mbedtls_cipher_context_t *ctx;
|
||||
mbedtls_cipher_context_t *ctx = NULL;
|
||||
size_t key_bitlen = 0;
|
||||
size_t iv_size = 0;
|
||||
int rc;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user