mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 21:00:33 +09:00
Compare commits
194 Commits
libssh-0.9
...
stable-0.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dc10ff63c | ||
|
|
72f59157e6 | ||
|
|
d18bd23358 | ||
|
|
5dfe742737 | ||
|
|
aef4a47000 | ||
|
|
9276027c68 | ||
|
|
a45a3c940d | ||
|
|
882d9cb5c8 | ||
|
|
93c1dbd69f | ||
|
|
768d1ed30c | ||
|
|
03bbbc9e4c | ||
|
|
fd49482555 | ||
|
|
87b93be5a2 | ||
|
|
6a8a18c73e | ||
|
|
cdaec0d627 | ||
|
|
a0dbe0d556 | ||
|
|
8cf4f4bfda | ||
|
|
4d7ae19e9c | ||
|
|
234ecdf4d9 | ||
|
|
efb24b6472 | ||
|
|
a5b8bd0d88 | ||
|
|
c3234e5f94 | ||
|
|
11bd6e6ad9 | ||
|
|
8b8584ce5f | ||
|
|
2dffb97007 | ||
|
|
70fef935b2 | ||
|
|
b3d19cc31d | ||
|
|
05de7cb6ac | ||
|
|
b733df6ddc | ||
|
|
18576cf98f | ||
|
|
0c855d2949 | ||
|
|
aaa3d4fc7d | ||
|
|
c4f05c28aa | ||
|
|
abcf9699aa | ||
|
|
6887a5bb20 | ||
|
|
85ddd8b34e | ||
|
|
4637c87f2d | ||
|
|
d1e1aea0b6 | ||
|
|
e9741edcde | ||
|
|
1529bbd7ac | ||
|
|
27e39655c5 | ||
|
|
1b5e183544 | ||
|
|
fef76366db | ||
|
|
cef34a78ef | ||
|
|
cf1c67ddb4 | ||
|
|
e72f58811f | ||
|
|
b923d25fef | ||
|
|
545724b7df | ||
|
|
9844dd5f79 | ||
|
|
cd8ef68b84 | ||
|
|
cee5f9f69c | ||
|
|
acfa6e3cac | ||
|
|
3f92520c74 | ||
|
|
587166577f | ||
|
|
6a7c1f4e5d | ||
|
|
dd899b7591 | ||
|
|
6c85771200 | ||
|
|
2830726c53 | ||
|
|
e8c959084f | ||
|
|
a94ac4c080 | ||
|
|
7f20bbca62 | ||
|
|
761ba97145 | ||
|
|
5d8c346225 | ||
|
|
754048b419 | ||
|
|
7b44e23e6f | ||
|
|
c26414972a | ||
|
|
31a33fd2fd | ||
|
|
3beac46361 | ||
|
|
fea290212a | ||
|
|
81320d35f3 | ||
|
|
cb8245a0e4 | ||
|
|
fd1add66cf | ||
|
|
ea075e3f2e | ||
|
|
6b89f4d206 | ||
|
|
da6d026c12 | ||
|
|
240bda21dc | ||
|
|
f3652f6da0 | ||
|
|
d3060bc84e | ||
|
|
948bcb773e | ||
|
|
64b3e358f9 | ||
|
|
2422081e55 | ||
|
|
a10aeb9490 | ||
|
|
a629f687cd | ||
|
|
2dda3514d1 | ||
|
|
c954ff4b2c | ||
|
|
7609ac60a1 | ||
|
|
2356152329 | ||
|
|
180cfd0799 | ||
|
|
3e51232c69 | ||
|
|
d8fea02d2b | ||
|
|
265b826f78 | ||
|
|
c2c5604077 | ||
|
|
51a0adfc18 | ||
|
|
b78db5f5d8 | ||
|
|
5e2a2be6cd | ||
|
|
7cf3866744 | ||
|
|
81b17de7f7 | ||
|
|
a2a79ec68a | ||
|
|
08f96dcca6 | ||
|
|
435f45291d | ||
|
|
09e9167329 | ||
|
|
effb421a88 | ||
|
|
098ae8c4bd | ||
|
|
04824e2f5e | ||
|
|
0a5b93e479 | ||
|
|
761a4d5fa2 | ||
|
|
bd9a4e2498 | ||
|
|
67b7b383b2 | ||
|
|
1736cb0567 | ||
|
|
36e56dcd93 | ||
|
|
f834e10a47 | ||
|
|
deb9fc015e | ||
|
|
f8314af85a | ||
|
|
1fc8266fcb | ||
|
|
0cceefd49d | ||
|
|
8af24251c1 | ||
|
|
645106a1ca | ||
|
|
6672a457fb | ||
|
|
737ba4a680 | ||
|
|
d4b07d1675 | ||
|
|
d462cc30c9 | ||
|
|
c7f35f4d49 | ||
|
|
6a1dc7df87 | ||
|
|
41e54ce042 | ||
|
|
a7c0ccd35e | ||
|
|
9ec6923479 | ||
|
|
d9e37c4e09 | ||
|
|
56ebe3c7d0 | ||
|
|
e0c7d78a39 | ||
|
|
74e162c67f | ||
|
|
039054ea6e | ||
|
|
1da78553dc | ||
|
|
c5dfc2d5ce | ||
|
|
f760781cb8 | ||
|
|
8316bf1177 | ||
|
|
e631ebb3e2 | ||
|
|
dcc0b9d7aa | ||
|
|
b1bbd20dfa | ||
|
|
929a6b7d50 | ||
|
|
88d676cf1a | ||
|
|
b93c9ae641 | ||
|
|
a77d89d3ea | ||
|
|
4276560680 | ||
|
|
a7ce241652 | ||
|
|
1c7cfaba9c | ||
|
|
98c91e68fa | ||
|
|
078cb4c6f3 | ||
|
|
5972d7a98e | ||
|
|
d35fdfbdb4 | ||
|
|
7ee7ff94ba | ||
|
|
c42aab0122 | ||
|
|
69e97057c7 | ||
|
|
3025eeace3 | ||
|
|
ffb0007768 | ||
|
|
a99b8a3979 | ||
|
|
0a450f0251 | ||
|
|
9e9df61244 | ||
|
|
958afb1c6a | ||
|
|
e510de0315 | ||
|
|
34c596182d | ||
|
|
1a18d9cce2 | ||
|
|
4c83d19c48 | ||
|
|
673bf1ff09 | ||
|
|
fe1fe49617 | ||
|
|
316f46f833 | ||
|
|
0dd71375e7 | ||
|
|
9a10cef920 | ||
|
|
6fcd0940e3 | ||
|
|
0c8dbf5c81 | ||
|
|
a0aa62fffe | ||
|
|
402c922a9e | ||
|
|
112e32ba86 | ||
|
|
e2c5f5c7d1 | ||
|
|
6dcfa25c9b | ||
|
|
eed8d8e957 | ||
|
|
1935e15cd4 | ||
|
|
238dbabef8 | ||
|
|
ee7ee2404a | ||
|
|
6205cad534 | ||
|
|
d5a37e2bf5 | ||
|
|
226d2a16b0 | ||
|
|
46105f4aa6 | ||
|
|
62f7004d5a | ||
|
|
d7358ee5a7 | ||
|
|
ec8cedd803 | ||
|
|
92124ae65a | ||
|
|
ea198fee43 | ||
|
|
393cd36c01 | ||
|
|
93bf0ab6a3 | ||
|
|
251f60c031 | ||
|
|
b33dcda94d | ||
|
|
f0335d1b59 | ||
|
|
ed87c2221c | ||
|
|
ac2f4853bb |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,6 +5,7 @@
|
|||||||
*~$
|
*~$
|
||||||
cscope.*
|
cscope.*
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
/.cache
|
||||||
/.clangd
|
/.clangd
|
||||||
tags
|
tags
|
||||||
/build
|
/build
|
||||||
|
|||||||
135
.gitlab-ci.yml
135
.gitlab-ci.yml
@@ -2,6 +2,8 @@ variables:
|
|||||||
BUILD_IMAGES_PROJECT: libssh/build-images
|
BUILD_IMAGES_PROJECT: libssh/build-images
|
||||||
FEDORA_BUILD: buildenv-fedora
|
FEDORA_BUILD: buildenv-fedora
|
||||||
CENTOS7_BUILD: buildenv-centos7
|
CENTOS7_BUILD: buildenv-centos7
|
||||||
|
CENTOS8_BUILD: buildenv-c8s
|
||||||
|
CENTOS9_BUILD: buildenv-c9s
|
||||||
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
||||||
MINGW_BUILD: buildenv-mingw
|
MINGW_BUILD: buildenv-mingw
|
||||||
|
|
||||||
@@ -25,6 +27,47 @@ centos7/openssl_1.0.x/x86_64:
|
|||||||
paths:
|
paths:
|
||||||
- obj/
|
- obj/
|
||||||
|
|
||||||
|
centos8/openssl_1.1.1/x86_64:
|
||||||
|
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS8_BUILD
|
||||||
|
script:
|
||||||
|
- mkdir -p obj && cd obj && cmake
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||||
|
-DPICKY_DEVELOPER=ON
|
||||||
|
-DWITH_BLOWFISH_CIPHER=ON
|
||||||
|
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||||
|
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||||
|
make -j$(nproc) && ctest --output-on-failure
|
||||||
|
tags:
|
||||||
|
- shared
|
||||||
|
except:
|
||||||
|
- tags
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 week
|
||||||
|
when: on_failure
|
||||||
|
paths:
|
||||||
|
- obj/
|
||||||
|
|
||||||
|
centos9/openssl_3.0.x/x86_64:
|
||||||
|
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||||
|
script:
|
||||||
|
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
|
||||||
|
- mkdir -p obj && cd obj && cmake
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||||
|
-DPICKY_DEVELOPER=ON
|
||||||
|
-DWITH_BLOWFISH_CIPHER=ON
|
||||||
|
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||||
|
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||||
|
make -j$(nproc) && ctest --output-on-failure
|
||||||
|
tags:
|
||||||
|
- shared
|
||||||
|
except:
|
||||||
|
- tags
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 week
|
||||||
|
when: on_failure
|
||||||
|
paths:
|
||||||
|
- obj/
|
||||||
|
|
||||||
fedora/openssl_1.1.x/x86_64:
|
fedora/openssl_1.1.x/x86_64:
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||||
script:
|
script:
|
||||||
@@ -47,8 +90,8 @@ fedora/openssl_1.1.x/x86_64:
|
|||||||
paths:
|
paths:
|
||||||
- obj/
|
- obj/
|
||||||
|
|
||||||
fedora/openssl_1.1.x/x86_64/fips:
|
centos8/openssl_1.1.1/x86_64/fips:
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS8_BUILD
|
||||||
script:
|
script:
|
||||||
- echo 1 > /etc/system-fips
|
- echo 1 > /etc/system-fips
|
||||||
- update-crypto-policies --set FIPS
|
- update-crypto-policies --set FIPS
|
||||||
@@ -197,11 +240,13 @@ freebsd/x86_64:
|
|||||||
make && ctest --output-on-failure
|
make && ctest --output-on-failure
|
||||||
tags:
|
tags:
|
||||||
- freebsd
|
- freebsd
|
||||||
|
- private
|
||||||
except:
|
except:
|
||||||
- tags
|
- tags
|
||||||
only:
|
only:
|
||||||
- branches@libssh/libssh-mirror
|
- branches@libssh/libssh-mirror
|
||||||
- branches@cryptomilk/libssh-mirror
|
- branches@cryptomilk/libssh-mirror
|
||||||
|
- branches@jjelen/libssh-mirror
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
when: on_failure
|
when: on_failure
|
||||||
@@ -455,57 +500,55 @@ tumbleweed/static-analysis:
|
|||||||
paths:
|
paths:
|
||||||
- obj/scan
|
- obj/scan
|
||||||
|
|
||||||
visualstudio/x86_64:
|
###############################################################################
|
||||||
|
# Visual Studio builds #
|
||||||
|
###############################################################################
|
||||||
|
.vs:
|
||||||
|
stage: test
|
||||||
|
cache:
|
||||||
|
key: vcpkg.${CI_JOB_NAME}
|
||||||
|
paths:
|
||||||
|
- .vcpkg
|
||||||
|
variables:
|
||||||
|
ErrorActionPreference: STOP
|
||||||
script:
|
script:
|
||||||
- $env:VCPKG_DEFAULT_TRIPLET="x64-windows"
|
- cmake --build .
|
||||||
- cd obj
|
- ctest --output-on-failure
|
||||||
- cmake
|
|
||||||
-A x64
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON ..
|
|
||||||
- cmake --build .
|
|
||||||
- ctest --output-on-failure
|
|
||||||
tags:
|
tags:
|
||||||
- vs2017
|
- windows
|
||||||
- windows
|
- shared-windows
|
||||||
except:
|
except:
|
||||||
- tags
|
- tags
|
||||||
only:
|
|
||||||
- branches@libssh/libssh-mirror
|
|
||||||
- branches@ansasaki/libssh-mirror
|
|
||||||
- branches@cryptomilk/libssh-mirror
|
|
||||||
- branches@jjelen/libssh-mirror
|
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
when: on_failure
|
when: on_failure
|
||||||
paths:
|
paths:
|
||||||
- obj/
|
- obj/
|
||||||
|
before_script:
|
||||||
|
- If (!(test-path .vcpkg\archives)) { mkdir -p .vcpkg\archives }
|
||||||
|
- $env:VCPKG_DEFAULT_BINARY_CACHE="$PWD\.vcpkg\archives"
|
||||||
|
- echo $env:VCPKG_DEFAULT_BINARY_CACHE
|
||||||
|
- $env:VCPKG_DEFAULT_TRIPLET="$TRIPLET-windows"
|
||||||
|
- vcpkg install cmocka
|
||||||
|
- vcpkg install openssl
|
||||||
|
- vcpkg install zlib
|
||||||
|
- vcpkg integrate install
|
||||||
|
- mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1}
|
||||||
|
- cmake
|
||||||
|
-A $PLATFORM
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||||
|
-DPICKY_DEVELOPER=ON
|
||||||
|
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||||
|
-DUNIT_TESTING=ON ..
|
||||||
|
|
||||||
|
visualstudio/x86_64:
|
||||||
|
extends: .vs
|
||||||
|
variables:
|
||||||
|
PLATFORM: "x64"
|
||||||
|
TRIPLET: "x64"
|
||||||
|
|
||||||
visualstudio/x86:
|
visualstudio/x86:
|
||||||
script:
|
extends: .vs
|
||||||
- $env:VCPKG_DEFAULT_TRIPLET="x86-windows"
|
variables:
|
||||||
- cd obj
|
PLATFORM: "win32"
|
||||||
- cmake
|
TRIPLET: "x86"
|
||||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON ..
|
|
||||||
- cmake --build .
|
|
||||||
- ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- vs2017
|
|
||||||
- windows
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
only:
|
|
||||||
- branches@libssh/libssh-mirror
|
|
||||||
- branches@ansasaki/libssh-mirror
|
|
||||||
- branches@cryptomilk/libssh-mirror
|
|
||||||
- branches@jjelen/libssh-mirror
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
|||||||
include(DefineCMakeDefaults)
|
include(DefineCMakeDefaults)
|
||||||
include(DefineCompilerFlags)
|
include(DefineCompilerFlags)
|
||||||
|
|
||||||
project(libssh VERSION 0.9.3 LANGUAGES C)
|
project(libssh VERSION 0.9.8 LANGUAGES C)
|
||||||
|
|
||||||
# global needed variable
|
# global needed variable
|
||||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||||
@@ -22,7 +22,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
|||||||
# Increment AGE. Set REVISION to 0
|
# Increment AGE. Set REVISION to 0
|
||||||
# If the source code was changed, but there were no interface changes:
|
# If the source code was changed, but there were no interface changes:
|
||||||
# Increment REVISION.
|
# Increment REVISION.
|
||||||
set(LIBRARY_VERSION "4.8.4")
|
set(LIBRARY_VERSION "4.8.9")
|
||||||
set(LIBRARY_SOVERSION "4")
|
set(LIBRARY_SOVERSION "4")
|
||||||
|
|
||||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||||
@@ -59,7 +59,13 @@ elseif(WITH_MBEDTLS)
|
|||||||
endif (NOT MBEDTLS_FOUND)
|
endif (NOT MBEDTLS_FOUND)
|
||||||
else (WITH_GCRYPT)
|
else (WITH_GCRYPT)
|
||||||
find_package(OpenSSL)
|
find_package(OpenSSL)
|
||||||
if (NOT OPENSSL_FOUND)
|
if (OPENSSL_FOUND)
|
||||||
|
# On CMake < 3.16, OPENSSL_CRYPTO_LIBRARIES is usually a synonym for OPENSSL_CRYPTO_LIBRARY, but is not defined
|
||||||
|
# when building on Windows outside of Cygwin. We provide the synonym here, if FindOpenSSL didn't define it already.
|
||||||
|
if (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
|
||||||
|
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||||
|
endif (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
|
||||||
|
else (OPENSSL_FOUND)
|
||||||
find_package(GCrypt)
|
find_package(GCrypt)
|
||||||
if (NOT GCRYPT_FOUND)
|
if (NOT GCRYPT_FOUND)
|
||||||
find_package(MbedTLS)
|
find_package(MbedTLS)
|
||||||
@@ -67,7 +73,7 @@ else (WITH_GCRYPT)
|
|||||||
message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
|
message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
|
||||||
endif (NOT MBEDTLS_FOUND)
|
endif (NOT MBEDTLS_FOUND)
|
||||||
endif (NOT GCRYPT_FOUND)
|
endif (NOT GCRYPT_FOUND)
|
||||||
endif (NOT OPENSSL_FOUND)
|
endif (OPENSSL_FOUND)
|
||||||
endif(WITH_GCRYPT)
|
endif(WITH_GCRYPT)
|
||||||
|
|
||||||
if (UNIT_TESTING)
|
if (UNIT_TESTING)
|
||||||
@@ -203,10 +209,10 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
|||||||
endif(UPDATE_ABI)
|
endif(UPDATE_ABI)
|
||||||
endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||||
|
|
||||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET})
|
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET} VERBATIM)
|
||||||
|
|
||||||
# Link compile database for clangd
|
# Link compile database for clangd
|
||||||
execute_process(COMMAND cmake -E create_symlink
|
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||||
"${CMAKE_BINARY_DIR}/compile_commands.json"
|
"${CMAKE_BINARY_DIR}/compile_commands.json"
|
||||||
"${CMAKE_SOURCE_DIR}/compile_commands.json")
|
"${CMAKE_SOURCE_DIR}/compile_commands.json")
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
|||||||
|
|
||||||
# SOURCE GENERATOR
|
# SOURCE GENERATOR
|
||||||
set(CPACK_SOURCE_GENERATOR "TXZ")
|
set(CPACK_SOURCE_GENERATOR "TXZ")
|
||||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;/[.]clangd/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
|
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
|
||||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
|
||||||
### NSIS INSTALLER
|
### NSIS INSTALLER
|
||||||
|
|||||||
45
ChangeLog
45
ChangeLog
@@ -1,5 +1,50 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
==========
|
==========
|
||||||
|
version 0.9.8 (released 2023-12-18)
|
||||||
|
* Fix CVE-2023-6004: Command injection using proxycommand
|
||||||
|
* Fix CVE-2023-48795: Potential downgrade attack using strict kex
|
||||||
|
* Fix CVE-2023-6918: Missing checks for return values of MD functions
|
||||||
|
* Allow @ in usernames when parsing from URI composes
|
||||||
|
|
||||||
|
version 0.9.7 (released 2023-05-04)
|
||||||
|
* Fix CVE-2023-1667: a NULL dereference during rekeying with algorithm guessing
|
||||||
|
* Fix CVE-2023-2283: a possible authorization bypass in
|
||||||
|
pki_verify_data_signature under low-memory conditions.
|
||||||
|
* Fix several memory leaks in GSSAPI handling code
|
||||||
|
* Build and test related backports
|
||||||
|
|
||||||
|
version 0.9.6 (released 2021-08-26)
|
||||||
|
* CVE-2021-3634: Fix possible heap-buffer overflow when rekeying with
|
||||||
|
different key exchange mechanism
|
||||||
|
* Fix several memory leaks on error paths
|
||||||
|
* Reset pending_call_state on disconnect
|
||||||
|
* Fix handshake bug with AEAD ciphers and no HMAC overlap
|
||||||
|
* Use OPENSSL_CRYPTO_LIBRARIES in CMake
|
||||||
|
* Ignore request success and failure message if they are not expected
|
||||||
|
* Support more identity files in configuration
|
||||||
|
* Avoid setting compiler flags directly in CMake
|
||||||
|
* Support build directories with special characters
|
||||||
|
* Include stdlib.h to avoid crash in Windows
|
||||||
|
* Fix sftp_new_channel constructs an invalid object
|
||||||
|
* Fix Ninja multiple rules error
|
||||||
|
* Several tests fixes
|
||||||
|
|
||||||
|
version 0.9.5 (released 2020-09-10)
|
||||||
|
* CVE-2020-16135: Avoid null pointer dereference in sftpserver (T232)
|
||||||
|
* Improve handling of library initialization (T222)
|
||||||
|
* Fix parsing of subsecond times in SFTP (T219)
|
||||||
|
* Make the documentation reproducible
|
||||||
|
* Remove deprecated API usage in OpenSSL
|
||||||
|
* Fix regression of ssh_channel_poll_timeout() returning SSH_AGAIN
|
||||||
|
* Define version in one place (T226)
|
||||||
|
* Prevent invalid free when using different C runtimes than OpenSSL (T229)
|
||||||
|
* Compatibility improvements to testsuite
|
||||||
|
|
||||||
|
version 0.9.4 (released 2020-04-09)
|
||||||
|
* Fixed CVE-2020-1730 - Possible DoS in client and server when handling
|
||||||
|
AES-CTR keys with OpenSSL
|
||||||
|
* Added diffie-hellman-group14-sha256
|
||||||
|
* Fixed serveral possible memory leaks
|
||||||
|
|
||||||
version 0.9.3 (released 2019-12-10)
|
version 0.9.3 (released 2019-12-10)
|
||||||
* Fixed CVE-2019-14889 - SCP: Unsanitized location leads to command execution
|
* Fixed CVE-2019-14889 - SCP: Unsanitized location leads to command execution
|
||||||
|
|||||||
@@ -101,53 +101,53 @@ if (OPENSSL_FOUND)
|
|||||||
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(EVP_aes_128_ctr HAVE_OPENSSL_EVP_AES_CTR)
|
check_function_exists(EVP_aes_128_ctr HAVE_OPENSSL_EVP_AES_CTR)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(EVP_aes_128_cbc HAVE_OPENSSL_EVP_AES_CBC)
|
check_function_exists(EVP_aes_128_cbc HAVE_OPENSSL_EVP_AES_CBC)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(EVP_aes_128_gcm HAVE_OPENSSL_EVP_AES_GCM)
|
check_function_exists(EVP_aes_128_gcm HAVE_OPENSSL_EVP_AES_GCM)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(CRYPTO_THREADID_set_callback HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK)
|
check_function_exists(CRYPTO_THREADID_set_callback HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(CRYPTO_ctr128_encrypt HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT)
|
check_function_exists(CRYPTO_ctr128_encrypt HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(EVP_CIPHER_CTX_new HAVE_OPENSSL_EVP_CIPHER_CTX_NEW)
|
check_function_exists(EVP_CIPHER_CTX_new HAVE_OPENSSL_EVP_CIPHER_CTX_NEW)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID)
|
check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE)
|
check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
|
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN)
|
check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_function_exists(EVP_DigestVerify HAVE_OPENSSL_EVP_DIGESTVERIFY)
|
check_function_exists(EVP_DigestVerify HAVE_OPENSSL_EVP_DIGESTVERIFY)
|
||||||
|
|
||||||
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
|
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519)
|
check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519)
|
||||||
|
|
||||||
if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND
|
if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND
|
||||||
@@ -156,7 +156,7 @@ if (OPENSSL_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||||
check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519)
|
check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519)
|
||||||
|
|
||||||
unset(CMAKE_REQUIRED_INCLUDES)
|
unset(CMAKE_REQUIRED_INCLUDES)
|
||||||
|
|||||||
@@ -302,12 +302,13 @@ function(get_file_list _TARGET_NAME)
|
|||||||
add_custom_target(
|
add_custom_target(
|
||||||
${_TARGET_NAME}_int ALL
|
${_TARGET_NAME}_int ALL
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-DOUTPUT_PATH="${_get_files_list_OUTPUT_PATH}"
|
-DOUTPUT_PATH=${_get_files_list_OUTPUT_PATH}
|
||||||
-DDIRECTORIES="${_get_files_list_DIRECTORIES}"
|
-DDIRECTORIES=${_get_files_list_DIRECTORIES}
|
||||||
-DFILES_PATTERNS="${_get_files_list_FILES_PATTERNS}"
|
-DFILES_PATTERNS=${_get_files_list_FILES_PATTERNS}
|
||||||
-P ${_GET_FILES_LIST_SCRIPT}
|
-P ${_GET_FILES_LIST_SCRIPT}
|
||||||
COMMENT
|
COMMENT
|
||||||
"Searching for files"
|
"Searching for files"
|
||||||
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
if (DEFINED _get_files_list_COPY_TO)
|
if (DEFINED _get_files_list_COPY_TO)
|
||||||
@@ -318,6 +319,7 @@ function(get_file_list _TARGET_NAME)
|
|||||||
${_FILES_LIST_OUTPUT_PATH} ${_get_files_list_COPY_TO}
|
${_FILES_LIST_OUTPUT_PATH} ${_get_files_list_COPY_TO}
|
||||||
DEPENDS ${_TARGET_NAME}_int
|
DEPENDS ${_TARGET_NAME}_int
|
||||||
COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}"
|
COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}"
|
||||||
|
VERBATIM
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
add_custom_target(${_TARGET_NAME} ALL
|
add_custom_target(${_TARGET_NAME} ALL
|
||||||
@@ -369,12 +371,13 @@ function(extract_symbols _TARGET_NAME)
|
|||||||
add_custom_target(
|
add_custom_target(
|
||||||
${_TARGET_NAME}_int ALL
|
${_TARGET_NAME}_int ALL
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-DOUTPUT_PATH="${_SYMBOLS_OUTPUT_PATH}"
|
-DOUTPUT_PATH=${_SYMBOLS_OUTPUT_PATH}
|
||||||
-DHEADERS_LIST_FILE="${_HEADERS_LIST_FILE}"
|
-DHEADERS_LIST_FILE=${_HEADERS_LIST_FILE}
|
||||||
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
|
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
|
||||||
-P ${_EXTRACT_SYMBOLS_SCRIPT}
|
-P ${_EXTRACT_SYMBOLS_SCRIPT}
|
||||||
DEPENDS ${_extract_symbols_HEADERS_LIST}
|
DEPENDS ${_extract_symbols_HEADERS_LIST}
|
||||||
COMMENT "Extracting symbols from headers"
|
COMMENT "Extracting symbols from headers"
|
||||||
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
if (DEFINED _extract_symbols_COPY_TO)
|
if (DEFINED _extract_symbols_COPY_TO)
|
||||||
@@ -385,6 +388,7 @@ function(extract_symbols _TARGET_NAME)
|
|||||||
${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO}
|
${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO}
|
||||||
DEPENDS ${_TARGET_NAME}_int
|
DEPENDS ${_TARGET_NAME}_int
|
||||||
COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}"
|
COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}"
|
||||||
|
VERBATIM
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
add_custom_target(${_TARGET_NAME} ALL
|
add_custom_target(${_TARGET_NAME} ALL
|
||||||
@@ -449,35 +453,37 @@ function(generate_map_file _TARGET_NAME)
|
|||||||
${_TARGET_NAME}_int ALL
|
${_TARGET_NAME}_int ALL
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE}
|
-DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE}
|
||||||
-DSYMBOLS="${_SYMBOLS_FILE}"
|
-DSYMBOLS=${_SYMBOLS_FILE}
|
||||||
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
|
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
|
||||||
-DOUTPUT_PATH="${_MAP_OUTPUT_PATH}"
|
-DOUTPUT_PATH=${_MAP_OUTPUT_PATH}
|
||||||
-DFINAL=${_generate_map_file_FINAL}
|
-DFINAL=${_generate_map_file_FINAL}
|
||||||
-DBREAK_ABI=${_generate_map_file_BREAK_ABI}
|
-DBREAK_ABI=${_generate_map_file_BREAK_ABI}
|
||||||
-DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION}
|
-DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION}
|
||||||
-P ${_GENERATE_MAP_SCRIPT}
|
-P ${_GENERATE_MAP_SCRIPT}
|
||||||
DEPENDS ${_generate_map_file_SYMBOLS}
|
DEPENDS ${_generate_map_file_SYMBOLS}
|
||||||
COMMENT "Generating the map ${_TARGET_NAME}"
|
COMMENT "Generating the map ${_TARGET_NAME}"
|
||||||
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add a custom command setting the map as OUTPUT to allow it to be added as
|
# Add a custom command setting the map as OUTPUT to allow it to be added as
|
||||||
# a generated source
|
# a generated source
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${_MAP_OUTPUT_PATH}
|
OUTPUT ${_MAP_OUTPUT_PATH}
|
||||||
DEPENDS ${_TARGET_NAME}
|
DEPENDS ${_TARGET_NAME}_copy
|
||||||
)
|
)
|
||||||
|
|
||||||
if (DEFINED _generate_map_file_COPY_TO)
|
if (DEFINED _generate_map_file_COPY_TO)
|
||||||
# Copy the generated map back to the COPY_TO
|
# Copy the generated map back to the COPY_TO
|
||||||
add_custom_target(${_TARGET_NAME} ALL
|
add_custom_target(${_TARGET_NAME}_copy ALL
|
||||||
COMMAND
|
COMMAND
|
||||||
${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH}
|
${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH}
|
||||||
${_generate_map_file_COPY_TO}
|
${_generate_map_file_COPY_TO}
|
||||||
DEPENDS ${_TARGET_NAME}_int
|
DEPENDS ${_TARGET_NAME}_int
|
||||||
COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}"
|
COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}"
|
||||||
|
VERBATIM
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
add_custom_target(${_TARGET_NAME} ALL
|
add_custom_target(${_TARGET_NAME}_copy ALL
|
||||||
DEPENDS ${_TARGET_NAME}_int
|
DEPENDS ${_TARGET_NAME}_int
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -13,8 +13,11 @@ if (DOXYGEN_FOUND)
|
|||||||
set(DOXYGEN_TAB_SIZE 4)
|
set(DOXYGEN_TAB_SIZE 4)
|
||||||
set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
|
set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
|
||||||
set(DOXYGEN_MARKDOWN_SUPPORT YES)
|
set(DOXYGEN_MARKDOWN_SUPPORT YES)
|
||||||
|
set(DOXYGEN_FULL_PATH_NAMES NO)
|
||||||
|
|
||||||
set(DOXYGEN_PREDEFINED DOXYGEN
|
set(DOXYGEN_PREDEFINED DOXYGEN
|
||||||
|
WITH_SERVER
|
||||||
|
WITH_SFTP
|
||||||
PRINTF_ATTRIBUTE(x,y))
|
PRINTF_ATTRIBUTE(x,y))
|
||||||
|
|
||||||
set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style)
|
set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style)
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ the dllimport attribute.
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If you're are statically linking with OpenSSL, read the "Linking your
|
If you're are statically linking with OpenSSL, read the "Linking your
|
||||||
application" section in the NOTES.<OS> in the OpenSSL source tree!
|
application" section in the NOTES.[OS] in the OpenSSL source tree!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ set(examples_SRCS
|
|||||||
connect_ssh.c
|
connect_ssh.c
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(${libssh_BINARY_DIR})
|
include_directories(${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR})
|
||||||
|
|
||||||
if (ARGP_INCLUDE_DIR)
|
if (ARGP_INCLUDE_DIR)
|
||||||
include_directories(${ARGP_INCLUDE_DIR})
|
include_directories(${ARGP_INCLUDE_DIR})
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ int main(void) {
|
|||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
int nbytes;
|
int rbytes, wbytes, total = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
session = connect_ssh("localhost", NULL, 0);
|
session = connect_ssh("localhost", NULL, 0);
|
||||||
@@ -35,15 +35,30 @@ int main(void) {
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
while (nbytes > 0) {
|
if (rbytes <= 0) {
|
||||||
if (fwrite(buffer, 1, nbytes, stdout) != (unsigned int) nbytes) {
|
goto failed;
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes < 0) {
|
do {
|
||||||
|
wbytes = fwrite(buffer + total, 1, rbytes, stdout);
|
||||||
|
if (wbytes <= 0) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
total += wbytes;
|
||||||
|
|
||||||
|
/* When it was not possible to write the whole buffer to stdout */
|
||||||
|
if (wbytes < rbytes) {
|
||||||
|
rbytes -= wbytes;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
|
total = 0;
|
||||||
|
} while (rbytes > 0);
|
||||||
|
|
||||||
|
if (rbytes < 0) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ static int open_location(struct location *loc, int flag) {
|
|||||||
loc->file = fopen(loc->path, flag == READ ? "r":"w");
|
loc->file = fopen(loc->path, flag == READ ? "r":"w");
|
||||||
if (!loc->file) {
|
if (!loc->file) {
|
||||||
if (errno == EISDIR) {
|
if (errno == EISDIR) {
|
||||||
if (chdir(loc->path)) {
|
if (loc->path != NULL && chdir(loc->path)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error changing directory to %s: %s\n",
|
"Error changing directory to %s: %s\n",
|
||||||
loc->path, strerror(errno));
|
loc->path, strerror(errno));
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ clients must be made or how a client should react.
|
|||||||
#ifdef HAVE_ARGP_H
|
#ifdef HAVE_ARGP_H
|
||||||
#include <argp.h>
|
#include <argp.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -79,11 +81,18 @@ static struct cleanup_node_struct *cleanup_stack = NULL;
|
|||||||
|
|
||||||
static void _close_socket(struct event_fd_data_struct event_fd_data);
|
static void _close_socket(struct event_fd_data_struct event_fd_data);
|
||||||
|
|
||||||
static void cleanup_push(struct cleanup_node_struct** head_ref, struct event_fd_data_struct *new_data) {
|
static void
|
||||||
|
cleanup_push(struct cleanup_node_struct** head_ref,
|
||||||
|
struct event_fd_data_struct *new_data)
|
||||||
|
{
|
||||||
// Allocate memory for node
|
// Allocate memory for node
|
||||||
struct cleanup_node_struct *new_node = malloc(sizeof *new_node);
|
struct cleanup_node_struct *new_node = malloc(sizeof *new_node);
|
||||||
|
|
||||||
new_node->next = (*head_ref);
|
if (head_ref != NULL) {
|
||||||
|
new_node->next = *head_ref;
|
||||||
|
} else {
|
||||||
|
new_node->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy new_data
|
// Copy new_data
|
||||||
new_node->data = new_data;
|
new_node->data = new_data;
|
||||||
@@ -92,7 +101,9 @@ static void cleanup_push(struct cleanup_node_struct** head_ref, struct event_fd_
|
|||||||
(*head_ref) = new_node;
|
(*head_ref) = new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_cleanup(struct cleanup_node_struct **head_ref) {
|
static void
|
||||||
|
do_cleanup(struct cleanup_node_struct **head_ref)
|
||||||
|
{
|
||||||
struct cleanup_node_struct *current = (*head_ref);
|
struct cleanup_node_struct *current = (*head_ref);
|
||||||
struct cleanup_node_struct *previous = NULL, *gone = NULL;
|
struct cleanup_node_struct *previous = NULL, *gone = NULL;
|
||||||
|
|
||||||
@@ -131,16 +142,22 @@ static void do_cleanup(struct cleanup_node_struct **head_ref) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int auth_password(ssh_session session, const char *user,
|
static int
|
||||||
const char *password, void *userdata) {
|
auth_password(ssh_session session,
|
||||||
(void)userdata;
|
const char *user,
|
||||||
_ssh_log(SSH_LOG_PROTOCOL, "=== auth_password", "Authenticating user %s pwd %s",user, password);
|
const char *password,
|
||||||
if (strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
|
UNUSED_PARAM(void *userdata))
|
||||||
|
{
|
||||||
|
_ssh_log(SSH_LOG_PROTOCOL,
|
||||||
|
"=== auth_password", "Authenticating user %s pwd %s",
|
||||||
|
user,
|
||||||
|
password);
|
||||||
|
if (strcmp(user, USER) == 0 && strcmp(password, PASSWORD) == 0) {
|
||||||
authenticated = true;
|
authenticated = true;
|
||||||
printf("Authenticated\n");
|
printf("Authenticated\n");
|
||||||
return SSH_AUTH_SUCCESS;
|
return SSH_AUTH_SUCCESS;
|
||||||
}
|
}
|
||||||
if (tries >= 3){
|
if (tries >= 3) {
|
||||||
printf("Too many authentication tries\n");
|
printf("Too many authentication tries\n");
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
error_set = true;
|
error_set = true;
|
||||||
@@ -150,25 +167,34 @@ static int auth_password(ssh_session session, const char *user,
|
|||||||
return SSH_AUTH_DENIED;
|
return SSH_AUTH_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata) {
|
static int
|
||||||
|
auth_gssapi_mic(ssh_session session,
|
||||||
|
const char *user,
|
||||||
|
const char *principal,
|
||||||
|
UNUSED_PARAM(void *userdata))
|
||||||
|
{
|
||||||
ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
|
ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
|
||||||
(void)userdata;
|
printf("Authenticating user %s with gssapi principal %s\n",
|
||||||
printf("Authenticating user %s with gssapi principal %s\n", user, principal);
|
user, principal);
|
||||||
if (creds != NULL)
|
if (creds != NULL) {
|
||||||
printf("Received some gssapi credentials\n");
|
printf("Received some gssapi credentials\n");
|
||||||
else
|
} else {
|
||||||
printf("Not received any forwardable creds\n");
|
printf("Not received any forwardable creds\n");
|
||||||
|
}
|
||||||
printf("authenticated\n");
|
printf("authenticated\n");
|
||||||
authenticated = true;
|
authenticated = true;
|
||||||
return SSH_AUTH_SUCCESS;
|
return SSH_AUTH_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata) {
|
static int
|
||||||
(void)session;
|
subsystem_request(UNUSED_PARAM(ssh_session session),
|
||||||
(void)channel;
|
UNUSED_PARAM(ssh_channel channel),
|
||||||
//(void)subsystem;
|
const char *subsystem,
|
||||||
(void)userdata;
|
UNUSED_PARAM(void *userdata))
|
||||||
_ssh_log(SSH_LOG_PROTOCOL, "=== subsystem_request", "Channel subsystem reqeuest: %s", subsystem);
|
{
|
||||||
|
_ssh_log(SSH_LOG_PROTOCOL,
|
||||||
|
"=== subsystem_request", "Channel subsystem reqeuest: %s",
|
||||||
|
subsystem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,9 +202,10 @@ struct ssh_channel_callbacks_struct channel_cb = {
|
|||||||
.channel_subsystem_request_function = subsystem_request
|
.channel_subsystem_request_function = subsystem_request
|
||||||
};
|
};
|
||||||
|
|
||||||
static ssh_channel new_session_channel(ssh_session session, void *userdata) {
|
static ssh_channel
|
||||||
(void)session;
|
new_session_channel(UNUSED_PARAM(ssh_session session),
|
||||||
(void)userdata;
|
UNUSED_PARAM(void *userdata))
|
||||||
|
{
|
||||||
_ssh_log(SSH_LOG_PROTOCOL, "=== subsystem_request", "Session channel request");
|
_ssh_log(SSH_LOG_PROTOCOL, "=== subsystem_request", "Session channel request");
|
||||||
/* For TCP forward only there seems to be no need for a session channel */
|
/* For TCP forward only there seems to be no need for a session channel */
|
||||||
/*if(chan != NULL)
|
/*if(chan != NULL)
|
||||||
@@ -191,18 +218,25 @@ static ssh_channel new_session_channel(ssh_session session, void *userdata) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stack_socket_close(UNUSED_PARAM(ssh_session session),
|
static void
|
||||||
struct event_fd_data_struct *event_fd_data)
|
stack_socket_close(UNUSED_PARAM(ssh_session session),
|
||||||
|
struct event_fd_data_struct *event_fd_data)
|
||||||
{
|
{
|
||||||
if (event_fd_data->stacked != 1) {
|
if (event_fd_data->stacked != 1) {
|
||||||
_ssh_log(SSH_LOG_FUNCTIONS, "=== stack_socket_close", "Closing fd = %d sockets_cnt = %d", *event_fd_data->p_fd, sockets_cnt);
|
_ssh_log(SSH_LOG_FUNCTIONS, "=== stack_socket_close",
|
||||||
|
"Closing fd = %d sockets_cnt = %d", *event_fd_data->p_fd,
|
||||||
|
sockets_cnt);
|
||||||
event_fd_data->stacked = 1;
|
event_fd_data->stacked = 1;
|
||||||
cleanup_push(&cleanup_stack, event_fd_data);
|
cleanup_push(&cleanup_stack, event_fd_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _close_socket(struct event_fd_data_struct event_fd_data) {
|
static void
|
||||||
_ssh_log(SSH_LOG_FUNCTIONS, "=== close_socket", "Closing fd = %d sockets_cnt = %d", *event_fd_data.p_fd, sockets_cnt);
|
_close_socket(struct event_fd_data_struct event_fd_data)
|
||||||
|
{
|
||||||
|
_ssh_log(SSH_LOG_FUNCTIONS, "=== close_socket",
|
||||||
|
"Closing fd = %d sockets_cnt = %d", *event_fd_data.p_fd,
|
||||||
|
sockets_cnt);
|
||||||
ssh_event_remove_fd(mainloop, *event_fd_data.p_fd);
|
ssh_event_remove_fd(mainloop, *event_fd_data.p_fd);
|
||||||
sockets_cnt--;
|
sockets_cnt--;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -213,23 +247,31 @@ static void _close_socket(struct event_fd_data_struct event_fd_data) {
|
|||||||
(*event_fd_data.p_fd) = SSH_INVALID_SOCKET;
|
(*event_fd_data.p_fd) = SSH_INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int service_request(ssh_session session, const char *service, void *userdata) {
|
static int
|
||||||
(void)session;
|
service_request(UNUSED_PARAM(ssh_session session),
|
||||||
//(void)service;
|
const char *service,
|
||||||
(void)userdata;
|
UNUSED_PARAM(void *userdata))
|
||||||
|
{
|
||||||
_ssh_log(SSH_LOG_PROTOCOL, "=== service_request", "Service request: %s", service);
|
_ssh_log(SSH_LOG_PROTOCOL, "=== service_request", "Service request: %s", service);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void global_request(ssh_session session, ssh_message message, void *userdata) {
|
static void
|
||||||
(void)session;
|
global_request(UNUSED_PARAM(ssh_session session),
|
||||||
(void)userdata;
|
ssh_message message,
|
||||||
_ssh_log(SSH_LOG_PROTOCOL, "=== global_request", "Global request, message type: %d", ssh_message_type(message));
|
UNUSED_PARAM(void *userdata))
|
||||||
|
{
|
||||||
|
_ssh_log(SSH_LOG_PROTOCOL,
|
||||||
|
"=== global_request", "Global request, message type: %d",
|
||||||
|
ssh_message_type(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void my_channel_close_function(ssh_session session, ssh_channel channel, void *userdata) {
|
static void
|
||||||
|
my_channel_close_function(ssh_session session,
|
||||||
|
UNUSED_PARAM(ssh_channel channel),
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||||
(void)session;
|
|
||||||
|
|
||||||
_ssh_log(SSH_LOG_PROTOCOL,
|
_ssh_log(SSH_LOG_PROTOCOL,
|
||||||
"=== my_channel_close_function",
|
"=== my_channel_close_function",
|
||||||
@@ -238,9 +280,12 @@ static void my_channel_close_function(ssh_session session, ssh_channel channel,
|
|||||||
stack_socket_close(session, event_fd_data);
|
stack_socket_close(session, event_fd_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void my_channel_eof_function(ssh_session session, ssh_channel channel, void *userdata) {
|
static void
|
||||||
|
my_channel_eof_function(ssh_session session,
|
||||||
|
UNUSED_PARAM(ssh_channel channel),
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||||
(void)session;
|
|
||||||
|
|
||||||
_ssh_log(SSH_LOG_PROTOCOL,
|
_ssh_log(SSH_LOG_PROTOCOL,
|
||||||
"=== my_channel_eof_function",
|
"=== my_channel_eof_function",
|
||||||
@@ -250,9 +295,13 @@ static void my_channel_eof_function(ssh_session session, ssh_channel channel, vo
|
|||||||
stack_socket_close(session, event_fd_data);
|
stack_socket_close(session, event_fd_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void my_channel_exit_status_function(ssh_session session, ssh_channel channel, int exit_status, void *userdata) {
|
static void
|
||||||
|
my_channel_exit_status_function(UNUSED_PARAM(ssh_session session),
|
||||||
|
UNUSED_PARAM(ssh_channel channel),
|
||||||
|
int exit_status,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||||
(void)session;
|
|
||||||
|
|
||||||
_ssh_log(SSH_LOG_PROTOCOL,
|
_ssh_log(SSH_LOG_PROTOCOL,
|
||||||
"=== my_channel_exit_status_function",
|
"=== my_channel_exit_status_function",
|
||||||
@@ -260,12 +309,13 @@ static void my_channel_exit_status_function(ssh_session session, ssh_channel cha
|
|||||||
exit_status, *event_fd_data->p_fd);
|
exit_status, *event_fd_data->p_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int my_channel_data_function(ssh_session session,
|
static int
|
||||||
ssh_channel channel,
|
my_channel_data_function(ssh_session session,
|
||||||
void *data,
|
UNUSED_PARAM(ssh_channel channel),
|
||||||
uint32_t len,
|
void *data,
|
||||||
UNUSED_PARAM(int is_stderr),
|
uint32_t len,
|
||||||
void *userdata)
|
UNUSED_PARAM(int is_stderr),
|
||||||
|
void *userdata)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||||
@@ -283,7 +333,9 @@ static int my_channel_data_function(ssh_session session,
|
|||||||
i = send(*event_fd_data->p_fd, data, len, 0);
|
i = send(*event_fd_data->p_fd, data, len, 0);
|
||||||
}
|
}
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
_ssh_log(SSH_LOG_WARNING, "=== my_channel_data_function", "Writing to tcp socket %d: %s", *event_fd_data->p_fd, strerror(errno));
|
_ssh_log(SSH_LOG_WARNING, "=== my_channel_data_function",
|
||||||
|
"Writing to tcp socket %d: %s", *event_fd_data->p_fd,
|
||||||
|
strerror(errno));
|
||||||
stack_socket_close(session, event_fd_data);
|
stack_socket_close(session, event_fd_data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -292,9 +344,10 @@ static int my_channel_data_function(ssh_session session,
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int my_fd_data_function(UNUSED_PARAM(socket_t fd),
|
static int
|
||||||
int revents,
|
my_fd_data_function(UNUSED_PARAM(socket_t fd),
|
||||||
void *userdata)
|
int revents,
|
||||||
|
void *userdata)
|
||||||
{
|
{
|
||||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||||
ssh_channel channel = event_fd_data->channel;
|
ssh_channel channel = event_fd_data->channel;
|
||||||
@@ -387,7 +440,9 @@ static int my_fd_data_function(UNUSED_PARAM(socket_t fd),
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_tcp_socket(ssh_message msg) {
|
static int
|
||||||
|
open_tcp_socket(ssh_message msg)
|
||||||
|
{
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int forwardsock = -1;
|
int forwardsock = -1;
|
||||||
struct hostent *host;
|
struct hostent *host;
|
||||||
@@ -428,17 +483,20 @@ static int open_tcp_socket(ssh_message msg) {
|
|||||||
return forwardsock;
|
return forwardsock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int message_callback(ssh_session session, ssh_message message, void *userdata) {
|
static int
|
||||||
|
message_callback(UNUSED_PARAM(ssh_session session),
|
||||||
|
ssh_message message,
|
||||||
|
UNUSED_PARAM(void *userdata))
|
||||||
|
{
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
int socket_fd, *pFd;
|
int socket_fd, *pFd;
|
||||||
struct ssh_channel_callbacks_struct *cb_chan;
|
struct ssh_channel_callbacks_struct *cb_chan;
|
||||||
struct event_fd_data_struct *event_fd_data;
|
struct event_fd_data_struct *event_fd_data;
|
||||||
(void)session;
|
|
||||||
(void)message;
|
|
||||||
(void)userdata;
|
|
||||||
|
|
||||||
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d", ssh_message_type(message));
|
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d",
|
||||||
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message Subtype: %d", ssh_message_subtype(message));
|
ssh_message_type(message));
|
||||||
|
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message Subtype: %d",
|
||||||
|
ssh_message_subtype(message));
|
||||||
if (ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN) {
|
if (ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN) {
|
||||||
_ssh_log(SSH_LOG_PROTOCOL, "=== message_callback", "channel_request_open");
|
_ssh_log(SSH_LOG_PROTOCOL, "=== message_callback", "channel_request_open");
|
||||||
|
|
||||||
@@ -460,6 +518,12 @@ static int message_callback(ssh_session session, ssh_message message, void *user
|
|||||||
pFd = malloc(sizeof *pFd);
|
pFd = malloc(sizeof *pFd);
|
||||||
cb_chan = malloc(sizeof *cb_chan);
|
cb_chan = malloc(sizeof *cb_chan);
|
||||||
event_fd_data = malloc(sizeof *event_fd_data);
|
event_fd_data = malloc(sizeof *event_fd_data);
|
||||||
|
if (pFd == NULL || cb_chan == NULL || event_fd_data == NULL) {
|
||||||
|
SAFE_FREE(pFd);
|
||||||
|
SAFE_FREE(cb_chan);
|
||||||
|
SAFE_FREE(event_fd_data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
(*pFd) = socket_fd;
|
(*pFd) = socket_fd;
|
||||||
event_fd_data->channel = channel;
|
event_fd_data->channel = channel;
|
||||||
@@ -542,7 +606,9 @@ static struct argp_option options[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Parse a single option. */
|
/* Parse a single option. */
|
||||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
static error_t
|
||||||
|
parse_opt (int key, char *arg, struct argp_state *state)
|
||||||
|
{
|
||||||
/* Get the input argument from argp_parse, which we
|
/* Get the input argument from argp_parse, which we
|
||||||
* know is a pointer to our arguments structure.
|
* know is a pointer to our arguments structure.
|
||||||
*/
|
*/
|
||||||
@@ -588,7 +654,9 @@ 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};
|
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||||
#endif /* HAVE_ARGP_H */
|
#endif /* HAVE_ARGP_H */
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_bind sshbind;
|
ssh_bind sshbind;
|
||||||
struct ssh_server_callbacks_struct cb = {
|
struct ssh_server_callbacks_struct cb = {
|
||||||
|
|||||||
@@ -233,9 +233,10 @@ void set_pcap(ssh_session session){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_pcap(void);
|
void cleanup_pcap(void);
|
||||||
void cleanup_pcap(){
|
void cleanup_pcap(void)
|
||||||
|
{
|
||||||
ssh_pcap_file_free(pcap);
|
ssh_pcap_file_free(pcap);
|
||||||
pcap=NULL;
|
pcap = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -31,3 +31,9 @@ install(
|
|||||||
headers
|
headers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libssh_version.h.cmake
|
||||||
|
${libssh_BINARY_DIR}/include/libssh/libssh_version.h
|
||||||
|
@ONLY)
|
||||||
|
install(FILES ${libssh_BINARY_DIR}/include/libssh/libssh_version.h
|
||||||
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${APPLICATION_NAME}
|
||||||
|
COMPONENT headers)
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
#ifndef CONFIG_PARSER_H_
|
#ifndef CONFIG_PARSER_H_
|
||||||
#define CONFIG_PARSER_H_
|
#define CONFIG_PARSER_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
char *ssh_config_get_cmd(char **str);
|
char *ssh_config_get_cmd(char **str);
|
||||||
|
|
||||||
char *ssh_config_get_token(char **str);
|
char *ssh_config_get_token(char **str);
|
||||||
@@ -45,13 +47,16 @@ int ssh_config_get_yesno(char **str, int notfound);
|
|||||||
* be stored or NULL if we do not care about the result.
|
* be stored or NULL if we do not care about the result.
|
||||||
* @param[out] port Pointer to the location, where the new port will
|
* @param[out] port Pointer to the location, where the new port will
|
||||||
* be stored or NULL if we do not care about the result.
|
* be stored or NULL if we do not care about the result.
|
||||||
|
* @param[in] ignore_port Set to true if the we should not attempt to parse
|
||||||
|
* port number.
|
||||||
*
|
*
|
||||||
* @returns SSH_OK if the provided string is in format of SSH URI,
|
* @returns SSH_OK if the provided string is in format of SSH URI,
|
||||||
* SSH_ERROR on failure
|
* SSH_ERROR on failure
|
||||||
*/
|
*/
|
||||||
int ssh_config_parse_uri(const char *tok,
|
int ssh_config_parse_uri(const char *tok,
|
||||||
char **username,
|
char **username,
|
||||||
char **hostname,
|
char **hostname,
|
||||||
char **port);
|
char **port,
|
||||||
|
bool ignore_port);
|
||||||
|
|
||||||
#endif /* LIBSSH_CONFIG_H_ */
|
#endif /* LIBSSH_CONFIG_H_ */
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ enum ssh_key_exchange_e {
|
|||||||
SSH_KEX_DH_GROUP16_SHA512,
|
SSH_KEX_DH_GROUP16_SHA512,
|
||||||
/* diffie-hellman-group18-sha512 */
|
/* diffie-hellman-group18-sha512 */
|
||||||
SSH_KEX_DH_GROUP18_SHA512,
|
SSH_KEX_DH_GROUP18_SHA512,
|
||||||
|
/* diffie-hellman-group14-sha256 */
|
||||||
|
SSH_KEX_DH_GROUP14_SHA256,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ssh_cipher_e {
|
enum ssh_cipher_e {
|
||||||
@@ -124,8 +126,9 @@ struct ssh_crypto_struct {
|
|||||||
ssh_curve25519_pubkey curve25519_server_pubkey;
|
ssh_curve25519_pubkey curve25519_server_pubkey;
|
||||||
#endif
|
#endif
|
||||||
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
||||||
size_t digest_len; /* len of the two fields below */
|
size_t session_id_len;
|
||||||
unsigned char *session_id;
|
unsigned char *session_id;
|
||||||
|
size_t digest_len; /* len of the secret hash */
|
||||||
unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */
|
unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */
|
||||||
unsigned char *encryptIV;
|
unsigned char *encryptIV;
|
||||||
unsigned char *decryptIV;
|
unsigned char *decryptIV;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
|
|||||||
|
|
||||||
|
|
||||||
int ssh_client_curve25519_init(ssh_session session);
|
int ssh_client_curve25519_init(ssh_session session);
|
||||||
|
void ssh_client_curve25519_remove_callbacks(ssh_session session);
|
||||||
|
|
||||||
#ifdef WITH_SERVER
|
#ifdef WITH_SERVER
|
||||||
void ssh_server_curve25519_init(ssh_session session);
|
void ssh_server_curve25519_init(ssh_session session);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#define SRC_DH_GEX_H_
|
#define SRC_DH_GEX_H_
|
||||||
|
|
||||||
int ssh_client_dhgex_init(ssh_session session);
|
int ssh_client_dhgex_init(ssh_session session);
|
||||||
|
void ssh_client_dhgex_remove_callbacks(ssh_session session);
|
||||||
|
|
||||||
#ifdef WITH_SERVER
|
#ifdef WITH_SERVER
|
||||||
void ssh_server_dhgex_init(ssh_session session);
|
void ssh_server_dhgex_init(ssh_session session);
|
||||||
|
|||||||
@@ -63,8 +63,10 @@ int ssh_dh_get_current_server_publickey_blob(ssh_session session,
|
|||||||
ssh_key ssh_dh_get_next_server_publickey(ssh_session session);
|
ssh_key ssh_dh_get_next_server_publickey(ssh_session session);
|
||||||
int ssh_dh_get_next_server_publickey_blob(ssh_session session,
|
int ssh_dh_get_next_server_publickey_blob(ssh_session session,
|
||||||
ssh_string *pubkey_blob);
|
ssh_string *pubkey_blob);
|
||||||
|
int dh_handshake(ssh_session session);
|
||||||
|
|
||||||
int ssh_client_dh_init(ssh_session session);
|
int ssh_client_dh_init(ssh_session session);
|
||||||
|
void ssh_client_dh_remove_callbacks(ssh_session session);
|
||||||
#ifdef WITH_SERVER
|
#ifdef WITH_SERVER
|
||||||
void ssh_server_dh_init(ssh_session session);
|
void ssh_server_dh_init(ssh_session session);
|
||||||
#endif /* WITH_SERVER */
|
#endif /* WITH_SERVER */
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks;
|
extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks;
|
||||||
/* Backend-specific functions. */
|
/* Backend-specific functions. */
|
||||||
int ssh_client_ecdh_init(ssh_session session);
|
int ssh_client_ecdh_init(ssh_session session);
|
||||||
|
void ssh_client_ecdh_remove_callbacks(ssh_session session);
|
||||||
int ecdh_build_k(ssh_session session);
|
int ecdh_build_k(ssh_session session);
|
||||||
|
|
||||||
#ifdef WITH_SERVER
|
#ifdef WITH_SERVER
|
||||||
|
|||||||
@@ -33,9 +33,10 @@ struct ssh_kex_struct {
|
|||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
|
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
|
||||||
|
|
||||||
int ssh_send_kex(ssh_session session, int server_kex);
|
int ssh_send_kex(ssh_session session);
|
||||||
void ssh_list_kex(struct ssh_kex_struct *kex);
|
void ssh_list_kex(struct ssh_kex_struct *kex);
|
||||||
int ssh_set_client_kex(ssh_session session);
|
int ssh_set_client_kex(ssh_session session);
|
||||||
|
int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex);
|
||||||
int ssh_kex_select_methods(ssh_session session);
|
int ssh_kex_select_methods(ssh_session session);
|
||||||
int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name);
|
int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name);
|
||||||
char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list);
|
char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list);
|
||||||
|
|||||||
@@ -28,13 +28,13 @@
|
|||||||
struct ssh_public_key_struct {
|
struct ssh_public_key_struct {
|
||||||
int type;
|
int type;
|
||||||
const char *type_c; /* Don't free it ! it is static */
|
const char *type_c; /* Don't free it ! it is static */
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#if defined(HAVE_LIBGCRYPT)
|
||||||
gcry_sexp_t dsa_pub;
|
gcry_sexp_t dsa_pub;
|
||||||
gcry_sexp_t rsa_pub;
|
gcry_sexp_t rsa_pub;
|
||||||
#elif HAVE_LIBCRYPTO
|
#elif defined(HAVE_LIBCRYPTO)
|
||||||
DSA *dsa_pub;
|
DSA *dsa_pub;
|
||||||
RSA *rsa_pub;
|
RSA *rsa_pub;
|
||||||
#elif HAVE_LIBMBEDCRYPTO
|
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||||
mbedtls_pk_context *rsa_pub;
|
mbedtls_pk_context *rsa_pub;
|
||||||
void *dsa_pub;
|
void *dsa_pub;
|
||||||
#endif
|
#endif
|
||||||
@@ -42,13 +42,13 @@ struct ssh_public_key_struct {
|
|||||||
|
|
||||||
struct ssh_private_key_struct {
|
struct ssh_private_key_struct {
|
||||||
int type;
|
int type;
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#if defined(HAVE_LIBGCRYPT)
|
||||||
gcry_sexp_t dsa_priv;
|
gcry_sexp_t dsa_priv;
|
||||||
gcry_sexp_t rsa_priv;
|
gcry_sexp_t rsa_priv;
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined(HAVE_LIBCRYPTO)
|
||||||
DSA *dsa_priv;
|
DSA *dsa_priv;
|
||||||
RSA *rsa_priv;
|
RSA *rsa_priv;
|
||||||
#elif HAVE_LIBMBEDCRYPTO
|
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||||
mbedtls_pk_context *rsa_priv;
|
mbedtls_pk_context *rsa_priv;
|
||||||
void *dsa_priv;
|
void *dsa_priv;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -39,11 +39,6 @@ typedef EVP_MD_CTX* SHA384CTX;
|
|||||||
typedef EVP_MD_CTX* SHA512CTX;
|
typedef EVP_MD_CTX* SHA512CTX;
|
||||||
typedef EVP_MD_CTX* MD5CTX;
|
typedef EVP_MD_CTX* MD5CTX;
|
||||||
typedef HMAC_CTX* HMACCTX;
|
typedef HMAC_CTX* HMACCTX;
|
||||||
#ifdef HAVE_ECC
|
|
||||||
typedef EVP_MD_CTX *EVPCTX;
|
|
||||||
#else
|
|
||||||
typedef void *EVPCTX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||||
#define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
|
#define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ typedef gcry_md_hd_t SHA384CTX;
|
|||||||
typedef gcry_md_hd_t SHA512CTX;
|
typedef gcry_md_hd_t SHA512CTX;
|
||||||
typedef gcry_md_hd_t MD5CTX;
|
typedef gcry_md_hd_t MD5CTX;
|
||||||
typedef gcry_md_hd_t HMACCTX;
|
typedef gcry_md_hd_t HMACCTX;
|
||||||
typedef gcry_md_hd_t EVPCTX;
|
|
||||||
#define SHA_DIGEST_LENGTH 20
|
#define SHA_DIGEST_LENGTH 20
|
||||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||||
#define MD5_DIGEST_LEN 16
|
#define MD5_DIGEST_LEN 16
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ typedef mbedtls_md_context_t *SHA384CTX;
|
|||||||
typedef mbedtls_md_context_t *SHA512CTX;
|
typedef mbedtls_md_context_t *SHA512CTX;
|
||||||
typedef mbedtls_md_context_t *MD5CTX;
|
typedef mbedtls_md_context_t *MD5CTX;
|
||||||
typedef mbedtls_md_context_t *HMACCTX;
|
typedef mbedtls_md_context_t *HMACCTX;
|
||||||
typedef mbedtls_md_context_t *EVPCTX;
|
|
||||||
|
|
||||||
#define SHA_DIGEST_LENGTH 20
|
#define SHA_DIGEST_LENGTH 20
|
||||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the SSH Library
|
* This file is part of the SSH Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2009 by Aris Adamantiadis
|
* Copyright (c) 2003-2021 by Aris Adamantiadis and the libssh team
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
#ifndef _LIBSSH_H
|
#ifndef _LIBSSH_H
|
||||||
#define _LIBSSH_H
|
#define _LIBSSH_H
|
||||||
|
|
||||||
|
#include <libssh/libssh_version.h>
|
||||||
|
|
||||||
#if defined _WIN32 || defined __CYGWIN__
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
#ifdef LIBSSH_STATIC
|
#ifdef LIBSSH_STATIC
|
||||||
#define LIBSSH_API
|
#define LIBSSH_API
|
||||||
@@ -71,23 +73,6 @@
|
|||||||
#define SSH_STRINGIFY(s) SSH_TOSTRING(s)
|
#define SSH_STRINGIFY(s) SSH_TOSTRING(s)
|
||||||
#define SSH_TOSTRING(s) #s
|
#define SSH_TOSTRING(s) #s
|
||||||
|
|
||||||
/* libssh version macros */
|
|
||||||
#define SSH_VERSION_INT(a, b, c) ((a) << 16 | (b) << 8 | (c))
|
|
||||||
#define SSH_VERSION_DOT(a, b, c) a ##.## b ##.## c
|
|
||||||
#define SSH_VERSION(a, b, c) SSH_VERSION_DOT(a, b, c)
|
|
||||||
|
|
||||||
/* libssh version */
|
|
||||||
#define LIBSSH_VERSION_MAJOR 0
|
|
||||||
#define LIBSSH_VERSION_MINOR 9
|
|
||||||
#define LIBSSH_VERSION_MICRO 3
|
|
||||||
|
|
||||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
|
||||||
LIBSSH_VERSION_MINOR, \
|
|
||||||
LIBSSH_VERSION_MICRO)
|
|
||||||
#define LIBSSH_VERSION SSH_VERSION(LIBSSH_VERSION_MAJOR, \
|
|
||||||
LIBSSH_VERSION_MINOR, \
|
|
||||||
LIBSSH_VERSION_MICRO)
|
|
||||||
|
|
||||||
/* GCC have printf type attribute check. */
|
/* GCC have printf type attribute check. */
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
|
#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
|
||||||
@@ -633,7 +618,13 @@ LIBSSH_API ssh_pcap_file ssh_pcap_file_new(void);
|
|||||||
LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief SSH authentication callback.
|
* @addtogroup libssh_auth
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SSH authentication callback for password and publickey auth.
|
||||||
*
|
*
|
||||||
* @param prompt Prompt to be displayed.
|
* @param prompt Prompt to be displayed.
|
||||||
* @param buf Buffer to save the password. You should null-terminate it.
|
* @param buf Buffer to save the password. You should null-terminate it.
|
||||||
@@ -648,6 +639,8 @@ LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
|||||||
typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
||||||
int echo, int verify, void *userdata);
|
int echo, int verify, void *userdata);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
LIBSSH_API ssh_key ssh_key_new(void);
|
LIBSSH_API ssh_key ssh_key_new(void);
|
||||||
#define SSH_KEY_FREE(x) \
|
#define SSH_KEY_FREE(x) \
|
||||||
do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0)
|
do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0)
|
||||||
|
|||||||
41
include/libssh/libssh_version.h.cmake
Normal file
41
include/libssh/libssh_version.h.cmake
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 by Heiko Thiery
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBSSH_VERSION_H
|
||||||
|
#define _LIBSSH_VERSION_H
|
||||||
|
|
||||||
|
/* libssh version macros */
|
||||||
|
#define SSH_VERSION_INT(a, b, c) ((a) << 16 | (b) << 8 | (c))
|
||||||
|
#define SSH_VERSION_DOT(a, b, c) a ##.## b ##.## c
|
||||||
|
#define SSH_VERSION(a, b, c) SSH_VERSION_DOT(a, b, c)
|
||||||
|
|
||||||
|
/* libssh version */
|
||||||
|
#define LIBSSH_VERSION_MAJOR @libssh_VERSION_MAJOR@
|
||||||
|
#define LIBSSH_VERSION_MINOR @libssh_VERSION_MINOR@
|
||||||
|
#define LIBSSH_VERSION_MICRO @libssh_VERSION_PATCH@
|
||||||
|
|
||||||
|
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||||
|
LIBSSH_VERSION_MINOR, \
|
||||||
|
LIBSSH_VERSION_MICRO)
|
||||||
|
#define LIBSSH_VERSION SSH_VERSION(LIBSSH_VERSION_MAJOR, \
|
||||||
|
LIBSSH_VERSION_MINOR, \
|
||||||
|
LIBSSH_VERSION_MICRO)
|
||||||
|
|
||||||
|
#endif /* _LIBSSH_VERSION_H */
|
||||||
@@ -97,4 +97,6 @@ int ssh_mkdirs(const char *pathname, mode_t mode);
|
|||||||
int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
|
int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
|
||||||
int ssh_newline_vis(const char *string, char *buf, size_t buf_len);
|
int ssh_newline_vis(const char *string, char *buf, size_t buf_len);
|
||||||
|
|
||||||
|
int ssh_check_hostname_syntax(const char *hostname);
|
||||||
|
|
||||||
#endif /* MISC_H_ */
|
#endif /* MISC_H_ */
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info);
|
|||||||
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init);
|
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int ssh_packet_send_newkeys(ssh_session session);
|
||||||
int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum);
|
int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum);
|
||||||
int ssh_packet_parse_type(ssh_session session);
|
int ssh_packet_parse_type(ssh_session session);
|
||||||
//int packet_flush(ssh_session session, int enforce_blocking);
|
//int packet_flush(ssh_session session, int enforce_blocking);
|
||||||
@@ -80,7 +81,7 @@ int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *sourc
|
|||||||
size_t start, size_t encrypted_size);
|
size_t start, size_t encrypted_size);
|
||||||
unsigned char *ssh_packet_encrypt(ssh_session session,
|
unsigned char *ssh_packet_encrypt(ssh_session session,
|
||||||
void *packet,
|
void *packet,
|
||||||
unsigned int len);
|
uint32_t len);
|
||||||
int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len,
|
int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len,
|
||||||
unsigned char *mac, enum ssh_hmac_e type);
|
unsigned char *mac, enum ssh_hmac_e type);
|
||||||
int ssh_packet_set_newkeys(ssh_session session,
|
int ssh_packet_set_newkeys(ssh_session session,
|
||||||
|
|||||||
@@ -125,6 +125,8 @@ enum ssh_digest_e ssh_key_hash_from_name(const char *name);
|
|||||||
/* SSH Signature Functions */
|
/* SSH Signature Functions */
|
||||||
ssh_signature ssh_signature_new(void);
|
ssh_signature ssh_signature_new(void);
|
||||||
void ssh_signature_free(ssh_signature sign);
|
void ssh_signature_free(ssh_signature sign);
|
||||||
|
#define SSH_SIGNATURE_FREE(x) \
|
||||||
|
do { ssh_signature_free(x); x = NULL; } while(0)
|
||||||
|
|
||||||
int ssh_pki_export_signature_blob(const ssh_signature sign,
|
int ssh_pki_export_signature_blob(const ssh_signature sign,
|
||||||
ssh_string *sign_blob);
|
ssh_string *sign_blob);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if !defined(HAVE_STRTOULL)
|
#if !defined(HAVE_STRTOULL)
|
||||||
# if defined(HAVE___STRTOULL)
|
# if defined(HAVE___STRTOULL)
|
||||||
@@ -405,22 +406,24 @@ void explicit_bzero(void *s, size_t n);
|
|||||||
# endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
|
# endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
|
||||||
#endif /* FALL_THROUGH */
|
#endif /* FALL_THROUGH */
|
||||||
|
|
||||||
#ifndef __unused__
|
#ifndef __attr_unused__
|
||||||
# ifdef HAVE_UNUSED_ATTRIBUTE
|
# ifdef HAVE_UNUSED_ATTRIBUTE
|
||||||
# define __unused__ __attribute__((unused))
|
# define __attr_unused__ __attribute__((unused))
|
||||||
# else /* HAVE_UNUSED_ATTRIBUTE */
|
# else /* HAVE_UNUSED_ATTRIBUTE */
|
||||||
# define __unused__
|
# define __attr_unused__
|
||||||
# endif /* HAVE_UNUSED_ATTRIBUTE */
|
# endif /* HAVE_UNUSED_ATTRIBUTE */
|
||||||
#endif /* __unused__ */
|
#endif /* __attr_unused__ */
|
||||||
|
|
||||||
#ifndef UNUSED_PARAM
|
#ifndef UNUSED_PARAM
|
||||||
#define UNUSED_PARAM(param) param __unused__
|
#define UNUSED_PARAM(param) param __attr_unused__
|
||||||
#endif /* UNUSED_PARAM */
|
#endif /* UNUSED_PARAM */
|
||||||
|
|
||||||
#ifndef UNUSED_VAR
|
#ifndef UNUSED_VAR
|
||||||
#define UNUSED_VAR(var) __unused__ var
|
#define UNUSED_VAR(var) __attr_unused__ var
|
||||||
#endif /* UNUSED_VAR */
|
#endif /* UNUSED_VAR */
|
||||||
|
|
||||||
void ssh_agent_state_free(void *data);
|
void ssh_agent_state_free(void *data);
|
||||||
|
|
||||||
|
bool is_ssh_initialized(void);
|
||||||
|
|
||||||
#endif /* _LIBSSH_PRIV_H */
|
#endif /* _LIBSSH_PRIV_H */
|
||||||
|
|||||||
@@ -75,6 +75,17 @@ enum ssh_pending_call_e {
|
|||||||
/* Client successfully authenticated */
|
/* Client successfully authenticated */
|
||||||
#define SSH_SESSION_FLAG_AUTHENTICATED 2
|
#define SSH_SESSION_FLAG_AUTHENTICATED 2
|
||||||
|
|
||||||
|
/* The KEXINIT message can be sent first by either of the parties so this flag
|
||||||
|
* indicates that the message was already sent to make sure it is sent and avoid
|
||||||
|
* sending it twice during key exchange to simplify the state machine. */
|
||||||
|
#define SSH_SESSION_FLAG_KEXINIT_SENT 4
|
||||||
|
|
||||||
|
/* The current SSH2 session implements the "strict KEX" feature and should behave
|
||||||
|
* differently on SSH2_MSG_NEWKEYS. */
|
||||||
|
#define SSH_SESSION_FLAG_KEX_STRICT 0x0010
|
||||||
|
/* Unexpected packets have been sent while the session was still unencrypted */
|
||||||
|
#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020
|
||||||
|
|
||||||
/* codes to use with ssh_handle_packets*() */
|
/* codes to use with ssh_handle_packets*() */
|
||||||
/* Infinite timeout */
|
/* Infinite timeout */
|
||||||
#define SSH_TIMEOUT_INFINITE -1
|
#define SSH_TIMEOUT_INFINITE -1
|
||||||
@@ -131,10 +142,8 @@ struct ssh_session_struct {
|
|||||||
/* Extensions negotiated using RFC 8308 */
|
/* Extensions negotiated using RFC 8308 */
|
||||||
uint32_t extensions;
|
uint32_t extensions;
|
||||||
|
|
||||||
ssh_string banner; /* that's the issue banner from
|
ssh_string banner; /* that's the issue banner from the server */
|
||||||
the server */
|
char *discon_msg; /* disconnect message from the remote host */
|
||||||
char *discon_msg; /* disconnect message from
|
|
||||||
the remote host */
|
|
||||||
ssh_buffer in_buffer;
|
ssh_buffer in_buffer;
|
||||||
PACKET in_packet;
|
PACKET in_packet;
|
||||||
ssh_buffer out_buffer;
|
ssh_buffer out_buffer;
|
||||||
@@ -158,25 +167,33 @@ struct ssh_session_struct {
|
|||||||
uint32_t current_method;
|
uint32_t current_method;
|
||||||
} auth;
|
} auth;
|
||||||
|
|
||||||
|
/* Sending this flag before key exchange to save one round trip during the
|
||||||
|
* key exchange. This might make sense on high-latency connections.
|
||||||
|
* So far internal only for testing. Usable only on the client side --
|
||||||
|
* there is no key exchange method that would start with server message */
|
||||||
|
bool send_first_kex_follows;
|
||||||
/*
|
/*
|
||||||
* RFC 4253, 7.1: if the first_kex_packet_follows flag was set in
|
* RFC 4253, 7.1: if the first_kex_packet_follows flag was set in
|
||||||
* the received SSH_MSG_KEXINIT, but the guess was wrong, this
|
* the received SSH_MSG_KEXINIT, but the guess was wrong, this
|
||||||
* field will be set such that the following guessed packet will
|
* field will be set such that the following guessed packet will
|
||||||
* be ignored. Once that packet has been received and ignored,
|
* be ignored on the receiving side. Once that packet has been received and
|
||||||
* this field is cleared.
|
* ignored, this field is cleared.
|
||||||
|
* On the sending side, this is set after we got peer KEXINIT message and we
|
||||||
|
* need to resend the initial message of the negotiated KEX algorithm.
|
||||||
*/
|
*/
|
||||||
int first_kex_follows_guess_wrong;
|
bool first_kex_follows_guess_wrong;
|
||||||
|
|
||||||
ssh_buffer in_hashbuf;
|
ssh_buffer in_hashbuf;
|
||||||
ssh_buffer out_hashbuf;
|
ssh_buffer out_hashbuf;
|
||||||
struct ssh_crypto_struct *current_crypto;
|
struct ssh_crypto_struct *current_crypto;
|
||||||
struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
|
/* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
|
||||||
|
struct ssh_crypto_struct *next_crypto;
|
||||||
|
|
||||||
struct ssh_list *channels; /* linked list of channels */
|
struct ssh_list *channels; /* linked list of channels */
|
||||||
int maxchannel;
|
int maxchannel;
|
||||||
ssh_agent agent; /* ssh agent */
|
ssh_agent agent; /* ssh agent */
|
||||||
|
|
||||||
/* keyb interactive data */
|
/* keyboard interactive data */
|
||||||
struct ssh_kbdint_struct *kbdint;
|
struct ssh_kbdint_struct *kbdint;
|
||||||
struct ssh_gssapi_struct *gssapi;
|
struct ssh_gssapi_struct *gssapi;
|
||||||
|
|
||||||
@@ -193,7 +210,8 @@ struct ssh_session_struct {
|
|||||||
|
|
||||||
/* auths accepted by server */
|
/* auths accepted by server */
|
||||||
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
|
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
|
||||||
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata);
|
int (*ssh_message_callback)(struct ssh_session_struct *session,
|
||||||
|
ssh_message msg, void *userdata);
|
||||||
void *ssh_message_callback_data;
|
void *ssh_message_callback_data;
|
||||||
ssh_server_callbacks server_callbacks;
|
ssh_server_callbacks server_callbacks;
|
||||||
void (*ssh_connection_callback)( struct ssh_session_struct *session);
|
void (*ssh_connection_callback)( struct ssh_session_struct *session);
|
||||||
@@ -219,7 +237,7 @@ struct ssh_session_struct {
|
|||||||
char *custombanner;
|
char *custombanner;
|
||||||
unsigned long timeout; /* seconds */
|
unsigned long timeout; /* seconds */
|
||||||
unsigned long timeout_usec;
|
unsigned long timeout_usec;
|
||||||
unsigned int port;
|
uint16_t port;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
int StrictHostKeyChecking;
|
int StrictHostKeyChecking;
|
||||||
char compressionlevel;
|
char compressionlevel;
|
||||||
|
|||||||
@@ -67,37 +67,38 @@ struct ssh_crypto_struct;
|
|||||||
|
|
||||||
typedef struct ssh_mac_ctx_struct *ssh_mac_ctx;
|
typedef struct ssh_mac_ctx_struct *ssh_mac_ctx;
|
||||||
MD5CTX md5_init(void);
|
MD5CTX md5_init(void);
|
||||||
void md5_update(MD5CTX c, const void *data, unsigned long len);
|
void md5_ctx_free(MD5CTX);
|
||||||
void md5_final(unsigned char *md,MD5CTX c);
|
int md5_update(MD5CTX c, const void *data, unsigned long len);
|
||||||
|
int md5_final(unsigned char *md,MD5CTX c);
|
||||||
|
|
||||||
SHACTX sha1_init(void);
|
SHACTX sha1_init(void);
|
||||||
void sha1_update(SHACTX c, const void *data, unsigned long len);
|
void sha1_ctx_free(SHACTX);
|
||||||
void sha1_final(unsigned char *md,SHACTX c);
|
int sha1_update(SHACTX c, const void *data, unsigned long len);
|
||||||
void sha1(const unsigned char *digest,int len,unsigned char *hash);
|
int sha1_final(unsigned char *md,SHACTX c);
|
||||||
|
int sha1(const unsigned char *digest,int len,unsigned char *hash);
|
||||||
|
|
||||||
SHA256CTX sha256_init(void);
|
SHA256CTX sha256_init(void);
|
||||||
void sha256_update(SHA256CTX c, const void *data, unsigned long len);
|
void sha256_ctx_free(SHA256CTX);
|
||||||
void sha256_final(unsigned char *md,SHA256CTX c);
|
int sha256_update(SHA256CTX c, const void *data, unsigned long len);
|
||||||
void sha256(const unsigned char *digest, int len, unsigned char *hash);
|
int sha256_final(unsigned char *md,SHA256CTX c);
|
||||||
|
int sha256(const unsigned char *digest, int len, unsigned char *hash);
|
||||||
|
|
||||||
SHA384CTX sha384_init(void);
|
SHA384CTX sha384_init(void);
|
||||||
void sha384_update(SHA384CTX c, const void *data, unsigned long len);
|
void sha384_ctx_free(SHA384CTX);
|
||||||
void sha384_final(unsigned char *md,SHA384CTX c);
|
int sha384_update(SHA384CTX c, const void *data, unsigned long len);
|
||||||
void sha384(const unsigned char *digest, int len, unsigned char *hash);
|
int sha384_final(unsigned char *md,SHA384CTX c);
|
||||||
|
int sha384(const unsigned char *digest, int len, unsigned char *hash);
|
||||||
|
|
||||||
SHA512CTX sha512_init(void);
|
SHA512CTX sha512_init(void);
|
||||||
void sha512_update(SHA512CTX c, const void *data, unsigned long len);
|
void sha512_ctx_free(SHA512CTX);
|
||||||
void sha512_final(unsigned char *md,SHA512CTX c);
|
int sha512_update(SHA512CTX c, const void *data, unsigned long len);
|
||||||
void sha512(const unsigned char *digest, int len, unsigned char *hash);
|
int sha512_final(unsigned char *md,SHA512CTX c);
|
||||||
|
int sha512(const unsigned char *digest, int len, unsigned char *hash);
|
||||||
void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen);
|
|
||||||
EVPCTX evp_init(int nid);
|
|
||||||
void evp_update(EVPCTX ctx, const void *data, unsigned long len);
|
|
||||||
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen);
|
|
||||||
|
|
||||||
HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type);
|
HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type);
|
||||||
void hmac_update(HMACCTX c, const void *data, unsigned long len);
|
void hmac_update(HMACCTX c, const void *data, unsigned long len);
|
||||||
void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
|
void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
|
||||||
|
|
||||||
size_t hmac_digest_len(enum ssh_hmac_e type);
|
size_t hmac_digest_len(enum ssh_hmac_e type);
|
||||||
|
|
||||||
int ssh_kdf(struct ssh_crypto_struct *crypto,
|
int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
4.8.4
|
4.8.9
|
||||||
421
src/ABI/libssh-4.8.5.symbols
Normal file
421
src/ABI/libssh-4.8.5.symbols
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
_ssh_log
|
||||||
|
buffer_free
|
||||||
|
buffer_get
|
||||||
|
buffer_get_len
|
||||||
|
buffer_new
|
||||||
|
channel_accept_x11
|
||||||
|
channel_change_pty_size
|
||||||
|
channel_close
|
||||||
|
channel_forward_accept
|
||||||
|
channel_forward_cancel
|
||||||
|
channel_forward_listen
|
||||||
|
channel_free
|
||||||
|
channel_get_exit_status
|
||||||
|
channel_get_session
|
||||||
|
channel_is_closed
|
||||||
|
channel_is_eof
|
||||||
|
channel_is_open
|
||||||
|
channel_new
|
||||||
|
channel_open_forward
|
||||||
|
channel_open_session
|
||||||
|
channel_poll
|
||||||
|
channel_read
|
||||||
|
channel_read_buffer
|
||||||
|
channel_read_nonblocking
|
||||||
|
channel_request_env
|
||||||
|
channel_request_exec
|
||||||
|
channel_request_pty
|
||||||
|
channel_request_pty_size
|
||||||
|
channel_request_send_signal
|
||||||
|
channel_request_sftp
|
||||||
|
channel_request_shell
|
||||||
|
channel_request_subsystem
|
||||||
|
channel_request_x11
|
||||||
|
channel_select
|
||||||
|
channel_send_eof
|
||||||
|
channel_set_blocking
|
||||||
|
channel_write
|
||||||
|
channel_write_stderr
|
||||||
|
privatekey_free
|
||||||
|
privatekey_from_file
|
||||||
|
publickey_free
|
||||||
|
publickey_from_file
|
||||||
|
publickey_from_privatekey
|
||||||
|
publickey_to_string
|
||||||
|
sftp_async_read
|
||||||
|
sftp_async_read_begin
|
||||||
|
sftp_attributes_free
|
||||||
|
sftp_canonicalize_path
|
||||||
|
sftp_chmod
|
||||||
|
sftp_chown
|
||||||
|
sftp_client_message_free
|
||||||
|
sftp_client_message_get_data
|
||||||
|
sftp_client_message_get_filename
|
||||||
|
sftp_client_message_get_flags
|
||||||
|
sftp_client_message_get_submessage
|
||||||
|
sftp_client_message_get_type
|
||||||
|
sftp_client_message_set_filename
|
||||||
|
sftp_close
|
||||||
|
sftp_closedir
|
||||||
|
sftp_dir_eof
|
||||||
|
sftp_extension_supported
|
||||||
|
sftp_extensions_get_count
|
||||||
|
sftp_extensions_get_data
|
||||||
|
sftp_extensions_get_name
|
||||||
|
sftp_file_set_blocking
|
||||||
|
sftp_file_set_nonblocking
|
||||||
|
sftp_free
|
||||||
|
sftp_fstat
|
||||||
|
sftp_fstatvfs
|
||||||
|
sftp_fsync
|
||||||
|
sftp_get_client_message
|
||||||
|
sftp_get_error
|
||||||
|
sftp_handle
|
||||||
|
sftp_handle_alloc
|
||||||
|
sftp_handle_remove
|
||||||
|
sftp_init
|
||||||
|
sftp_lstat
|
||||||
|
sftp_mkdir
|
||||||
|
sftp_new
|
||||||
|
sftp_new_channel
|
||||||
|
sftp_open
|
||||||
|
sftp_opendir
|
||||||
|
sftp_read
|
||||||
|
sftp_readdir
|
||||||
|
sftp_readlink
|
||||||
|
sftp_rename
|
||||||
|
sftp_reply_attr
|
||||||
|
sftp_reply_data
|
||||||
|
sftp_reply_handle
|
||||||
|
sftp_reply_name
|
||||||
|
sftp_reply_names
|
||||||
|
sftp_reply_names_add
|
||||||
|
sftp_reply_status
|
||||||
|
sftp_rewind
|
||||||
|
sftp_rmdir
|
||||||
|
sftp_seek
|
||||||
|
sftp_seek64
|
||||||
|
sftp_send_client_message
|
||||||
|
sftp_server_free
|
||||||
|
sftp_server_init
|
||||||
|
sftp_server_new
|
||||||
|
sftp_server_version
|
||||||
|
sftp_setstat
|
||||||
|
sftp_stat
|
||||||
|
sftp_statvfs
|
||||||
|
sftp_statvfs_free
|
||||||
|
sftp_symlink
|
||||||
|
sftp_tell
|
||||||
|
sftp_tell64
|
||||||
|
sftp_unlink
|
||||||
|
sftp_utimes
|
||||||
|
sftp_write
|
||||||
|
ssh_accept
|
||||||
|
ssh_add_channel_callbacks
|
||||||
|
ssh_auth_list
|
||||||
|
ssh_basename
|
||||||
|
ssh_bind_accept
|
||||||
|
ssh_bind_accept_fd
|
||||||
|
ssh_bind_fd_toaccept
|
||||||
|
ssh_bind_free
|
||||||
|
ssh_bind_get_fd
|
||||||
|
ssh_bind_listen
|
||||||
|
ssh_bind_new
|
||||||
|
ssh_bind_options_parse_config
|
||||||
|
ssh_bind_options_set
|
||||||
|
ssh_bind_set_blocking
|
||||||
|
ssh_bind_set_callbacks
|
||||||
|
ssh_bind_set_fd
|
||||||
|
ssh_blocking_flush
|
||||||
|
ssh_buffer_add_data
|
||||||
|
ssh_buffer_free
|
||||||
|
ssh_buffer_get
|
||||||
|
ssh_buffer_get_data
|
||||||
|
ssh_buffer_get_len
|
||||||
|
ssh_buffer_new
|
||||||
|
ssh_buffer_reinit
|
||||||
|
ssh_channel_accept_forward
|
||||||
|
ssh_channel_accept_x11
|
||||||
|
ssh_channel_cancel_forward
|
||||||
|
ssh_channel_change_pty_size
|
||||||
|
ssh_channel_close
|
||||||
|
ssh_channel_free
|
||||||
|
ssh_channel_get_exit_status
|
||||||
|
ssh_channel_get_session
|
||||||
|
ssh_channel_is_closed
|
||||||
|
ssh_channel_is_eof
|
||||||
|
ssh_channel_is_open
|
||||||
|
ssh_channel_listen_forward
|
||||||
|
ssh_channel_new
|
||||||
|
ssh_channel_open_auth_agent
|
||||||
|
ssh_channel_open_forward
|
||||||
|
ssh_channel_open_forward_unix
|
||||||
|
ssh_channel_open_reverse_forward
|
||||||
|
ssh_channel_open_session
|
||||||
|
ssh_channel_open_x11
|
||||||
|
ssh_channel_poll
|
||||||
|
ssh_channel_poll_timeout
|
||||||
|
ssh_channel_read
|
||||||
|
ssh_channel_read_nonblocking
|
||||||
|
ssh_channel_read_timeout
|
||||||
|
ssh_channel_request_auth_agent
|
||||||
|
ssh_channel_request_env
|
||||||
|
ssh_channel_request_exec
|
||||||
|
ssh_channel_request_pty
|
||||||
|
ssh_channel_request_pty_size
|
||||||
|
ssh_channel_request_send_break
|
||||||
|
ssh_channel_request_send_exit_signal
|
||||||
|
ssh_channel_request_send_exit_status
|
||||||
|
ssh_channel_request_send_signal
|
||||||
|
ssh_channel_request_sftp
|
||||||
|
ssh_channel_request_shell
|
||||||
|
ssh_channel_request_subsystem
|
||||||
|
ssh_channel_request_x11
|
||||||
|
ssh_channel_select
|
||||||
|
ssh_channel_send_eof
|
||||||
|
ssh_channel_set_blocking
|
||||||
|
ssh_channel_set_counter
|
||||||
|
ssh_channel_window_size
|
||||||
|
ssh_channel_write
|
||||||
|
ssh_channel_write_stderr
|
||||||
|
ssh_clean_pubkey_hash
|
||||||
|
ssh_connect
|
||||||
|
ssh_connector_free
|
||||||
|
ssh_connector_new
|
||||||
|
ssh_connector_set_in_channel
|
||||||
|
ssh_connector_set_in_fd
|
||||||
|
ssh_connector_set_out_channel
|
||||||
|
ssh_connector_set_out_fd
|
||||||
|
ssh_copyright
|
||||||
|
ssh_dirname
|
||||||
|
ssh_disconnect
|
||||||
|
ssh_dump_knownhost
|
||||||
|
ssh_event_add_connector
|
||||||
|
ssh_event_add_fd
|
||||||
|
ssh_event_add_session
|
||||||
|
ssh_event_dopoll
|
||||||
|
ssh_event_free
|
||||||
|
ssh_event_new
|
||||||
|
ssh_event_remove_connector
|
||||||
|
ssh_event_remove_fd
|
||||||
|
ssh_event_remove_session
|
||||||
|
ssh_execute_message_callbacks
|
||||||
|
ssh_finalize
|
||||||
|
ssh_forward_accept
|
||||||
|
ssh_forward_cancel
|
||||||
|
ssh_forward_listen
|
||||||
|
ssh_free
|
||||||
|
ssh_get_cipher_in
|
||||||
|
ssh_get_cipher_out
|
||||||
|
ssh_get_clientbanner
|
||||||
|
ssh_get_disconnect_message
|
||||||
|
ssh_get_error
|
||||||
|
ssh_get_error_code
|
||||||
|
ssh_get_fd
|
||||||
|
ssh_get_fingerprint_hash
|
||||||
|
ssh_get_hexa
|
||||||
|
ssh_get_hmac_in
|
||||||
|
ssh_get_hmac_out
|
||||||
|
ssh_get_issue_banner
|
||||||
|
ssh_get_kex_algo
|
||||||
|
ssh_get_log_callback
|
||||||
|
ssh_get_log_level
|
||||||
|
ssh_get_log_userdata
|
||||||
|
ssh_get_openssh_version
|
||||||
|
ssh_get_poll_flags
|
||||||
|
ssh_get_pubkey
|
||||||
|
ssh_get_pubkey_hash
|
||||||
|
ssh_get_publickey
|
||||||
|
ssh_get_publickey_hash
|
||||||
|
ssh_get_random
|
||||||
|
ssh_get_server_publickey
|
||||||
|
ssh_get_serverbanner
|
||||||
|
ssh_get_status
|
||||||
|
ssh_get_version
|
||||||
|
ssh_getpass
|
||||||
|
ssh_gssapi_get_creds
|
||||||
|
ssh_gssapi_set_creds
|
||||||
|
ssh_handle_key_exchange
|
||||||
|
ssh_init
|
||||||
|
ssh_is_blocking
|
||||||
|
ssh_is_connected
|
||||||
|
ssh_is_server_known
|
||||||
|
ssh_key_cmp
|
||||||
|
ssh_key_free
|
||||||
|
ssh_key_is_private
|
||||||
|
ssh_key_is_public
|
||||||
|
ssh_key_new
|
||||||
|
ssh_key_type
|
||||||
|
ssh_key_type_from_name
|
||||||
|
ssh_key_type_to_char
|
||||||
|
ssh_known_hosts_parse_line
|
||||||
|
ssh_knownhosts_entry_free
|
||||||
|
ssh_log
|
||||||
|
ssh_message_auth_interactive_request
|
||||||
|
ssh_message_auth_kbdint_is_response
|
||||||
|
ssh_message_auth_password
|
||||||
|
ssh_message_auth_pubkey
|
||||||
|
ssh_message_auth_publickey
|
||||||
|
ssh_message_auth_publickey_state
|
||||||
|
ssh_message_auth_reply_pk_ok
|
||||||
|
ssh_message_auth_reply_pk_ok_simple
|
||||||
|
ssh_message_auth_reply_success
|
||||||
|
ssh_message_auth_set_methods
|
||||||
|
ssh_message_auth_user
|
||||||
|
ssh_message_channel_request_channel
|
||||||
|
ssh_message_channel_request_command
|
||||||
|
ssh_message_channel_request_env_name
|
||||||
|
ssh_message_channel_request_env_value
|
||||||
|
ssh_message_channel_request_open_destination
|
||||||
|
ssh_message_channel_request_open_destination_port
|
||||||
|
ssh_message_channel_request_open_originator
|
||||||
|
ssh_message_channel_request_open_originator_port
|
||||||
|
ssh_message_channel_request_open_reply_accept
|
||||||
|
ssh_message_channel_request_open_reply_accept_channel
|
||||||
|
ssh_message_channel_request_pty_height
|
||||||
|
ssh_message_channel_request_pty_pxheight
|
||||||
|
ssh_message_channel_request_pty_pxwidth
|
||||||
|
ssh_message_channel_request_pty_term
|
||||||
|
ssh_message_channel_request_pty_width
|
||||||
|
ssh_message_channel_request_reply_success
|
||||||
|
ssh_message_channel_request_subsystem
|
||||||
|
ssh_message_channel_request_x11_auth_cookie
|
||||||
|
ssh_message_channel_request_x11_auth_protocol
|
||||||
|
ssh_message_channel_request_x11_screen_number
|
||||||
|
ssh_message_channel_request_x11_single_connection
|
||||||
|
ssh_message_free
|
||||||
|
ssh_message_get
|
||||||
|
ssh_message_global_request_address
|
||||||
|
ssh_message_global_request_port
|
||||||
|
ssh_message_global_request_reply_success
|
||||||
|
ssh_message_reply_default
|
||||||
|
ssh_message_retrieve
|
||||||
|
ssh_message_service_reply_success
|
||||||
|
ssh_message_service_service
|
||||||
|
ssh_message_subtype
|
||||||
|
ssh_message_type
|
||||||
|
ssh_mkdir
|
||||||
|
ssh_new
|
||||||
|
ssh_options_copy
|
||||||
|
ssh_options_get
|
||||||
|
ssh_options_get_port
|
||||||
|
ssh_options_getopt
|
||||||
|
ssh_options_parse_config
|
||||||
|
ssh_options_set
|
||||||
|
ssh_pcap_file_close
|
||||||
|
ssh_pcap_file_free
|
||||||
|
ssh_pcap_file_new
|
||||||
|
ssh_pcap_file_open
|
||||||
|
ssh_pki_copy_cert_to_privkey
|
||||||
|
ssh_pki_export_privkey_base64
|
||||||
|
ssh_pki_export_privkey_file
|
||||||
|
ssh_pki_export_privkey_to_pubkey
|
||||||
|
ssh_pki_export_pubkey_base64
|
||||||
|
ssh_pki_export_pubkey_file
|
||||||
|
ssh_pki_generate
|
||||||
|
ssh_pki_import_cert_base64
|
||||||
|
ssh_pki_import_cert_file
|
||||||
|
ssh_pki_import_privkey_base64
|
||||||
|
ssh_pki_import_privkey_file
|
||||||
|
ssh_pki_import_pubkey_base64
|
||||||
|
ssh_pki_import_pubkey_file
|
||||||
|
ssh_pki_key_ecdsa_name
|
||||||
|
ssh_print_hash
|
||||||
|
ssh_print_hexa
|
||||||
|
ssh_privatekey_type
|
||||||
|
ssh_publickey_to_file
|
||||||
|
ssh_remove_channel_callbacks
|
||||||
|
ssh_scp_accept_request
|
||||||
|
ssh_scp_close
|
||||||
|
ssh_scp_deny_request
|
||||||
|
ssh_scp_free
|
||||||
|
ssh_scp_init
|
||||||
|
ssh_scp_leave_directory
|
||||||
|
ssh_scp_new
|
||||||
|
ssh_scp_pull_request
|
||||||
|
ssh_scp_push_directory
|
||||||
|
ssh_scp_push_file
|
||||||
|
ssh_scp_push_file64
|
||||||
|
ssh_scp_read
|
||||||
|
ssh_scp_request_get_filename
|
||||||
|
ssh_scp_request_get_permissions
|
||||||
|
ssh_scp_request_get_size
|
||||||
|
ssh_scp_request_get_size64
|
||||||
|
ssh_scp_request_get_warning
|
||||||
|
ssh_scp_write
|
||||||
|
ssh_select
|
||||||
|
ssh_send_debug
|
||||||
|
ssh_send_ignore
|
||||||
|
ssh_send_keepalive
|
||||||
|
ssh_server_init_kex
|
||||||
|
ssh_service_request
|
||||||
|
ssh_session_export_known_hosts_entry
|
||||||
|
ssh_session_get_known_hosts_entry
|
||||||
|
ssh_session_has_known_hosts_entry
|
||||||
|
ssh_session_is_known_server
|
||||||
|
ssh_session_update_known_hosts
|
||||||
|
ssh_set_agent_channel
|
||||||
|
ssh_set_agent_socket
|
||||||
|
ssh_set_auth_methods
|
||||||
|
ssh_set_blocking
|
||||||
|
ssh_set_callbacks
|
||||||
|
ssh_set_channel_callbacks
|
||||||
|
ssh_set_counters
|
||||||
|
ssh_set_fd_except
|
||||||
|
ssh_set_fd_toread
|
||||||
|
ssh_set_fd_towrite
|
||||||
|
ssh_set_log_callback
|
||||||
|
ssh_set_log_level
|
||||||
|
ssh_set_log_userdata
|
||||||
|
ssh_set_message_callback
|
||||||
|
ssh_set_pcap_file
|
||||||
|
ssh_set_server_callbacks
|
||||||
|
ssh_silent_disconnect
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_get_char
|
||||||
|
ssh_string_len
|
||||||
|
ssh_string_new
|
||||||
|
ssh_string_to_char
|
||||||
|
ssh_threads_get_default
|
||||||
|
ssh_threads_get_noop
|
||||||
|
ssh_threads_get_pthread
|
||||||
|
ssh_threads_set_callbacks
|
||||||
|
ssh_try_publickey_from_file
|
||||||
|
ssh_userauth_agent
|
||||||
|
ssh_userauth_agent_pubkey
|
||||||
|
ssh_userauth_autopubkey
|
||||||
|
ssh_userauth_gssapi
|
||||||
|
ssh_userauth_kbdint
|
||||||
|
ssh_userauth_kbdint_getanswer
|
||||||
|
ssh_userauth_kbdint_getinstruction
|
||||||
|
ssh_userauth_kbdint_getname
|
||||||
|
ssh_userauth_kbdint_getnanswers
|
||||||
|
ssh_userauth_kbdint_getnprompts
|
||||||
|
ssh_userauth_kbdint_getprompt
|
||||||
|
ssh_userauth_kbdint_setanswer
|
||||||
|
ssh_userauth_list
|
||||||
|
ssh_userauth_none
|
||||||
|
ssh_userauth_offer_pubkey
|
||||||
|
ssh_userauth_password
|
||||||
|
ssh_userauth_privatekey_file
|
||||||
|
ssh_userauth_pubkey
|
||||||
|
ssh_userauth_publickey
|
||||||
|
ssh_userauth_publickey_auto
|
||||||
|
ssh_userauth_try_publickey
|
||||||
|
ssh_version
|
||||||
|
ssh_write_knownhost
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
421
src/ABI/libssh-4.8.6.symbols
Normal file
421
src/ABI/libssh-4.8.6.symbols
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
_ssh_log
|
||||||
|
buffer_free
|
||||||
|
buffer_get
|
||||||
|
buffer_get_len
|
||||||
|
buffer_new
|
||||||
|
channel_accept_x11
|
||||||
|
channel_change_pty_size
|
||||||
|
channel_close
|
||||||
|
channel_forward_accept
|
||||||
|
channel_forward_cancel
|
||||||
|
channel_forward_listen
|
||||||
|
channel_free
|
||||||
|
channel_get_exit_status
|
||||||
|
channel_get_session
|
||||||
|
channel_is_closed
|
||||||
|
channel_is_eof
|
||||||
|
channel_is_open
|
||||||
|
channel_new
|
||||||
|
channel_open_forward
|
||||||
|
channel_open_session
|
||||||
|
channel_poll
|
||||||
|
channel_read
|
||||||
|
channel_read_buffer
|
||||||
|
channel_read_nonblocking
|
||||||
|
channel_request_env
|
||||||
|
channel_request_exec
|
||||||
|
channel_request_pty
|
||||||
|
channel_request_pty_size
|
||||||
|
channel_request_send_signal
|
||||||
|
channel_request_sftp
|
||||||
|
channel_request_shell
|
||||||
|
channel_request_subsystem
|
||||||
|
channel_request_x11
|
||||||
|
channel_select
|
||||||
|
channel_send_eof
|
||||||
|
channel_set_blocking
|
||||||
|
channel_write
|
||||||
|
channel_write_stderr
|
||||||
|
privatekey_free
|
||||||
|
privatekey_from_file
|
||||||
|
publickey_free
|
||||||
|
publickey_from_file
|
||||||
|
publickey_from_privatekey
|
||||||
|
publickey_to_string
|
||||||
|
sftp_async_read
|
||||||
|
sftp_async_read_begin
|
||||||
|
sftp_attributes_free
|
||||||
|
sftp_canonicalize_path
|
||||||
|
sftp_chmod
|
||||||
|
sftp_chown
|
||||||
|
sftp_client_message_free
|
||||||
|
sftp_client_message_get_data
|
||||||
|
sftp_client_message_get_filename
|
||||||
|
sftp_client_message_get_flags
|
||||||
|
sftp_client_message_get_submessage
|
||||||
|
sftp_client_message_get_type
|
||||||
|
sftp_client_message_set_filename
|
||||||
|
sftp_close
|
||||||
|
sftp_closedir
|
||||||
|
sftp_dir_eof
|
||||||
|
sftp_extension_supported
|
||||||
|
sftp_extensions_get_count
|
||||||
|
sftp_extensions_get_data
|
||||||
|
sftp_extensions_get_name
|
||||||
|
sftp_file_set_blocking
|
||||||
|
sftp_file_set_nonblocking
|
||||||
|
sftp_free
|
||||||
|
sftp_fstat
|
||||||
|
sftp_fstatvfs
|
||||||
|
sftp_fsync
|
||||||
|
sftp_get_client_message
|
||||||
|
sftp_get_error
|
||||||
|
sftp_handle
|
||||||
|
sftp_handle_alloc
|
||||||
|
sftp_handle_remove
|
||||||
|
sftp_init
|
||||||
|
sftp_lstat
|
||||||
|
sftp_mkdir
|
||||||
|
sftp_new
|
||||||
|
sftp_new_channel
|
||||||
|
sftp_open
|
||||||
|
sftp_opendir
|
||||||
|
sftp_read
|
||||||
|
sftp_readdir
|
||||||
|
sftp_readlink
|
||||||
|
sftp_rename
|
||||||
|
sftp_reply_attr
|
||||||
|
sftp_reply_data
|
||||||
|
sftp_reply_handle
|
||||||
|
sftp_reply_name
|
||||||
|
sftp_reply_names
|
||||||
|
sftp_reply_names_add
|
||||||
|
sftp_reply_status
|
||||||
|
sftp_rewind
|
||||||
|
sftp_rmdir
|
||||||
|
sftp_seek
|
||||||
|
sftp_seek64
|
||||||
|
sftp_send_client_message
|
||||||
|
sftp_server_free
|
||||||
|
sftp_server_init
|
||||||
|
sftp_server_new
|
||||||
|
sftp_server_version
|
||||||
|
sftp_setstat
|
||||||
|
sftp_stat
|
||||||
|
sftp_statvfs
|
||||||
|
sftp_statvfs_free
|
||||||
|
sftp_symlink
|
||||||
|
sftp_tell
|
||||||
|
sftp_tell64
|
||||||
|
sftp_unlink
|
||||||
|
sftp_utimes
|
||||||
|
sftp_write
|
||||||
|
ssh_accept
|
||||||
|
ssh_add_channel_callbacks
|
||||||
|
ssh_auth_list
|
||||||
|
ssh_basename
|
||||||
|
ssh_bind_accept
|
||||||
|
ssh_bind_accept_fd
|
||||||
|
ssh_bind_fd_toaccept
|
||||||
|
ssh_bind_free
|
||||||
|
ssh_bind_get_fd
|
||||||
|
ssh_bind_listen
|
||||||
|
ssh_bind_new
|
||||||
|
ssh_bind_options_parse_config
|
||||||
|
ssh_bind_options_set
|
||||||
|
ssh_bind_set_blocking
|
||||||
|
ssh_bind_set_callbacks
|
||||||
|
ssh_bind_set_fd
|
||||||
|
ssh_blocking_flush
|
||||||
|
ssh_buffer_add_data
|
||||||
|
ssh_buffer_free
|
||||||
|
ssh_buffer_get
|
||||||
|
ssh_buffer_get_data
|
||||||
|
ssh_buffer_get_len
|
||||||
|
ssh_buffer_new
|
||||||
|
ssh_buffer_reinit
|
||||||
|
ssh_channel_accept_forward
|
||||||
|
ssh_channel_accept_x11
|
||||||
|
ssh_channel_cancel_forward
|
||||||
|
ssh_channel_change_pty_size
|
||||||
|
ssh_channel_close
|
||||||
|
ssh_channel_free
|
||||||
|
ssh_channel_get_exit_status
|
||||||
|
ssh_channel_get_session
|
||||||
|
ssh_channel_is_closed
|
||||||
|
ssh_channel_is_eof
|
||||||
|
ssh_channel_is_open
|
||||||
|
ssh_channel_listen_forward
|
||||||
|
ssh_channel_new
|
||||||
|
ssh_channel_open_auth_agent
|
||||||
|
ssh_channel_open_forward
|
||||||
|
ssh_channel_open_forward_unix
|
||||||
|
ssh_channel_open_reverse_forward
|
||||||
|
ssh_channel_open_session
|
||||||
|
ssh_channel_open_x11
|
||||||
|
ssh_channel_poll
|
||||||
|
ssh_channel_poll_timeout
|
||||||
|
ssh_channel_read
|
||||||
|
ssh_channel_read_nonblocking
|
||||||
|
ssh_channel_read_timeout
|
||||||
|
ssh_channel_request_auth_agent
|
||||||
|
ssh_channel_request_env
|
||||||
|
ssh_channel_request_exec
|
||||||
|
ssh_channel_request_pty
|
||||||
|
ssh_channel_request_pty_size
|
||||||
|
ssh_channel_request_send_break
|
||||||
|
ssh_channel_request_send_exit_signal
|
||||||
|
ssh_channel_request_send_exit_status
|
||||||
|
ssh_channel_request_send_signal
|
||||||
|
ssh_channel_request_sftp
|
||||||
|
ssh_channel_request_shell
|
||||||
|
ssh_channel_request_subsystem
|
||||||
|
ssh_channel_request_x11
|
||||||
|
ssh_channel_select
|
||||||
|
ssh_channel_send_eof
|
||||||
|
ssh_channel_set_blocking
|
||||||
|
ssh_channel_set_counter
|
||||||
|
ssh_channel_window_size
|
||||||
|
ssh_channel_write
|
||||||
|
ssh_channel_write_stderr
|
||||||
|
ssh_clean_pubkey_hash
|
||||||
|
ssh_connect
|
||||||
|
ssh_connector_free
|
||||||
|
ssh_connector_new
|
||||||
|
ssh_connector_set_in_channel
|
||||||
|
ssh_connector_set_in_fd
|
||||||
|
ssh_connector_set_out_channel
|
||||||
|
ssh_connector_set_out_fd
|
||||||
|
ssh_copyright
|
||||||
|
ssh_dirname
|
||||||
|
ssh_disconnect
|
||||||
|
ssh_dump_knownhost
|
||||||
|
ssh_event_add_connector
|
||||||
|
ssh_event_add_fd
|
||||||
|
ssh_event_add_session
|
||||||
|
ssh_event_dopoll
|
||||||
|
ssh_event_free
|
||||||
|
ssh_event_new
|
||||||
|
ssh_event_remove_connector
|
||||||
|
ssh_event_remove_fd
|
||||||
|
ssh_event_remove_session
|
||||||
|
ssh_execute_message_callbacks
|
||||||
|
ssh_finalize
|
||||||
|
ssh_forward_accept
|
||||||
|
ssh_forward_cancel
|
||||||
|
ssh_forward_listen
|
||||||
|
ssh_free
|
||||||
|
ssh_get_cipher_in
|
||||||
|
ssh_get_cipher_out
|
||||||
|
ssh_get_clientbanner
|
||||||
|
ssh_get_disconnect_message
|
||||||
|
ssh_get_error
|
||||||
|
ssh_get_error_code
|
||||||
|
ssh_get_fd
|
||||||
|
ssh_get_fingerprint_hash
|
||||||
|
ssh_get_hexa
|
||||||
|
ssh_get_hmac_in
|
||||||
|
ssh_get_hmac_out
|
||||||
|
ssh_get_issue_banner
|
||||||
|
ssh_get_kex_algo
|
||||||
|
ssh_get_log_callback
|
||||||
|
ssh_get_log_level
|
||||||
|
ssh_get_log_userdata
|
||||||
|
ssh_get_openssh_version
|
||||||
|
ssh_get_poll_flags
|
||||||
|
ssh_get_pubkey
|
||||||
|
ssh_get_pubkey_hash
|
||||||
|
ssh_get_publickey
|
||||||
|
ssh_get_publickey_hash
|
||||||
|
ssh_get_random
|
||||||
|
ssh_get_server_publickey
|
||||||
|
ssh_get_serverbanner
|
||||||
|
ssh_get_status
|
||||||
|
ssh_get_version
|
||||||
|
ssh_getpass
|
||||||
|
ssh_gssapi_get_creds
|
||||||
|
ssh_gssapi_set_creds
|
||||||
|
ssh_handle_key_exchange
|
||||||
|
ssh_init
|
||||||
|
ssh_is_blocking
|
||||||
|
ssh_is_connected
|
||||||
|
ssh_is_server_known
|
||||||
|
ssh_key_cmp
|
||||||
|
ssh_key_free
|
||||||
|
ssh_key_is_private
|
||||||
|
ssh_key_is_public
|
||||||
|
ssh_key_new
|
||||||
|
ssh_key_type
|
||||||
|
ssh_key_type_from_name
|
||||||
|
ssh_key_type_to_char
|
||||||
|
ssh_known_hosts_parse_line
|
||||||
|
ssh_knownhosts_entry_free
|
||||||
|
ssh_log
|
||||||
|
ssh_message_auth_interactive_request
|
||||||
|
ssh_message_auth_kbdint_is_response
|
||||||
|
ssh_message_auth_password
|
||||||
|
ssh_message_auth_pubkey
|
||||||
|
ssh_message_auth_publickey
|
||||||
|
ssh_message_auth_publickey_state
|
||||||
|
ssh_message_auth_reply_pk_ok
|
||||||
|
ssh_message_auth_reply_pk_ok_simple
|
||||||
|
ssh_message_auth_reply_success
|
||||||
|
ssh_message_auth_set_methods
|
||||||
|
ssh_message_auth_user
|
||||||
|
ssh_message_channel_request_channel
|
||||||
|
ssh_message_channel_request_command
|
||||||
|
ssh_message_channel_request_env_name
|
||||||
|
ssh_message_channel_request_env_value
|
||||||
|
ssh_message_channel_request_open_destination
|
||||||
|
ssh_message_channel_request_open_destination_port
|
||||||
|
ssh_message_channel_request_open_originator
|
||||||
|
ssh_message_channel_request_open_originator_port
|
||||||
|
ssh_message_channel_request_open_reply_accept
|
||||||
|
ssh_message_channel_request_open_reply_accept_channel
|
||||||
|
ssh_message_channel_request_pty_height
|
||||||
|
ssh_message_channel_request_pty_pxheight
|
||||||
|
ssh_message_channel_request_pty_pxwidth
|
||||||
|
ssh_message_channel_request_pty_term
|
||||||
|
ssh_message_channel_request_pty_width
|
||||||
|
ssh_message_channel_request_reply_success
|
||||||
|
ssh_message_channel_request_subsystem
|
||||||
|
ssh_message_channel_request_x11_auth_cookie
|
||||||
|
ssh_message_channel_request_x11_auth_protocol
|
||||||
|
ssh_message_channel_request_x11_screen_number
|
||||||
|
ssh_message_channel_request_x11_single_connection
|
||||||
|
ssh_message_free
|
||||||
|
ssh_message_get
|
||||||
|
ssh_message_global_request_address
|
||||||
|
ssh_message_global_request_port
|
||||||
|
ssh_message_global_request_reply_success
|
||||||
|
ssh_message_reply_default
|
||||||
|
ssh_message_retrieve
|
||||||
|
ssh_message_service_reply_success
|
||||||
|
ssh_message_service_service
|
||||||
|
ssh_message_subtype
|
||||||
|
ssh_message_type
|
||||||
|
ssh_mkdir
|
||||||
|
ssh_new
|
||||||
|
ssh_options_copy
|
||||||
|
ssh_options_get
|
||||||
|
ssh_options_get_port
|
||||||
|
ssh_options_getopt
|
||||||
|
ssh_options_parse_config
|
||||||
|
ssh_options_set
|
||||||
|
ssh_pcap_file_close
|
||||||
|
ssh_pcap_file_free
|
||||||
|
ssh_pcap_file_new
|
||||||
|
ssh_pcap_file_open
|
||||||
|
ssh_pki_copy_cert_to_privkey
|
||||||
|
ssh_pki_export_privkey_base64
|
||||||
|
ssh_pki_export_privkey_file
|
||||||
|
ssh_pki_export_privkey_to_pubkey
|
||||||
|
ssh_pki_export_pubkey_base64
|
||||||
|
ssh_pki_export_pubkey_file
|
||||||
|
ssh_pki_generate
|
||||||
|
ssh_pki_import_cert_base64
|
||||||
|
ssh_pki_import_cert_file
|
||||||
|
ssh_pki_import_privkey_base64
|
||||||
|
ssh_pki_import_privkey_file
|
||||||
|
ssh_pki_import_pubkey_base64
|
||||||
|
ssh_pki_import_pubkey_file
|
||||||
|
ssh_pki_key_ecdsa_name
|
||||||
|
ssh_print_hash
|
||||||
|
ssh_print_hexa
|
||||||
|
ssh_privatekey_type
|
||||||
|
ssh_publickey_to_file
|
||||||
|
ssh_remove_channel_callbacks
|
||||||
|
ssh_scp_accept_request
|
||||||
|
ssh_scp_close
|
||||||
|
ssh_scp_deny_request
|
||||||
|
ssh_scp_free
|
||||||
|
ssh_scp_init
|
||||||
|
ssh_scp_leave_directory
|
||||||
|
ssh_scp_new
|
||||||
|
ssh_scp_pull_request
|
||||||
|
ssh_scp_push_directory
|
||||||
|
ssh_scp_push_file
|
||||||
|
ssh_scp_push_file64
|
||||||
|
ssh_scp_read
|
||||||
|
ssh_scp_request_get_filename
|
||||||
|
ssh_scp_request_get_permissions
|
||||||
|
ssh_scp_request_get_size
|
||||||
|
ssh_scp_request_get_size64
|
||||||
|
ssh_scp_request_get_warning
|
||||||
|
ssh_scp_write
|
||||||
|
ssh_select
|
||||||
|
ssh_send_debug
|
||||||
|
ssh_send_ignore
|
||||||
|
ssh_send_keepalive
|
||||||
|
ssh_server_init_kex
|
||||||
|
ssh_service_request
|
||||||
|
ssh_session_export_known_hosts_entry
|
||||||
|
ssh_session_get_known_hosts_entry
|
||||||
|
ssh_session_has_known_hosts_entry
|
||||||
|
ssh_session_is_known_server
|
||||||
|
ssh_session_update_known_hosts
|
||||||
|
ssh_set_agent_channel
|
||||||
|
ssh_set_agent_socket
|
||||||
|
ssh_set_auth_methods
|
||||||
|
ssh_set_blocking
|
||||||
|
ssh_set_callbacks
|
||||||
|
ssh_set_channel_callbacks
|
||||||
|
ssh_set_counters
|
||||||
|
ssh_set_fd_except
|
||||||
|
ssh_set_fd_toread
|
||||||
|
ssh_set_fd_towrite
|
||||||
|
ssh_set_log_callback
|
||||||
|
ssh_set_log_level
|
||||||
|
ssh_set_log_userdata
|
||||||
|
ssh_set_message_callback
|
||||||
|
ssh_set_pcap_file
|
||||||
|
ssh_set_server_callbacks
|
||||||
|
ssh_silent_disconnect
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_get_char
|
||||||
|
ssh_string_len
|
||||||
|
ssh_string_new
|
||||||
|
ssh_string_to_char
|
||||||
|
ssh_threads_get_default
|
||||||
|
ssh_threads_get_noop
|
||||||
|
ssh_threads_get_pthread
|
||||||
|
ssh_threads_set_callbacks
|
||||||
|
ssh_try_publickey_from_file
|
||||||
|
ssh_userauth_agent
|
||||||
|
ssh_userauth_agent_pubkey
|
||||||
|
ssh_userauth_autopubkey
|
||||||
|
ssh_userauth_gssapi
|
||||||
|
ssh_userauth_kbdint
|
||||||
|
ssh_userauth_kbdint_getanswer
|
||||||
|
ssh_userauth_kbdint_getinstruction
|
||||||
|
ssh_userauth_kbdint_getname
|
||||||
|
ssh_userauth_kbdint_getnanswers
|
||||||
|
ssh_userauth_kbdint_getnprompts
|
||||||
|
ssh_userauth_kbdint_getprompt
|
||||||
|
ssh_userauth_kbdint_setanswer
|
||||||
|
ssh_userauth_list
|
||||||
|
ssh_userauth_none
|
||||||
|
ssh_userauth_offer_pubkey
|
||||||
|
ssh_userauth_password
|
||||||
|
ssh_userauth_privatekey_file
|
||||||
|
ssh_userauth_pubkey
|
||||||
|
ssh_userauth_publickey
|
||||||
|
ssh_userauth_publickey_auto
|
||||||
|
ssh_userauth_try_publickey
|
||||||
|
ssh_version
|
||||||
|
ssh_write_knownhost
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
421
src/ABI/libssh-4.8.7.symbols
Normal file
421
src/ABI/libssh-4.8.7.symbols
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
_ssh_log
|
||||||
|
buffer_free
|
||||||
|
buffer_get
|
||||||
|
buffer_get_len
|
||||||
|
buffer_new
|
||||||
|
channel_accept_x11
|
||||||
|
channel_change_pty_size
|
||||||
|
channel_close
|
||||||
|
channel_forward_accept
|
||||||
|
channel_forward_cancel
|
||||||
|
channel_forward_listen
|
||||||
|
channel_free
|
||||||
|
channel_get_exit_status
|
||||||
|
channel_get_session
|
||||||
|
channel_is_closed
|
||||||
|
channel_is_eof
|
||||||
|
channel_is_open
|
||||||
|
channel_new
|
||||||
|
channel_open_forward
|
||||||
|
channel_open_session
|
||||||
|
channel_poll
|
||||||
|
channel_read
|
||||||
|
channel_read_buffer
|
||||||
|
channel_read_nonblocking
|
||||||
|
channel_request_env
|
||||||
|
channel_request_exec
|
||||||
|
channel_request_pty
|
||||||
|
channel_request_pty_size
|
||||||
|
channel_request_send_signal
|
||||||
|
channel_request_sftp
|
||||||
|
channel_request_shell
|
||||||
|
channel_request_subsystem
|
||||||
|
channel_request_x11
|
||||||
|
channel_select
|
||||||
|
channel_send_eof
|
||||||
|
channel_set_blocking
|
||||||
|
channel_write
|
||||||
|
channel_write_stderr
|
||||||
|
privatekey_free
|
||||||
|
privatekey_from_file
|
||||||
|
publickey_free
|
||||||
|
publickey_from_file
|
||||||
|
publickey_from_privatekey
|
||||||
|
publickey_to_string
|
||||||
|
sftp_async_read
|
||||||
|
sftp_async_read_begin
|
||||||
|
sftp_attributes_free
|
||||||
|
sftp_canonicalize_path
|
||||||
|
sftp_chmod
|
||||||
|
sftp_chown
|
||||||
|
sftp_client_message_free
|
||||||
|
sftp_client_message_get_data
|
||||||
|
sftp_client_message_get_filename
|
||||||
|
sftp_client_message_get_flags
|
||||||
|
sftp_client_message_get_submessage
|
||||||
|
sftp_client_message_get_type
|
||||||
|
sftp_client_message_set_filename
|
||||||
|
sftp_close
|
||||||
|
sftp_closedir
|
||||||
|
sftp_dir_eof
|
||||||
|
sftp_extension_supported
|
||||||
|
sftp_extensions_get_count
|
||||||
|
sftp_extensions_get_data
|
||||||
|
sftp_extensions_get_name
|
||||||
|
sftp_file_set_blocking
|
||||||
|
sftp_file_set_nonblocking
|
||||||
|
sftp_free
|
||||||
|
sftp_fstat
|
||||||
|
sftp_fstatvfs
|
||||||
|
sftp_fsync
|
||||||
|
sftp_get_client_message
|
||||||
|
sftp_get_error
|
||||||
|
sftp_handle
|
||||||
|
sftp_handle_alloc
|
||||||
|
sftp_handle_remove
|
||||||
|
sftp_init
|
||||||
|
sftp_lstat
|
||||||
|
sftp_mkdir
|
||||||
|
sftp_new
|
||||||
|
sftp_new_channel
|
||||||
|
sftp_open
|
||||||
|
sftp_opendir
|
||||||
|
sftp_read
|
||||||
|
sftp_readdir
|
||||||
|
sftp_readlink
|
||||||
|
sftp_rename
|
||||||
|
sftp_reply_attr
|
||||||
|
sftp_reply_data
|
||||||
|
sftp_reply_handle
|
||||||
|
sftp_reply_name
|
||||||
|
sftp_reply_names
|
||||||
|
sftp_reply_names_add
|
||||||
|
sftp_reply_status
|
||||||
|
sftp_rewind
|
||||||
|
sftp_rmdir
|
||||||
|
sftp_seek
|
||||||
|
sftp_seek64
|
||||||
|
sftp_send_client_message
|
||||||
|
sftp_server_free
|
||||||
|
sftp_server_init
|
||||||
|
sftp_server_new
|
||||||
|
sftp_server_version
|
||||||
|
sftp_setstat
|
||||||
|
sftp_stat
|
||||||
|
sftp_statvfs
|
||||||
|
sftp_statvfs_free
|
||||||
|
sftp_symlink
|
||||||
|
sftp_tell
|
||||||
|
sftp_tell64
|
||||||
|
sftp_unlink
|
||||||
|
sftp_utimes
|
||||||
|
sftp_write
|
||||||
|
ssh_accept
|
||||||
|
ssh_add_channel_callbacks
|
||||||
|
ssh_auth_list
|
||||||
|
ssh_basename
|
||||||
|
ssh_bind_accept
|
||||||
|
ssh_bind_accept_fd
|
||||||
|
ssh_bind_fd_toaccept
|
||||||
|
ssh_bind_free
|
||||||
|
ssh_bind_get_fd
|
||||||
|
ssh_bind_listen
|
||||||
|
ssh_bind_new
|
||||||
|
ssh_bind_options_parse_config
|
||||||
|
ssh_bind_options_set
|
||||||
|
ssh_bind_set_blocking
|
||||||
|
ssh_bind_set_callbacks
|
||||||
|
ssh_bind_set_fd
|
||||||
|
ssh_blocking_flush
|
||||||
|
ssh_buffer_add_data
|
||||||
|
ssh_buffer_free
|
||||||
|
ssh_buffer_get
|
||||||
|
ssh_buffer_get_data
|
||||||
|
ssh_buffer_get_len
|
||||||
|
ssh_buffer_new
|
||||||
|
ssh_buffer_reinit
|
||||||
|
ssh_channel_accept_forward
|
||||||
|
ssh_channel_accept_x11
|
||||||
|
ssh_channel_cancel_forward
|
||||||
|
ssh_channel_change_pty_size
|
||||||
|
ssh_channel_close
|
||||||
|
ssh_channel_free
|
||||||
|
ssh_channel_get_exit_status
|
||||||
|
ssh_channel_get_session
|
||||||
|
ssh_channel_is_closed
|
||||||
|
ssh_channel_is_eof
|
||||||
|
ssh_channel_is_open
|
||||||
|
ssh_channel_listen_forward
|
||||||
|
ssh_channel_new
|
||||||
|
ssh_channel_open_auth_agent
|
||||||
|
ssh_channel_open_forward
|
||||||
|
ssh_channel_open_forward_unix
|
||||||
|
ssh_channel_open_reverse_forward
|
||||||
|
ssh_channel_open_session
|
||||||
|
ssh_channel_open_x11
|
||||||
|
ssh_channel_poll
|
||||||
|
ssh_channel_poll_timeout
|
||||||
|
ssh_channel_read
|
||||||
|
ssh_channel_read_nonblocking
|
||||||
|
ssh_channel_read_timeout
|
||||||
|
ssh_channel_request_auth_agent
|
||||||
|
ssh_channel_request_env
|
||||||
|
ssh_channel_request_exec
|
||||||
|
ssh_channel_request_pty
|
||||||
|
ssh_channel_request_pty_size
|
||||||
|
ssh_channel_request_send_break
|
||||||
|
ssh_channel_request_send_exit_signal
|
||||||
|
ssh_channel_request_send_exit_status
|
||||||
|
ssh_channel_request_send_signal
|
||||||
|
ssh_channel_request_sftp
|
||||||
|
ssh_channel_request_shell
|
||||||
|
ssh_channel_request_subsystem
|
||||||
|
ssh_channel_request_x11
|
||||||
|
ssh_channel_select
|
||||||
|
ssh_channel_send_eof
|
||||||
|
ssh_channel_set_blocking
|
||||||
|
ssh_channel_set_counter
|
||||||
|
ssh_channel_window_size
|
||||||
|
ssh_channel_write
|
||||||
|
ssh_channel_write_stderr
|
||||||
|
ssh_clean_pubkey_hash
|
||||||
|
ssh_connect
|
||||||
|
ssh_connector_free
|
||||||
|
ssh_connector_new
|
||||||
|
ssh_connector_set_in_channel
|
||||||
|
ssh_connector_set_in_fd
|
||||||
|
ssh_connector_set_out_channel
|
||||||
|
ssh_connector_set_out_fd
|
||||||
|
ssh_copyright
|
||||||
|
ssh_dirname
|
||||||
|
ssh_disconnect
|
||||||
|
ssh_dump_knownhost
|
||||||
|
ssh_event_add_connector
|
||||||
|
ssh_event_add_fd
|
||||||
|
ssh_event_add_session
|
||||||
|
ssh_event_dopoll
|
||||||
|
ssh_event_free
|
||||||
|
ssh_event_new
|
||||||
|
ssh_event_remove_connector
|
||||||
|
ssh_event_remove_fd
|
||||||
|
ssh_event_remove_session
|
||||||
|
ssh_execute_message_callbacks
|
||||||
|
ssh_finalize
|
||||||
|
ssh_forward_accept
|
||||||
|
ssh_forward_cancel
|
||||||
|
ssh_forward_listen
|
||||||
|
ssh_free
|
||||||
|
ssh_get_cipher_in
|
||||||
|
ssh_get_cipher_out
|
||||||
|
ssh_get_clientbanner
|
||||||
|
ssh_get_disconnect_message
|
||||||
|
ssh_get_error
|
||||||
|
ssh_get_error_code
|
||||||
|
ssh_get_fd
|
||||||
|
ssh_get_fingerprint_hash
|
||||||
|
ssh_get_hexa
|
||||||
|
ssh_get_hmac_in
|
||||||
|
ssh_get_hmac_out
|
||||||
|
ssh_get_issue_banner
|
||||||
|
ssh_get_kex_algo
|
||||||
|
ssh_get_log_callback
|
||||||
|
ssh_get_log_level
|
||||||
|
ssh_get_log_userdata
|
||||||
|
ssh_get_openssh_version
|
||||||
|
ssh_get_poll_flags
|
||||||
|
ssh_get_pubkey
|
||||||
|
ssh_get_pubkey_hash
|
||||||
|
ssh_get_publickey
|
||||||
|
ssh_get_publickey_hash
|
||||||
|
ssh_get_random
|
||||||
|
ssh_get_server_publickey
|
||||||
|
ssh_get_serverbanner
|
||||||
|
ssh_get_status
|
||||||
|
ssh_get_version
|
||||||
|
ssh_getpass
|
||||||
|
ssh_gssapi_get_creds
|
||||||
|
ssh_gssapi_set_creds
|
||||||
|
ssh_handle_key_exchange
|
||||||
|
ssh_init
|
||||||
|
ssh_is_blocking
|
||||||
|
ssh_is_connected
|
||||||
|
ssh_is_server_known
|
||||||
|
ssh_key_cmp
|
||||||
|
ssh_key_free
|
||||||
|
ssh_key_is_private
|
||||||
|
ssh_key_is_public
|
||||||
|
ssh_key_new
|
||||||
|
ssh_key_type
|
||||||
|
ssh_key_type_from_name
|
||||||
|
ssh_key_type_to_char
|
||||||
|
ssh_known_hosts_parse_line
|
||||||
|
ssh_knownhosts_entry_free
|
||||||
|
ssh_log
|
||||||
|
ssh_message_auth_interactive_request
|
||||||
|
ssh_message_auth_kbdint_is_response
|
||||||
|
ssh_message_auth_password
|
||||||
|
ssh_message_auth_pubkey
|
||||||
|
ssh_message_auth_publickey
|
||||||
|
ssh_message_auth_publickey_state
|
||||||
|
ssh_message_auth_reply_pk_ok
|
||||||
|
ssh_message_auth_reply_pk_ok_simple
|
||||||
|
ssh_message_auth_reply_success
|
||||||
|
ssh_message_auth_set_methods
|
||||||
|
ssh_message_auth_user
|
||||||
|
ssh_message_channel_request_channel
|
||||||
|
ssh_message_channel_request_command
|
||||||
|
ssh_message_channel_request_env_name
|
||||||
|
ssh_message_channel_request_env_value
|
||||||
|
ssh_message_channel_request_open_destination
|
||||||
|
ssh_message_channel_request_open_destination_port
|
||||||
|
ssh_message_channel_request_open_originator
|
||||||
|
ssh_message_channel_request_open_originator_port
|
||||||
|
ssh_message_channel_request_open_reply_accept
|
||||||
|
ssh_message_channel_request_open_reply_accept_channel
|
||||||
|
ssh_message_channel_request_pty_height
|
||||||
|
ssh_message_channel_request_pty_pxheight
|
||||||
|
ssh_message_channel_request_pty_pxwidth
|
||||||
|
ssh_message_channel_request_pty_term
|
||||||
|
ssh_message_channel_request_pty_width
|
||||||
|
ssh_message_channel_request_reply_success
|
||||||
|
ssh_message_channel_request_subsystem
|
||||||
|
ssh_message_channel_request_x11_auth_cookie
|
||||||
|
ssh_message_channel_request_x11_auth_protocol
|
||||||
|
ssh_message_channel_request_x11_screen_number
|
||||||
|
ssh_message_channel_request_x11_single_connection
|
||||||
|
ssh_message_free
|
||||||
|
ssh_message_get
|
||||||
|
ssh_message_global_request_address
|
||||||
|
ssh_message_global_request_port
|
||||||
|
ssh_message_global_request_reply_success
|
||||||
|
ssh_message_reply_default
|
||||||
|
ssh_message_retrieve
|
||||||
|
ssh_message_service_reply_success
|
||||||
|
ssh_message_service_service
|
||||||
|
ssh_message_subtype
|
||||||
|
ssh_message_type
|
||||||
|
ssh_mkdir
|
||||||
|
ssh_new
|
||||||
|
ssh_options_copy
|
||||||
|
ssh_options_get
|
||||||
|
ssh_options_get_port
|
||||||
|
ssh_options_getopt
|
||||||
|
ssh_options_parse_config
|
||||||
|
ssh_options_set
|
||||||
|
ssh_pcap_file_close
|
||||||
|
ssh_pcap_file_free
|
||||||
|
ssh_pcap_file_new
|
||||||
|
ssh_pcap_file_open
|
||||||
|
ssh_pki_copy_cert_to_privkey
|
||||||
|
ssh_pki_export_privkey_base64
|
||||||
|
ssh_pki_export_privkey_file
|
||||||
|
ssh_pki_export_privkey_to_pubkey
|
||||||
|
ssh_pki_export_pubkey_base64
|
||||||
|
ssh_pki_export_pubkey_file
|
||||||
|
ssh_pki_generate
|
||||||
|
ssh_pki_import_cert_base64
|
||||||
|
ssh_pki_import_cert_file
|
||||||
|
ssh_pki_import_privkey_base64
|
||||||
|
ssh_pki_import_privkey_file
|
||||||
|
ssh_pki_import_pubkey_base64
|
||||||
|
ssh_pki_import_pubkey_file
|
||||||
|
ssh_pki_key_ecdsa_name
|
||||||
|
ssh_print_hash
|
||||||
|
ssh_print_hexa
|
||||||
|
ssh_privatekey_type
|
||||||
|
ssh_publickey_to_file
|
||||||
|
ssh_remove_channel_callbacks
|
||||||
|
ssh_scp_accept_request
|
||||||
|
ssh_scp_close
|
||||||
|
ssh_scp_deny_request
|
||||||
|
ssh_scp_free
|
||||||
|
ssh_scp_init
|
||||||
|
ssh_scp_leave_directory
|
||||||
|
ssh_scp_new
|
||||||
|
ssh_scp_pull_request
|
||||||
|
ssh_scp_push_directory
|
||||||
|
ssh_scp_push_file
|
||||||
|
ssh_scp_push_file64
|
||||||
|
ssh_scp_read
|
||||||
|
ssh_scp_request_get_filename
|
||||||
|
ssh_scp_request_get_permissions
|
||||||
|
ssh_scp_request_get_size
|
||||||
|
ssh_scp_request_get_size64
|
||||||
|
ssh_scp_request_get_warning
|
||||||
|
ssh_scp_write
|
||||||
|
ssh_select
|
||||||
|
ssh_send_debug
|
||||||
|
ssh_send_ignore
|
||||||
|
ssh_send_keepalive
|
||||||
|
ssh_server_init_kex
|
||||||
|
ssh_service_request
|
||||||
|
ssh_session_export_known_hosts_entry
|
||||||
|
ssh_session_get_known_hosts_entry
|
||||||
|
ssh_session_has_known_hosts_entry
|
||||||
|
ssh_session_is_known_server
|
||||||
|
ssh_session_update_known_hosts
|
||||||
|
ssh_set_agent_channel
|
||||||
|
ssh_set_agent_socket
|
||||||
|
ssh_set_auth_methods
|
||||||
|
ssh_set_blocking
|
||||||
|
ssh_set_callbacks
|
||||||
|
ssh_set_channel_callbacks
|
||||||
|
ssh_set_counters
|
||||||
|
ssh_set_fd_except
|
||||||
|
ssh_set_fd_toread
|
||||||
|
ssh_set_fd_towrite
|
||||||
|
ssh_set_log_callback
|
||||||
|
ssh_set_log_level
|
||||||
|
ssh_set_log_userdata
|
||||||
|
ssh_set_message_callback
|
||||||
|
ssh_set_pcap_file
|
||||||
|
ssh_set_server_callbacks
|
||||||
|
ssh_silent_disconnect
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_get_char
|
||||||
|
ssh_string_len
|
||||||
|
ssh_string_new
|
||||||
|
ssh_string_to_char
|
||||||
|
ssh_threads_get_default
|
||||||
|
ssh_threads_get_noop
|
||||||
|
ssh_threads_get_pthread
|
||||||
|
ssh_threads_set_callbacks
|
||||||
|
ssh_try_publickey_from_file
|
||||||
|
ssh_userauth_agent
|
||||||
|
ssh_userauth_agent_pubkey
|
||||||
|
ssh_userauth_autopubkey
|
||||||
|
ssh_userauth_gssapi
|
||||||
|
ssh_userauth_kbdint
|
||||||
|
ssh_userauth_kbdint_getanswer
|
||||||
|
ssh_userauth_kbdint_getinstruction
|
||||||
|
ssh_userauth_kbdint_getname
|
||||||
|
ssh_userauth_kbdint_getnanswers
|
||||||
|
ssh_userauth_kbdint_getnprompts
|
||||||
|
ssh_userauth_kbdint_getprompt
|
||||||
|
ssh_userauth_kbdint_setanswer
|
||||||
|
ssh_userauth_list
|
||||||
|
ssh_userauth_none
|
||||||
|
ssh_userauth_offer_pubkey
|
||||||
|
ssh_userauth_password
|
||||||
|
ssh_userauth_privatekey_file
|
||||||
|
ssh_userauth_pubkey
|
||||||
|
ssh_userauth_publickey
|
||||||
|
ssh_userauth_publickey_auto
|
||||||
|
ssh_userauth_try_publickey
|
||||||
|
ssh_version
|
||||||
|
ssh_write_knownhost
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
421
src/ABI/libssh-4.8.8.symbols
Normal file
421
src/ABI/libssh-4.8.8.symbols
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
_ssh_log
|
||||||
|
buffer_free
|
||||||
|
buffer_get
|
||||||
|
buffer_get_len
|
||||||
|
buffer_new
|
||||||
|
channel_accept_x11
|
||||||
|
channel_change_pty_size
|
||||||
|
channel_close
|
||||||
|
channel_forward_accept
|
||||||
|
channel_forward_cancel
|
||||||
|
channel_forward_listen
|
||||||
|
channel_free
|
||||||
|
channel_get_exit_status
|
||||||
|
channel_get_session
|
||||||
|
channel_is_closed
|
||||||
|
channel_is_eof
|
||||||
|
channel_is_open
|
||||||
|
channel_new
|
||||||
|
channel_open_forward
|
||||||
|
channel_open_session
|
||||||
|
channel_poll
|
||||||
|
channel_read
|
||||||
|
channel_read_buffer
|
||||||
|
channel_read_nonblocking
|
||||||
|
channel_request_env
|
||||||
|
channel_request_exec
|
||||||
|
channel_request_pty
|
||||||
|
channel_request_pty_size
|
||||||
|
channel_request_send_signal
|
||||||
|
channel_request_sftp
|
||||||
|
channel_request_shell
|
||||||
|
channel_request_subsystem
|
||||||
|
channel_request_x11
|
||||||
|
channel_select
|
||||||
|
channel_send_eof
|
||||||
|
channel_set_blocking
|
||||||
|
channel_write
|
||||||
|
channel_write_stderr
|
||||||
|
privatekey_free
|
||||||
|
privatekey_from_file
|
||||||
|
publickey_free
|
||||||
|
publickey_from_file
|
||||||
|
publickey_from_privatekey
|
||||||
|
publickey_to_string
|
||||||
|
sftp_async_read
|
||||||
|
sftp_async_read_begin
|
||||||
|
sftp_attributes_free
|
||||||
|
sftp_canonicalize_path
|
||||||
|
sftp_chmod
|
||||||
|
sftp_chown
|
||||||
|
sftp_client_message_free
|
||||||
|
sftp_client_message_get_data
|
||||||
|
sftp_client_message_get_filename
|
||||||
|
sftp_client_message_get_flags
|
||||||
|
sftp_client_message_get_submessage
|
||||||
|
sftp_client_message_get_type
|
||||||
|
sftp_client_message_set_filename
|
||||||
|
sftp_close
|
||||||
|
sftp_closedir
|
||||||
|
sftp_dir_eof
|
||||||
|
sftp_extension_supported
|
||||||
|
sftp_extensions_get_count
|
||||||
|
sftp_extensions_get_data
|
||||||
|
sftp_extensions_get_name
|
||||||
|
sftp_file_set_blocking
|
||||||
|
sftp_file_set_nonblocking
|
||||||
|
sftp_free
|
||||||
|
sftp_fstat
|
||||||
|
sftp_fstatvfs
|
||||||
|
sftp_fsync
|
||||||
|
sftp_get_client_message
|
||||||
|
sftp_get_error
|
||||||
|
sftp_handle
|
||||||
|
sftp_handle_alloc
|
||||||
|
sftp_handle_remove
|
||||||
|
sftp_init
|
||||||
|
sftp_lstat
|
||||||
|
sftp_mkdir
|
||||||
|
sftp_new
|
||||||
|
sftp_new_channel
|
||||||
|
sftp_open
|
||||||
|
sftp_opendir
|
||||||
|
sftp_read
|
||||||
|
sftp_readdir
|
||||||
|
sftp_readlink
|
||||||
|
sftp_rename
|
||||||
|
sftp_reply_attr
|
||||||
|
sftp_reply_data
|
||||||
|
sftp_reply_handle
|
||||||
|
sftp_reply_name
|
||||||
|
sftp_reply_names
|
||||||
|
sftp_reply_names_add
|
||||||
|
sftp_reply_status
|
||||||
|
sftp_rewind
|
||||||
|
sftp_rmdir
|
||||||
|
sftp_seek
|
||||||
|
sftp_seek64
|
||||||
|
sftp_send_client_message
|
||||||
|
sftp_server_free
|
||||||
|
sftp_server_init
|
||||||
|
sftp_server_new
|
||||||
|
sftp_server_version
|
||||||
|
sftp_setstat
|
||||||
|
sftp_stat
|
||||||
|
sftp_statvfs
|
||||||
|
sftp_statvfs_free
|
||||||
|
sftp_symlink
|
||||||
|
sftp_tell
|
||||||
|
sftp_tell64
|
||||||
|
sftp_unlink
|
||||||
|
sftp_utimes
|
||||||
|
sftp_write
|
||||||
|
ssh_accept
|
||||||
|
ssh_add_channel_callbacks
|
||||||
|
ssh_auth_list
|
||||||
|
ssh_basename
|
||||||
|
ssh_bind_accept
|
||||||
|
ssh_bind_accept_fd
|
||||||
|
ssh_bind_fd_toaccept
|
||||||
|
ssh_bind_free
|
||||||
|
ssh_bind_get_fd
|
||||||
|
ssh_bind_listen
|
||||||
|
ssh_bind_new
|
||||||
|
ssh_bind_options_parse_config
|
||||||
|
ssh_bind_options_set
|
||||||
|
ssh_bind_set_blocking
|
||||||
|
ssh_bind_set_callbacks
|
||||||
|
ssh_bind_set_fd
|
||||||
|
ssh_blocking_flush
|
||||||
|
ssh_buffer_add_data
|
||||||
|
ssh_buffer_free
|
||||||
|
ssh_buffer_get
|
||||||
|
ssh_buffer_get_data
|
||||||
|
ssh_buffer_get_len
|
||||||
|
ssh_buffer_new
|
||||||
|
ssh_buffer_reinit
|
||||||
|
ssh_channel_accept_forward
|
||||||
|
ssh_channel_accept_x11
|
||||||
|
ssh_channel_cancel_forward
|
||||||
|
ssh_channel_change_pty_size
|
||||||
|
ssh_channel_close
|
||||||
|
ssh_channel_free
|
||||||
|
ssh_channel_get_exit_status
|
||||||
|
ssh_channel_get_session
|
||||||
|
ssh_channel_is_closed
|
||||||
|
ssh_channel_is_eof
|
||||||
|
ssh_channel_is_open
|
||||||
|
ssh_channel_listen_forward
|
||||||
|
ssh_channel_new
|
||||||
|
ssh_channel_open_auth_agent
|
||||||
|
ssh_channel_open_forward
|
||||||
|
ssh_channel_open_forward_unix
|
||||||
|
ssh_channel_open_reverse_forward
|
||||||
|
ssh_channel_open_session
|
||||||
|
ssh_channel_open_x11
|
||||||
|
ssh_channel_poll
|
||||||
|
ssh_channel_poll_timeout
|
||||||
|
ssh_channel_read
|
||||||
|
ssh_channel_read_nonblocking
|
||||||
|
ssh_channel_read_timeout
|
||||||
|
ssh_channel_request_auth_agent
|
||||||
|
ssh_channel_request_env
|
||||||
|
ssh_channel_request_exec
|
||||||
|
ssh_channel_request_pty
|
||||||
|
ssh_channel_request_pty_size
|
||||||
|
ssh_channel_request_send_break
|
||||||
|
ssh_channel_request_send_exit_signal
|
||||||
|
ssh_channel_request_send_exit_status
|
||||||
|
ssh_channel_request_send_signal
|
||||||
|
ssh_channel_request_sftp
|
||||||
|
ssh_channel_request_shell
|
||||||
|
ssh_channel_request_subsystem
|
||||||
|
ssh_channel_request_x11
|
||||||
|
ssh_channel_select
|
||||||
|
ssh_channel_send_eof
|
||||||
|
ssh_channel_set_blocking
|
||||||
|
ssh_channel_set_counter
|
||||||
|
ssh_channel_window_size
|
||||||
|
ssh_channel_write
|
||||||
|
ssh_channel_write_stderr
|
||||||
|
ssh_clean_pubkey_hash
|
||||||
|
ssh_connect
|
||||||
|
ssh_connector_free
|
||||||
|
ssh_connector_new
|
||||||
|
ssh_connector_set_in_channel
|
||||||
|
ssh_connector_set_in_fd
|
||||||
|
ssh_connector_set_out_channel
|
||||||
|
ssh_connector_set_out_fd
|
||||||
|
ssh_copyright
|
||||||
|
ssh_dirname
|
||||||
|
ssh_disconnect
|
||||||
|
ssh_dump_knownhost
|
||||||
|
ssh_event_add_connector
|
||||||
|
ssh_event_add_fd
|
||||||
|
ssh_event_add_session
|
||||||
|
ssh_event_dopoll
|
||||||
|
ssh_event_free
|
||||||
|
ssh_event_new
|
||||||
|
ssh_event_remove_connector
|
||||||
|
ssh_event_remove_fd
|
||||||
|
ssh_event_remove_session
|
||||||
|
ssh_execute_message_callbacks
|
||||||
|
ssh_finalize
|
||||||
|
ssh_forward_accept
|
||||||
|
ssh_forward_cancel
|
||||||
|
ssh_forward_listen
|
||||||
|
ssh_free
|
||||||
|
ssh_get_cipher_in
|
||||||
|
ssh_get_cipher_out
|
||||||
|
ssh_get_clientbanner
|
||||||
|
ssh_get_disconnect_message
|
||||||
|
ssh_get_error
|
||||||
|
ssh_get_error_code
|
||||||
|
ssh_get_fd
|
||||||
|
ssh_get_fingerprint_hash
|
||||||
|
ssh_get_hexa
|
||||||
|
ssh_get_hmac_in
|
||||||
|
ssh_get_hmac_out
|
||||||
|
ssh_get_issue_banner
|
||||||
|
ssh_get_kex_algo
|
||||||
|
ssh_get_log_callback
|
||||||
|
ssh_get_log_level
|
||||||
|
ssh_get_log_userdata
|
||||||
|
ssh_get_openssh_version
|
||||||
|
ssh_get_poll_flags
|
||||||
|
ssh_get_pubkey
|
||||||
|
ssh_get_pubkey_hash
|
||||||
|
ssh_get_publickey
|
||||||
|
ssh_get_publickey_hash
|
||||||
|
ssh_get_random
|
||||||
|
ssh_get_server_publickey
|
||||||
|
ssh_get_serverbanner
|
||||||
|
ssh_get_status
|
||||||
|
ssh_get_version
|
||||||
|
ssh_getpass
|
||||||
|
ssh_gssapi_get_creds
|
||||||
|
ssh_gssapi_set_creds
|
||||||
|
ssh_handle_key_exchange
|
||||||
|
ssh_init
|
||||||
|
ssh_is_blocking
|
||||||
|
ssh_is_connected
|
||||||
|
ssh_is_server_known
|
||||||
|
ssh_key_cmp
|
||||||
|
ssh_key_free
|
||||||
|
ssh_key_is_private
|
||||||
|
ssh_key_is_public
|
||||||
|
ssh_key_new
|
||||||
|
ssh_key_type
|
||||||
|
ssh_key_type_from_name
|
||||||
|
ssh_key_type_to_char
|
||||||
|
ssh_known_hosts_parse_line
|
||||||
|
ssh_knownhosts_entry_free
|
||||||
|
ssh_log
|
||||||
|
ssh_message_auth_interactive_request
|
||||||
|
ssh_message_auth_kbdint_is_response
|
||||||
|
ssh_message_auth_password
|
||||||
|
ssh_message_auth_pubkey
|
||||||
|
ssh_message_auth_publickey
|
||||||
|
ssh_message_auth_publickey_state
|
||||||
|
ssh_message_auth_reply_pk_ok
|
||||||
|
ssh_message_auth_reply_pk_ok_simple
|
||||||
|
ssh_message_auth_reply_success
|
||||||
|
ssh_message_auth_set_methods
|
||||||
|
ssh_message_auth_user
|
||||||
|
ssh_message_channel_request_channel
|
||||||
|
ssh_message_channel_request_command
|
||||||
|
ssh_message_channel_request_env_name
|
||||||
|
ssh_message_channel_request_env_value
|
||||||
|
ssh_message_channel_request_open_destination
|
||||||
|
ssh_message_channel_request_open_destination_port
|
||||||
|
ssh_message_channel_request_open_originator
|
||||||
|
ssh_message_channel_request_open_originator_port
|
||||||
|
ssh_message_channel_request_open_reply_accept
|
||||||
|
ssh_message_channel_request_open_reply_accept_channel
|
||||||
|
ssh_message_channel_request_pty_height
|
||||||
|
ssh_message_channel_request_pty_pxheight
|
||||||
|
ssh_message_channel_request_pty_pxwidth
|
||||||
|
ssh_message_channel_request_pty_term
|
||||||
|
ssh_message_channel_request_pty_width
|
||||||
|
ssh_message_channel_request_reply_success
|
||||||
|
ssh_message_channel_request_subsystem
|
||||||
|
ssh_message_channel_request_x11_auth_cookie
|
||||||
|
ssh_message_channel_request_x11_auth_protocol
|
||||||
|
ssh_message_channel_request_x11_screen_number
|
||||||
|
ssh_message_channel_request_x11_single_connection
|
||||||
|
ssh_message_free
|
||||||
|
ssh_message_get
|
||||||
|
ssh_message_global_request_address
|
||||||
|
ssh_message_global_request_port
|
||||||
|
ssh_message_global_request_reply_success
|
||||||
|
ssh_message_reply_default
|
||||||
|
ssh_message_retrieve
|
||||||
|
ssh_message_service_reply_success
|
||||||
|
ssh_message_service_service
|
||||||
|
ssh_message_subtype
|
||||||
|
ssh_message_type
|
||||||
|
ssh_mkdir
|
||||||
|
ssh_new
|
||||||
|
ssh_options_copy
|
||||||
|
ssh_options_get
|
||||||
|
ssh_options_get_port
|
||||||
|
ssh_options_getopt
|
||||||
|
ssh_options_parse_config
|
||||||
|
ssh_options_set
|
||||||
|
ssh_pcap_file_close
|
||||||
|
ssh_pcap_file_free
|
||||||
|
ssh_pcap_file_new
|
||||||
|
ssh_pcap_file_open
|
||||||
|
ssh_pki_copy_cert_to_privkey
|
||||||
|
ssh_pki_export_privkey_base64
|
||||||
|
ssh_pki_export_privkey_file
|
||||||
|
ssh_pki_export_privkey_to_pubkey
|
||||||
|
ssh_pki_export_pubkey_base64
|
||||||
|
ssh_pki_export_pubkey_file
|
||||||
|
ssh_pki_generate
|
||||||
|
ssh_pki_import_cert_base64
|
||||||
|
ssh_pki_import_cert_file
|
||||||
|
ssh_pki_import_privkey_base64
|
||||||
|
ssh_pki_import_privkey_file
|
||||||
|
ssh_pki_import_pubkey_base64
|
||||||
|
ssh_pki_import_pubkey_file
|
||||||
|
ssh_pki_key_ecdsa_name
|
||||||
|
ssh_print_hash
|
||||||
|
ssh_print_hexa
|
||||||
|
ssh_privatekey_type
|
||||||
|
ssh_publickey_to_file
|
||||||
|
ssh_remove_channel_callbacks
|
||||||
|
ssh_scp_accept_request
|
||||||
|
ssh_scp_close
|
||||||
|
ssh_scp_deny_request
|
||||||
|
ssh_scp_free
|
||||||
|
ssh_scp_init
|
||||||
|
ssh_scp_leave_directory
|
||||||
|
ssh_scp_new
|
||||||
|
ssh_scp_pull_request
|
||||||
|
ssh_scp_push_directory
|
||||||
|
ssh_scp_push_file
|
||||||
|
ssh_scp_push_file64
|
||||||
|
ssh_scp_read
|
||||||
|
ssh_scp_request_get_filename
|
||||||
|
ssh_scp_request_get_permissions
|
||||||
|
ssh_scp_request_get_size
|
||||||
|
ssh_scp_request_get_size64
|
||||||
|
ssh_scp_request_get_warning
|
||||||
|
ssh_scp_write
|
||||||
|
ssh_select
|
||||||
|
ssh_send_debug
|
||||||
|
ssh_send_ignore
|
||||||
|
ssh_send_keepalive
|
||||||
|
ssh_server_init_kex
|
||||||
|
ssh_service_request
|
||||||
|
ssh_session_export_known_hosts_entry
|
||||||
|
ssh_session_get_known_hosts_entry
|
||||||
|
ssh_session_has_known_hosts_entry
|
||||||
|
ssh_session_is_known_server
|
||||||
|
ssh_session_update_known_hosts
|
||||||
|
ssh_set_agent_channel
|
||||||
|
ssh_set_agent_socket
|
||||||
|
ssh_set_auth_methods
|
||||||
|
ssh_set_blocking
|
||||||
|
ssh_set_callbacks
|
||||||
|
ssh_set_channel_callbacks
|
||||||
|
ssh_set_counters
|
||||||
|
ssh_set_fd_except
|
||||||
|
ssh_set_fd_toread
|
||||||
|
ssh_set_fd_towrite
|
||||||
|
ssh_set_log_callback
|
||||||
|
ssh_set_log_level
|
||||||
|
ssh_set_log_userdata
|
||||||
|
ssh_set_message_callback
|
||||||
|
ssh_set_pcap_file
|
||||||
|
ssh_set_server_callbacks
|
||||||
|
ssh_silent_disconnect
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_get_char
|
||||||
|
ssh_string_len
|
||||||
|
ssh_string_new
|
||||||
|
ssh_string_to_char
|
||||||
|
ssh_threads_get_default
|
||||||
|
ssh_threads_get_noop
|
||||||
|
ssh_threads_get_pthread
|
||||||
|
ssh_threads_set_callbacks
|
||||||
|
ssh_try_publickey_from_file
|
||||||
|
ssh_userauth_agent
|
||||||
|
ssh_userauth_agent_pubkey
|
||||||
|
ssh_userauth_autopubkey
|
||||||
|
ssh_userauth_gssapi
|
||||||
|
ssh_userauth_kbdint
|
||||||
|
ssh_userauth_kbdint_getanswer
|
||||||
|
ssh_userauth_kbdint_getinstruction
|
||||||
|
ssh_userauth_kbdint_getname
|
||||||
|
ssh_userauth_kbdint_getnanswers
|
||||||
|
ssh_userauth_kbdint_getnprompts
|
||||||
|
ssh_userauth_kbdint_getprompt
|
||||||
|
ssh_userauth_kbdint_setanswer
|
||||||
|
ssh_userauth_list
|
||||||
|
ssh_userauth_none
|
||||||
|
ssh_userauth_offer_pubkey
|
||||||
|
ssh_userauth_password
|
||||||
|
ssh_userauth_privatekey_file
|
||||||
|
ssh_userauth_pubkey
|
||||||
|
ssh_userauth_publickey
|
||||||
|
ssh_userauth_publickey_auto
|
||||||
|
ssh_userauth_try_publickey
|
||||||
|
ssh_version
|
||||||
|
ssh_write_knownhost
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
421
src/ABI/libssh-4.8.9.symbols
Normal file
421
src/ABI/libssh-4.8.9.symbols
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
_ssh_log
|
||||||
|
buffer_free
|
||||||
|
buffer_get
|
||||||
|
buffer_get_len
|
||||||
|
buffer_new
|
||||||
|
channel_accept_x11
|
||||||
|
channel_change_pty_size
|
||||||
|
channel_close
|
||||||
|
channel_forward_accept
|
||||||
|
channel_forward_cancel
|
||||||
|
channel_forward_listen
|
||||||
|
channel_free
|
||||||
|
channel_get_exit_status
|
||||||
|
channel_get_session
|
||||||
|
channel_is_closed
|
||||||
|
channel_is_eof
|
||||||
|
channel_is_open
|
||||||
|
channel_new
|
||||||
|
channel_open_forward
|
||||||
|
channel_open_session
|
||||||
|
channel_poll
|
||||||
|
channel_read
|
||||||
|
channel_read_buffer
|
||||||
|
channel_read_nonblocking
|
||||||
|
channel_request_env
|
||||||
|
channel_request_exec
|
||||||
|
channel_request_pty
|
||||||
|
channel_request_pty_size
|
||||||
|
channel_request_send_signal
|
||||||
|
channel_request_sftp
|
||||||
|
channel_request_shell
|
||||||
|
channel_request_subsystem
|
||||||
|
channel_request_x11
|
||||||
|
channel_select
|
||||||
|
channel_send_eof
|
||||||
|
channel_set_blocking
|
||||||
|
channel_write
|
||||||
|
channel_write_stderr
|
||||||
|
privatekey_free
|
||||||
|
privatekey_from_file
|
||||||
|
publickey_free
|
||||||
|
publickey_from_file
|
||||||
|
publickey_from_privatekey
|
||||||
|
publickey_to_string
|
||||||
|
sftp_async_read
|
||||||
|
sftp_async_read_begin
|
||||||
|
sftp_attributes_free
|
||||||
|
sftp_canonicalize_path
|
||||||
|
sftp_chmod
|
||||||
|
sftp_chown
|
||||||
|
sftp_client_message_free
|
||||||
|
sftp_client_message_get_data
|
||||||
|
sftp_client_message_get_filename
|
||||||
|
sftp_client_message_get_flags
|
||||||
|
sftp_client_message_get_submessage
|
||||||
|
sftp_client_message_get_type
|
||||||
|
sftp_client_message_set_filename
|
||||||
|
sftp_close
|
||||||
|
sftp_closedir
|
||||||
|
sftp_dir_eof
|
||||||
|
sftp_extension_supported
|
||||||
|
sftp_extensions_get_count
|
||||||
|
sftp_extensions_get_data
|
||||||
|
sftp_extensions_get_name
|
||||||
|
sftp_file_set_blocking
|
||||||
|
sftp_file_set_nonblocking
|
||||||
|
sftp_free
|
||||||
|
sftp_fstat
|
||||||
|
sftp_fstatvfs
|
||||||
|
sftp_fsync
|
||||||
|
sftp_get_client_message
|
||||||
|
sftp_get_error
|
||||||
|
sftp_handle
|
||||||
|
sftp_handle_alloc
|
||||||
|
sftp_handle_remove
|
||||||
|
sftp_init
|
||||||
|
sftp_lstat
|
||||||
|
sftp_mkdir
|
||||||
|
sftp_new
|
||||||
|
sftp_new_channel
|
||||||
|
sftp_open
|
||||||
|
sftp_opendir
|
||||||
|
sftp_read
|
||||||
|
sftp_readdir
|
||||||
|
sftp_readlink
|
||||||
|
sftp_rename
|
||||||
|
sftp_reply_attr
|
||||||
|
sftp_reply_data
|
||||||
|
sftp_reply_handle
|
||||||
|
sftp_reply_name
|
||||||
|
sftp_reply_names
|
||||||
|
sftp_reply_names_add
|
||||||
|
sftp_reply_status
|
||||||
|
sftp_rewind
|
||||||
|
sftp_rmdir
|
||||||
|
sftp_seek
|
||||||
|
sftp_seek64
|
||||||
|
sftp_send_client_message
|
||||||
|
sftp_server_free
|
||||||
|
sftp_server_init
|
||||||
|
sftp_server_new
|
||||||
|
sftp_server_version
|
||||||
|
sftp_setstat
|
||||||
|
sftp_stat
|
||||||
|
sftp_statvfs
|
||||||
|
sftp_statvfs_free
|
||||||
|
sftp_symlink
|
||||||
|
sftp_tell
|
||||||
|
sftp_tell64
|
||||||
|
sftp_unlink
|
||||||
|
sftp_utimes
|
||||||
|
sftp_write
|
||||||
|
ssh_accept
|
||||||
|
ssh_add_channel_callbacks
|
||||||
|
ssh_auth_list
|
||||||
|
ssh_basename
|
||||||
|
ssh_bind_accept
|
||||||
|
ssh_bind_accept_fd
|
||||||
|
ssh_bind_fd_toaccept
|
||||||
|
ssh_bind_free
|
||||||
|
ssh_bind_get_fd
|
||||||
|
ssh_bind_listen
|
||||||
|
ssh_bind_new
|
||||||
|
ssh_bind_options_parse_config
|
||||||
|
ssh_bind_options_set
|
||||||
|
ssh_bind_set_blocking
|
||||||
|
ssh_bind_set_callbacks
|
||||||
|
ssh_bind_set_fd
|
||||||
|
ssh_blocking_flush
|
||||||
|
ssh_buffer_add_data
|
||||||
|
ssh_buffer_free
|
||||||
|
ssh_buffer_get
|
||||||
|
ssh_buffer_get_data
|
||||||
|
ssh_buffer_get_len
|
||||||
|
ssh_buffer_new
|
||||||
|
ssh_buffer_reinit
|
||||||
|
ssh_channel_accept_forward
|
||||||
|
ssh_channel_accept_x11
|
||||||
|
ssh_channel_cancel_forward
|
||||||
|
ssh_channel_change_pty_size
|
||||||
|
ssh_channel_close
|
||||||
|
ssh_channel_free
|
||||||
|
ssh_channel_get_exit_status
|
||||||
|
ssh_channel_get_session
|
||||||
|
ssh_channel_is_closed
|
||||||
|
ssh_channel_is_eof
|
||||||
|
ssh_channel_is_open
|
||||||
|
ssh_channel_listen_forward
|
||||||
|
ssh_channel_new
|
||||||
|
ssh_channel_open_auth_agent
|
||||||
|
ssh_channel_open_forward
|
||||||
|
ssh_channel_open_forward_unix
|
||||||
|
ssh_channel_open_reverse_forward
|
||||||
|
ssh_channel_open_session
|
||||||
|
ssh_channel_open_x11
|
||||||
|
ssh_channel_poll
|
||||||
|
ssh_channel_poll_timeout
|
||||||
|
ssh_channel_read
|
||||||
|
ssh_channel_read_nonblocking
|
||||||
|
ssh_channel_read_timeout
|
||||||
|
ssh_channel_request_auth_agent
|
||||||
|
ssh_channel_request_env
|
||||||
|
ssh_channel_request_exec
|
||||||
|
ssh_channel_request_pty
|
||||||
|
ssh_channel_request_pty_size
|
||||||
|
ssh_channel_request_send_break
|
||||||
|
ssh_channel_request_send_exit_signal
|
||||||
|
ssh_channel_request_send_exit_status
|
||||||
|
ssh_channel_request_send_signal
|
||||||
|
ssh_channel_request_sftp
|
||||||
|
ssh_channel_request_shell
|
||||||
|
ssh_channel_request_subsystem
|
||||||
|
ssh_channel_request_x11
|
||||||
|
ssh_channel_select
|
||||||
|
ssh_channel_send_eof
|
||||||
|
ssh_channel_set_blocking
|
||||||
|
ssh_channel_set_counter
|
||||||
|
ssh_channel_window_size
|
||||||
|
ssh_channel_write
|
||||||
|
ssh_channel_write_stderr
|
||||||
|
ssh_clean_pubkey_hash
|
||||||
|
ssh_connect
|
||||||
|
ssh_connector_free
|
||||||
|
ssh_connector_new
|
||||||
|
ssh_connector_set_in_channel
|
||||||
|
ssh_connector_set_in_fd
|
||||||
|
ssh_connector_set_out_channel
|
||||||
|
ssh_connector_set_out_fd
|
||||||
|
ssh_copyright
|
||||||
|
ssh_dirname
|
||||||
|
ssh_disconnect
|
||||||
|
ssh_dump_knownhost
|
||||||
|
ssh_event_add_connector
|
||||||
|
ssh_event_add_fd
|
||||||
|
ssh_event_add_session
|
||||||
|
ssh_event_dopoll
|
||||||
|
ssh_event_free
|
||||||
|
ssh_event_new
|
||||||
|
ssh_event_remove_connector
|
||||||
|
ssh_event_remove_fd
|
||||||
|
ssh_event_remove_session
|
||||||
|
ssh_execute_message_callbacks
|
||||||
|
ssh_finalize
|
||||||
|
ssh_forward_accept
|
||||||
|
ssh_forward_cancel
|
||||||
|
ssh_forward_listen
|
||||||
|
ssh_free
|
||||||
|
ssh_get_cipher_in
|
||||||
|
ssh_get_cipher_out
|
||||||
|
ssh_get_clientbanner
|
||||||
|
ssh_get_disconnect_message
|
||||||
|
ssh_get_error
|
||||||
|
ssh_get_error_code
|
||||||
|
ssh_get_fd
|
||||||
|
ssh_get_fingerprint_hash
|
||||||
|
ssh_get_hexa
|
||||||
|
ssh_get_hmac_in
|
||||||
|
ssh_get_hmac_out
|
||||||
|
ssh_get_issue_banner
|
||||||
|
ssh_get_kex_algo
|
||||||
|
ssh_get_log_callback
|
||||||
|
ssh_get_log_level
|
||||||
|
ssh_get_log_userdata
|
||||||
|
ssh_get_openssh_version
|
||||||
|
ssh_get_poll_flags
|
||||||
|
ssh_get_pubkey
|
||||||
|
ssh_get_pubkey_hash
|
||||||
|
ssh_get_publickey
|
||||||
|
ssh_get_publickey_hash
|
||||||
|
ssh_get_random
|
||||||
|
ssh_get_server_publickey
|
||||||
|
ssh_get_serverbanner
|
||||||
|
ssh_get_status
|
||||||
|
ssh_get_version
|
||||||
|
ssh_getpass
|
||||||
|
ssh_gssapi_get_creds
|
||||||
|
ssh_gssapi_set_creds
|
||||||
|
ssh_handle_key_exchange
|
||||||
|
ssh_init
|
||||||
|
ssh_is_blocking
|
||||||
|
ssh_is_connected
|
||||||
|
ssh_is_server_known
|
||||||
|
ssh_key_cmp
|
||||||
|
ssh_key_free
|
||||||
|
ssh_key_is_private
|
||||||
|
ssh_key_is_public
|
||||||
|
ssh_key_new
|
||||||
|
ssh_key_type
|
||||||
|
ssh_key_type_from_name
|
||||||
|
ssh_key_type_to_char
|
||||||
|
ssh_known_hosts_parse_line
|
||||||
|
ssh_knownhosts_entry_free
|
||||||
|
ssh_log
|
||||||
|
ssh_message_auth_interactive_request
|
||||||
|
ssh_message_auth_kbdint_is_response
|
||||||
|
ssh_message_auth_password
|
||||||
|
ssh_message_auth_pubkey
|
||||||
|
ssh_message_auth_publickey
|
||||||
|
ssh_message_auth_publickey_state
|
||||||
|
ssh_message_auth_reply_pk_ok
|
||||||
|
ssh_message_auth_reply_pk_ok_simple
|
||||||
|
ssh_message_auth_reply_success
|
||||||
|
ssh_message_auth_set_methods
|
||||||
|
ssh_message_auth_user
|
||||||
|
ssh_message_channel_request_channel
|
||||||
|
ssh_message_channel_request_command
|
||||||
|
ssh_message_channel_request_env_name
|
||||||
|
ssh_message_channel_request_env_value
|
||||||
|
ssh_message_channel_request_open_destination
|
||||||
|
ssh_message_channel_request_open_destination_port
|
||||||
|
ssh_message_channel_request_open_originator
|
||||||
|
ssh_message_channel_request_open_originator_port
|
||||||
|
ssh_message_channel_request_open_reply_accept
|
||||||
|
ssh_message_channel_request_open_reply_accept_channel
|
||||||
|
ssh_message_channel_request_pty_height
|
||||||
|
ssh_message_channel_request_pty_pxheight
|
||||||
|
ssh_message_channel_request_pty_pxwidth
|
||||||
|
ssh_message_channel_request_pty_term
|
||||||
|
ssh_message_channel_request_pty_width
|
||||||
|
ssh_message_channel_request_reply_success
|
||||||
|
ssh_message_channel_request_subsystem
|
||||||
|
ssh_message_channel_request_x11_auth_cookie
|
||||||
|
ssh_message_channel_request_x11_auth_protocol
|
||||||
|
ssh_message_channel_request_x11_screen_number
|
||||||
|
ssh_message_channel_request_x11_single_connection
|
||||||
|
ssh_message_free
|
||||||
|
ssh_message_get
|
||||||
|
ssh_message_global_request_address
|
||||||
|
ssh_message_global_request_port
|
||||||
|
ssh_message_global_request_reply_success
|
||||||
|
ssh_message_reply_default
|
||||||
|
ssh_message_retrieve
|
||||||
|
ssh_message_service_reply_success
|
||||||
|
ssh_message_service_service
|
||||||
|
ssh_message_subtype
|
||||||
|
ssh_message_type
|
||||||
|
ssh_mkdir
|
||||||
|
ssh_new
|
||||||
|
ssh_options_copy
|
||||||
|
ssh_options_get
|
||||||
|
ssh_options_get_port
|
||||||
|
ssh_options_getopt
|
||||||
|
ssh_options_parse_config
|
||||||
|
ssh_options_set
|
||||||
|
ssh_pcap_file_close
|
||||||
|
ssh_pcap_file_free
|
||||||
|
ssh_pcap_file_new
|
||||||
|
ssh_pcap_file_open
|
||||||
|
ssh_pki_copy_cert_to_privkey
|
||||||
|
ssh_pki_export_privkey_base64
|
||||||
|
ssh_pki_export_privkey_file
|
||||||
|
ssh_pki_export_privkey_to_pubkey
|
||||||
|
ssh_pki_export_pubkey_base64
|
||||||
|
ssh_pki_export_pubkey_file
|
||||||
|
ssh_pki_generate
|
||||||
|
ssh_pki_import_cert_base64
|
||||||
|
ssh_pki_import_cert_file
|
||||||
|
ssh_pki_import_privkey_base64
|
||||||
|
ssh_pki_import_privkey_file
|
||||||
|
ssh_pki_import_pubkey_base64
|
||||||
|
ssh_pki_import_pubkey_file
|
||||||
|
ssh_pki_key_ecdsa_name
|
||||||
|
ssh_print_hash
|
||||||
|
ssh_print_hexa
|
||||||
|
ssh_privatekey_type
|
||||||
|
ssh_publickey_to_file
|
||||||
|
ssh_remove_channel_callbacks
|
||||||
|
ssh_scp_accept_request
|
||||||
|
ssh_scp_close
|
||||||
|
ssh_scp_deny_request
|
||||||
|
ssh_scp_free
|
||||||
|
ssh_scp_init
|
||||||
|
ssh_scp_leave_directory
|
||||||
|
ssh_scp_new
|
||||||
|
ssh_scp_pull_request
|
||||||
|
ssh_scp_push_directory
|
||||||
|
ssh_scp_push_file
|
||||||
|
ssh_scp_push_file64
|
||||||
|
ssh_scp_read
|
||||||
|
ssh_scp_request_get_filename
|
||||||
|
ssh_scp_request_get_permissions
|
||||||
|
ssh_scp_request_get_size
|
||||||
|
ssh_scp_request_get_size64
|
||||||
|
ssh_scp_request_get_warning
|
||||||
|
ssh_scp_write
|
||||||
|
ssh_select
|
||||||
|
ssh_send_debug
|
||||||
|
ssh_send_ignore
|
||||||
|
ssh_send_keepalive
|
||||||
|
ssh_server_init_kex
|
||||||
|
ssh_service_request
|
||||||
|
ssh_session_export_known_hosts_entry
|
||||||
|
ssh_session_get_known_hosts_entry
|
||||||
|
ssh_session_has_known_hosts_entry
|
||||||
|
ssh_session_is_known_server
|
||||||
|
ssh_session_update_known_hosts
|
||||||
|
ssh_set_agent_channel
|
||||||
|
ssh_set_agent_socket
|
||||||
|
ssh_set_auth_methods
|
||||||
|
ssh_set_blocking
|
||||||
|
ssh_set_callbacks
|
||||||
|
ssh_set_channel_callbacks
|
||||||
|
ssh_set_counters
|
||||||
|
ssh_set_fd_except
|
||||||
|
ssh_set_fd_toread
|
||||||
|
ssh_set_fd_towrite
|
||||||
|
ssh_set_log_callback
|
||||||
|
ssh_set_log_level
|
||||||
|
ssh_set_log_userdata
|
||||||
|
ssh_set_message_callback
|
||||||
|
ssh_set_pcap_file
|
||||||
|
ssh_set_server_callbacks
|
||||||
|
ssh_silent_disconnect
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_get_char
|
||||||
|
ssh_string_len
|
||||||
|
ssh_string_new
|
||||||
|
ssh_string_to_char
|
||||||
|
ssh_threads_get_default
|
||||||
|
ssh_threads_get_noop
|
||||||
|
ssh_threads_get_pthread
|
||||||
|
ssh_threads_set_callbacks
|
||||||
|
ssh_try_publickey_from_file
|
||||||
|
ssh_userauth_agent
|
||||||
|
ssh_userauth_agent_pubkey
|
||||||
|
ssh_userauth_autopubkey
|
||||||
|
ssh_userauth_gssapi
|
||||||
|
ssh_userauth_kbdint
|
||||||
|
ssh_userauth_kbdint_getanswer
|
||||||
|
ssh_userauth_kbdint_getinstruction
|
||||||
|
ssh_userauth_kbdint_getname
|
||||||
|
ssh_userauth_kbdint_getnanswers
|
||||||
|
ssh_userauth_kbdint_getnprompts
|
||||||
|
ssh_userauth_kbdint_getprompt
|
||||||
|
ssh_userauth_kbdint_setanswer
|
||||||
|
ssh_userauth_list
|
||||||
|
ssh_userauth_none
|
||||||
|
ssh_userauth_offer_pubkey
|
||||||
|
ssh_userauth_password
|
||||||
|
ssh_userauth_privatekey_file
|
||||||
|
ssh_userauth_pubkey
|
||||||
|
ssh_userauth_publickey
|
||||||
|
ssh_userauth_publickey_auto
|
||||||
|
ssh_userauth_try_publickey
|
||||||
|
ssh_version
|
||||||
|
ssh_write_knownhost
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
set(LIBSSH_PUBLIC_INCLUDE_DIRS ${libssh_SOURCE_DIR}/include)
|
set(LIBSSH_PUBLIC_INCLUDE_DIRS ${libssh_SOURCE_DIR}/include)
|
||||||
|
|
||||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
|
${libssh_BINARY_DIR}/include
|
||||||
${libssh_BINARY_DIR}
|
${libssh_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -8,14 +9,7 @@ set(LIBSSH_LINK_LIBRARIES
|
|||||||
${LIBSSH_REQUIRED_LIBRARIES}
|
${LIBSSH_REQUIRED_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (OPENSSL_CRYPTO_LIBRARIES)
|
||||||
set(LIBSSH_LINK_LIBRARIES
|
|
||||||
${LIBSSH_LINK_LIBRARIES}
|
|
||||||
ws2_32
|
|
||||||
)
|
|
||||||
endif (WIN32)
|
|
||||||
|
|
||||||
if (OPENSSL_CRYPTO_LIBRARY)
|
|
||||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||||
${OPENSSL_INCLUDE_DIR}
|
${OPENSSL_INCLUDE_DIR}
|
||||||
@@ -23,9 +17,9 @@ if (OPENSSL_CRYPTO_LIBRARY)
|
|||||||
|
|
||||||
set(LIBSSH_LINK_LIBRARIES
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
${LIBSSH_LINK_LIBRARIES}
|
${LIBSSH_LINK_LIBRARIES}
|
||||||
${OPENSSL_CRYPTO_LIBRARY}
|
${OPENSSL_CRYPTO_LIBRARIES}
|
||||||
)
|
)
|
||||||
endif (OPENSSL_CRYPTO_LIBRARY)
|
endif (OPENSSL_CRYPTO_LIBRARIES)
|
||||||
|
|
||||||
if (MBEDTLS_CRYPTO_LIBRARY)
|
if (MBEDTLS_CRYPTO_LIBRARY)
|
||||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||||
@@ -85,6 +79,23 @@ if (WITH_NACL AND NACL_FOUND)
|
|||||||
)
|
)
|
||||||
endif (WITH_NACL AND NACL_FOUND)
|
endif (WITH_NACL AND NACL_FOUND)
|
||||||
|
|
||||||
|
if (MINGW AND Threads_FOUND)
|
||||||
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
|
${LIBSSH_LINK_LIBRARIES}
|
||||||
|
Threads::Threads
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# This needs to be last for mingw to build
|
||||||
|
# https://gitlab.com/libssh/libssh-mirror/-/issues/84
|
||||||
|
if (WIN32)
|
||||||
|
set(LIBSSH_LINK_LIBRARIES
|
||||||
|
${LIBSSH_LINK_LIBRARIES}
|
||||||
|
iphlpapi
|
||||||
|
ws2_32
|
||||||
|
)
|
||||||
|
endif (WIN32)
|
||||||
|
|
||||||
if (BUILD_STATIC_LIB)
|
if (BUILD_STATIC_LIB)
|
||||||
set(LIBSSH_STATIC_LIBRARY
|
set(LIBSSH_STATIC_LIBRARY
|
||||||
ssh_static
|
ssh_static
|
||||||
@@ -323,7 +334,7 @@ target_link_libraries(ssh
|
|||||||
PRIVATE ${LIBSSH_LINK_LIBRARIES})
|
PRIVATE ${LIBSSH_LINK_LIBRARIES})
|
||||||
|
|
||||||
if (WIN32 AND NOT BUILD_SHARED_LIBS)
|
if (WIN32 AND NOT BUILD_SHARED_LIBS)
|
||||||
set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-DLIBSSH_STATIC")
|
target_compile_definitions(ssh PUBLIC "LIBSSH_STATIC")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_library(ssh::ssh ALIAS ssh)
|
add_library(ssh::ssh ALIAS ssh)
|
||||||
@@ -334,9 +345,7 @@ if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
|||||||
set(MAP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_dev.map")
|
set(MAP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_dev.map")
|
||||||
endif (ABIMAP_FOUND)
|
endif (ABIMAP_FOUND)
|
||||||
|
|
||||||
set_target_properties(ssh
|
target_link_libraries(ssh PRIVATE "-Wl,--version-script,\"${MAP_PATH}\"")
|
||||||
PROPERTIES LINK_FLAGS
|
|
||||||
"-Wl,--version-script,\"${MAP_PATH}\"")
|
|
||||||
endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||||
|
|
||||||
set_target_properties(ssh
|
set_target_properties(ssh
|
||||||
@@ -350,11 +359,12 @@ set_target_properties(ssh
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (WITH_VISIBILITY_HIDDEN)
|
if (WITH_VISIBILITY_HIDDEN)
|
||||||
set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
set_target_properties(ssh PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||||
endif (WITH_VISIBILITY_HIDDEN)
|
endif (WITH_VISIBILITY_HIDDEN)
|
||||||
|
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
set_target_properties(ssh PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup")
|
target_link_libraries(ssh PRIVATE "-Wl,--enable-stdcall-fixup")
|
||||||
|
target_compile_definitions(ssh PRIVATE "_POSIX_SOURCE")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
@@ -403,12 +413,7 @@ if (BUILD_STATIC_LIB)
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set_target_properties(
|
target_compile_definitions(ssh-static PUBLIC "LIBSSH_STATIC")
|
||||||
ssh-static
|
|
||||||
PROPERTIES
|
|
||||||
COMPILE_FLAGS
|
|
||||||
"-DLIBSSH_STATIC"
|
|
||||||
)
|
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
endif (BUILD_STATIC_LIB)
|
endif (BUILD_STATIC_LIB)
|
||||||
|
|
||||||
|
|||||||
@@ -1116,7 +1116,9 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
|||||||
"Public key authentication error for %s",
|
"Public key authentication error for %s",
|
||||||
privkey_file);
|
privkey_file);
|
||||||
ssh_key_free(state->privkey);
|
ssh_key_free(state->privkey);
|
||||||
|
state->privkey = NULL;
|
||||||
ssh_key_free(state->pubkey);
|
ssh_key_free(state->pubkey);
|
||||||
|
state->pubkey = NULL;
|
||||||
SAFE_FREE(session->auth.auto_state);
|
SAFE_FREE(session->auth.auto_state);
|
||||||
return rc;
|
return rc;
|
||||||
} else if (rc == SSH_AUTH_AGAIN) {
|
} else if (rc == SSH_AUTH_AGAIN) {
|
||||||
@@ -1182,6 +1184,9 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssh_key_free(state->privkey);
|
||||||
|
ssh_key_free(state->pubkey);
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_WARN,
|
SSH_LOG(SSH_LOG_WARN,
|
||||||
"The server accepted the public key but refused the signature");
|
"The server accepted the public key but refused the signature");
|
||||||
state->it = state->it->next;
|
state->it = state->it->next;
|
||||||
|
|||||||
45
src/buffer.c
45
src/buffer.c
@@ -299,28 +299,33 @@ int ssh_buffer_reinit(struct ssh_buffer_struct *buffer)
|
|||||||
*/
|
*/
|
||||||
int ssh_buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len)
|
int ssh_buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len)
|
||||||
{
|
{
|
||||||
buffer_verify(buffer);
|
if (buffer == NULL) {
|
||||||
|
return -1;
|
||||||
if (data == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer->used + len < len) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer->allocated < (buffer->used + len)) {
|
|
||||||
if(buffer->pos > 0)
|
|
||||||
buffer_shift(buffer);
|
|
||||||
if (realloc_buffer(buffer, buffer->used + len) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer->data+buffer->used, data, len);
|
buffer_verify(buffer);
|
||||||
buffer->used+=len;
|
|
||||||
buffer_verify(buffer);
|
if (data == NULL) {
|
||||||
return 0;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->used + len < len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->allocated < (buffer->used + len)) {
|
||||||
|
if (buffer->pos > 0) {
|
||||||
|
buffer_shift(buffer);
|
||||||
|
}
|
||||||
|
if (realloc_buffer(buffer, buffer->used + len) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer->data + buffer->used, data, len);
|
||||||
|
buffer->used += len;
|
||||||
|
buffer_verify(buffer);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif /* HAVE_SYS_TIME_H */
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@@ -117,6 +120,13 @@ ssh_channel ssh_channel_new(ssh_session session)
|
|||||||
|
|
||||||
if (session->channels == NULL) {
|
if (session->channels == NULL) {
|
||||||
session->channels = ssh_list_new();
|
session->channels = ssh_list_new();
|
||||||
|
if (session->channels == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
SSH_BUFFER_FREE(channel->stdout_buffer);
|
||||||
|
SSH_BUFFER_FREE(channel->stderr_buffer);
|
||||||
|
SAFE_FREE(channel);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_list_prepend(session->channels, channel);
|
ssh_list_prepend(session->channels, channel);
|
||||||
@@ -2932,15 +2942,16 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
|||||||
if (session->session_state == SSH_SESSION_STATE_ERROR) {
|
if (session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
/* If the server closed the channel properly, there is nothing to do */
|
||||||
|
if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (channel->state == SSH_CHANNEL_STATE_CLOSED) {
|
if (channel->state == SSH_CHANNEL_STATE_CLOSED) {
|
||||||
ssh_set_error(session,
|
ssh_set_error(session,
|
||||||
SSH_FATAL,
|
SSH_FATAL,
|
||||||
"Remote channel is closed.");
|
"Remote channel is closed.");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
len = ssh_buffer_get_len(stdbuf);
|
len = ssh_buffer_get_len(stdbuf);
|
||||||
/* Read count bytes if len is greater, everything otherwise */
|
/* Read count bytes if len is greater, everything otherwise */
|
||||||
len = (len > count ? count : len);
|
len = (len > count ? count : len);
|
||||||
@@ -3095,7 +3106,7 @@ int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
|
|||||||
size_t len;
|
size_t len;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if(channel == NULL) {
|
if (channel == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3113,12 +3124,23 @@ int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
|
|||||||
ssh_channel_read_termination,
|
ssh_channel_read_termination,
|
||||||
&ctx);
|
&ctx);
|
||||||
if (rc == SSH_ERROR ||
|
if (rc == SSH_ERROR ||
|
||||||
session->session_state == SSH_SESSION_STATE_ERROR) {
|
session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||||
rc = SSH_ERROR;
|
rc = SSH_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
|
} else if (rc == SSH_AGAIN) {
|
||||||
|
/* If the above timeout expired, it is ok and we do not need to
|
||||||
|
* attempt to check the read buffer. The calling functions do not
|
||||||
|
* expect us to return SSH_AGAIN either here. */
|
||||||
|
rc = SSH_OK;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
len = ssh_buffer_get_len(stdbuf);
|
len = ssh_buffer_get_len(stdbuf);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
|
if (len > INT_MAX) {
|
||||||
|
rc = SSH_ERROR;
|
||||||
|
} else {
|
||||||
|
rc = (int)len;
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (channel->remote_eof) {
|
if (channel->remote_eof) {
|
||||||
@@ -3381,9 +3403,15 @@ int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans,
|
|||||||
firstround=0;
|
firstround=0;
|
||||||
} while(1);
|
} while(1);
|
||||||
|
|
||||||
memcpy(readchans, rchans, (count_ptrs(rchans) + 1) * sizeof(ssh_channel ));
|
if (readchans != &dummy) {
|
||||||
memcpy(writechans, wchans, (count_ptrs(wchans) + 1) * sizeof(ssh_channel ));
|
memcpy(readchans, rchans, (count_ptrs(rchans) + 1) * sizeof(ssh_channel));
|
||||||
memcpy(exceptchans, echans, (count_ptrs(echans) + 1) * sizeof(ssh_channel ));
|
}
|
||||||
|
if (writechans != &dummy) {
|
||||||
|
memcpy(writechans, wchans, (count_ptrs(wchans) + 1) * sizeof(ssh_channel));
|
||||||
|
}
|
||||||
|
if (exceptchans != &dummy) {
|
||||||
|
memcpy(exceptchans, echans, (count_ptrs(echans) + 1) * sizeof(ssh_channel));
|
||||||
|
}
|
||||||
SAFE_FREE(rchans);
|
SAFE_FREE(rchans);
|
||||||
SAFE_FREE(wchans);
|
SAFE_FREE(wchans);
|
||||||
SAFE_FREE(echans);
|
SAFE_FREE(echans);
|
||||||
|
|||||||
380
src/client.c
380
src/client.c
@@ -243,15 +243,19 @@ end:
|
|||||||
* @warning this function returning is no proof that DH handshake is
|
* @warning this function returning is no proof that DH handshake is
|
||||||
* completed
|
* completed
|
||||||
*/
|
*/
|
||||||
static int dh_handshake(ssh_session session) {
|
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);
|
||||||
|
|
||||||
switch (session->dh_handshake_state) {
|
switch (session->dh_handshake_state) {
|
||||||
case DH_STATE_INIT:
|
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_GROUP1_SHA1:
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
|
case SSH_KEX_DH_GROUP14_SHA256:
|
||||||
case SSH_KEX_DH_GROUP16_SHA512:
|
case SSH_KEX_DH_GROUP16_SHA512:
|
||||||
case SSH_KEX_DH_GROUP18_SHA512:
|
case SSH_KEX_DH_GROUP18_SHA512:
|
||||||
rc = ssh_client_dh_init(session);
|
rc = ssh_client_dh_init(session);
|
||||||
@@ -385,95 +389,101 @@ static void ssh_client_connection_callback(ssh_session session)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
switch(session->session_state) {
|
SSH_LOG(SSH_LOG_DEBUG, "session_state=%d", session->session_state);
|
||||||
case SSH_SESSION_STATE_NONE:
|
|
||||||
case SSH_SESSION_STATE_CONNECTING:
|
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
|
||||||
ssh_set_fd_towrite(session);
|
|
||||||
ssh_send_banner(session, 0);
|
|
||||||
|
|
||||||
break;
|
switch (session->session_state) {
|
||||||
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
case SSH_SESSION_STATE_NONE:
|
||||||
if (session->serverbanner == NULL) {
|
case SSH_SESSION_STATE_CONNECTING:
|
||||||
goto error;
|
break;
|
||||||
}
|
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
||||||
set_status(session, 0.4f);
|
ssh_set_fd_towrite(session);
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
ssh_send_banner(session, 0);
|
||||||
"SSH server banner: %s", session->serverbanner);
|
|
||||||
|
|
||||||
/* Here we analyze the different protocols the server allows. */
|
break;
|
||||||
rc = ssh_analyze_banner(session, 0);
|
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
||||||
if (rc < 0) {
|
if (session->serverbanner == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
goto error;
|
||||||
"No version of SSH protocol usable (banner: %s)",
|
}
|
||||||
session->serverbanner);
|
set_status(session, 0.4f);
|
||||||
goto error;
|
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||||
}
|
"SSH server banner: %s", session->serverbanner);
|
||||||
|
|
||||||
ssh_packet_register_socket_callback(session, session->socket);
|
/* Here we analyze the different protocols the server allows. */
|
||||||
|
rc = ssh_analyze_banner(session, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"No version of SSH protocol usable (banner: %s)",
|
||||||
|
session->serverbanner);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
ssh_packet_set_default_callbacks(session);
|
ssh_packet_register_socket_callback(session, session->socket);
|
||||||
session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
|
|
||||||
|
ssh_packet_set_default_callbacks(session);
|
||||||
|
session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
|
||||||
|
rc = ssh_set_client_kex(session);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
rc = ssh_send_kex(session);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
set_status(session, 0.5f);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_INITIAL_KEX:
|
||||||
|
/* TODO: This state should disappear in favor of get_key handle */
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
||||||
|
set_status(session, 0.6f);
|
||||||
|
ssh_list_kex(&session->next_crypto->server_kex);
|
||||||
|
if ((session->flags & SSH_SESSION_FLAG_KEXINIT_SENT) == 0) {
|
||||||
|
/* in rekeying state if next_crypto client_kex might be empty */
|
||||||
rc = ssh_set_client_kex(session);
|
rc = ssh_set_client_kex(session);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rc = ssh_send_kex(session, 0);
|
rc = ssh_send_kex(session);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
set_status(session, 0.5f);
|
}
|
||||||
|
if (ssh_kex_select_methods(session) == SSH_ERROR)
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_INITIAL_KEX:
|
|
||||||
/* TODO: This state should disappear in favor of get_key handle */
|
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
|
||||||
set_status(session,0.6f);
|
|
||||||
ssh_list_kex(&session->next_crypto->server_kex);
|
|
||||||
if (session->next_crypto->client_kex.methods[0] == NULL) {
|
|
||||||
/* in rekeying state if next_crypto client_kex is empty */
|
|
||||||
rc = ssh_set_client_kex(session);
|
|
||||||
if (rc != SSH_OK) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
rc = ssh_send_kex(session, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ssh_kex_select_methods(session) == SSH_ERROR)
|
|
||||||
goto error;
|
|
||||||
set_status(session,0.8f);
|
|
||||||
session->session_state=SSH_SESSION_STATE_DH;
|
|
||||||
if (dh_handshake(session) == SSH_ERROR) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
/* FALL THROUGH */
|
|
||||||
case SSH_SESSION_STATE_DH:
|
|
||||||
if(session->dh_handshake_state==DH_STATE_FINISHED){
|
|
||||||
set_status(session,1.0f);
|
|
||||||
session->connected = 1;
|
|
||||||
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
|
||||||
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
|
||||||
else
|
|
||||||
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_AUTHENTICATING:
|
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_ERROR:
|
|
||||||
goto error;
|
goto error;
|
||||||
default:
|
set_status(session, 0.8f);
|
||||||
ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
|
session->session_state = SSH_SESSION_STATE_DH;
|
||||||
|
|
||||||
|
/* If the init packet was already sent in previous step, this will be no
|
||||||
|
* operation */
|
||||||
|
if (dh_handshake(session) == SSH_ERROR) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
FALL_THROUGH;
|
||||||
|
case SSH_SESSION_STATE_DH:
|
||||||
|
if (session->dh_handshake_state == DH_STATE_FINISHED) {
|
||||||
|
set_status(session, 1.0f);
|
||||||
|
session->connected = 1;
|
||||||
|
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
||||||
|
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
||||||
|
else
|
||||||
|
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_AUTHENTICATING:
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_ERROR:
|
||||||
|
goto error;
|
||||||
|
default:
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Invalid state %d",
|
||||||
|
session->session_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
ssh_socket_close(session->socket);
|
ssh_socket_close(session->socket);
|
||||||
session->alive = 0;
|
session->alive = 0;
|
||||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,119 +514,138 @@ static int ssh_connect_termination(void *user){
|
|||||||
* @see ssh_new()
|
* @see ssh_new()
|
||||||
* @see ssh_disconnect()
|
* @see ssh_disconnect()
|
||||||
*/
|
*/
|
||||||
int ssh_connect(ssh_session session) {
|
int ssh_connect(ssh_session session)
|
||||||
int ret;
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (session == NULL) {
|
if (!is_ssh_initialized()) {
|
||||||
return SSH_ERROR;
|
ssh_set_error(session, SSH_FATAL,
|
||||||
}
|
"Library not initialized.");
|
||||||
|
|
||||||
switch(session->pending_call_state){
|
return SSH_ERROR;
|
||||||
case SSH_PENDING_CALL_NONE:
|
|
||||||
break;
|
|
||||||
case SSH_PENDING_CALL_CONNECT:
|
|
||||||
goto pending;
|
|
||||||
default:
|
|
||||||
ssh_set_error(session,SSH_FATAL,"Bad call during pending SSH call in ssh_connect");
|
|
||||||
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
session->alive = 0;
|
|
||||||
session->client = 1;
|
|
||||||
|
|
||||||
if (session->opts.fd == SSH_INVALID_SOCKET &&
|
|
||||||
session->opts.host == NULL &&
|
|
||||||
session->opts.ProxyCommand == NULL) {
|
|
||||||
ssh_set_error(session, SSH_FATAL, "Hostname required");
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the system configuration files were not yet processed, do it now */
|
|
||||||
if (!session->opts.config_processed) {
|
|
||||||
ret = ssh_options_parse_config(session, NULL);
|
|
||||||
if (ret != 0) {
|
|
||||||
ssh_set_error(session, SSH_FATAL,
|
|
||||||
"Failed to process system configuration files");
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ret = ssh_options_apply(session);
|
if (session == NULL) {
|
||||||
if (ret < 0) {
|
return SSH_ERROR;
|
||||||
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
|
}
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
switch(session->pending_call_state) {
|
||||||
"libssh %s, using threading %s",
|
case SSH_PENDING_CALL_NONE:
|
||||||
ssh_copyright(),
|
break;
|
||||||
ssh_threads_get_type());
|
case SSH_PENDING_CALL_CONNECT:
|
||||||
|
goto pending;
|
||||||
|
default:
|
||||||
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"Bad call during pending SSH call in ssh_connect");
|
||||||
|
|
||||||
session->ssh_connection_callback = ssh_client_connection_callback;
|
return SSH_ERROR;
|
||||||
session->session_state=SSH_SESSION_STATE_CONNECTING;
|
}
|
||||||
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
|
session->alive = 0;
|
||||||
session->socket_callbacks.connected=socket_callback_connected;
|
session->client = 1;
|
||||||
session->socket_callbacks.data=callback_receive_banner;
|
|
||||||
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
if (session->opts.fd == SSH_INVALID_SOCKET &&
|
||||||
session->socket_callbacks.userdata=session;
|
session->opts.host == NULL &&
|
||||||
if (session->opts.fd != SSH_INVALID_SOCKET) {
|
session->opts.ProxyCommand == NULL)
|
||||||
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
|
{
|
||||||
ssh_socket_set_fd(session->socket, session->opts.fd);
|
ssh_set_error(session, SSH_FATAL, "Hostname required");
|
||||||
ret=SSH_OK;
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the system configuration files were not yet processed, do it now */
|
||||||
|
if (!session->opts.config_processed) {
|
||||||
|
ret = ssh_options_parse_config(session, NULL);
|
||||||
|
if (ret != 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"Failed to process system configuration files");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ssh_options_apply(session);
|
||||||
|
if (ret < 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||||
|
"libssh %s, using threading %s",
|
||||||
|
ssh_copyright(),
|
||||||
|
ssh_threads_get_type());
|
||||||
|
|
||||||
|
session->ssh_connection_callback = ssh_client_connection_callback;
|
||||||
|
session->session_state = SSH_SESSION_STATE_CONNECTING;
|
||||||
|
ssh_socket_set_callbacks(session->socket, &session->socket_callbacks);
|
||||||
|
session->socket_callbacks.connected = socket_callback_connected;
|
||||||
|
session->socket_callbacks.data = callback_receive_banner;
|
||||||
|
session->socket_callbacks.exception = ssh_socket_exception_callback;
|
||||||
|
session->socket_callbacks.userdata = session;
|
||||||
|
|
||||||
|
if (session->opts.fd != SSH_INVALID_SOCKET) {
|
||||||
|
session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||||
|
ssh_socket_set_fd(session->socket, session->opts.fd);
|
||||||
|
ret = SSH_OK;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
} else if (session->opts.ProxyCommand != NULL){
|
} else if (session->opts.ProxyCommand != NULL) {
|
||||||
ret = ssh_socket_connect_proxycommand(session->socket,
|
ret = ssh_socket_connect_proxycommand(session->socket,
|
||||||
session->opts.ProxyCommand);
|
session->opts.ProxyCommand);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ret=ssh_socket_connect(session->socket,
|
ret = ssh_socket_connect(session->socket,
|
||||||
session->opts.host,
|
session->opts.host,
|
||||||
session->opts.port > 0 ? session->opts.port : 22,
|
session->opts.port > 0 ? session->opts.port : 22,
|
||||||
session->opts.bindaddr);
|
session->opts.bindaddr);
|
||||||
}
|
}
|
||||||
if (ret == SSH_ERROR) {
|
if (ret == SSH_ERROR) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_status(session, 0.2f);
|
set_status(session, 0.2f);
|
||||||
|
|
||||||
|
session->alive = 1;
|
||||||
|
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||||
|
"Socket connecting, now waiting for the callbacks to work");
|
||||||
|
|
||||||
session->alive = 1;
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
|
|
||||||
pending:
|
pending:
|
||||||
session->pending_call_state=SSH_PENDING_CALL_CONNECT;
|
session->pending_call_state = SSH_PENDING_CALL_CONNECT;
|
||||||
if(ssh_is_blocking(session)) {
|
if(ssh_is_blocking(session)) {
|
||||||
int timeout = (session->opts.timeout * 1000) +
|
int timeout = (session->opts.timeout * 1000) +
|
||||||
(session->opts.timeout_usec / 1000);
|
(session->opts.timeout_usec / 1000);
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
timeout = 10 * 1000;
|
timeout = 10 * 1000;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PACKET,"Actual timeout : %d", timeout);
|
SSH_LOG(SSH_LOG_PACKET, "Actual timeout : %d", timeout);
|
||||||
ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
|
ret = ssh_handle_packets_termination(session, timeout,
|
||||||
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
ssh_connect_termination, session);
|
||||||
(ret == SSH_ERROR || !ssh_connect_termination(session))) {
|
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
||||||
ssh_set_error(session, SSH_FATAL,
|
(ret == SSH_ERROR || !ssh_connect_termination(session)))
|
||||||
"Timeout connecting to %s", session->opts.host);
|
{
|
||||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
ssh_set_error(session, SSH_FATAL,
|
||||||
}
|
"Timeout connecting to %s", session->opts.host);
|
||||||
}
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
else {
|
}
|
||||||
ret = ssh_handle_packets_termination(session,
|
} else {
|
||||||
SSH_TIMEOUT_NONBLOCKING,
|
ret = ssh_handle_packets_termination(session,
|
||||||
ssh_connect_termination,
|
SSH_TIMEOUT_NONBLOCKING,
|
||||||
session);
|
ssh_connect_termination,
|
||||||
if (ret == SSH_ERROR) {
|
session);
|
||||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
if (ret == SSH_ERROR) {
|
||||||
}
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PACKET,"current state : %d",session->session_state);
|
}
|
||||||
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
|
|
||||||
return SSH_AGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
session->pending_call_state=SSH_PENDING_CALL_NONE;
|
SSH_LOG(SSH_LOG_PACKET, "current state : %d", session->session_state);
|
||||||
if(session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED)
|
if (!ssh_is_blocking(session) && !ssh_connect_termination(session)) {
|
||||||
return SSH_ERROR;
|
return SSH_AGAIN;
|
||||||
return SSH_OK;
|
}
|
||||||
|
|
||||||
|
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
||||||
|
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||||
|
session->session_state == SSH_SESSION_STATE_DISCONNECTED)
|
||||||
|
{
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -701,6 +730,7 @@ error:
|
|||||||
}
|
}
|
||||||
session->opts.fd = SSH_INVALID_SOCKET;
|
session->opts.fd = SSH_INVALID_SOCKET;
|
||||||
session->session_state=SSH_SESSION_STATE_DISCONNECTED;
|
session->session_state=SSH_SESSION_STATE_DISCONNECTED;
|
||||||
|
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
||||||
|
|
||||||
while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
|
while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
|
||||||
ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
|
ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
|
||||||
@@ -750,7 +780,7 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *ssh_copyright(void) {
|
const char *ssh_copyright(void) {
|
||||||
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2019 "
|
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2021 "
|
||||||
"Aris Adamantiadis, Andreas Schneider "
|
"Aris Adamantiadis, Andreas Schneider "
|
||||||
"and libssh contributors. "
|
"and libssh contributors. "
|
||||||
"Distributed under the LGPL, please refer to COPYING "
|
"Distributed under the LGPL, please refer to COPYING "
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing)
|
|||||||
}
|
}
|
||||||
if (parse_entry) {
|
if (parse_entry) {
|
||||||
/* We actually care only about the first item */
|
/* We actually care only about the first item */
|
||||||
rv = ssh_config_parse_uri(cp, &username, &hostname, &port);
|
rv = ssh_config_parse_uri(cp, &username, &hostname, &port, false);
|
||||||
/* The rest of the list needs to be passed on */
|
/* The rest of the list needs to be passed on */
|
||||||
if (endp != NULL) {
|
if (endp != NULL) {
|
||||||
next = strdup(endp + 1);
|
next = strdup(endp + 1);
|
||||||
@@ -335,7 +335,7 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* The rest is just sanity-checked to avoid failures later */
|
/* The rest is just sanity-checked to avoid failures later */
|
||||||
rv = ssh_config_parse_uri(cp, NULL, NULL, NULL);
|
rv = ssh_config_parse_uri(cp, NULL, NULL, NULL, false);
|
||||||
}
|
}
|
||||||
if (rv != SSH_OK) {
|
if (rv != SSH_OK) {
|
||||||
goto out;
|
goto out;
|
||||||
@@ -425,6 +425,7 @@ ssh_config_parse_line(ssh_session session,
|
|||||||
opcode != SOC_HOST &&
|
opcode != SOC_HOST &&
|
||||||
opcode != SOC_MATCH &&
|
opcode != SOC_MATCH &&
|
||||||
opcode != SOC_INCLUDE &&
|
opcode != SOC_INCLUDE &&
|
||||||
|
opcode != SOC_IDENTITY &&
|
||||||
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
|
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
|
||||||
/* Skip all the options that were already applied */
|
/* Skip all the options that were already applied */
|
||||||
if (seen[opcode] != 0) {
|
if (seen[opcode] != 0) {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "libssh/config_parser.h"
|
#include "libssh/config_parser.h"
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
|
#include "libssh/misc.h"
|
||||||
|
|
||||||
char *ssh_config_get_cmd(char **str)
|
char *ssh_config_get_cmd(char **str)
|
||||||
{
|
{
|
||||||
@@ -133,12 +134,14 @@ int ssh_config_get_yesno(char **str, int notfound)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ssh_config_parse_uri(const char *tok,
|
int ssh_config_parse_uri(const char *tok,
|
||||||
char **username,
|
char **username,
|
||||||
char **hostname,
|
char **hostname,
|
||||||
char **port)
|
char **port,
|
||||||
|
bool ignore_port)
|
||||||
{
|
{
|
||||||
char *endp = NULL;
|
char *endp = NULL;
|
||||||
long port_n;
|
long port_n;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Sanitize inputs */
|
/* Sanitize inputs */
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
@@ -152,7 +155,7 @@ int ssh_config_parse_uri(const char *tok,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Username part (optional) */
|
/* Username part (optional) */
|
||||||
endp = strchr(tok, '@');
|
endp = strrchr(tok, '@');
|
||||||
if (endp != NULL) {
|
if (endp != NULL) {
|
||||||
/* Zero-length username is not valid */
|
/* Zero-length username is not valid */
|
||||||
if (tok == endp) {
|
if (tok == endp) {
|
||||||
@@ -180,12 +183,17 @@ int ssh_config_parse_uri(const char *tok,
|
|||||||
if (endp == NULL) {
|
if (endp == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!ignore_port) {
|
||||||
/* Hostnames or aliases expand to the last colon or to the end */
|
/* Hostnames or aliases expand to the last colon (if port is requested)
|
||||||
|
* or to the end */
|
||||||
endp = strrchr(tok, ':');
|
endp = strrchr(tok, ':');
|
||||||
if (endp == NULL) {
|
if (endp == NULL) {
|
||||||
endp = strchr(tok, '\0');
|
endp = strchr(tok, '\0');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* If no port is requested, expand to the end of line
|
||||||
|
* (to accommodate the IPv6 addresses) */
|
||||||
|
endp = strchr(tok, '\0');
|
||||||
}
|
}
|
||||||
if (tok == endp) {
|
if (tok == endp) {
|
||||||
/* Zero-length hostnames are not valid */
|
/* Zero-length hostnames are not valid */
|
||||||
@@ -196,6 +204,14 @@ int ssh_config_parse_uri(const char *tok,
|
|||||||
if (*hostname == NULL) {
|
if (*hostname == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
/* if not an ip, check syntax */
|
||||||
|
rc = ssh_is_ipaddr(*hostname);
|
||||||
|
if (rc == 0) {
|
||||||
|
rc = ssh_check_hostname_syntax(*hostname);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Skip also the closing bracket */
|
/* Skip also the closing bracket */
|
||||||
if (*endp == ']') {
|
if (*endp == ']') {
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif /* HAVE_SYS_TIME_H */
|
||||||
|
|
||||||
#include "libssh/libssh.h"
|
#include "libssh/libssh.h"
|
||||||
#include "libssh/misc.h"
|
#include "libssh/misc.h"
|
||||||
@@ -133,7 +136,7 @@ static int getai(const char *host, int port, struct addrinfo **ai)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssh_is_ipaddr(host)) {
|
if (ssh_is_ipaddr(host) == 1) {
|
||||||
/* this is an IP address */
|
/* this is an IP address */
|
||||||
SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host);
|
SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host);
|
||||||
hints.ai_flags |= AI_NUMERICHOST;
|
hints.ai_flags |= AI_NUMERICHOST;
|
||||||
|
|||||||
@@ -172,6 +172,11 @@ int ssh_client_curve25519_init(ssh_session session)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssh_client_curve25519_remove_callbacks(ssh_session session)
|
||||||
|
{
|
||||||
|
ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
static int ssh_curve25519_build_k(ssh_session session)
|
static int ssh_curve25519_build_k(ssh_session session)
|
||||||
{
|
{
|
||||||
ssh_curve25519_pubkey k;
|
ssh_curve25519_pubkey k;
|
||||||
@@ -179,8 +184,8 @@ static int ssh_curve25519_build_k(ssh_session session)
|
|||||||
#ifdef HAVE_OPENSSL_X25519
|
#ifdef HAVE_OPENSSL_X25519
|
||||||
EVP_PKEY_CTX *pctx = NULL;
|
EVP_PKEY_CTX *pctx = NULL;
|
||||||
EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
||||||
size_t shared_key_len;
|
size_t shared_key_len = sizeof(k);
|
||||||
int rc;
|
int rc, ret = SSH_ERROR;
|
||||||
|
|
||||||
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
|
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
|
||||||
session->next_crypto->curve25519_privkey,
|
session->next_crypto->curve25519_privkey,
|
||||||
@@ -197,8 +202,7 @@ static int ssh_curve25519_build_k(ssh_session session)
|
|||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Failed to initialize X25519 context: %s",
|
"Failed to initialize X25519 context: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
EVP_PKEY_free(pkey);
|
goto out;
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = EVP_PKEY_derive_init(pctx);
|
rc = EVP_PKEY_derive_init(pctx);
|
||||||
@@ -206,9 +210,7 @@ static int ssh_curve25519_build_k(ssh_session session)
|
|||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Failed to initialize X25519 key derivation: %s",
|
"Failed to initialize X25519 key derivation: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
EVP_PKEY_free(pkey);
|
goto out;
|
||||||
EVP_PKEY_CTX_free(pctx);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->server) {
|
if (session->server) {
|
||||||
@@ -224,9 +226,7 @@ static int ssh_curve25519_build_k(ssh_session session)
|
|||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Failed to create X25519 public key EVP_PKEY: %s",
|
"Failed to create X25519 public key EVP_PKEY: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
EVP_PKEY_free(pkey);
|
goto out;
|
||||||
EVP_PKEY_CTX_free(pctx);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
|
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
|
||||||
@@ -234,23 +234,23 @@ static int ssh_curve25519_build_k(ssh_session session)
|
|||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Failed to set peer X25519 public key: %s",
|
"Failed to set peer X25519 public key: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
EVP_PKEY_free(pkey);
|
goto out;
|
||||||
EVP_PKEY_free(pubkey);
|
|
||||||
EVP_PKEY_CTX_free(pctx);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = EVP_PKEY_derive(pctx,
|
rc = EVP_PKEY_derive(pctx, k, &shared_key_len);
|
||||||
k,
|
|
||||||
&shared_key_len);
|
|
||||||
if (rc != 1) {
|
if (rc != 1) {
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Failed to derive X25519 shared secret: %s",
|
"Failed to derive X25519 shared secret: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
EVP_PKEY_free(pkey);
|
goto out;
|
||||||
EVP_PKEY_free(pubkey);
|
}
|
||||||
EVP_PKEY_CTX_free(pctx);
|
ret = SSH_OK;
|
||||||
return SSH_ERROR;
|
out:
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
EVP_PKEY_free(pubkey);
|
||||||
|
EVP_PKEY_CTX_free(pctx);
|
||||||
|
if (ret == SSH_ERROR) {
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (session->server) {
|
if (session->server) {
|
||||||
@@ -290,7 +290,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
|
|||||||
(void)type;
|
(void)type;
|
||||||
(void)user;
|
(void)user;
|
||||||
|
|
||||||
ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks);
|
ssh_client_curve25519_remove_callbacks(session);
|
||||||
|
|
||||||
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||||
if (pubkey_blob == NULL) {
|
if (pubkey_blob == NULL) {
|
||||||
@@ -335,16 +335,10 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Send the MSG_NEWKEYS */
|
/* Send the MSG_NEWKEYS */
|
||||||
if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
|
rc = ssh_packet_send_newkeys(session);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc=ssh_packet_send(session);
|
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
|
||||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
@@ -382,12 +376,12 @@ void ssh_server_curve25519_init(ssh_session session){
|
|||||||
*/
|
*/
|
||||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||||
/* ECDH keys */
|
/* ECDH keys */
|
||||||
ssh_string q_c_string;
|
ssh_string q_c_string = NULL;
|
||||||
ssh_string q_s_string;
|
ssh_string q_s_string = NULL;
|
||||||
ssh_string server_pubkey_blob = NULL;
|
ssh_string server_pubkey_blob = NULL;
|
||||||
|
|
||||||
/* SSH host keys (rsa,dsa,ecdsa) */
|
/* SSH host keys (rsa,dsa,ecdsa) */
|
||||||
ssh_key privkey;
|
ssh_key privkey = NULL;
|
||||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||||
ssh_string sig_blob = NULL;
|
ssh_string sig_blob = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -407,7 +401,6 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
|||||||
SSH_FATAL,
|
SSH_FATAL,
|
||||||
"Incorrect size for server Curve25519 public key: %zu",
|
"Incorrect size for server Curve25519 public key: %zu",
|
||||||
ssh_string_len(q_c_string));
|
ssh_string_len(q_c_string));
|
||||||
SSH_STRING_FREE(q_c_string);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,12 +458,17 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
|||||||
/* add ecdh public key */
|
/* add ecdh public key */
|
||||||
q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
|
q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
|
||||||
if (q_s_string == NULL) {
|
if (q_s_string == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(q_s_string,
|
rc = ssh_string_fill(q_s_string,
|
||||||
session->next_crypto->curve25519_server_pubkey,
|
session->next_crypto->curve25519_server_pubkey,
|
||||||
CURVE25519_PUBKEY_SIZE);
|
CURVE25519_PUBKEY_SIZE);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Could not copy public key");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, q_s_string);
|
rc = ssh_buffer_add_ssh_string(session->out_buffer, q_s_string);
|
||||||
SSH_STRING_FREE(q_s_string);
|
SSH_STRING_FREE(q_s_string);
|
||||||
@@ -498,21 +496,18 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the MSG_NEWKEYS */
|
|
||||||
rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
rc = ssh_packet_send(session);
|
|
||||||
|
/* Send the MSG_NEWKEYS */
|
||||||
|
rc = ssh_packet_send_newkeys(session);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
error:
|
error:
|
||||||
|
SSH_STRING_FREE(q_c_string);
|
||||||
|
SSH_STRING_FREE(q_s_string);
|
||||||
ssh_buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
|
|||||||
26
src/dh-gex.c
26
src/dh-gex.c
@@ -238,6 +238,11 @@ error:
|
|||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssh_client_dhgex_remove_callbacks(ssh_session session)
|
||||||
|
{
|
||||||
|
ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
||||||
{
|
{
|
||||||
struct ssh_crypto_struct *crypto=session->next_crypto;
|
struct ssh_crypto_struct *crypto=session->next_crypto;
|
||||||
@@ -248,7 +253,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
|||||||
(void)user;
|
(void)user;
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_REPLY received");
|
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_REPLY received");
|
||||||
|
|
||||||
ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks);
|
ssh_client_dhgex_remove_callbacks(session);
|
||||||
rc = ssh_buffer_unpack(packet,
|
rc = ssh_buffer_unpack(packet,
|
||||||
"SBS",
|
"SBS",
|
||||||
&pubkey_blob, &server_pubkey,
|
&pubkey_blob, &server_pubkey,
|
||||||
@@ -263,6 +268,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
|||||||
bignum_safe_free(server_pubkey);
|
bignum_safe_free(server_pubkey);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
/* The ownership was passed to the crypto structure */
|
||||||
|
server_pubkey = NULL;
|
||||||
|
|
||||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||||
SSH_STRING_FREE(pubkey_blob);
|
SSH_STRING_FREE(pubkey_blob);
|
||||||
@@ -280,19 +287,15 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Send the MSG_NEWKEYS */
|
/* Send the MSG_NEWKEYS */
|
||||||
if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
|
rc = ssh_packet_send_newkeys(session);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_packet_send(session);
|
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
|
||||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
error:
|
error:
|
||||||
|
SSH_STRING_FREE(pubkey_blob);
|
||||||
ssh_dh_cleanup(session->next_crypto);
|
ssh_dh_cleanup(session->next_crypto);
|
||||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
|
|
||||||
@@ -366,8 +369,13 @@ static bool dhgroup_better_size(uint32_t pmin,
|
|||||||
*/
|
*/
|
||||||
static bool invn_chance(int n)
|
static bool invn_chance(int n)
|
||||||
{
|
{
|
||||||
uint32_t nounce;
|
uint32_t nounce = 0;
|
||||||
ssh_get_random(&nounce, sizeof(nounce), 0);
|
int ok;
|
||||||
|
|
||||||
|
ok = ssh_get_random(&nounce, sizeof(nounce), 0);
|
||||||
|
if (!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return (nounce % n) == 0;
|
return (nounce % n) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
src/dh.c
26
src/dh.c
@@ -342,6 +342,11 @@ error:
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssh_client_dh_remove_callbacks(ssh_session session)
|
||||||
|
{
|
||||||
|
ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
||||||
struct ssh_crypto_struct *crypto=session->next_crypto;
|
struct ssh_crypto_struct *crypto=session->next_crypto;
|
||||||
ssh_string pubkey_blob = NULL;
|
ssh_string pubkey_blob = NULL;
|
||||||
@@ -351,7 +356,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
|||||||
(void)type;
|
(void)type;
|
||||||
(void)user;
|
(void)user;
|
||||||
|
|
||||||
ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
|
ssh_client_dh_remove_callbacks(session);
|
||||||
|
|
||||||
rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey,
|
rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey,
|
||||||
&crypto->dh_server_signature);
|
&crypto->dh_server_signature);
|
||||||
@@ -361,6 +366,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
|||||||
rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR,
|
rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR,
|
||||||
NULL, server_pubkey);
|
NULL, server_pubkey);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
|
SSH_STRING_FREE(pubkey_blob);
|
||||||
bignum_safe_free(server_pubkey);
|
bignum_safe_free(server_pubkey);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -380,16 +386,10 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Send the MSG_NEWKEYS */
|
/* Send the MSG_NEWKEYS */
|
||||||
if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
|
rc = ssh_packet_send_newkeys(session);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc=ssh_packet_send(session);
|
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
|
||||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
error:
|
error:
|
||||||
@@ -482,6 +482,7 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
|
|||||||
switch (crypto->kex_type){
|
switch (crypto->kex_type){
|
||||||
case SSH_KEX_DH_GROUP1_SHA1:
|
case SSH_KEX_DH_GROUP1_SHA1:
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
|
case SSH_KEX_DH_GROUP14_SHA256:
|
||||||
case SSH_KEX_DH_GROUP16_SHA512:
|
case SSH_KEX_DH_GROUP16_SHA512:
|
||||||
case SSH_KEX_DH_GROUP18_SHA512:
|
case SSH_KEX_DH_GROUP18_SHA512:
|
||||||
packet_type = SSH2_MSG_KEXDH_REPLY;
|
packet_type = SSH2_MSG_KEXDH_REPLY;
|
||||||
@@ -525,15 +526,12 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
|
|||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_[GEX]_REPLY");
|
SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_[GEX]_REPLY");
|
||||||
|
|
||||||
if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
|
|
||||||
ssh_buffer_reinit(session->out_buffer);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
|
session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
|
||||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
/* Send the MSG_NEWKEYS */
|
||||||
|
rc = ssh_packet_send_newkeys(session);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
|
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
|||||||
rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator);
|
rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator);
|
||||||
break;
|
break;
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
|
case SSH_KEX_DH_GROUP14_SHA256:
|
||||||
rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator);
|
rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator);
|
||||||
break;
|
break;
|
||||||
case SSH_KEX_DH_GROUP16_SHA512:
|
case SSH_KEX_DH_GROUP16_SHA512:
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
|||||||
rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator);
|
rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator);
|
||||||
break;
|
break;
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
|
case SSH_KEX_DH_GROUP14_SHA256:
|
||||||
rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator);
|
rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator);
|
||||||
break;
|
break;
|
||||||
case SSH_KEX_DH_GROUP16_SHA512:
|
case SSH_KEX_DH_GROUP16_SHA512:
|
||||||
|
|||||||
15
src/ecdh.c
15
src/ecdh.c
@@ -43,6 +43,11 @@ struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks = {
|
|||||||
.user = NULL
|
.user = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ssh_client_ecdh_remove_callbacks(ssh_session session)
|
||||||
|
{
|
||||||
|
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
|
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
|
||||||
* a SSH_MSG_NEWKEYS
|
* a SSH_MSG_NEWKEYS
|
||||||
@@ -55,7 +60,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){
|
|||||||
(void)type;
|
(void)type;
|
||||||
(void)user;
|
(void)user;
|
||||||
|
|
||||||
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
|
ssh_client_ecdh_remove_callbacks(session);
|
||||||
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||||
if (pubkey_blob == NULL) {
|
if (pubkey_blob == NULL) {
|
||||||
ssh_set_error(session,SSH_FATAL, "No public key in packet");
|
ssh_set_error(session,SSH_FATAL, "No public key in packet");
|
||||||
@@ -88,16 +93,10 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Send the MSG_NEWKEYS */
|
/* Send the MSG_NEWKEYS */
|
||||||
if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
|
rc = ssh_packet_send_newkeys(session);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc=ssh_packet_send(session);
|
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
|
||||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
|
|||||||
@@ -323,18 +323,12 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the MSG_NEWKEYS */
|
|
||||||
rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
rc = ssh_packet_send(session);
|
/* Send the MSG_NEWKEYS */
|
||||||
if (rc == SSH_ERROR){
|
rc = ssh_packet_send_newkeys(session);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
|
||||||
|
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -372,17 +372,13 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
/* Send the MSG_NEWKEYS */
|
/* Send the MSG_NEWKEYS */
|
||||||
rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
|
rc = ssh_packet_send_newkeys(session);
|
||||||
if (rc != SSH_OK) {
|
if (rc == SSH_ERROR) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
|
||||||
rc = ssh_packet_send(session);
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
gcry_sexp_release(param);
|
gcry_sexp_release(param);
|
||||||
gcry_sexp_release(key);
|
gcry_sexp_release(key);
|
||||||
|
|||||||
@@ -300,16 +300,13 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
|
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||||
if (rc < 0) {
|
/* Send the MSG_NEWKEYS */
|
||||||
rc = SSH_ERROR;
|
rc = ssh_packet_send_newkeys(session);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
|
||||||
rc = ssh_packet_send(session);
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mbedtls_ecp_group_free(&grp);
|
mbedtls_ecp_group_free(&grp);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
|
|||||||
2
src/external/bcrypt_pbkdf.c
vendored
2
src/external/bcrypt_pbkdf.c
vendored
@@ -87,7 +87,7 @@ bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
|
|||||||
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
|
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
|
||||||
&j);
|
&j);
|
||||||
for (i = 0; i < 64; i++)
|
for (i = 0; i < 64; i++)
|
||||||
ssh_blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
|
ssh_blf_enc(&state, cdata, BCRYPT_BLOCKS/2);
|
||||||
|
|
||||||
/* copy out */
|
/* copy out */
|
||||||
for (i = 0; i < BCRYPT_BLOCKS; i++) {
|
for (i = 0; i < BCRYPT_BLOCKS; i++) {
|
||||||
|
|||||||
8
src/external/ed25519.c
vendored
8
src/external/ed25519.c
vendored
@@ -77,8 +77,8 @@ static void get_hram(unsigned char *hram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int crypto_sign_ed25519_keypair(unsigned char *pk,
|
int crypto_sign_ed25519_keypair(ed25519_pubkey pk,
|
||||||
unsigned char *sk)
|
ed25519_privkey sk)
|
||||||
{
|
{
|
||||||
sc25519 scsk;
|
sc25519 scsk;
|
||||||
ge25519 gepk;
|
ge25519 gepk;
|
||||||
@@ -114,7 +114,7 @@ int crypto_sign_ed25519(unsigned char *sm,
|
|||||||
uint64_t *smlen,
|
uint64_t *smlen,
|
||||||
const unsigned char *m,
|
const unsigned char *m,
|
||||||
uint64_t mlen,
|
uint64_t mlen,
|
||||||
const unsigned char *sk)
|
const ed25519_privkey sk)
|
||||||
{
|
{
|
||||||
sc25519 sck, scs, scsk;
|
sc25519 sck, scs, scsk;
|
||||||
ge25519 ger;
|
ge25519 ger;
|
||||||
@@ -177,7 +177,7 @@ int crypto_sign_ed25519_open(unsigned char *m,
|
|||||||
uint64_t *mlen,
|
uint64_t *mlen,
|
||||||
const unsigned char *sm,
|
const unsigned char *sm,
|
||||||
uint64_t smlen,
|
uint64_t smlen,
|
||||||
const unsigned char *pk)
|
const ed25519_pubkey pk)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|||||||
@@ -255,7 +255,11 @@ int ssh_getpass(const char *prompt,
|
|||||||
|
|
||||||
/* disable nonblocking I/O */
|
/* disable nonblocking I/O */
|
||||||
if (fd & O_NDELAY) {
|
if (fd & O_NDELAY) {
|
||||||
fcntl(0, F_SETFL, fd & ~O_NDELAY);
|
ok = fcntl(0, F_SETFL, fd & ~O_NDELAY);
|
||||||
|
if (ok < 0) {
|
||||||
|
perror("fcntl");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = ssh_gets(prompt, buf, len, verify);
|
ok = ssh_gets(prompt, buf, len, verify);
|
||||||
@@ -267,7 +271,11 @@ int ssh_getpass(const char *prompt,
|
|||||||
|
|
||||||
/* close fd */
|
/* close fd */
|
||||||
if (fd & O_NDELAY) {
|
if (fd & O_NDELAY) {
|
||||||
fcntl(0, F_SETFL, fd);
|
ok = fcntl(0, F_SETFL, fd);
|
||||||
|
if (ok < 0) {
|
||||||
|
perror("fcntl");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
|||||||
36
src/gssapi.c
36
src/gssapi.c
@@ -223,6 +223,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
|||||||
"indicate mechs",
|
"indicate mechs",
|
||||||
maj_stat,
|
maj_stat,
|
||||||
min_stat);
|
min_stat);
|
||||||
|
gss_release_oid_set(&min_stat, &both_supported);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,8 +260,10 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
/* from now we have room for context */
|
/* from now we have room for context */
|
||||||
if (ssh_gssapi_init(session) == SSH_ERROR)
|
if (ssh_gssapi_init(session) == SSH_ERROR) {
|
||||||
|
gss_release_oid_set(&min_stat, &both_supported);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
name_buf.value = service_name;
|
name_buf.value = service_name;
|
||||||
name_buf.length = strlen(name_buf.value) + 1;
|
name_buf.length = strlen(name_buf.value) + 1;
|
||||||
@@ -272,6 +275,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
|||||||
"importing name",
|
"importing name",
|
||||||
maj_stat,
|
maj_stat,
|
||||||
min_stat);
|
min_stat);
|
||||||
|
gss_release_oid_set(&min_stat, &both_supported);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,6 +342,7 @@ static char *ssh_gssapi_name_to_char(gss_name_t name){
|
|||||||
min_stat);
|
min_stat);
|
||||||
ptr = malloc(buffer.length + 1);
|
ptr = malloc(buffer.length + 1);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
|
gss_release_buffer(&min_stat, &buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy(ptr, buffer.value, buffer.length);
|
memcpy(ptr, buffer.value, buffer.length);
|
||||||
@@ -421,6 +426,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
|||||||
"Gssapi error",
|
"Gssapi error",
|
||||||
maj_stat,
|
maj_stat,
|
||||||
min_stat);
|
min_stat);
|
||||||
|
gss_release_buffer(&min_stat, &output_token);
|
||||||
ssh_auth_reply_default(session,0);
|
ssh_auth_reply_default(session,0);
|
||||||
ssh_gssapi_free(session);
|
ssh_gssapi_free(session);
|
||||||
session->gssapi=NULL;
|
session->gssapi=NULL;
|
||||||
@@ -438,6 +444,9 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
|||||||
(size_t)output_token.length, output_token.value);
|
(size_t)output_token.length, output_token.value);
|
||||||
ssh_packet_send(session);
|
ssh_packet_send(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gss_release_buffer(&min_stat, &output_token);
|
||||||
|
|
||||||
if(maj_stat == GSS_S_COMPLETE){
|
if(maj_stat == GSS_S_COMPLETE){
|
||||||
session->gssapi->state = SSH_GSSAPI_STATE_RCV_MIC;
|
session->gssapi->state = SSH_GSSAPI_STATE_RCV_MIC;
|
||||||
}
|
}
|
||||||
@@ -465,8 +474,8 @@ static ssh_buffer ssh_gssapi_build_mic(ssh_session session)
|
|||||||
|
|
||||||
rc = ssh_buffer_pack(mic_buffer,
|
rc = ssh_buffer_pack(mic_buffer,
|
||||||
"dPbsss",
|
"dPbsss",
|
||||||
crypto->digest_len,
|
crypto->session_id_len,
|
||||||
(size_t)crypto->digest_len, crypto->session_id,
|
crypto->session_id_len, crypto->session_id,
|
||||||
SSH2_MSG_USERAUTH_REQUEST,
|
SSH2_MSG_USERAUTH_REQUEST,
|
||||||
session->gssapi->user,
|
session->gssapi->user,
|
||||||
"ssh-connection",
|
"ssh-connection",
|
||||||
@@ -638,7 +647,7 @@ fail:
|
|||||||
static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
|
static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
|
||||||
{
|
{
|
||||||
OM_uint32 maj_stat, min_stat, lifetime;
|
OM_uint32 maj_stat, min_stat, lifetime;
|
||||||
gss_OID_set actual_mechs;
|
gss_OID_set actual_mechs = GSS_C_NO_OID_SET;
|
||||||
gss_buffer_desc namebuf;
|
gss_buffer_desc namebuf;
|
||||||
gss_name_t client_id = GSS_C_NO_NAME;
|
gss_name_t client_id = GSS_C_NO_NAME;
|
||||||
gss_OID oid;
|
gss_OID oid;
|
||||||
@@ -700,6 +709,7 @@ static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
|
|||||||
ret = SSH_OK;
|
ret = SSH_OK;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
gss_release_oid_set(&min_stat, &actual_mechs);
|
||||||
gss_release_name(&min_stat, &client_id);
|
gss_release_name(&min_stat, &client_id);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -713,7 +723,7 @@ end:
|
|||||||
*/
|
*/
|
||||||
int ssh_gssapi_auth_mic(ssh_session session){
|
int ssh_gssapi_auth_mic(ssh_session session){
|
||||||
size_t i;
|
size_t i;
|
||||||
gss_OID_set selected; /* oid selected for authentication */
|
gss_OID_set selected = GSS_C_NO_OID_SET; /* oid selected for authentication */
|
||||||
ssh_string *oids = NULL;
|
ssh_string *oids = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
size_t n_oids = 0;
|
size_t n_oids = 0;
|
||||||
@@ -790,6 +800,8 @@ out:
|
|||||||
SSH_STRING_FREE(oids[i]);
|
SSH_STRING_FREE(oids[i]);
|
||||||
}
|
}
|
||||||
free(oids);
|
free(oids);
|
||||||
|
gss_release_oid_set(&min_stat, &selected);
|
||||||
|
|
||||||
if (rc != SSH_ERROR) {
|
if (rc != SSH_ERROR) {
|
||||||
return SSH_AUTH_AGAIN;
|
return SSH_AUTH_AGAIN;
|
||||||
}
|
}
|
||||||
@@ -893,6 +905,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){
|
|||||||
ssh_packet_send(session);
|
ssh_packet_send(session);
|
||||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN;
|
session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gss_release_buffer(&min_stat, &output_token);
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -921,9 +935,11 @@ static int ssh_gssapi_send_mic(ssh_session session){
|
|||||||
|
|
||||||
maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT,
|
maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT,
|
||||||
&mic_buf, &mic_token_buf);
|
&mic_buf, &mic_token_buf);
|
||||||
|
|
||||||
|
SSH_BUFFER_FREE(mic_buffer);
|
||||||
|
|
||||||
if (GSS_ERROR(maj_stat)){
|
if (GSS_ERROR(maj_stat)){
|
||||||
SSH_BUFFER_FREE(mic_buffer);
|
ssh_gssapi_log_error(SSH_LOG_DEBUG,
|
||||||
ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
|
|
||||||
"generating MIC",
|
"generating MIC",
|
||||||
maj_stat,
|
maj_stat,
|
||||||
min_stat);
|
min_stat);
|
||||||
@@ -935,8 +951,10 @@ static int ssh_gssapi_send_mic(ssh_session session){
|
|||||||
SSH2_MSG_USERAUTH_GSSAPI_MIC,
|
SSH2_MSG_USERAUTH_GSSAPI_MIC,
|
||||||
mic_token_buf.length,
|
mic_token_buf.length,
|
||||||
(size_t)mic_token_buf.length, mic_token_buf.value);
|
(size_t)mic_token_buf.length, mic_token_buf.value);
|
||||||
|
|
||||||
|
gss_release_buffer(&min_stat, &mic_token_buf);
|
||||||
|
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
SSH_BUFFER_FREE(mic_buffer);
|
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -1005,6 +1023,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
|||||||
ssh_packet_send(session);
|
ssh_packet_send(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gss_release_buffer(&min_stat, &output_token);
|
||||||
|
|
||||||
if (maj_stat == GSS_S_COMPLETE) {
|
if (maj_stat == GSS_S_COMPLETE) {
|
||||||
ssh_gssapi_send_mic(session);
|
ssh_gssapi_send_mic(session);
|
||||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT;
|
session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT;
|
||||||
|
|||||||
47
src/init.c
47
src/init.c
@@ -106,7 +106,6 @@ _ret:
|
|||||||
*
|
*
|
||||||
* This functions is automatically called when the library is loaded.
|
* This functions is automatically called when the library is loaded.
|
||||||
*
|
*
|
||||||
* @returns 0 on success, -1 if an error occured.
|
|
||||||
*/
|
*/
|
||||||
void libssh_constructor(void)
|
void libssh_constructor(void)
|
||||||
{
|
{
|
||||||
@@ -136,14 +135,20 @@ void libssh_constructor(void)
|
|||||||
/**
|
/**
|
||||||
* @brief Initialize global cryptographic data structures.
|
* @brief Initialize global cryptographic data structures.
|
||||||
*
|
*
|
||||||
* Since version 0.8.0, it is not necessary to call this function on systems
|
* Since version 0.8.0, when libssh is dynamically linked, it is not necessary
|
||||||
* which are fully supported with regards to threading (that is, system with
|
* to call this function on systems which are fully supported with regards to
|
||||||
* pthreads available).
|
* threading (that is, system with pthreads available).
|
||||||
|
*
|
||||||
|
* If libssh is statically linked, it is necessary to explicitly call ssh_init()
|
||||||
|
* before calling any other provided API, and it is necessary to explicitly call
|
||||||
|
* ssh_finalize() to free the allocated resources before exiting.
|
||||||
*
|
*
|
||||||
* If the library is already initialized, increments the _ssh_initialized
|
* If the library is already initialized, increments the _ssh_initialized
|
||||||
* counter and return the error code cached in _ssh_init_ret.
|
* counter and return the error code cached in _ssh_init_ret.
|
||||||
*
|
*
|
||||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
||||||
|
*
|
||||||
|
* @see ssh_finalize()
|
||||||
*/
|
*/
|
||||||
int ssh_init(void) {
|
int ssh_init(void) {
|
||||||
return _ssh_init(0);
|
return _ssh_init(0);
|
||||||
@@ -188,8 +193,6 @@ _ret:
|
|||||||
*
|
*
|
||||||
* This function is automatically called when the library is unloaded.
|
* This function is automatically called when the library is unloaded.
|
||||||
*
|
*
|
||||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void libssh_destructor(void)
|
void libssh_destructor(void)
|
||||||
{
|
{
|
||||||
@@ -205,8 +208,13 @@ void libssh_destructor(void)
|
|||||||
/**
|
/**
|
||||||
* @brief Finalize and cleanup all libssh and cryptographic data structures.
|
* @brief Finalize and cleanup all libssh and cryptographic data structures.
|
||||||
*
|
*
|
||||||
* Since version 0.8.0, it is not necessary to call this function, since it is
|
* Since version 0.8.0, when libssh is dynamically linked, it is not necessary
|
||||||
* automatically called when the library is unloaded.
|
* to call this function, since it is automatically called when the library is
|
||||||
|
* unloaded.
|
||||||
|
*
|
||||||
|
* If libssh is statically linked, it is necessary to explicitly call ssh_init()
|
||||||
|
* before calling any other provided API, and it is necessary to explicitly call
|
||||||
|
* ssh_finalize() to free the allocated resources before exiting.
|
||||||
*
|
*
|
||||||
* If ssh_init() is called explicitly, then ssh_finalize() must be called
|
* If ssh_init() is called explicitly, then ssh_finalize() must be called
|
||||||
* explicitly.
|
* explicitly.
|
||||||
@@ -214,9 +222,9 @@ void libssh_destructor(void)
|
|||||||
* When called, decrements the counter _ssh_initialized. If the counter reaches
|
* When called, decrements the counter _ssh_initialized. If the counter reaches
|
||||||
* zero, then the libssh and cryptographic data structures are cleaned up.
|
* zero, then the libssh and cryptographic data structures are cleaned up.
|
||||||
*
|
*
|
||||||
* @returns 0 on succes, -1 if an error occured.
|
* @returns 0 on success, -1 if an error occurred.
|
||||||
*
|
*
|
||||||
@returns 0 otherwise
|
* @see ssh_init()
|
||||||
*/
|
*/
|
||||||
int ssh_finalize(void) {
|
int ssh_finalize(void) {
|
||||||
return _ssh_finalize(0);
|
return _ssh_finalize(0);
|
||||||
@@ -253,4 +261,23 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
|||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @brief Return whether the library is initialized
|
||||||
|
*
|
||||||
|
* @returns true if the library is initialized; false otherwise.
|
||||||
|
*
|
||||||
|
* @see ssh_init()
|
||||||
|
*/
|
||||||
|
bool is_ssh_initialized(void) {
|
||||||
|
|
||||||
|
bool is_initialized = false;
|
||||||
|
|
||||||
|
ssh_mutex_lock(&ssh_init_mutex);
|
||||||
|
is_initialized = _ssh_initialized > 0;
|
||||||
|
ssh_mutex_unlock(&ssh_init_mutex);
|
||||||
|
|
||||||
|
return is_initialized;
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
146
src/kdf.c
146
src/kdf.c
@@ -58,65 +58,102 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->digest_type = type;
|
ctx->digest_type = type;
|
||||||
switch(type){
|
switch (type) {
|
||||||
case SSH_KDF_SHA1:
|
case SSH_KDF_SHA1:
|
||||||
ctx->ctx.sha1_ctx = sha1_init();
|
ctx->ctx.sha1_ctx = sha1_init();
|
||||||
|
if (ctx->ctx.sha1_ctx == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
case SSH_KDF_SHA256:
|
case SSH_KDF_SHA256:
|
||||||
ctx->ctx.sha256_ctx = sha256_init();
|
ctx->ctx.sha256_ctx = sha256_init();
|
||||||
|
if (ctx->ctx.sha256_ctx == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
case SSH_KDF_SHA384:
|
case SSH_KDF_SHA384:
|
||||||
ctx->ctx.sha384_ctx = sha384_init();
|
ctx->ctx.sha384_ctx = sha384_init();
|
||||||
|
if (ctx->ctx.sha384_ctx == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
case SSH_KDF_SHA512:
|
case SSH_KDF_SHA512:
|
||||||
ctx->ctx.sha512_ctx = sha512_init();
|
ctx->ctx.sha512_ctx = sha512_init();
|
||||||
|
if (ctx->ctx.sha512_ctx == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
default:
|
|
||||||
SAFE_FREE(ctx);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
err:
|
||||||
|
SAFE_FREE(ctx);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len)
|
static void ssh_mac_ctx_free(ssh_mac_ctx ctx)
|
||||||
{
|
{
|
||||||
switch(ctx->digest_type){
|
if (ctx == NULL) {
|
||||||
case SSH_KDF_SHA1:
|
return;
|
||||||
sha1_update(ctx->ctx.sha1_ctx, data, len);
|
|
||||||
break;
|
|
||||||
case SSH_KDF_SHA256:
|
|
||||||
sha256_update(ctx->ctx.sha256_ctx, data, len);
|
|
||||||
break;
|
|
||||||
case SSH_KDF_SHA384:
|
|
||||||
sha384_update(ctx->ctx.sha384_ctx, data, len);
|
|
||||||
break;
|
|
||||||
case SSH_KDF_SHA512:
|
|
||||||
sha512_update(ctx->ctx.sha512_ctx, data, len);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx)
|
switch (ctx->digest_type) {
|
||||||
{
|
|
||||||
switch(ctx->digest_type){
|
|
||||||
case SSH_KDF_SHA1:
|
case SSH_KDF_SHA1:
|
||||||
sha1_final(md,ctx->ctx.sha1_ctx);
|
sha1_ctx_free(ctx->ctx.sha1_ctx);
|
||||||
break;
|
break;
|
||||||
case SSH_KDF_SHA256:
|
case SSH_KDF_SHA256:
|
||||||
sha256_final(md,ctx->ctx.sha256_ctx);
|
sha256_ctx_free(ctx->ctx.sha256_ctx);
|
||||||
break;
|
break;
|
||||||
case SSH_KDF_SHA384:
|
case SSH_KDF_SHA384:
|
||||||
sha384_final(md,ctx->ctx.sha384_ctx);
|
sha384_ctx_free(ctx->ctx.sha384_ctx);
|
||||||
break;
|
break;
|
||||||
case SSH_KDF_SHA512:
|
case SSH_KDF_SHA512:
|
||||||
sha512_final(md,ctx->ctx.sha512_ctx);
|
sha512_ctx_free(ctx->ctx.sha512_ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SAFE_FREE(ctx);
|
SAFE_FREE(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len)
|
||||||
|
{
|
||||||
|
switch (ctx->digest_type) {
|
||||||
|
case SSH_KDF_SHA1:
|
||||||
|
return sha1_update(ctx->ctx.sha1_ctx, data, len);
|
||||||
|
case SSH_KDF_SHA256:
|
||||||
|
return sha256_update(ctx->ctx.sha256_ctx, data, len);
|
||||||
|
case SSH_KDF_SHA384:
|
||||||
|
return sha384_update(ctx->ctx.sha384_ctx, data, len);
|
||||||
|
case SSH_KDF_SHA512:
|
||||||
|
return sha512_update(ctx->ctx.sha512_ctx, data, len);
|
||||||
|
}
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx)
|
||||||
|
{
|
||||||
|
int rc = SSH_ERROR;
|
||||||
|
|
||||||
|
switch (ctx->digest_type) {
|
||||||
|
case SSH_KDF_SHA1:
|
||||||
|
rc = sha1_final(md, ctx->ctx.sha1_ctx);
|
||||||
|
break;
|
||||||
|
case SSH_KDF_SHA256:
|
||||||
|
rc = sha256_final(md, ctx->ctx.sha256_ctx);
|
||||||
|
break;
|
||||||
|
case SSH_KDF_SHA384:
|
||||||
|
rc = sha384_final(md, ctx->ctx.sha384_ctx);
|
||||||
|
break;
|
||||||
|
case SSH_KDF_SHA512:
|
||||||
|
rc = sha512_final(md, ctx->ctx.sha512_ctx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SAFE_FREE(ctx);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
||||||
unsigned char *key, size_t key_len,
|
unsigned char *key,
|
||||||
int key_type, unsigned char *output,
|
size_t key_len,
|
||||||
|
int key_type,
|
||||||
|
unsigned char *output,
|
||||||
size_t requested_len)
|
size_t requested_len)
|
||||||
{
|
{
|
||||||
/* Can't use VLAs with Visual Studio, so allocate the biggest
|
/* Can't use VLAs with Visual Studio, so allocate the biggest
|
||||||
@@ -125,6 +162,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
|||||||
size_t output_len = crypto->digest_len;
|
size_t output_len = crypto->digest_len;
|
||||||
char letter = key_type;
|
char letter = key_type;
|
||||||
ssh_mac_ctx ctx;
|
ssh_mac_ctx ctx;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (DIGEST_MAX_LEN < crypto->digest_len) {
|
if (DIGEST_MAX_LEN < crypto->digest_len) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -135,11 +173,30 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_mac_update(ctx, key, key_len);
|
rc = ssh_mac_update(ctx, key, key_len);
|
||||||
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
if (rc != SSH_OK) {
|
||||||
ssh_mac_update(ctx, &letter, 1);
|
ssh_mac_ctx_free(ctx);
|
||||||
ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
|
return -1;
|
||||||
ssh_mac_final(digest, ctx);
|
}
|
||||||
|
rc = ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_mac_ctx_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = ssh_mac_update(ctx, &letter, 1);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_mac_ctx_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_mac_ctx_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = ssh_mac_final(digest, ctx);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (requested_len < output_len) {
|
if (requested_len < output_len) {
|
||||||
output_len = requested_len;
|
output_len = requested_len;
|
||||||
@@ -151,10 +208,25 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
|||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ssh_mac_update(ctx, key, key_len);
|
rc = ssh_mac_update(ctx, key, key_len);
|
||||||
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
if (rc != SSH_OK) {
|
||||||
ssh_mac_update(ctx, output, output_len);
|
ssh_mac_ctx_free(ctx);
|
||||||
ssh_mac_final(digest, ctx);
|
return -1;
|
||||||
|
}
|
||||||
|
rc = ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_mac_ctx_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = ssh_mac_update(ctx, output, output_len);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
ssh_mac_ctx_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = ssh_mac_final(digest, ctx);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (requested_len < output_len + crypto->digest_len) {
|
if (requested_len < output_len + crypto->digest_len) {
|
||||||
memcpy(output + output_len, digest, requested_len - output_len);
|
memcpy(output + output_len, digest, requested_len - output_len);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
592
src/kex.c
592
src/kex.c
@@ -28,6 +28,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "libssh/libssh.h"
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/buffer.h"
|
#include "libssh/buffer.h"
|
||||||
#include "libssh/dh.h"
|
#include "libssh/dh.h"
|
||||||
@@ -154,6 +155,7 @@
|
|||||||
ECDH \
|
ECDH \
|
||||||
"diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \
|
"diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \
|
||||||
GEX_SHA256 \
|
GEX_SHA256 \
|
||||||
|
"diffie-hellman-group14-sha256," \
|
||||||
"diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
"diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
||||||
#define KEY_EXCHANGE_SUPPORTED \
|
#define KEY_EXCHANGE_SUPPORTED \
|
||||||
GEX_SHA1 \
|
GEX_SHA1 \
|
||||||
@@ -161,6 +163,9 @@
|
|||||||
|
|
||||||
/* RFC 8308 */
|
/* RFC 8308 */
|
||||||
#define KEX_EXTENSION_CLIENT "ext-info-c"
|
#define KEX_EXTENSION_CLIENT "ext-info-c"
|
||||||
|
/* Strict kex mitigation against CVE-2023-48795 */
|
||||||
|
#define KEX_STRICT_CLIENT "kex-strict-c-v00@openssh.com"
|
||||||
|
#define KEX_STRICT_SERVER "kex-strict-s-v00@openssh.com"
|
||||||
|
|
||||||
/* Allowed algorithms in FIPS mode */
|
/* Allowed algorithms in FIPS mode */
|
||||||
#define FIPS_ALLOWED_CIPHERS "aes256-gcm@openssh.com,"\
|
#define FIPS_ALLOWED_CIPHERS "aes256-gcm@openssh.com,"\
|
||||||
@@ -183,6 +188,7 @@
|
|||||||
"ecdh-sha2-nistp384,"\
|
"ecdh-sha2-nistp384,"\
|
||||||
"ecdh-sha2-nistp521,"\
|
"ecdh-sha2-nistp521,"\
|
||||||
"diffie-hellman-group-exchange-sha256,"\
|
"diffie-hellman-group-exchange-sha256,"\
|
||||||
|
"diffie-hellman-group14-sha256,"\
|
||||||
"diffie-hellman-group16-sha512,"\
|
"diffie-hellman-group16-sha512,"\
|
||||||
"diffie-hellman-group18-sha512"
|
"diffie-hellman-group18-sha512"
|
||||||
|
|
||||||
@@ -303,6 +309,10 @@ static int cmp_first_kex_algo(const char *client_str,
|
|||||||
|
|
||||||
int is_wrong = 1;
|
int is_wrong = 1;
|
||||||
|
|
||||||
|
if (client_str == NULL || server_str == NULL) {
|
||||||
|
return is_wrong;
|
||||||
|
}
|
||||||
|
|
||||||
colon = strchr(client_str, ',');
|
colon = strchr(client_str, ',');
|
||||||
if (colon == NULL) {
|
if (colon == NULL) {
|
||||||
client_kex_len = strlen(client_str);
|
client_kex_len = strlen(client_str);
|
||||||
@@ -329,6 +339,7 @@ static int cmp_first_kex_algo(const char *client_str,
|
|||||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||||
{
|
{
|
||||||
int i, ok;
|
int i, ok;
|
||||||
|
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||||
int server_kex = session->server;
|
int server_kex = session->server;
|
||||||
ssh_string str = NULL;
|
ssh_string str = NULL;
|
||||||
char *strings[SSH_KEX_METHODS] = {0};
|
char *strings[SSH_KEX_METHODS] = {0};
|
||||||
@@ -342,35 +353,67 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
|||||||
(void)type;
|
(void)type;
|
||||||
(void)user;
|
(void)user;
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "KEXINIT received");
|
||||||
|
|
||||||
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) {
|
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
SSH_LOG(SSH_LOG_INFO, "Initiating key re-exchange");
|
if (session->dh_handshake_state == DH_STATE_FINISHED) {
|
||||||
|
SSH_LOG(SSH_LOG_DEBUG, "Peer initiated key re-exchange");
|
||||||
|
/* Reset the sent flag if the re-kex was initiated by the peer */
|
||||||
|
session->flags &= ~SSH_SESSION_FLAG_KEXINIT_SENT;
|
||||||
|
} else if (session->flags & SSH_SESSION_FLAG_KEXINIT_SENT &&
|
||||||
|
session->dh_handshake_state == DH_STATE_INIT_SENT) {
|
||||||
|
/* This happens only when we are sending our-guessed first kex
|
||||||
|
* packet right after our KEXINIT packet. */
|
||||||
|
SSH_LOG(SSH_LOG_DEBUG, "Received peer kexinit answer.");
|
||||||
|
} else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
|
||||||
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"SSH_KEXINIT received in wrong state");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
} else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
|
} else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
|
||||||
ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state");
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"SSH_KEXINIT received in wrong state");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server_kex) {
|
if (server_kex) {
|
||||||
len = ssh_buffer_get_data(packet,session->next_crypto->client_kex.cookie, 16);
|
#ifdef WITH_SERVER
|
||||||
|
len = ssh_buffer_get_data(packet, crypto->client_kex.cookie, 16);
|
||||||
if (len != 16) {
|
if (len != 16) {
|
||||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet");
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"ssh_packet_kexinit: no cookie in packet");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ssh_hashbufin_add_cookie(session, session->next_crypto->client_kex.cookie);
|
ok = ssh_hashbufin_add_cookie(session, crypto->client_kex.cookie);
|
||||||
if (len < 0) {
|
if (ok < 0) {
|
||||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed");
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"ssh_packet_kexinit: adding cookie failed");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ok = server_set_kex(session);
|
||||||
|
if (ok == SSH_ERROR) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
len = ssh_buffer_get_data(packet,session->next_crypto->server_kex.cookie, 16);
|
len = ssh_buffer_get_data(packet, crypto->server_kex.cookie, 16);
|
||||||
if (len != 16) {
|
if (len != 16) {
|
||||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet");
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"ssh_packet_kexinit: no cookie in packet");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ssh_hashbufin_add_cookie(session, session->next_crypto->server_kex.cookie);
|
ok = ssh_hashbufin_add_cookie(session, crypto->server_kex.cookie);
|
||||||
if (len < 0) {
|
if (ok < 0) {
|
||||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed");
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"ssh_packet_kexinit: adding cookie failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = ssh_set_client_kex(session);
|
||||||
|
if (ok == SSH_ERROR) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,7 +426,8 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
|||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(session->in_hashbuf, str);
|
rc = ssh_buffer_add_ssh_string(session->in_hashbuf, str);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Error adding string in hash buffer");
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"Error adding string in hash buffer");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,14 +440,14 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
|||||||
str = NULL;
|
str = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the server kex info into an array of strings */
|
/* copy the peer kex info into an array of strings */
|
||||||
if (server_kex) {
|
if (server_kex) {
|
||||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||||
session->next_crypto->client_kex.methods[i] = strings[i];
|
crypto->client_kex.methods[i] = strings[i];
|
||||||
}
|
}
|
||||||
} else { /* client */
|
} else { /* client */
|
||||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||||
session->next_crypto->server_kex.methods[i] = strings[i];
|
crypto->server_kex.methods[i] = strings[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,30 +461,69 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
|||||||
* that its value is included when computing the session ID (see
|
* that its value is included when computing the session ID (see
|
||||||
* 'make_sessionid').
|
* 'make_sessionid').
|
||||||
*/
|
*/
|
||||||
|
rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember whether 'first_kex_packet_follows' was set and the client
|
||||||
|
* guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
|
||||||
|
* must be ignored on the server side.
|
||||||
|
* Client needs to start the Key exchange over with the correct method
|
||||||
|
*/
|
||||||
|
if (first_kex_packet_follows || session->send_first_kex_follows) {
|
||||||
|
char **client_methods = crypto->client_kex.methods;
|
||||||
|
char **server_methods = crypto->server_kex.methods;
|
||||||
|
session->first_kex_follows_guess_wrong =
|
||||||
|
cmp_first_kex_algo(client_methods[SSH_KEX],
|
||||||
|
server_methods[SSH_KEX]) ||
|
||||||
|
cmp_first_kex_algo(client_methods[SSH_HOSTKEYS],
|
||||||
|
server_methods[SSH_HOSTKEYS]);
|
||||||
|
SSH_LOG(SSH_LOG_DEBUG, "The initial guess was %s.",
|
||||||
|
session->first_kex_follows_guess_wrong ? "wrong" : "right");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle the "strict KEX" feature. If supported by peer, then set up the
|
||||||
|
* flag and verify packet sequence numbers.
|
||||||
|
*/
|
||||||
if (server_kex) {
|
if (server_kex) {
|
||||||
rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows);
|
ok = ssh_match_group(crypto->client_kex.methods[SSH_KEX],
|
||||||
if (rc != 1) {
|
KEX_STRICT_CLIENT);
|
||||||
goto error;
|
if (ok) {
|
||||||
|
SSH_LOG(SSH_LOG_DEBUG, "Client supports strict kex, enabling.");
|
||||||
|
session->flags |= SSH_SESSION_FLAG_KEX_STRICT;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows);
|
/* client kex */
|
||||||
if (rc < 0) {
|
ok = ssh_match_group(crypto->server_kex.methods[SSH_KEX],
|
||||||
goto error;
|
KEX_STRICT_SERVER);
|
||||||
}
|
if (ok) {
|
||||||
|
SSH_LOG(SSH_LOG_DEBUG, "Server supports strict kex, enabling.");
|
||||||
rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved);
|
session->flags |= SSH_SESSION_FLAG_KEX_STRICT;
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server_kex) {
|
||||||
/*
|
/*
|
||||||
* If client sent a ext-info-c message in the kex list, it supports
|
* If client sent a ext-info-c message in the kex list, it supports
|
||||||
* RFC 8308 extension negotiation.
|
* RFC 8308 extension negotiation.
|
||||||
*/
|
*/
|
||||||
ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX],
|
ok = ssh_match_group(crypto->client_kex.methods[SSH_KEX],
|
||||||
KEX_EXTENSION_CLIENT);
|
KEX_EXTENSION_CLIENT);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
const char *hostkeys = NULL;
|
const char *hostkeys = NULL, *wanted_hostkeys = NULL;
|
||||||
|
|
||||||
/* The client supports extension negotiation */
|
/* The client supports extension negotiation */
|
||||||
session->extensions |= SSH_EXT_NEGOTIATION;
|
session->extensions |= SSH_EXT_NEGOTIATION;
|
||||||
@@ -450,14 +533,14 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
|||||||
* by the client and enable the respective extensions to provide
|
* by the client and enable the respective extensions to provide
|
||||||
* correct signature in the next packet if RSA is negotiated
|
* correct signature in the next packet if RSA is negotiated
|
||||||
*/
|
*/
|
||||||
hostkeys = session->next_crypto->client_kex.methods[SSH_HOSTKEYS];
|
hostkeys = crypto->client_kex.methods[SSH_HOSTKEYS];
|
||||||
|
wanted_hostkeys = session->opts.wanted_methods[SSH_HOSTKEYS];
|
||||||
ok = ssh_match_group(hostkeys, "rsa-sha2-512");
|
ok = ssh_match_group(hostkeys, "rsa-sha2-512");
|
||||||
if (ok) {
|
if (ok) {
|
||||||
/* Check if rsa-sha2-512 is allowed by config */
|
/* Check if rsa-sha2-512 is allowed by config */
|
||||||
if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) {
|
if (wanted_hostkeys != NULL) {
|
||||||
char *is_allowed =
|
char *is_allowed = ssh_find_matching(wanted_hostkeys,
|
||||||
ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS],
|
"rsa-sha2-512");
|
||||||
"rsa-sha2-512");
|
|
||||||
if (is_allowed != NULL) {
|
if (is_allowed != NULL) {
|
||||||
session->extensions |= SSH_EXT_SIG_RSA_SHA512;
|
session->extensions |= SSH_EXT_SIG_RSA_SHA512;
|
||||||
}
|
}
|
||||||
@@ -467,10 +550,9 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
|||||||
ok = ssh_match_group(hostkeys, "rsa-sha2-256");
|
ok = ssh_match_group(hostkeys, "rsa-sha2-256");
|
||||||
if (ok) {
|
if (ok) {
|
||||||
/* Check if rsa-sha2-256 is allowed by config */
|
/* Check if rsa-sha2-256 is allowed by config */
|
||||||
if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) {
|
if (wanted_hostkeys != NULL) {
|
||||||
char *is_allowed =
|
char *is_allowed = ssh_find_matching(wanted_hostkeys,
|
||||||
ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS],
|
"rsa-sha2-256");
|
||||||
"rsa-sha2-256");
|
|
||||||
if (is_allowed != NULL) {
|
if (is_allowed != NULL) {
|
||||||
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
|
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
|
||||||
}
|
}
|
||||||
@@ -486,7 +568,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
|||||||
(session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
|
(session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
|
||||||
session->extensions &= ~(SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512);
|
session->extensions &= ~(SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512);
|
||||||
rsa_sig_ext = ssh_find_matching("rsa-sha2-512,rsa-sha2-256",
|
rsa_sig_ext = ssh_find_matching("rsa-sha2-512,rsa-sha2-256",
|
||||||
session->next_crypto->client_kex.methods[SSH_HOSTKEYS]);
|
hostkeys);
|
||||||
if (rsa_sig_ext == NULL) {
|
if (rsa_sig_ext == NULL) {
|
||||||
goto error; /* should never happen */
|
goto error; /* should never happen */
|
||||||
} else if (strcmp(rsa_sig_ext, "rsa-sha2-512") == 0) {
|
} else if (strcmp(rsa_sig_ext, "rsa-sha2-512") == 0) {
|
||||||
@@ -505,24 +587,16 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
|||||||
session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "",
|
session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "",
|
||||||
session->extensions & SSH_EXT_SIG_RSA_SHA512 ? " SHA512" : "");
|
session->extensions & SSH_EXT_SIG_RSA_SHA512 ? " SHA512" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Remember whether 'first_kex_packet_follows' was set and the client
|
|
||||||
* guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
|
|
||||||
* must be ignored.
|
|
||||||
*/
|
|
||||||
if (first_kex_packet_follows) {
|
|
||||||
session->first_kex_follows_guess_wrong =
|
|
||||||
cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_KEX],
|
|
||||||
session->next_crypto->server_kex.methods[SSH_KEX]) ||
|
|
||||||
cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_HOSTKEYS],
|
|
||||||
session->next_crypto->server_kex.methods[SSH_HOSTKEYS]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note, that his overwrites authenticated state in case of rekeying */
|
/* Note, that his overwrites authenticated state in case of rekeying */
|
||||||
session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED;
|
session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED;
|
||||||
session->dh_handshake_state = DH_STATE_INIT;
|
/* if we already sent our initial key exchange packet, do not reset the
|
||||||
|
* DH state. We will know if we were right with our guess only in
|
||||||
|
* dh_handshake_state() */
|
||||||
|
if (session->send_first_kex_follows == false) {
|
||||||
|
session->dh_handshake_state = DH_STATE_INIT;
|
||||||
|
}
|
||||||
session->ssh_connection_callback(session);
|
session->ssh_connection_callback(session);
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
|
|
||||||
@@ -664,11 +738,14 @@ int ssh_set_client_kex(ssh_session session)
|
|||||||
{
|
{
|
||||||
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
|
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
|
||||||
const char *wanted;
|
const char *wanted;
|
||||||
char *kex = NULL;
|
|
||||||
char *kex_tmp = NULL;
|
|
||||||
int ok;
|
int ok;
|
||||||
int i;
|
int i;
|
||||||
size_t kex_len, len;
|
|
||||||
|
/* Skip if already set, for example for the rekey or when we do the guessing
|
||||||
|
* it could have been already used to make some protocol decisions. */
|
||||||
|
if (client->methods[0] != NULL) {
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
ok = ssh_get_random(client->cookie, 16, 0);
|
ok = ssh_get_random(client->cookie, 16, 0);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -676,8 +753,6 @@ int ssh_set_client_kex(ssh_session session)
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(client->methods, 0, SSH_KEX_METHODS * sizeof(char **));
|
|
||||||
|
|
||||||
/* Set the list of allowed algorithms in order of preference, if it hadn't
|
/* Set the list of allowed algorithms in order of preference, if it hadn't
|
||||||
* been set yet. */
|
* been set yet. */
|
||||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||||
@@ -713,78 +788,204 @@ int ssh_set_client_kex(ssh_session session)
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here we append ext-info-c to the list of kex algorithms */
|
ok = ssh_kex_append_extensions(session, client);
|
||||||
kex = client->methods[SSH_KEX];
|
if (ok != SSH_OK){
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex)
|
||||||
|
{
|
||||||
|
char *kex = NULL;
|
||||||
|
char *kex_tmp = NULL;
|
||||||
|
size_t kex_len, len;
|
||||||
|
|
||||||
|
/* Here we append ext-info-c and kex-strict-c-v00@openssh.com for client
|
||||||
|
* and kex-strict-s-v00@openssh.com for server to the list of kex algorithms
|
||||||
|
*/
|
||||||
|
kex = pkex->methods[SSH_KEX];
|
||||||
len = strlen(kex);
|
len = strlen(kex);
|
||||||
if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) {
|
if (session->server) {
|
||||||
|
/* Comma, nul byte */
|
||||||
|
kex_len = len + 1 + strlen(KEX_STRICT_SERVER) + 1;
|
||||||
|
} else {
|
||||||
|
/* Comma, comma, nul byte */
|
||||||
|
kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 +
|
||||||
|
strlen(KEX_STRICT_CLIENT) + 1;
|
||||||
|
}
|
||||||
|
if (kex_len >= MAX_PACKET_LEN) {
|
||||||
/* Overflow */
|
/* Overflow */
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */
|
|
||||||
kex_tmp = realloc(kex, kex_len);
|
kex_tmp = realloc(kex, kex_len);
|
||||||
if (kex_tmp == NULL) {
|
if (kex_tmp == NULL) {
|
||||||
free(kex);
|
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT);
|
if (session->server){
|
||||||
client->methods[SSH_KEX] = kex_tmp;
|
snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_STRICT_SERVER);
|
||||||
|
} else {
|
||||||
|
snprintf(kex_tmp + len,
|
||||||
|
kex_len - len,
|
||||||
|
",%s,%s",
|
||||||
|
KEX_EXTENSION_CLIENT,
|
||||||
|
KEX_STRICT_CLIENT);
|
||||||
|
}
|
||||||
|
pkex->methods[SSH_KEX] = kex_tmp;
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *ssh_find_aead_hmac(const char *cipher)
|
||||||
|
{
|
||||||
|
if (cipher == NULL) {
|
||||||
|
return NULL;
|
||||||
|
} else if (strcmp(cipher, "chacha20-poly1305@openssh.com") == 0) {
|
||||||
|
return "aead-poly1305";
|
||||||
|
} else if (strcmp(cipher, "aes256-gcm@openssh.com") == 0) {
|
||||||
|
return "aead-gcm";
|
||||||
|
} else if (strcmp(cipher, "aes128-gcm@openssh.com") == 0) {
|
||||||
|
return "aead-gcm";
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum ssh_key_exchange_e
|
||||||
|
kex_select_kex_type(const char *kex)
|
||||||
|
{
|
||||||
|
if (strcmp(kex, "diffie-hellman-group1-sha1") == 0) {
|
||||||
|
return SSH_KEX_DH_GROUP1_SHA1;
|
||||||
|
} else if (strcmp(kex, "diffie-hellman-group14-sha1") == 0) {
|
||||||
|
return SSH_KEX_DH_GROUP14_SHA1;
|
||||||
|
} else if (strcmp(kex, "diffie-hellman-group14-sha256") == 0) {
|
||||||
|
return SSH_KEX_DH_GROUP14_SHA256;
|
||||||
|
} else if (strcmp(kex, "diffie-hellman-group16-sha512") == 0) {
|
||||||
|
return SSH_KEX_DH_GROUP16_SHA512;
|
||||||
|
} else if (strcmp(kex, "diffie-hellman-group18-sha512") == 0) {
|
||||||
|
return SSH_KEX_DH_GROUP18_SHA512;
|
||||||
|
#ifdef WITH_GEX
|
||||||
|
} else if (strcmp(kex, "diffie-hellman-group-exchange-sha1") == 0) {
|
||||||
|
return SSH_KEX_DH_GEX_SHA1;
|
||||||
|
} else if (strcmp(kex, "diffie-hellman-group-exchange-sha256") == 0) {
|
||||||
|
return SSH_KEX_DH_GEX_SHA256;
|
||||||
|
#endif /* WITH_GEX */
|
||||||
|
} else if (strcmp(kex, "ecdh-sha2-nistp256") == 0) {
|
||||||
|
return SSH_KEX_ECDH_SHA2_NISTP256;
|
||||||
|
} else if (strcmp(kex, "ecdh-sha2-nistp384") == 0) {
|
||||||
|
return SSH_KEX_ECDH_SHA2_NISTP384;
|
||||||
|
} else if (strcmp(kex, "ecdh-sha2-nistp521") == 0) {
|
||||||
|
return SSH_KEX_ECDH_SHA2_NISTP521;
|
||||||
|
} else if (strcmp(kex, "curve25519-sha256@libssh.org") == 0) {
|
||||||
|
return SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
|
||||||
|
} else if (strcmp(kex, "curve25519-sha256") == 0) {
|
||||||
|
return SSH_KEX_CURVE25519_SHA256;
|
||||||
|
}
|
||||||
|
/* should not happen. We should be getting only valid names at this stage */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief Reverts guessed callbacks set during the dh_handshake()
|
||||||
|
* @param session session handle
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
static void revert_kex_callbacks(ssh_session session)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
ssh_client_dh_remove_callbacks(session);
|
||||||
|
break;
|
||||||
|
#ifdef WITH_GEX
|
||||||
|
case SSH_KEX_DH_GEX_SHA1:
|
||||||
|
case SSH_KEX_DH_GEX_SHA256:
|
||||||
|
ssh_client_dhgex_remove_callbacks(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:
|
||||||
|
ssh_client_ecdh_remove_callbacks(session);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CURVE25519
|
||||||
|
case SSH_KEX_CURVE25519_SHA256:
|
||||||
|
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||||
|
ssh_client_curve25519_remove_callbacks(session);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Select the different methods on basis of client's and
|
/** @brief Select the different methods on basis of client's and
|
||||||
* server's kex messages, and watches out if a match is possible.
|
* server's kex messages, and watches out if a match is possible.
|
||||||
*/
|
*/
|
||||||
int ssh_kex_select_methods (ssh_session session){
|
int ssh_kex_select_methods (ssh_session session)
|
||||||
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
|
{
|
||||||
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
|
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||||
|
struct ssh_kex_struct *server = &crypto->server_kex;
|
||||||
|
struct ssh_kex_struct *client = &crypto->client_kex;
|
||||||
char *ext_start = NULL;
|
char *ext_start = NULL;
|
||||||
|
const char *aead_hmac = NULL;
|
||||||
|
enum ssh_key_exchange_e kex_type;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Here we should drop the ext-info-c from the list so we avoid matching.
|
/* Here we should drop the extensions from the list so we avoid matching.
|
||||||
* it. We added it to the end, so we can just truncate the string here */
|
* it. We added it to the end, so we can just truncate the string here */
|
||||||
ext_start = strstr(client->methods[SSH_KEX], ","KEX_EXTENSION_CLIENT);
|
if (session->client) {
|
||||||
if (ext_start != NULL) {
|
ext_start = strstr(client->methods[SSH_KEX], "," KEX_EXTENSION_CLIENT);
|
||||||
ext_start[0] = '\0';
|
if (ext_start != NULL) {
|
||||||
|
ext_start[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (session->server) {
|
||||||
|
ext_start = strstr(server->methods[SSH_KEX], "," KEX_STRICT_SERVER);
|
||||||
|
if (ext_start != NULL) {
|
||||||
|
ext_start[0] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||||
session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]);
|
crypto->kex_methods[i] = ssh_find_matching(server->methods[i],
|
||||||
if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){
|
client->methods[i]);
|
||||||
ssh_set_error(session,SSH_FATAL,"kex error : no match for method %s: server [%s], client [%s]",
|
|
||||||
ssh_kex_descriptions[i],server->methods[i],client->methods[i]);
|
if (i == SSH_MAC_C_S || i == SSH_MAC_S_C) {
|
||||||
|
aead_hmac = ssh_find_aead_hmac(crypto->kex_methods[i - 2]);
|
||||||
|
if (aead_hmac) {
|
||||||
|
free(crypto->kex_methods[i]);
|
||||||
|
crypto->kex_methods[i] = strdup(aead_hmac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S) {
|
||||||
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"kex error : no match for method %s: server [%s], "
|
||||||
|
"client [%s]", ssh_kex_descriptions[i],
|
||||||
|
server->methods[i], client->methods[i]);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
} else if ((i >= SSH_LANG_C_S) && (session->next_crypto->kex_methods[i] == NULL)) {
|
} else if ((i >= SSH_LANG_C_S) && (crypto->kex_methods[i] == NULL)) {
|
||||||
/* we can safely do that for languages */
|
/* we can safely do that for languages */
|
||||||
session->next_crypto->kex_methods[i] = strdup("");
|
crypto->kex_methods[i] = strdup("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){
|
|
||||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1;
|
/* We can not set this value directly as the old value is needed to revert
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){
|
* callbacks if we are client */
|
||||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1;
|
kex_type = kex_select_kex_type(crypto->kex_methods[SSH_KEX]);
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){
|
if (session->client && session->first_kex_follows_guess_wrong) {
|
||||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512;
|
SSH_LOG(SSH_LOG_DEBUG, "Our guess was wrong. Restarting the KEX");
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){
|
/* We need to remove the wrong callbacks and start kex again */
|
||||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512;
|
revert_kex_callbacks(session);
|
||||||
#ifdef WITH_GEX
|
session->dh_handshake_state = DH_STATE_INIT;
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha1") == 0){
|
session->first_kex_follows_guess_wrong = false;
|
||||||
session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA1;
|
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha256") == 0){
|
|
||||||
session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA256;
|
|
||||||
#endif /* WITH_GEX */
|
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
|
|
||||||
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256;
|
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){
|
|
||||||
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP384;
|
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp521") == 0){
|
|
||||||
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP521;
|
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256@libssh.org") == 0){
|
|
||||||
session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
|
|
||||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){
|
|
||||||
session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256;
|
|
||||||
}
|
}
|
||||||
|
crypto->kex_type = kex_type;
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
|
SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
|
||||||
session->next_crypto->kex_methods[SSH_KEX],
|
session->next_crypto->kex_methods[SSH_KEX],
|
||||||
session->next_crypto->kex_methods[SSH_HOSTKEYS],
|
session->next_crypto->kex_methods[SSH_HOSTKEYS],
|
||||||
@@ -802,62 +1003,116 @@ int ssh_kex_select_methods (ssh_session session){
|
|||||||
|
|
||||||
|
|
||||||
/* this function only sends the predefined set of kex methods */
|
/* this function only sends the predefined set of kex methods */
|
||||||
int ssh_send_kex(ssh_session session, int server_kex) {
|
int ssh_send_kex(ssh_session session)
|
||||||
struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex :
|
{
|
||||||
&session->next_crypto->client_kex);
|
struct ssh_kex_struct *kex = (session->server ?
|
||||||
ssh_string str = NULL;
|
&session->next_crypto->server_kex :
|
||||||
int i;
|
&session->next_crypto->client_kex);
|
||||||
int rc;
|
ssh_string str = NULL;
|
||||||
|
int i;
|
||||||
|
int rc;
|
||||||
|
int first_kex_packet_follows = 0;
|
||||||
|
|
||||||
rc = ssh_buffer_pack(session->out_buffer,
|
/* Only client can initiate the handshake methods we implement. If we
|
||||||
"bP",
|
* already received the peer mechanisms, there is no point in guessing */
|
||||||
SSH2_MSG_KEXINIT,
|
if (session->client &&
|
||||||
16,
|
session->session_state != SSH_SESSION_STATE_KEXINIT_RECEIVED &&
|
||||||
kex->cookie); /* cookie */
|
session->send_first_kex_follows) {
|
||||||
if (rc != SSH_OK)
|
first_kex_packet_follows = 1;
|
||||||
goto error;
|
|
||||||
if (ssh_hashbufout_add_cookie(session) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_list_kex(kex);
|
|
||||||
|
|
||||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
|
||||||
str = ssh_string_from_char(kex->methods[i]);
|
|
||||||
if (str == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) {
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
goto error;
|
"Sending KEXINIT packet, first_kex_packet_follows = %d",
|
||||||
|
first_kex_packet_follows);
|
||||||
|
|
||||||
|
rc = ssh_buffer_pack(session->out_buffer,
|
||||||
|
"bP",
|
||||||
|
SSH2_MSG_KEXINIT,
|
||||||
|
16,
|
||||||
|
kex->cookie); /* cookie */
|
||||||
|
if (rc != SSH_OK)
|
||||||
|
goto error;
|
||||||
|
if (ssh_hashbufout_add_cookie(session) < 0) {
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) {
|
|
||||||
goto error;
|
ssh_list_kex(kex);
|
||||||
|
|
||||||
|
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||||
|
str = ssh_string_from_char(kex->methods[i]);
|
||||||
|
if (str == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(session->out_hashbuf, str);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(session->out_buffer, str);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
SSH_STRING_FREE(str);
|
||||||
|
str = NULL;
|
||||||
}
|
}
|
||||||
SSH_STRING_FREE(str);
|
|
||||||
str = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_buffer_pack(session->out_buffer,
|
rc = ssh_buffer_pack(session->out_buffer,
|
||||||
"bd",
|
"bd",
|
||||||
0,
|
first_kex_packet_follows,
|
||||||
0);
|
0);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
/* Prepare also the first_kex_packet_follows and reserved to 0 */
|
||||||
return -1;
|
rc = ssh_buffer_add_u8(session->out_hashbuf, first_kex_packet_follows);
|
||||||
}
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_u32(session->out_hashbuf, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_packet_send(session);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->flags |= SSH_SESSION_FLAG_KEXINIT_SENT;
|
||||||
|
SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent");
|
||||||
|
|
||||||
|
/* If we indicated that we are sending the guessed key exchange packet,
|
||||||
|
* do it now. The packet is simple, but we need to do some preparations */
|
||||||
|
if (first_kex_packet_follows) {
|
||||||
|
char *list = kex->methods[SSH_KEX];
|
||||||
|
char *colon = strchr(list, ',');
|
||||||
|
size_t kex_name_len = colon ? (size_t)(colon - list) : strlen(list);
|
||||||
|
char *kex_name = calloc(kex_name_len + 1, 1);
|
||||||
|
if (kex_name == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
snprintf(kex_name, kex_name_len + 1, "%.*s", (int)kex_name_len, list);
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "Sending the first kex packet for %s", kex_name);
|
||||||
|
|
||||||
|
session->next_crypto->kex_type = kex_select_kex_type(kex_name);
|
||||||
|
free(kex_name);
|
||||||
|
|
||||||
|
/* run the first step of the DH handshake */
|
||||||
|
session->dh_handshake_state = DH_STATE_INIT;
|
||||||
|
if (dh_handshake(session) == SSH_ERROR) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent");
|
|
||||||
return 0;
|
|
||||||
error:
|
error:
|
||||||
ssh_buffer_reinit(session->out_buffer);
|
ssh_buffer_reinit(session->out_buffer);
|
||||||
ssh_buffer_reinit(session->out_hashbuf);
|
ssh_buffer_reinit(session->out_hashbuf);
|
||||||
SSH_STRING_FREE(str);
|
SSH_STRING_FREE(str);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -900,7 +1155,7 @@ int ssh_send_rekex(ssh_session session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
session->dh_handshake_state = DH_STATE_INIT;
|
session->dh_handshake_state = DH_STATE_INIT;
|
||||||
rc = ssh_send_kex(session, session->server);
|
rc = ssh_send_kex(session);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
SSH_LOG(SSH_LOG_PACKET, "Failed to send kex");
|
SSH_LOG(SSH_LOG_PACKET, "Failed to send kex");
|
||||||
return rc;
|
return rc;
|
||||||
@@ -977,33 +1232,6 @@ int ssh_make_sessionid(ssh_session session)
|
|||||||
client_hash = session->in_hashbuf;
|
client_hash = session->in_hashbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle the two final fields for the KEXINIT message (RFC 4253 7.1):
|
|
||||||
*
|
|
||||||
* boolean first_kex_packet_follows
|
|
||||||
* uint32 0 (reserved for future extension)
|
|
||||||
*/
|
|
||||||
rc = ssh_buffer_add_u8(server_hash, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_add_u32(server_hash, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* These fields are handled for the server case in ssh_packet_kexinit. */
|
|
||||||
if (session->client) {
|
|
||||||
rc = ssh_buffer_add_u8(client_hash, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_add_u32(client_hash, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
|
rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
@@ -1019,13 +1247,14 @@ int ssh_make_sessionid(ssh_session session)
|
|||||||
ssh_buffer_get(server_hash),
|
ssh_buffer_get(server_hash),
|
||||||
server_pubkey_blob);
|
server_pubkey_blob);
|
||||||
SSH_STRING_FREE(server_pubkey_blob);
|
SSH_STRING_FREE(server_pubkey_blob);
|
||||||
if(rc != SSH_OK){
|
if (rc != SSH_OK){
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(session->next_crypto->kex_type) {
|
switch(session->next_crypto->kex_type) {
|
||||||
case SSH_KEX_DH_GROUP1_SHA1:
|
case SSH_KEX_DH_GROUP1_SHA1:
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
|
case SSH_KEX_DH_GROUP14_SHA256:
|
||||||
case SSH_KEX_DH_GROUP16_SHA512:
|
case SSH_KEX_DH_GROUP16_SHA512:
|
||||||
case SSH_KEX_DH_GROUP18_SHA512:
|
case SSH_KEX_DH_GROUP18_SHA512:
|
||||||
rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
|
rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
|
||||||
@@ -1137,6 +1366,7 @@ int ssh_make_sessionid(ssh_session session)
|
|||||||
sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
|
sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
|
||||||
session->next_crypto->secret_hash);
|
session->next_crypto->secret_hash);
|
||||||
break;
|
break;
|
||||||
|
case SSH_KEX_DH_GROUP14_SHA256:
|
||||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||||
case SSH_KEX_CURVE25519_SHA256:
|
case SSH_KEX_CURVE25519_SHA256:
|
||||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||||
@@ -1191,11 +1421,13 @@ int ssh_make_sessionid(ssh_session session)
|
|||||||
}
|
}
|
||||||
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
||||||
session->next_crypto->digest_len);
|
session->next_crypto->digest_len);
|
||||||
|
/* Initial length is the same as secret hash */
|
||||||
|
session->next_crypto->session_id_len = session->next_crypto->digest_len;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
printf("Session hash: \n");
|
printf("Session hash: \n");
|
||||||
ssh_log_hexdump("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
|
ssh_log_hexdump("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
|
||||||
ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
|
ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->session_id_len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = SSH_OK;
|
rc = SSH_OK;
|
||||||
|
|||||||
@@ -372,6 +372,7 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
|||||||
|
|
||||||
list = ssh_list_new();
|
list = ssh_list_new();
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ void publickey_free(ssh_public_key key) {
|
|||||||
case SSH_KEYTYPE_DSS:
|
case SSH_KEYTYPE_DSS:
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
gcry_sexp_release(key->dsa_pub);
|
gcry_sexp_release(key->dsa_pub);
|
||||||
#elif HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
DSA_free(key->dsa_pub);
|
DSA_free(key->dsa_pub);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -280,6 +280,12 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
|||||||
OPENSSL_free(ctx);
|
OPENSSL_free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
|
||||||
|
{
|
||||||
|
EVP_CIPHER_CTX_init(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
HMAC_CTX *HMAC_CTX_new(void)
|
HMAC_CTX *HMAC_CTX_new(void)
|
||||||
{
|
{
|
||||||
HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
|
HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
|
||||||
@@ -394,3 +400,12 @@ int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *OpenSSL_version(int type)
|
||||||
|
{
|
||||||
|
return SSLeay_version(type);
|
||||||
|
}
|
||||||
|
unsigned long OpenSSL_version_num(void)
|
||||||
|
{
|
||||||
|
return SSLeay();
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
|
|||||||
EVP_MD_CTX *EVP_MD_CTX_new(void);
|
EVP_MD_CTX *EVP_MD_CTX_new(void);
|
||||||
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
|
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
|
||||||
|
|
||||||
|
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
|
||||||
|
|
||||||
HMAC_CTX *HMAC_CTX_new(void);
|
HMAC_CTX *HMAC_CTX_new(void);
|
||||||
int HMAC_CTX_reset(HMAC_CTX *ctx);
|
int HMAC_CTX_reset(HMAC_CTX *ctx);
|
||||||
void HMAC_CTX_free(HMAC_CTX *ctx);
|
void HMAC_CTX_free(HMAC_CTX *ctx);
|
||||||
@@ -44,6 +46,10 @@ int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
|
|||||||
void DH_get0_key(const DH *dh,
|
void DH_get0_key(const DH *dh,
|
||||||
const BIGNUM **pub_key, const BIGNUM **priv_key);
|
const BIGNUM **pub_key, const BIGNUM **priv_key);
|
||||||
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
|
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
|
||||||
|
|
||||||
|
const char *OpenSSL_version(int type);
|
||||||
|
unsigned long OpenSSL_version_num(void);
|
||||||
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
#endif /* LIBCRYPTO_COMPAT_H */
|
#endif /* LIBCRYPTO_COMPAT_H */
|
||||||
|
|||||||
288
src/libcrypto.c
288
src/libcrypto.c
@@ -126,82 +126,48 @@ SHACTX sha1_init(void)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha1_update(SHACTX c, const void *data, unsigned long len)
|
void sha1_ctx_free(SHACTX c)
|
||||||
{
|
{
|
||||||
EVP_DigestUpdate(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha1_final(unsigned char *md, SHACTX c)
|
|
||||||
{
|
|
||||||
unsigned int mdlen = 0;
|
|
||||||
|
|
||||||
EVP_DigestFinal(c, md, &mdlen);
|
|
||||||
EVP_MD_CTX_destroy(c);
|
EVP_MD_CTX_destroy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha1(const unsigned char *digest, int len, unsigned char *hash)
|
int sha1_update(SHACTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = EVP_DigestUpdate(c, data, len);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha1_final(unsigned char *md, SHACTX c)
|
||||||
|
{
|
||||||
|
unsigned int mdlen = 0;
|
||||||
|
int rc = EVP_DigestFinal(c, md, &mdlen);
|
||||||
|
|
||||||
|
EVP_MD_CTX_destroy(c);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha1(const unsigned char *digest, int len, unsigned char *hash)
|
||||||
{
|
{
|
||||||
SHACTX c = sha1_init();
|
SHACTX c = sha1_init();
|
||||||
if (c != NULL) {
|
int rc;
|
||||||
sha1_update(c, digest, len);
|
|
||||||
sha1_final(hash, c);
|
if (c == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
}
|
rc = sha1_update(c, digest, len);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
#ifdef HAVE_OPENSSL_ECC
|
sha1_ctx_free(c);
|
||||||
static const EVP_MD *nid_to_evpmd(int nid)
|
return SSH_ERROR;
|
||||||
{
|
|
||||||
switch (nid) {
|
|
||||||
case NID_X9_62_prime256v1:
|
|
||||||
return EVP_sha256();
|
|
||||||
case NID_secp384r1:
|
|
||||||
return EVP_sha384();
|
|
||||||
case NID_secp521r1:
|
|
||||||
return EVP_sha512();
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
return sha1_final(hash, c);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen)
|
|
||||||
{
|
|
||||||
const EVP_MD *evp_md = nid_to_evpmd(nid);
|
|
||||||
EVP_MD_CTX *md = EVP_MD_CTX_new();
|
|
||||||
|
|
||||||
EVP_DigestInit(md, evp_md);
|
|
||||||
EVP_DigestUpdate(md, digest, len);
|
|
||||||
EVP_DigestFinal(md, hash, hlen);
|
|
||||||
EVP_MD_CTX_free(md);
|
|
||||||
}
|
|
||||||
|
|
||||||
EVPCTX evp_init(int nid)
|
|
||||||
{
|
|
||||||
const EVP_MD *evp_md = nid_to_evpmd(nid);
|
|
||||||
|
|
||||||
EVPCTX ctx = EVP_MD_CTX_new();
|
|
||||||
if (ctx == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
EVP_DigestInit(ctx, evp_md);
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void evp_update(EVPCTX ctx, const void *data, unsigned long len)
|
|
||||||
{
|
|
||||||
EVP_DigestUpdate(ctx, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
|
|
||||||
{
|
|
||||||
EVP_DigestFinal(ctx, md, mdlen);
|
|
||||||
EVP_MD_CTX_free(ctx);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SHA256CTX sha256_init(void)
|
SHA256CTX sha256_init(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@@ -218,26 +184,46 @@ SHA256CTX sha256_init(void)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256_update(SHA256CTX c, const void *data, unsigned long len)
|
void sha256_ctx_free(SHA256CTX c)
|
||||||
{
|
{
|
||||||
EVP_DigestUpdate(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha256_final(unsigned char *md, SHA256CTX c)
|
|
||||||
{
|
|
||||||
unsigned int mdlen = 0;
|
|
||||||
|
|
||||||
EVP_DigestFinal(c, md, &mdlen);
|
|
||||||
EVP_MD_CTX_destroy(c);
|
EVP_MD_CTX_destroy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256(const unsigned char *digest, int len, unsigned char *hash)
|
int sha256_update(SHA256CTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = EVP_DigestUpdate(c, data, len);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha256_final(unsigned char *md, SHA256CTX c)
|
||||||
|
{
|
||||||
|
unsigned int mdlen = 0;
|
||||||
|
int rc = EVP_DigestFinal(c, md, &mdlen);
|
||||||
|
|
||||||
|
EVP_MD_CTX_destroy(c);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha256(const unsigned char *digest, int len, unsigned char *hash)
|
||||||
{
|
{
|
||||||
SHA256CTX c = sha256_init();
|
SHA256CTX c = sha256_init();
|
||||||
if (c != NULL) {
|
int rc;
|
||||||
sha256_update(c, digest, len);
|
|
||||||
sha256_final(hash, c);
|
if (c == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
rc = sha256_update(c, digest, len);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
sha256_ctx_free(c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return sha256_final(hash, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA384CTX sha384_init(void)
|
SHA384CTX sha384_init(void)
|
||||||
@@ -256,26 +242,47 @@ SHA384CTX sha384_init(void)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha384_update(SHA384CTX c, const void *data, unsigned long len)
|
void
|
||||||
|
sha384_ctx_free(SHA384CTX c)
|
||||||
{
|
{
|
||||||
EVP_DigestUpdate(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha384_final(unsigned char *md, SHA384CTX c)
|
|
||||||
{
|
|
||||||
unsigned int mdlen = 0;
|
|
||||||
|
|
||||||
EVP_DigestFinal(c, md, &mdlen);
|
|
||||||
EVP_MD_CTX_destroy(c);
|
EVP_MD_CTX_destroy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha384(const unsigned char *digest, int len, unsigned char *hash)
|
int sha384_update(SHA384CTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = EVP_DigestUpdate(c, data, len);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha384_final(unsigned char *md, SHA384CTX c)
|
||||||
|
{
|
||||||
|
unsigned int mdlen = 0;
|
||||||
|
int rc = EVP_DigestFinal(c, md, &mdlen);
|
||||||
|
|
||||||
|
EVP_MD_CTX_destroy(c);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha384(const unsigned char *digest, int len, unsigned char *hash)
|
||||||
{
|
{
|
||||||
SHA384CTX c = sha384_init();
|
SHA384CTX c = sha384_init();
|
||||||
if (c != NULL) {
|
int rc;
|
||||||
sha384_update(c, digest, len);
|
|
||||||
sha384_final(hash, c);
|
if (c == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
rc = sha384_update(c, digest, len);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
sha384_ctx_free(c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return sha384_final(hash, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA512CTX sha512_init(void)
|
SHA512CTX sha512_init(void)
|
||||||
@@ -294,26 +301,46 @@ SHA512CTX sha512_init(void)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha512_update(SHA512CTX c, const void *data, unsigned long len)
|
void sha512_ctx_free(SHA512CTX c)
|
||||||
{
|
{
|
||||||
EVP_DigestUpdate(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha512_final(unsigned char *md, SHA512CTX c)
|
|
||||||
{
|
|
||||||
unsigned int mdlen = 0;
|
|
||||||
|
|
||||||
EVP_DigestFinal(c, md, &mdlen);
|
|
||||||
EVP_MD_CTX_destroy(c);
|
EVP_MD_CTX_destroy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha512(const unsigned char *digest, int len, unsigned char *hash)
|
int sha512_update(SHA512CTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = EVP_DigestUpdate(c, data, len);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha512_final(unsigned char *md, SHA512CTX c)
|
||||||
|
{
|
||||||
|
unsigned int mdlen = 0;
|
||||||
|
int rc = EVP_DigestFinal(c, md, &mdlen);
|
||||||
|
|
||||||
|
EVP_MD_CTX_destroy(c);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha512(const unsigned char *digest, int len, unsigned char *hash)
|
||||||
{
|
{
|
||||||
SHA512CTX c = sha512_init();
|
SHA512CTX c = sha512_init();
|
||||||
if (c != NULL) {
|
int rc;
|
||||||
sha512_update(c, digest, len);
|
|
||||||
sha512_final(hash, c);
|
if (c == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
rc = sha512_update(c, digest, len);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
sha512_ctx_free(c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return sha512_final(hash, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5CTX md5_init(void)
|
MD5CTX md5_init(void)
|
||||||
@@ -332,19 +359,33 @@ MD5CTX md5_init(void)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void md5_update(MD5CTX c, const void *data, unsigned long len)
|
void md5_ctx_free(MD5CTX c)
|
||||||
{
|
{
|
||||||
EVP_DigestUpdate(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void md5_final(unsigned char *md, MD5CTX c)
|
|
||||||
{
|
|
||||||
unsigned int mdlen = 0;
|
|
||||||
|
|
||||||
EVP_DigestFinal(c, md, &mdlen);
|
|
||||||
EVP_MD_CTX_destroy(c);
|
EVP_MD_CTX_destroy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int md5_update(MD5CTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = EVP_DigestUpdate(c, data, len);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int md5_final(unsigned char *md, MD5CTX c)
|
||||||
|
{
|
||||||
|
unsigned int mdlen = 0;
|
||||||
|
int rc = EVP_DigestFinal(c, md, &mdlen);
|
||||||
|
|
||||||
|
EVP_MD_CTX_destroy(c);
|
||||||
|
if (rc != 1) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID
|
#ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID
|
||||||
static const EVP_MD *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type)
|
static const EVP_MD *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type)
|
||||||
{
|
{
|
||||||
@@ -392,7 +433,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
|
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
|
||||||
crypto->session_id, crypto->digest_len);
|
crypto->session_id, crypto->session_id_len);
|
||||||
if (rc != 1) {
|
if (rc != 1) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -536,7 +577,7 @@ static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher,
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
evp_cipher_init(cipher);
|
evp_cipher_init(cipher);
|
||||||
EVP_CIPHER_CTX_init(cipher->ctx);
|
EVP_CIPHER_CTX_reset(cipher->ctx);
|
||||||
|
|
||||||
rc = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
|
rc = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
|
||||||
if (rc != 1){
|
if (rc != 1){
|
||||||
@@ -569,7 +610,7 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher,
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
evp_cipher_init(cipher);
|
evp_cipher_init(cipher);
|
||||||
EVP_CIPHER_CTX_init(cipher->ctx);
|
EVP_CIPHER_CTX_reset(cipher->ctx);
|
||||||
|
|
||||||
rc = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
|
rc = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
|
||||||
if (rc != 1){
|
if (rc != 1){
|
||||||
@@ -652,7 +693,6 @@ static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher,
|
|||||||
|
|
||||||
static void evp_cipher_cleanup(struct ssh_cipher_struct *cipher) {
|
static void evp_cipher_cleanup(struct ssh_cipher_struct *cipher) {
|
||||||
if (cipher->ctx != NULL) {
|
if (cipher->ctx != NULL) {
|
||||||
EVP_CIPHER_CTX_cleanup(cipher->ctx);
|
|
||||||
EVP_CIPHER_CTX_free(cipher->ctx);
|
EVP_CIPHER_CTX_free(cipher->ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -708,8 +748,12 @@ aes_ctr_encrypt(struct ssh_cipher_struct *cipher,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){
|
static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){
|
||||||
explicit_bzero(cipher->aes_key, sizeof(*cipher->aes_key));
|
if (cipher != NULL) {
|
||||||
SAFE_FREE(cipher->aes_key);
|
if (cipher->aes_key != NULL) {
|
||||||
|
explicit_bzero(cipher->aes_key, sizeof(*cipher->aes_key));
|
||||||
|
}
|
||||||
|
SAFE_FREE(cipher->aes_key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_OPENSSL_EVP_AES_CTR */
|
#endif /* HAVE_OPENSSL_EVP_AES_CTR */
|
||||||
@@ -1080,11 +1124,11 @@ int ssh_crypto_init(void)
|
|||||||
if (libcrypto_initialized) {
|
if (libcrypto_initialized) {
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
if (SSLeay() != OPENSSL_VERSION_NUMBER){
|
if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER){
|
||||||
SSH_LOG(SSH_LOG_WARNING, "libssh compiled with %s "
|
SSH_LOG(SSH_LOG_WARNING, "libssh compiled with %s "
|
||||||
"headers, currently running with %s.",
|
"headers, currently running with %s.",
|
||||||
OPENSSL_VERSION_TEXT,
|
OPENSSL_VERSION_TEXT,
|
||||||
SSLeay_version(SSLeay())
|
OpenSSL_version(OpenSSL_version_num())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#ifdef CAN_DISABLE_AESNI
|
#ifdef CAN_DISABLE_AESNI
|
||||||
|
|||||||
200
src/libgcrypt.c
200
src/libgcrypt.c
@@ -68,72 +68,37 @@ SHACTX sha1_init(void) {
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha1_update(SHACTX c, const void *data, unsigned long len) {
|
void
|
||||||
|
sha1_ctx_free(SHACTX c)
|
||||||
|
{
|
||||||
|
gcry_md_close(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha1_update(SHACTX c, const void *data, unsigned long len) {
|
||||||
gcry_md_write(c, data, len);
|
gcry_md_write(c, data, len);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha1_final(unsigned char *md, SHACTX c) {
|
int sha1_final(unsigned char *md, SHACTX c)
|
||||||
gcry_md_final(c);
|
{
|
||||||
memcpy(md, gcry_md_read(c, 0), SHA_DIGEST_LEN);
|
unsigned char *tmp = NULL;
|
||||||
gcry_md_close(c);
|
|
||||||
|
gcry_md_final(c);
|
||||||
|
tmp = gcry_md_read(c, 0);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
memcpy(md, tmp, SHA_DIGEST_LEN);
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha1(const unsigned char *digest, int len, unsigned char *hash) {
|
int sha1(const unsigned char *digest, int len, unsigned char *hash) {
|
||||||
gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len);
|
gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_GCRYPT_ECC
|
|
||||||
static int nid_to_md_algo(int nid)
|
|
||||||
{
|
|
||||||
switch (nid) {
|
|
||||||
case NID_gcrypt_nistp256:
|
|
||||||
return GCRY_MD_SHA256;
|
|
||||||
case NID_gcrypt_nistp384:
|
|
||||||
return GCRY_MD_SHA384;
|
|
||||||
case NID_gcrypt_nistp521:
|
|
||||||
return GCRY_MD_SHA512;
|
|
||||||
}
|
|
||||||
return GCRY_MD_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void evp(int nid, unsigned char *digest, int len,
|
|
||||||
unsigned char *hash, unsigned int *hlen)
|
|
||||||
{
|
|
||||||
int algo = nid_to_md_algo(nid);
|
|
||||||
|
|
||||||
/* Note: What gcrypt calls 'hash' is called 'digest' here and
|
|
||||||
vice-versa. */
|
|
||||||
gcry_md_hash_buffer(algo, hash, digest, len);
|
|
||||||
*hlen = gcry_md_get_algo_dlen(algo);
|
|
||||||
}
|
|
||||||
|
|
||||||
EVPCTX evp_init(int nid)
|
|
||||||
{
|
|
||||||
gcry_error_t err;
|
|
||||||
int algo = nid_to_md_algo(nid);
|
|
||||||
EVPCTX ctx;
|
|
||||||
|
|
||||||
err = gcry_md_open(&ctx, algo, 0);
|
|
||||||
if (err) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void evp_update(EVPCTX ctx, const void *data, unsigned long len)
|
|
||||||
{
|
|
||||||
gcry_md_write(ctx, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
|
|
||||||
{
|
|
||||||
int algo = gcry_md_get_algo(ctx);
|
|
||||||
*mdlen = gcry_md_get_algo_dlen(algo);
|
|
||||||
memcpy(md, gcry_md_read(ctx, algo), *mdlen);
|
|
||||||
gcry_md_close(ctx);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SHA256CTX sha256_init(void) {
|
SHA256CTX sha256_init(void) {
|
||||||
SHA256CTX ctx = NULL;
|
SHA256CTX ctx = NULL;
|
||||||
@@ -142,18 +107,35 @@ SHA256CTX sha256_init(void) {
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256_update(SHACTX c, const void *data, unsigned long len) {
|
void
|
||||||
|
sha256_ctx_free(SHA256CTX c)
|
||||||
|
{
|
||||||
|
gcry_md_close(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha256_update(SHACTX c, const void *data, unsigned long len) {
|
||||||
gcry_md_write(c, data, len);
|
gcry_md_write(c, data, len);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256_final(unsigned char *md, SHACTX c) {
|
int sha256_final(unsigned char *md, SHACTX c)
|
||||||
gcry_md_final(c);
|
{
|
||||||
memcpy(md, gcry_md_read(c, 0), SHA256_DIGEST_LEN);
|
unsigned char *tmp = NULL;
|
||||||
gcry_md_close(c);
|
|
||||||
|
gcry_md_final(c);
|
||||||
|
tmp = gcry_md_read(c, 0);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
memcpy(md, tmp, SHA256_DIGEST_LEN);
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256(const unsigned char *digest, int len, unsigned char *hash){
|
int sha256(const unsigned char *digest, int len, unsigned char *hash){
|
||||||
gcry_md_hash_buffer(GCRY_MD_SHA256, hash, digest, len);
|
gcry_md_hash_buffer(GCRY_MD_SHA256, hash, digest, len);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA384CTX sha384_init(void) {
|
SHA384CTX sha384_init(void) {
|
||||||
@@ -163,18 +145,35 @@ SHA384CTX sha384_init(void) {
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha384_update(SHACTX c, const void *data, unsigned long len) {
|
void
|
||||||
|
sha384_ctx_free(SHA384CTX c)
|
||||||
|
{
|
||||||
|
gcry_md_close(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha384_update(SHACTX c, const void *data, unsigned long len) {
|
||||||
gcry_md_write(c, data, len);
|
gcry_md_write(c, data, len);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha384_final(unsigned char *md, SHACTX c) {
|
int sha384_final(unsigned char *md, SHACTX c)
|
||||||
gcry_md_final(c);
|
{
|
||||||
memcpy(md, gcry_md_read(c, 0), SHA384_DIGEST_LEN);
|
unsigned char *tmp = NULL;
|
||||||
gcry_md_close(c);
|
|
||||||
|
gcry_md_final(c);
|
||||||
|
tmp = gcry_md_read(c, 0);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
memcpy(md, tmp, SHA384_DIGEST_LEN);
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha384(const unsigned char *digest, int len, unsigned char *hash) {
|
int sha384(const unsigned char *digest, int len, unsigned char *hash) {
|
||||||
gcry_md_hash_buffer(GCRY_MD_SHA384, hash, digest, len);
|
gcry_md_hash_buffer(GCRY_MD_SHA384, hash, digest, len);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA512CTX sha512_init(void) {
|
SHA512CTX sha512_init(void) {
|
||||||
@@ -184,18 +183,35 @@ SHA512CTX sha512_init(void) {
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha512_update(SHACTX c, const void *data, unsigned long len) {
|
void
|
||||||
|
sha512_ctx_free(SHA512CTX c)
|
||||||
|
{
|
||||||
|
gcry_md_close(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha512_update(SHACTX c, const void *data, unsigned long len) {
|
||||||
gcry_md_write(c, data, len);
|
gcry_md_write(c, data, len);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha512_final(unsigned char *md, SHACTX c) {
|
int sha512_final(unsigned char *md, SHACTX c)
|
||||||
gcry_md_final(c);
|
{
|
||||||
memcpy(md, gcry_md_read(c, 0), SHA512_DIGEST_LEN);
|
unsigned char *tmp = NULL;
|
||||||
gcry_md_close(c);
|
|
||||||
|
gcry_md_final(c);
|
||||||
|
tmp = gcry_md_read(c, 0);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
memcpy(md, tmp, SHA512_DIGEST_LEN);
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha512(const unsigned char *digest, int len, unsigned char *hash) {
|
int sha512(const unsigned char *digest, int len, unsigned char *hash) {
|
||||||
gcry_md_hash_buffer(GCRY_MD_SHA512, hash, digest, len);
|
gcry_md_hash_buffer(GCRY_MD_SHA512, hash, digest, len);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5CTX md5_init(void) {
|
MD5CTX md5_init(void) {
|
||||||
@@ -205,14 +221,30 @@ MD5CTX md5_init(void) {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void md5_update(MD5CTX c, const void *data, unsigned long len) {
|
void
|
||||||
gcry_md_write(c,data,len);
|
md5_ctx_free(MD5CTX c)
|
||||||
|
{
|
||||||
|
gcry_md_close(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void md5_final(unsigned char *md, MD5CTX c) {
|
int md5_update(MD5CTX c, const void *data, unsigned long len) {
|
||||||
gcry_md_final(c);
|
gcry_md_write(c,data,len);
|
||||||
memcpy(md, gcry_md_read(c, 0), MD5_DIGEST_LEN);
|
return SSH_OK;
|
||||||
gcry_md_close(c);
|
}
|
||||||
|
|
||||||
|
int md5_final(unsigned char *md, MD5CTX c)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = NULL;
|
||||||
|
|
||||||
|
gcry_md_final(c);
|
||||||
|
tmp = gcry_md_read(c, 0);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
memcpy(md, tmp, MD5_DIGEST_LEN);
|
||||||
|
gcry_md_close(c);
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssh_kdf(struct ssh_crypto_struct *crypto,
|
int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||||
@@ -328,6 +360,10 @@ static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
SSH_LOG(SSH_LOG_WARNING, "Unksupported key length %u.", cipher->keysize);
|
||||||
|
SAFE_FREE(cipher->key);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (gcry_cipher_setkey(cipher->key[0], key, cipher->keysize / 8)) {
|
if (gcry_cipher_setkey(cipher->key[0], key, cipher->keysize / 8)) {
|
||||||
SAFE_FREE(cipher->key);
|
SAFE_FREE(cipher->key);
|
||||||
|
|||||||
@@ -82,99 +82,46 @@ SHACTX sha1_init(void)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha1_update(SHACTX c, const void *data, unsigned long len)
|
void
|
||||||
|
sha1_ctx_free(SHACTX c)
|
||||||
{
|
{
|
||||||
mbedtls_md_update(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha1_final(unsigned char *md, SHACTX c)
|
|
||||||
{
|
|
||||||
mbedtls_md_finish(c, md);
|
|
||||||
mbedtls_md_free(c);
|
mbedtls_md_free(c);
|
||||||
SAFE_FREE(c);
|
SAFE_FREE(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha1(const unsigned char *digest, int len, unsigned char *hash)
|
int sha1_update(SHACTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_update(c, data, len);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha1_final(unsigned char *md, SHACTX c)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_finish(c, md);
|
||||||
|
sha1_ctx_free(c);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha1(const unsigned char *digest, int len, unsigned char *hash)
|
||||||
{
|
{
|
||||||
const mbedtls_md_info_t *md_info =
|
const mbedtls_md_info_t *md_info =
|
||||||
mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
||||||
if (md_info != NULL) {
|
|
||||||
mbedtls_md(md_info, digest, len, hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static mbedtls_md_type_t nid_to_md_algo(int nid)
|
|
||||||
{
|
|
||||||
switch (nid) {
|
|
||||||
case NID_mbedtls_nistp256:
|
|
||||||
return MBEDTLS_MD_SHA256;
|
|
||||||
case NID_mbedtls_nistp384:
|
|
||||||
return MBEDTLS_MD_SHA384;
|
|
||||||
case NID_mbedtls_nistp521:
|
|
||||||
return MBEDTLS_MD_SHA512;
|
|
||||||
}
|
|
||||||
return MBEDTLS_MD_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void evp(int nid, unsigned char *digest, int len,
|
|
||||||
unsigned char *hash, unsigned int *hlen)
|
|
||||||
{
|
|
||||||
mbedtls_md_type_t algo = nid_to_md_algo(nid);
|
|
||||||
const mbedtls_md_info_t *md_info =
|
|
||||||
mbedtls_md_info_from_type(algo);
|
|
||||||
|
|
||||||
|
|
||||||
if (md_info != NULL) {
|
|
||||||
*hlen = mbedtls_md_get_size(md_info);
|
|
||||||
mbedtls_md(md_info, digest, len, hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EVPCTX evp_init(int nid)
|
|
||||||
{
|
|
||||||
EVPCTX ctx = NULL;
|
|
||||||
int rc;
|
int rc;
|
||||||
mbedtls_md_type_t algo = nid_to_md_algo(nid);
|
|
||||||
const mbedtls_md_info_t *md_info =
|
|
||||||
mbedtls_md_info_from_type(algo);
|
|
||||||
|
|
||||||
if (md_info == NULL) {
|
if (md_info == NULL) {
|
||||||
return NULL;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
rc = mbedtls_md(md_info, digest, len, hash);
|
||||||
ctx = malloc(sizeof(mbedtls_md_context_t));
|
|
||||||
if (ctx == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mbedtls_md_init(ctx);
|
|
||||||
|
|
||||||
rc = mbedtls_md_setup(ctx, md_info, 0);
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
SAFE_FREE(ctx);
|
return SSH_ERROR;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
return SSH_OK;
|
||||||
rc = mbedtls_md_starts(ctx);
|
|
||||||
if (rc != 0) {
|
|
||||||
SAFE_FREE(ctx);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void evp_update(EVPCTX ctx, const void *data, unsigned long len)
|
|
||||||
{
|
|
||||||
mbedtls_md_update(ctx, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
|
|
||||||
{
|
|
||||||
*mdlen = mbedtls_md_get_size(ctx->md_info);
|
|
||||||
mbedtls_md_finish(ctx, md);
|
|
||||||
mbedtls_md_free(ctx);
|
|
||||||
SAFE_FREE(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA256CTX sha256_init(void)
|
SHA256CTX sha256_init(void)
|
||||||
@@ -210,25 +157,46 @@ SHA256CTX sha256_init(void)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256_update(SHA256CTX c, const void *data, unsigned long len)
|
void
|
||||||
|
sha256_ctx_free(SHA256CTX c)
|
||||||
{
|
{
|
||||||
mbedtls_md_update(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha256_final(unsigned char *md, SHA256CTX c)
|
|
||||||
{
|
|
||||||
mbedtls_md_finish(c, md);
|
|
||||||
mbedtls_md_free(c);
|
mbedtls_md_free(c);
|
||||||
SAFE_FREE(c);
|
SAFE_FREE(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256(const unsigned char *digest, int len, unsigned char *hash)
|
int sha256_update(SHA256CTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_update(c, data, len);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha256_final(unsigned char *md, SHA256CTX c)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_finish(c, md);
|
||||||
|
sha256_ctx_free(c);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha256(const unsigned char *digest, int len, unsigned char *hash)
|
||||||
{
|
{
|
||||||
const mbedtls_md_info_t *md_info =
|
const mbedtls_md_info_t *md_info =
|
||||||
mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
||||||
if (md_info != NULL) {
|
int rc;
|
||||||
mbedtls_md(md_info, digest, len, hash);
|
|
||||||
|
if (md_info == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
rc = mbedtls_md(md_info, digest, len, hash);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA384CTX sha384_init(void)
|
SHA384CTX sha384_init(void)
|
||||||
@@ -264,25 +232,46 @@ SHA384CTX sha384_init(void)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha384_update(SHA384CTX c, const void *data, unsigned long len)
|
void
|
||||||
|
sha384_ctx_free(SHA384CTX c)
|
||||||
{
|
{
|
||||||
mbedtls_md_update(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha384_final(unsigned char *md, SHA384CTX c)
|
|
||||||
{
|
|
||||||
mbedtls_md_finish(c, md);
|
|
||||||
mbedtls_md_free(c);
|
mbedtls_md_free(c);
|
||||||
SAFE_FREE(c);
|
SAFE_FREE(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha384(const unsigned char *digest, int len, unsigned char *hash)
|
int sha384_update(SHA384CTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_update(c, data, len);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha384_final(unsigned char *md, SHA384CTX c)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_finish(c, md);
|
||||||
|
sha384_ctx_free(c);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha384(const unsigned char *digest, int len, unsigned char *hash)
|
||||||
{
|
{
|
||||||
const mbedtls_md_info_t *md_info =
|
const mbedtls_md_info_t *md_info =
|
||||||
mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
|
mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
|
||||||
if (md_info != NULL) {
|
int rc;
|
||||||
mbedtls_md(md_info, digest, len, hash);
|
|
||||||
|
if (md_info == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
rc = mbedtls_md(md_info, digest, len, hash);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA512CTX sha512_init(void)
|
SHA512CTX sha512_init(void)
|
||||||
@@ -317,25 +306,46 @@ SHA512CTX sha512_init(void)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha512_update(SHA512CTX c, const void *data, unsigned long len)
|
void
|
||||||
|
sha512_ctx_free(SHA512CTX c)
|
||||||
{
|
{
|
||||||
mbedtls_md_update(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha512_final(unsigned char *md, SHA512CTX c)
|
|
||||||
{
|
|
||||||
mbedtls_md_finish(c, md);
|
|
||||||
mbedtls_md_free(c);
|
mbedtls_md_free(c);
|
||||||
SAFE_FREE(c);
|
SAFE_FREE(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha512(const unsigned char *digest, int len, unsigned char *hash)
|
int sha512_update(SHA512CTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_update(c, data, len);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha512_final(unsigned char *md, SHA512CTX c)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_finish(c, md);
|
||||||
|
sha512_ctx_free(c);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sha512(const unsigned char *digest, int len, unsigned char *hash)
|
||||||
{
|
{
|
||||||
const mbedtls_md_info_t *md_info =
|
const mbedtls_md_info_t *md_info =
|
||||||
mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
||||||
if (md_info != NULL) {
|
int rc;
|
||||||
mbedtls_md(md_info, digest, len, hash);
|
|
||||||
|
if (md_info == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
rc = mbedtls_md(md_info, digest, len, hash);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5CTX md5_init(void)
|
MD5CTX md5_init(void)
|
||||||
@@ -370,18 +380,32 @@ MD5CTX md5_init(void)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
void md5_update(MD5CTX c, const void *data, unsigned long len) {
|
md5_ctx_free(MD5CTX c)
|
||||||
mbedtls_md_update(c, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void md5_final(unsigned char *md, MD5CTX c)
|
|
||||||
{
|
{
|
||||||
mbedtls_md_finish(c, md);
|
|
||||||
mbedtls_md_free(c);
|
mbedtls_md_free(c);
|
||||||
SAFE_FREE(c);
|
SAFE_FREE(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int md5_update(MD5CTX c, const void *data, unsigned long len)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_update(c, data, len);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int md5_final(unsigned char *md, MD5CTX c)
|
||||||
|
{
|
||||||
|
int rc = mbedtls_md_finish(c, md);
|
||||||
|
md5_ctx_free(c);
|
||||||
|
if (rc != 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int ssh_kdf(struct ssh_crypto_struct *crypto,
|
int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||||
unsigned char *key, size_t key_len,
|
unsigned char *key, size_t key_len,
|
||||||
int key_type, unsigned char *output,
|
int key_type, unsigned char *output,
|
||||||
@@ -687,7 +711,7 @@ static void cipher_encrypt(struct ssh_cipher_struct *cipher,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
|
static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||||
unsigned long len)
|
size_t len)
|
||||||
{
|
{
|
||||||
size_t outlen = 0;
|
size_t outlen = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -745,7 +769,7 @@ static void cipher_decrypt(struct ssh_cipher_struct *cipher,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
|
static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||||
unsigned long len)
|
size_t len)
|
||||||
{
|
{
|
||||||
size_t outlen = 0;
|
size_t outlen = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom)
|
|||||||
|
|
||||||
if (top == 0) {
|
if (top == 0) {
|
||||||
rc = mbedtls_mpi_set_bit(rnd, bits - 1, 0);
|
rc = mbedtls_mpi_set_bit(rnd, bits - 1, 0);
|
||||||
|
if (rc != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (top == 1) {
|
if (top == 1) {
|
||||||
@@ -149,7 +152,8 @@ int ssh_mbedcry_rand_range(bignum dest, bignum max)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
rc = bignum_rand(rnd, bits);
|
rc = bignum_rand(rnd, bits);
|
||||||
if (rc != 1){
|
if (rc != 1) {
|
||||||
|
bignum_safe_free(rnd);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
mbedtls_mpi_mod_mpi(dest, rnd, max);
|
mbedtls_mpi_mod_mpi(dest, rnd, max);
|
||||||
|
|||||||
@@ -513,24 +513,30 @@ static int ssh_message_termination(void *s){
|
|||||||
* @warning This function blocks until a message has been received. Betterset up
|
* @warning This function blocks until a message has been received. Betterset up
|
||||||
* a callback if this behavior is unwanted.
|
* a callback if this behavior is unwanted.
|
||||||
*/
|
*/
|
||||||
ssh_message ssh_message_get(ssh_session session) {
|
ssh_message ssh_message_get(ssh_session session)
|
||||||
ssh_message msg = NULL;
|
{
|
||||||
int rc;
|
ssh_message msg = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
msg=ssh_message_pop_head(session);
|
msg = ssh_message_pop_head(session);
|
||||||
if(msg) {
|
if (msg != NULL) {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
if(session->ssh_message_list == NULL) {
|
if (session->ssh_message_list == NULL) {
|
||||||
session->ssh_message_list = ssh_list_new();
|
session->ssh_message_list = ssh_list_new();
|
||||||
}
|
if (session->ssh_message_list == NULL) {
|
||||||
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
|
ssh_set_error_oom(session);
|
||||||
ssh_message_termination, session);
|
return NULL;
|
||||||
if(rc || session->session_state == SSH_SESSION_STATE_ERROR)
|
}
|
||||||
return NULL;
|
}
|
||||||
msg=ssh_list_pop_head(ssh_message, session->ssh_message_list);
|
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
|
||||||
|
ssh_message_termination, session);
|
||||||
|
if (rc || session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
msg = ssh_list_pop_head(ssh_message, session->ssh_message_list);
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -692,6 +698,9 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||||
|
if (crypto == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
buffer = ssh_buffer_new();
|
buffer = ssh_buffer_new();
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
@@ -705,8 +714,8 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
|||||||
|
|
||||||
rc = ssh_buffer_pack(buffer,
|
rc = ssh_buffer_pack(buffer,
|
||||||
"dPbsssbsS",
|
"dPbsssbsS",
|
||||||
crypto->digest_len, /* session ID string */
|
crypto->session_id_len, /* session ID string */
|
||||||
(size_t)crypto->digest_len, crypto->session_id,
|
crypto->session_id_len, crypto->session_id,
|
||||||
SSH2_MSG_USERAUTH_REQUEST, /* type */
|
SSH2_MSG_USERAUTH_REQUEST, /* type */
|
||||||
msg->auth_request.username,
|
msg->auth_request.username,
|
||||||
service,
|
service,
|
||||||
|
|||||||
125
src/misc.c
125
src/misc.c
@@ -32,6 +32,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@
|
|||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
|
#include <netioapi.h>
|
||||||
|
|
||||||
#ifdef HAVE_IO_H
|
#ifdef HAVE_IO_H
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
@@ -94,6 +96,8 @@
|
|||||||
#define ZLIB_STRING ""
|
#define ZLIB_STRING ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ARPA_DOMAIN_MAX_LEN 63
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup libssh_misc The SSH helper functions.
|
* @defgroup libssh_misc The SSH helper functions.
|
||||||
* @ingroup libssh
|
* @ingroup libssh
|
||||||
@@ -214,22 +218,37 @@ int ssh_is_ipaddr_v4(const char *str) {
|
|||||||
|
|
||||||
int ssh_is_ipaddr(const char *str) {
|
int ssh_is_ipaddr(const char *str) {
|
||||||
int rc = SOCKET_ERROR;
|
int rc = SOCKET_ERROR;
|
||||||
|
char *s = strdup(str);
|
||||||
|
|
||||||
if (strchr(str, ':')) {
|
if (s == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strchr(s, ':')) {
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
int sslen = sizeof(ss);
|
int sslen = sizeof(ss);
|
||||||
|
char *network_interface = strchr(s, '%');
|
||||||
|
|
||||||
/* TODO link-local (IP:v6:addr%ifname). */
|
/* link-local (IP:v6:addr%ifname). */
|
||||||
rc = WSAStringToAddressA((LPSTR) str,
|
if (network_interface != NULL) {
|
||||||
|
rc = if_nametoindex(network_interface + 1);
|
||||||
|
if (rc == 0) {
|
||||||
|
free(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*network_interface = '\0';
|
||||||
|
}
|
||||||
|
rc = WSAStringToAddressA((LPSTR) s,
|
||||||
AF_INET6,
|
AF_INET6,
|
||||||
NULL,
|
NULL,
|
||||||
(struct sockaddr*)&ss,
|
(struct sockaddr*)&ss,
|
||||||
&sslen);
|
&sslen);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
|
free(s);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(s);
|
||||||
return ssh_is_ipaddr_v4(str);
|
return ssh_is_ipaddr_v4(str);
|
||||||
}
|
}
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
@@ -333,17 +352,32 @@ int ssh_is_ipaddr_v4(const char *str) {
|
|||||||
|
|
||||||
int ssh_is_ipaddr(const char *str) {
|
int ssh_is_ipaddr(const char *str) {
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
char *s = strdup(str);
|
||||||
|
|
||||||
if (strchr(str, ':')) {
|
if (s == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strchr(s, ':')) {
|
||||||
struct in6_addr dest6;
|
struct in6_addr dest6;
|
||||||
|
char *network_interface = strchr(s, '%');
|
||||||
|
|
||||||
/* TODO link-local (IP:v6:addr%ifname). */
|
/* link-local (IP:v6:addr%ifname). */
|
||||||
rc = inet_pton(AF_INET6, str, &dest6);
|
if (network_interface != NULL) {
|
||||||
|
rc = if_nametoindex(network_interface + 1);
|
||||||
|
if (rc == 0) {
|
||||||
|
free(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*network_interface = '\0';
|
||||||
|
}
|
||||||
|
rc = inet_pton(AF_INET6, s, &dest6);
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
|
free(s);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(s);
|
||||||
return ssh_is_ipaddr_v4(str);
|
return ssh_is_ipaddr_v4(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1164,14 +1198,13 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
|
|||||||
x = strdup(session->opts.username);
|
x = strdup(session->opts.username);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
if (session->opts.port < 65536) {
|
{
|
||||||
char tmp[6];
|
char tmp[6];
|
||||||
|
|
||||||
snprintf(tmp,
|
snprintf(tmp, sizeof(tmp), "%hu",
|
||||||
sizeof(tmp),
|
(uint16_t)(session->opts.port > 0 ? session->opts.port
|
||||||
"%u",
|
: 22));
|
||||||
session->opts.port > 0 ? session->opts.port : 22);
|
x = strdup(tmp);
|
||||||
x = strdup(tmp);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1735,4 +1768,70 @@ int ssh_newline_vis(const char *string, char *buf, size_t buf_len)
|
|||||||
return out - buf;
|
return out - buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks syntax of a domain name
|
||||||
|
*
|
||||||
|
* The check is made based on the RFC1035 section 2.3.1
|
||||||
|
* Allowed characters are: hyphen, period, digits (0-9) and letters (a-zA-Z)
|
||||||
|
*
|
||||||
|
* The label should be no longer than 63 characters
|
||||||
|
* The label should start with a letter and end with a letter or number
|
||||||
|
* The label in this implementation can start with a number to allow virtual
|
||||||
|
* URLs to pass. Note that this will make IPv4 addresses to pass
|
||||||
|
* this check too.
|
||||||
|
*
|
||||||
|
* @param hostname The domain name to be checked, has to be null terminated
|
||||||
|
*
|
||||||
|
* @return SSH_OK if the hostname passes syntax check
|
||||||
|
* SSH_ERROR otherwise or if hostname is NULL or empty string
|
||||||
|
*/
|
||||||
|
int ssh_check_hostname_syntax(const char *hostname)
|
||||||
|
{
|
||||||
|
char *it = NULL, *s = NULL, *buf = NULL;
|
||||||
|
size_t it_len;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (hostname == NULL || strlen(hostname) == 0) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* strtok_r writes into the string, keep the input clean */
|
||||||
|
s = strdup(hostname);
|
||||||
|
if (s == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = strtok_r(s, ".", &buf);
|
||||||
|
/* if the token has 0 length */
|
||||||
|
if (it == NULL) {
|
||||||
|
free(s);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
it_len = strlen(it);
|
||||||
|
if (it_len > ARPA_DOMAIN_MAX_LEN ||
|
||||||
|
/* the first char must be a letter, but some virtual urls start
|
||||||
|
* with a number */
|
||||||
|
isalnum(it[0]) == 0 ||
|
||||||
|
isalnum(it[it_len - 1]) == 0) {
|
||||||
|
free(s);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
while (*it != '\0') {
|
||||||
|
c = *it;
|
||||||
|
/* the "." is allowed too, but tokenization removes it from the
|
||||||
|
* string */
|
||||||
|
if (isalnum(c) == 0 && c != '-') {
|
||||||
|
free(s);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
} while ((it = strtok_r(NULL, ".", &buf)) != NULL);
|
||||||
|
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/misc.h"
|
#include "libssh/misc.h"
|
||||||
#include "libssh/options.h"
|
#include "libssh/options.h"
|
||||||
|
#include "libssh/config_parser.h"
|
||||||
#ifdef WITH_SERVER
|
#ifdef WITH_SERVER
|
||||||
#include "libssh/server.h"
|
#include "libssh/server.h"
|
||||||
#include "libssh/bind.h"
|
#include "libssh/bind.h"
|
||||||
@@ -490,33 +491,18 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|||||||
ssh_set_error_invalid(session);
|
ssh_set_error_invalid(session);
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
q = strdup(value);
|
char *username = NULL, *hostname = NULL;
|
||||||
if (q == NULL) {
|
rc = ssh_config_parse_uri(value, &username, &hostname, NULL, true);
|
||||||
ssh_set_error_oom(session);
|
if (rc != SSH_OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p = strchr(q, '@');
|
if (username != NULL) {
|
||||||
|
|
||||||
SAFE_FREE(session->opts.host);
|
|
||||||
|
|
||||||
if (p) {
|
|
||||||
*p = '\0';
|
|
||||||
session->opts.host = strdup(p + 1);
|
|
||||||
if (session->opts.host == NULL) {
|
|
||||||
SAFE_FREE(q);
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SAFE_FREE(session->opts.username);
|
SAFE_FREE(session->opts.username);
|
||||||
session->opts.username = strdup(q);
|
session->opts.username = username;
|
||||||
SAFE_FREE(q);
|
}
|
||||||
if (session->opts.username == NULL) {
|
if (hostname != NULL) {
|
||||||
ssh_set_error_oom(session);
|
SAFE_FREE(session->opts.host);
|
||||||
return -1;
|
session->opts.host = hostname;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
session->opts.host = q;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -968,7 +954,6 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|||||||
case SSH_OPTIONS_PUBKEY_AUTH:
|
case SSH_OPTIONS_PUBKEY_AUTH:
|
||||||
case SSH_OPTIONS_KBDINT_AUTH:
|
case SSH_OPTIONS_KBDINT_AUTH:
|
||||||
case SSH_OPTIONS_GSSAPI_AUTH:
|
case SSH_OPTIONS_GSSAPI_AUTH:
|
||||||
u = 0;
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
ssh_set_error_invalid(session);
|
ssh_set_error_invalid(session);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
157
src/packet.c
157
src/packet.c
@@ -366,6 +366,11 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
if (!session->server) {
|
||||||
|
rc = SSH_PACKET_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (session->session_state != SSH_SESSION_STATE_DH) {
|
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||||
rc = SSH_PACKET_DENIED;
|
rc = SSH_PACKET_DENIED;
|
||||||
break;
|
break;
|
||||||
@@ -688,10 +693,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
/*
|
/*
|
||||||
* States required:
|
* States required:
|
||||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
|
||||||
*
|
*
|
||||||
* Transitions:
|
* Transitions:
|
||||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED
|
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||||
|
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||||
|
*
|
||||||
|
* If not in a pending state, message is ignored in the callback handler.
|
||||||
* */
|
* */
|
||||||
|
|
||||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
@@ -699,21 +706,18 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
|
||||||
rc = SSH_PACKET_DENIED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = SSH_PACKET_ALLOWED;
|
rc = SSH_PACKET_ALLOWED;
|
||||||
break;
|
break;
|
||||||
case SSH2_MSG_REQUEST_FAILURE: // 82
|
case SSH2_MSG_REQUEST_FAILURE: // 82
|
||||||
/*
|
/*
|
||||||
* States required:
|
* States required:
|
||||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
|
||||||
*
|
*
|
||||||
* Transitions:
|
* Transitions:
|
||||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED
|
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||||
|
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||||
|
*
|
||||||
|
* If not in a pending state, message is ignored in the callback handler.
|
||||||
* */
|
* */
|
||||||
|
|
||||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
@@ -721,11 +725,6 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
|
||||||
rc = SSH_PACKET_DENIED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = SSH_PACKET_ALLOWED;
|
rc = SSH_PACKET_ALLOWED;
|
||||||
break;
|
break;
|
||||||
case SSH2_MSG_CHANNEL_OPEN: // 90
|
case SSH2_MSG_CHANNEL_OPEN: // 90
|
||||||
@@ -878,10 +877,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
/*
|
/*
|
||||||
* States required:
|
* States required:
|
||||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
|
||||||
*
|
*
|
||||||
* Transitions:
|
* Transitions:
|
||||||
* - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||||
|
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||||
|
*
|
||||||
|
* If not in a pending state, message is ignored in the callback handler.
|
||||||
* */
|
* */
|
||||||
|
|
||||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
@@ -895,10 +896,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
/*
|
/*
|
||||||
* States required:
|
* States required:
|
||||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||||
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
|
||||||
*
|
*
|
||||||
* Transitions:
|
* Transitions:
|
||||||
* - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED
|
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||||
|
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||||
|
*
|
||||||
|
* If not in a pending state, message is ignored in the callback handler.
|
||||||
* */
|
* */
|
||||||
|
|
||||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
@@ -1306,6 +1309,19 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
|||||||
}
|
}
|
||||||
#endif /* WITH_ZLIB */
|
#endif /* WITH_ZLIB */
|
||||||
payloadsize = ssh_buffer_get_len(session->in_buffer);
|
payloadsize = ssh_buffer_get_len(session->in_buffer);
|
||||||
|
if (session->recv_seq == UINT32_MAX) {
|
||||||
|
/* Overflowing sequence numbers is always fishy */
|
||||||
|
if (crypto == NULL) {
|
||||||
|
/* don't allow sequence number overflow when unencrypted */
|
||||||
|
ssh_set_error(session,
|
||||||
|
SSH_FATAL,
|
||||||
|
"Incoming sequence number overflow");
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
SSH_LOG(SSH_LOG_WARNING,
|
||||||
|
"Incoming sequence number overflow");
|
||||||
|
}
|
||||||
|
}
|
||||||
session->recv_seq++;
|
session->recv_seq++;
|
||||||
if (crypto != NULL) {
|
if (crypto != NULL) {
|
||||||
struct ssh_cipher_struct *cipher = NULL;
|
struct ssh_cipher_struct *cipher = NULL;
|
||||||
@@ -1328,7 +1344,19 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
|||||||
SSH_LOG(SSH_LOG_PACKET,
|
SSH_LOG(SSH_LOG_PACKET,
|
||||||
"packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]",
|
"packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]",
|
||||||
session->in_packet.type, packet_len, padding, compsize, payloadsize);
|
session->in_packet.type, packet_len, padding, compsize, payloadsize);
|
||||||
|
if (crypto == NULL) {
|
||||||
|
/* In strict kex, only a few packets are allowed. Taint the session
|
||||||
|
* if we received packets that are normally allowed but to be
|
||||||
|
* refused if we are in strict kex when KEX is over.
|
||||||
|
*/
|
||||||
|
uint8_t type = session->in_packet.type;
|
||||||
|
|
||||||
|
if (type != SSH2_MSG_KEXINIT && type != SSH2_MSG_NEWKEYS &&
|
||||||
|
(type < SSH2_MSG_KEXDH_INIT ||
|
||||||
|
type > SSH2_MSG_KEX_DH_GEX_REQUEST)) {
|
||||||
|
session->flags |= SSH_SESSION_FLAG_KEX_TAINTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Check if the packet is expected */
|
/* Check if the packet is expected */
|
||||||
filter_result = ssh_packet_incoming_filter(session);
|
filter_result = ssh_packet_incoming_filter(session);
|
||||||
|
|
||||||
@@ -1344,6 +1372,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
|||||||
session->in_packet.type);
|
session->in_packet.type);
|
||||||
goto error;
|
goto error;
|
||||||
case SSH_PACKET_UNKNOWN:
|
case SSH_PACKET_UNKNOWN:
|
||||||
|
if (crypto == NULL) {
|
||||||
|
session->flags |= SSH_SESSION_FLAG_KEX_TAINTED;
|
||||||
|
}
|
||||||
ssh_packet_send_unimplemented(session, session->recv_seq - 1);
|
ssh_packet_send_unimplemented(session, session->recv_seq - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1412,31 +1443,41 @@ static void ssh_packet_socket_controlflow_callback(int code, void *userdata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){
|
void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s)
|
||||||
session->socket_callbacks.data=ssh_packet_socket_callback;
|
{
|
||||||
session->socket_callbacks.connected=NULL;
|
struct ssh_socket_callbacks_struct *callbacks = &session->socket_callbacks;
|
||||||
session->socket_callbacks.controlflow = ssh_packet_socket_controlflow_callback;
|
|
||||||
session->socket_callbacks.userdata=session;
|
callbacks->data = ssh_packet_socket_callback;
|
||||||
ssh_socket_set_callbacks(s,&session->socket_callbacks);
|
callbacks->connected = NULL;
|
||||||
|
callbacks->controlflow = ssh_packet_socket_controlflow_callback;
|
||||||
|
callbacks->userdata = session;
|
||||||
|
ssh_socket_set_callbacks(s, callbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief sets the callbacks for the packet layer
|
* @brief sets the callbacks for the packet layer
|
||||||
*/
|
*/
|
||||||
void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks){
|
void
|
||||||
if(session->packet_callbacks == NULL){
|
ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks)
|
||||||
session->packet_callbacks = ssh_list_new();
|
{
|
||||||
}
|
if (session->packet_callbacks == NULL) {
|
||||||
if (session->packet_callbacks != NULL) {
|
session->packet_callbacks = ssh_list_new();
|
||||||
|
if (session->packet_callbacks == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
ssh_list_append(session->packet_callbacks, callbacks);
|
ssh_list_append(session->packet_callbacks, callbacks);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief remove the callbacks from the packet layer
|
* @brief remove the callbacks from the packet layer
|
||||||
*/
|
*/
|
||||||
void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks){
|
void
|
||||||
|
ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks)
|
||||||
|
{
|
||||||
struct ssh_iterator *it = NULL;
|
struct ssh_iterator *it = NULL;
|
||||||
|
|
||||||
it = ssh_list_find(session->packet_callbacks, callbacks);
|
it = ssh_list_find(session->packet_callbacks, callbacks);
|
||||||
if (it != NULL) {
|
if (it != NULL) {
|
||||||
ssh_list_remove(session->packet_callbacks, it);
|
ssh_list_remove(session->packet_callbacks, it);
|
||||||
@@ -1446,12 +1487,15 @@ void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callb
|
|||||||
/** @internal
|
/** @internal
|
||||||
* @brief sets the default packet handlers
|
* @brief sets the default packet handlers
|
||||||
*/
|
*/
|
||||||
void ssh_packet_set_default_callbacks(ssh_session session){
|
void ssh_packet_set_default_callbacks(ssh_session session)
|
||||||
session->default_packet_callbacks.start=1;
|
{
|
||||||
session->default_packet_callbacks.n_callbacks=sizeof(default_packet_handlers)/sizeof(ssh_packet_callback);
|
struct ssh_packet_callbacks_struct *c = &session->default_packet_callbacks;
|
||||||
session->default_packet_callbacks.user=session;
|
|
||||||
session->default_packet_callbacks.callbacks=default_packet_handlers;
|
c->start = 1;
|
||||||
ssh_packet_set_callbacks(session, &session->default_packet_callbacks);
|
c->n_callbacks = sizeof(default_packet_handlers) / sizeof(ssh_packet_callback);
|
||||||
|
c->user = session;
|
||||||
|
c->callbacks = default_packet_handlers;
|
||||||
|
ssh_packet_set_callbacks(session, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
@@ -1505,9 +1549,35 @@ void ssh_packet_process(ssh_session session, uint8_t type)
|
|||||||
SSH_LOG(SSH_LOG_RARE, "Failed to send unimplemented: %s",
|
SSH_LOG(SSH_LOG_RARE, "Failed to send unimplemented: %s",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
}
|
}
|
||||||
|
if (session->current_crypto == NULL) {
|
||||||
|
session->flags |= SSH_SESSION_FLAG_KEX_TAINTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief sends a SSH_MSG_NEWKEYS when enabling the new negotiated ciphers
|
||||||
|
* @param session the SSH session
|
||||||
|
* @return SSH_ERROR on error, else SSH_OK
|
||||||
|
*/
|
||||||
|
int ssh_packet_send_newkeys(ssh_session session)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Send the MSG_NEWKEYS */
|
||||||
|
rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_packet_send(session);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief sends a SSH_MSG_UNIMPLEMENTED answer to an unhandled packet
|
* @brief sends a SSH_MSG_UNIMPLEMENTED answer to an unhandled packet
|
||||||
* @param session the SSH session
|
* @param session the SSH session
|
||||||
@@ -1813,6 +1883,10 @@ int ssh_packet_send(ssh_session session)
|
|||||||
if (rc == SSH_OK && type == SSH2_MSG_NEWKEYS) {
|
if (rc == SSH_OK && type == SSH2_MSG_NEWKEYS) {
|
||||||
struct ssh_iterator *it;
|
struct ssh_iterator *it;
|
||||||
|
|
||||||
|
if (session->flags & SSH_SESSION_FLAG_KEX_STRICT) {
|
||||||
|
/* reset packet sequence number when running in strict kex mode */
|
||||||
|
session->send_seq = 0;
|
||||||
|
}
|
||||||
for (it = ssh_list_get_iterator(session->out_queue);
|
for (it = ssh_list_get_iterator(session->out_queue);
|
||||||
it != NULL;
|
it != NULL;
|
||||||
it = ssh_list_get_iterator(session->out_queue)) {
|
it = ssh_list_get_iterator(session->out_queue)) {
|
||||||
@@ -1899,7 +1973,7 @@ ssh_packet_set_newkeys(ssh_session session,
|
|||||||
|
|
||||||
/* Both sides switched: do the actual switch now */
|
/* Both sides switched: do the actual switch now */
|
||||||
if (session->next_crypto->used == SSH_DIRECTION_BOTH) {
|
if (session->next_crypto->used == SSH_DIRECTION_BOTH) {
|
||||||
size_t digest_len;
|
size_t session_id_len;
|
||||||
|
|
||||||
if (session->current_crypto != NULL) {
|
if (session->current_crypto != NULL) {
|
||||||
crypto_free(session->current_crypto);
|
crypto_free(session->current_crypto);
|
||||||
@@ -1916,8 +1990,8 @@ ssh_packet_set_newkeys(ssh_session session,
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
digest_len = session->current_crypto->digest_len;
|
session_id_len = session->current_crypto->session_id_len;
|
||||||
session->next_crypto->session_id = malloc(digest_len);
|
session->next_crypto->session_id = malloc(session_id_len);
|
||||||
if (session->next_crypto->session_id == NULL) {
|
if (session->next_crypto->session_id == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -1925,7 +1999,8 @@ ssh_packet_set_newkeys(ssh_session session,
|
|||||||
|
|
||||||
memcpy(session->next_crypto->session_id,
|
memcpy(session->next_crypto->session_id,
|
||||||
session->current_crypto->session_id,
|
session->current_crypto->session_id,
|
||||||
digest_len);
|
session_id_len);
|
||||||
|
session->next_crypto->session_id_len = session_id_len;
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,18 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (session->flags & SSH_SESSION_FLAG_KEX_STRICT) {
|
||||||
|
/* reset packet sequence number when running in strict kex mode */
|
||||||
|
session->recv_seq = 0;
|
||||||
|
/* Check that we aren't tainted */
|
||||||
|
if (session->flags & SSH_SESSION_FLAG_KEX_TAINTED) {
|
||||||
|
ssh_set_error(session,
|
||||||
|
SSH_FATAL,
|
||||||
|
"Received unexpected packets in strict KEX mode.");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(session->server){
|
if(session->server){
|
||||||
/* server things are done in server.c */
|
/* server things are done in server.c */
|
||||||
session->dh_handshake_state=DH_STATE_FINISHED;
|
session->dh_handshake_state=DH_STATE_FINISHED;
|
||||||
@@ -129,6 +141,8 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_pki_import_signature_blob(sig_blob, server_key, &sig);
|
rc = ssh_pki_import_signature_blob(sig_blob, server_key, &sig);
|
||||||
|
ssh_string_burn(sig_blob);
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -152,10 +166,11 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
|||||||
server_key,
|
server_key,
|
||||||
session->next_crypto->secret_hash,
|
session->next_crypto->secret_hash,
|
||||||
session->next_crypto->digest_len);
|
session->next_crypto->digest_len);
|
||||||
ssh_string_burn(sig_blob);
|
SSH_SIGNATURE_FREE(sig);
|
||||||
SSH_STRING_FREE(sig_blob);
|
|
||||||
ssh_signature_free(sig);
|
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
|
ssh_set_error(session,
|
||||||
|
SSH_FATAL,
|
||||||
|
"Failed to verify server hostkey signature");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL,"Signature verified and valid");
|
SSH_LOG(SSH_LOG_PROTOCOL,"Signature verified and valid");
|
||||||
@@ -170,6 +185,9 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
|||||||
session->ssh_connection_callback(session);
|
session->ssh_connection_callback(session);
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
error:
|
error:
|
||||||
|
SSH_SIGNATURE_FREE(sig);
|
||||||
|
ssh_string_burn(sig_blob);
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ uint32_t ssh_packet_decrypt_len(ssh_session session,
|
|||||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||||
if (crypto != NULL) {
|
if (crypto != NULL) {
|
||||||
if (crypto->in_cipher->aead_decrypt_length != NULL) {
|
if (crypto->in_cipher->aead_decrypt_length != NULL) {
|
||||||
crypto->in_cipher->aead_decrypt_length(
|
rc = crypto->in_cipher->aead_decrypt_length(
|
||||||
crypto->in_cipher, source, destination,
|
crypto->in_cipher, source, destination,
|
||||||
crypto->in_cipher->lenfield_blocksize,
|
crypto->in_cipher->lenfield_blocksize,
|
||||||
session->recv_seq);
|
session->recv_seq);
|
||||||
@@ -71,9 +71,9 @@ uint32_t ssh_packet_decrypt_len(ssh_session session,
|
|||||||
source,
|
source,
|
||||||
0,
|
0,
|
||||||
crypto->in_cipher->blocksize);
|
crypto->in_cipher->blocksize);
|
||||||
if (rc < 0) {
|
}
|
||||||
return 0;
|
if (rc < 0) {
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy(destination, source, 8);
|
memcpy(destination, source, 8);
|
||||||
|
|||||||
25
src/pki.c
25
src/pki.c
@@ -1160,6 +1160,10 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
|||||||
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
|
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
|
||||||
SSH_STRING_FREE(i);
|
SSH_STRING_FREE(i);
|
||||||
if (nid == -1) {
|
if (nid == -1) {
|
||||||
|
ssh_string_burn(e);
|
||||||
|
SSH_STRING_FREE(e);
|
||||||
|
ssh_string_burn(exp);
|
||||||
|
SSH_STRING_FREE(exp);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2086,8 +2090,12 @@ int ssh_pki_export_signature_blob(const ssh_signature sig,
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
rc = ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
||||||
SSH_BUFFER_FREE(buf);
|
SSH_BUFFER_FREE(buf);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(str);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
*sig_blob = str;
|
*sig_blob = str;
|
||||||
|
|
||||||
@@ -2328,11 +2336,14 @@ ssh_string ssh_pki_do_sign(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the session ID */
|
/* Get the session ID */
|
||||||
session_id = ssh_string_new(crypto->digest_len);
|
session_id = ssh_string_new(crypto->session_id_len);
|
||||||
if (session_id == NULL) {
|
if (session_id == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ssh_string_fill(session_id, crypto->session_id, crypto->digest_len);
|
rc = ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill the input */
|
/* Fill the input */
|
||||||
sign_input = ssh_buffer_new();
|
sign_input = ssh_buffer_new();
|
||||||
@@ -2389,11 +2400,15 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* prepend session identifier */
|
/* prepend session identifier */
|
||||||
session_id = ssh_string_new(crypto->digest_len);
|
session_id = ssh_string_new(crypto->session_id_len);
|
||||||
if (session_id == NULL) {
|
if (session_id == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ssh_string_fill(session_id, crypto->session_id, crypto->digest_len);
|
rc = ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(session_id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
sig_buf = ssh_buffer_new();
|
sig_buf = ssh_buffer_new();
|
||||||
if (sig_buf == NULL) {
|
if (sig_buf == NULL) {
|
||||||
|
|||||||
120
src/pki_crypto.c
120
src/pki_crypto.c
@@ -94,7 +94,7 @@ static int pki_key_ecdsa_to_nid(EC_KEY *k)
|
|||||||
|
|
||||||
static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(EC_KEY *k)
|
static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(EC_KEY *k)
|
||||||
{
|
{
|
||||||
static int nid;
|
int nid;
|
||||||
|
|
||||||
nid = pki_key_ecdsa_to_nid(k);
|
nid = pki_key_ecdsa_to_nid(k);
|
||||||
|
|
||||||
@@ -831,7 +831,12 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(blob, buf->data, buf->length);
|
rc = ssh_string_fill(blob, buf->data, buf->length);
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_string_free(blob);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
BIO_free(mem);
|
BIO_free(mem);
|
||||||
|
|
||||||
return blob;
|
return blob;
|
||||||
@@ -1383,6 +1388,7 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
|
|||||||
|
|
||||||
const unsigned char *raw_sig_data = NULL;
|
const unsigned char *raw_sig_data = NULL;
|
||||||
size_t raw_sig_len;
|
size_t raw_sig_len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
DSA_SIG *dsa_sig;
|
DSA_SIG *dsa_sig;
|
||||||
|
|
||||||
@@ -1439,7 +1445,11 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(sig_blob, buffer, 40);
|
rc = ssh_string_fill(sig_blob, buffer, 40);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return sig_blob;
|
return sig_blob;
|
||||||
|
|
||||||
@@ -1516,7 +1526,10 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
rc = ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
||||||
|
if (rc < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
SSH_STRING_FREE(r);
|
SSH_STRING_FREE(r);
|
||||||
SSH_STRING_FREE(s);
|
SSH_STRING_FREE(s);
|
||||||
@@ -1526,6 +1539,7 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig)
|
|||||||
return sig_blob;
|
return sig_blob;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
SSH_STRING_FREE(r);
|
SSH_STRING_FREE(r);
|
||||||
SSH_STRING_FREE(s);
|
SSH_STRING_FREE(s);
|
||||||
ECDSA_SIG_free(ecdsa_sig);
|
ECDSA_SIG_free(ecdsa_sig);
|
||||||
@@ -1569,9 +1583,9 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey,
|
|||||||
ssh_signature sig)
|
ssh_signature sig)
|
||||||
{
|
{
|
||||||
uint32_t pad_len = 0;
|
uint32_t pad_len = 0;
|
||||||
char *blob_orig;
|
char *blob_orig = NULL;
|
||||||
char *blob_padded_data;
|
char *blob_padded_data = NULL;
|
||||||
ssh_string sig_blob_padded;
|
ssh_string sig_blob_padded = NULL;
|
||||||
|
|
||||||
size_t rsalen = 0;
|
size_t rsalen = 0;
|
||||||
size_t len = ssh_string_len(sig_blob);
|
size_t len = ssh_string_len(sig_blob);
|
||||||
@@ -1629,6 +1643,7 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey,
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
|
SSH_STRING_FREE(sig_blob_padded);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1646,6 +1661,7 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
|||||||
|
|
||||||
int raw_sig_len = 0;
|
int raw_sig_len = 0;
|
||||||
unsigned char *raw_sig_data = NULL;
|
unsigned char *raw_sig_data = NULL;
|
||||||
|
unsigned char *temp_raw_sig = NULL;
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -1668,7 +1684,11 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
|||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ssh_string_fill(r, ssh_string_data(sig_blob), 20);
|
rc = ssh_string_fill(r, ssh_string_data(sig_blob), 20);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(r);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
pr = ssh_make_string_bn(r);
|
pr = ssh_make_string_bn(r);
|
||||||
ssh_string_burn(r);
|
ssh_string_burn(r);
|
||||||
@@ -1681,7 +1701,11 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
|||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20);
|
rc = ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(s);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
ps = ssh_make_string_bn(s);
|
ps = ssh_make_string_bn(s);
|
||||||
ssh_string_burn(s);
|
ssh_string_burn(s);
|
||||||
@@ -1704,8 +1728,23 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
|||||||
ps = NULL;
|
ps = NULL;
|
||||||
pr = NULL;
|
pr = NULL;
|
||||||
|
|
||||||
raw_sig_len = i2d_DSA_SIG(dsa_sig, &raw_sig_data);
|
/* Get the expected size of the buffer */
|
||||||
if (raw_sig_len < 0) {
|
rc = i2d_DSA_SIG(dsa_sig, NULL);
|
||||||
|
if (rc <= 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
raw_sig_len = rc;
|
||||||
|
|
||||||
|
raw_sig_data = (unsigned char *)calloc(1, raw_sig_len);
|
||||||
|
if (raw_sig_data == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
temp_raw_sig = raw_sig_data;
|
||||||
|
|
||||||
|
/* It is necessary to use a temporary pointer as i2d_* "advances" the
|
||||||
|
* pointer */
|
||||||
|
raw_sig_len = i2d_DSA_SIG(dsa_sig, &temp_raw_sig);
|
||||||
|
if (raw_sig_len <= 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1749,6 +1788,7 @@ static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
|||||||
uint32_t rlen;
|
uint32_t rlen;
|
||||||
|
|
||||||
unsigned char *raw_sig_data = NULL;
|
unsigned char *raw_sig_data = NULL;
|
||||||
|
unsigned char *temp_raw_sig = NULL;
|
||||||
size_t raw_sig_len = 0;
|
size_t raw_sig_len = 0;
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
@@ -1824,12 +1864,26 @@ static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
|||||||
pr = NULL;
|
pr = NULL;
|
||||||
ps = NULL;
|
ps = NULL;
|
||||||
|
|
||||||
rc = i2d_ECDSA_SIG(ecdsa_sig, &raw_sig_data);
|
/* Get the expected size of the buffer */
|
||||||
if (rc < 0) {
|
rc = i2d_ECDSA_SIG(ecdsa_sig, NULL);
|
||||||
|
if (rc <= 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
raw_sig_len = rc;
|
raw_sig_len = rc;
|
||||||
|
|
||||||
|
raw_sig_data = (unsigned char *)calloc(1, raw_sig_len);
|
||||||
|
if (raw_sig_data == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
temp_raw_sig = raw_sig_data;
|
||||||
|
|
||||||
|
/* It is necessary to use a temporary pointer as i2d_* "advances" the
|
||||||
|
* pointer */
|
||||||
|
rc = i2d_ECDSA_SIG(ecdsa_sig, &temp_raw_sig);
|
||||||
|
if (rc <= 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
sig->raw_sig = ssh_string_new(raw_sig_len);
|
sig->raw_sig = ssh_string_new(raw_sig_len);
|
||||||
if (sig->raw_sig == NULL) {
|
if (sig->raw_sig == NULL) {
|
||||||
explicit_bzero(raw_sig_data, raw_sig_len);
|
explicit_bzero(raw_sig_data, raw_sig_len);
|
||||||
@@ -2237,8 +2291,12 @@ int pki_verify_data_signature(ssh_signature signature,
|
|||||||
unsigned char *raw_sig_data = NULL;
|
unsigned char *raw_sig_data = NULL;
|
||||||
unsigned int raw_sig_len;
|
unsigned int raw_sig_len;
|
||||||
|
|
||||||
|
/* Function return code
|
||||||
|
* Do not change this variable throughout the function until the signature
|
||||||
|
* is successfully verified!
|
||||||
|
*/
|
||||||
int rc = SSH_ERROR;
|
int rc = SSH_ERROR;
|
||||||
int evp_rc;
|
int ok;
|
||||||
|
|
||||||
if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL ||
|
if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL ||
|
||||||
signature == NULL || (signature->raw_sig == NULL
|
signature == NULL || (signature->raw_sig == NULL
|
||||||
@@ -2253,8 +2311,8 @@ int pki_verify_data_signature(ssh_signature signature,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if public key and hash type are compatible */
|
/* Check if public key and hash type are compatible */
|
||||||
rc = pki_key_check_hash_compatible(pubkey, signature->hash_type);
|
ok = pki_key_check_hash_compatible(pubkey, signature->hash_type);
|
||||||
if (rc != SSH_OK) {
|
if (ok != SSH_OK) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2297,8 +2355,8 @@ int pki_verify_data_signature(ssh_signature signature,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Verify the signature */
|
/* Verify the signature */
|
||||||
evp_rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey);
|
ok = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey);
|
||||||
if (evp_rc != 1){
|
if (ok != 1){
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"EVP_DigestVerifyInit() failed: %s",
|
"EVP_DigestVerifyInit() failed: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
@@ -2306,35 +2364,31 @@ int pki_verify_data_signature(ssh_signature signature,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_EVP_DIGESTVERIFY
|
#ifdef HAVE_OPENSSL_EVP_DIGESTVERIFY
|
||||||
evp_rc = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len);
|
ok = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len);
|
||||||
#else
|
#else
|
||||||
evp_rc = EVP_DigestVerifyUpdate(ctx, input, input_len);
|
ok = EVP_DigestVerifyUpdate(ctx, input, input_len);
|
||||||
if (evp_rc != 1) {
|
if (ok != 1) {
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"EVP_DigestVerifyUpdate() failed: %s",
|
"EVP_DigestVerifyUpdate() failed: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
evp_rc = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len);
|
ok = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len);
|
||||||
#endif
|
#endif
|
||||||
if (evp_rc == 1) {
|
if (ok != 1) {
|
||||||
SSH_LOG(SSH_LOG_TRACE, "Signature valid");
|
|
||||||
rc = SSH_OK;
|
|
||||||
} else {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Signature invalid: %s",
|
"Signature invalid: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
rc = SSH_ERROR;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "Signature valid");
|
||||||
|
rc = SSH_OK;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (ctx != NULL) {
|
EVP_MD_CTX_free(ctx);
|
||||||
EVP_MD_CTX_free(ctx);
|
EVP_PKEY_free(pkey);
|
||||||
}
|
|
||||||
if (pkey != NULL) {
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ int pki_ed25519_key_cmp(const ssh_key k1,
|
|||||||
if (cmp != 0) {
|
if (cmp != 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* FALL THROUGH */
|
FALL_THROUGH;
|
||||||
case SSH_KEY_CMP_PUBLIC:
|
case SSH_KEY_CMP_PUBLIC:
|
||||||
if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) {
|
if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -214,6 +214,7 @@ int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key)
|
|||||||
ssh_string pki_ed25519_signature_to_blob(ssh_signature sig)
|
ssh_string pki_ed25519_signature_to_blob(ssh_signature sig)
|
||||||
{
|
{
|
||||||
ssh_string sig_blob;
|
ssh_string sig_blob;
|
||||||
|
int rc;
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_ED25519
|
#ifdef HAVE_OPENSSL_ED25519
|
||||||
/* When using the OpenSSL implementation, the signature is stored in raw_sig
|
/* When using the OpenSSL implementation, the signature is stored in raw_sig
|
||||||
@@ -235,11 +236,15 @@ ssh_string pki_ed25519_signature_to_blob(ssh_signature sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_ED25519
|
#ifdef HAVE_OPENSSL_ED25519
|
||||||
ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig),
|
rc = ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig),
|
||||||
ssh_string_len(sig->raw_sig));
|
ssh_string_len(sig->raw_sig));
|
||||||
#else
|
#else
|
||||||
ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN);
|
rc = ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN);
|
||||||
#endif
|
#endif
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return sig_blob;
|
return sig_blob;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ static int privatekey_decrypt(int algo, int mode, unsigned int key_len,
|
|||||||
if (gcry_cipher_open(&cipher, algo, mode, 0)
|
if (gcry_cipher_open(&cipher, algo, mode, 0)
|
||||||
|| gcry_cipher_setkey(cipher, key, key_len)
|
|| gcry_cipher_setkey(cipher, key, key_len)
|
||||||
|| gcry_cipher_setiv(cipher, iv, iv_len)
|
|| gcry_cipher_setiv(cipher, iv, iv_len)
|
||||||
|| (tmp = calloc(ssh_buffer_get_len(data), sizeof(char))) == NULL
|
|| (tmp = calloc(ssh_buffer_get_len(data), sizeof(unsigned char))) == NULL
|
||||||
|| gcry_cipher_decrypt(cipher, tmp, ssh_buffer_get_len(data),
|
|| gcry_cipher_decrypt(cipher, tmp, ssh_buffer_get_len(data),
|
||||||
ssh_buffer_get(data), ssh_buffer_get_len(data))) {
|
ssh_buffer_get(data), ssh_buffer_get_len(data))) {
|
||||||
gcry_cipher_close(cipher);
|
gcry_cipher_close(cipher);
|
||||||
@@ -741,7 +741,7 @@ static int pki_key_ecdsa_to_nid(gcry_sexp_t k)
|
|||||||
|
|
||||||
static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(gcry_sexp_t k)
|
static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(gcry_sexp_t k)
|
||||||
{
|
{
|
||||||
static int nid;
|
int nid;
|
||||||
|
|
||||||
nid = pki_key_ecdsa_to_nid(k);
|
nid = pki_key_ecdsa_to_nid(k);
|
||||||
|
|
||||||
@@ -938,6 +938,8 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
|
|||||||
(void) auth_fn;
|
(void) auth_fn;
|
||||||
(void) auth_data;
|
(void) auth_data;
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_WARN, "PEM export not supported by gcrypt backend!");
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1763,6 +1765,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
|||||||
gcry_sexp_t sexp;
|
gcry_sexp_t sexp;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ssh_string sig_blob = NULL;
|
ssh_string sig_blob = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
switch(sig->type) {
|
switch(sig->type) {
|
||||||
case SSH_KEYTYPE_DSS:
|
case SSH_KEYTYPE_DSS:
|
||||||
@@ -1810,7 +1813,11 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(sig_blob, buffer, 40);
|
rc = ssh_string_fill(sig_blob, buffer, 40);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_RSA:
|
case SSH_KEYTYPE_RSA:
|
||||||
sexp = gcry_sexp_find_token(sig->rsa_sig, "s", 0);
|
sexp = gcry_sexp_find_token(sig->rsa_sig, "s", 0);
|
||||||
@@ -1827,13 +1834,16 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
|||||||
if (sig_blob == NULL) {
|
if (sig_blob == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ssh_string_fill(sig_blob, discard_const_p(char, s), size);
|
rc = ssh_string_fill(sig_blob, discard_const_p(char, s), size);
|
||||||
|
|
||||||
gcry_sexp_release(sexp);
|
gcry_sexp_release(sexp);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_ED25519:
|
case SSH_KEYTYPE_ED25519:
|
||||||
sig_blob = pki_ed25519_signature_to_blob(sig);
|
sig_blob = pki_ed25519_signature_to_blob(sig);
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_ECDSA_P256:
|
case SSH_KEYTYPE_ECDSA_P256:
|
||||||
case SSH_KEYTYPE_ECDSA_P384:
|
case SSH_KEYTYPE_ECDSA_P384:
|
||||||
case SSH_KEYTYPE_ECDSA_P521:
|
case SSH_KEYTYPE_ECDSA_P521:
|
||||||
@@ -1842,7 +1852,6 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
|||||||
ssh_string R;
|
ssh_string R;
|
||||||
ssh_string S;
|
ssh_string S;
|
||||||
ssh_buffer b;
|
ssh_buffer b;
|
||||||
int rc;
|
|
||||||
|
|
||||||
b = ssh_buffer_new();
|
b = ssh_buffer_new();
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
@@ -1883,9 +1892,13 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(sig_blob,
|
rc = ssh_string_fill(sig_blob,
|
||||||
ssh_buffer_get(b), ssh_buffer_get_len(b));
|
ssh_buffer_get(b), ssh_buffer_get_len(b));
|
||||||
SSH_BUFFER_FREE(b);
|
SSH_BUFFER_FREE(b);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ static int pki_key_ecdsa_to_nid(mbedtls_ecdsa_context *ecdsa)
|
|||||||
|
|
||||||
static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(mbedtls_ecdsa_context *ecdsa)
|
static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(mbedtls_ecdsa_context *ecdsa)
|
||||||
{
|
{
|
||||||
static int nid;
|
int nid;
|
||||||
|
|
||||||
nid = pki_key_ecdsa_to_nid(ecdsa);
|
nid = pki_key_ecdsa_to_nid(ecdsa);
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
|
|||||||
valid = auth_fn("Passphrase for private key:", (char *) tmp,
|
valid = auth_fn("Passphrase for private key:", (char *) tmp,
|
||||||
MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
|
MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
|
||||||
if (valid < 0) {
|
if (valid < 0) {
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* TODO fix signedness and strlen */
|
/* TODO fix signedness and strlen */
|
||||||
valid = mbedtls_pk_parse_key(rsa,
|
valid = mbedtls_pk_parse_key(rsa,
|
||||||
@@ -155,7 +155,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
|
|||||||
valid = auth_fn("Passphrase for private key:", (char *) tmp,
|
valid = auth_fn("Passphrase for private key:", (char *) tmp,
|
||||||
MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
|
MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
|
||||||
if (valid < 0) {
|
if (valid < 0) {
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
valid = mbedtls_pk_parse_key(ecdsa,
|
valid = mbedtls_pk_parse_key(ecdsa,
|
||||||
(const unsigned char *) b64_key,
|
(const unsigned char *) b64_key,
|
||||||
@@ -246,7 +246,7 @@ int pki_privkey_build_rsa(ssh_key key,
|
|||||||
ssh_string n,
|
ssh_string n,
|
||||||
ssh_string e,
|
ssh_string e,
|
||||||
ssh_string d,
|
ssh_string d,
|
||||||
ssh_string iqmp,
|
UNUSED_PARAM(ssh_string iqmp),
|
||||||
ssh_string p,
|
ssh_string p,
|
||||||
ssh_string q)
|
ssh_string q)
|
||||||
{
|
{
|
||||||
@@ -832,8 +832,13 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b));
|
rc = ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b));
|
||||||
SSH_BUFFER_FREE(b);
|
SSH_BUFFER_FREE(b);
|
||||||
|
if (rc < 0) {
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SSH_KEYTYPE_ED25519:
|
case SSH_KEYTYPE_ED25519:
|
||||||
@@ -1074,9 +1079,13 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_fill(sig_blob, sig, slen);
|
ok = ssh_string_fill(sig_blob, sig, slen);
|
||||||
explicit_bzero(sig, slen);
|
explicit_bzero(sig, slen);
|
||||||
SAFE_FREE(sig);
|
SAFE_FREE(sig);
|
||||||
|
if (ok < 0) {
|
||||||
|
SSH_STRING_FREE(sig_blob);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return sig_blob;
|
return sig_blob;
|
||||||
}
|
}
|
||||||
|
|||||||
255
src/server.c
255
src/server.c
@@ -92,7 +92,11 @@ int server_set_kex(ssh_session session)
|
|||||||
size_t len;
|
size_t len;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
ZERO_STRUCTP(server);
|
/* Skip if already set, for example for the rekey or when we do the guessing
|
||||||
|
* it could have been already used to make some protocol decisions. */
|
||||||
|
if (server->methods[0] != NULL) {
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
ok = ssh_get_random(server->cookie, 16, 0);
|
ok = ssh_get_random(server->cookie, 16, 0);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -191,7 +195,13 @@ int server_set_kex(ssh_session session)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
/* Do not append the extensions during rekey */
|
||||||
|
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) {
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_kex_append_extensions(session, server);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssh_server_init_kex(ssh_session session) {
|
int ssh_server_init_kex(ssh_session session) {
|
||||||
@@ -335,117 +345,121 @@ ssh_get_key_params(ssh_session session,
|
|||||||
* @brief A function to be called each time a step has been done in the
|
* @brief A function to be called each time a step has been done in the
|
||||||
* connection.
|
* connection.
|
||||||
*/
|
*/
|
||||||
static void ssh_server_connection_callback(ssh_session session){
|
static void ssh_server_connection_callback(ssh_session session)
|
||||||
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
switch(session->session_state){
|
switch (session->session_state) {
|
||||||
case SSH_SESSION_STATE_NONE:
|
case SSH_SESSION_STATE_NONE:
|
||||||
case SSH_SESSION_STATE_CONNECTING:
|
case SSH_SESSION_STATE_CONNECTING:
|
||||||
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
||||||
break;
|
break;
|
||||||
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
||||||
if (session->clientbanner == NULL) {
|
if (session->clientbanner == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
set_status(session, 0.4f);
|
set_status(session, 0.4f);
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||||
"SSH client banner: %s", session->clientbanner);
|
"SSH client banner: %s", session->clientbanner);
|
||||||
|
|
||||||
/* Here we analyze the different protocols the server allows. */
|
/* Here we analyze the different protocols the server allows. */
|
||||||
rc = ssh_analyze_banner(session, 1);
|
rc = ssh_analyze_banner(session, 1);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"No version of SSH protocol usable (banner: %s)",
|
"No version of SSH protocol usable (banner: %s)",
|
||||||
session->clientbanner);
|
session->clientbanner);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* from now, the packet layer is handling incoming packets */
|
||||||
|
session->socket_callbacks.data = ssh_packet_socket_callback;
|
||||||
|
ssh_packet_register_socket_callback(session, session->socket);
|
||||||
|
|
||||||
|
ssh_packet_set_default_callbacks(session);
|
||||||
|
set_status(session, 0.5f);
|
||||||
|
session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
|
||||||
|
if (ssh_send_kex(session) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_INITIAL_KEX:
|
||||||
|
/* TODO: This state should disappear in favor of get_key handle */
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
||||||
|
set_status(session, 0.6f);
|
||||||
|
if ((session->flags & SSH_SESSION_FLAG_KEXINIT_SENT) == 0) {
|
||||||
|
if (server_set_kex(session) == SSH_ERROR)
|
||||||
|
goto error;
|
||||||
|
/* We are in a rekeying, so we need to send the server kex */
|
||||||
|
if (ssh_send_kex(session) < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ssh_list_kex(&session->next_crypto->client_kex); // log client kex
|
||||||
|
if (ssh_kex_select_methods(session) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (crypt_set_algorithms_server(session) == SSH_ERROR)
|
||||||
|
goto error;
|
||||||
|
set_status(session, 0.8f);
|
||||||
|
session->session_state = SSH_SESSION_STATE_DH;
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_DH:
|
||||||
|
if (session->dh_handshake_state == DH_STATE_FINISHED) {
|
||||||
|
|
||||||
|
rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* from now, the packet layer is handling incoming packets */
|
/*
|
||||||
session->socket_callbacks.data=ssh_packet_socket_callback;
|
* If the client supports extension negotiation, we will send
|
||||||
ssh_packet_register_socket_callback(session, session->socket);
|
* our supported extensions now. This is the first message after
|
||||||
|
* sending NEWKEYS message and after turning on crypto.
|
||||||
ssh_packet_set_default_callbacks(session);
|
*/
|
||||||
set_status(session, 0.5f);
|
if (session->extensions & SSH_EXT_NEGOTIATION &&
|
||||||
session->session_state=SSH_SESSION_STATE_INITIAL_KEX;
|
session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||||
if (ssh_send_kex(session, 1) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_INITIAL_KEX:
|
|
||||||
/* TODO: This state should disappear in favor of get_key handle */
|
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
|
||||||
set_status(session,0.6f);
|
|
||||||
if(session->next_crypto->server_kex.methods[0]==NULL){
|
|
||||||
if(server_set_kex(session) == SSH_ERROR)
|
|
||||||
goto error;
|
|
||||||
/* We are in a rekeying, so we need to send the server kex */
|
|
||||||
if(ssh_send_kex(session, 1) < 0)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ssh_list_kex(&session->next_crypto->client_kex); // log client kex
|
|
||||||
if (ssh_kex_select_methods(session) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (crypt_set_algorithms_server(session) == SSH_ERROR)
|
|
||||||
goto error;
|
|
||||||
set_status(session,0.8f);
|
|
||||||
session->session_state=SSH_SESSION_STATE_DH;
|
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_DH:
|
|
||||||
if(session->dh_handshake_state==DH_STATE_FINISHED){
|
|
||||||
|
|
||||||
rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN);
|
|
||||||
if (rc != SSH_OK) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the client supports extension negotiation, we will send
|
* Only send an SSH_MSG_EXT_INFO message the first time the
|
||||||
* our supported extensions now. This is the first message after
|
* client undergoes NEWKEYS. It is unexpected for this message
|
||||||
* sending NEWKEYS message and after turning on crypto.
|
* to be sent upon rekey, and may cause clients to log error
|
||||||
|
* messages.
|
||||||
|
*
|
||||||
|
* The session_state can not be used for this purpose because it
|
||||||
|
* is re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey.
|
||||||
|
* So, use the connected flag which transitions from non-zero
|
||||||
|
* below.
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* - https://bugzilla.mindrot.org/show_bug.cgi?id=2929
|
||||||
*/
|
*/
|
||||||
if (session->extensions & SSH_EXT_NEGOTIATION &&
|
if (session->connected == 0) {
|
||||||
session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
ssh_server_send_extensions(session);
|
||||||
|
|
||||||
/*
|
|
||||||
* Only send an SSH_MSG_EXT_INFO message the first time the client
|
|
||||||
* undergoes NEWKEYS. It is unexpected for this message to be sent
|
|
||||||
* upon rekey, and may cause clients to log error messages.
|
|
||||||
*
|
|
||||||
* The session_state can not be used for this purpose because it is
|
|
||||||
* re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey. So,
|
|
||||||
* use the connected flag which transitions from non-zero below.
|
|
||||||
*
|
|
||||||
* See also:
|
|
||||||
* - https://bugzilla.mindrot.org/show_bug.cgi?id=2929
|
|
||||||
*/
|
|
||||||
if (session->connected == 0) {
|
|
||||||
ssh_server_send_extensions(session);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_status(session,1.0f);
|
|
||||||
session->connected = 1;
|
|
||||||
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
|
||||||
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
|
||||||
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case SSH_SESSION_STATE_AUTHENTICATING:
|
set_status(session, 1.0f);
|
||||||
break;
|
session->connected = 1;
|
||||||
case SSH_SESSION_STATE_ERROR:
|
session->session_state = SSH_SESSION_STATE_AUTHENTICATING;
|
||||||
goto error;
|
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
||||||
default:
|
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
||||||
ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_AUTHENTICATING:
|
||||||
|
break;
|
||||||
|
case SSH_SESSION_STATE_ERROR:
|
||||||
|
goto error;
|
||||||
|
default:
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Invalid state %d",
|
||||||
|
session->session_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
ssh_socket_close(session->socket);
|
ssh_socket_close(session->socket);
|
||||||
session->alive = 0;
|
session->alive = 0;
|
||||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -459,16 +473,17 @@ error:
|
|||||||
* @param user is a pointer to session
|
* @param user is a pointer to session
|
||||||
* @returns Number of bytes processed, or zero if the banner is not complete.
|
* @returns Number of bytes processed, or zero if the banner is not complete.
|
||||||
*/
|
*/
|
||||||
static int callback_receive_banner(const void *data, size_t len, void *user) {
|
static int callback_receive_banner(const void *data, size_t len, void *user)
|
||||||
char *buffer = (char *) data;
|
{
|
||||||
ssh_session session = (ssh_session) user;
|
char *buffer = (char *)data;
|
||||||
|
ssh_session session = (ssh_session)user;
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
int ret=0;
|
int ret=0;
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
#ifdef WITH_PCAP
|
#ifdef WITH_PCAP
|
||||||
if(session->pcap_ctx && buffer[i] == '\n') {
|
if (session->pcap_ctx && buffer[i] == '\n') {
|
||||||
ssh_pcap_context_write(session->pcap_ctx,
|
ssh_pcap_context_write(session->pcap_ctx,
|
||||||
SSH_PCAP_DIR_IN,
|
SSH_PCAP_DIR_IN,
|
||||||
buffer,
|
buffer,
|
||||||
@@ -477,11 +492,11 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (buffer[i] == '\r') {
|
if (buffer[i] == '\r') {
|
||||||
buffer[i]='\0';
|
buffer[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer[i] == '\n') {
|
if (buffer[i] == '\n') {
|
||||||
buffer[i]='\0';
|
buffer[i] = '\0';
|
||||||
|
|
||||||
str = strdup(buffer);
|
str = strdup(buffer);
|
||||||
/* number of bytes read */
|
/* number of bytes read */
|
||||||
@@ -494,10 +509,11 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i > 127) {
|
if (i > 127) {
|
||||||
/* Too big banner */
|
/* Too big banner */
|
||||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
ssh_set_error(session, SSH_FATAL, "Receiving banner: too large banner");
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"Receiving banner: too large banner");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -525,10 +541,14 @@ void ssh_set_auth_methods(ssh_session session, int auth_methods)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do the banner and key exchange */
|
/* Do the banner and key exchange */
|
||||||
int ssh_handle_key_exchange(ssh_session session) {
|
int ssh_handle_key_exchange(ssh_session session)
|
||||||
|
{
|
||||||
int rc;
|
int rc;
|
||||||
if (session->session_state != SSH_SESSION_STATE_NONE)
|
|
||||||
goto pending;
|
if (session->session_state != SSH_SESSION_STATE_NONE) {
|
||||||
|
goto pending;
|
||||||
|
}
|
||||||
|
|
||||||
rc = ssh_send_banner(session, 1);
|
rc = ssh_send_banner(session, 1);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -539,27 +559,28 @@ int ssh_handle_key_exchange(ssh_session session) {
|
|||||||
session->ssh_connection_callback = ssh_server_connection_callback;
|
session->ssh_connection_callback = ssh_server_connection_callback;
|
||||||
session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
|
session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||||
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
|
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
|
||||||
session->socket_callbacks.data=callback_receive_banner;
|
session->socket_callbacks.data = callback_receive_banner;
|
||||||
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
session->socket_callbacks.exception = ssh_socket_exception_callback;
|
||||||
session->socket_callbacks.userdata=session;
|
session->socket_callbacks.userdata = session;
|
||||||
|
|
||||||
rc = server_set_kex(session);
|
rc = server_set_kex(session);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
pending:
|
pending:
|
||||||
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
|
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
|
||||||
ssh_server_kex_termination,session);
|
ssh_server_kex_termination,session);
|
||||||
SSH_LOG(SSH_LOG_PACKET, "ssh_handle_key_exchange: current state : %d",
|
SSH_LOG(SSH_LOG_PACKET, "ssh_handle_key_exchange: current state : %d",
|
||||||
session->session_state);
|
session->session_state);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK) {
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||||
session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
|
session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* messages */
|
/* messages */
|
||||||
|
|||||||
@@ -372,6 +372,8 @@ const char* ssh_get_kex_algo(ssh_session session) {
|
|||||||
return "diffie-hellman-group1-sha1";
|
return "diffie-hellman-group1-sha1";
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
return "diffie-hellman-group14-sha1";
|
return "diffie-hellman-group14-sha1";
|
||||||
|
case SSH_KEX_DH_GROUP14_SHA256:
|
||||||
|
return "diffie-hellman-group14-sha256";
|
||||||
case SSH_KEX_DH_GROUP16_SHA512:
|
case SSH_KEX_DH_GROUP16_SHA512:
|
||||||
return "diffie-hellman-group16-sha512";
|
return "diffie-hellman-group16-sha512";
|
||||||
case SSH_KEX_DH_GROUP18_SHA512:
|
case SSH_KEX_DH_GROUP18_SHA512:
|
||||||
@@ -641,6 +643,10 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spoll = ssh_socket_get_poll_handle(session->socket);
|
spoll = ssh_socket_get_poll_handle(session->socket);
|
||||||
|
if (spoll == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
ssh_poll_add_events(spoll, POLLIN);
|
ssh_poll_add_events(spoll, POLLIN);
|
||||||
ctx = ssh_poll_get_ctx(spoll);
|
ctx = ssh_poll_get_ctx(spoll);
|
||||||
|
|
||||||
@@ -687,7 +693,8 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
|||||||
* @param[in] fct Termination function to be used to determine if it is
|
* @param[in] fct Termination function to be used to determine if it is
|
||||||
* possible to stop polling.
|
* possible to stop polling.
|
||||||
* @param[in] user User parameter to be passed to fct termination function.
|
* @param[in] user User parameter to be passed to fct termination function.
|
||||||
* @return SSH_OK on success, SSH_ERROR otherwise.
|
* @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
|
||||||
|
* SSH_ERROR otherwise.
|
||||||
*/
|
*/
|
||||||
int ssh_handle_packets_termination(ssh_session session,
|
int ssh_handle_packets_termination(ssh_session session,
|
||||||
long timeout,
|
long timeout,
|
||||||
@@ -994,7 +1001,18 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash)
|
|||||||
*hash = NULL;
|
*hash = NULL;
|
||||||
if (session->current_crypto == NULL ||
|
if (session->current_crypto == NULL ||
|
||||||
session->current_crypto->server_pubkey == NULL) {
|
session->current_crypto->server_pubkey == NULL) {
|
||||||
ssh_set_error(session,SSH_FATAL,"No current cryptographic context");
|
ssh_set_error(session, SSH_FATAL, "No current cryptographic context");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_get_server_publickey(session, &pubkey);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob);
|
||||||
|
ssh_key_free(pubkey);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,24 +1027,20 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash)
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_get_server_publickey(session, &pubkey);
|
rc = md5_update(ctx,
|
||||||
|
ssh_string_data(pubkey_blob),
|
||||||
|
ssh_string_len(pubkey_blob));
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
md5_final(h, ctx);
|
md5_ctx_free(ctx);
|
||||||
SAFE_FREE(h);
|
SAFE_FREE(h);
|
||||||
return SSH_ERROR;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob);
|
|
||||||
ssh_key_free(pubkey);
|
|
||||||
if (rc != SSH_OK) {
|
|
||||||
md5_final(h, ctx);
|
|
||||||
SAFE_FREE(h);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
md5_update(ctx, ssh_string_data(pubkey_blob), ssh_string_len(pubkey_blob));
|
|
||||||
SSH_STRING_FREE(pubkey_blob);
|
SSH_STRING_FREE(pubkey_blob);
|
||||||
md5_final(h, ctx);
|
rc = md5_final(h, ctx);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
SAFE_FREE(h);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
*hash = h;
|
*hash = h;
|
||||||
|
|
||||||
@@ -1146,8 +1160,17 @@ int ssh_get_publickey_hash(const ssh_key key,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
rc = sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||||
sha1_final(h, ctx);
|
if (rc != SSH_OK) {
|
||||||
|
free(h);
|
||||||
|
sha1_ctx_free(ctx);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
rc = sha1_final(h, ctx);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
free(h);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
*hlen = SHA_DIGEST_LEN;
|
*hlen = SHA_DIGEST_LEN;
|
||||||
}
|
}
|
||||||
@@ -1169,8 +1192,17 @@ int ssh_get_publickey_hash(const ssh_key key,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
rc = sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||||
sha256_final(h, ctx);
|
if (rc != SSH_OK) {
|
||||||
|
free(h);
|
||||||
|
sha256_ctx_free(ctx);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
rc = sha256_final(h, ctx);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
free(h);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
*hlen = SHA256_DIGEST_LEN;
|
*hlen = SHA256_DIGEST_LEN;
|
||||||
}
|
}
|
||||||
@@ -1200,8 +1232,17 @@ int ssh_get_publickey_hash(const ssh_key key,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
rc = md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||||
md5_final(h, ctx);
|
if (rc != SSH_OK) {
|
||||||
|
free(h);
|
||||||
|
md5_ctx_free(ctx);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
rc = md5_final(h, ctx);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
free(h);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
*hlen = MD5_DIGEST_LEN;
|
*hlen = MD5_DIGEST_LEN;
|
||||||
}
|
}
|
||||||
|
|||||||
97
src/sftp.c
97
src/sftp.c
@@ -32,6 +32,9 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif /* HAVE_SYS_TIME_H */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@@ -173,32 +176,56 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sftp_session sftp_new_channel(ssh_session session, ssh_channel channel){
|
sftp_session
|
||||||
sftp_session sftp;
|
sftp_new_channel(ssh_session session, ssh_channel channel)
|
||||||
|
{
|
||||||
|
sftp_session sftp = NULL;
|
||||||
|
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sftp = calloc(1, sizeof(struct sftp_session_struct));
|
sftp = calloc(1, sizeof(struct sftp_session_struct));
|
||||||
if (sftp == NULL) {
|
if (sftp == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
sftp->ext = sftp_ext_new();
|
||||||
}
|
if (sftp->ext == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
sftp->ext = sftp_ext_new();
|
sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct));
|
||||||
if (sftp->ext == NULL) {
|
if (sftp->read_packet == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
sftp->read_packet->payload = ssh_buffer_new();
|
||||||
|
if (sftp->read_packet->payload == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
sftp->session = session;
|
||||||
|
sftp->channel = channel;
|
||||||
|
|
||||||
|
return sftp;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (sftp->ext != NULL) {
|
||||||
|
sftp_ext_free(sftp->ext);
|
||||||
|
}
|
||||||
|
if (sftp->read_packet != NULL) {
|
||||||
|
if (sftp->read_packet->payload != NULL) {
|
||||||
|
SSH_BUFFER_FREE(sftp->read_packet->payload);
|
||||||
|
}
|
||||||
|
SAFE_FREE(sftp->read_packet);
|
||||||
|
}
|
||||||
SAFE_FREE(sftp);
|
SAFE_FREE(sftp);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
sftp->session = session;
|
|
||||||
sftp->channel = channel;
|
|
||||||
|
|
||||||
return sftp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_SERVER
|
#ifdef WITH_SERVER
|
||||||
@@ -1173,13 +1200,13 @@ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
attr->atime64 = ntohll(attr->atime64);
|
attr->atime64 = ntohll(attr->atime64);
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) {
|
if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) {
|
||||||
if (ssh_buffer_get_u32(buf, &attr->atime_nseconds) != 4) {
|
if (ssh_buffer_get_u32(buf, &attr->atime_nseconds) != 4) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
attr->atime_nseconds = ntohl(attr->atime_nseconds);
|
||||||
}
|
}
|
||||||
attr->atime_nseconds = ntohl(attr->atime_nseconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SSH_FILEXFER_ATTR_CREATETIME) {
|
if (flags & SSH_FILEXFER_ATTR_CREATETIME) {
|
||||||
@@ -1187,13 +1214,13 @@ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
attr->createtime = ntohll(attr->createtime);
|
attr->createtime = ntohll(attr->createtime);
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) {
|
if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) {
|
||||||
if (ssh_buffer_get_u32(buf, &attr->createtime_nseconds) != 4) {
|
if (ssh_buffer_get_u32(buf, &attr->createtime_nseconds) != 4) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
attr->createtime_nseconds = ntohl(attr->createtime_nseconds);
|
||||||
}
|
}
|
||||||
attr->createtime_nseconds = ntohl(attr->createtime_nseconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SSH_FILEXFER_ATTR_MODIFYTIME) {
|
if (flags & SSH_FILEXFER_ATTR_MODIFYTIME) {
|
||||||
@@ -1201,13 +1228,13 @@ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
attr->mtime64 = ntohll(attr->mtime64);
|
attr->mtime64 = ntohll(attr->mtime64);
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) {
|
if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) {
|
||||||
if (ssh_buffer_get_u32(buf, &attr->mtime_nseconds) != 4) {
|
if (ssh_buffer_get_u32(buf, &attr->mtime_nseconds) != 4) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
attr->mtime_nseconds = ntohl(attr->mtime_nseconds);
|
||||||
}
|
}
|
||||||
attr->mtime_nseconds = ntohl(attr->mtime_nseconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SSH_FILEXFER_ATTR_ACL) {
|
if (flags & SSH_FILEXFER_ATTR_ACL) {
|
||||||
|
|||||||
@@ -67,9 +67,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
|||||||
|
|
||||||
/* take a copy of the whole packet */
|
/* take a copy of the whole packet */
|
||||||
msg->complete_message = ssh_buffer_new();
|
msg->complete_message = ssh_buffer_new();
|
||||||
ssh_buffer_add_data(msg->complete_message,
|
if (msg->complete_message == NULL) {
|
||||||
ssh_buffer_get(payload),
|
ssh_set_error_oom(session);
|
||||||
ssh_buffer_get_len(payload));
|
sftp_client_message_free(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_data(msg->complete_message,
|
||||||
|
ssh_buffer_get(payload),
|
||||||
|
ssh_buffer_get_len(payload));
|
||||||
|
if (rc < 0) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
sftp_client_message_free(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ssh_buffer_get_u32(payload, &msg->id);
|
ssh_buffer_get_u32(payload, &msg->id);
|
||||||
|
|
||||||
|
|||||||
36
src/socket.c
36
src/socket.c
@@ -42,8 +42,10 @@
|
|||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <signal.h>
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
@@ -87,6 +89,9 @@ struct ssh_socket_struct {
|
|||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_socket_callbacks callbacks;
|
ssh_socket_callbacks callbacks;
|
||||||
ssh_poll_handle poll_handle;
|
ssh_poll_handle poll_handle;
|
||||||
|
#ifndef _WIN32
|
||||||
|
pid_t proxy_pid;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sockets_initialized = 0;
|
static int sockets_initialized = 0;
|
||||||
@@ -191,6 +196,9 @@ void ssh_socket_reset(ssh_socket s)
|
|||||||
s->data_except = 0;
|
s->data_except = 0;
|
||||||
s->poll_handle = NULL;
|
s->poll_handle = NULL;
|
||||||
s->state=SSH_SOCKET_NONE;
|
s->state=SSH_SOCKET_NONE;
|
||||||
|
#ifndef _WIN32
|
||||||
|
s->proxy_pid = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -454,6 +462,28 @@ void ssh_socket_close(ssh_socket s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->state = SSH_SOCKET_CLOSED;
|
s->state = SSH_SOCKET_CLOSED;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
/* If the proxy command still runs try to kill it */
|
||||||
|
if (s->proxy_pid != 0) {
|
||||||
|
int status;
|
||||||
|
pid_t pid = s->proxy_pid;
|
||||||
|
|
||||||
|
s->proxy_pid = 0;
|
||||||
|
kill(pid, SIGTERM);
|
||||||
|
while (waitpid(pid, &status, 0) == -1) {
|
||||||
|
if (errno != EINTR) {
|
||||||
|
SSH_LOG(SSH_LOG_WARN, "waitpid failed: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!WIFEXITED(status)) {
|
||||||
|
SSH_LOG(SSH_LOG_WARN, "Proxy command exitted abnormally");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "Proxy command returned %d", WEXITSTATUS(status));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -843,7 +873,7 @@ ssh_execute_command(const char *command, socket_t in, socket_t out)
|
|||||||
/* Prepare /dev/null socket for the stderr redirection */
|
/* Prepare /dev/null socket for the stderr redirection */
|
||||||
int devnull = open("/dev/null", O_WRONLY);
|
int devnull = open("/dev/null", O_WRONLY);
|
||||||
if (devnull == -1) {
|
if (devnull == -1) {
|
||||||
SSH_LOG(SSH_LOG_WARNING, "Failed to open stderr");
|
SSH_LOG(SSH_LOG_WARNING, "Failed to open /dev/null");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -886,9 +916,11 @@ ssh_socket_connect_proxycommand(ssh_socket s, const char *command)
|
|||||||
|
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "Executing proxycommand '%s'", command);
|
SSH_LOG(SSH_LOG_PROTOCOL, "Executing proxycommand '%s'", command);
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid == 0) {
|
if (pid == 0) {
|
||||||
ssh_execute_command(command, pair[0], pair[0]);
|
ssh_execute_command(command, pair[0], pair[0]);
|
||||||
|
/* Does not return */
|
||||||
}
|
}
|
||||||
|
s->proxy_pid = pid;
|
||||||
close(pair[0]);
|
close(pair[0]);
|
||||||
SSH_LOG(SSH_LOG_PROTOCOL, "ProxyCommand connection pipe: [%d,%d]",pair[0],pair[1]);
|
SSH_LOG(SSH_LOG_PROTOCOL, "ProxyCommand connection pipe: [%d,%d]",pair[0],pair[1]);
|
||||||
ssh_socket_set_fd(s, pair[1]);
|
ssh_socket_set_fd(s, pair[1]);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
static int ssh_winlock_mutex_init (void **priv)
|
static int ssh_winlock_mutex_init (void **priv)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ struct ssh_tokens_st *ssh_tokenize(const char *chain, char separator)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens->buffer= strdup(chain);
|
tokens->buffer = strdup(chain);
|
||||||
if (tokens->buffer == NULL) {
|
if (tokens->buffer == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,15 +147,16 @@ static void cipher_free(struct ssh_cipher_struct *cipher) {
|
|||||||
SAFE_FREE(cipher);
|
SAFE_FREE(cipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssh_crypto_struct *crypto_new(void) {
|
struct ssh_crypto_struct *crypto_new(void)
|
||||||
struct ssh_crypto_struct *crypto;
|
{
|
||||||
|
struct ssh_crypto_struct *crypto;
|
||||||
|
|
||||||
crypto = malloc(sizeof(struct ssh_crypto_struct));
|
crypto = malloc(sizeof(struct ssh_crypto_struct));
|
||||||
if (crypto == NULL) {
|
if (crypto == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ZERO_STRUCTP(crypto);
|
ZERO_STRUCTP(crypto);
|
||||||
return crypto;
|
return crypto;
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_free(struct ssh_crypto_struct *crypto)
|
void crypto_free(struct ssh_crypto_struct *crypto)
|
||||||
@@ -182,8 +183,9 @@ void crypto_free(struct ssh_crypto_struct *crypto)
|
|||||||
crypto->ecdh_privkey = NULL;
|
crypto->ecdh_privkey = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
SAFE_FREE(crypto->dh_server_signature);
|
||||||
if (crypto->session_id != NULL) {
|
if (crypto->session_id != NULL) {
|
||||||
explicit_bzero(crypto->session_id, crypto->digest_len);
|
explicit_bzero(crypto->session_id, crypto->session_id_len);
|
||||||
SAFE_FREE(crypto->session_id);
|
SAFE_FREE(crypto->session_id);
|
||||||
}
|
}
|
||||||
if (crypto->secret_hash != NULL) {
|
if (crypto->secret_hash != NULL) {
|
||||||
@@ -545,6 +547,7 @@ int crypt_set_algorithms_server(ssh_session session){
|
|||||||
switch (session->next_crypto->kex_type) {
|
switch (session->next_crypto->kex_type) {
|
||||||
case SSH_KEX_DH_GROUP1_SHA1:
|
case SSH_KEX_DH_GROUP1_SHA1:
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
|
case SSH_KEX_DH_GROUP14_SHA256:
|
||||||
case SSH_KEX_DH_GROUP16_SHA512:
|
case SSH_KEX_DH_GROUP16_SHA512:
|
||||||
case SSH_KEX_DH_GROUP18_SHA512:
|
case SSH_KEX_DH_GROUP18_SHA512:
|
||||||
ssh_server_dh_init(session);
|
ssh_server_dh_init(session);
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ set(TORTURE_LIBRARY torture)
|
|||||||
include_directories(${OPENSSL_INCLUDE_DIR}
|
include_directories(${OPENSSL_INCLUDE_DIR}
|
||||||
${CMOCKA_INCLUDE_DIR}
|
${CMOCKA_INCLUDE_DIR}
|
||||||
${ZLIB_INCLUDE_DIR}
|
${ZLIB_INCLUDE_DIR}
|
||||||
|
${libssh_BINARY_DIR}/include
|
||||||
${libssh_BINARY_DIR}
|
${libssh_BINARY_DIR}
|
||||||
${libssh_SOURCE_DIR}/src
|
${libssh_SOURCE_DIR}/src
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_BINARY_DIR}/tests)
|
||||||
|
|
||||||
set(TORTURE_LINK_LIBRARIES
|
set(TORTURE_LINK_LIBRARIES
|
||||||
${CMOCKA_LIBRARY}
|
${CMOCKA_LIBRARY}
|
||||||
@@ -43,22 +45,96 @@ set(TEST_TARGET_LIBRARIES
|
|||||||
|
|
||||||
add_subdirectory(unittests)
|
add_subdirectory(unittests)
|
||||||
|
|
||||||
|
# OpenSSH Capabilities are required for all unit tests
|
||||||
|
find_program(SSH_EXECUTABLE NAMES ssh)
|
||||||
|
if (SSH_EXECUTABLE)
|
||||||
|
execute_process(COMMAND ${SSH_EXECUTABLE} -V ERROR_VARIABLE OPENSSH_VERSION_STR)
|
||||||
|
string(REGEX REPLACE "^.*OpenSSH_([0-9]).[0-9].*$" "\\1" OPENSSH_VERSION_MAJOR "${OPENSSH_VERSION_STR}")
|
||||||
|
string(REGEX REPLACE "^.*OpenSSH_[0-9].([0-9]).*$" "\\1" OPENSSH_VERSION_MINOR "${OPENSSH_VERSION_STR}")
|
||||||
|
set(OPENSSH_VERSION "${OPENSSH_VERSION_MAJOR}.${OPENSSH_VERSION_MINOR}")
|
||||||
|
if("${OPENSSH_VERSION}" VERSION_LESS "6.3")
|
||||||
|
# ssh - Q was introduced in 6.3
|
||||||
|
message("Version less than 6.3, hardcoding cipher list")
|
||||||
|
set(OPENSSH_CIPHERS "aes128-ctr\naes192-ctr\naes256-ctr\narcfour256\narcfour128\naes128-gcm@openssh.com\naes256-gcm@openssh.com\naes128-cbc\n3des-cbc\nblowfish-cbc\ncast128-cbc\naes192-cbc\naes256-cbc\narcfour\nrijndael-cbc@lysator.liu.se\n")
|
||||||
|
set(OPENSSH_MACS "hmac-md5-etm@openssh.com\nhmac-sha1-etm@openssh.com\numac-64-etm@openssh.com\numac-128-etm@openssh.com\nhmac-sha2-256-etm@openssh.com\nhmac-sha2-512-etm@openssh.com\nhmac-ripemd160-etm@openssh.com\nhmac-sha1-96-etm@openssh.com\nhmac-md5-96-etm@openssh.com\nhmac-md5\nhmac-sha1\numac-64@openssh.com\numac-128@openssh.com\nhmac-sha2-256\nhmac-sha2-512\nhmac-ripemd160\nhmac-ripemd160@openssh.com\nhmac-sha1-96\nhmac-md5-96\n")
|
||||||
|
set(OPENSSH_KEX "ecdh-sha2-nistp256\necdh-sha2-nistp384\necdh-sha2-nistp521\ndiffie-hellman-group-exchange-sha256\ndiffie-hellman-group-exchange-sha1\ndiffie-hellman-group14-sha1\ndiffie-hellman-group1-sha1\n")
|
||||||
|
set(OPENSSH_KEYS "ssh-rsa\nssh-dss\necdsa-sha2-nistp256\n")
|
||||||
|
else()
|
||||||
|
execute_process(COMMAND ${SSH_EXECUTABLE} -Q cipher OUTPUT_VARIABLE OPENSSH_CIPHERS)
|
||||||
|
execute_process(COMMAND ${SSH_EXECUTABLE} -Q mac OUTPUT_VARIABLE OPENSSH_MACS)
|
||||||
|
execute_process(COMMAND ${SSH_EXECUTABLE} -Q kex OUTPUT_VARIABLE OPENSSH_KEX)
|
||||||
|
execute_process(COMMAND ${SSH_EXECUTABLE} -Q key OUTPUT_VARIABLE OPENSSH_KEYS)
|
||||||
|
execute_process(COMMAND ${SSH_EXECUTABLE} -Q sig OUTPUT_VARIABLE OPENSSH_SIGS ERROR_QUIET)
|
||||||
|
|
||||||
|
# We need both of them, but lets get rid of duplicate items presented in both lists
|
||||||
|
# to avoid processing too long arguments in pkd
|
||||||
|
set(OPENSSH_KEYS "${OPENSSH_KEYS}${OPENSSH_SIGS}")
|
||||||
|
string(REPLACE "\n" ";" OPENSSH_KEYS "${OPENSSH_KEYS}")
|
||||||
|
list(REMOVE_DUPLICATES OPENSSH_KEYS)
|
||||||
|
string(REPLACE ";" "\n" OPENSSH_KEYS "${OPENSSH_KEYS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(SSH_ALGORITHMS
|
||||||
|
3des-cbc aes128-cbc aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se aes128-ctr aes192-ctr
|
||||||
|
aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com chacha20-poly1305@openssh.com
|
||||||
|
hmac-sha1 hmac-sha1-96 hmac-sha2-256 hmac-sha2-512 hmac-md5 hmac-md5-96 umac-64@openssh.com
|
||||||
|
umac-128@openssh.com hmac-sha1-etm@openssh.com hmac-sha1-96-etm@openssh.com
|
||||||
|
hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com hmac-md5-etm@openssh.com
|
||||||
|
hmac-md5-96-etm@openssh.com umac-64-etm@openssh.com umac-128-etm@openssh.com
|
||||||
|
diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group14-sha256
|
||||||
|
diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1
|
||||||
|
diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521
|
||||||
|
curve25519-sha256 curve25519-sha256@libssh.org
|
||||||
|
ssh-ed25519 ssh-ed25519-cert-v01@openssh.com ssh-rsa ssh-dss
|
||||||
|
ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521
|
||||||
|
ssh-rsa-cert-v01@openssh.com ssh-dss-cert-v01@openssh.com
|
||||||
|
ecdsa-sha2-nistp256-cert-v01@openssh.com ecdsa-sha2-nistp384-cert-v01@openssh.com
|
||||||
|
ecdsa-sha2-nistp521-cert-v01@openssh.com
|
||||||
|
)
|
||||||
|
foreach(ALGORITHM ${SSH_ALGORITHMS})
|
||||||
|
string(TOUPPER ${ALGORITHM} VARNAME)
|
||||||
|
string(REGEX REPLACE "[-@.]" "_" VARNAME "OPENSSH_${VARNAME}")
|
||||||
|
|
||||||
|
# Match the current algorithm into the complete list of OpenSSH supported algorithms.
|
||||||
|
# If matching, create an OPENSSH_CIPHER_NAME variable.
|
||||||
|
string(REGEX MATCH ".*${ALGORITHM}\n" "${VARNAME}" "${OPENSSH_CIPHERS}${OPENSSH_MACS}${OPENSSH_KEX}${OPENSSH_KEYS}")
|
||||||
|
endforeach(ALGORITHM)
|
||||||
|
|
||||||
|
string(STRIP "${OPENSSH_CIPHERS}" OPENSSH_CIPHERS)
|
||||||
|
string(STRIP "${OPENSSH_MACS}" OPENSSH_MACS)
|
||||||
|
string(STRIP "${OPENSSH_KEX}" OPENSSH_KEX)
|
||||||
|
string(STRIP "${OPENSSH_KEYS}" OPENSSH_KEYS)
|
||||||
|
string(REPLACE "\n" "," OPENSSH_CIPHERS "${OPENSSH_CIPHERS}")
|
||||||
|
string(REPLACE "\n" "," OPENSSH_MACS "${OPENSSH_MACS}")
|
||||||
|
string(REPLACE "\n" "," OPENSSH_KEX "${OPENSSH_KEX}")
|
||||||
|
string(REPLACE "\n" "," OPENSSH_KEYS "${OPENSSH_KEYS}")
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(SSHD_EXECUTABLE
|
||||||
|
NAME
|
||||||
|
sshd
|
||||||
|
PATHS
|
||||||
|
/sbin
|
||||||
|
/usr/sbin
|
||||||
|
/usr/local/sbin)
|
||||||
|
|
||||||
if (CLIENT_TESTING OR SERVER_TESTING)
|
if (CLIENT_TESTING OR SERVER_TESTING)
|
||||||
find_package(socket_wrapper 1.1.5 REQUIRED)
|
find_package(socket_wrapper 1.1.5 REQUIRED)
|
||||||
find_package(nss_wrapper 1.1.2 REQUIRED)
|
find_package(nss_wrapper 1.1.2 REQUIRED)
|
||||||
find_package(uid_wrapper 1.2.0 REQUIRED)
|
find_package(uid_wrapper 1.2.0 REQUIRED)
|
||||||
find_package(pam_wrapper 1.0.1 REQUIRED)
|
find_package(pam_wrapper 1.0.1 REQUIRED)
|
||||||
|
|
||||||
find_program(SSHD_EXECUTABLE
|
|
||||||
NAME
|
|
||||||
sshd
|
|
||||||
PATHS
|
|
||||||
/sbin
|
|
||||||
/usr/sbin
|
|
||||||
/usr/local/sbin)
|
|
||||||
if (NOT SSHD_EXECUTABLE)
|
if (NOT SSHD_EXECUTABLE)
|
||||||
message(SEND_ERROR "Could not find sshd which is required for client testing")
|
message(SEND_ERROR "Could not find sshd which is required for client testing")
|
||||||
endif()
|
endif()
|
||||||
|
find_program(NC_EXECUTABLE
|
||||||
|
NAME
|
||||||
|
nc
|
||||||
|
PATHS
|
||||||
|
/bin
|
||||||
|
/usr/bin
|
||||||
|
/usr/local/bin)
|
||||||
|
|
||||||
find_program(SSH_EXECUTABLE NAMES ssh)
|
find_program(SSH_EXECUTABLE NAMES ssh)
|
||||||
if (SSH_EXECUTABLE)
|
if (SSH_EXECUTABLE)
|
||||||
@@ -119,7 +195,7 @@ if (CLIENT_TESTING OR SERVER_TESTING)
|
|||||||
file(COPY keys/id_ed25519 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
file(COPY keys/id_ed25519 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
file(COPY keys/id_ed25519.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
file(COPY keys/id_ed25519.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||||
|
|
||||||
# Allow to auth with bob his public keys on alice account
|
# Allow to auth with bob's public keys on alice account
|
||||||
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY)
|
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY)
|
||||||
# append ECDSA public key
|
# append ECDSA public key
|
||||||
file(READ keys/id_ecdsa.pub CONTENTS)
|
file(READ keys/id_ecdsa.pub CONTENTS)
|
||||||
@@ -137,6 +213,8 @@ if (CLIENT_TESTING OR SERVER_TESTING)
|
|||||||
message(STATUS "TORTURE_ENVIRONMENT=${TORTURE_ENVIRONMENT}")
|
message(STATUS "TORTURE_ENVIRONMENT=${TORTURE_ENVIRONMENT}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
configure_file(tests_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/tests_config.h)
|
||||||
|
|
||||||
if (WITH_BENCHMARKS)
|
if (WITH_BENCHMARKS)
|
||||||
add_subdirectory(benchmarks)
|
add_subdirectory(benchmarks)
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ if (WITH_SFTP)
|
|||||||
endif()
|
endif()
|
||||||
set(LIBSSH_CLIENT_TESTS
|
set(LIBSSH_CLIENT_TESTS
|
||||||
${LIBSSH_CLIENT_TESTS}
|
${LIBSSH_CLIENT_TESTS}
|
||||||
|
torture_sftp_init
|
||||||
torture_sftp_ext
|
torture_sftp_ext
|
||||||
torture_sftp_canonicalize_path
|
torture_sftp_canonicalize_path
|
||||||
torture_sftp_dir
|
torture_sftp_dir
|
||||||
|
|||||||
@@ -45,6 +45,16 @@ static int sshd_teardown(void **state) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sshd_setup_hmac(void **state)
|
||||||
|
{
|
||||||
|
torture_setup_sshd_server(state, false);
|
||||||
|
/* Set MAC to be something other than what the client will offer */
|
||||||
|
torture_update_sshd_config(state, "MACs hmac-sha2-512");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int session_setup(void **state) {
|
static int session_setup(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
int verbosity = torture_libssh_verbosity();
|
int verbosity = torture_libssh_verbosity();
|
||||||
@@ -412,6 +422,20 @@ static void torture_algorithms_aes256_gcm(void **state)
|
|||||||
test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-gcm@openssh.com", NULL);
|
test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-gcm@openssh.com", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_algorithms_aes128_gcm_mac(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
|
test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-gcm@openssh.com", "hmac-sha1");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_algorithms_aes256_gcm_mac(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
|
test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-gcm@openssh.com", "hmac-sha1");
|
||||||
|
}
|
||||||
|
|
||||||
static void torture_algorithms_3des_cbc_hmac_sha1(void **state) {
|
static void torture_algorithms_3des_cbc_hmac_sha1(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
@@ -472,8 +496,7 @@ static void torture_algorithms_3des_cbc_hmac_sha2_512_etm(void **state) {
|
|||||||
test_algorithm(s->ssh.session, NULL/*kex*/, "3des-cbc", "hmac-sha2-512-etm@openssh.com");
|
test_algorithm(s->ssh.session, NULL/*kex*/, "3des-cbc", "hmac-sha2-512-etm@openssh.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_BLOWFISH_CIPHER
|
#if defined(WITH_BLOWFISH_CIPHER) && defined(OPENSSH_BLOWFISH_CBC)
|
||||||
#if ((OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR < 6) || OPENSSH_VERSION_MAJOR <= 6)
|
|
||||||
static void torture_algorithms_blowfish_cbc_hmac_sha1(void **state) {
|
static void torture_algorithms_blowfish_cbc_hmac_sha1(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
@@ -533,9 +556,9 @@ static void torture_algorithms_blowfish_cbc_hmac_sha2_512_etm(void **state) {
|
|||||||
|
|
||||||
test_algorithm(s->ssh.session, NULL/*kex*/, "blowfish-cbc", "hmac-sha2-512-etm@openssh.com");
|
test_algorithm(s->ssh.session, NULL/*kex*/, "blowfish-cbc", "hmac-sha2-512-etm@openssh.com");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endif /* WITH_BLOWFISH_CIPHER */
|
#endif /* WITH_BLOWFISH_CIPHER */
|
||||||
|
|
||||||
|
#ifdef OPENSSH_CHACHA20_POLY1305_OPENSSH_COM
|
||||||
static void torture_algorithms_chacha20_poly1305(void **state)
|
static void torture_algorithms_chacha20_poly1305(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -549,6 +572,20 @@ static void torture_algorithms_chacha20_poly1305(void **state)
|
|||||||
"chacha20-poly1305@openssh.com",
|
"chacha20-poly1305@openssh.com",
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
static void torture_algorithms_chacha20_poly1305_mac(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
|
if (ssh_fips_mode()) {
|
||||||
|
skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
test_algorithm(s->ssh.session,
|
||||||
|
NULL, /*kex*/
|
||||||
|
"chacha20-poly1305@openssh.com",
|
||||||
|
"hmac-sha1"); /* different from the server */
|
||||||
|
}
|
||||||
|
#endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */
|
||||||
|
|
||||||
static void torture_algorithms_zlib(void **state) {
|
static void torture_algorithms_zlib(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -647,7 +684,7 @@ static void torture_algorithms_ecdh_sha2_nistp521(void **state) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR >= 3) || OPENSSH_VERSION_MAJOR > 7)
|
#ifdef OPENSSH_CURVE25519_SHA256
|
||||||
static void torture_algorithms_ecdh_curve25519_sha256(void **state) {
|
static void torture_algorithms_ecdh_curve25519_sha256(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
@@ -657,9 +694,9 @@ static void torture_algorithms_ecdh_curve25519_sha256(void **state) {
|
|||||||
|
|
||||||
test_algorithm(s->ssh.session, "curve25519-sha256", NULL/*cipher*/, NULL/*hmac*/);
|
test_algorithm(s->ssh.session, "curve25519-sha256", NULL/*cipher*/, NULL/*hmac*/);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* OPENSSH_CURVE25519_SHA256 */
|
||||||
|
|
||||||
#if ((OPENSSH_VERSION_MAJOR == 6 && OPENSSH_VERSION_MINOR >= 5) || OPENSSH_VERSION_MAJOR > 6)
|
#ifdef OPENSSH_CURVE25519_SHA256_LIBSSH_ORG
|
||||||
static void torture_algorithms_ecdh_curve25519_sha256_libssh_org(void **state) {
|
static void torture_algorithms_ecdh_curve25519_sha256_libssh_org(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
@@ -669,7 +706,7 @@ static void torture_algorithms_ecdh_curve25519_sha256_libssh_org(void **state) {
|
|||||||
|
|
||||||
test_algorithm(s->ssh.session, "curve25519-sha256@libssh.org", NULL/*cipher*/, NULL/*hmac*/);
|
test_algorithm(s->ssh.session, "curve25519-sha256@libssh.org", NULL/*cipher*/, NULL/*hmac*/);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* OPENSSH_CURVE25519_SHA256_LIBSSH_ORG */
|
||||||
|
|
||||||
static void torture_algorithms_dh_group1(void **state) {
|
static void torture_algorithms_dh_group1(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -691,6 +728,16 @@ static void torture_algorithms_dh_group14(void **state) {
|
|||||||
test_algorithm(s->ssh.session, "diffie-hellman-group14-sha1", NULL/*cipher*/, NULL/*hmac*/);
|
test_algorithm(s->ssh.session, "diffie-hellman-group14-sha1", NULL/*cipher*/, NULL/*hmac*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_algorithms_dh_group14_sha256(void **state) {
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
|
if (ssh_fips_mode()) {
|
||||||
|
skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
test_algorithm(s->ssh.session, "diffie-hellman-group14-sha256", NULL/*cipher*/, NULL/*hmac*/);
|
||||||
|
}
|
||||||
|
|
||||||
static void torture_algorithms_dh_group16(void **state) {
|
static void torture_algorithms_dh_group16(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
@@ -864,8 +911,7 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_512_etm,
|
cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_512_etm,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
#ifdef WITH_BLOWFISH_CIPHER
|
#if defined(WITH_BLOWFISH_CIPHER) && defined(OPENSSH_BLOWFISH_CBC)
|
||||||
#if ((OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR < 6) || OPENSSH_VERSION_MAJOR <= 6)
|
|
||||||
cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha1,
|
cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha1,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
@@ -884,11 +930,12 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_512_etm,
|
cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_512_etm,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
#endif
|
|
||||||
#endif /* WITH_BLOWFISH_CIPHER */
|
#endif /* WITH_BLOWFISH_CIPHER */
|
||||||
|
#ifdef OPENSSH_CHACHA20_POLY1305_OPENSSH_COM
|
||||||
cmocka_unit_test_setup_teardown(torture_algorithms_chacha20_poly1305,
|
cmocka_unit_test_setup_teardown(torture_algorithms_chacha20_poly1305,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
#endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */
|
||||||
cmocka_unit_test_setup_teardown(torture_algorithms_zlib,
|
cmocka_unit_test_setup_teardown(torture_algorithms_zlib,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
@@ -901,6 +948,9 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group14,
|
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group14,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group14_sha256,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group16,
|
cmocka_unit_test_setup_teardown(torture_algorithms_dh_group16,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
@@ -915,16 +965,16 @@ int torture_run_tests(void) {
|
|||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
#endif /* WITH_GEX */
|
#endif /* WITH_GEX */
|
||||||
#if ((OPENSSH_VERSION_MAJOR == 7 && OPENSSH_VERSION_MINOR >= 3) || OPENSSH_VERSION_MAJOR > 7)
|
#ifdef OPENSSH_CURVE25519_SHA256
|
||||||
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_curve25519_sha256,
|
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_curve25519_sha256,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
#endif
|
#endif /* OPENSSH_CURVE25519_SHA256 */
|
||||||
#if ((OPENSSH_VERSION_MAJOR == 6 && OPENSSH_VERSION_MINOR >= 5) || OPENSSH_VERSION_MAJOR > 6)
|
#ifdef OPENSSH_CURVE25519_SHA256_LIBSSH_ORG
|
||||||
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_curve25519_sha256_libssh_org,
|
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_curve25519_sha256_libssh_org,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
#endif
|
#endif /* OPENSSH_CURVE25519_SHA256_LIBSSH_ORG */
|
||||||
#if defined(HAVE_ECC)
|
#if defined(HAVE_ECC)
|
||||||
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_sha2_nistp256,
|
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_sha2_nistp256,
|
||||||
session_setup,
|
session_setup,
|
||||||
@@ -938,10 +988,30 @@ int torture_run_tests(void) {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CMUnitTest tests_hmac[] = {
|
||||||
|
cmocka_unit_test_setup_teardown(torture_algorithms_aes128_gcm_mac,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_algorithms_aes256_gcm_mac,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
|
#ifdef OPENSSH_CHACHA20_POLY1305_OPENSSH_COM
|
||||||
|
cmocka_unit_test_setup_teardown(torture_algorithms_chacha20_poly1305_mac,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
|
#endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */
|
||||||
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|
||||||
torture_filter_tests(tests);
|
torture_filter_tests(tests);
|
||||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
torture_filter_tests(tests);
|
||||||
|
rc = cmocka_run_group_tests(tests_hmac, sshd_setup_hmac, sshd_teardown);
|
||||||
|
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ static int session_setup(void **state)
|
|||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
int verbosity = torture_libssh_verbosity();
|
int verbosity = torture_libssh_verbosity();
|
||||||
|
const char *all_keytypes = NULL;
|
||||||
struct passwd *pwd;
|
struct passwd *pwd;
|
||||||
bool b = false;
|
bool b = false;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -71,6 +72,11 @@ static int session_setup(void **state)
|
|||||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b);
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b);
|
||||||
assert_ssh_return_code(s->ssh.session, rc);
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
/* Enable all hostkeys */
|
||||||
|
all_keytypes = ssh_kex_get_supported_method(SSH_HOSTKEYS);
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, all_keytypes);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +200,8 @@ static int agent_teardown(void **state)
|
|||||||
assert_non_null(ssh_agent_pidfile);
|
assert_non_null(ssh_agent_pidfile);
|
||||||
|
|
||||||
/* kill agent pid */
|
/* kill agent pid */
|
||||||
torture_terminate_process(ssh_agent_pidfile);
|
rc = torture_terminate_process(ssh_agent_pidfile);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
|
||||||
unlink(ssh_agent_pidfile);
|
unlink(ssh_agent_pidfile);
|
||||||
|
|
||||||
@@ -545,6 +552,7 @@ static void torture_auth_cert(void **state) {
|
|||||||
|
|
||||||
static void torture_auth_agent_cert(void **state)
|
static void torture_auth_agent_cert(void **state)
|
||||||
{
|
{
|
||||||
|
#if OPENSSH_VERSION_MAJOR < 8 || (OPENSSH_VERSION_MAJOR == 8 && OPENSSH_VERSION_MINOR == 0)
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
ssh_session session = s->ssh.session;
|
ssh_session session = s->ssh.session;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -564,6 +572,7 @@ static void torture_auth_agent_cert(void **state)
|
|||||||
"ssh-rsa-cert-v01@openssh.com");
|
"ssh-rsa-cert-v01@openssh.com");
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
}
|
}
|
||||||
|
#endif /* OPENSSH_VERSION_MAJOR < 8.1 */
|
||||||
|
|
||||||
/* Setup loads a different key, tests are exactly the same. */
|
/* Setup loads a different key, tests are exactly the same. */
|
||||||
torture_auth_agent(state);
|
torture_auth_agent(state);
|
||||||
@@ -571,6 +580,7 @@ static void torture_auth_agent_cert(void **state)
|
|||||||
|
|
||||||
static void torture_auth_agent_cert_nonblocking(void **state)
|
static void torture_auth_agent_cert_nonblocking(void **state)
|
||||||
{
|
{
|
||||||
|
#if OPENSSH_VERSION_MAJOR < 8 || (OPENSSH_VERSION_MAJOR == 8 && OPENSSH_VERSION_MINOR == 0)
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
ssh_session session = s->ssh.session;
|
ssh_session session = s->ssh.session;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -590,6 +600,7 @@ static void torture_auth_agent_cert_nonblocking(void **state)
|
|||||||
"ssh-rsa-cert-v01@openssh.com");
|
"ssh-rsa-cert-v01@openssh.com");
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
}
|
}
|
||||||
|
#endif /* OPENSSH_VERSION_MAJOR < 8.1 */
|
||||||
|
|
||||||
torture_auth_agent_nonblocking(state);
|
torture_auth_agent_nonblocking(state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,6 +183,38 @@ static void torture_connect_socket(void **state) {
|
|||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_connect_uninitialized(UNUSED_PARAM(void **state))
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
ssh_session session;
|
||||||
|
struct passwd *pwd;
|
||||||
|
|
||||||
|
/* Make sure the library is unitialized */
|
||||||
|
while (is_ssh_initialized()) {
|
||||||
|
rc = ssh_finalize();
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd = getpwnam("bob");
|
||||||
|
assert_non_null(pwd);
|
||||||
|
|
||||||
|
rc = setuid(pwd->pw_uid);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
|
||||||
|
session = ssh_new();
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* Expect error from ssh_connect */
|
||||||
|
rc = ssh_connect(session);
|
||||||
|
assert_false(rc == SSH_OK);
|
||||||
|
assert_string_equal(ssh_get_error(session), "Library not initialized.");
|
||||||
|
|
||||||
|
ssh_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
@@ -193,6 +225,7 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_connect_timeout, session_setup, session_teardown),
|
cmocka_unit_test_setup_teardown(torture_connect_timeout, session_setup, session_teardown),
|
||||||
#endif
|
#endif
|
||||||
cmocka_unit_test_setup_teardown(torture_connect_socket, session_setup, session_teardown),
|
cmocka_unit_test_setup_teardown(torture_connect_socket, session_setup, session_teardown),
|
||||||
|
cmocka_unit_test(torture_connect_uninitialized),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ static void torture_knownhosts_other_auto(void **state) {
|
|||||||
char tmp_file[1024] = {0};
|
char tmp_file[1024] = {0};
|
||||||
char *known_hosts_file = NULL;
|
char *known_hosts_file = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
bool process_config = false;
|
||||||
|
|
||||||
snprintf(tmp_file,
|
snprintf(tmp_file,
|
||||||
sizeof(tmp_file),
|
sizeof(tmp_file),
|
||||||
@@ -344,6 +345,9 @@ static void torture_knownhosts_other_auto(void **state) {
|
|||||||
|
|
||||||
s->ssh.session = session;
|
s->ssh.session = session;
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
@@ -368,6 +372,7 @@ static void torture_knownhosts_conflict(void **state) {
|
|||||||
char *known_hosts_file = NULL;
|
char *known_hosts_file = NULL;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
int rc;
|
int rc;
|
||||||
|
bool process_config = false;
|
||||||
|
|
||||||
snprintf(tmp_file,
|
snprintf(tmp_file,
|
||||||
sizeof(tmp_file),
|
sizeof(tmp_file),
|
||||||
@@ -411,6 +416,9 @@ static void torture_knownhosts_conflict(void **state) {
|
|||||||
|
|
||||||
s->ssh.session = session;
|
s->ssh.session = session;
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||||
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file);
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file);
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "rsa-sha2-256");
|
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "rsa-sha2-256");
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ static int session_teardown(void **state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NC_EXECUTABLE
|
||||||
static void torture_options_set_proxycommand(void **state)
|
static void torture_options_set_proxycommand(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -70,13 +71,13 @@ static void torture_options_set_proxycommand(void **state)
|
|||||||
int rc;
|
int rc;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
|
|
||||||
rc = stat("/bin/nc", &sb);
|
rc = stat(NC_EXECUTABLE, &sb);
|
||||||
if (rc != 0 || (sb.st_mode & S_IXOTH) == 0) {
|
if (rc != 0 || (sb.st_mode & S_IXOTH) == 0) {
|
||||||
SSH_LOG(SSH_LOG_WARNING, "Could not find /bin/nc: Skipping the test");
|
SSH_LOG(SSH_LOG_WARNING, "Could not find " NC_EXECUTABLE ": Skipping the test");
|
||||||
skip();
|
skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = snprintf(command, sizeof(command), "/bin/nc %s %d", address, port);
|
rc = snprintf(command, sizeof(command), NC_EXECUTABLE " %s %d", address, port);
|
||||||
assert_true((size_t)rc < sizeof(command));
|
assert_true((size_t)rc < sizeof(command));
|
||||||
|
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command);
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command);
|
||||||
@@ -89,6 +90,16 @@ static void torture_options_set_proxycommand(void **state)
|
|||||||
assert_int_equal(rc & O_RDWR, O_RDWR);
|
assert_int_equal(rc & O_RDWR, O_RDWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* NC_EXECUTABLE */
|
||||||
|
|
||||||
|
static void torture_options_set_proxycommand(void **state)
|
||||||
|
{
|
||||||
|
(void) state;
|
||||||
|
skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* NC_EXECUTABLE */
|
||||||
|
|
||||||
static void torture_options_set_proxycommand_notexist(void **state) {
|
static void torture_options_set_proxycommand_notexist(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
ssh_session session = s->ssh.session;
|
ssh_session session = s->ssh.session;
|
||||||
@@ -110,7 +121,9 @@ static void torture_options_set_proxycommand_ssh(void **state)
|
|||||||
int rc;
|
int rc;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
|
|
||||||
rc = snprintf(command, sizeof(command), "ssh -W [%%h]:%%p alice@%s", address);
|
rc = snprintf(command, sizeof(command),
|
||||||
|
"ssh -oStrictHostKeyChecking=no -W [%%h]:%%p alice@%s",
|
||||||
|
address);
|
||||||
assert_true((size_t)rc < sizeof(command));
|
assert_true((size_t)rc < sizeof(command));
|
||||||
|
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command);
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command);
|
||||||
@@ -132,7 +145,10 @@ static void torture_options_set_proxycommand_ssh_stderr(void **state)
|
|||||||
int rc;
|
int rc;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
|
|
||||||
rc = snprintf(command, sizeof(command), "ssh -vvv -W [%%h]:%%p alice@%s", address);
|
/* The -vvv switches produce the desired output on the standard error */
|
||||||
|
rc = snprintf(command, sizeof(command),
|
||||||
|
"ssh -vvv -oStrictHostKeyChecking=no -W [%%h]:%%p alice@%s",
|
||||||
|
address);
|
||||||
assert_true((size_t)rc < sizeof(command));
|
assert_true((size_t)rc < sizeof(command));
|
||||||
|
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command);
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command);
|
||||||
@@ -145,6 +161,56 @@ static void torture_options_set_proxycommand_ssh_stderr(void **state)
|
|||||||
assert_int_equal(rc & O_RDWR, O_RDWR);
|
assert_int_equal(rc & O_RDWR, O_RDWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_options_proxycommand_injection(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
struct passwd *pwd = NULL;
|
||||||
|
const char *malicious_host = "`echo foo > mfile`";
|
||||||
|
const char *command = "nc %h %p";
|
||||||
|
char *current_dir = NULL;
|
||||||
|
char *malicious_file_path = NULL;
|
||||||
|
int mfp_len;
|
||||||
|
int verbosity = torture_libssh_verbosity();
|
||||||
|
struct stat sb;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
pwd = getpwnam("bob");
|
||||||
|
assert_non_null(pwd);
|
||||||
|
|
||||||
|
rc = setuid(pwd->pw_uid);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
|
||||||
|
s->ssh.session = ssh_new();
|
||||||
|
assert_non_null(s->ssh.session);
|
||||||
|
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||||
|
// if we would be checking the rc, this should fail
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, malicious_host);
|
||||||
|
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||||
|
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROXYCOMMAND, command);
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
rc = ssh_connect(s->ssh.session);
|
||||||
|
assert_ssh_return_code_equal(s->ssh.session, rc, SSH_ERROR);
|
||||||
|
|
||||||
|
current_dir = torture_get_current_working_dir();
|
||||||
|
assert_non_null(current_dir);
|
||||||
|
mfp_len = strlen(current_dir) + 6;
|
||||||
|
malicious_file_path = malloc(mfp_len);
|
||||||
|
assert_non_null(malicious_file_path);
|
||||||
|
rc = snprintf(malicious_file_path, mfp_len,
|
||||||
|
"%s/mfile", current_dir);
|
||||||
|
assert_int_equal(rc, mfp_len);
|
||||||
|
free(current_dir);
|
||||||
|
rc = stat(malicious_file_path, &sb);
|
||||||
|
assert_int_not_equal(rc, 0);
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
remove(malicious_file_path);
|
||||||
|
free(malicious_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
@@ -160,6 +226,9 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_options_set_proxycommand_ssh_stderr,
|
cmocka_unit_test_setup_teardown(torture_options_set_proxycommand_ssh_stderr,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_options_proxycommand_injection,
|
||||||
|
NULL,
|
||||||
|
session_teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,10 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#define KEX_RETRY 32
|
||||||
|
|
||||||
|
static uint64_t bytes = 2048; /* 2KB (more than the authentication phase) */
|
||||||
|
|
||||||
static int sshd_setup(void **state)
|
static int sshd_setup(void **state)
|
||||||
{
|
{
|
||||||
torture_setup_sshd_server(state, false);
|
torture_setup_sshd_server(state, false);
|
||||||
@@ -72,7 +76,7 @@ static int session_setup(void **state)
|
|||||||
ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||||
ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||||
|
|
||||||
/* Authenticate as alice with bob his pubkey */
|
/* Authenticate as alice with bob's pubkey */
|
||||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
@@ -144,6 +148,29 @@ static void torture_rekey_default(void **state)
|
|||||||
ssh_disconnect(s->ssh.session);
|
ssh_disconnect(s->ssh.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sanity_check_session(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
struct ssh_crypto_struct *c = NULL;
|
||||||
|
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
assert_non_null(c);
|
||||||
|
assert_int_equal(c->in_cipher->max_blocks,
|
||||||
|
bytes / c->in_cipher->blocksize);
|
||||||
|
assert_int_equal(c->out_cipher->max_blocks,
|
||||||
|
bytes / c->out_cipher->blocksize);
|
||||||
|
/* when strict kex is used, the newkeys reset the sequence number */
|
||||||
|
if ((s->ssh.session->flags & SSH_SESSION_FLAG_KEX_STRICT) != 0) {
|
||||||
|
assert_int_equal(c->out_cipher->packets, s->ssh.session->send_seq);
|
||||||
|
assert_int_equal(c->in_cipher->packets, s->ssh.session->recv_seq);
|
||||||
|
} else {
|
||||||
|
/* Otherwise we have less encrypted packets than transferred
|
||||||
|
* (first are not encrypted) */
|
||||||
|
assert_true(c->out_cipher->packets < s->ssh.session->send_seq);
|
||||||
|
assert_true(c->in_cipher->packets < s->ssh.session->recv_seq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* We lower the rekey limits manually and check that the rekey
|
/* We lower the rekey limits manually and check that the rekey
|
||||||
* really happens when sending data
|
* really happens when sending data
|
||||||
*/
|
*/
|
||||||
@@ -153,7 +180,6 @@ static void torture_rekey_send(void **state)
|
|||||||
int rc;
|
int rc;
|
||||||
char data[256];
|
char data[256];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uint64_t bytes = 2048; /* 2KB (more than the authentication phase) */
|
|
||||||
struct ssh_crypto_struct *c = NULL;
|
struct ssh_crypto_struct *c = NULL;
|
||||||
unsigned char *secret_hash = NULL;
|
unsigned char *secret_hash = NULL;
|
||||||
|
|
||||||
@@ -163,16 +189,10 @@ static void torture_rekey_send(void **state)
|
|||||||
rc = ssh_connect(s->ssh.session);
|
rc = ssh_connect(s->ssh.session);
|
||||||
assert_ssh_return_code(s->ssh.session, rc);
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
/* The blocks limit is set correctly */
|
sanity_check_session(state);
|
||||||
c = s->ssh.session->current_crypto;
|
|
||||||
assert_int_equal(c->in_cipher->max_blocks,
|
|
||||||
bytes / c->in_cipher->blocksize);
|
|
||||||
assert_int_equal(c->out_cipher->max_blocks,
|
|
||||||
bytes / c->out_cipher->blocksize);
|
|
||||||
/* We should have less encrypted packets than transfered (first are not encrypted) */
|
|
||||||
assert_true(c->out_cipher->packets < s->ssh.session->send_seq);
|
|
||||||
assert_true(c->in_cipher->packets < s->ssh.session->recv_seq);
|
|
||||||
/* Copy the initial secret hash = session_id so we know we changed keys later */
|
/* Copy the initial secret hash = session_id so we know we changed keys later */
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
assert_non_null(c);
|
||||||
secret_hash = malloc(c->digest_len);
|
secret_hash = malloc(c->digest_len);
|
||||||
assert_non_null(secret_hash);
|
assert_non_null(secret_hash);
|
||||||
memcpy(secret_hash, c->secret_hash, c->digest_len);
|
memcpy(secret_hash, c->secret_hash, c->digest_len);
|
||||||
@@ -189,10 +209,11 @@ static void torture_rekey_send(void **state)
|
|||||||
rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL);
|
rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL);
|
||||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||||
|
|
||||||
/* send ignore packets of up to 1KB to trigger rekey */
|
/* send ignore packets of up to 1KB to trigger rekey. Send little bit more
|
||||||
|
* to make sure it completes with all different ciphers */
|
||||||
memset(data, 0, sizeof(data));
|
memset(data, 0, sizeof(data));
|
||||||
memset(data, 'A', 128);
|
memset(data, 'A', 128);
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < KEX_RETRY; i++) {
|
||||||
ssh_send_ignore(s->ssh.session, data);
|
ssh_send_ignore(s->ssh.session, data);
|
||||||
ssh_handle_packets(s->ssh.session, 50);
|
ssh_handle_packets(s->ssh.session, 50);
|
||||||
}
|
}
|
||||||
@@ -234,8 +255,6 @@ static void session_setup_sftp(void **state)
|
|||||||
assert_non_null(s->ssh.tsftp);
|
assert_non_null(s->ssh.tsftp);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t bytes = 2048; /* 2KB */
|
|
||||||
|
|
||||||
static int session_setup_sftp_client(void **state)
|
static int session_setup_sftp_client(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -270,20 +289,16 @@ static void torture_rekey_recv(void **state)
|
|||||||
sftp_file file;
|
sftp_file file;
|
||||||
mode_t mask;
|
mode_t mask;
|
||||||
|
|
||||||
/* The blocks limit is set correctly */
|
sanity_check_session(state);
|
||||||
c = s->ssh.session->current_crypto;
|
|
||||||
assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize);
|
|
||||||
assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize);
|
|
||||||
/* We should have less encrypted packets than transfered (first are not encrypted) */
|
|
||||||
assert_true(c->out_cipher->packets < s->ssh.session->send_seq);
|
|
||||||
assert_true(c->in_cipher->packets < s->ssh.session->recv_seq);
|
|
||||||
/* Copy the initial secret hash = session_id so we know we changed keys later */
|
/* Copy the initial secret hash = session_id so we know we changed keys later */
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
assert_non_null(c);
|
||||||
secret_hash = malloc(c->digest_len);
|
secret_hash = malloc(c->digest_len);
|
||||||
assert_non_null(secret_hash);
|
assert_non_null(secret_hash);
|
||||||
memcpy(secret_hash, c->secret_hash, c->digest_len);
|
memcpy(secret_hash, c->secret_hash, c->digest_len);
|
||||||
|
|
||||||
/* Download a file */
|
/* Download a file */
|
||||||
file = sftp_open(s->ssh.tsftp->sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
file = sftp_open(s->ssh.tsftp->sftp, SSH_EXECUTABLE, O_RDONLY, 0);
|
||||||
assert_non_null(file);
|
assert_non_null(file);
|
||||||
|
|
||||||
mask = umask(S_IRWXO | S_IRWXG);
|
mask = umask(S_IRWXO | S_IRWXG);
|
||||||
@@ -439,6 +454,160 @@ static void torture_rekey_server_send(void **state)
|
|||||||
ssh_disconnect(s->ssh.session);
|
ssh_disconnect(s->ssh.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_rekey_different_kex(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
int rc;
|
||||||
|
char data[256];
|
||||||
|
unsigned int i;
|
||||||
|
struct ssh_crypto_struct *c = NULL;
|
||||||
|
unsigned char *secret_hash = NULL;
|
||||||
|
size_t secret_hash_len = 0;
|
||||||
|
const char *kex1 = "diffie-hellman-group14-sha256,curve25519-sha256,ecdh-sha2-nistp256";
|
||||||
|
const char *kex2 = "diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,ecdh-sha2-nistp521";
|
||||||
|
|
||||||
|
/* Use short digest for initial key exchange */
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_KEY_EXCHANGE, kex1);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
rc = ssh_connect(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
/* The blocks limit is set correctly */
|
||||||
|
sanity_check_session(state);
|
||||||
|
/* Copy the initial secret hash = session_id so we know we changed keys later */
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
assert_non_null(c);
|
||||||
|
secret_hash = malloc(c->digest_len);
|
||||||
|
assert_non_null(secret_hash);
|
||||||
|
memcpy(secret_hash, c->secret_hash, c->digest_len);
|
||||||
|
secret_hash_len = c->digest_len;
|
||||||
|
assert_int_equal(secret_hash_len, 32); /* SHA256 len */
|
||||||
|
|
||||||
|
/* OpenSSH can not rekey before authentication so authenticate here */
|
||||||
|
rc = ssh_userauth_none(s->ssh.session, NULL);
|
||||||
|
/* This request should return a SSH_REQUEST_DENIED error */
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
assert_int_equal(ssh_get_error_code(s->ssh.session), SSH_REQUEST_DENIED);
|
||||||
|
}
|
||||||
|
rc = ssh_userauth_list(s->ssh.session, NULL);
|
||||||
|
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||||
|
|
||||||
|
rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL);
|
||||||
|
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||||
|
|
||||||
|
/* Now try to change preference of key exchange algorithm to something with larger digest */
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_KEY_EXCHANGE, kex2);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
/* send ignore packets of up to 1KB to trigger rekey. Send litle bit more
|
||||||
|
* to make sure the rekey it completes with all different ciphers (paddings */
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
memset(data, 'A', 128);
|
||||||
|
for (i = 0; i < KEX_RETRY; i++) {
|
||||||
|
ssh_send_ignore(s->ssh.session, data);
|
||||||
|
ssh_handle_packets(s->ssh.session, 100);
|
||||||
|
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
/* SHA256 len */
|
||||||
|
if (c->digest_len != 32) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The rekey limit was restored in the new crypto to the same value */
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize);
|
||||||
|
assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize);
|
||||||
|
/* Check that the secret hash is different than initially */
|
||||||
|
assert_int_equal(c->digest_len, 64); /* SHA512 len */
|
||||||
|
assert_memory_not_equal(secret_hash, c->secret_hash, secret_hash_len);
|
||||||
|
/* Session ID stays same after one rekey */
|
||||||
|
assert_memory_equal(secret_hash, c->session_id, secret_hash_len);
|
||||||
|
free(secret_hash);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_is_connected(s->ssh.session), 1);
|
||||||
|
assert_int_equal(s->ssh.session->session_state, SSH_SESSION_STATE_AUTHENTICATED);
|
||||||
|
|
||||||
|
ssh_disconnect(s->ssh.session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_rekey_server_different_kex(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
int rc;
|
||||||
|
char data[256];
|
||||||
|
unsigned int i;
|
||||||
|
struct ssh_crypto_struct *c = NULL;
|
||||||
|
unsigned char *secret_hash = NULL;
|
||||||
|
size_t secret_hash_len = 0;
|
||||||
|
const char *sshd_config = "RekeyLimit 2K none";
|
||||||
|
const char *kex1 = "diffie-hellman-group14-sha256,curve25519-sha256,ecdh-sha2-nistp256";
|
||||||
|
const char *kex2 = "diffie-hellman-group18-sha512,diffie-hellman-group16-sha512";
|
||||||
|
|
||||||
|
/* Use short digest for initial key exchange */
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_KEY_EXCHANGE, kex1);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
torture_update_sshd_config(state, sshd_config);
|
||||||
|
|
||||||
|
rc = ssh_connect(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
/* Copy the initial secret hash = session_id so we know we changed keys later */
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
secret_hash = malloc(c->digest_len);
|
||||||
|
assert_non_null(secret_hash);
|
||||||
|
memcpy(secret_hash, c->secret_hash, c->digest_len);
|
||||||
|
secret_hash_len = c->digest_len;
|
||||||
|
assert_int_equal(secret_hash_len, 32); /* SHA256 len */
|
||||||
|
|
||||||
|
/* OpenSSH can not rekey before authentication so authenticate here */
|
||||||
|
rc = ssh_userauth_none(s->ssh.session, NULL);
|
||||||
|
/* This request should return a SSH_REQUEST_DENIED error */
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
assert_int_equal(ssh_get_error_code(s->ssh.session), SSH_REQUEST_DENIED);
|
||||||
|
}
|
||||||
|
rc = ssh_userauth_list(s->ssh.session, NULL);
|
||||||
|
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||||
|
|
||||||
|
rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL);
|
||||||
|
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||||
|
|
||||||
|
/* Now try to change preference of key exchange algorithm to something with larger digest */
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_KEY_EXCHANGE, kex2);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
/* send ignore packets of up to 1KB to trigger rekey. Send litle bit more
|
||||||
|
* to make sure the rekey it completes with all different ciphers (paddings */
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
memset(data, 'A', 128);
|
||||||
|
for (i = 0; i < KEX_RETRY; i++) {
|
||||||
|
ssh_send_ignore(s->ssh.session, data);
|
||||||
|
ssh_handle_packets(s->ssh.session, 100);
|
||||||
|
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
/* SHA256 len */
|
||||||
|
if (c->digest_len != 32) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the secret hash is different than initially */
|
||||||
|
c = s->ssh.session->current_crypto;
|
||||||
|
assert_int_equal(c->digest_len, 64); /* SHA512 len */
|
||||||
|
assert_memory_not_equal(secret_hash, c->secret_hash, secret_hash_len);
|
||||||
|
/* Session ID stays same after one rekey */
|
||||||
|
assert_memory_equal(secret_hash, c->session_id, secret_hash_len);
|
||||||
|
free(secret_hash);
|
||||||
|
|
||||||
|
ssh_disconnect(s->ssh.session);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_SFTP
|
#ifdef WITH_SFTP
|
||||||
static int session_setup_sftp_server(void **state)
|
static int session_setup_sftp_server(void **state)
|
||||||
{
|
{
|
||||||
@@ -473,7 +642,7 @@ static void torture_rekey_server_recv(void **state)
|
|||||||
memcpy(secret_hash, c->secret_hash, c->digest_len);
|
memcpy(secret_hash, c->secret_hash, c->digest_len);
|
||||||
|
|
||||||
/* Download a file */
|
/* Download a file */
|
||||||
file = sftp_open(s->ssh.tsftp->sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
file = sftp_open(s->ssh.tsftp->sftp, SSH_EXECUTABLE, O_RDONLY, 0);
|
||||||
assert_non_null(file);
|
assert_non_null(file);
|
||||||
|
|
||||||
mask = umask(S_IRWXO | S_IRWXG);
|
mask = umask(S_IRWXO | S_IRWXG);
|
||||||
@@ -505,6 +674,92 @@ static void torture_rekey_server_recv(void **state)
|
|||||||
#endif /* WITH_SFTP */
|
#endif /* WITH_SFTP */
|
||||||
|
|
||||||
|
|
||||||
|
static void setup_server_for_good_guess(void *state)
|
||||||
|
{
|
||||||
|
const char *default_sshd_config = "KexAlgorithms curve25519-sha256";
|
||||||
|
const char *fips_sshd_config = "KexAlgorithms ecdh-sha2-nistp256";
|
||||||
|
const char *sshd_config = default_sshd_config;
|
||||||
|
|
||||||
|
if (ssh_fips_mode()) {
|
||||||
|
sshd_config = fips_sshd_config;
|
||||||
|
}
|
||||||
|
/* This sets an only supported kex algorithm that we do not have as a first
|
||||||
|
* option */
|
||||||
|
torture_update_sshd_config(state, sshd_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_rekey_guess_send(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
|
setup_server_for_good_guess(state);
|
||||||
|
|
||||||
|
/* Make the client send the first_kex_packet_follows flag during key
|
||||||
|
* exchange as well as during the rekey */
|
||||||
|
s->ssh.session->send_first_kex_follows = true;
|
||||||
|
|
||||||
|
torture_rekey_send(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_rekey_guess_wrong_send(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
const char *sshd_config = "KexAlgorithms diffie-hellman-group14-sha256";
|
||||||
|
|
||||||
|
/* This sets an only supported kex algorithm that we do not have as a first
|
||||||
|
* option */
|
||||||
|
torture_update_sshd_config(state, sshd_config);
|
||||||
|
|
||||||
|
/* Make the client send the first_kex_packet_follows flag during key
|
||||||
|
* exchange as well as during the rekey */
|
||||||
|
s->ssh.session->send_first_kex_follows = true;
|
||||||
|
|
||||||
|
torture_rekey_send(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_SFTP
|
||||||
|
static void torture_rekey_guess_recv(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
setup_server_for_good_guess(state);
|
||||||
|
|
||||||
|
/* Make the client send the first_kex_packet_follows flag during key
|
||||||
|
* exchange as well as during the rekey */
|
||||||
|
s->ssh.session->send_first_kex_follows = true;
|
||||||
|
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
session_setup_sftp(state);
|
||||||
|
|
||||||
|
torture_rekey_recv(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_rekey_guess_wrong_recv(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
const char *sshd_config = "KexAlgorithms diffie-hellman-group14-sha256";
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* This sets an only supported kex algorithm that we do not have as a first
|
||||||
|
* option */
|
||||||
|
torture_update_sshd_config(state, sshd_config);
|
||||||
|
|
||||||
|
/* Make the client send the first_kex_packet_follows flag during key
|
||||||
|
* exchange as well as during the rekey */
|
||||||
|
s->ssh.session->send_first_kex_follows = true;
|
||||||
|
|
||||||
|
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
session_setup_sftp(state);
|
||||||
|
|
||||||
|
torture_rekey_recv(state);
|
||||||
|
}
|
||||||
|
#endif /* WITH_SFTP */
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
@@ -522,16 +777,37 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_rekey_send,
|
cmocka_unit_test_setup_teardown(torture_rekey_send,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
/* Note, that this modifies the sshd_config */
|
cmocka_unit_test_setup_teardown(torture_rekey_different_kex,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
|
/* TODO verify the two rekey are possible and the states are not broken after rekey */
|
||||||
|
|
||||||
|
cmocka_unit_test_setup_teardown(torture_rekey_server_different_kex,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
|
/* Note, that these tests modify the sshd_config so follow-up tests
|
||||||
|
* might get unexpected behavior if they do not update the server with
|
||||||
|
* torture_update_sshd_config() too */
|
||||||
cmocka_unit_test_setup_teardown(torture_rekey_server_send,
|
cmocka_unit_test_setup_teardown(torture_rekey_server_send,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_rekey_guess_send,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_send,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
#ifdef WITH_SFTP
|
#ifdef WITH_SFTP
|
||||||
cmocka_unit_test_setup_teardown(torture_rekey_server_recv,
|
cmocka_unit_test_setup_teardown(torture_rekey_server_recv,
|
||||||
session_setup_sftp_server,
|
session_setup_sftp_server,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_rekey_guess_recv,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_recv,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
#endif /* WITH_SFTP */
|
#endif /* WITH_SFTP */
|
||||||
/* TODO verify the two rekey are possible and the states are not broken after rekey */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#define BUF_SIZE 1024
|
#define BUF_SIZE 1024
|
||||||
|
|
||||||
#define TEMPLATE BINARYDIR "/tests/home/alice/temp_dir_XXXXXX"
|
#define TEMPLATE BINARYDIR "/tests/home/alice/temp_dir_XXXXXX"
|
||||||
|
#define ALICE_HOME BINARYDIR "/tests/home/alice"
|
||||||
|
|
||||||
struct scp_st {
|
struct scp_st {
|
||||||
struct torture_state *s;
|
struct torture_state *s;
|
||||||
@@ -157,7 +158,7 @@ static void torture_scp_upload(void **state)
|
|||||||
char expected_a[BUF_SIZE];
|
char expected_a[BUF_SIZE];
|
||||||
char buf[BUF_SIZE];
|
char buf[BUF_SIZE];
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
|
size_t len = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert_non_null(state);
|
assert_non_null(state);
|
||||||
@@ -202,7 +203,8 @@ static void torture_scp_upload(void **state)
|
|||||||
file = fopen(buf, "r");
|
file = fopen(buf, "r");
|
||||||
assert_non_null(file);
|
assert_non_null(file);
|
||||||
|
|
||||||
fread(buf, BUF_SIZE, 1, file);
|
len = fread(buf, BUF_SIZE, 1, file);
|
||||||
|
assert_int_equal(len, 1);
|
||||||
assert_memory_equal(buf, expected_a, BUF_SIZE);
|
assert_memory_equal(buf, expected_a, BUF_SIZE);
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
@@ -218,8 +220,8 @@ static void torture_scp_upload_recursive(void **state)
|
|||||||
|
|
||||||
char expected_b[BUF_SIZE];
|
char expected_b[BUF_SIZE];
|
||||||
char buf[BUF_SIZE];
|
char buf[BUF_SIZE];
|
||||||
|
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -273,7 +275,8 @@ static void torture_scp_upload_recursive(void **state)
|
|||||||
file = fopen(buf, "r");
|
file = fopen(buf, "r");
|
||||||
assert_non_null(file);
|
assert_non_null(file);
|
||||||
|
|
||||||
fread(buf, BUF_SIZE, 1, file);
|
len = fread(buf, BUF_SIZE, 1, file);
|
||||||
|
assert_int_equal(len, 1);
|
||||||
assert_memory_equal(buf, expected_b, BUF_SIZE);
|
assert_memory_equal(buf, expected_b, BUF_SIZE);
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
@@ -480,7 +483,7 @@ static void torture_scp_upload_newline(void **state)
|
|||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
char *rs = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert_non_null(state);
|
assert_non_null(state);
|
||||||
@@ -531,7 +534,88 @@ static void torture_scp_upload_newline(void **state)
|
|||||||
file = fopen(buf, "r");
|
file = fopen(buf, "r");
|
||||||
assert_non_null(file);
|
assert_non_null(file);
|
||||||
|
|
||||||
fgets(buf, 1024, file);
|
rs = fgets(buf, 1024, file);
|
||||||
|
assert_non_null(rs);
|
||||||
|
assert_string_equal(buf, "original");
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_scp_upload_appended_command(void **state)
|
||||||
|
{
|
||||||
|
struct scp_st *ts = NULL;
|
||||||
|
struct torture_state *s = NULL;
|
||||||
|
|
||||||
|
ssh_session session = NULL;
|
||||||
|
ssh_scp scp = NULL;
|
||||||
|
|
||||||
|
FILE *file = NULL;
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
char *rs = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert_non_null(state);
|
||||||
|
ts = *state;
|
||||||
|
|
||||||
|
assert_non_null(ts->s);
|
||||||
|
s = ts->s;
|
||||||
|
|
||||||
|
session = s->ssh.session;
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
assert_non_null(ts->tmp_dir_basename);
|
||||||
|
assert_non_null(ts->tmp_dir);
|
||||||
|
|
||||||
|
/* Upload a file path with a command appended */
|
||||||
|
|
||||||
|
/* Append a command to the file path */
|
||||||
|
snprintf(buf, BUF_SIZE, "%s"
|
||||||
|
"/;touch hack",
|
||||||
|
ts->tmp_dir);
|
||||||
|
|
||||||
|
/* When writing the file_name must be the directory name */
|
||||||
|
scp = ssh_scp_new(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE,
|
||||||
|
buf);
|
||||||
|
assert_non_null(scp);
|
||||||
|
|
||||||
|
rc = ssh_scp_init(scp);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* Push directory where the new file will be copied */
|
||||||
|
rc = ssh_scp_push_directory(scp, ";touch hack", 0755);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* Try to push file */
|
||||||
|
rc = ssh_scp_push_file(scp, "original", 8, 0644);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
rc = ssh_scp_write(scp, "original", 8);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* Leave the directory */
|
||||||
|
rc = ssh_scp_leave_directory(scp);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
ssh_scp_close(scp);
|
||||||
|
ssh_scp_free(scp);
|
||||||
|
|
||||||
|
/* Make sure the command was not executed */
|
||||||
|
snprintf(buf, BUF_SIZE, ALICE_HOME "/hack");
|
||||||
|
file = fopen(buf, "r");
|
||||||
|
assert_null(file);
|
||||||
|
|
||||||
|
/* Open the file and check content */
|
||||||
|
snprintf(buf, BUF_SIZE, "%s"
|
||||||
|
"/;touch hack/original",
|
||||||
|
ts->tmp_dir);
|
||||||
|
|
||||||
|
file = fopen(buf, "r");
|
||||||
|
assert_non_null(file);
|
||||||
|
|
||||||
|
rs = fgets(buf, 1024, file);
|
||||||
|
assert_non_null(rs);
|
||||||
assert_string_equal(buf, "original");
|
assert_string_equal(buf, "original");
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
@@ -556,6 +640,9 @@ int torture_run_tests(void)
|
|||||||
cmocka_unit_test_setup_teardown(torture_scp_upload_newline,
|
cmocka_unit_test_setup_teardown(torture_scp_upload_newline,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_scp_upload_appended_command,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user