Version in base suite: 0.9.5-1+deb11u1 Base version: libssh_0.9.5-1+deb11u1 Target version: libssh_0.9.7-0+deb11u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libs/libssh/libssh_0.9.5-1+deb11u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libs/libssh/libssh_0.9.7-0+deb11u1.dsc .gitlab-ci.yml | 515 ---------- CMakeLists.txt | 18 CPackConfig.cmake | 2 ChangeLog | 25 ConfigureChecks.cmake | 26 cmake/Modules/FindABIMap.cmake | 26 debian/changelog | 18 debian/patches/0001-dh-gex-Avoid-memory-leaks.patch | 38 debian/patches/0002-Fix-handshake-bug-with-AEAD-ciphers-and-no-HMAC-over.patch | 160 --- debian/patches/0003-Add-initial-server-algorithm-test-for-no-HMAC-overla.patch | 402 ------- debian/patches/0004-CVE-2021-3634-Create-a-separate-length-for-session_i.patch | 179 --- debian/patches/0005-tests-Simple-reproducer-for-rekeying-with-different-.patch | 222 ---- debian/patches/2004-install-static-lib.patch | 8 debian/patches/series | 5 examples/libssh_scp.c | 2 examples/sshd_direct-tcpip.c | 12 examples/sshnetcat.c | 5 include/libssh/crypto.h | 3 include/libssh/curve25519.h | 1 include/libssh/dh-gex.h | 1 include/libssh/dh.h | 2 include/libssh/ecdh.h | 1 include/libssh/kex.h | 2 include/libssh/libssh.h | 2 include/libssh/packet.h | 2 include/libssh/pki.h | 2 include/libssh/session.h | 34 src/ABI/current | 2 src/ABI/libssh-4.8.7.symbols | 421 ++++++++ src/ABI/libssh-4.8.8.symbols | 421 ++++++++ src/CMakeLists.txt | 25 src/channels.c | 10 src/client.c | 158 +-- src/config.c | 1 src/connect.c | 3 src/curve25519.c | 27 src/dh-gex.c | 10 src/dh.c | 8 src/ecdh.c | 7 src/external/ed25519.c | 8 src/getpass.c | 12 src/gssapi.c | 36 src/init.c | 2 src/kdf.c | 2 src/kex.c | 498 ++++++--- src/knownhosts.c | 1 src/libcrypto.c | 2 src/libmbedcrypto.c | 4 src/messages.c | 44 src/misc.c | 13 src/packet.c | 99 + src/packet_cb.c | 12 src/pki.c | 25 src/pki_crypto.c | 72 - src/pki_ed25519_common.c | 11 src/pki_gcrypt.c | 25 src/pki_mbedcrypto.c | 13 src/server.c | 243 ++-- src/sftp.c | 65 - src/threads/winlocks.c | 1 src/token.c | 2 src/wrapper.c | 20 tests/client/CMakeLists.txt | 1 tests/client/torture_algorithms.c | 57 + tests/client/torture_auth.c | 7 tests/client/torture_rekey.c | 282 +++++ tests/client/torture_sftp_init.c | 106 ++ tests/pkd/pkd_hello.c | 65 - tests/pkd/pkd_keyutil.c | 24 tests/server/torture_server_config.c | 10 tests/torture.c | 112 +- tests/torture.h | 1 tests/unittests/torture_callbacks.c | 5 tests/unittests/torture_misc.c | 3 tests/unittests/torture_packet_filter.c | 96 + tests/unittests/torture_pki_ed25519.c | 6 tests/unittests/torture_session_keys.c | 7 77 files changed, 2583 insertions(+), 2215 deletions(-) diff -Nru libssh-0.9.5/.gitlab-ci.yml libssh-0.9.7/.gitlab-ci.yml --- libssh-0.9.5/.gitlab-ci.yml 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/.gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,515 +0,0 @@ -variables: - BUILD_IMAGES_PROJECT: libssh/build-images - FEDORA_BUILD: buildenv-fedora - CENTOS7_BUILD: buildenv-centos7 - TUMBLEWEED_BUILD: buildenv-tumbleweed - MINGW_BUILD: buildenv-mingw - -# pkd tests fail on CentOS7 docker images, so we don't use -DSERVER_TESTING=ON -centos7/openssl_1.0.x/x86_64: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD - script: - - mkdir -p obj && cd obj && cmake3 - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON -DCLIENT_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: - - 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 - -DWITH_DEBUG_CRYPTO=ON - -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=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/fips: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - echo 1 > /etc/system-fips - - update-crypto-policies --set FIPS - - 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 - -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON - -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. && - make -j$(nproc) && OPENSSL_FORCE_FIPS_MODE=1 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/minimal: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_ZLIB=OFF -DWITH_PCAP=OFF - -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DWITH_GEX=OFF .. && - make -j$(nproc) && ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -# Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite -# so, this is only enabled for unit tests right now. -# TODO: add -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -fedora/address-sanitizer: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=AddressSanitizer - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -# This is disabled as it report OpenSSL issues -# It also has ethe same issues with cwrap as AddressSanitizer -.fedora/memory-sanitizer: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=MemorySanitizer - -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. - && make -j$(nproc) && ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -fedora/undefined-sanitizer: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=UndefinedSanitizer - -DPICKY_DEVELOPER=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/csbuild: - variables: - GIT_DEPTH: "100" - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - | - if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then - export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") - fi - - # Check if the commit exists in this branch - # This is not the case for a force push - git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") - - export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA" - - - csbuild - --build-dir=obj-csbuild - --build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@ && make clean && make -j$(nproc)" - --git-commit-range $CI_COMMIT_RANGE - --color - --print-current --print-fixed - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj-csbuild/ - -# That is a specific runner that we cannot enable universally. -# We restrict it to builds under the $BUILD_IMAGES_PROJECT project. -freebsd/x86_64: - image: - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make && ctest --output-on-failure - tags: - - freebsd - except: - - tags - only: - - branches@libssh/libssh-mirror - - branches@cryptomilk/libssh-mirror - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -fedora/libgcrypt/x86_64: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON - -DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON .. && - make -j$(nproc) && ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -fedora/mbedtls/x86_64: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON - -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON .. && - make -j$(nproc) && ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -# Unit testing only, no client and pkd testing, because cwrap is not available -# for MinGW -fedora/mingw64: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD - script: - - export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin - - export WINEDEBUG=-all - - mkdir -p obj && cd obj && mingw64-cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -# Unit testing only, no client and pkd testing, because cwrap is not available -# for MinGW -fedora/mingw32: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD - script: - - export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin - - export WINEDEBUG=-all - - mkdir -p obj && cd obj && mingw32-cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && - ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -tumbleweed/openssl_1.1.x/x86_64/gcc: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config - -DUNIT_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/ - -tumbleweed/openssl_1.1.x/x86/gcc: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -tumbleweed/openssl_1.1.x/x86_64/gcc7: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config - -DUNIT_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/ - -tumbleweed/openssl_1.1.x/x86/gcc7: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake - -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -tumbleweed/openssl_1.1.x/x86_64/clang: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config - -DUNIT_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/ - -tumbleweed/docs: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - mkdir -p obj && cd obj && cmake .. && make docs - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/ - -tumbleweed/undefined-sanitizer: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=UndefinedSanitizer - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_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/ - -tumbleweed/static-analysis: - image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD - script: - - export CCC_CC=clang - - export CCC_CXX=clang++ - - mkdir -p obj && cd obj && scan-build cmake - -DCMAKE_BUILD_TYPE=Debug - -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON - -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && - scan-build --status-bugs -o scan make -j$(nproc) - tags: - - shared - except: - - tags - artifacts: - expire_in: 1 week - when: on_failure - paths: - - obj/scan - -visualstudio/x86_64: - 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 - 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/ - -visualstudio/x86: - 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/ diff -Nru libssh-0.9.5/CMakeLists.txt libssh-0.9.7/CMakeLists.txt --- libssh-0.9.5/CMakeLists.txt 2020-09-10 12:43:36.000000000 +0000 +++ libssh-0.9.7/CMakeLists.txt 2023-05-04 11:41:35.000000000 +0000 @@ -10,7 +10,7 @@ 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 @@ # 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 @@ 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 @@ 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 @@ 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") diff -Nru libssh-0.9.5/CPackConfig.cmake libssh-0.9.7/CPackConfig.cmake --- libssh-0.9.5/CPackConfig.cmake 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/CPackConfig.cmake 2023-05-04 11:41:22.000000000 +0000 @@ -10,7 +10,7 @@ # 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 diff -Nru libssh-0.9.5/ChangeLog libssh-0.9.7/ChangeLog --- libssh-0.9.5/ChangeLog 2020-09-10 12:43:36.000000000 +0000 +++ libssh-0.9.7/ChangeLog 2023-05-04 11:41:09.000000000 +0000 @@ -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) diff -Nru libssh-0.9.5/ConfigureChecks.cmake libssh-0.9.7/ConfigureChecks.cmake --- libssh-0.9.5/ConfigureChecks.cmake 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/ConfigureChecks.cmake 2022-05-23 13:08:11.000000000 +0000 @@ -101,53 +101,53 @@ 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 @@ 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) diff -Nru libssh-0.9.5/cmake/Modules/FindABIMap.cmake libssh-0.9.7/cmake/Modules/FindABIMap.cmake --- libssh-0.9.5/cmake/Modules/FindABIMap.cmake 2020-01-27 15:45:32.000000000 +0000 +++ libssh-0.9.7/cmake/Modules/FindABIMap.cmake 2022-05-23 13:08:11.000000000 +0000 @@ -302,12 +302,13 @@ 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 @@ ${_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 @@ 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 @@ ${_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 @@ ${_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() diff -Nru libssh-0.9.5/debian/changelog libssh-0.9.7/debian/changelog --- libssh-0.9.5/debian/changelog 2021-08-28 11:52:11.000000000 +0000 +++ libssh-0.9.7/debian/changelog 2023-05-21 18:22:05.000000000 +0000 @@ -1,3 +1,21 @@ +libssh (0.9.7-0+deb11u1) bullseye-security; urgency=medium + + * New upstream security microrelease: + - CVE-2023-1667: Authenticated remote DoS. + Fix authenticated remote DoS through potential NULL dereference during + rekeying with algorithm guessing + https://www.libssh.org/security/advisories/CVE-2023-1667.txt + - CVE-2023-2283: Client authentication bypass. + Fix client authentication bypass in pki_verify_data_signature() in + low-memory conditions with OpenSSL backend; gcrypt backend is not + affected. + https://www.libssh.org/security/advisories/CVE-2023-2283.txt + (Closes: #1035832) + * Drop 000* patches which were backported from the upstream stable 0.9 + branch, now included in this release. Unfuzz 2004-install-static-lib.patch. + + -- Martin Pitt Sun, 21 May 2023 18:22:05 +0000 + libssh (0.9.5-1+deb11u1) bullseye-security; urgency=high * dh-gex: Avoid memory leaks. diff -Nru libssh-0.9.5/debian/patches/0001-dh-gex-Avoid-memory-leaks.patch libssh-0.9.7/debian/patches/0001-dh-gex-Avoid-memory-leaks.patch --- libssh-0.9.5/debian/patches/0001-dh-gex-Avoid-memory-leaks.patch 2021-08-28 11:52:11.000000000 +0000 +++ libssh-0.9.7/debian/patches/0001-dh-gex-Avoid-memory-leaks.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -From ae809b3cbbfde6010cb6cb5e84660af128a8b16a Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 15 Jan 2021 19:23:53 +0100 -Subject: [PATCH] dh-gex: Avoid memory leaks - -Thanks oss-fuzz - -https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29611 -Signed-off-by: Jakub Jelen -Reviewed-by: Andreas Schneider ---- - src/dh-gex.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git src/dh-gex.c src/dh-gex.c -index 9bf0546a..88a97140 100644 ---- a/src/dh-gex.c -+++ b/src/dh-gex.c -@@ -263,6 +263,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 +295,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; - --- -2.31.1 - diff -Nru libssh-0.9.5/debian/patches/0002-Fix-handshake-bug-with-AEAD-ciphers-and-no-HMAC-over.patch libssh-0.9.7/debian/patches/0002-Fix-handshake-bug-with-AEAD-ciphers-and-no-HMAC-over.patch --- libssh-0.9.5/debian/patches/0002-Fix-handshake-bug-with-AEAD-ciphers-and-no-HMAC-over.patch 2021-08-28 11:52:11.000000000 +0000 +++ libssh-0.9.7/debian/patches/0002-Fix-handshake-bug-with-AEAD-ciphers-and-no-HMAC-over.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,160 +0,0 @@ -From 42741b18832aa8acab51c53505efa263e8193537 Mon Sep 17 00:00:00 2001 -From: Dirkjan Bussink -Date: Tue, 29 Sep 2020 15:14:09 +0200 -Subject: [PATCH] Fix handshake bug with AEAD ciphers and no HMAC overlap - -There's currently a bug in libssh that a handshake doesn't complete if -there is no overlap between HMAC methods, but when an AEAD cipher is -used. - -In case of an AEAD cipher such as chacha20-poly1305 or aes256-gcm, the -HMAC algorithm that is being picked is not relevant. But the problem -here is that the HMAC still needs to have an overlap in the handshake, -even if it is not used afterwards. - -This was found with a very strict server side configuration with libssh -where only AEAD ciphers and EtM HMAC modes are accepted. The client -tested against was dropbear. - -Dropbear does have support for chacha20-poly1305 and AES GCM modes, but -no support for EtM HMAC modes. This meant that the libssh server in this -case rejected the dropbear client, even though it is perfectly able to -serve it since dropbear supports AEAD algorithms. - -The fix implemented here updates the HMAC phase of the handshake to -handle this case. If it detects an AEAD cipher is used, it uses the HMAC -abbreviations for the method instead. This is the same name that is used -in other places as well. It matches the client to server and server to -client values, but it does depend on the order of things in the -ssh_kex_types_e enum, which I'm assuming here is ok since it's explicit. - -I've looked at how to add a test for this, but I couldn't really find a -suitable place for it. I would love some tips if this is easily -possible, or if it's easier for someone else to contribute, that's of -course welcome too. - -Signed-off-by: Dirkjan Bussink -Reviewed-by: Anderson Toshiyuki Sasaki -Reviewed-by: Jakub Jelen ---- - src/kex.c | 57 +++++++++++++++++++++++++++++++++++++++---------------- - 1 file changed, 41 insertions(+), 16 deletions(-) - -diff --git src/kex.c src/kex.c -index 1df22830..95948136 100644 ---- a/src/kex.c -+++ a/src/kex.c -@@ -755,13 +755,29 @@ 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; -+} -+ - /** @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){ -+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; - char *ext_start = NULL; -+ const char *aead_hmac = NULL; - int i; - - /* Here we should drop the ext-info-c from the list so we avoid matching. -@@ -773,7 +789,15 @@ 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){ -+ -+ if (i == SSH_MAC_C_S || i == SSH_MAC_S_C) { -+ aead_hmac = ssh_find_aead_hmac(session->next_crypto->kex_methods[i-2]); -+ if (aead_hmac) { -+ free(session->next_crypto->kex_methods[i]); -+ session->next_crypto->kex_methods[i] = strdup(aead_hmac); -+ } -+ } -+ 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]); - return SSH_ERROR; -@@ -782,31 +806,31 @@ int ssh_kex_select_methods (ssh_session session){ - session->next_crypto->kex_methods[i] = strdup(""); - } - } -- if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){ -+ 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){ -+ } 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){ -+ } 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){ -+ } 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){ -+ } 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){ -+ } 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){ -+ } 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){ -+ } 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){ -+ } 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){ -+ } 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){ -+ } 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){ -+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){ - session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256; - } - SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", -@@ -826,7 +850,8 @@ 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) { -+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; -@@ -1043,7 +1068,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; - } - --- -2.31.1 - diff -Nru libssh-0.9.5/debian/patches/0003-Add-initial-server-algorithm-test-for-no-HMAC-overla.patch libssh-0.9.7/debian/patches/0003-Add-initial-server-algorithm-test-for-no-HMAC-overla.patch --- libssh-0.9.5/debian/patches/0003-Add-initial-server-algorithm-test-for-no-HMAC-overla.patch 2021-08-28 11:52:11.000000000 +0000 +++ libssh-0.9.7/debian/patches/0003-Add-initial-server-algorithm-test-for-no-HMAC-overla.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,402 +0,0 @@ -From 39cbe8178e94279282ca3a045ab126baaea2bb31 Mon Sep 17 00:00:00 2001 -From: Dirkjan Bussink -Date: Mon, 5 Oct 2020 13:34:06 +0000 -Subject: [PATCH] Add initial server algorithm test for no HMAC overlap - -This adds an initial test with all AEAD modes to verify that they work -if there is no overlap in HMAC ciphers. - -Signed-off-by: Dirkjan Bussink -Reviewed-by: Anderson Toshiyuki Sasaki -Reviewed-by: Jakub Jelen ---- - tests/server/CMakeLists.txt | 1 + - tests/server/torture_server_algorithms.c | 364 +++++++++++++++++++++++ - 2 files changed, 365 insertions(+) - create mode 100644 tests/server/torture_server_algorithms.c - -diff --git tests/server/CMakeLists.txt tests/server/CMakeLists.txt -index ebe2d169..96457cd2 100644 ---- a/tests/server/CMakeLists.txt -+++ b/tests/server/CMakeLists.txt -@@ -10,6 +10,7 @@ set(LIBSSH_SERVER_TESTS - torture_server - torture_server_auth_kbdint - torture_server_config -+ torture_server_algorithms - ) - - include_directories(${libssh_SOURCE_DIR}/include -diff --git tests/server/torture_server_algorithms.c tests/server/torture_server_algorithms.c -new file mode 100644 -index 00000000..3963e368 ---- /dev/null -+++ b/tests/server/torture_server_algorithms.c -@@ -0,0 +1,364 @@ -+/* -+ * This file is part of the SSH Library -+ * -+ * Copyright (c) 2019 by Red Hat, Inc. -+ * -+ * Author: Anderson Toshiyuki Sasaki -+ * -+ * The SSH Library is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License as published by -+ * the Free Software Foundation; either version 2.1 of the License, or (at your -+ * option) any later version. -+ * -+ * The SSH Library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -+ * License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with the SSH Library; see the file COPYING. If not, write to -+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -+ * MA 02111-1307, USA. -+ */ -+ -+#include "config.h" -+ -+#define LIBSSH_STATIC -+ -+#include -+#include -+#include -+#include -+ -+#include "torture.h" -+#include "torture_key.h" -+#include "libssh/libssh.h" -+#include "libssh/priv.h" -+#include "libssh/session.h" -+#include "libssh/token.h" -+ -+#include "test_server.h" -+#include "default_cb.h" -+ -+const char template[] = "temp_dir_XXXXXX"; -+ -+struct test_server_st { -+ struct torture_state *state; -+ char *cwd; -+ char *temp_dir; -+ char rsa_hostkey[1024]; -+}; -+ -+static int setup_files(void **state) -+{ -+ struct test_server_st *tss; -+ struct torture_state *s; -+ char sshd_path[1024]; -+ -+ int rc; -+ -+ tss = (struct test_server_st*)calloc(1, sizeof(struct test_server_st)); -+ assert_non_null(tss); -+ -+ torture_setup_socket_dir((void **)&s); -+ assert_non_null(s->socket_dir); -+ -+ /* Set the default interface for the server */ -+ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1); -+ -+ snprintf(sshd_path, -+ sizeof(sshd_path), -+ "%s/sshd", -+ s->socket_dir); -+ -+ rc = mkdir(sshd_path, 0755); -+ assert_return_code(rc, errno); -+ -+ snprintf(tss->rsa_hostkey, -+ sizeof(tss->rsa_hostkey), -+ "%s/sshd/ssh_host_rsa_key", -+ s->socket_dir); -+ torture_write_file(tss->rsa_hostkey, torture_get_testkey(SSH_KEYTYPE_RSA, 0)); -+ -+ tss->state = s; -+ *state = tss; -+ -+ return 0; -+} -+ -+static int teardown_files(void **state) -+{ -+ struct torture_state *s; -+ struct test_server_st *tss; -+ -+ tss = *state; -+ assert_non_null(tss); -+ -+ s = tss->state; -+ assert_non_null(s); -+ -+ torture_teardown_socket_dir((void **)&s); -+ SAFE_FREE(tss); -+ -+ return 0; -+} -+ -+static int setup_temp_dir(void **state) -+{ -+ struct test_server_st *tss = *state; -+ struct torture_state *s; -+ -+ char *cwd = NULL; -+ char *tmp_dir = NULL; -+ -+ assert_non_null(tss); -+ -+ s = tss->state; -+ assert_non_null(s); -+ -+ cwd = torture_get_current_working_dir(); -+ assert_non_null(cwd); -+ -+ tmp_dir = torture_make_temp_dir(template); -+ assert_non_null(tmp_dir); -+ -+ tss->cwd = cwd; -+ tss->temp_dir = tmp_dir; -+ -+ return 0; -+} -+ -+static int teardown_temp_dir(void **state) -+{ -+ struct test_server_st *tss = *state; -+ int rc; -+ -+ assert_non_null(tss); -+ -+ rc = torture_change_dir(tss->cwd); -+ assert_int_equal(rc, 0); -+ -+ rc = torture_rmdirs(tss->temp_dir); -+ assert_int_equal(rc, 0); -+ -+ SAFE_FREE(tss->temp_dir); -+ SAFE_FREE(tss->cwd); -+ -+ return 0; -+} -+ -+static int start_server(void **state) -+{ -+ struct test_server_st *tss = *state; -+ struct torture_state *s; -+ -+ assert_non_null(tss); -+ -+ s = tss->state; -+ assert_non_null(s); -+ -+ /* Start the server using the default values */ -+ torture_setup_libssh_server((void **)&s, "./test_server/test_server"); -+ assert_non_null(s); -+ -+ return 0; -+} -+ -+static int stop_server(void **state) -+{ -+ struct torture_state *s; -+ struct test_server_st *tss; -+ -+ int rc; -+ -+ tss = *state; -+ assert_non_null(tss); -+ -+ s = tss->state; -+ assert_non_null(s); -+ -+ rc = torture_terminate_process(s->srv_pidfile); -+ assert_return_code(rc, errno); -+ -+ unlink(s->srv_pidfile); -+ -+ return 0; -+} -+ -+static int session_setup(void **state) -+{ -+ struct test_server_st *tss = *state; -+ struct torture_state *s; -+ int verbosity = torture_libssh_verbosity(); -+ struct passwd *pwd; -+ bool b = false; -+ int rc; -+ -+ assert_non_null(tss); -+ -+ /* Make sure we do not test the agent */ -+ unsetenv("SSH_AUTH_SOCK"); -+ -+ s = tss->state; -+ assert_non_null(s); -+ -+ pwd = getpwnam("bob"); -+ assert_non_null(pwd); -+ -+ rc = setuid(pwd->pw_uid); -+ assert_return_code(rc, errno); -+ -+ s->ssh.session = ssh_new(); -+ assert_non_null(s->ssh.session); -+ -+ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); -+ assert_ssh_return_code(s->ssh.session, rc); -+ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); -+ assert_ssh_return_code(s->ssh.session, rc); -+ /* Make sure no other configuration options from system will get used */ -+ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b); -+ assert_ssh_return_code(s->ssh.session, rc); -+ -+ return 0; -+} -+ -+static int session_teardown(void **state) -+{ -+ struct test_server_st *tss = *state; -+ struct torture_state *s; -+ -+ assert_non_null(tss); -+ -+ s = tss->state; -+ assert_non_null(s); -+ -+ ssh_disconnect(s->ssh.session); -+ ssh_free(s->ssh.session); -+ -+ return 0; -+} -+ -+/* -+ * Check that the handshake works with an AEAD cipher configured -+ * but with no overlap for HMACs. AEAD ciphers have an implied HMAC -+ * so no HMAC overlap in the handshake should not fail the connection. -+ */ -+static void test_algorithm_no_hmac_overlap(void **state, const char *algorithm) -+{ -+ struct test_server_st *tss = *state; -+ struct torture_state *s = NULL; -+ char config_content[4096]; -+ -+ ssh_session session = NULL; -+ -+ int rc; -+ -+ assert_non_null(tss); -+ s = tss->state; -+ assert_non_null(s); -+ -+ /* Prepare key files */ -+ snprintf(config_content, -+ sizeof(config_content), -+ "HostKey %s\nCiphers %s\nMACs %s\n", -+ tss->rsa_hostkey, -+ algorithm, -+ "hmac-sha2-512-etm@openssh.com"); -+ -+ assert_non_null(s->srv_config); -+ torture_write_file(s->srv_config, config_content); -+ -+ fprintf(stderr, "Config file %s content: \n\n%s\n", s->srv_config, -+ config_content); -+ fflush(stderr); -+ -+ /* Start server */ -+ rc = start_server(state); -+ assert_int_equal(rc, 0); -+ -+ /* Setup session */ -+ rc = session_setup(state); -+ assert_int_equal(rc, 0); -+ -+ session = s->ssh.session; -+ assert_non_null(session); -+ -+ rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); -+ assert_int_equal(rc, SSH_OK); -+ -+ rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, algorithm); -+ assert_int_equal(rc, SSH_OK); -+ -+ rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, algorithm); -+ assert_int_equal(rc, SSH_OK); -+ -+ rc = ssh_options_set(session, SSH_OPTIONS_HMAC_C_S, "hmac-sha2-512"); -+ assert_int_equal(rc, SSH_OK); -+ -+ rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "hmac-sha2-512"); -+ assert_int_equal(rc, SSH_OK); -+ -+ rc = ssh_connect(session); -+ assert_int_equal(rc, SSH_OK); -+ -+ rc = ssh_userauth_none(session, NULL); -+ /* This request should return a SSH_REQUEST_DENIED error */ -+ if (rc == SSH_ERROR) { -+ assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); -+ } -+ rc = ssh_userauth_list(session, NULL); -+ assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); -+ -+ rc = ssh_userauth_publickey_auto(session, NULL, NULL); -+ assert_ssh_return_code(session, rc); -+ -+ rc = session_teardown(state); -+ assert_int_equal(rc, 0); -+ -+ rc = stop_server(state); -+ assert_int_equal(rc, 0); -+ -+ SAFE_FREE(s->srv_additional_config); -+} -+ -+static void torture_algorithm_chacha20_with_no_hmac_overlap(void **state) -+{ -+ if (ssh_fips_mode()) { -+ skip(); -+ } -+ test_algorithm_no_hmac_overlap(state, "chacha20-poly1305@openssh.com"); -+} -+ -+static void torture_algorithm_aes256gcm_with_no_hmac_overlap(void **state) -+{ -+ test_algorithm_no_hmac_overlap(state, "aes256-gcm@openssh.com"); -+} -+ -+static void torture_algorithm_aes128gcm_with_no_hmac_overlap(void **state) -+{ -+ test_algorithm_no_hmac_overlap(state, "aes128-gcm@openssh.com"); -+} -+ -+int torture_run_tests(void) -+{ -+ int rc; -+ struct CMUnitTest tests[] = { -+ cmocka_unit_test_setup_teardown(torture_algorithm_chacha20_with_no_hmac_overlap, -+ setup_temp_dir, teardown_temp_dir), -+ cmocka_unit_test_setup_teardown(torture_algorithm_aes256gcm_with_no_hmac_overlap, -+ setup_temp_dir, teardown_temp_dir), -+ cmocka_unit_test_setup_teardown(torture_algorithm_aes128gcm_with_no_hmac_overlap, -+ setup_temp_dir, teardown_temp_dir), -+ }; -+ -+ ssh_init(); -+ -+ torture_filter_tests(tests); -+ rc = cmocka_run_group_tests(tests, -+ setup_files, -+ teardown_files); -+ -+ ssh_finalize(); -+ -+ return rc; -+} --- -2.31.1 - diff -Nru libssh-0.9.5/debian/patches/0004-CVE-2021-3634-Create-a-separate-length-for-session_i.patch libssh-0.9.7/debian/patches/0004-CVE-2021-3634-Create-a-separate-length-for-session_i.patch --- libssh-0.9.5/debian/patches/0004-CVE-2021-3634-Create-a-separate-length-for-session_i.patch 2021-08-28 11:52:11.000000000 +0000 +++ libssh-0.9.7/debian/patches/0004-CVE-2021-3634-Create-a-separate-length-for-session_i.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -From f5211239f918acf405d104b200891ca58130e23e Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 23 Jun 2021 13:16:33 +0200 -Subject: [PATCH] CVE-2021-3634: Create a separate length for session_id - -Normally, the length of session_id and secret_hash is the same, -but if we will get into rekeying with a peer that changes preference -of key exchange algorithm, the new secret hash can be larger or -smaller than the previous session_id causing invalid reads or writes. - -Resolves https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35485 - -Signed-off-by: Jakub Jelen -Reviewed-by: Andreas Schneider - ---- a/include/libssh/crypto.h -+++ b/include/libssh/crypto.h -@@ -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; ---- a/src/gssapi.c -+++ b/src/gssapi.c -@@ -465,8 +465,8 @@ static ssh_buffer ssh_gssapi_build_mic(s - - 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", ---- a/src/kdf.c -+++ b/src/kdf.c -@@ -138,7 +138,7 @@ int sshkdf_derive_key(struct ssh_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) { ---- a/src/kex.c -+++ b/src/kex.c -@@ -1222,11 +1222,13 @@ int ssh_make_sessionid(ssh_session sessi - } - 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; ---- a/src/libcrypto.c -+++ b/src/libcrypto.c -@@ -392,7 +392,7 @@ int ssh_kdf(struct ssh_crypto_struct *cr - 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; - } ---- a/src/messages.c -+++ b/src/messages.c -@@ -708,8 +708,8 @@ static ssh_buffer ssh_msg_userauth_build - - 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, ---- a/src/packet.c -+++ b/src/packet.c -@@ -1899,7 +1899,7 @@ ssh_packet_set_newkeys(ssh_session sessi - - /* 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 +1916,8 @@ ssh_packet_set_newkeys(ssh_session sessi - 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 +1925,8 @@ ssh_packet_set_newkeys(ssh_session sessi - - 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; - } ---- a/src/pki.c -+++ b/src/pki.c -@@ -2328,11 +2328,11 @@ ssh_string ssh_pki_do_sign(ssh_session s - } - - /* 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); -+ ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len); - - /* Fill the input */ - sign_input = ssh_buffer_new(); -@@ -2389,11 +2389,11 @@ ssh_string ssh_pki_do_sign_agent(ssh_ses - } - - /* 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); -+ ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len); - - sig_buf = ssh_buffer_new(); - if (sig_buf == NULL) { ---- a/src/wrapper.c -+++ b/src/wrapper.c -@@ -183,7 +183,7 @@ void crypto_free(struct ssh_crypto_struc - } - #endif - 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) { ---- a/tests/unittests/torture_session_keys.c -+++ b/tests/unittests/torture_session_keys.c -@@ -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, diff -Nru libssh-0.9.5/debian/patches/0005-tests-Simple-reproducer-for-rekeying-with-different-.patch libssh-0.9.7/debian/patches/0005-tests-Simple-reproducer-for-rekeying-with-different-.patch --- libssh-0.9.5/debian/patches/0005-tests-Simple-reproducer-for-rekeying-with-different-.patch 2021-08-28 11:52:11.000000000 +0000 +++ libssh-0.9.7/debian/patches/0005-tests-Simple-reproducer-for-rekeying-with-different-.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,222 +0,0 @@ -From f8817c0c355350cd6ca55a91f815d082b3bd9f73 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Thu, 24 Jun 2021 10:47:33 +0200 -Subject: [PATCH] tests: Simple reproducer for rekeying with different kex - -We do not use SHA1 as it is disabled in many systems - -Verifies CVE-2021-3634 - -Signed-off-by: Jakub Jelen -Reviewed-by: Andreas Schneider ---- - tests/client/torture_rekey.c | 158 ++++++++++++++++++++++++++++++++++- - 1 file changed, 155 insertions(+), 3 deletions(-) - -diff --git a/tests/client/torture_rekey.c b/tests/client/torture_rekey.c -index c599332d..e7813e1e 100644 ---- a/tests/client/torture_rekey.c -+++ b/tests/client/torture_rekey.c -@@ -38,6 +38,8 @@ - #include - #include - -+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 +155,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; - -@@ -234,8 +235,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; -@@ -442,6 +441,153 @@ 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 < 20; i++) { -+ ssh_send_ignore(s->ssh.session, data); -+ ssh_handle_packets(s->ssh.session, 50); -+ } -+ -+ /* 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 < 25; i++) { -+ ssh_send_ignore(s->ssh.session, data); -+ ssh_handle_packets(s->ssh.session, 50); -+ } -+ -+ /* 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) - { -@@ -528,6 +674,9 @@ int torture_run_tests(void) { - cmocka_unit_test_setup_teardown(torture_rekey_send, - session_setup, - session_teardown), -+ cmocka_unit_test_setup_teardown(torture_rekey_different_kex, -+ session_setup, -+ session_teardown), - /* Note, that this modifies the sshd_config */ - cmocka_unit_test_setup_teardown(torture_rekey_server_send, - session_setup, -@@ -537,6 +686,9 @@ int torture_run_tests(void) { - session_setup_sftp_server, - session_teardown), - #endif /* WITH_SFTP */ -+ cmocka_unit_test_setup_teardown(torture_rekey_server_different_kex, -+ session_setup, -+ session_teardown), - /* TODO verify the two rekey are possible and the states are not broken after rekey */ - }; - --- -2.31.1 - diff -Nru libssh-0.9.5/debian/patches/2004-install-static-lib.patch libssh-0.9.7/debian/patches/2004-install-static-lib.patch --- libssh-0.9.5/debian/patches/2004-install-static-lib.patch 2021-08-28 11:52:11.000000000 +0000 +++ libssh-0.9.7/debian/patches/2004-install-static-lib.patch 2023-05-21 18:22:05.000000000 +0000 @@ -3,9 +3,9 @@ --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt -@@ -417,6 +417,13 @@ if (BUILD_STATIC_LIB) - "-DLIBSSH_STATIC" - ) +@@ -419,6 +419,13 @@ if (BUILD_STATIC_LIB) + if (WIN32) + target_compile_definitions(ssh-static PUBLIC "LIBSSH_STATIC") endif (WIN32) + + install(TARGETS @@ -15,5 +15,5 @@ + COMPONENT + libraries) endif (BUILD_STATIC_LIB) - + message(STATUS "Threads_FOUND=${Threads_FOUND}") diff -Nru libssh-0.9.5/debian/patches/series libssh-0.9.7/debian/patches/series --- libssh-0.9.5/debian/patches/series 2021-08-28 11:52:11.000000000 +0000 +++ libssh-0.9.7/debian/patches/series 2023-05-21 18:22:05.000000000 +0000 @@ -1,8 +1,3 @@ -0001-dh-gex-Avoid-memory-leaks.patch -0002-Fix-handshake-bug-with-AEAD-ciphers-and-no-HMAC-over.patch -0003-Add-initial-server-algorithm-test-for-no-HMAC-overla.patch -0004-CVE-2021-3634-Create-a-separate-length-for-session_i.patch -0005-tests-Simple-reproducer-for-rekeying-with-different-.patch 1003-custom-lib-names.patch 2003-disable-expand_tilde_unix-test.patch 2004-install-static-lib.patch diff -Nru libssh-0.9.5/examples/libssh_scp.c libssh-0.9.7/examples/libssh_scp.c --- libssh-0.9.5/examples/libssh_scp.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/examples/libssh_scp.c 2022-05-23 13:08:11.000000000 +0000 @@ -233,7 +233,7 @@ 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)); diff -Nru libssh-0.9.5/examples/sshd_direct-tcpip.c libssh-0.9.7/examples/sshd_direct-tcpip.c --- libssh-0.9.5/examples/sshd_direct-tcpip.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/examples/sshd_direct-tcpip.c 2022-05-23 13:08:11.000000000 +0000 @@ -88,7 +88,11 @@ // 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 @@ 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; diff -Nru libssh-0.9.5/examples/sshnetcat.c libssh-0.9.7/examples/sshnetcat.c --- libssh-0.9.5/examples/sshnetcat.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/examples/sshnetcat.c 2023-05-04 11:39:39.000000000 +0000 @@ -233,9 +233,10 @@ } void cleanup_pcap(void); -void cleanup_pcap(){ +void cleanup_pcap(void) +{ ssh_pcap_file_free(pcap); - pcap=NULL; + pcap = NULL; } #endif diff -Nru libssh-0.9.5/include/libssh/crypto.h libssh-0.9.7/include/libssh/crypto.h --- libssh-0.9.5/include/libssh/crypto.h 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/include/libssh/crypto.h 2022-05-23 13:08:11.000000000 +0000 @@ -126,8 +126,9 @@ 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; diff -Nru libssh-0.9.5/include/libssh/curve25519.h libssh-0.9.7/include/libssh/curve25519.h --- libssh-0.9.5/include/libssh/curve25519.h 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/include/libssh/curve25519.h 2023-05-04 11:40:41.000000000 +0000 @@ -48,6 +48,7 @@ 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); diff -Nru libssh-0.9.5/include/libssh/dh-gex.h libssh-0.9.7/include/libssh/dh-gex.h --- libssh-0.9.5/include/libssh/dh-gex.h 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/include/libssh/dh-gex.h 2023-05-04 11:40:41.000000000 +0000 @@ -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); diff -Nru libssh-0.9.5/include/libssh/dh.h libssh-0.9.7/include/libssh/dh.h --- libssh-0.9.5/include/libssh/dh.h 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/include/libssh/dh.h 2023-05-04 11:40:48.000000000 +0000 @@ -63,8 +63,10 @@ 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 */ diff -Nru libssh-0.9.5/include/libssh/ecdh.h libssh-0.9.7/include/libssh/ecdh.h --- libssh-0.9.5/include/libssh/ecdh.h 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/include/libssh/ecdh.h 2023-05-04 11:40:41.000000000 +0000 @@ -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 diff -Nru libssh-0.9.5/include/libssh/kex.h libssh-0.9.7/include/libssh/kex.h --- libssh-0.9.5/include/libssh/kex.h 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/include/libssh/kex.h 2023-05-04 11:40:37.000000000 +0000 @@ -33,7 +33,7 @@ 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); diff -Nru libssh-0.9.5/include/libssh/libssh.h libssh-0.9.7/include/libssh/libssh.h --- libssh-0.9.5/include/libssh/libssh.h 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/include/libssh/libssh.h 2022-05-23 13:08:11.000000000 +0000 @@ -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 diff -Nru libssh-0.9.5/include/libssh/packet.h libssh-0.9.7/include/libssh/packet.h --- libssh-0.9.5/include/libssh/packet.h 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/include/libssh/packet.h 2022-05-23 13:08:11.000000000 +0000 @@ -80,7 +80,7 @@ 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, diff -Nru libssh-0.9.5/include/libssh/pki.h libssh-0.9.7/include/libssh/pki.h --- libssh-0.9.5/include/libssh/pki.h 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/include/libssh/pki.h 2022-05-23 13:08:11.000000000 +0000 @@ -125,6 +125,8 @@ /* 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); diff -Nru libssh-0.9.5/include/libssh/session.h libssh-0.9.7/include/libssh/session.h --- libssh-0.9.5/include/libssh/session.h 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/include/libssh/session.h 2023-05-04 11:40:48.000000000 +0000 @@ -75,6 +75,11 @@ /* 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 @@ /* 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 @@ 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 @@ /* 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 @@ char *custombanner; unsigned long timeout; /* seconds */ unsigned long timeout_usec; - unsigned int port; + uint16_t port; socket_t fd; int StrictHostKeyChecking; char compressionlevel; diff -Nru libssh-0.9.5/src/ABI/current libssh-0.9.7/src/ABI/current --- libssh-0.9.5/src/ABI/current 2020-09-10 12:44:21.000000000 +0000 +++ libssh-0.9.7/src/ABI/current 2023-05-04 11:41:41.000000000 +0000 @@ -1 +1 @@ -4.8.6 \ No newline at end of file +4.8.8 \ No newline at end of file diff -Nru libssh-0.9.5/src/ABI/libssh-4.8.7.symbols libssh-0.9.7/src/ABI/libssh-4.8.7.symbols --- libssh-0.9.5/src/ABI/libssh-4.8.7.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libssh-0.9.7/src/ABI/libssh-4.8.7.symbols 2022-05-23 13:08:11.000000000 +0000 @@ -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 \ No newline at end of file diff -Nru libssh-0.9.5/src/ABI/libssh-4.8.8.symbols libssh-0.9.7/src/ABI/libssh-4.8.8.symbols --- libssh-0.9.5/src/ABI/libssh-4.8.8.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libssh-0.9.7/src/ABI/libssh-4.8.8.symbols 2023-05-04 11:41:42.000000000 +0000 @@ -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 \ No newline at end of file diff -Nru libssh-0.9.5/src/CMakeLists.txt libssh-0.9.7/src/CMakeLists.txt --- libssh-0.9.5/src/CMakeLists.txt 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/CMakeLists.txt 2022-05-23 13:08:11.000000000 +0000 @@ -16,7 +16,7 @@ ) 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 @@ 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 @@ 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 @@ 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 @@ ) 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 (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) diff -Nru libssh-0.9.5/src/channels.c libssh-0.9.7/src/channels.c --- libssh-0.9.5/src/channels.c 2020-09-10 12:43:04.000000000 +0000 +++ libssh-0.9.7/src/channels.c 2022-05-23 13:08:11.000000000 +0000 @@ -29,6 +29,9 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ #ifndef _WIN32 #include @@ -117,6 +120,13 @@ 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); diff -Nru libssh-0.9.5/src/client.c libssh-0.9.7/src/client.c --- libssh-0.9.5/src/client.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/client.c 2023-05-04 11:40:48.000000000 +0000 @@ -243,10 +243,13 @@ * @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 @@ { 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); - - 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_LOG(SSH_LOG_DEBUG, "session_state=%d", session->session_state); - /* 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; - } + 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_packet_register_socket_callback(session, session->socket); + 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); + + /* 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_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); - ssh_packet_set_default_callbacks(session); - session->session_state = SSH_SESSION_STATE_INITIAL_KEX; + 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); + } + if (ssh_kex_select_methods(session) == SSH_ERROR) + goto error; + set_status(session, 0.8f); + session->session_state = SSH_SESSION_STATE_DH; - 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 the init packet was already sent in previous step, this will be no + * operation */ + if (dh_handshake(session) == SSH_ERROR) { goto error; - default: - ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state); + } + 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 @@ } 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 @@ } 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 " diff -Nru libssh-0.9.5/src/config.c libssh-0.9.7/src/config.c --- libssh-0.9.5/src/config.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/config.c 2022-05-23 13:08:11.000000000 +0000 @@ -425,6 +425,7 @@ 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) { diff -Nru libssh-0.9.5/src/connect.c libssh-0.9.7/src/connect.c --- libssh-0.9.5/src/connect.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/connect.c 2022-05-23 13:08:11.000000000 +0000 @@ -29,6 +29,9 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ #include "libssh/libssh.h" #include "libssh/misc.h" diff -Nru libssh-0.9.5/src/curve25519.c libssh-0.9.7/src/curve25519.c --- libssh-0.9.5/src/curve25519.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/curve25519.c 2023-05-04 11:40:41.000000000 +0000 @@ -172,6 +172,11 @@ 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 @@ (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 @@ */ 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 @@ 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 @@ /* 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 @@ 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; diff -Nru libssh-0.9.5/src/dh-gex.c libssh-0.9.7/src/dh-gex.c --- libssh-0.9.5/src/dh-gex.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/dh-gex.c 2023-05-04 11:40:41.000000000 +0000 @@ -238,6 +238,11 @@ 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 @@ (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 @@ 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 @@ return SSH_PACKET_USED; error: + SSH_STRING_FREE(pubkey_blob); ssh_dh_cleanup(session->next_crypto); session->session_state = SSH_SESSION_STATE_ERROR; diff -Nru libssh-0.9.5/src/dh.c libssh-0.9.7/src/dh.c --- libssh-0.9.5/src/dh.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/dh.c 2023-05-04 11:40:41.000000000 +0000 @@ -342,6 +342,11 @@ 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 @@ (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 @@ 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; } diff -Nru libssh-0.9.5/src/ecdh.c libssh-0.9.7/src/ecdh.c --- libssh-0.9.5/src/ecdh.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/ecdh.c 2023-05-04 11:40:41.000000000 +0000 @@ -43,6 +43,11 @@ .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 @@ (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"); diff -Nru libssh-0.9.5/src/external/ed25519.c libssh-0.9.7/src/external/ed25519.c --- libssh-0.9.5/src/external/ed25519.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/external/ed25519.c 2022-05-23 13:08:11.000000000 +0000 @@ -77,8 +77,8 @@ } -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 @@ 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 @@ uint64_t *mlen, const unsigned char *sm, uint64_t smlen, - const unsigned char *pk) + const ed25519_pubkey pk) { unsigned int i; int ret; diff -Nru libssh-0.9.5/src/getpass.c libssh-0.9.7/src/getpass.c --- libssh-0.9.5/src/getpass.c 2020-01-27 15:45:32.000000000 +0000 +++ libssh-0.9.7/src/getpass.c 2022-05-23 13:08:11.000000000 +0000 @@ -255,7 +255,11 @@ /* 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 @@ /* 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) { diff -Nru libssh-0.9.5/src/gssapi.c libssh-0.9.7/src/gssapi.c --- libssh-0.9.5/src/gssapi.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/gssapi.c 2023-05-04 11:39:39.000000000 +0000 @@ -223,6 +223,7 @@ "indicate mechs", maj_stat, min_stat); + gss_release_oid_set(&min_stat, &both_supported); return SSH_ERROR; } @@ -259,8 +260,10 @@ 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 @@ "importing name", maj_stat, min_stat); + gss_release_oid_set(&min_stat, &both_supported); return -1; } @@ -338,6 +342,7 @@ 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 @@ "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 @@ (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 @@ 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 @@ 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 @@ 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 @@ */ 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 @@ 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_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 @@ 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 @@ 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_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; diff -Nru libssh-0.9.5/src/init.c libssh-0.9.7/src/init.c --- libssh-0.9.5/src/init.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/init.c 2023-05-04 11:39:39.000000000 +0000 @@ -269,7 +269,7 @@ * * @see ssh_init() */ -bool is_ssh_initialized() { +bool is_ssh_initialized(void) { bool is_initialized = false; diff -Nru libssh-0.9.5/src/kdf.c libssh-0.9.7/src/kdf.c --- libssh-0.9.5/src/kdf.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/kdf.c 2022-05-23 13:08:11.000000000 +0000 @@ -138,7 +138,7 @@ 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) { diff -Nru libssh-0.9.5/src/kex.c libssh-0.9.7/src/kex.c --- libssh-0.9.5/src/kex.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/kex.c 2023-05-04 11:40:48.000000000 +0000 @@ -28,6 +28,7 @@ #include #include +#include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/dh.h" @@ -305,6 +306,10 @@ 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 @@ 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 @@ (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 @@ 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 @@ 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 @@ * that its value is included when computing the session ID (see * 'make_sessionid'). */ - if (server_kex) { - rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows); - if (rc != 1) { - goto error; - } + 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_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; - } + 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) { /* * 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 @@ * 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 @@ 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 @@ (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 @@ 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 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 @@ 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 @@ } 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 @@ /* 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; - - 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; - } +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; + + /* 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; + } + + 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; + } + + ssh_list_kex(kex); - 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; + } - 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; } - if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) { - goto error; + rc = ssh_buffer_pack(session->out_buffer, + "bd", + first_kex_packet_follows, + 0); + if (rc != SSH_OK) { + goto error; } - if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) { - goto error; + + /* 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; } - SSH_STRING_FREE(str); - str = NULL; - } - rc = ssh_buffer_pack(session->out_buffer, - "bd", - 0, - 0); - if (rc != SSH_OK) { - goto error; - } + rc = ssh_packet_send(session); + if (rc == SSH_ERROR) { + return -1; + } - if (ssh_packet_send(session) == 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 @@ } 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 @@ 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 @@ 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 @@ } 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; diff -Nru libssh-0.9.5/src/knownhosts.c libssh-0.9.7/src/knownhosts.c --- libssh-0.9.5/src/knownhosts.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/knownhosts.c 2022-05-23 13:08:11.000000000 +0000 @@ -372,6 +372,7 @@ list = ssh_list_new(); if (list == NULL) { + ssh_set_error_oom(session); SAFE_FREE(host_port); return NULL; } diff -Nru libssh-0.9.5/src/libcrypto.c libssh-0.9.7/src/libcrypto.c --- libssh-0.9.5/src/libcrypto.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/libcrypto.c 2022-05-23 13:08:11.000000000 +0000 @@ -392,7 +392,7 @@ 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; } diff -Nru libssh-0.9.5/src/libmbedcrypto.c libssh-0.9.7/src/libmbedcrypto.c --- libssh-0.9.5/src/libmbedcrypto.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/libmbedcrypto.c 2022-05-23 13:08:11.000000000 +0000 @@ -687,7 +687,7 @@ } 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_cbc(struct ssh_cipher_struct *cipher, void *in, void *out, - unsigned long len) + size_t len) { size_t outlen = 0; int rc = 0; diff -Nru libssh-0.9.5/src/messages.c libssh-0.9.7/src/messages.c --- libssh-0.9.5/src/messages.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/messages.c 2022-05-23 13:08:11.000000000 +0000 @@ -513,24 +513,30 @@ * @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; - - 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); +ssh_message ssh_message_get(ssh_session session) +{ + ssh_message msg = NULL; + int rc; + + 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 @@ 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, diff -Nru libssh-0.9.5/src/misc.c libssh-0.9.7/src/misc.c --- libssh-0.9.5/src/misc.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/misc.c 2023-05-04 11:39:39.000000000 +0000 @@ -1164,14 +1164,13 @@ 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: diff -Nru libssh-0.9.5/src/packet.c libssh-0.9.7/src/packet.c --- libssh-0.9.5/src/packet.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/packet.c 2023-05-04 11:40:36.000000000 +0000 @@ -366,6 +366,11 @@ * - 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 @@ /* * 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 @@ 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 @@ 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 @@ /* * 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 @@ /* * 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 @@ } } -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 @@ /** @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 @@ /* 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 @@ 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 @@ 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; } diff -Nru libssh-0.9.5/src/packet_cb.c libssh-0.9.7/src/packet_cb.c --- libssh-0.9.5/src/packet_cb.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/packet_cb.c 2023-05-04 11:40:23.000000000 +0000 @@ -129,6 +129,8 @@ } 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 @@ 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 @@ 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; } diff -Nru libssh-0.9.5/src/pki.c libssh-0.9.7/src/pki.c --- libssh-0.9.5/src/pki.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/pki.c 2022-05-23 13:08:11.000000000 +0000 @@ -1160,6 +1160,10 @@ 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 @@ 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 @@ } /* 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 @@ } /* 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) { diff -Nru libssh-0.9.5/src/pki_crypto.c libssh-0.9.7/src/pki_crypto.c --- libssh-0.9.5/src/pki_crypto.c 2020-09-10 12:43:04.000000000 +0000 +++ libssh-0.9.7/src/pki_crypto.c 2023-05-04 11:41:08.000000000 +0000 @@ -831,7 +831,12 @@ 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 @@ const unsigned char *raw_sig_data = NULL; size_t raw_sig_len; + int rc; DSA_SIG *dsa_sig; @@ -1439,7 +1445,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } /* 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 @@ } /* 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 @@ } #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; } diff -Nru libssh-0.9.5/src/pki_ed25519_common.c libssh-0.9.7/src/pki_ed25519_common.c --- libssh-0.9.5/src/pki_ed25519_common.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/pki_ed25519_common.c 2022-05-23 13:08:11.000000000 +0000 @@ -214,6 +214,7 @@ 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 @@ } #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; } diff -Nru libssh-0.9.5/src/pki_gcrypt.c libssh-0.9.7/src/pki_gcrypt.c --- libssh-0.9.5/src/pki_gcrypt.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/pki_gcrypt.c 2022-05-23 13:08:11.000000000 +0000 @@ -1765,6 +1765,7 @@ 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 @@ 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 @@ 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 R; ssh_string S; ssh_buffer b; - int rc; b = ssh_buffer_new(); if (b == NULL) { @@ -1885,9 +1892,13 @@ 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 diff -Nru libssh-0.9.5/src/pki_mbedcrypto.c libssh-0.9.7/src/pki_mbedcrypto.c --- libssh-0.9.5/src/pki_mbedcrypto.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/pki_mbedcrypto.c 2022-05-23 13:08:11.000000000 +0000 @@ -832,8 +832,13 @@ 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 @@ 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; } diff -Nru libssh-0.9.5/src/server.c libssh-0.9.7/src/server.c --- libssh-0.9.5/src/server.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/server.c 2023-05-04 11:40:47.000000000 +0000 @@ -92,7 +92,11 @@ 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 @@ * @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) { + 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); + 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; - } - 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); + /* 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) { - /* 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) { + rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); + if (rc != SSH_OK) { 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; + 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); + } + 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 @@ * @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 @@ } #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 @@ 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 @@ } /* 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 @@ 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 */ diff -Nru libssh-0.9.5/src/sftp.c libssh-0.9.7/src/sftp.c --- libssh-0.9.5/src/sftp.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/sftp.c 2022-05-23 13:08:11.000000000 +0000 @@ -32,6 +32,9 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ #include #include #include @@ -173,32 +176,56 @@ 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); - SAFE_FREE(sftp); + sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct)); + if (sftp->read_packet == NULL) { + ssh_set_error_oom(session); + goto error; + } - return NULL; - } + 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; - sftp->session = session; - sftp->channel = channel; + return sftp; - 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; } #ifdef WITH_SERVER diff -Nru libssh-0.9.5/src/threads/winlocks.c libssh-0.9.7/src/threads/winlocks.c --- libssh-0.9.5/src/threads/winlocks.c 2020-01-27 15:45:32.000000000 +0000 +++ libssh-0.9.7/src/threads/winlocks.c 2022-05-23 13:08:11.000000000 +0000 @@ -26,6 +26,7 @@ #include #include #include +#include static int ssh_winlock_mutex_init (void **priv) { diff -Nru libssh-0.9.5/src/token.c libssh-0.9.7/src/token.c --- libssh-0.9.5/src/token.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/src/token.c 2023-05-04 11:39:39.000000000 +0000 @@ -87,7 +87,7 @@ return NULL; } - tokens->buffer= strdup(chain); + tokens->buffer = strdup(chain); if (tokens->buffer == NULL) { goto error; } diff -Nru libssh-0.9.5/src/wrapper.c libssh-0.9.7/src/wrapper.c --- libssh-0.9.5/src/wrapper.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/src/wrapper.c 2023-05-04 11:39:39.000000000 +0000 @@ -147,15 +147,16 @@ 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 @@ 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) { diff -Nru libssh-0.9.5/tests/client/CMakeLists.txt libssh-0.9.7/tests/client/CMakeLists.txt --- libssh-0.9.5/tests/client/CMakeLists.txt 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/tests/client/CMakeLists.txt 2022-05-23 13:08:11.000000000 +0000 @@ -37,6 +37,7 @@ endif() set(LIBSSH_CLIENT_TESTS ${LIBSSH_CLIENT_TESTS} + torture_sftp_init torture_sftp_ext torture_sftp_canonicalize_path torture_sftp_dir diff -Nru libssh-0.9.5/tests/client/torture_algorithms.c libssh-0.9.7/tests/client/torture_algorithms.c --- libssh-0.9.5/tests/client/torture_algorithms.c 2020-09-10 12:43:04.000000000 +0000 +++ libssh-0.9.7/tests/client/torture_algorithms.c 2022-05-23 13:08:11.000000000 +0000 @@ -45,6 +45,16 @@ 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 @@ 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 @@ "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 @@ #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(); diff -Nru libssh-0.9.5/tests/client/torture_auth.c libssh-0.9.7/tests/client/torture_auth.c --- libssh-0.9.5/tests/client/torture_auth.c 2020-09-10 12:43:04.000000000 +0000 +++ libssh-0.9.7/tests/client/torture_auth.c 2023-05-04 11:39:39.000000000 +0000 @@ -200,7 +200,8 @@ 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_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 @@ "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_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 @@ "ssh-rsa-cert-v01@openssh.com"); assert_int_equal(rc, SSH_OK); } +#endif /* OPENSSH_VERSION_MAJOR < 8.1 */ torture_auth_agent_nonblocking(state); } diff -Nru libssh-0.9.5/tests/client/torture_rekey.c libssh-0.9.7/tests/client/torture_rekey.c --- libssh-0.9.5/tests/client/torture_rekey.c 2020-09-10 12:43:04.000000000 +0000 +++ libssh-0.9.7/tests/client/torture_rekey.c 2023-05-04 11:40:51.000000000 +0000 @@ -38,6 +38,10 @@ #include #include +#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 @@ 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 @@ 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 @@ 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 @@ 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 @@ #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 @@ 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(); diff -Nru libssh-0.9.5/tests/client/torture_sftp_init.c libssh-0.9.7/tests/client/torture_sftp_init.c --- libssh-0.9.5/tests/client/torture_sftp_init.c 1970-01-01 00:00:00.000000000 +0000 +++ libssh-0.9.7/tests/client/torture_sftp_init.c 2022-05-23 13:08:11.000000000 +0000 @@ -0,0 +1,106 @@ +#include "config.h" + +#define LIBSSH_STATIC + +#include "torture.h" +#include "sftp.c" + +#include +#include +#include + +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; +} diff -Nru libssh-0.9.5/tests/pkd/pkd_hello.c libssh-0.9.7/tests/pkd/pkd_hello.c --- libssh-0.9.5/tests/pkd/pkd_hello.c 2020-09-10 12:43:04.000000000 +0000 +++ libssh-0.9.7/tests/pkd/pkd_hello.c 2022-05-23 13:08:11.000000000 +0000 @@ -392,45 +392,37 @@ #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 @@ #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 @@ 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 @@ 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 diff -Nru libssh-0.9.5/tests/pkd/pkd_keyutil.c libssh-0.9.7/tests/pkd/pkd_keyutil.c --- libssh-0.9.5/tests/pkd/pkd_keyutil.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/tests/pkd/pkd_keyutil.c 2023-05-04 11:39:39.000000000 +0000 @@ -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 @@ 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 @@ } #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 @@ } #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 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 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 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 @@ assert_int_equal(rc, 0); } -void cleanup_dropbear_client_rsa_key() { +void cleanup_dropbear_client_rsa_key(void) { unlink(DROPBEAR_RSA_TESTKEY); } diff -Nru libssh-0.9.5/tests/server/torture_server_config.c libssh-0.9.7/tests/server/torture_server_config.c --- libssh-0.9.5/tests/server/torture_server_config.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/tests/server/torture_server_config.c 2023-05-04 11:39:39.000000000 +0000 @@ -285,9 +285,7 @@ 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 @@ /* 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", diff -Nru libssh-0.9.5/tests/torture.c libssh-0.9.7/tests/torture.c --- libssh-0.9.5/tests/torture.c 2020-09-10 12:43:04.000000000 +0000 +++ libssh-0.9.7/tests/torture.c 2023-05-04 11:39:39.000000000 +0000 @@ -250,8 +250,12 @@ 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 @@ "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 @@ #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 @@ } 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 @@ 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 @@ "\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 @@ "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 @@ "\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 @@ "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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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); - - 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; - } + rc = torture_terminate_process(s->srv_pidfile); + assert_return_code(rc, errno); - /* 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 @@ 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); } diff -Nru libssh-0.9.5/tests/torture.h libssh-0.9.7/tests/torture.h --- libssh-0.9.5/tests/torture.h 2020-09-10 12:43:04.000000000 +0000 +++ libssh-0.9.7/tests/torture.h 2022-05-23 13:08:11.000000000 +0000 @@ -111,6 +111,7 @@ 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); diff -Nru libssh-0.9.5/tests/unittests/torture_callbacks.c libssh-0.9.7/tests/unittests/torture_callbacks.c --- libssh-0.9.5/tests/unittests/torture_callbacks.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/tests/unittests/torture_callbacks.c 2022-05-23 13:08:11.000000000 +0000 @@ -138,6 +138,9 @@ }; (void)state; + + assert_non_null(list); + ssh_callbacks_init(&c1); ssh_callbacks_init(&c2); ssh_callbacks_init(&c3); @@ -213,6 +216,8 @@ (void)state; /* unused */ + assert_non_null(list); + ssh_callbacks_init(&c1); ssh_callbacks_init(&c2); diff -Nru libssh-0.9.5/tests/unittests/torture_misc.c libssh-0.9.7/tests/unittests/torture_misc.c --- libssh-0.9.5/tests/unittests/torture_misc.c 2020-09-10 12:43:02.000000000 +0000 +++ libssh-0.9.7/tests/unittests/torture_misc.c 2022-05-23 13:08:11.000000000 +0000 @@ -209,7 +209,8 @@ 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)); diff -Nru libssh-0.9.5/tests/unittests/torture_packet_filter.c libssh-0.9.7/tests/unittests/torture_packet_filter.c --- libssh-0.9.5/tests/unittests/torture_packet_filter.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/tests/unittests/torture_packet_filter.c 2022-05-23 13:08:11.000000000 +0000 @@ -517,12 +517,108 @@ 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) }; diff -Nru libssh-0.9.5/tests/unittests/torture_pki_ed25519.c libssh-0.9.7/tests/unittests/torture_pki_ed25519.c --- libssh-0.9.5/tests/unittests/torture_pki_ed25519.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/tests/unittests/torture_pki_ed25519.c 2022-05-23 13:08:11.000000000 +0000 @@ -796,7 +796,8 @@ 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 @@ /* 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); diff -Nru libssh-0.9.5/tests/unittests/torture_session_keys.c libssh-0.9.7/tests/unittests/torture_session_keys.c --- libssh-0.9.5/tests/unittests/torture_session_keys.c 2020-05-07 11:51:36.000000000 +0000 +++ libssh-0.9.7/tests/unittests/torture_session_keys.c 2022-05-23 13:08:11.000000000 +0000 @@ -48,8 +48,9 @@ }; 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 @@ 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);