mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 04:40:31 +09:00
Compare commits
89 Commits
libssh-0.9
...
libssh-0.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,6 +5,7 @@
|
||||
*~$
|
||||
cscope.*
|
||||
compile_commands.json
|
||||
/.cache
|
||||
/.clangd
|
||||
tags
|
||||
/build
|
||||
|
||||
133
.gitlab-ci.yml
133
.gitlab-ci.yml
@@ -2,6 +2,8 @@ variables:
|
||||
BUILD_IMAGES_PROJECT: libssh/build-images
|
||||
FEDORA_BUILD: buildenv-fedora
|
||||
CENTOS7_BUILD: buildenv-centos7
|
||||
CENTOS8_BUILD: buildenv-c8s
|
||||
CENTOS9_BUILD: buildenv-c9s
|
||||
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
||||
MINGW_BUILD: buildenv-mingw
|
||||
|
||||
@@ -25,6 +27,47 @@ centos7/openssl_1.0.x/x86_64:
|
||||
paths:
|
||||
- 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:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
@@ -47,8 +90,8 @@ fedora/openssl_1.1.x/x86_64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
fedora/openssl_1.1.x/x86_64/fips:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
centos8/openssl_1.1.1/x86_64/fips:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS8_BUILD
|
||||
script:
|
||||
- echo 1 > /etc/system-fips
|
||||
- update-crypto-policies --set FIPS
|
||||
@@ -197,11 +240,13 @@ freebsd/x86_64:
|
||||
make && ctest --output-on-failure
|
||||
tags:
|
||||
- freebsd
|
||||
- private
|
||||
except:
|
||||
- tags
|
||||
only:
|
||||
- branches@libssh/libssh-mirror
|
||||
- branches@cryptomilk/libssh-mirror
|
||||
- branches@jjelen/libssh-mirror
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
@@ -455,61 +500,55 @@ tumbleweed/static-analysis:
|
||||
paths:
|
||||
- obj/scan
|
||||
|
||||
visualstudio/x86_64:
|
||||
###############################################################################
|
||||
# Visual Studio builds #
|
||||
###############################################################################
|
||||
.vs:
|
||||
stage: test
|
||||
cache:
|
||||
key: vcpkg.${CI_JOB_NAME}
|
||||
paths:
|
||||
- .vcpkg
|
||||
variables:
|
||||
ErrorActionPreference: STOP
|
||||
script:
|
||||
- $env:VCPKG_DEFAULT_TRIPLET="x64-windows"
|
||||
- mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1}
|
||||
- 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
|
||||
- cmake --build .
|
||||
- ctest --output-on-failure
|
||||
tags:
|
||||
- vs2017
|
||||
- windows
|
||||
- windows
|
||||
- shared-windows
|
||||
except:
|
||||
- tags
|
||||
only:
|
||||
- branches@libssh/libssh-mirror
|
||||
- branches@ansasaki/libssh-mirror
|
||||
- branches@cryptomilk/libssh-mirror
|
||||
- branches@jjelen/libssh-mirror
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- 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:
|
||||
extends: .vs
|
||||
variables:
|
||||
ErrorActionPreference: STOP
|
||||
script:
|
||||
- $env:VCPKG_DEFAULT_TRIPLET="x86-windows"
|
||||
- mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1}
|
||||
- cmake
|
||||
-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/
|
||||
PLATFORM: "win32"
|
||||
TRIPLET: "x86"
|
||||
|
||||
@@ -10,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
|
||||
project(libssh VERSION 0.9.5 LANGUAGES C)
|
||||
project(libssh VERSION 0.9.7 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -22,7 +22,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.8.6")
|
||||
set(LIBRARY_VERSION "4.8.8")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
@@ -59,7 +59,13 @@ elseif(WITH_MBEDTLS)
|
||||
endif (NOT MBEDTLS_FOUND)
|
||||
else (WITH_GCRYPT)
|
||||
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)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
find_package(MbedTLS)
|
||||
@@ -67,7 +73,7 @@ else (WITH_GCRYPT)
|
||||
message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
|
||||
endif (NOT MBEDTLS_FOUND)
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
endif (NOT OPENSSL_FOUND)
|
||||
endif (OPENSSL_FOUND)
|
||||
endif(WITH_GCRYPT)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
@@ -203,10 +209,10 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
endif(UPDATE_ABI)
|
||||
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
|
||||
execute_process(COMMAND cmake -E create_symlink
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"${CMAKE_BINARY_DIR}/compile_commands.json"
|
||||
"${CMAKE_SOURCE_DIR}/compile_commands.json")
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
|
||||
# SOURCE GENERATOR
|
||||
set(CPACK_SOURCE_GENERATOR "TXZ")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;/[.]clangd/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
### NSIS INSTALLER
|
||||
|
||||
25
ChangeLog
25
ChangeLog
@@ -1,7 +1,30 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.9.5 (released 2020-XX-XX)
|
||||
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)
|
||||
|
||||
@@ -101,53 +101,53 @@ if (OPENSSL_FOUND)
|
||||
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
|
||||
|
||||
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)
|
||||
|
||||
if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND
|
||||
@@ -156,7 +156,7 @@ if (OPENSSL_FOUND)
|
||||
endif()
|
||||
|
||||
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)
|
||||
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
|
||||
@@ -302,12 +302,13 @@ function(get_file_list _TARGET_NAME)
|
||||
add_custom_target(
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOUTPUT_PATH="${_get_files_list_OUTPUT_PATH}"
|
||||
-DDIRECTORIES="${_get_files_list_DIRECTORIES}"
|
||||
-DFILES_PATTERNS="${_get_files_list_FILES_PATTERNS}"
|
||||
-DOUTPUT_PATH=${_get_files_list_OUTPUT_PATH}
|
||||
-DDIRECTORIES=${_get_files_list_DIRECTORIES}
|
||||
-DFILES_PATTERNS=${_get_files_list_FILES_PATTERNS}
|
||||
-P ${_GET_FILES_LIST_SCRIPT}
|
||||
COMMENT
|
||||
"Searching for files"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
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}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
@@ -369,12 +371,13 @@ function(extract_symbols _TARGET_NAME)
|
||||
add_custom_target(
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOUTPUT_PATH="${_SYMBOLS_OUTPUT_PATH}"
|
||||
-DHEADERS_LIST_FILE="${_HEADERS_LIST_FILE}"
|
||||
-DOUTPUT_PATH=${_SYMBOLS_OUTPUT_PATH}
|
||||
-DHEADERS_LIST_FILE=${_HEADERS_LIST_FILE}
|
||||
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
|
||||
-P ${_EXTRACT_SYMBOLS_SCRIPT}
|
||||
DEPENDS ${_extract_symbols_HEADERS_LIST}
|
||||
COMMENT "Extracting symbols from headers"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
if (DEFINED _extract_symbols_COPY_TO)
|
||||
@@ -385,6 +388,7 @@ function(extract_symbols _TARGET_NAME)
|
||||
${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
@@ -449,35 +453,37 @@ function(generate_map_file _TARGET_NAME)
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE}
|
||||
-DSYMBOLS="${_SYMBOLS_FILE}"
|
||||
-DSYMBOLS=${_SYMBOLS_FILE}
|
||||
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
|
||||
-DOUTPUT_PATH="${_MAP_OUTPUT_PATH}"
|
||||
-DOUTPUT_PATH=${_MAP_OUTPUT_PATH}
|
||||
-DFINAL=${_generate_map_file_FINAL}
|
||||
-DBREAK_ABI=${_generate_map_file_BREAK_ABI}
|
||||
-DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION}
|
||||
-P ${_GENERATE_MAP_SCRIPT}
|
||||
DEPENDS ${_generate_map_file_SYMBOLS}
|
||||
COMMENT "Generating the map ${_TARGET_NAME}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Add a custom command setting the map as OUTPUT to allow it to be added as
|
||||
# a generated source
|
||||
add_custom_command(
|
||||
OUTPUT ${_MAP_OUTPUT_PATH}
|
||||
DEPENDS ${_TARGET_NAME}
|
||||
DEPENDS ${_TARGET_NAME}_copy
|
||||
)
|
||||
|
||||
if (DEFINED _generate_map_file_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
|
||||
${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH}
|
||||
${_generate_map_file_COPY_TO}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
add_custom_target(${_TARGET_NAME}_copy ALL
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -233,7 +233,7 @@ static int open_location(struct location *loc, int flag) {
|
||||
loc->file = fopen(loc->path, flag == READ ? "r":"w");
|
||||
if (!loc->file) {
|
||||
if (errno == EISDIR) {
|
||||
if (chdir(loc->path)) {
|
||||
if (loc->path != NULL && chdir(loc->path)) {
|
||||
fprintf(stderr,
|
||||
"Error changing directory to %s: %s\n",
|
||||
loc->path, strerror(errno));
|
||||
|
||||
@@ -88,7 +88,11 @@ cleanup_push(struct cleanup_node_struct** head_ref,
|
||||
// Allocate memory for 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
|
||||
new_node->data = new_data;
|
||||
@@ -514,6 +518,12 @@ message_callback(UNUSED_PARAM(ssh_session session),
|
||||
pFd = malloc(sizeof *pFd);
|
||||
cb_chan = malloc(sizeof *cb_chan);
|
||||
event_fd_data = malloc(sizeof *event_fd_data);
|
||||
if (pFd == NULL || cb_chan == NULL || event_fd_data == NULL) {
|
||||
SAFE_FREE(pFd);
|
||||
SAFE_FREE(cb_chan);
|
||||
SAFE_FREE(event_fd_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*pFd) = socket_fd;
|
||||
event_fd_data->channel = channel;
|
||||
|
||||
@@ -233,9 +233,10 @@ void set_pcap(ssh_session session){
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
void cleanup_pcap(void)
|
||||
{
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
pcap = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -126,8 +126,9 @@ struct ssh_crypto_struct {
|
||||
ssh_curve25519_pubkey curve25519_server_pubkey;
|
||||
#endif
|
||||
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;
|
||||
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 *encryptIV;
|
||||
unsigned char *decryptIV;
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
|
||||
|
||||
|
||||
int ssh_client_curve25519_init(ssh_session session);
|
||||
void ssh_client_curve25519_remove_callbacks(ssh_session session);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
void ssh_server_curve25519_init(ssh_session session);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define SRC_DH_GEX_H_
|
||||
|
||||
int ssh_client_dhgex_init(ssh_session session);
|
||||
void ssh_client_dhgex_remove_callbacks(ssh_session session);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
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);
|
||||
int ssh_dh_get_next_server_publickey_blob(ssh_session session,
|
||||
ssh_string *pubkey_blob);
|
||||
int dh_handshake(ssh_session session);
|
||||
|
||||
int ssh_client_dh_init(ssh_session session);
|
||||
void ssh_client_dh_remove_callbacks(ssh_session session);
|
||||
#ifdef WITH_SERVER
|
||||
void ssh_server_dh_init(ssh_session session);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks;
|
||||
/* Backend-specific functions. */
|
||||
int ssh_client_ecdh_init(ssh_session session);
|
||||
void ssh_client_ecdh_remove_callbacks(ssh_session session);
|
||||
int ecdh_build_k(ssh_session session);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
|
||||
@@ -33,7 +33,7 @@ struct ssh_kex_struct {
|
||||
|
||||
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);
|
||||
int ssh_set_client_kex(ssh_session session);
|
||||
int ssh_kex_select_methods(ssh_session session);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
||||
@@ -80,7 +80,7 @@ int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *sourc
|
||||
size_t start, size_t encrypted_size);
|
||||
unsigned char *ssh_packet_encrypt(ssh_session session,
|
||||
void *packet,
|
||||
unsigned int len);
|
||||
uint32_t len);
|
||||
int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len,
|
||||
unsigned char *mac, enum ssh_hmac_e type);
|
||||
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 ssh_signature_new(void);
|
||||
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,
|
||||
ssh_string *sign_blob);
|
||||
|
||||
@@ -75,6 +75,11 @@ enum ssh_pending_call_e {
|
||||
/* Client successfully authenticated */
|
||||
#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
|
||||
|
||||
/* codes to use with ssh_handle_packets*() */
|
||||
/* Infinite timeout */
|
||||
#define SSH_TIMEOUT_INFINITE -1
|
||||
@@ -131,10 +136,8 @@ struct ssh_session_struct {
|
||||
/* Extensions negotiated using RFC 8308 */
|
||||
uint32_t extensions;
|
||||
|
||||
ssh_string banner; /* that's the issue banner from
|
||||
the server */
|
||||
char *discon_msg; /* disconnect message from
|
||||
the remote host */
|
||||
ssh_string banner; /* that's the issue banner from the server */
|
||||
char *discon_msg; /* disconnect message from the remote host */
|
||||
ssh_buffer in_buffer;
|
||||
PACKET in_packet;
|
||||
ssh_buffer out_buffer;
|
||||
@@ -158,25 +161,33 @@ struct ssh_session_struct {
|
||||
uint32_t current_method;
|
||||
} 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
|
||||
* the received SSH_MSG_KEXINIT, but the guess was wrong, this
|
||||
* field will be set such that the following guessed packet will
|
||||
* be ignored. Once that packet has been received and ignored,
|
||||
* this field is cleared.
|
||||
* be ignored on the receiving side. Once that packet has been received and
|
||||
* 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 out_hashbuf;
|
||||
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 */
|
||||
int maxchannel;
|
||||
ssh_agent agent; /* ssh agent */
|
||||
|
||||
/* keyb interactive data */
|
||||
/* keyboard interactive data */
|
||||
struct ssh_kbdint_struct *kbdint;
|
||||
struct ssh_gssapi_struct *gssapi;
|
||||
|
||||
@@ -193,7 +204,8 @@ struct ssh_session_struct {
|
||||
|
||||
/* auths accepted by server */
|
||||
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;
|
||||
ssh_server_callbacks server_callbacks;
|
||||
void (*ssh_connection_callback)( struct ssh_session_struct *session);
|
||||
@@ -219,7 +231,7 @@ struct ssh_session_struct {
|
||||
char *custombanner;
|
||||
unsigned long timeout; /* seconds */
|
||||
unsigned long timeout_usec;
|
||||
unsigned int port;
|
||||
uint16_t port;
|
||||
socket_t fd;
|
||||
int StrictHostKeyChecking;
|
||||
char compressionlevel;
|
||||
|
||||
@@ -1 +1 @@
|
||||
4.8.6
|
||||
4.8.8
|
||||
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
|
||||
@@ -16,7 +16,7 @@ if (WIN32)
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
if (OPENSSL_CRYPTO_LIBRARY)
|
||||
if (OPENSSL_CRYPTO_LIBRARIES)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
@@ -24,9 +24,9 @@ if (OPENSSL_CRYPTO_LIBRARY)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
${OPENSSL_CRYPTO_LIBRARY}
|
||||
${OPENSSL_CRYPTO_LIBRARIES}
|
||||
)
|
||||
endif (OPENSSL_CRYPTO_LIBRARY)
|
||||
endif (OPENSSL_CRYPTO_LIBRARIES)
|
||||
|
||||
if (MBEDTLS_CRYPTO_LIBRARY)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
@@ -331,7 +331,7 @@ target_link_libraries(ssh
|
||||
PRIVATE ${LIBSSH_LINK_LIBRARIES})
|
||||
|
||||
if (WIN32 AND NOT BUILD_SHARED_LIBS)
|
||||
set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-DLIBSSH_STATIC")
|
||||
target_compile_definitions(ssh PUBLIC "LIBSSH_STATIC")
|
||||
endif ()
|
||||
|
||||
add_library(ssh::ssh ALIAS ssh)
|
||||
@@ -342,9 +342,7 @@ if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
set(MAP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_dev.map")
|
||||
endif (ABIMAP_FOUND)
|
||||
|
||||
set_target_properties(ssh
|
||||
PROPERTIES LINK_FLAGS
|
||||
"-Wl,--version-script,\"${MAP_PATH}\"")
|
||||
target_link_libraries(ssh PRIVATE "-Wl,--version-script,\"${MAP_PATH}\"")
|
||||
endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
|
||||
set_target_properties(ssh
|
||||
@@ -358,12 +356,12 @@ set_target_properties(ssh
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
if (MINGW)
|
||||
set_target_properties(ssh PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup")
|
||||
set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-D_POSIX_SOURCE")
|
||||
target_link_libraries(ssh PRIVATE "-Wl,--enable-stdcall-fixup")
|
||||
target_compile_definitions(ssh PRIVATE "_POSIX_SOURCE")
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -412,12 +410,7 @@ if (BUILD_STATIC_LIB)
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
set_target_properties(
|
||||
ssh-static
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-DLIBSSH_STATIC"
|
||||
)
|
||||
target_compile_definitions(ssh-static PUBLIC "LIBSSH_STATIC")
|
||||
endif (WIN32)
|
||||
endif (BUILD_STATIC_LIB)
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif /* HAVE_SYS_TIME_H */
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
@@ -117,6 +120,13 @@ ssh_channel ssh_channel_new(ssh_session session)
|
||||
|
||||
if (session->channels == NULL) {
|
||||
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);
|
||||
|
||||
158
src/client.c
158
src/client.c
@@ -243,10 +243,13 @@ end:
|
||||
* @warning this function returning is no proof that DH handshake is
|
||||
* completed
|
||||
*/
|
||||
static int dh_handshake(ssh_session session) {
|
||||
|
||||
int dh_handshake(ssh_session session)
|
||||
{
|
||||
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) {
|
||||
case DH_STATE_INIT:
|
||||
switch(session->next_crypto->kex_type){
|
||||
@@ -386,95 +389,101 @@ static void ssh_client_connection_callback(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch(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);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "session_state=%d", session->session_state);
|
||||
|
||||
break;
|
||||
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
||||
if (session->serverbanner == NULL) {
|
||||
goto error;
|
||||
}
|
||||
set_status(session, 0.4f);
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"SSH server banner: %s", session->serverbanner);
|
||||
switch (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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
break;
|
||||
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
||||
if (session->serverbanner == NULL) {
|
||||
goto error;
|
||||
}
|
||||
set_status(session, 0.4f);
|
||||
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);
|
||||
session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
|
||||
ssh_packet_register_socket_callback(session, session->socket);
|
||||
|
||||
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);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_send_kex(session, 0);
|
||||
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->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:
|
||||
}
|
||||
if (ssh_kex_select_methods(session) == SSH_ERROR)
|
||||
goto error;
|
||||
default:
|
||||
ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
|
||||
set_status(session, 0.8f);
|
||||
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;
|
||||
error:
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive = 0;
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
|
||||
}
|
||||
|
||||
@@ -721,6 +730,7 @@ error:
|
||||
}
|
||||
session->opts.fd = SSH_INVALID_SOCKET;
|
||||
session->session_state=SSH_SESSION_STATE_DISCONNECTED;
|
||||
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
||||
|
||||
while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
|
||||
ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
|
||||
@@ -770,7 +780,7 @@ error:
|
||||
}
|
||||
|
||||
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 "
|
||||
"and libssh contributors. "
|
||||
"Distributed under the LGPL, please refer to COPYING "
|
||||
|
||||
@@ -425,6 +425,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
opcode != SOC_HOST &&
|
||||
opcode != SOC_MATCH &&
|
||||
opcode != SOC_INCLUDE &&
|
||||
opcode != SOC_IDENTITY &&
|
||||
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
|
||||
/* Skip all the options that were already applied */
|
||||
if (seen[opcode] != 0) {
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif /* HAVE_SYS_TIME_H */
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
@@ -172,6 +172,11 @@ int ssh_client_curve25519_init(ssh_session session)
|
||||
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)
|
||||
{
|
||||
ssh_curve25519_pubkey k;
|
||||
@@ -285,7 +290,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
|
||||
(void)type;
|
||||
(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);
|
||||
if (pubkey_blob == NULL) {
|
||||
@@ -377,12 +382,12 @@ void ssh_server_curve25519_init(ssh_session session){
|
||||
*/
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
/* ECDH keys */
|
||||
ssh_string q_c_string;
|
||||
ssh_string q_s_string;
|
||||
ssh_string q_c_string = NULL;
|
||||
ssh_string q_s_string = NULL;
|
||||
ssh_string server_pubkey_blob = NULL;
|
||||
|
||||
/* SSH host keys (rsa,dsa,ecdsa) */
|
||||
ssh_key privkey;
|
||||
ssh_key privkey = NULL;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
int rc;
|
||||
@@ -402,7 +407,6 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
SSH_FATAL,
|
||||
"Incorrect size for server Curve25519 public key: %zu",
|
||||
ssh_string_len(q_c_string));
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -460,12 +464,17 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
/* add ecdh public key */
|
||||
q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
|
||||
if (q_s_string == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_string_fill(q_s_string,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
rc = ssh_string_fill(q_s_string,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
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);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
@@ -508,6 +517,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
error:
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
10
src/dh-gex.c
10
src/dh-gex.c
@@ -238,6 +238,11 @@ error:
|
||||
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)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto=session->next_crypto;
|
||||
@@ -248,7 +253,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
||||
(void)user;
|
||||
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,
|
||||
"SBS",
|
||||
&pubkey_blob, &server_pubkey,
|
||||
@@ -263,6 +268,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
||||
bignum_safe_free(server_pubkey);
|
||||
goto error;
|
||||
}
|
||||
/* The ownership was passed to the crypto structure */
|
||||
server_pubkey = NULL;
|
||||
|
||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
@@ -293,6 +300,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
error:
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
ssh_dh_cleanup(session->next_crypto);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
|
||||
|
||||
8
src/dh.c
8
src/dh.c
@@ -342,6 +342,11 @@ 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){
|
||||
struct ssh_crypto_struct *crypto=session->next_crypto;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
@@ -351,7 +356,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
||||
(void)type;
|
||||
(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,
|
||||
&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,
|
||||
NULL, server_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
bignum_safe_free(server_pubkey);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,11 @@ struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks = {
|
||||
.user = NULL
|
||||
};
|
||||
|
||||
void ssh_client_ecdh_remove_callbacks(ssh_session session)
|
||||
{
|
||||
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
|
||||
* a SSH_MSG_NEWKEYS
|
||||
@@ -55,7 +60,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){
|
||||
(void)type;
|
||||
(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);
|
||||
if (pubkey_blob == NULL) {
|
||||
ssh_set_error(session,SSH_FATAL, "No public key in packet");
|
||||
|
||||
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,
|
||||
unsigned char *sk)
|
||||
int crypto_sign_ed25519_keypair(ed25519_pubkey pk,
|
||||
ed25519_privkey sk)
|
||||
{
|
||||
sc25519 scsk;
|
||||
ge25519 gepk;
|
||||
@@ -114,7 +114,7 @@ int crypto_sign_ed25519(unsigned char *sm,
|
||||
uint64_t *smlen,
|
||||
const unsigned char *m,
|
||||
uint64_t mlen,
|
||||
const unsigned char *sk)
|
||||
const ed25519_privkey sk)
|
||||
{
|
||||
sc25519 sck, scs, scsk;
|
||||
ge25519 ger;
|
||||
@@ -177,7 +177,7 @@ int crypto_sign_ed25519_open(unsigned char *m,
|
||||
uint64_t *mlen,
|
||||
const unsigned char *sm,
|
||||
uint64_t smlen,
|
||||
const unsigned char *pk)
|
||||
const ed25519_pubkey pk)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
@@ -255,7 +255,11 @@ int ssh_getpass(const char *prompt,
|
||||
|
||||
/* disable nonblocking I/O */
|
||||
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);
|
||||
@@ -267,7 +271,11 @@ int ssh_getpass(const char *prompt,
|
||||
|
||||
/* close fd */
|
||||
if (fd & O_NDELAY) {
|
||||
fcntl(0, F_SETFL, fd);
|
||||
ok = fcntl(0, F_SETFL, fd);
|
||||
if (ok < 0) {
|
||||
perror("fcntl");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
gss_release_oid_set(&min_stat, &both_supported);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -259,8 +260,10 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
return SSH_OK;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
name_buf.value = service_name;
|
||||
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",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
gss_release_oid_set(&min_stat, &both_supported);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -338,6 +342,7 @@ static char *ssh_gssapi_name_to_char(gss_name_t name){
|
||||
min_stat);
|
||||
ptr = malloc(buffer.length + 1);
|
||||
if (ptr == NULL) {
|
||||
gss_release_buffer(&min_stat, &buffer);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(ptr, buffer.value, buffer.length);
|
||||
@@ -421,6 +426,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
||||
"Gssapi error",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
gss_release_buffer(&min_stat, &output_token);
|
||||
ssh_auth_reply_default(session,0);
|
||||
ssh_gssapi_free(session);
|
||||
session->gssapi=NULL;
|
||||
@@ -438,6 +444,9 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
||||
(size_t)output_token.length, output_token.value);
|
||||
ssh_packet_send(session);
|
||||
}
|
||||
|
||||
gss_release_buffer(&min_stat, &output_token);
|
||||
|
||||
if(maj_stat == GSS_S_COMPLETE){
|
||||
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,
|
||||
"dPbsss",
|
||||
crypto->digest_len,
|
||||
(size_t)crypto->digest_len, crypto->session_id,
|
||||
crypto->session_id_len,
|
||||
crypto->session_id_len, crypto->session_id,
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
session->gssapi->user,
|
||||
"ssh-connection",
|
||||
@@ -638,7 +647,7 @@ fail:
|
||||
static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
|
||||
{
|
||||
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_name_t client_id = GSS_C_NO_NAME;
|
||||
gss_OID oid;
|
||||
@@ -700,6 +709,7 @@ static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
|
||||
ret = SSH_OK;
|
||||
|
||||
end:
|
||||
gss_release_oid_set(&min_stat, &actual_mechs);
|
||||
gss_release_name(&min_stat, &client_id);
|
||||
return ret;
|
||||
}
|
||||
@@ -713,7 +723,7 @@ end:
|
||||
*/
|
||||
int ssh_gssapi_auth_mic(ssh_session session){
|
||||
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;
|
||||
int rc;
|
||||
size_t n_oids = 0;
|
||||
@@ -790,6 +800,8 @@ out:
|
||||
SSH_STRING_FREE(oids[i]);
|
||||
}
|
||||
free(oids);
|
||||
gss_release_oid_set(&min_stat, &selected);
|
||||
|
||||
if (rc != SSH_ERROR) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
}
|
||||
@@ -893,6 +905,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){
|
||||
ssh_packet_send(session);
|
||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN;
|
||||
}
|
||||
|
||||
gss_release_buffer(&min_stat, &output_token);
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
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,
|
||||
&mic_buf, &mic_token_buf);
|
||||
|
||||
SSH_BUFFER_FREE(mic_buffer);
|
||||
|
||||
if (GSS_ERROR(maj_stat)){
|
||||
SSH_BUFFER_FREE(mic_buffer);
|
||||
ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
|
||||
ssh_gssapi_log_error(SSH_LOG_DEBUG,
|
||||
"generating MIC",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
@@ -935,8 +951,10 @@ static int ssh_gssapi_send_mic(ssh_session session){
|
||||
SSH2_MSG_USERAUTH_GSSAPI_MIC,
|
||||
mic_token_buf.length,
|
||||
(size_t)mic_token_buf.length, mic_token_buf.value);
|
||||
|
||||
gss_release_buffer(&min_stat, &mic_token_buf);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
SSH_BUFFER_FREE(mic_buffer);
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -1005,6 +1023,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
||||
ssh_packet_send(session);
|
||||
}
|
||||
|
||||
gss_release_buffer(&min_stat, &output_token);
|
||||
|
||||
if (maj_stat == GSS_S_COMPLETE) {
|
||||
ssh_gssapi_send_mic(session);
|
||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT;
|
||||
|
||||
@@ -269,7 +269,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
||||
*
|
||||
* @see ssh_init()
|
||||
*/
|
||||
bool is_ssh_initialized() {
|
||||
bool is_ssh_initialized(void) {
|
||||
|
||||
bool is_initialized = false;
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
||||
ssh_mac_update(ctx, key, key_len);
|
||||
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||
ssh_mac_update(ctx, &letter, 1);
|
||||
ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
|
||||
ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len);
|
||||
ssh_mac_final(digest, ctx);
|
||||
|
||||
if (requested_len < output_len) {
|
||||
|
||||
504
src/kex.c
504
src/kex.c
@@ -28,6 +28,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/dh.h"
|
||||
@@ -305,6 +306,10 @@ static int cmp_first_kex_algo(const char *client_str,
|
||||
|
||||
int is_wrong = 1;
|
||||
|
||||
if (client_str == NULL || server_str == NULL) {
|
||||
return is_wrong;
|
||||
}
|
||||
|
||||
colon = strchr(client_str, ',');
|
||||
if (colon == NULL) {
|
||||
client_kex_len = strlen(client_str);
|
||||
@@ -331,6 +336,7 @@ static int cmp_first_kex_algo(const char *client_str,
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
{
|
||||
int i, ok;
|
||||
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||
int server_kex = session->server;
|
||||
ssh_string str = NULL;
|
||||
char *strings[SSH_KEX_METHODS] = {0};
|
||||
@@ -344,35 +350,67 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "KEXINIT received");
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
ok = ssh_hashbufin_add_cookie(session, session->next_crypto->client_kex.cookie);
|
||||
ok = ssh_hashbufin_add_cookie(session, crypto->client_kex.cookie);
|
||||
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 = server_set_kex(session);
|
||||
if (ok == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
} 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) {
|
||||
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;
|
||||
}
|
||||
|
||||
ok = ssh_hashbufin_add_cookie(session, session->next_crypto->server_kex.cookie);
|
||||
ok = ssh_hashbufin_add_cookie(session, crypto->server_kex.cookie);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -385,7 +423,8 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->in_hashbuf, str);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -398,14 +437,14 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
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) {
|
||||
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 */
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
session->next_crypto->server_kex.methods[i] = strings[i];
|
||||
crypto->server_kex.methods[i] = strings[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,30 +458,48 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
* that its value is included when computing the session ID (see
|
||||
* '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");
|
||||
}
|
||||
|
||||
if (server_kex) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* If client sent a ext-info-c message in the kex list, it supports
|
||||
* 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);
|
||||
if (ok) {
|
||||
const char *hostkeys = NULL;
|
||||
const char *hostkeys = NULL, *wanted_hostkeys = NULL;
|
||||
|
||||
/* The client supports extension negotiation */
|
||||
session->extensions |= SSH_EXT_NEGOTIATION;
|
||||
@@ -452,14 +509,14 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
* by the client and enable the respective extensions to provide
|
||||
* 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");
|
||||
if (ok) {
|
||||
/* Check if rsa-sha2-512 is allowed by config */
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) {
|
||||
char *is_allowed =
|
||||
ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS],
|
||||
"rsa-sha2-512");
|
||||
if (wanted_hostkeys != NULL) {
|
||||
char *is_allowed = ssh_find_matching(wanted_hostkeys,
|
||||
"rsa-sha2-512");
|
||||
if (is_allowed != NULL) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA512;
|
||||
}
|
||||
@@ -469,10 +526,9 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
ok = ssh_match_group(hostkeys, "rsa-sha2-256");
|
||||
if (ok) {
|
||||
/* Check if rsa-sha2-256 is allowed by config */
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) {
|
||||
char *is_allowed =
|
||||
ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS],
|
||||
"rsa-sha2-256");
|
||||
if (wanted_hostkeys != NULL) {
|
||||
char *is_allowed = ssh_find_matching(wanted_hostkeys,
|
||||
"rsa-sha2-256");
|
||||
if (is_allowed != NULL) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
|
||||
}
|
||||
@@ -488,7 +544,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
(session->extensions & 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",
|
||||
session->next_crypto->client_kex.methods[SSH_HOSTKEYS]);
|
||||
hostkeys);
|
||||
if (rsa_sig_ext == NULL) {
|
||||
goto error; /* should never happen */
|
||||
} else if (strcmp(rsa_sig_ext, "rsa-sha2-512") == 0) {
|
||||
@@ -507,24 +563,16 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "",
|
||||
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 */
|
||||
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);
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
@@ -672,14 +720,18 @@ int ssh_set_client_kex(ssh_session session)
|
||||
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);
|
||||
if (!ok) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG 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
|
||||
* been set yet. */
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
@@ -735,13 +787,103 @@ int ssh_set_client_kex(ssh_session session)
|
||||
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
|
||||
* server's kex messages, and watches out if a match is possible.
|
||||
*/
|
||||
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;
|
||||
int ssh_kex_select_methods (ssh_session session)
|
||||
{
|
||||
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;
|
||||
const char *aead_hmac = NULL;
|
||||
enum ssh_key_exchange_e kex_type;
|
||||
int i;
|
||||
|
||||
/* Here we should drop the ext-info-c from the list so we avoid matching.
|
||||
@@ -752,43 +894,40 @@ int ssh_kex_select_methods (ssh_session session){
|
||||
}
|
||||
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]);
|
||||
if(session->next_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]);
|
||||
crypto->kex_methods[i] = ssh_find_matching(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;
|
||||
} 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 */
|
||||
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;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha256") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA256;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512;
|
||||
#ifdef WITH_GEX
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha1") == 0){
|
||||
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;
|
||||
|
||||
/* We can not set this value directly as the old value is needed to revert
|
||||
* callbacks if we are client */
|
||||
kex_type = kex_select_kex_type(crypto->kex_methods[SSH_KEX]);
|
||||
if (session->client && session->first_kex_follows_guess_wrong) {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Our guess was wrong. Restarting the KEX");
|
||||
/* We need to remove the wrong callbacks and start kex again */
|
||||
revert_kex_callbacks(session);
|
||||
session->dh_handshake_state = DH_STATE_INIT;
|
||||
session->first_kex_follows_guess_wrong = false;
|
||||
}
|
||||
crypto->kex_type = kex_type;
|
||||
|
||||
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_HOSTKEYS],
|
||||
@@ -806,62 +945,116 @@ int ssh_kex_select_methods (ssh_session session){
|
||||
|
||||
|
||||
/* this function only sends the predefined set of kex methods */
|
||||
int ssh_send_kex(ssh_session session, int server_kex) {
|
||||
struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex :
|
||||
&session->next_crypto->client_kex);
|
||||
ssh_string str = NULL;
|
||||
int i;
|
||||
int rc;
|
||||
int ssh_send_kex(ssh_session session)
|
||||
{
|
||||
struct ssh_kex_struct *kex = (session->server ?
|
||||
&session->next_crypto->server_kex :
|
||||
&session->next_crypto->client_kex);
|
||||
ssh_string str = NULL;
|
||||
int i;
|
||||
int rc;
|
||||
int first_kex_packet_follows = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
/* Only client can initiate the handshake methods we implement. If we
|
||||
* already received the peer mechanisms, there is no point in guessing */
|
||||
if (session->client &&
|
||||
session->session_state != SSH_SESSION_STATE_KEXINIT_RECEIVED &&
|
||||
session->send_first_kex_follows) {
|
||||
first_kex_packet_follows = 1;
|
||||
}
|
||||
|
||||
if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) {
|
||||
goto error;
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"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,
|
||||
"bd",
|
||||
0,
|
||||
0);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bd",
|
||||
first_kex_packet_follows,
|
||||
0);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
/* Prepare also the first_kex_packet_follows and reserved to 0 */
|
||||
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:
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
ssh_buffer_reinit(session->out_hashbuf);
|
||||
SSH_STRING_FREE(str);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
ssh_buffer_reinit(session->out_hashbuf);
|
||||
SSH_STRING_FREE(str);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -904,7 +1097,7 @@ int ssh_send_rekex(ssh_session session)
|
||||
}
|
||||
|
||||
session->dh_handshake_state = DH_STATE_INIT;
|
||||
rc = ssh_send_kex(session, session->server);
|
||||
rc = ssh_send_kex(session);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to send kex");
|
||||
return rc;
|
||||
@@ -981,33 +1174,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
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);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
@@ -1023,7 +1189,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
ssh_buffer_get(server_hash),
|
||||
server_pubkey_blob);
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
if(rc != SSH_OK){
|
||||
if (rc != SSH_OK){
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1197,11 +1363,13 @@ int ssh_make_sessionid(ssh_session session)
|
||||
}
|
||||
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
||||
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
|
||||
printf("Session hash: \n");
|
||||
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
|
||||
|
||||
rc = SSH_OK;
|
||||
|
||||
@@ -372,6 +372,7 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
||||
|
||||
list = ssh_list_new();
|
||||
if (list == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(host_port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||
goto out;
|
||||
}
|
||||
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) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -687,7 +687,7 @@ static void cipher_encrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len)
|
||||
size_t len)
|
||||
{
|
||||
size_t outlen = 0;
|
||||
int rc = 0;
|
||||
@@ -745,7 +745,7 @@ static void cipher_decrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len)
|
||||
size_t len)
|
||||
{
|
||||
size_t outlen = 0;
|
||||
int rc = 0;
|
||||
|
||||
@@ -513,24 +513,30 @@ static int ssh_message_termination(void *s){
|
||||
* @warning This function blocks until a message has been received. Betterset up
|
||||
* a callback if this behavior is unwanted.
|
||||
*/
|
||||
ssh_message ssh_message_get(ssh_session session) {
|
||||
ssh_message msg = NULL;
|
||||
int rc;
|
||||
ssh_message ssh_message_get(ssh_session session)
|
||||
{
|
||||
ssh_message msg = NULL;
|
||||
int rc;
|
||||
|
||||
msg=ssh_message_pop_head(session);
|
||||
if(msg) {
|
||||
return msg;
|
||||
}
|
||||
if(session->ssh_message_list == NULL) {
|
||||
session->ssh_message_list = ssh_list_new();
|
||||
}
|
||||
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);
|
||||
msg = ssh_message_pop_head(session);
|
||||
if (msg != NULL) {
|
||||
return msg;
|
||||
}
|
||||
if (session->ssh_message_list == NULL) {
|
||||
session->ssh_message_list = ssh_list_new();
|
||||
if (session->ssh_message_list == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -708,8 +714,8 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"dPbsssbsS",
|
||||
crypto->digest_len, /* session ID string */
|
||||
(size_t)crypto->digest_len, crypto->session_id,
|
||||
crypto->session_id_len, /* session ID string */
|
||||
crypto->session_id_len, crypto->session_id,
|
||||
SSH2_MSG_USERAUTH_REQUEST, /* type */
|
||||
msg->auth_request.username,
|
||||
service,
|
||||
|
||||
13
src/misc.c
13
src/misc.c
@@ -1164,14 +1164,13 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
|
||||
x = strdup(session->opts.username);
|
||||
break;
|
||||
case 'p':
|
||||
if (session->opts.port < 65536) {
|
||||
char tmp[6];
|
||||
{
|
||||
char tmp[6];
|
||||
|
||||
snprintf(tmp,
|
||||
sizeof(tmp),
|
||||
"%u",
|
||||
session->opts.port > 0 ? session->opts.port : 22);
|
||||
x = strdup(tmp);
|
||||
snprintf(tmp, sizeof(tmp), "%hu",
|
||||
(uint16_t)(session->opts.port > 0 ? session->opts.port
|
||||
: 22));
|
||||
x = strdup(tmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
99
src/packet.c
99
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
|
||||
* */
|
||||
|
||||
if (!session->server) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
@@ -688,10 +693,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* 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) {
|
||||
@@ -699,21 +706,18 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_REQUEST_FAILURE: // 82
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* 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) {
|
||||
@@ -721,11 +725,6 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
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:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* 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) {
|
||||
@@ -895,10 +896,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* 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) {
|
||||
@@ -1412,31 +1415,41 @@ static void ssh_packet_socket_controlflow_callback(int code, void *userdata)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
session->socket_callbacks.controlflow = ssh_packet_socket_controlflow_callback;
|
||||
session->socket_callbacks.userdata=session;
|
||||
ssh_socket_set_callbacks(s,&session->socket_callbacks);
|
||||
void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s)
|
||||
{
|
||||
struct ssh_socket_callbacks_struct *callbacks = &session->socket_callbacks;
|
||||
|
||||
callbacks->data = ssh_packet_socket_callback;
|
||||
callbacks->connected = NULL;
|
||||
callbacks->controlflow = ssh_packet_socket_controlflow_callback;
|
||||
callbacks->userdata = session;
|
||||
ssh_socket_set_callbacks(s, callbacks);
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief sets the callbacks for the packet layer
|
||||
*/
|
||||
void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks){
|
||||
if(session->packet_callbacks == NULL){
|
||||
session->packet_callbacks = ssh_list_new();
|
||||
}
|
||||
if (session->packet_callbacks != NULL) {
|
||||
void
|
||||
ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @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;
|
||||
|
||||
it = ssh_list_find(session->packet_callbacks, callbacks);
|
||||
if (it != NULL) {
|
||||
ssh_list_remove(session->packet_callbacks, it);
|
||||
@@ -1446,12 +1459,15 @@ void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callb
|
||||
/** @internal
|
||||
* @brief sets the default packet handlers
|
||||
*/
|
||||
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);
|
||||
session->default_packet_callbacks.user=session;
|
||||
session->default_packet_callbacks.callbacks=default_packet_handlers;
|
||||
ssh_packet_set_callbacks(session, &session->default_packet_callbacks);
|
||||
void ssh_packet_set_default_callbacks(ssh_session session)
|
||||
{
|
||||
struct ssh_packet_callbacks_struct *c = &session->default_packet_callbacks;
|
||||
|
||||
c->start = 1;
|
||||
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
|
||||
@@ -1899,7 +1915,7 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
|
||||
/* Both sides switched: do the actual switch now */
|
||||
if (session->next_crypto->used == SSH_DIRECTION_BOTH) {
|
||||
size_t digest_len;
|
||||
size_t session_id_len;
|
||||
|
||||
if (session->current_crypto != NULL) {
|
||||
crypto_free(session->current_crypto);
|
||||
@@ -1916,8 +1932,8 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
digest_len = session->current_crypto->digest_len;
|
||||
session->next_crypto->session_id = malloc(digest_len);
|
||||
session_id_len = session->current_crypto->session_id_len;
|
||||
session->next_crypto->session_id = malloc(session_id_len);
|
||||
if (session->next_crypto->session_id == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
@@ -1925,7 +1941,8 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
|
||||
memcpy(session->next_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;
|
||||
}
|
||||
|
||||
@@ -129,6 +129,8 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
}
|
||||
|
||||
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) {
|
||||
goto error;
|
||||
}
|
||||
@@ -152,10 +154,11 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
server_key,
|
||||
session->next_crypto->secret_hash,
|
||||
session->next_crypto->digest_len);
|
||||
ssh_string_burn(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
ssh_signature_free(sig);
|
||||
SSH_SIGNATURE_FREE(sig);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to verify server hostkey signature");
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,"Signature verified and valid");
|
||||
@@ -170,6 +173,9 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
session->ssh_connection_callback(session);
|
||||
return SSH_PACKET_USED;
|
||||
error:
|
||||
SSH_SIGNATURE_FREE(sig);
|
||||
ssh_string_burn(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
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));
|
||||
SSH_STRING_FREE(i);
|
||||
if (nid == -1) {
|
||||
ssh_string_burn(e);
|
||||
SSH_STRING_FREE(e);
|
||||
ssh_string_burn(exp);
|
||||
SSH_STRING_FREE(exp);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -2086,8 +2090,12 @@ int ssh_pki_export_signature_blob(const ssh_signature sig,
|
||||
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);
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(str);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
*sig_blob = str;
|
||||
|
||||
@@ -2328,11 +2336,14 @@ ssh_string ssh_pki_do_sign(ssh_session session,
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
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 */
|
||||
sign_input = ssh_buffer_new();
|
||||
@@ -2389,11 +2400,15 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session,
|
||||
}
|
||||
|
||||
/* prepend session identifier */
|
||||
session_id = ssh_string_new(crypto->digest_len);
|
||||
session_id = ssh_string_new(crypto->session_id_len);
|
||||
if (session_id == 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();
|
||||
if (sig_buf == NULL) {
|
||||
|
||||
@@ -831,7 +831,12 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
|
||||
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);
|
||||
|
||||
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;
|
||||
size_t raw_sig_len;
|
||||
int rc;
|
||||
|
||||
DSA_SIG *dsa_sig;
|
||||
|
||||
@@ -1439,7 +1445,11 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
|
||||
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;
|
||||
|
||||
@@ -1516,7 +1526,10 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig)
|
||||
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(s);
|
||||
@@ -1526,6 +1539,7 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig)
|
||||
return sig_blob;
|
||||
|
||||
error:
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_STRING_FREE(r);
|
||||
SSH_STRING_FREE(s);
|
||||
ECDSA_SIG_free(ecdsa_sig);
|
||||
@@ -1670,7 +1684,11 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
||||
if (r == NULL) {
|
||||
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);
|
||||
ssh_string_burn(r);
|
||||
@@ -1683,7 +1701,11 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
||||
if (s == NULL) {
|
||||
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);
|
||||
ssh_string_burn(s);
|
||||
@@ -2269,8 +2291,12 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
unsigned char *raw_sig_data = NULL;
|
||||
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 evp_rc;
|
||||
int ok;
|
||||
|
||||
if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL ||
|
||||
signature == NULL || (signature->raw_sig == NULL
|
||||
@@ -2285,8 +2311,8 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
}
|
||||
|
||||
/* Check if public key and hash type are compatible */
|
||||
rc = pki_key_check_hash_compatible(pubkey, signature->hash_type);
|
||||
if (rc != SSH_OK) {
|
||||
ok = pki_key_check_hash_compatible(pubkey, signature->hash_type);
|
||||
if (ok != SSH_OK) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -2329,8 +2355,8 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
}
|
||||
|
||||
/* Verify the signature */
|
||||
evp_rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey);
|
||||
if (evp_rc != 1){
|
||||
ok = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey);
|
||||
if (ok != 1){
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"EVP_DigestVerifyInit() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
@@ -2338,35 +2364,31 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
}
|
||||
|
||||
#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
|
||||
evp_rc = EVP_DigestVerifyUpdate(ctx, input, input_len);
|
||||
if (evp_rc != 1) {
|
||||
ok = EVP_DigestVerifyUpdate(ctx, input, input_len);
|
||||
if (ok != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"EVP_DigestVerifyUpdate() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
evp_rc = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len);
|
||||
ok = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len);
|
||||
#endif
|
||||
if (evp_rc == 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Signature valid");
|
||||
rc = SSH_OK;
|
||||
} else {
|
||||
if (ok != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Signature invalid: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "Signature valid");
|
||||
rc = SSH_OK;
|
||||
|
||||
out:
|
||||
if (ctx != NULL) {
|
||||
EVP_MD_CTX_free(ctx);
|
||||
}
|
||||
if (pkey != NULL) {
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 sig_blob;
|
||||
int rc;
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* 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
|
||||
ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig),
|
||||
ssh_string_len(sig->raw_sig));
|
||||
rc = ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig),
|
||||
ssh_string_len(sig->raw_sig));
|
||||
#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
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
@@ -1765,6 +1765,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
gcry_sexp_t sexp;
|
||||
size_t size = 0;
|
||||
ssh_string sig_blob = NULL;
|
||||
int rc;
|
||||
|
||||
switch(sig->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
@@ -1812,7 +1813,11 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
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;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
sexp = gcry_sexp_find_token(sig->rsa_sig, "s", 0);
|
||||
@@ -1829,13 +1834,16 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
if (sig_blob == 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);
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
sig_blob = pki_ed25519_signature_to_blob(sig);
|
||||
break;
|
||||
sig_blob = pki_ed25519_signature_to_blob(sig);
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA_P256:
|
||||
case SSH_KEYTYPE_ECDSA_P384:
|
||||
case SSH_KEYTYPE_ECDSA_P521:
|
||||
@@ -1844,7 +1852,6 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
ssh_string R;
|
||||
ssh_string S;
|
||||
ssh_buffer b;
|
||||
int rc;
|
||||
|
||||
b = ssh_buffer_new();
|
||||
if (b == NULL) {
|
||||
@@ -1885,9 +1892,13 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh_string_fill(sig_blob,
|
||||
rc = ssh_string_fill(sig_blob,
|
||||
ssh_buffer_get(b), ssh_buffer_get_len(b));
|
||||
SSH_BUFFER_FREE(b);
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -832,8 +832,13 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
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);
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
@@ -1074,9 +1079,13 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh_string_fill(sig_blob, sig, slen);
|
||||
ok = ssh_string_fill(sig_blob, sig, slen);
|
||||
explicit_bzero(sig, slen);
|
||||
SAFE_FREE(sig);
|
||||
if (ok < 0) {
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
247
src/server.c
247
src/server.c
@@ -92,7 +92,11 @@ int server_set_kex(ssh_session session)
|
||||
size_t len;
|
||||
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);
|
||||
if (!ok) {
|
||||
@@ -335,117 +339,121 @@ ssh_get_key_params(ssh_session session,
|
||||
* @brief A function to be called each time a step has been done in the
|
||||
* connection.
|
||||
*/
|
||||
static void ssh_server_connection_callback(ssh_session session){
|
||||
static void ssh_server_connection_callback(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch(session->session_state){
|
||||
case SSH_SESSION_STATE_NONE:
|
||||
case SSH_SESSION_STATE_CONNECTING:
|
||||
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
||||
break;
|
||||
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
||||
if (session->clientbanner == NULL) {
|
||||
goto error;
|
||||
}
|
||||
set_status(session, 0.4f);
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"SSH client banner: %s", session->clientbanner);
|
||||
switch (session->session_state) {
|
||||
case SSH_SESSION_STATE_NONE:
|
||||
case SSH_SESSION_STATE_CONNECTING:
|
||||
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
||||
break;
|
||||
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
||||
if (session->clientbanner == NULL) {
|
||||
goto error;
|
||||
}
|
||||
set_status(session, 0.4f);
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"SSH client banner: %s", session->clientbanner);
|
||||
|
||||
/* Here we analyze the different protocols the server allows. */
|
||||
rc = ssh_analyze_banner(session, 1);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"No version of SSH protocol usable (banner: %s)",
|
||||
session->clientbanner);
|
||||
/* Here we analyze the different protocols the server allows. */
|
||||
rc = ssh_analyze_banner(session, 1);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"No version of SSH protocol usable (banner: %s)",
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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, 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
|
||||
* our supported extensions now. This is the first message after
|
||||
* sending NEWKEYS message and after turning on crypto.
|
||||
*/
|
||||
if (session->extensions & SSH_EXT_NEGOTIATION &&
|
||||
session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
|
||||
/*
|
||||
* If the client supports extension negotiation, we will send
|
||||
* our supported extensions now. This is the first message after
|
||||
* sending NEWKEYS message and after turning on crypto.
|
||||
* 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->extensions & SSH_EXT_NEGOTIATION &&
|
||||
session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
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:
|
||||
break;
|
||||
case SSH_SESSION_STATE_ERROR:
|
||||
goto error;
|
||||
default:
|
||||
ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
|
||||
|
||||
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:
|
||||
break;
|
||||
case SSH_SESSION_STATE_ERROR:
|
||||
goto error;
|
||||
default:
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid state %d",
|
||||
session->session_state);
|
||||
}
|
||||
|
||||
return;
|
||||
error:
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive = 0;
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,16 +467,17 @@ error:
|
||||
* @param user is a pointer to session
|
||||
* @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) {
|
||||
char *buffer = (char *) data;
|
||||
ssh_session session = (ssh_session) 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 *str = NULL;
|
||||
size_t i;
|
||||
int ret=0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
#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_DIR_IN,
|
||||
buffer,
|
||||
@@ -477,11 +486,11 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
|
||||
}
|
||||
#endif
|
||||
if (buffer[i] == '\r') {
|
||||
buffer[i]='\0';
|
||||
buffer[i] = '\0';
|
||||
}
|
||||
|
||||
if (buffer[i] == '\n') {
|
||||
buffer[i]='\0';
|
||||
buffer[i] = '\0';
|
||||
|
||||
str = strdup(buffer);
|
||||
/* number of bytes read */
|
||||
@@ -494,10 +503,11 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(i > 127) {
|
||||
if (i > 127) {
|
||||
/* Too big banner */
|
||||
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;
|
||||
}
|
||||
@@ -525,10 +535,14 @@ void ssh_set_auth_methods(ssh_session session, int auth_methods)
|
||||
}
|
||||
|
||||
/* Do the banner and key exchange */
|
||||
int ssh_handle_key_exchange(ssh_session session) {
|
||||
int ssh_handle_key_exchange(ssh_session session)
|
||||
{
|
||||
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);
|
||||
if (rc < 0) {
|
||||
return SSH_ERROR;
|
||||
@@ -539,27 +553,28 @@ int ssh_handle_key_exchange(ssh_session session) {
|
||||
session->ssh_connection_callback = ssh_server_connection_callback;
|
||||
session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
|
||||
session->socket_callbacks.data=callback_receive_banner;
|
||||
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
||||
session->socket_callbacks.userdata=session;
|
||||
session->socket_callbacks.data = callback_receive_banner;
|
||||
session->socket_callbacks.exception = ssh_socket_exception_callback;
|
||||
session->socket_callbacks.userdata = session;
|
||||
|
||||
rc = server_set_kex(session);
|
||||
if (rc < 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
pending:
|
||||
pending:
|
||||
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",
|
||||
session->session_state);
|
||||
if (rc != SSH_OK)
|
||||
return rc;
|
||||
session->session_state);
|
||||
if (rc != SSH_OK) {
|
||||
return rc;
|
||||
}
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||
session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
|
||||
return SSH_ERROR;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/* messages */
|
||||
|
||||
67
src/sftp.c
67
src/sftp.c
@@ -32,6 +32,9 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif /* HAVE_SYS_TIME_H */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
@@ -173,32 +176,56 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sftp_session sftp_new_channel(ssh_session session, ssh_channel channel){
|
||||
sftp_session sftp;
|
||||
sftp_session
|
||||
sftp_new_channel(ssh_session session, ssh_channel channel)
|
||||
{
|
||||
sftp_session sftp = NULL;
|
||||
|
||||
if (session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sftp = calloc(1, sizeof(struct sftp_session_struct));
|
||||
if (sftp == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp = calloc(1, sizeof(struct sftp_session_struct));
|
||||
if (sftp == NULL) {
|
||||
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();
|
||||
if (sftp->ext == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct));
|
||||
if (sftp->read_packet == NULL) {
|
||||
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);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sftp->session = session;
|
||||
sftp->channel = channel;
|
||||
|
||||
return sftp;
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
tokens->buffer= strdup(chain);
|
||||
tokens->buffer = strdup(chain);
|
||||
if (tokens->buffer == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -147,15 +147,16 @@ static void cipher_free(struct ssh_cipher_struct *cipher) {
|
||||
SAFE_FREE(cipher);
|
||||
}
|
||||
|
||||
struct ssh_crypto_struct *crypto_new(void) {
|
||||
struct ssh_crypto_struct *crypto;
|
||||
struct ssh_crypto_struct *crypto_new(void)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto;
|
||||
|
||||
crypto = malloc(sizeof(struct ssh_crypto_struct));
|
||||
if (crypto == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(crypto);
|
||||
return crypto;
|
||||
crypto = malloc(sizeof(struct ssh_crypto_struct));
|
||||
if (crypto == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(crypto);
|
||||
return 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;
|
||||
}
|
||||
#endif
|
||||
SAFE_FREE(crypto->dh_server_signature);
|
||||
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);
|
||||
}
|
||||
if (crypto->secret_hash != NULL) {
|
||||
|
||||
@@ -37,6 +37,7 @@ if (WITH_SFTP)
|
||||
endif()
|
||||
set(LIBSSH_CLIENT_TESTS
|
||||
${LIBSSH_CLIENT_TESTS}
|
||||
torture_sftp_init
|
||||
torture_sftp_ext
|
||||
torture_sftp_canonicalize_path
|
||||
torture_sftp_dir
|
||||
|
||||
@@ -45,6 +45,16 @@ static int sshd_teardown(void **state) {
|
||||
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) {
|
||||
struct torture_state *s = *state;
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
struct torture_state *s = *state;
|
||||
|
||||
@@ -548,6 +572,19 @@ static void torture_algorithms_chacha20_poly1305(void **state)
|
||||
"chacha20-poly1305@openssh.com",
|
||||
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) {
|
||||
@@ -951,10 +988,30 @@ int torture_run_tests(void) {
|
||||
#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();
|
||||
|
||||
torture_filter_tests(tests);
|
||||
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();
|
||||
|
||||
|
||||
@@ -200,7 +200,8 @@ static int agent_teardown(void **state)
|
||||
assert_non_null(ssh_agent_pidfile);
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -551,6 +552,7 @@ static void torture_auth_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;
|
||||
ssh_session session = s->ssh.session;
|
||||
int rc;
|
||||
@@ -570,6 +572,7 @@ static void torture_auth_agent_cert(void **state)
|
||||
"ssh-rsa-cert-v01@openssh.com");
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
#endif /* OPENSSH_VERSION_MAJOR < 8.1 */
|
||||
|
||||
/* Setup loads a different key, tests are exactly the same. */
|
||||
torture_auth_agent(state);
|
||||
@@ -577,6 +580,7 @@ static void torture_auth_agent_cert(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;
|
||||
ssh_session session = s->ssh.session;
|
||||
int rc;
|
||||
@@ -596,6 +600,7 @@ static void torture_auth_agent_cert_nonblocking(void **state)
|
||||
"ssh-rsa-cert-v01@openssh.com");
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
#endif /* OPENSSH_VERSION_MAJOR < 8.1 */
|
||||
|
||||
torture_auth_agent_nonblocking(state);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#include <fcntl.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)
|
||||
{
|
||||
torture_setup_sshd_server(state, false);
|
||||
@@ -153,7 +157,6 @@ static void torture_rekey_send(void **state)
|
||||
int rc;
|
||||
char data[256];
|
||||
unsigned int i;
|
||||
uint64_t bytes = 2048; /* 2KB (more than the authentication phase) */
|
||||
struct ssh_crypto_struct *c = NULL;
|
||||
unsigned char *secret_hash = NULL;
|
||||
|
||||
@@ -189,10 +192,11 @@ static void torture_rekey_send(void **state)
|
||||
rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL);
|
||||
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, 'A', 128);
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (i = 0; i < KEX_RETRY; i++) {
|
||||
ssh_send_ignore(s->ssh.session, data);
|
||||
ssh_handle_packets(s->ssh.session, 50);
|
||||
}
|
||||
@@ -234,8 +238,6 @@ static void session_setup_sftp(void **state)
|
||||
assert_non_null(s->ssh.tsftp);
|
||||
}
|
||||
|
||||
uint64_t bytes = 2048; /* 2KB */
|
||||
|
||||
static int session_setup_sftp_client(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
@@ -439,6 +441,165 @@ static void torture_rekey_server_send(void **state)
|
||||
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 */
|
||||
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 */
|
||||
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
|
||||
static int session_setup_sftp_server(void **state)
|
||||
{
|
||||
@@ -505,6 +666,92 @@ static void torture_rekey_server_recv(void **state)
|
||||
#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 rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
@@ -522,16 +769,37 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_rekey_send,
|
||||
session_setup,
|
||||
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,
|
||||
session_setup,
|
||||
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
|
||||
cmocka_unit_test_setup_teardown(torture_rekey_server_recv,
|
||||
session_setup_sftp_server,
|
||||
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 */
|
||||
/* TODO verify the two rekey are possible and the states are not broken after rekey */
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
106
tests/client/torture_sftp_init.c
Normal file
106
tests/client/torture_sftp_init.c
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "config.h"
|
||||
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include "torture.h"
|
||||
#include "sftp.c"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int sshd_setup(void **state)
|
||||
{
|
||||
torture_setup_sshd_server(state, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sshd_teardown(void **state) {
|
||||
torture_teardown_sshd_server(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void session_setup(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
struct passwd *pwd;
|
||||
int rc;
|
||||
|
||||
pwd = getpwnam("bob");
|
||||
assert_non_null(pwd);
|
||||
|
||||
rc = setuid(pwd->pw_uid);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
s->ssh.session = torture_ssh_session(s,
|
||||
TORTURE_SSH_SERVER,
|
||||
NULL,
|
||||
TORTURE_SSH_USER_ALICE,
|
||||
NULL);
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
s->ssh.tsftp = torture_sftp_session(s->ssh.session);
|
||||
assert_non_null(s->ssh.tsftp);
|
||||
}
|
||||
|
||||
static void session_setup_channel(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
struct passwd *pwd = NULL;
|
||||
ssh_channel c = NULL;
|
||||
int rc;
|
||||
|
||||
pwd = getpwnam("bob");
|
||||
assert_non_null(pwd);
|
||||
|
||||
rc = setuid(pwd->pw_uid);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
s->ssh.session = torture_ssh_session(s,
|
||||
TORTURE_SSH_SERVER,
|
||||
NULL,
|
||||
TORTURE_SSH_USER_ALICE,
|
||||
NULL);
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
c = ssh_channel_new(s->ssh.session);
|
||||
assert_non_null(c);
|
||||
|
||||
s->ssh.tsftp = torture_sftp_session_channel(s->ssh.session, c);
|
||||
assert_non_null(s->ssh.tsftp);
|
||||
}
|
||||
|
||||
static int session_teardown(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
|
||||
torture_rmdirs(s->ssh.tsftp->testdir);
|
||||
torture_sftp_close(s->ssh.tsftp);
|
||||
ssh_disconnect(s->ssh.session);
|
||||
ssh_free(s->ssh.session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(session_setup,
|
||||
NULL,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(session_setup_channel,
|
||||
NULL,
|
||||
session_teardown)
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -392,45 +392,37 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
#endif
|
||||
|
||||
|
||||
#define PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \
|
||||
f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \
|
||||
#define PKDTESTS_CIPHER_COMMON(f, client, ciphercmd) \
|
||||
f(client, rsa_aes128_ctr, ciphercmd("aes128-ctr"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_rsa, teardown) \
|
||||
f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_521, teardown)
|
||||
|
||||
#define PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \
|
||||
PKDTESTS_CIPHER_COMMON(f, client, ciphercmd) \
|
||||
f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \
|
||||
f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown)
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
#define PKDTESTS_CIPHER(f, client, ciphercmd) \
|
||||
/* Ciphers. */ \
|
||||
PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \
|
||||
f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \
|
||||
f(client, dsa_3des_cbc, ciphercmd("3des-cbc"), setup_dsa, teardown) \
|
||||
f(client, dsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_dsa, teardown) \
|
||||
PKDTESTS_CIPHER_COMMON(f, client, ciphercmd) \
|
||||
f(client, dsa_aes128_ctr, ciphercmd("aes128-ctr"), setup_dsa, teardown) \
|
||||
f(client, dsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_dsa, teardown) \
|
||||
f(client, dsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_dsa, teardown) \
|
||||
f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown)
|
||||
f(client, dsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_dsa, teardown)
|
||||
#else
|
||||
#define PKDTESTS_CIPHER(f, client, ciphercmd) \
|
||||
/* Ciphers. */ \
|
||||
PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \
|
||||
f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \
|
||||
f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown)
|
||||
PKDTESTS_CIPHER_COMMON(f, client, ciphercmd)
|
||||
#endif
|
||||
|
||||
#define CHACHA20 "chacha20-poly1305@openssh.com"
|
||||
@@ -451,10 +443,16 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
#define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \
|
||||
/* Ciphers. */ \
|
||||
PKDTESTS_CIPHER_OPENSSHONLY_FIPS(f, client, ciphercmd) \
|
||||
f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \
|
||||
f(client, rsa_chacha20, ciphercmd(CHACHA20), setup_rsa, teardown) \
|
||||
f(client, dsa_3des_cbc, ciphercmd("3des-cbc"), setup_dsa, teardown) \
|
||||
f(client, dsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_dsa, teardown) \
|
||||
f(client, dsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_dsa, teardown) \
|
||||
f(client, dsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_dsa, teardown) \
|
||||
f(client, dsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_dsa, teardown) \
|
||||
f(client, dsa_chacha20, ciphercmd(CHACHA20), setup_dsa, teardown) \
|
||||
f(client, dsa_aes128_gcm, ciphercmd(AES128_GCM), setup_dsa, teardown) \
|
||||
@@ -469,20 +467,32 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ed25519_chacha20, ciphercmd(CHACHA20), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes128_gcm, ciphercmd(AES128_GCM), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes256_gcm, ciphercmd(AES256_GCM), setup_ed25519, teardown) \
|
||||
f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_chacha20, ciphercmd(CHACHA20), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_chacha20, ciphercmd(CHACHA20), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown)
|
||||
#else
|
||||
#define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \
|
||||
/* Ciphers. */ \
|
||||
PKDTESTS_CIPHER_OPENSSHONLY_FIPS(f, client, ciphercmd) \
|
||||
f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \
|
||||
f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \
|
||||
f(client, rsa_chacha20, ciphercmd(CHACHA20), setup_rsa, teardown) \
|
||||
f(client, ed25519_3des_cbc, ciphercmd("3des-cbc"), setup_ed25519, teardown) \
|
||||
@@ -493,13 +503,22 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ed25519_aes192_cbc, ciphercmd("aes192-cbc"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_aes192_ctr, ciphercmd("aes192-ctr"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_chacha20, ciphercmd(CHACHA20), setup_ed25519, teardown) \
|
||||
f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_chacha20, ciphercmd(CHACHA20), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_chacha20, ciphercmd(CHACHA20), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown)
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "pkd_keyutil.h"
|
||||
#include "pkd_util.h"
|
||||
|
||||
void setup_rsa_key() {
|
||||
void setup_rsa_key(void) {
|
||||
int rc = 0;
|
||||
if (access(LIBSSH_RSA_TESTKEY, F_OK) != 0) {
|
||||
rc = system_checked(OPENSSH_KEYGEN " -t rsa -q -N \"\" -f "
|
||||
@@ -31,7 +31,7 @@ void setup_rsa_key() {
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
void setup_ed25519_key() {
|
||||
void setup_ed25519_key(void) {
|
||||
int rc = 0;
|
||||
if (access(LIBSSH_ED25519_TESTKEY, F_OK) != 0) {
|
||||
rc = system_checked(OPENSSH_KEYGEN " -t ed25519 -q -N \"\" -f "
|
||||
@@ -41,7 +41,7 @@ void setup_ed25519_key() {
|
||||
}
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
void setup_dsa_key() {
|
||||
void setup_dsa_key(void) {
|
||||
int rc = 0;
|
||||
if (access(LIBSSH_DSA_TESTKEY, F_OK) != 0) {
|
||||
rc = system_checked(OPENSSH_KEYGEN " -t dsa -q -N \"\" -f "
|
||||
@@ -51,7 +51,7 @@ void setup_dsa_key() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void setup_ecdsa_keys() {
|
||||
void setup_ecdsa_keys(void) {
|
||||
int rc = 0;
|
||||
|
||||
if (access(LIBSSH_ECDSA_256_TESTKEY, F_OK) != 0) {
|
||||
@@ -71,27 +71,27 @@ void setup_ecdsa_keys() {
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_rsa_key() {
|
||||
void cleanup_rsa_key(void) {
|
||||
cleanup_key(LIBSSH_RSA_TESTKEY);
|
||||
}
|
||||
|
||||
void cleanup_ed25519_key() {
|
||||
void cleanup_ed25519_key(void) {
|
||||
cleanup_key(LIBSSH_ED25519_TESTKEY);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
void cleanup_dsa_key() {
|
||||
void cleanup_dsa_key(void) {
|
||||
cleanup_key(LIBSSH_DSA_TESTKEY);
|
||||
}
|
||||
#endif
|
||||
|
||||
void cleanup_ecdsa_keys() {
|
||||
void cleanup_ecdsa_keys(void) {
|
||||
cleanup_key(LIBSSH_ECDSA_256_TESTKEY);
|
||||
cleanup_key(LIBSSH_ECDSA_384_TESTKEY);
|
||||
cleanup_key(LIBSSH_ECDSA_521_TESTKEY);
|
||||
}
|
||||
|
||||
void setup_openssh_client_keys() {
|
||||
void setup_openssh_client_keys(void) {
|
||||
int rc = 0;
|
||||
|
||||
if (access(OPENSSH_CA_TESTKEY, F_OK) != 0) {
|
||||
@@ -184,7 +184,7 @@ void setup_openssh_client_keys() {
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_openssh_client_keys() {
|
||||
void cleanup_openssh_client_keys(void) {
|
||||
cleanup_key(OPENSSH_CA_TESTKEY);
|
||||
cleanup_key(OPENSSH_RSA_TESTKEY);
|
||||
cleanup_file(OPENSSH_RSA_TESTKEY "-sha256-cert.pub");
|
||||
@@ -199,7 +199,7 @@ void cleanup_openssh_client_keys() {
|
||||
}
|
||||
}
|
||||
|
||||
void setup_dropbear_client_rsa_key() {
|
||||
void setup_dropbear_client_rsa_key(void) {
|
||||
int rc = 0;
|
||||
if (access(DROPBEAR_RSA_TESTKEY, F_OK) != 0) {
|
||||
rc = system_checked(DROPBEAR_KEYGEN " -t rsa -f "
|
||||
@@ -208,6 +208,6 @@ void setup_dropbear_client_rsa_key() {
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
void cleanup_dropbear_client_rsa_key() {
|
||||
void cleanup_dropbear_client_rsa_key(void) {
|
||||
unlink(DROPBEAR_RSA_TESTKEY);
|
||||
}
|
||||
|
||||
@@ -285,9 +285,7 @@ static int stop_server(void **state)
|
||||
assert_non_null(s);
|
||||
|
||||
rc = torture_terminate_process(s->srv_pidfile);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "XXXXXX Failed to terminate sshd\n");
|
||||
}
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
unlink(s->srv_pidfile);
|
||||
|
||||
@@ -513,6 +511,12 @@ static void torture_server_config_ciphers(void **state)
|
||||
/* Try each algorithm individually */
|
||||
j = 0;
|
||||
while(tokens->tokens[j] != NULL) {
|
||||
char *cmp = strstr(OPENSSH_CIPHERS, tokens->tokens[j]);
|
||||
if (cmp == NULL) {
|
||||
/* This cipher is not supported by the OpenSSH. Skip it */
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
snprintf(config_content,
|
||||
sizeof(config_content),
|
||||
"HostKey %s\nCiphers %s\n",
|
||||
|
||||
112
tests/torture.c
112
tests/torture.c
@@ -250,8 +250,12 @@ int torture_terminate_process(const char *pidfile)
|
||||
|
||||
rc = kill(pid, 0);
|
||||
if (rc != 0) {
|
||||
is_running = 0;
|
||||
break;
|
||||
/* Process not found */
|
||||
if (errno == ESRCH) {
|
||||
is_running = 0;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +264,7 @@ int torture_terminate_process(const char *pidfile)
|
||||
"WARNING: The process with pid %u is still running!\n", pid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
ssh_session torture_ssh_session(struct torture_state *s,
|
||||
@@ -421,7 +425,8 @@ ssh_bind torture_ssh_bind(const char *addr,
|
||||
|
||||
#ifdef WITH_SFTP
|
||||
|
||||
struct torture_sftp *torture_sftp_session(ssh_session session) {
|
||||
struct torture_sftp *torture_sftp_session_channel(ssh_session session, ssh_channel channel)
|
||||
{
|
||||
struct torture_sftp *t;
|
||||
char template[] = "/tmp/ssh_torture_XXXXXX";
|
||||
char *p;
|
||||
@@ -437,9 +442,26 @@ struct torture_sftp *torture_sftp_session(ssh_session session) {
|
||||
}
|
||||
|
||||
t->ssh = session;
|
||||
t->sftp = sftp_new(session);
|
||||
if (t->sftp == NULL) {
|
||||
goto failed;
|
||||
if (channel == NULL) {
|
||||
t->sftp = sftp_new(session);
|
||||
if (t->sftp == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
} else {
|
||||
t->sftp = sftp_new_channel(session, channel);
|
||||
if (t->sftp == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc != SSH_OK) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
rc = ssh_channel_request_sftp(channel);
|
||||
if (rc != SSH_OK) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
rc = sftp_init(t->sftp);
|
||||
@@ -470,6 +492,11 @@ failed:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct torture_sftp *torture_sftp_session(ssh_session session)
|
||||
{
|
||||
return torture_sftp_session_channel(session, NULL);
|
||||
}
|
||||
|
||||
void torture_sftp_close(struct torture_sftp *t) {
|
||||
if (t == NULL) {
|
||||
return;
|
||||
@@ -629,7 +656,8 @@ static void torture_setup_create_sshd_config(void **state, bool pam)
|
||||
"\n"
|
||||
"StrictModes no\n"
|
||||
"\n"
|
||||
"%s" /* Here comes UsePam */
|
||||
"%s\n" /* Here comes UsePam */
|
||||
"%s" /* The space for test-specific options */
|
||||
"\n"
|
||||
/* add all supported algorithms */
|
||||
"HostKeyAlgorithms " OPENSSH_KEYS "\n"
|
||||
@@ -644,8 +672,7 @@ static void torture_setup_create_sshd_config(void **state, bool pam)
|
||||
"AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT\n"
|
||||
"AcceptEnv LC_IDENTIFICATION LC_ALL LC_LIBSSH\n"
|
||||
"\n"
|
||||
"PidFile %s\n"
|
||||
"%s\n"; /* The space for test-specific options */
|
||||
"PidFile %s\n";
|
||||
/* FIPS config */
|
||||
const char fips_config_string[]=
|
||||
"Port 22\n"
|
||||
@@ -663,7 +690,8 @@ static void torture_setup_create_sshd_config(void **state, bool pam)
|
||||
"\n"
|
||||
"StrictModes no\n"
|
||||
"\n"
|
||||
"%s" /* UsePam */
|
||||
"%s\n" /* Here comes UsePam */
|
||||
"%s" /* The space for test-specific options */
|
||||
"\n"
|
||||
"Ciphers "
|
||||
"aes256-gcm@openssh.com,aes256-ctr,aes256-cbc,"
|
||||
@@ -692,8 +720,7 @@ static void torture_setup_create_sshd_config(void **state, bool pam)
|
||||
"AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT\n"
|
||||
"AcceptEnv LC_IDENTIFICATION LC_ALL LC_LIBSSH\n"
|
||||
"\n"
|
||||
"PidFile %s\n" /* PID file */
|
||||
"%s\n"; /* The space for test-specific options */
|
||||
"PidFile %s\n"; /* PID file */
|
||||
const char usepam_yes[] =
|
||||
"UsePAM yes\n"
|
||||
"KbdInteractiveAuthentication yes\n";
|
||||
@@ -794,8 +821,8 @@ static void torture_setup_create_sshd_config(void **state, bool pam)
|
||||
trusted_ca_pubkey,
|
||||
sftp_server,
|
||||
usepam,
|
||||
s->srv_pidfile,
|
||||
additional_config);
|
||||
additional_config,
|
||||
s->srv_pidfile);
|
||||
} else {
|
||||
snprintf(sshd_config, sizeof(sshd_config),
|
||||
config_string,
|
||||
@@ -808,8 +835,8 @@ static void torture_setup_create_sshd_config(void **state, bool pam)
|
||||
trusted_ca_pubkey,
|
||||
sftp_server,
|
||||
usepam,
|
||||
s->srv_pidfile,
|
||||
additional_config);
|
||||
additional_config,
|
||||
s->srv_pidfile);
|
||||
}
|
||||
|
||||
torture_write_file(s->srv_config, sshd_config);
|
||||
@@ -833,21 +860,16 @@ static int torture_wait_for_daemon(unsigned int seconds)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void torture_setup_sshd_server(void **state, bool pam)
|
||||
static int torture_start_sshd_server(void **state)
|
||||
{
|
||||
struct torture_state *s;
|
||||
struct torture_state *s = *state;
|
||||
char sshd_start_cmd[1024];
|
||||
int rc;
|
||||
|
||||
torture_setup_socket_dir(state);
|
||||
torture_setup_create_sshd_config(state, pam);
|
||||
|
||||
/* Set the default interface for the server */
|
||||
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1);
|
||||
setenv("PAM_WRAPPER", "1", 1);
|
||||
|
||||
s = *state;
|
||||
|
||||
snprintf(sshd_start_cmd, sizeof(sshd_start_cmd),
|
||||
SSHD_EXECUTABLE " -r -f %s -E %s/sshd/daemon.log 2> %s/sshd/cwrap.log",
|
||||
s->srv_config, s->socket_dir, s->socket_dir);
|
||||
@@ -859,7 +881,20 @@ void torture_setup_sshd_server(void **state, bool pam)
|
||||
unsetenv("PAM_WRAPPER");
|
||||
|
||||
/* Wait until the sshd is ready to accept connections */
|
||||
rc = torture_wait_for_daemon(5);
|
||||
rc = torture_wait_for_daemon(15);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
void torture_setup_sshd_server(void **state, bool pam)
|
||||
{
|
||||
int rc;
|
||||
|
||||
torture_setup_socket_dir(state);
|
||||
torture_setup_create_sshd_config(state, pam);
|
||||
|
||||
rc = torture_start_sshd_server(state);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
@@ -899,29 +934,12 @@ static int
|
||||
torture_reload_sshd_server(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
pid_t pid;
|
||||
int rc;
|
||||
|
||||
/* read the pidfile */
|
||||
pid = torture_read_pidfile(s->srv_pidfile);
|
||||
assert_int_not_equal(pid, -1);
|
||||
rc = torture_terminate_process(s->srv_pidfile);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
kill(pid, SIGHUP);
|
||||
|
||||
/* 10 ms */
|
||||
usleep(10 * 1000);
|
||||
|
||||
rc = kill(pid, 0);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr,
|
||||
"ERROR: SSHD process %u died during reload!\n", pid);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Wait until the sshd is ready to accept connections */
|
||||
rc = torture_wait_for_daemon(5);
|
||||
assert_int_equal(rc, 0);
|
||||
return SSH_OK;
|
||||
return torture_start_sshd_server(state);
|
||||
}
|
||||
|
||||
/* @brief: Updates SSHD server configuration with more options and
|
||||
@@ -957,9 +975,7 @@ void torture_teardown_sshd_server(void **state)
|
||||
int rc;
|
||||
|
||||
rc = torture_terminate_process(s->srv_pidfile);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "XXXXXX Failed to terminate sshd\n");
|
||||
}
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
torture_teardown_socket_dir(state);
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ ssh_bind torture_ssh_bind(const char *addr,
|
||||
const char *private_key_file);
|
||||
|
||||
struct torture_sftp *torture_sftp_session(ssh_session session);
|
||||
struct torture_sftp *torture_sftp_session_channel(ssh_session session, ssh_channel channel);
|
||||
void torture_sftp_close(struct torture_sftp *t);
|
||||
|
||||
void torture_write_file(const char *filename, const char *data);
|
||||
|
||||
@@ -138,6 +138,9 @@ static void torture_callbacks_execute_list(void **state){
|
||||
};
|
||||
|
||||
(void)state;
|
||||
|
||||
assert_non_null(list);
|
||||
|
||||
ssh_callbacks_init(&c1);
|
||||
ssh_callbacks_init(&c2);
|
||||
ssh_callbacks_init(&c3);
|
||||
@@ -213,6 +216,8 @@ static void torture_callbacks_iterate(void **state){
|
||||
|
||||
(void)state; /* unused */
|
||||
|
||||
assert_non_null(list);
|
||||
|
||||
ssh_callbacks_init(&c1);
|
||||
ssh_callbacks_init(&c2);
|
||||
|
||||
|
||||
@@ -209,7 +209,8 @@ static void torture_timeout_elapsed(void **state){
|
||||
struct ssh_timestamp ts;
|
||||
(void) state;
|
||||
ssh_timestamp_init(&ts);
|
||||
usleep(50000);
|
||||
usleep(30000);
|
||||
|
||||
assert_true(ssh_timeout_elapsed(&ts,25));
|
||||
assert_false(ssh_timeout_elapsed(&ts,30000));
|
||||
assert_false(ssh_timeout_elapsed(&ts,75));
|
||||
|
||||
@@ -517,12 +517,108 @@ static void torture_packet_filter_check_channel_open(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void torture_packet_filter_check_channel_success(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* The only condition to accept a CHANNEL_SUCCESS is to be authenticated */
|
||||
global_state accepted[] = {
|
||||
{
|
||||
.flags = COMPARE_SESSION_STATE,
|
||||
.session = SSH_SESSION_STATE_AUTHENTICATED,
|
||||
}
|
||||
};
|
||||
|
||||
int accepted_count = 1;
|
||||
|
||||
/* Unused */
|
||||
(void) state;
|
||||
|
||||
rc = check_message_in_all_states(accepted, accepted_count,
|
||||
SSH2_MSG_CHANNEL_SUCCESS);
|
||||
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void torture_packet_filter_check_channel_failure(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* The only condition to accept a CHANNEL_FAILURE is to be authenticated */
|
||||
global_state accepted[] = {
|
||||
{
|
||||
.flags = COMPARE_SESSION_STATE,
|
||||
.session = SSH_SESSION_STATE_AUTHENTICATED,
|
||||
}
|
||||
};
|
||||
|
||||
int accepted_count = 1;
|
||||
|
||||
/* Unused */
|
||||
(void) state;
|
||||
|
||||
rc = check_message_in_all_states(accepted, accepted_count,
|
||||
SSH2_MSG_CHANNEL_FAILURE);
|
||||
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void torture_packet_filter_check_request_success(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* The only condition to accept a REQUEST_SUCCESS is to be authenticated */
|
||||
global_state accepted[] = {
|
||||
{
|
||||
.flags = COMPARE_SESSION_STATE,
|
||||
.session = SSH_SESSION_STATE_AUTHENTICATED,
|
||||
}
|
||||
};
|
||||
|
||||
int accepted_count = 1;
|
||||
|
||||
/* Unused */
|
||||
(void) state;
|
||||
|
||||
rc = check_message_in_all_states(accepted, accepted_count,
|
||||
SSH2_MSG_REQUEST_SUCCESS);
|
||||
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void torture_packet_filter_check_request_failure(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* The only condition to accept a REQUEST_FAILURE is to be authenticated */
|
||||
global_state accepted[] = {
|
||||
{
|
||||
.flags = COMPARE_SESSION_STATE,
|
||||
.session = SSH_SESSION_STATE_AUTHENTICATED,
|
||||
}
|
||||
};
|
||||
|
||||
int accepted_count = 1;
|
||||
|
||||
/* Unused */
|
||||
(void) state;
|
||||
|
||||
rc = check_message_in_all_states(accepted, accepted_count,
|
||||
SSH2_MSG_REQUEST_FAILURE);
|
||||
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(torture_packet_filter_check_auth_success),
|
||||
cmocka_unit_test(torture_packet_filter_check_channel_open),
|
||||
cmocka_unit_test(torture_packet_filter_check_channel_success),
|
||||
cmocka_unit_test(torture_packet_filter_check_channel_failure),
|
||||
cmocka_unit_test(torture_packet_filter_check_request_success),
|
||||
cmocka_unit_test(torture_packet_filter_check_request_failure),
|
||||
cmocka_unit_test(torture_packet_filter_check_unfiltered),
|
||||
cmocka_unit_test(torture_packet_filter_check_msg_ext_info)
|
||||
};
|
||||
|
||||
@@ -796,7 +796,8 @@ static void torture_pki_ed25519_verify(void **state){
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN);
|
||||
rc = ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN);
|
||||
assert_int_equal(rc, 0);
|
||||
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO);
|
||||
assert_non_null(sig);
|
||||
|
||||
@@ -853,7 +854,8 @@ static void torture_pki_ed25519_verify_bad(void **state){
|
||||
/* alter signature and expect false result */
|
||||
|
||||
for (i=0; i < ED25519_SIG_LEN; ++i){
|
||||
ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN);
|
||||
rc = ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN);
|
||||
assert_int_equal(rc, 0);
|
||||
((uint8_t *)ssh_string_data(blob))[i] ^= 0xff;
|
||||
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO);
|
||||
assert_non_null(sig);
|
||||
|
||||
@@ -48,8 +48,9 @@ struct ssh_cipher_struct fake_out_cipher = {
|
||||
};
|
||||
|
||||
struct ssh_crypto_struct test_crypto = {
|
||||
.digest_len = 32,
|
||||
.session_id_len = 32,
|
||||
.session_id = secret,
|
||||
.digest_len = 32,
|
||||
.secret_hash = secret,
|
||||
.in_cipher = &fake_in_cipher,
|
||||
.out_cipher = &fake_out_cipher,
|
||||
@@ -68,7 +69,9 @@ static void torture_session_keys(UNUSED_PARAM(void **state))
|
||||
int rc;
|
||||
|
||||
k_string = ssh_string_new(32);
|
||||
ssh_string_fill(k_string, key, 32);
|
||||
rc = ssh_string_fill(k_string, key, 32);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
test_crypto.shared_secret = ssh_make_string_bn(k_string);
|
||||
|
||||
rc = ssh_generate_session_keys(&session);
|
||||
|
||||
Reference in New Issue
Block a user