mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 04:40:31 +09:00
Compare commits
307 Commits
libssh-0.9
...
libssh-0.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70fef935b2 | ||
|
|
b3d19cc31d | ||
|
|
05de7cb6ac | ||
|
|
b733df6ddc | ||
|
|
18576cf98f | ||
|
|
0c855d2949 | ||
|
|
aaa3d4fc7d | ||
|
|
c4f05c28aa | ||
|
|
abcf9699aa | ||
|
|
6887a5bb20 | ||
|
|
85ddd8b34e | ||
|
|
4637c87f2d | ||
|
|
d1e1aea0b6 | ||
|
|
e9741edcde | ||
|
|
1529bbd7ac | ||
|
|
27e39655c5 | ||
|
|
1b5e183544 | ||
|
|
fef76366db | ||
|
|
cef34a78ef | ||
|
|
cf1c67ddb4 | ||
|
|
e72f58811f | ||
|
|
b923d25fef | ||
|
|
545724b7df | ||
|
|
9844dd5f79 | ||
|
|
cd8ef68b84 | ||
|
|
cee5f9f69c | ||
|
|
acfa6e3cac | ||
|
|
3f92520c74 | ||
|
|
587166577f | ||
|
|
6a7c1f4e5d | ||
|
|
dd899b7591 | ||
|
|
6c85771200 | ||
|
|
2830726c53 | ||
|
|
e8c959084f | ||
|
|
a94ac4c080 | ||
|
|
7f20bbca62 | ||
|
|
761ba97145 | ||
|
|
5d8c346225 | ||
|
|
754048b419 | ||
|
|
7b44e23e6f | ||
|
|
c26414972a | ||
|
|
31a33fd2fd | ||
|
|
3beac46361 | ||
|
|
fea290212a | ||
|
|
81320d35f3 | ||
|
|
cb8245a0e4 | ||
|
|
fd1add66cf | ||
|
|
ea075e3f2e | ||
|
|
6b89f4d206 | ||
|
|
da6d026c12 | ||
|
|
240bda21dc | ||
|
|
f3652f6da0 | ||
|
|
d3060bc84e | ||
|
|
948bcb773e | ||
|
|
64b3e358f9 | ||
|
|
2422081e55 | ||
|
|
a10aeb9490 | ||
|
|
a629f687cd | ||
|
|
2dda3514d1 | ||
|
|
c954ff4b2c | ||
|
|
7609ac60a1 | ||
|
|
2356152329 | ||
|
|
180cfd0799 | ||
|
|
3e51232c69 | ||
|
|
d8fea02d2b | ||
|
|
265b826f78 | ||
|
|
c2c5604077 | ||
|
|
51a0adfc18 | ||
|
|
b78db5f5d8 | ||
|
|
5e2a2be6cd | ||
|
|
7cf3866744 | ||
|
|
81b17de7f7 | ||
|
|
a2a79ec68a | ||
|
|
08f96dcca6 | ||
|
|
435f45291d | ||
|
|
09e9167329 | ||
|
|
effb421a88 | ||
|
|
098ae8c4bd | ||
|
|
04824e2f5e | ||
|
|
0a5b93e479 | ||
|
|
761a4d5fa2 | ||
|
|
bd9a4e2498 | ||
|
|
67b7b383b2 | ||
|
|
1736cb0567 | ||
|
|
36e56dcd93 | ||
|
|
f834e10a47 | ||
|
|
deb9fc015e | ||
|
|
f8314af85a | ||
|
|
1fc8266fcb | ||
|
|
0cceefd49d | ||
|
|
8af24251c1 | ||
|
|
645106a1ca | ||
|
|
6672a457fb | ||
|
|
737ba4a680 | ||
|
|
d4b07d1675 | ||
|
|
d462cc30c9 | ||
|
|
c7f35f4d49 | ||
|
|
6a1dc7df87 | ||
|
|
41e54ce042 | ||
|
|
a7c0ccd35e | ||
|
|
9ec6923479 | ||
|
|
d9e37c4e09 | ||
|
|
56ebe3c7d0 | ||
|
|
e0c7d78a39 | ||
|
|
74e162c67f | ||
|
|
039054ea6e | ||
|
|
1da78553dc | ||
|
|
c5dfc2d5ce | ||
|
|
f760781cb8 | ||
|
|
8316bf1177 | ||
|
|
e631ebb3e2 | ||
|
|
dcc0b9d7aa | ||
|
|
b1bbd20dfa | ||
|
|
929a6b7d50 | ||
|
|
88d676cf1a | ||
|
|
b93c9ae641 | ||
|
|
a77d89d3ea | ||
|
|
4276560680 | ||
|
|
a7ce241652 | ||
|
|
1c7cfaba9c | ||
|
|
98c91e68fa | ||
|
|
078cb4c6f3 | ||
|
|
5972d7a98e | ||
|
|
d35fdfbdb4 | ||
|
|
7ee7ff94ba | ||
|
|
c42aab0122 | ||
|
|
69e97057c7 | ||
|
|
3025eeace3 | ||
|
|
ffb0007768 | ||
|
|
a99b8a3979 | ||
|
|
0a450f0251 | ||
|
|
9e9df61244 | ||
|
|
958afb1c6a | ||
|
|
e510de0315 | ||
|
|
34c596182d | ||
|
|
1a18d9cce2 | ||
|
|
4c83d19c48 | ||
|
|
673bf1ff09 | ||
|
|
fe1fe49617 | ||
|
|
316f46f833 | ||
|
|
0dd71375e7 | ||
|
|
9a10cef920 | ||
|
|
6fcd0940e3 | ||
|
|
0c8dbf5c81 | ||
|
|
a0aa62fffe | ||
|
|
402c922a9e | ||
|
|
112e32ba86 | ||
|
|
e2c5f5c7d1 | ||
|
|
6dcfa25c9b | ||
|
|
eed8d8e957 | ||
|
|
1935e15cd4 | ||
|
|
238dbabef8 | ||
|
|
ee7ee2404a | ||
|
|
6205cad534 | ||
|
|
d5a37e2bf5 | ||
|
|
226d2a16b0 | ||
|
|
46105f4aa6 | ||
|
|
62f7004d5a | ||
|
|
d7358ee5a7 | ||
|
|
ec8cedd803 | ||
|
|
92124ae65a | ||
|
|
ea198fee43 | ||
|
|
393cd36c01 | ||
|
|
93bf0ab6a3 | ||
|
|
251f60c031 | ||
|
|
b33dcda94d | ||
|
|
f0335d1b59 | ||
|
|
ed87c2221c | ||
|
|
ac2f4853bb | ||
|
|
64ce53fdba | ||
|
|
295739e0c8 | ||
|
|
101ffd70a7 | ||
|
|
45878b131c | ||
|
|
21adb54dc6 | ||
|
|
13fa009a2e | ||
|
|
8600015b3e | ||
|
|
8f20ece14f | ||
|
|
d15fa16213 | ||
|
|
a91e5f7585 | ||
|
|
7b7b2acd23 | ||
|
|
1c66217875 | ||
|
|
95eb071c22 | ||
|
|
d117de188f | ||
|
|
ae68f13a78 | ||
|
|
ad49f0a556 | ||
|
|
975eb87c19 | ||
|
|
a888b65ff5 | ||
|
|
375724bafe | ||
|
|
b7b9c6d5b9 | ||
|
|
1c7efb7b46 | ||
|
|
128fb03d7e | ||
|
|
994b653161 | ||
|
|
9817d13de0 | ||
|
|
41cd5f4012 | ||
|
|
e6fdb28faf | ||
|
|
b21cba0c3c | ||
|
|
7498167e6c | ||
|
|
f1b1355975 | ||
|
|
83a8c87b08 | ||
|
|
48c34509f2 | ||
|
|
0469458194 | ||
|
|
d0dc57be06 | ||
|
|
7f7c249e15 | ||
|
|
a64aa7406b | ||
|
|
81650a7652 | ||
|
|
26a29ee362 | ||
|
|
7f5d851f6e | ||
|
|
b1f4b6ffec | ||
|
|
1788f98543 | ||
|
|
413ee92572 | ||
|
|
d6664d248b | ||
|
|
14e19ee37e | ||
|
|
7fe7203f06 | ||
|
|
02ed74711f | ||
|
|
55cbb64f44 | ||
|
|
acc109eb67 | ||
|
|
54e7c8d21a | ||
|
|
a8b2a874de | ||
|
|
deaf3f3195 | ||
|
|
123e8448e6 | ||
|
|
ba563611ee | ||
|
|
69b4860404 | ||
|
|
564e298989 | ||
|
|
5a41514d8d | ||
|
|
8f0ab53b7b | ||
|
|
0016888942 | ||
|
|
ce045cf5ed | ||
|
|
5ae2a05ca1 | ||
|
|
8dcaf4bfa3 | ||
|
|
6c392befcc | ||
|
|
5b55eefb96 | ||
|
|
9fc8e095ce | ||
|
|
65918ec38a | ||
|
|
2caedc0d0d | ||
|
|
0187b71912 | ||
|
|
053a23b50d | ||
|
|
2b52a8df4d | ||
|
|
fa33b61102 | ||
|
|
563e1fc821 | ||
|
|
f6c8e87c3e | ||
|
|
0ff2cfe0e6 | ||
|
|
828f8dd106 | ||
|
|
5f5a6e15b3 | ||
|
|
e5b403f83a | ||
|
|
11cb618c75 | ||
|
|
338e6cece5 | ||
|
|
4603105e0b | ||
|
|
ee1f8512a4 | ||
|
|
278ed59501 | ||
|
|
9e9d35164b | ||
|
|
a011f853ed | ||
|
|
c98d024b9a | ||
|
|
d5b10f569d | ||
|
|
31f65d1ffb | ||
|
|
44e37c2546 | ||
|
|
35188b3843 | ||
|
|
76aeedad1b | ||
|
|
66419896f7 | ||
|
|
0cb50ef31a | ||
|
|
88e40516c9 | ||
|
|
f45aa46322 | ||
|
|
dbf757e3e8 | ||
|
|
0a404349bc | ||
|
|
e9b74b5cb7 | ||
|
|
6a0cbc73bd | ||
|
|
40ee7d2b38 | ||
|
|
7db565601d | ||
|
|
95faeb498f | ||
|
|
db97435a41 | ||
|
|
c72a3495d0 | ||
|
|
f2487f07f5 | ||
|
|
675d85e538 | ||
|
|
dfd73d7cb2 | ||
|
|
db68813cb9 | ||
|
|
affb43a45f | ||
|
|
1e71951a51 | ||
|
|
297aed60c4 | ||
|
|
4e5dfd677e | ||
|
|
34fd4ebfc3 | ||
|
|
0080ac1f03 | ||
|
|
dd4eb4a288 | ||
|
|
a967258649 | ||
|
|
e0e3636c60 | ||
|
|
c0e5393927 | ||
|
|
36bdcb85b3 | ||
|
|
cf34ba92bf | ||
|
|
f5f547f35e | ||
|
|
1eed0cbd3d | ||
|
|
1668bd8baf | ||
|
|
245be62438 | ||
|
|
8ce782f9ec | ||
|
|
db34fd44fb | ||
|
|
00dd3f864b | ||
|
|
52550994c5 | ||
|
|
182d363b27 | ||
|
|
f9189a8a9a | ||
|
|
56c079cbb2 | ||
|
|
ab24d64241 | ||
|
|
7856ae594b | ||
|
|
eeb9ae15c7 | ||
|
|
8837d32d92 | ||
|
|
0408d8d851 | ||
|
|
bab8d84d13 | ||
|
|
6ee159d9d2 | ||
|
|
71ff06d04a | ||
|
|
7851f216af | ||
|
|
9b316fe8b9 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,6 +5,7 @@
|
||||
*~$
|
||||
cscope.*
|
||||
compile_commands.json
|
||||
/.cache
|
||||
/.clangd
|
||||
tags
|
||||
/build
|
||||
|
||||
137
.gitlab-ci.yml
137
.gitlab-ci.yml
@@ -2,6 +2,8 @@ variables:
|
||||
BUILD_IMAGES_PROJECT: libssh/build-images
|
||||
FEDORA_BUILD: buildenv-fedora
|
||||
CENTOS7_BUILD: buildenv-centos7
|
||||
CENTOS8_BUILD: buildenv-c8s
|
||||
CENTOS9_BUILD: buildenv-c9s
|
||||
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
||||
MINGW_BUILD: buildenv-mingw
|
||||
|
||||
@@ -25,6 +27,47 @@ centos7/openssl_1.0.x/x86_64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
centos8/openssl_1.1.1/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS8_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_BLOWFISH_CIPHER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
centos9/openssl_3.0.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||
script:
|
||||
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_BLOWFISH_CIPHER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
fedora/openssl_1.1.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
@@ -47,8 +90,8 @@ fedora/openssl_1.1.x/x86_64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
fedora/openssl_1.1.x/x86_64/fips:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
centos8/openssl_1.1.1/x86_64/fips:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS8_BUILD
|
||||
script:
|
||||
- echo 1 > /etc/system-fips
|
||||
- update-crypto-policies --set FIPS
|
||||
@@ -153,6 +196,8 @@ fedora/undefined-sanitizer:
|
||||
- obj/
|
||||
|
||||
fedora/csbuild:
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- |
|
||||
@@ -195,11 +240,13 @@ freebsd/x86_64:
|
||||
make && ctest --output-on-failure
|
||||
tags:
|
||||
- freebsd
|
||||
- private
|
||||
except:
|
||||
- tags
|
||||
only:
|
||||
- branches@libssh/libssh-mirror
|
||||
- branches@cryptomilk/libssh-mirror
|
||||
- branches@jjelen/libssh-mirror
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
@@ -453,57 +500,55 @@ tumbleweed/static-analysis:
|
||||
paths:
|
||||
- obj/scan
|
||||
|
||||
visualstudio/x86_64:
|
||||
###############################################################################
|
||||
# Visual Studio builds #
|
||||
###############################################################################
|
||||
.vs:
|
||||
stage: test
|
||||
cache:
|
||||
key: vcpkg.${CI_JOB_NAME}
|
||||
paths:
|
||||
- .vcpkg
|
||||
variables:
|
||||
ErrorActionPreference: STOP
|
||||
script:
|
||||
- $env:VCPKG_DEFAULT_TRIPLET="x64-windows"
|
||||
- cd obj
|
||||
- cmake
|
||||
-A x64
|
||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON ..
|
||||
- cmake --build .
|
||||
- ctest --output-on-failure
|
||||
- cmake --build .
|
||||
- ctest --output-on-failure
|
||||
tags:
|
||||
- vs2017
|
||||
- windows
|
||||
- windows
|
||||
- shared-windows
|
||||
except:
|
||||
- tags
|
||||
only:
|
||||
- branches@libssh/libssh-mirror
|
||||
- branches@ansasaki/libssh-mirror
|
||||
- branches@cryptomilk/libssh-mirror
|
||||
- branches@jjelen/libssh-mirror
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
before_script:
|
||||
- If (!(test-path .vcpkg\archives)) { mkdir -p .vcpkg\archives }
|
||||
- $env:VCPKG_DEFAULT_BINARY_CACHE="$PWD\.vcpkg\archives"
|
||||
- echo $env:VCPKG_DEFAULT_BINARY_CACHE
|
||||
- $env:VCPKG_DEFAULT_TRIPLET="$TRIPLET-windows"
|
||||
- vcpkg install cmocka
|
||||
- vcpkg install openssl
|
||||
- vcpkg install zlib
|
||||
- vcpkg integrate install
|
||||
- mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1}
|
||||
- cmake
|
||||
-A $PLATFORM
|
||||
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON ..
|
||||
|
||||
visualstudio/x86_64:
|
||||
extends: .vs
|
||||
variables:
|
||||
PLATFORM: "x64"
|
||||
TRIPLET: "x64"
|
||||
|
||||
visualstudio/x86:
|
||||
script:
|
||||
- $env:VCPKG_DEFAULT_TRIPLET="x86-windows"
|
||||
- cd obj
|
||||
- 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/
|
||||
extends: .vs
|
||||
variables:
|
||||
PLATFORM: "win32"
|
||||
TRIPLET: "x86"
|
||||
|
||||
@@ -10,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
|
||||
project(libssh VERSION 0.9.2 LANGUAGES C)
|
||||
project(libssh VERSION 0.9.7 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -22,7 +22,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.8.3")
|
||||
set(LIBRARY_VERSION "4.8.8")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
@@ -59,7 +59,13 @@ elseif(WITH_MBEDTLS)
|
||||
endif (NOT MBEDTLS_FOUND)
|
||||
else (WITH_GCRYPT)
|
||||
find_package(OpenSSL)
|
||||
if (NOT OPENSSL_FOUND)
|
||||
if (OPENSSL_FOUND)
|
||||
# On CMake < 3.16, OPENSSL_CRYPTO_LIBRARIES is usually a synonym for OPENSSL_CRYPTO_LIBRARY, but is not defined
|
||||
# when building on Windows outside of Cygwin. We provide the synonym here, if FindOpenSSL didn't define it already.
|
||||
if (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
|
||||
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
endif (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
|
||||
else (OPENSSL_FOUND)
|
||||
find_package(GCrypt)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
find_package(MbedTLS)
|
||||
@@ -67,7 +73,7 @@ else (WITH_GCRYPT)
|
||||
message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
|
||||
endif (NOT MBEDTLS_FOUND)
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
endif (NOT OPENSSL_FOUND)
|
||||
endif (OPENSSL_FOUND)
|
||||
endif(WITH_GCRYPT)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
@@ -203,10 +209,10 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
endif(UPDATE_ABI)
|
||||
endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
|
||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET})
|
||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET} VERBATIM)
|
||||
|
||||
# Link compile database for clangd
|
||||
execute_process(COMMAND cmake -E create_symlink
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"${CMAKE_BINARY_DIR}/compile_commands.json"
|
||||
"${CMAKE_SOURCE_DIR}/compile_commands.json")
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
|
||||
# SOURCE GENERATOR
|
||||
set(CPACK_SOURCE_GENERATOR "TXZ")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;/[.]clangd/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json")
|
||||
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
|
||||
@@ -23,7 +23,7 @@ if (WIN32)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS")
|
||||
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
|
||||
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
|
||||
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
|
||||
set(CPACK_NSIS_MENU_LINKS "https://www.libssh.org/" "libssh homepage")
|
||||
endif (NSIS_MAKE)
|
||||
endif (WIN32)
|
||||
|
||||
|
||||
55
ChangeLog
55
ChangeLog
@@ -1,6 +1,61 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.9.7 (released 2023-05-04)
|
||||
* Fix CVE-2023-1667: a NULL dereference during rekeying with algorithm guessing
|
||||
* Fix CVE-2023-2283: a possible authorization bypass in
|
||||
pki_verify_data_signature under low-memory conditions.
|
||||
* Fix several memory leaks in GSSAPI handling code
|
||||
* Build and test related backports
|
||||
|
||||
version 0.9.6 (released 2021-08-26)
|
||||
* CVE-2021-3634: Fix possible heap-buffer overflow when rekeying with
|
||||
different key exchange mechanism
|
||||
* Fix several memory leaks on error paths
|
||||
* Reset pending_call_state on disconnect
|
||||
* Fix handshake bug with AEAD ciphers and no HMAC overlap
|
||||
* Use OPENSSL_CRYPTO_LIBRARIES in CMake
|
||||
* Ignore request success and failure message if they are not expected
|
||||
* Support more identity files in configuration
|
||||
* Avoid setting compiler flags directly in CMake
|
||||
* Support build directories with special characters
|
||||
* Include stdlib.h to avoid crash in Windows
|
||||
* Fix sftp_new_channel constructs an invalid object
|
||||
* Fix Ninja multiple rules error
|
||||
* Several tests fixes
|
||||
|
||||
version 0.9.5 (released 2020-09-10)
|
||||
* CVE-2020-16135: Avoid null pointer dereference in sftpserver (T232)
|
||||
* Improve handling of library initialization (T222)
|
||||
* Fix parsing of subsecond times in SFTP (T219)
|
||||
* Make the documentation reproducible
|
||||
* Remove deprecated API usage in OpenSSL
|
||||
* Fix regression of ssh_channel_poll_timeout() returning SSH_AGAIN
|
||||
* Define version in one place (T226)
|
||||
* Prevent invalid free when using different C runtimes than OpenSSL (T229)
|
||||
* Compatibility improvements to testsuite
|
||||
|
||||
version 0.9.4 (released 2020-04-09)
|
||||
* Fixed CVE-2020-1730 - Possible DoS in client and server when handling
|
||||
AES-CTR keys with OpenSSL
|
||||
* Added diffie-hellman-group14-sha256
|
||||
* Fixed serveral possible memory leaks
|
||||
|
||||
version 0.9.3 (released 2019-12-10)
|
||||
* Fixed CVE-2019-14889 - SCP: Unsanitized location leads to command execution
|
||||
* SSH-01-003 Client: Missing NULL check leads to crash in erroneous state
|
||||
* SSH-01-006 General: Various unchecked Null-derefs cause DOS
|
||||
* SSH-01-007 PKI Gcrypt: Potential UAF/double free with RSA pubkeys
|
||||
* SSH-01-010 SSH: Deprecated hash function in fingerprinting
|
||||
* SSH-01-013 Conf-Parsing: Recursive wildcards in hostnames lead to DOS
|
||||
* SSH-01-014 Conf-Parsing: Integer underflow leads to OOB array access
|
||||
* SSH-01-001 State Machine: Initial machine states should be set explicitly
|
||||
* SSH-01-002 Kex: Differently bound macros used to iterate same array
|
||||
* SSH-01-005 Code-Quality: Integer sign confusion during assignments
|
||||
* SSH-01-008 SCP: Protocol Injection via unescaped File Names
|
||||
* SSH-01-009 SSH: Update documentation which RFCs are implemented
|
||||
* SSH-01-012 PKI: Information leak via uninitialized stack buffer
|
||||
|
||||
version 0.9.2 (released 2019-11-07)
|
||||
* Fixed libssh-config.cmake
|
||||
* Fixed issues with rsa algorithm negotiation (T191)
|
||||
|
||||
@@ -42,6 +42,7 @@ if (UNIX)
|
||||
add_c_compiler_flag("-Wstrict-overflow=2" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wmissing-field-initializers" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wsign-compare" SUPPORTED_COMPILER_FLAGS)
|
||||
|
||||
check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT)
|
||||
if (REQUIRED_FLAGS_WFORMAT)
|
||||
|
||||
@@ -101,53 +101,53 @@ if (OPENSSL_FOUND)
|
||||
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_aes_128_ctr HAVE_OPENSSL_EVP_AES_CTR)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_aes_128_cbc HAVE_OPENSSL_EVP_AES_CBC)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_aes_128_gcm HAVE_OPENSSL_EVP_AES_GCM)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(CRYPTO_THREADID_set_callback HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(CRYPTO_ctr128_encrypt HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_CIPHER_CTX_new HAVE_OPENSSL_EVP_CIPHER_CTX_NEW)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_DigestVerify HAVE_OPENSSL_EVP_DIGESTVERIFY)
|
||||
|
||||
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519)
|
||||
|
||||
if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND
|
||||
@@ -156,7 +156,7 @@ if (OPENSSL_FOUND)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519)
|
||||
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
|
||||
10
INSTALL
10
INSTALL
@@ -7,11 +7,11 @@
|
||||
In order to build libssh, you need to install several components:
|
||||
|
||||
- A C compiler
|
||||
- [CMake](http://www.cmake.org) >= 2.6.0.
|
||||
- [openssl](http://www.openssl.org) >= 0.9.8
|
||||
- [CMake](https://www.cmake.org) >= 2.6.0.
|
||||
- [openssl](https://www.openssl.org) >= 0.9.8
|
||||
or
|
||||
- [gcrypt](http://www.gnu.org/directory/Security/libgcrypt.html) >= 1.4
|
||||
- [libz](http://www.zlib.net) >= 1.2
|
||||
- [gcrypt](https://www.gnu.org/directory/Security/libgcrypt.html) >= 1.4
|
||||
- [libz](https://www.zlib.net) >= 1.2
|
||||
|
||||
optional:
|
||||
- [cmocka](https://cmocka.org/) >= 1.1.0
|
||||
@@ -117,4 +117,4 @@ This document is written using [Markdown][] syntax, making it possible to
|
||||
provide usable information in both plain text and HTML format. Whenever
|
||||
modifying this document please use [Markdown][] syntax.
|
||||
|
||||
[markdown]: http://www.daringfireball.net/projects/markdown
|
||||
[markdown]: https://www.daringfireball.net/projects/markdown
|
||||
|
||||
2
README
2
README
@@ -31,7 +31,7 @@ If you ask yourself how to compile libssh, please read INSTALL before anything.
|
||||
3* Where ?
|
||||
-_-_-_-_-_-_
|
||||
|
||||
http://www.libssh.org
|
||||
https://www.libssh.org
|
||||
|
||||
4* Contributing
|
||||
-_-_-_-_-_-_-_-_-_
|
||||
|
||||
@@ -60,7 +60,7 @@ following to $HOME/.vimrc:
|
||||
|
||||
You can use the Vim gitmodline plugin to store this in the git config:
|
||||
|
||||
http://git.cryptomilk.org/projects/vim-gitmodeline.git/
|
||||
https://git.cryptomilk.org/projects/vim-gitmodeline.git/
|
||||
|
||||
For Vim, the following settings in $HOME/.vimrc will also deal with
|
||||
displaying trailing whitespace:
|
||||
|
||||
@@ -23,7 +23,7 @@ much easier to work with individuals who have ownership than corporate
|
||||
legal departments if we ever need to make reasonable compromises with
|
||||
people using and working with libssh.
|
||||
|
||||
We track the ownership of every part of libssh via http://git.libssh.org,
|
||||
We track the ownership of every part of libssh via https://git.libssh.org,
|
||||
our source code control system, so we know the provenance of every piece
|
||||
of code that is committed to libssh.
|
||||
|
||||
@@ -85,7 +85,7 @@ By making a contribution to this project, I certify that:
|
||||
Free Software Foundation; either version 2.1 of
|
||||
the License, or (at the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
https://www.gnu.org/licenses/lgpl-2.1.html
|
||||
|
||||
|
||||
We will maintain a copy of that email as a record that you have the
|
||||
|
||||
@@ -302,12 +302,13 @@ function(get_file_list _TARGET_NAME)
|
||||
add_custom_target(
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOUTPUT_PATH="${_get_files_list_OUTPUT_PATH}"
|
||||
-DDIRECTORIES="${_get_files_list_DIRECTORIES}"
|
||||
-DFILES_PATTERNS="${_get_files_list_FILES_PATTERNS}"
|
||||
-DOUTPUT_PATH=${_get_files_list_OUTPUT_PATH}
|
||||
-DDIRECTORIES=${_get_files_list_DIRECTORIES}
|
||||
-DFILES_PATTERNS=${_get_files_list_FILES_PATTERNS}
|
||||
-P ${_GET_FILES_LIST_SCRIPT}
|
||||
COMMENT
|
||||
"Searching for files"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
if (DEFINED _get_files_list_COPY_TO)
|
||||
@@ -318,6 +319,7 @@ function(get_file_list _TARGET_NAME)
|
||||
${_FILES_LIST_OUTPUT_PATH} ${_get_files_list_COPY_TO}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
@@ -369,12 +371,13 @@ function(extract_symbols _TARGET_NAME)
|
||||
add_custom_target(
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOUTPUT_PATH="${_SYMBOLS_OUTPUT_PATH}"
|
||||
-DHEADERS_LIST_FILE="${_HEADERS_LIST_FILE}"
|
||||
-DOUTPUT_PATH=${_SYMBOLS_OUTPUT_PATH}
|
||||
-DHEADERS_LIST_FILE=${_HEADERS_LIST_FILE}
|
||||
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
|
||||
-P ${_EXTRACT_SYMBOLS_SCRIPT}
|
||||
DEPENDS ${_extract_symbols_HEADERS_LIST}
|
||||
COMMENT "Extracting symbols from headers"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
if (DEFINED _extract_symbols_COPY_TO)
|
||||
@@ -385,6 +388,7 @@ function(extract_symbols _TARGET_NAME)
|
||||
${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
@@ -449,35 +453,37 @@ function(generate_map_file _TARGET_NAME)
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE}
|
||||
-DSYMBOLS="${_SYMBOLS_FILE}"
|
||||
-DSYMBOLS=${_SYMBOLS_FILE}
|
||||
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
|
||||
-DOUTPUT_PATH="${_MAP_OUTPUT_PATH}"
|
||||
-DOUTPUT_PATH=${_MAP_OUTPUT_PATH}
|
||||
-DFINAL=${_generate_map_file_FINAL}
|
||||
-DBREAK_ABI=${_generate_map_file_BREAK_ABI}
|
||||
-DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION}
|
||||
-P ${_GENERATE_MAP_SCRIPT}
|
||||
DEPENDS ${_generate_map_file_SYMBOLS}
|
||||
COMMENT "Generating the map ${_TARGET_NAME}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Add a custom command setting the map as OUTPUT to allow it to be added as
|
||||
# a generated source
|
||||
add_custom_command(
|
||||
OUTPUT ${_MAP_OUTPUT_PATH}
|
||||
DEPENDS ${_TARGET_NAME}
|
||||
DEPENDS ${_TARGET_NAME}_copy
|
||||
)
|
||||
|
||||
if (DEFINED _generate_map_file_COPY_TO)
|
||||
# Copy the generated map back to the COPY_TO
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
add_custom_target(${_TARGET_NAME}_copy ALL
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH}
|
||||
${_generate_map_file_COPY_TO}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
add_custom_target(${_TARGET_NAME}_copy ALL
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -13,8 +13,11 @@ if (DOXYGEN_FOUND)
|
||||
set(DOXYGEN_TAB_SIZE 4)
|
||||
set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
|
||||
set(DOXYGEN_MARKDOWN_SUPPORT YES)
|
||||
set(DOXYGEN_FULL_PATH_NAMES NO)
|
||||
|
||||
set(DOXYGEN_PREDEFINED DOXYGEN
|
||||
WITH_SERVER
|
||||
WITH_SFTP
|
||||
PRINTF_ATTRIBUTE(x,y))
|
||||
|
||||
set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style)
|
||||
|
||||
@@ -112,8 +112,8 @@ This number is calculated using the following procedure:
|
||||
This conversion follows the network byte order. This step differs from
|
||||
RFC5656.
|
||||
|
||||
[RFC5656] http://tools.ietf.org/html/rfc5656
|
||||
[RFC5656] https://tools.ietf.org/html/rfc5656
|
||||
[SCHNEIER] https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929
|
||||
[DJB] http://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf
|
||||
[DJB] https://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf
|
||||
[Curve25519] "Curve25519: new Diffie-Hellman speed records."
|
||||
http://cr.yp.to/ecdh/curve25519-20060209.pdf
|
||||
https://cr.yp.to/ecdh/curve25519-20060209.pdf
|
||||
|
||||
@@ -28,6 +28,6 @@ the dllimport attribute.
|
||||
@endcode
|
||||
|
||||
If you're are statically linking with OpenSSL, read the "Linking your
|
||||
application" section in the NOTES.<OS> in the OpenSSL source tree!
|
||||
application" section in the NOTES.[OS] in the OpenSSL source tree!
|
||||
|
||||
*/
|
||||
|
||||
@@ -39,8 +39,8 @@ The libssh library provides:
|
||||
|
||||
- Client <b>and</b> server support
|
||||
- SSHv2 and SSHv1 protocol support
|
||||
- Supports <a href="http://test.libssh.org/" target="_blank">Linux, UNIX, BSD, Solaris, OS/2 and Windows</a>
|
||||
- Automated test cases with nightly <a href="http://test.libssh.org/" target="_blank">tests</a>
|
||||
- Supports <a href="https://test.libssh.org/" target="_blank">Linux, UNIX, BSD, Solaris, OS/2 and Windows</a>
|
||||
- Automated test cases with nightly <a href="https://test.libssh.org/" target="_blank">tests</a>
|
||||
- Event model based on poll(2), or a poll(2)-emulation.
|
||||
|
||||
@section main-copyright Copyright Policy
|
||||
@@ -111,7 +111,7 @@ By making a contribution to this project, I certify that:
|
||||
Free Software Foundation; either version 2.1 of
|
||||
the License, or (at the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
https://www.gnu.org/licenses/lgpl-2.1.html
|
||||
@endverbatim
|
||||
|
||||
We will maintain a copy of that email as a record that you have the rights to
|
||||
@@ -151,47 +151,79 @@ The libssh Team
|
||||
|
||||
The following RFC documents described SSH-2 protcol as an Internet standard.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
|
||||
The Secure Shell (SSH) Protocol Assigned Numbers
|
||||
- <a href="http://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
|
||||
The Secure Shell (SSH) Protocol Architecture
|
||||
- <a href="http://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
|
||||
The Secure Shell (SSH) Authentication Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
|
||||
The Secure Shell (SSH) Transport Layer Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
|
||||
The Secure Shell (SSH) Connection Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
|
||||
Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
|
||||
- <a href="http://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
|
||||
(not implemented in libssh)
|
||||
- <a href="https://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
|
||||
Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
|
||||
- <a href="http://tools.ietf.org/html/rfc4335" target="_blank">RFC 4335</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4335" target="_blank">RFC 4335</a>,
|
||||
The Secure Shell (SSH) Session Channel Break Extension
|
||||
- <a href="http://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
|
||||
The Secure Shell (SSH) Transport Layer Encryption Modes
|
||||
- <a href="http://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>,
|
||||
Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
|
||||
|
||||
It was later modified and expanded by the following RFCs.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
|
||||
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
|
||||
Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>,
|
||||
- <a href="https://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>,
|
||||
RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
|
||||
(not implemented in libssh)
|
||||
- <a href="https://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
|
||||
Generic Security Service Application Program Interface (GSS-API)
|
||||
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
|
||||
(only the authentication implemented in libssh)
|
||||
- <a href="https://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
|
||||
The Secure Shell (SSH) Public Key File Format
|
||||
- <a href="http://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
|
||||
(not implemented in libssh)
|
||||
- <a href="https://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
|
||||
AES Galois Counter Mode for the Secure Shell Transport Layer Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
|
||||
(the algorithm negotiation implemented according to openssh.com)
|
||||
- <a href="https://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
|
||||
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
|
||||
- <a href="https://tools.ietf.org/html/rfc6594" target="_blank">RFC 6594</a>,
|
||||
Use of the SHA-256 Algorithm with RSA, DSA, and ECDSA in SSHFP Resource Records
|
||||
(not implemented in libssh)
|
||||
- <a href="https://tools.ietf.org/html/rfc6668" target="_blank">RFC 6668</a>,
|
||||
SHA-2 Data Integrity Verification for the Secure Shell (SSH) Transport Layer Protocol
|
||||
- <a href="https://tools.ietf.org/html/rfc7479" target="_blank">RFC 7479</a>,
|
||||
Using Ed25519 in SSHFP Resource Records
|
||||
(not implemented in libssh)
|
||||
- <a href="https://tools.ietf.org/html/rfc8160" target="_blank">RFC 8160</a>,
|
||||
IUTF8 Terminal Mode in Secure Shell (SSH)
|
||||
(not handled in libssh)
|
||||
- <a href="https://tools.ietf.org/html/rfc8270" target="_blank">RFC 8270</a>,
|
||||
Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits
|
||||
- <a href="https://tools.ietf.org/html/rfc8308" target="_blank">RFC 8308</a>,
|
||||
Extension Negotiation in the Secure Shell (SSH) Protocol
|
||||
(only the "server-sig-algs" extension implemented)
|
||||
- <a href="https://tools.ietf.org/html/rfc8332" target="_blank">RFC 8332</a>,
|
||||
Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol
|
||||
|
||||
There are also drafts that are being currently developed and followed.
|
||||
|
||||
- <a href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-kex-sha2-10" target="_blank">draft-ietf-curdle-ssh-kex-sha2-10</a>
|
||||
Key Exchange (KEX) Method Updates and Recommendations for Secure Shell (SSH)
|
||||
- <a href="https://tools.ietf.org/html/draft-miller-ssh-agent-03" target="_blank">draft-miller-ssh-agent-03</a>
|
||||
SSH Agent Protocol
|
||||
- <a href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-12" target="_blank">draft-ietf-curdle-ssh-curves-12</a>
|
||||
Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
|
||||
|
||||
Interesting cryptography documents:
|
||||
|
||||
- <a href="http://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards.
|
||||
- <a href="https://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards.
|
||||
|
||||
@subsection main-rfc-sftp Secure Shell File Transfer Protocol (SFTP)
|
||||
|
||||
@@ -199,26 +231,22 @@ The protocol is not an Internet standard but it is still widely implemented.
|
||||
OpenSSH and most other implementation implement Version 3 of the protocol. We
|
||||
do the same in libssh.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank">
|
||||
- <a href="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank">
|
||||
draft-ietf-secsh-filexfer-02.txt</a>,
|
||||
SSH File Transfer Protocol
|
||||
|
||||
@subsection main-rfc-extensions Secure Shell Extensions
|
||||
|
||||
The libssh project has an extension to support Curve25519 which is also supported by
|
||||
the OpenSSH project.
|
||||
|
||||
- <a href="http://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt" target="_blank">curve25519-sha256@libssh.org</a>,
|
||||
Curve25519-SHA256 for ECDH KEX
|
||||
|
||||
The OpenSSH project has defined some extensions to the protocol. We support some of
|
||||
them like the statvfs calls in SFTP or the ssh-agent.
|
||||
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL" target="_blank">
|
||||
- <a href="https://api.libssh.org/rfc/PROTOCOL" target="_blank">
|
||||
OpenSSH's deviations and extensions</a>
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.agent" target="_blank">
|
||||
OpenSSH's ssh-agent</a>
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
|
||||
- <a href="https://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
|
||||
OpenSSH's pubkey certificate authentication</a>
|
||||
- <a href="https://api.libssh.org/rfc/PROTOCOL.chacha20poly1305" target="_blank">
|
||||
chacha20-poly1305@openssh.com authenticated encryption mode</a>
|
||||
- <a href="https://api.libssh.org/rfc/PROTOCOL.key" target="_blank">
|
||||
OpenSSH private key format (openssh-key-v1)</a>
|
||||
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,7 @@ set(examples_SRCS
|
||||
connect_ssh.c
|
||||
)
|
||||
|
||||
include_directories(${libssh_BINARY_DIR})
|
||||
include_directories(${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR})
|
||||
|
||||
if (ARGP_INCLUDE_DIR)
|
||||
include_directories(${ARGP_INCLUDE_DIR})
|
||||
|
||||
@@ -234,7 +234,7 @@ int authenticate_console(ssh_session session)
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n",banner);
|
||||
ssh_string_free_char(banner);
|
||||
SSH_STRING_FREE_CHAR(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -8,7 +8,7 @@ int main(void) {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
int rbytes, wbytes, total = 0;
|
||||
int rc;
|
||||
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
@@ -35,15 +35,30 @@ int main(void) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0) {
|
||||
if (fwrite(buffer, 1, nbytes, stdout) != (unsigned int) nbytes) {
|
||||
goto failed;
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (rbytes <= 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (nbytes < 0) {
|
||||
do {
|
||||
wbytes = fwrite(buffer + total, 1, rbytes, stdout);
|
||||
if (wbytes <= 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
total += wbytes;
|
||||
|
||||
/* When it was not possible to write the whole buffer to stdout */
|
||||
if (wbytes < rbytes) {
|
||||
rbytes -= wbytes;
|
||||
continue;
|
||||
}
|
||||
|
||||
rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
total = 0;
|
||||
} while (rbytes > 0);
|
||||
|
||||
if (rbytes < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ static int open_location(struct location *loc, int flag) {
|
||||
loc->file = fopen(loc->path, flag == READ ? "r":"w");
|
||||
if (!loc->file) {
|
||||
if (errno == EISDIR) {
|
||||
if (chdir(loc->path)) {
|
||||
if (loc->path != NULL && chdir(loc->path)) {
|
||||
fprintf(stderr,
|
||||
"Error changing directory to %s: %s\n",
|
||||
loc->path, strerror(errno));
|
||||
@@ -257,14 +257,15 @@ static int open_location(struct location *loc, int flag) {
|
||||
* @param recursive Copy also directories
|
||||
*/
|
||||
static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
int size;
|
||||
size_t size;
|
||||
socket_t fd;
|
||||
struct stat s;
|
||||
int w, r;
|
||||
char buffer[16384];
|
||||
int total = 0;
|
||||
int mode;
|
||||
size_t total = 0;
|
||||
mode_t mode;
|
||||
char *filename = NULL;
|
||||
|
||||
/* recursive mode doesn't work yet */
|
||||
(void)recursive;
|
||||
/* Get the file name and size*/
|
||||
@@ -302,7 +303,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
fprintf(stderr,
|
||||
"Error: %s\n",
|
||||
ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||
@@ -315,7 +316,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
fprintf(stderr,
|
||||
"error: %s\n",
|
||||
ssh_get_error(dest->session));
|
||||
ssh_string_free_char(filename);
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp = NULL;
|
||||
return -1;
|
||||
@@ -330,7 +331,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
if (src->is_ssh) {
|
||||
ssh_scp_deny_request(src->scp, "Cannot open local file");
|
||||
}
|
||||
ssh_string_free_char(filename);
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -346,7 +347,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
fprintf(stderr,
|
||||
"Error reading scp: %s\n",
|
||||
ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -363,7 +364,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
fprintf(stderr,
|
||||
"Error reading file: %s\n",
|
||||
strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -376,7 +377,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp = NULL;
|
||||
ssh_string_free_char(filename);
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
@@ -385,7 +386,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
fprintf(stderr,
|
||||
"Error writing in local file: %s\n",
|
||||
strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -393,8 +394,8 @@ static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
|
||||
} while(total < size);
|
||||
|
||||
ssh_string_free_char(filename);
|
||||
printf("wrote %d bytes\n", total);
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
printf("wrote %zu bytes\n", total);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,17 +23,32 @@ clients must be made or how a client should react.
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/channels.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
|
||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
|
||||
|
||||
#ifndef __unused__
|
||||
# ifdef HAVE_UNUSED_ATTRIBUTE
|
||||
# define __unused__ __attribute__((unused))
|
||||
# else /* HAVE_UNUSED_ATTRIBUTE */
|
||||
# define __unused__
|
||||
# endif /* HAVE_UNUSED_ATTRIBUTE */
|
||||
#endif /* __unused__ */
|
||||
|
||||
#ifndef UNUSED_PARAM
|
||||
#define UNUSED_PARAM(param) param __unused__
|
||||
#endif /* UNUSED_PARAM */
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
@@ -66,11 +81,18 @@ static struct cleanup_node_struct *cleanup_stack = NULL;
|
||||
|
||||
static void _close_socket(struct event_fd_data_struct event_fd_data);
|
||||
|
||||
static void cleanup_push(struct cleanup_node_struct** head_ref, struct event_fd_data_struct *new_data) {
|
||||
static void
|
||||
cleanup_push(struct cleanup_node_struct** head_ref,
|
||||
struct event_fd_data_struct *new_data)
|
||||
{
|
||||
// Allocate memory for node
|
||||
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;
|
||||
@@ -79,7 +101,9 @@ static void cleanup_push(struct cleanup_node_struct** head_ref, struct event_fd_
|
||||
(*head_ref) = new_node;
|
||||
}
|
||||
|
||||
static void do_cleanup(struct cleanup_node_struct **head_ref) {
|
||||
static void
|
||||
do_cleanup(struct cleanup_node_struct **head_ref)
|
||||
{
|
||||
struct cleanup_node_struct *current = (*head_ref);
|
||||
struct cleanup_node_struct *previous = NULL, *gone = NULL;
|
||||
|
||||
@@ -118,16 +142,22 @@ static void do_cleanup(struct cleanup_node_struct **head_ref) {
|
||||
}
|
||||
}
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *password, void *userdata) {
|
||||
(void)userdata;
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== auth_password", "Authenticating user %s pwd %s",user, password);
|
||||
if (strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
|
||||
static int
|
||||
auth_password(ssh_session session,
|
||||
const char *user,
|
||||
const char *password,
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
_ssh_log(SSH_LOG_PROTOCOL,
|
||||
"=== auth_password", "Authenticating user %s pwd %s",
|
||||
user,
|
||||
password);
|
||||
if (strcmp(user, USER) == 0 && strcmp(password, PASSWORD) == 0) {
|
||||
authenticated = true;
|
||||
printf("Authenticated\n");
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
if (tries >= 3){
|
||||
if (tries >= 3) {
|
||||
printf("Too many authentication tries\n");
|
||||
ssh_disconnect(session);
|
||||
error_set = true;
|
||||
@@ -137,25 +167,34 @@ static int auth_password(ssh_session session, const char *user,
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata) {
|
||||
static int
|
||||
auth_gssapi_mic(ssh_session session,
|
||||
const char *user,
|
||||
const char *principal,
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
|
||||
(void)userdata;
|
||||
printf("Authenticating user %s with gssapi principal %s\n", user, principal);
|
||||
if (creds != NULL)
|
||||
printf("Authenticating user %s with gssapi principal %s\n",
|
||||
user, principal);
|
||||
if (creds != NULL) {
|
||||
printf("Received some gssapi credentials\n");
|
||||
else
|
||||
} else {
|
||||
printf("Not received any forwardable creds\n");
|
||||
}
|
||||
printf("authenticated\n");
|
||||
authenticated = true;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
static int subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata) {
|
||||
(void)session;
|
||||
(void)channel;
|
||||
//(void)subsystem;
|
||||
(void)userdata;
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== subsystem_request", "Channel subsystem reqeuest: %s", subsystem);
|
||||
static int
|
||||
subsystem_request(UNUSED_PARAM(ssh_session session),
|
||||
UNUSED_PARAM(ssh_channel channel),
|
||||
const char *subsystem,
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
_ssh_log(SSH_LOG_PROTOCOL,
|
||||
"=== subsystem_request", "Channel subsystem reqeuest: %s",
|
||||
subsystem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -163,9 +202,10 @@ struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.channel_subsystem_request_function = subsystem_request
|
||||
};
|
||||
|
||||
static ssh_channel new_session_channel(ssh_session session, void *userdata) {
|
||||
(void)session;
|
||||
(void)userdata;
|
||||
static ssh_channel
|
||||
new_session_channel(UNUSED_PARAM(ssh_session session),
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== subsystem_request", "Session channel request");
|
||||
/* For TCP forward only there seems to be no need for a session channel */
|
||||
/*if(chan != NULL)
|
||||
@@ -178,18 +218,25 @@ static ssh_channel new_session_channel(ssh_session session, void *userdata) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void stack_socket_close(UNUSED_PARAM(ssh_session session),
|
||||
struct event_fd_data_struct *event_fd_data)
|
||||
static void
|
||||
stack_socket_close(UNUSED_PARAM(ssh_session session),
|
||||
struct event_fd_data_struct *event_fd_data)
|
||||
{
|
||||
if (event_fd_data->stacked != 1) {
|
||||
_ssh_log(SSH_LOG_FUNCTIONS, "=== stack_socket_close", "Closing fd = %d sockets_cnt = %d", *event_fd_data->p_fd, sockets_cnt);
|
||||
_ssh_log(SSH_LOG_FUNCTIONS, "=== stack_socket_close",
|
||||
"Closing fd = %d sockets_cnt = %d", *event_fd_data->p_fd,
|
||||
sockets_cnt);
|
||||
event_fd_data->stacked = 1;
|
||||
cleanup_push(&cleanup_stack, event_fd_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void _close_socket(struct event_fd_data_struct event_fd_data) {
|
||||
_ssh_log(SSH_LOG_FUNCTIONS, "=== close_socket", "Closing fd = %d sockets_cnt = %d", *event_fd_data.p_fd, sockets_cnt);
|
||||
static void
|
||||
_close_socket(struct event_fd_data_struct event_fd_data)
|
||||
{
|
||||
_ssh_log(SSH_LOG_FUNCTIONS, "=== close_socket",
|
||||
"Closing fd = %d sockets_cnt = %d", *event_fd_data.p_fd,
|
||||
sockets_cnt);
|
||||
ssh_event_remove_fd(mainloop, *event_fd_data.p_fd);
|
||||
sockets_cnt--;
|
||||
#ifdef _WIN32
|
||||
@@ -200,51 +247,75 @@ static void _close_socket(struct event_fd_data_struct event_fd_data) {
|
||||
(*event_fd_data.p_fd) = SSH_INVALID_SOCKET;
|
||||
}
|
||||
|
||||
static int service_request(ssh_session session, const char *service, void *userdata) {
|
||||
(void)session;
|
||||
//(void)service;
|
||||
(void)userdata;
|
||||
static int
|
||||
service_request(UNUSED_PARAM(ssh_session session),
|
||||
const char *service,
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== service_request", "Service request: %s", service);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void global_request(ssh_session session, ssh_message message, void *userdata) {
|
||||
(void)session;
|
||||
(void)userdata;
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== global_request", "Global request, message type: %d", ssh_message_type(message));
|
||||
static void
|
||||
global_request(UNUSED_PARAM(ssh_session session),
|
||||
ssh_message message,
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
_ssh_log(SSH_LOG_PROTOCOL,
|
||||
"=== global_request", "Global request, message type: %d",
|
||||
ssh_message_type(message));
|
||||
}
|
||||
|
||||
static void my_channel_close_function(ssh_session session, ssh_channel channel, void *userdata) {
|
||||
static void
|
||||
my_channel_close_function(ssh_session session,
|
||||
UNUSED_PARAM(ssh_channel channel),
|
||||
void *userdata)
|
||||
{
|
||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||
(void)session;
|
||||
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_close_function", "Channel %d:%d closed by remote. State=%d", channel->local_channel, channel->remote_channel, channel->state);
|
||||
_ssh_log(SSH_LOG_PROTOCOL,
|
||||
"=== my_channel_close_function",
|
||||
"Channel closed by remote.");
|
||||
|
||||
stack_socket_close(session, event_fd_data);
|
||||
}
|
||||
|
||||
static void my_channel_eof_function(ssh_session session, ssh_channel channel, void *userdata) {
|
||||
static void
|
||||
my_channel_eof_function(ssh_session session,
|
||||
UNUSED_PARAM(ssh_channel channel),
|
||||
void *userdata)
|
||||
{
|
||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||
(void)session;
|
||||
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_eof_function", "Got EOF on channel %d:%d. Shuting down write on socket (fd = %d).", channel->local_channel, channel->remote_channel, *event_fd_data->p_fd);
|
||||
_ssh_log(SSH_LOG_PROTOCOL,
|
||||
"=== my_channel_eof_function",
|
||||
"Got EOF on channel. Shuting down write on socket (fd = %d).",
|
||||
*event_fd_data->p_fd);
|
||||
|
||||
stack_socket_close(session, event_fd_data);
|
||||
}
|
||||
|
||||
static void my_channel_exit_status_function(ssh_session session, ssh_channel channel, int exit_status, void *userdata) {
|
||||
static void
|
||||
my_channel_exit_status_function(UNUSED_PARAM(ssh_session session),
|
||||
UNUSED_PARAM(ssh_channel channel),
|
||||
int exit_status,
|
||||
void *userdata)
|
||||
{
|
||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||
(void)session;
|
||||
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_exit_status_function", "Got exit status %d on channel %d:%d fd = %d.", exit_status, channel->local_channel, channel->remote_channel, *event_fd_data->p_fd);
|
||||
_ssh_log(SSH_LOG_PROTOCOL,
|
||||
"=== my_channel_exit_status_function",
|
||||
"Got exit status %d on channel fd = %d.",
|
||||
exit_status, *event_fd_data->p_fd);
|
||||
}
|
||||
|
||||
static int my_channel_data_function(ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *data,
|
||||
uint32_t len,
|
||||
UNUSED_PARAM(int is_stderr),
|
||||
void *userdata)
|
||||
static int
|
||||
my_channel_data_function(ssh_session session,
|
||||
UNUSED_PARAM(ssh_channel channel),
|
||||
void *data,
|
||||
uint32_t len,
|
||||
UNUSED_PARAM(int is_stderr),
|
||||
void *userdata)
|
||||
{
|
||||
int i = 0;
|
||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||
@@ -253,12 +324,18 @@ static int my_channel_data_function(ssh_session session,
|
||||
fprintf(stderr, "Why we're here? Stacked = %d\n", event_fd_data->stacked);
|
||||
}
|
||||
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_data_function", "%d bytes waiting on channel %d:%d for reading. Fd = %d",len, channel->local_channel, channel->remote_channel, *event_fd_data->p_fd);
|
||||
_ssh_log(SSH_LOG_PROTOCOL,
|
||||
"=== my_channel_data_function",
|
||||
"%d bytes waiting on channel for reading. Fd = %d",
|
||||
len,
|
||||
*event_fd_data->p_fd);
|
||||
if (len > 0) {
|
||||
i = send(*event_fd_data->p_fd, data, len, 0);
|
||||
}
|
||||
if (i < 0) {
|
||||
_ssh_log(SSH_LOG_WARNING, "=== my_channel_data_function", "Writing to tcp socket %d: %s", *event_fd_data->p_fd, strerror(errno));
|
||||
_ssh_log(SSH_LOG_WARNING, "=== my_channel_data_function",
|
||||
"Writing to tcp socket %d: %s", *event_fd_data->p_fd,
|
||||
strerror(errno));
|
||||
stack_socket_close(session, event_fd_data);
|
||||
}
|
||||
else {
|
||||
@@ -267,9 +344,10 @@ static int my_channel_data_function(ssh_session session,
|
||||
return i;
|
||||
}
|
||||
|
||||
static int my_fd_data_function(UNUSED_PARAM(socket_t fd),
|
||||
int revents,
|
||||
void *userdata)
|
||||
static int
|
||||
my_fd_data_function(UNUSED_PARAM(socket_t fd),
|
||||
int revents,
|
||||
void *userdata)
|
||||
{
|
||||
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
|
||||
ssh_channel channel = event_fd_data->channel;
|
||||
@@ -313,8 +391,10 @@ static int my_fd_data_function(UNUSED_PARAM(socket_t fd),
|
||||
blocking = ssh_is_blocking(session);
|
||||
ssh_set_blocking(session, 0);
|
||||
|
||||
_ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "Trying to read from tcp socket fd = %d... (Channel %d:%d state=%d)",
|
||||
*event_fd_data->p_fd, channel->local_channel, channel->remote_channel, channel->state);
|
||||
_ssh_log(SSH_LOG_FUNCTIONS,
|
||||
"=== my_fd_data_function",
|
||||
"Trying to read from tcp socket fd = %d",
|
||||
*event_fd_data->p_fd);
|
||||
#ifdef _WIN32
|
||||
struct sockaddr from;
|
||||
int fromlen = sizeof(from);
|
||||
@@ -360,7 +440,9 @@ static int my_fd_data_function(UNUSED_PARAM(socket_t fd),
|
||||
return len;
|
||||
}
|
||||
|
||||
static int open_tcp_socket(ssh_message msg) {
|
||||
static int
|
||||
open_tcp_socket(ssh_message msg)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int forwardsock = -1;
|
||||
struct hostent *host;
|
||||
@@ -401,17 +483,20 @@ static int open_tcp_socket(ssh_message msg) {
|
||||
return forwardsock;
|
||||
}
|
||||
|
||||
static int message_callback(ssh_session session, ssh_message message, void *userdata) {
|
||||
static int
|
||||
message_callback(UNUSED_PARAM(ssh_session session),
|
||||
ssh_message message,
|
||||
UNUSED_PARAM(void *userdata))
|
||||
{
|
||||
ssh_channel channel;
|
||||
int socket_fd, *pFd;
|
||||
struct ssh_channel_callbacks_struct *cb_chan;
|
||||
struct event_fd_data_struct *event_fd_data;
|
||||
(void)session;
|
||||
(void)message;
|
||||
(void)userdata;
|
||||
|
||||
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d", ssh_message_type(message));
|
||||
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message Subtype: %d", ssh_message_subtype(message));
|
||||
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d",
|
||||
ssh_message_type(message));
|
||||
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message Subtype: %d",
|
||||
ssh_message_subtype(message));
|
||||
if (ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN) {
|
||||
_ssh_log(SSH_LOG_PROTOCOL, "=== message_callback", "channel_request_open");
|
||||
|
||||
@@ -433,6 +518,12 @@ static int message_callback(ssh_session session, ssh_message message, void *user
|
||||
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;
|
||||
@@ -515,7 +606,9 @@ static struct argp_option options[] = {
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
static error_t
|
||||
parse_opt (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
@@ -561,7 +654,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
|
||||
@@ -233,9 +233,10 @@ void set_pcap(ssh_session session){
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
void cleanup_pcap(void)
|
||||
{
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
pcap = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -31,3 +31,9 @@ install(
|
||||
headers
|
||||
)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libssh_version.h.cmake
|
||||
${libssh_BINARY_DIR}/include/libssh/libssh_version.h
|
||||
@ONLY)
|
||||
install(FILES ${libssh_BINARY_DIR}/include/libssh/libssh_version.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${APPLICATION_NAME}
|
||||
COMPONENT headers)
|
||||
|
||||
@@ -104,7 +104,7 @@ void ssh_agent_free(struct ssh_agent_struct *agent);
|
||||
*/
|
||||
int ssh_agent_is_running(struct ssh_session_struct *session);
|
||||
|
||||
int ssh_agent_get_ident_count(struct ssh_session_struct *session);
|
||||
uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session);
|
||||
|
||||
ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define BIND_H_
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/kex.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
struct ssh_bind_struct {
|
||||
@@ -31,7 +32,7 @@ struct ssh_bind_struct {
|
||||
|
||||
struct ssh_poll_handle_struct *poll;
|
||||
/* options */
|
||||
char *wanted_methods[10];
|
||||
char *wanted_methods[SSH_KEX_METHODS];
|
||||
char *banner;
|
||||
char *ecdsakey;
|
||||
char *dsakey;
|
||||
|
||||
@@ -97,8 +97,9 @@ SSH_PACKET_CALLBACK(channel_rcv_close);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_request);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_data);
|
||||
|
||||
int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
int is_stderr);
|
||||
int channel_default_bufferize(ssh_channel channel,
|
||||
void *data, size_t len,
|
||||
bool is_stderr);
|
||||
int ssh_channel_flush(ssh_channel channel);
|
||||
uint32_t ssh_channel_new_id(ssh_session session);
|
||||
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
|
||||
|
||||
@@ -80,6 +80,8 @@ enum ssh_key_exchange_e {
|
||||
SSH_KEX_DH_GROUP16_SHA512,
|
||||
/* diffie-hellman-group18-sha512 */
|
||||
SSH_KEX_DH_GROUP18_SHA512,
|
||||
/* diffie-hellman-group14-sha256 */
|
||||
SSH_KEX_DH_GROUP14_SHA256,
|
||||
};
|
||||
|
||||
enum ssh_cipher_e {
|
||||
@@ -105,7 +107,7 @@ struct ssh_crypto_struct {
|
||||
bignum shared_secret;
|
||||
struct dh_ctx *dh_ctx;
|
||||
#ifdef WITH_GEX
|
||||
size_t dh_pmin; int dh_pn; int dh_pmax; /* preferred group parameters */
|
||||
size_t dh_pmin; size_t dh_pn; size_t dh_pmax; /* preferred group parameters */
|
||||
#endif /* WITH_GEX */
|
||||
#ifdef HAVE_ECDH
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
@@ -124,8 +126,9 @@ struct ssh_crypto_struct {
|
||||
ssh_curve25519_pubkey curve25519_server_pubkey;
|
||||
#endif
|
||||
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
||||
size_t digest_len; /* len of the two fields below */
|
||||
size_t session_id_len;
|
||||
unsigned char *session_id;
|
||||
size_t digest_len; /* len of the secret hash */
|
||||
unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */
|
||||
unsigned char *encryptIV;
|
||||
unsigned char *decryptIV;
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
|
||||
|
||||
|
||||
int ssh_client_curve25519_init(ssh_session session);
|
||||
void ssh_client_curve25519_remove_callbacks(ssh_session session);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
void ssh_server_curve25519_init(ssh_session session);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define SRC_DH_GEX_H_
|
||||
|
||||
int ssh_client_dhgex_init(ssh_session session);
|
||||
void ssh_client_dhgex_remove_callbacks(ssh_session session);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
void ssh_server_dhgex_init(ssh_session session);
|
||||
|
||||
@@ -63,8 +63,10 @@ int ssh_dh_get_current_server_publickey_blob(ssh_session session,
|
||||
ssh_key ssh_dh_get_next_server_publickey(ssh_session session);
|
||||
int ssh_dh_get_next_server_publickey_blob(ssh_session session,
|
||||
ssh_string *pubkey_blob);
|
||||
int dh_handshake(ssh_session session);
|
||||
|
||||
int ssh_client_dh_init(ssh_session session);
|
||||
void ssh_client_dh_remove_callbacks(ssh_session session);
|
||||
#ifdef WITH_SERVER
|
||||
void ssh_server_dh_init(ssh_session session);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks;
|
||||
/* Backend-specific functions. */
|
||||
int ssh_client_ecdh_init(ssh_session session);
|
||||
void ssh_client_ecdh_remove_callbacks(ssh_session session);
|
||||
int ecdh_build_k(ssh_session session);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
|
||||
@@ -39,7 +39,7 @@ void fe25519_unpack(fe25519 *r, const unsigned char x[32]);
|
||||
|
||||
void fe25519_pack(unsigned char r[32], const fe25519 *x);
|
||||
|
||||
int fe25519_iszero(const fe25519 *x);
|
||||
uint32_t fe25519_iszero(const fe25519 *x);
|
||||
|
||||
int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ struct ssh_kex_struct {
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
|
||||
|
||||
int ssh_send_kex(ssh_session session, int server_kex);
|
||||
int ssh_send_kex(ssh_session session);
|
||||
void ssh_list_kex(struct ssh_kex_struct *kex);
|
||||
int ssh_set_client_kex(ssh_session session);
|
||||
int ssh_kex_select_methods(ssh_session session);
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
struct ssh_public_key_struct {
|
||||
int type;
|
||||
const char *type_c; /* Don't free it ! it is static */
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#if defined(HAVE_LIBGCRYPT)
|
||||
gcry_sexp_t dsa_pub;
|
||||
gcry_sexp_t rsa_pub;
|
||||
#elif HAVE_LIBCRYPTO
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
DSA *dsa_pub;
|
||||
RSA *rsa_pub;
|
||||
#elif HAVE_LIBMBEDCRYPTO
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
mbedtls_pk_context *rsa_pub;
|
||||
void *dsa_pub;
|
||||
#endif
|
||||
@@ -42,13 +42,13 @@ struct ssh_public_key_struct {
|
||||
|
||||
struct ssh_private_key_struct {
|
||||
int type;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#if defined(HAVE_LIBGCRYPT)
|
||||
gcry_sexp_t dsa_priv;
|
||||
gcry_sexp_t rsa_priv;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
DSA *dsa_priv;
|
||||
RSA *rsa_priv;
|
||||
#elif HAVE_LIBMBEDCRYPTO
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
mbedtls_pk_context *rsa_priv;
|
||||
void *dsa_priv;
|
||||
#endif
|
||||
|
||||
@@ -96,9 +96,9 @@ typedef BN_CTX* bignum_CTX;
|
||||
#define bignum_add(dest, a, b) BN_add(dest, a, b)
|
||||
#define bignum_sub(dest, a, b) BN_sub(dest, a, b)
|
||||
#define bignum_mod(dest, a, b, ctx) BN_mod(dest, a, b, ctx)
|
||||
#define bignum_num_bytes(num) BN_num_bytes(num)
|
||||
#define bignum_num_bits(num) BN_num_bits(num)
|
||||
#define bignum_is_bit_set(num,bit) BN_is_bit_set(num,bit)
|
||||
#define bignum_num_bytes(num) (size_t)BN_num_bytes(num)
|
||||
#define bignum_num_bits(num) (size_t)BN_num_bits(num)
|
||||
#define bignum_is_bit_set(num,bit) BN_is_bit_set(num, (int)bit)
|
||||
#define bignum_bn2bin(num,len, ptr) BN_bn2bin(num, ptr)
|
||||
#define bignum_cmp(num1,num2) BN_cmp(num1,num2)
|
||||
#define bignum_rshift1(dest, src) BN_rshift1(dest, src)
|
||||
|
||||
@@ -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
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef _LIBSSH_H
|
||||
#define _LIBSSH_H
|
||||
|
||||
#include <libssh/libssh_version.h>
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef LIBSSH_STATIC
|
||||
#define LIBSSH_API
|
||||
@@ -71,23 +73,6 @@
|
||||
#define SSH_STRINGIFY(s) SSH_TOSTRING(s)
|
||||
#define SSH_TOSTRING(s) #s
|
||||
|
||||
/* libssh version macros */
|
||||
#define SSH_VERSION_INT(a, b, c) ((a) << 16 | (b) << 8 | (c))
|
||||
#define SSH_VERSION_DOT(a, b, c) a ##.## b ##.## c
|
||||
#define SSH_VERSION(a, b, c) SSH_VERSION_DOT(a, b, c)
|
||||
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 9
|
||||
#define LIBSSH_VERSION_MICRO 2
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
LIBSSH_VERSION_MICRO)
|
||||
#define LIBSSH_VERSION SSH_VERSION(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
LIBSSH_VERSION_MICRO)
|
||||
|
||||
/* GCC have printf type attribute check. */
|
||||
#ifdef __GNUC__
|
||||
#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
|
||||
@@ -168,13 +153,13 @@ enum ssh_auth_e {
|
||||
};
|
||||
|
||||
/* auth flags */
|
||||
#define SSH_AUTH_METHOD_UNKNOWN 0
|
||||
#define SSH_AUTH_METHOD_NONE 0x0001
|
||||
#define SSH_AUTH_METHOD_PASSWORD 0x0002
|
||||
#define SSH_AUTH_METHOD_PUBLICKEY 0x0004
|
||||
#define SSH_AUTH_METHOD_HOSTBASED 0x0008
|
||||
#define SSH_AUTH_METHOD_INTERACTIVE 0x0010
|
||||
#define SSH_AUTH_METHOD_GSSAPI_MIC 0x0020
|
||||
#define SSH_AUTH_METHOD_UNKNOWN 0x0000u
|
||||
#define SSH_AUTH_METHOD_NONE 0x0001u
|
||||
#define SSH_AUTH_METHOD_PASSWORD 0x0002u
|
||||
#define SSH_AUTH_METHOD_PUBLICKEY 0x0004u
|
||||
#define SSH_AUTH_METHOD_HOSTBASED 0x0008u
|
||||
#define SSH_AUTH_METHOD_INTERACTIVE 0x0010u
|
||||
#define SSH_AUTH_METHOD_GSSAPI_MIC 0x0020u
|
||||
|
||||
/* messages */
|
||||
enum ssh_requests_e {
|
||||
@@ -633,7 +618,13 @@ LIBSSH_API ssh_pcap_file ssh_pcap_file_new(void);
|
||||
LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback.
|
||||
* @addtogroup libssh_auth
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback for password and publickey auth.
|
||||
*
|
||||
* @param prompt Prompt to be displayed.
|
||||
* @param buf Buffer to save the password. You should null-terminate it.
|
||||
@@ -648,6 +639,8 @@ LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
||||
typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata);
|
||||
|
||||
/** @} */
|
||||
|
||||
LIBSSH_API ssh_key ssh_key_new(void);
|
||||
#define SSH_KEY_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0)
|
||||
|
||||
41
include/libssh/libssh_version.h.cmake
Normal file
41
include/libssh/libssh_version.h.cmake
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2020 by Heiko Thiery
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _LIBSSH_VERSION_H
|
||||
#define _LIBSSH_VERSION_H
|
||||
|
||||
/* libssh version macros */
|
||||
#define SSH_VERSION_INT(a, b, c) ((a) << 16 | (b) << 8 | (c))
|
||||
#define SSH_VERSION_DOT(a, b, c) a ##.## b ##.## c
|
||||
#define SSH_VERSION(a, b, c) SSH_VERSION_DOT(a, b, c)
|
||||
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR @libssh_VERSION_MAJOR@
|
||||
#define LIBSSH_VERSION_MINOR @libssh_VERSION_MINOR@
|
||||
#define LIBSSH_VERSION_MICRO @libssh_VERSION_PATCH@
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
LIBSSH_VERSION_MICRO)
|
||||
#define LIBSSH_VERSION SSH_VERSION(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
LIBSSH_VERSION_MICRO)
|
||||
|
||||
#endif /* _LIBSSH_VERSION_H */
|
||||
@@ -28,7 +28,7 @@ struct ssh_auth_request {
|
||||
int method;
|
||||
char *password;
|
||||
struct ssh_key_struct *pubkey;
|
||||
char signature_state;
|
||||
enum ssh_publickey_state_e signature_state;
|
||||
char kbdint_response;
|
||||
};
|
||||
|
||||
|
||||
@@ -51,6 +51,12 @@ struct ssh_timestamp {
|
||||
long useconds;
|
||||
};
|
||||
|
||||
enum ssh_quote_state_e {
|
||||
NO_QUOTE,
|
||||
SINGLE_QUOTE,
|
||||
DOUBLE_QUOTE
|
||||
};
|
||||
|
||||
struct ssh_list *ssh_list_new(void);
|
||||
void ssh_list_free(struct ssh_list *list);
|
||||
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
|
||||
@@ -88,4 +94,7 @@ void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len);
|
||||
|
||||
int ssh_mkdirs(const char *pathname, mode_t mode);
|
||||
|
||||
int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
|
||||
int ssh_newline_vis(const char *string, char *buf, size_t buf_len);
|
||||
|
||||
#endif /* MISC_H_ */
|
||||
|
||||
@@ -80,7 +80,7 @@ int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *sourc
|
||||
size_t start, size_t encrypted_size);
|
||||
unsigned char *ssh_packet_encrypt(ssh_session session,
|
||||
void *packet,
|
||||
unsigned int len);
|
||||
uint32_t len);
|
||||
int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len,
|
||||
unsigned char *mac, enum ssh_hmac_e type);
|
||||
int ssh_packet_set_newkeys(ssh_session session,
|
||||
|
||||
@@ -125,6 +125,8 @@ enum ssh_digest_e ssh_key_hash_from_name(const char *name);
|
||||
/* SSH Signature Functions */
|
||||
ssh_signature ssh_signature_new(void);
|
||||
void ssh_signature_free(ssh_signature sign);
|
||||
#define SSH_SIGNATURE_FREE(x) \
|
||||
do { ssh_signature_free(x); x = NULL; } while(0)
|
||||
|
||||
int ssh_pki_export_signature_blob(const ssh_signature sign,
|
||||
ssh_string *sign_blob);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(HAVE_STRTOULL)
|
||||
# if defined(HAVE___STRTOULL)
|
||||
@@ -287,7 +288,7 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
|
||||
/* in base64.c */
|
||||
ssh_buffer base64_to_bin(const char *source);
|
||||
unsigned char *bin_to_base64(const unsigned char *source, int len);
|
||||
uint8_t *bin_to_base64(const uint8_t *source, size_t len);
|
||||
|
||||
/* gzip.c */
|
||||
int compress_buffer(ssh_session session,ssh_buffer buf);
|
||||
@@ -405,22 +406,24 @@ void explicit_bzero(void *s, size_t n);
|
||||
# endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
|
||||
#endif /* FALL_THROUGH */
|
||||
|
||||
#ifndef __unused__
|
||||
#ifndef __attr_unused__
|
||||
# ifdef HAVE_UNUSED_ATTRIBUTE
|
||||
# define __unused__ __attribute__((unused))
|
||||
# define __attr_unused__ __attribute__((unused))
|
||||
# else /* HAVE_UNUSED_ATTRIBUTE */
|
||||
# define __unused__
|
||||
# define __attr_unused__
|
||||
# endif /* HAVE_UNUSED_ATTRIBUTE */
|
||||
#endif /* __unused__ */
|
||||
#endif /* __attr_unused__ */
|
||||
|
||||
#ifndef UNUSED_PARAM
|
||||
#define UNUSED_PARAM(param) param __unused__
|
||||
#define UNUSED_PARAM(param) param __attr_unused__
|
||||
#endif /* UNUSED_PARAM */
|
||||
|
||||
#ifndef UNUSED_VAR
|
||||
#define UNUSED_VAR(var) __unused__ var
|
||||
#define UNUSED_VAR(var) __attr_unused__ var
|
||||
#endif /* UNUSED_VAR */
|
||||
|
||||
void ssh_agent_state_free(void *data);
|
||||
|
||||
bool is_ssh_initialized(void);
|
||||
|
||||
#endif /* _LIBSSH_PRIV_H */
|
||||
|
||||
@@ -75,6 +75,11 @@ enum ssh_pending_call_e {
|
||||
/* Client successfully authenticated */
|
||||
#define SSH_SESSION_FLAG_AUTHENTICATED 2
|
||||
|
||||
/* The KEXINIT message can be sent first by either of the parties so this flag
|
||||
* indicates that the message was already sent to make sure it is sent and avoid
|
||||
* sending it twice during key exchange to simplify the state machine. */
|
||||
#define SSH_SESSION_FLAG_KEXINIT_SENT 4
|
||||
|
||||
/* codes to use with ssh_handle_packets*() */
|
||||
/* Infinite timeout */
|
||||
#define SSH_TIMEOUT_INFINITE -1
|
||||
@@ -131,10 +136,8 @@ struct ssh_session_struct {
|
||||
/* Extensions negotiated using RFC 8308 */
|
||||
uint32_t extensions;
|
||||
|
||||
ssh_string banner; /* that's the issue banner from
|
||||
the server */
|
||||
char *discon_msg; /* disconnect message from
|
||||
the remote host */
|
||||
ssh_string banner; /* that's the issue banner from the server */
|
||||
char *discon_msg; /* disconnect message from the remote host */
|
||||
ssh_buffer in_buffer;
|
||||
PACKET in_packet;
|
||||
ssh_buffer out_buffer;
|
||||
@@ -145,7 +148,7 @@ struct ssh_session_struct {
|
||||
/* where it was before being interrupted */
|
||||
enum ssh_pending_call_e pending_call_state;
|
||||
enum ssh_session_state_e session_state;
|
||||
int packet_state;
|
||||
enum ssh_packet_state_e packet_state;
|
||||
enum ssh_dh_state_e dh_handshake_state;
|
||||
enum ssh_channel_request_state_e global_req_state;
|
||||
struct ssh_agent_state_struct *agent_state;
|
||||
@@ -158,25 +161,33 @@ struct ssh_session_struct {
|
||||
uint32_t current_method;
|
||||
} auth;
|
||||
|
||||
/* Sending this flag before key exchange to save one round trip during the
|
||||
* key exchange. This might make sense on high-latency connections.
|
||||
* So far internal only for testing. Usable only on the client side --
|
||||
* there is no key exchange method that would start with server message */
|
||||
bool send_first_kex_follows;
|
||||
/*
|
||||
* RFC 4253, 7.1: if the first_kex_packet_follows flag was set in
|
||||
* the received SSH_MSG_KEXINIT, but the guess was wrong, this
|
||||
* field will be set such that the following guessed packet will
|
||||
* be ignored. Once that packet has been received and ignored,
|
||||
* this field is cleared.
|
||||
* be ignored on the receiving side. Once that packet has been received and
|
||||
* ignored, this field is cleared.
|
||||
* On the sending side, this is set after we got peer KEXINIT message and we
|
||||
* need to resend the initial message of the negotiated KEX algorithm.
|
||||
*/
|
||||
int first_kex_follows_guess_wrong;
|
||||
bool first_kex_follows_guess_wrong;
|
||||
|
||||
ssh_buffer in_hashbuf;
|
||||
ssh_buffer out_hashbuf;
|
||||
struct ssh_crypto_struct *current_crypto;
|
||||
struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
|
||||
/* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
|
||||
struct ssh_crypto_struct *next_crypto;
|
||||
|
||||
struct ssh_list *channels; /* linked list of channels */
|
||||
int maxchannel;
|
||||
ssh_agent agent; /* ssh agent */
|
||||
|
||||
/* keyb interactive data */
|
||||
/* keyboard interactive data */
|
||||
struct ssh_kbdint_struct *kbdint;
|
||||
struct ssh_gssapi_struct *gssapi;
|
||||
|
||||
@@ -193,7 +204,8 @@ struct ssh_session_struct {
|
||||
|
||||
/* auths accepted by server */
|
||||
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
|
||||
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata);
|
||||
int (*ssh_message_callback)(struct ssh_session_struct *session,
|
||||
ssh_message msg, void *userdata);
|
||||
void *ssh_message_callback_data;
|
||||
ssh_server_callbacks server_callbacks;
|
||||
void (*ssh_connection_callback)( struct ssh_session_struct *session);
|
||||
@@ -213,13 +225,13 @@ struct ssh_session_struct {
|
||||
char *sshdir;
|
||||
char *knownhosts;
|
||||
char *global_knownhosts;
|
||||
char *wanted_methods[10];
|
||||
char *wanted_methods[SSH_KEX_METHODS];
|
||||
char *pubkey_accepted_types;
|
||||
char *ProxyCommand;
|
||||
char *custombanner;
|
||||
unsigned long timeout; /* seconds */
|
||||
unsigned long timeout_usec;
|
||||
unsigned int port;
|
||||
uint16_t port;
|
||||
socket_t fd;
|
||||
int StrictHostKeyChecking;
|
||||
char compressionlevel;
|
||||
|
||||
@@ -870,13 +870,6 @@ LIBSSH_API int sftp_server_init(sftp_session sftp);
|
||||
LIBSSH_API void sftp_server_free(sftp_session sftp);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
/* this is not a public interface */
|
||||
#define SFTP_HANDLES 256
|
||||
sftp_packet sftp_packet_read(sftp_session sftp);
|
||||
int sftp_packet_write(sftp_session sftp,uint8_t type, ssh_buffer payload);
|
||||
void sftp_packet_free(sftp_packet packet);
|
||||
int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr);
|
||||
sftp_attributes sftp_parse_attr(sftp_session session, ssh_buffer buf,int expectname);
|
||||
/* sftpserver.c */
|
||||
|
||||
LIBSSH_API sftp_client_message sftp_get_client_message(sftp_session sftp);
|
||||
|
||||
32
include/libssh/sftp_priv.h
Normal file
32
include/libssh/sftp_priv.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-2008 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SFTP_PRIV_H
|
||||
#define SFTP_PRIV_H
|
||||
|
||||
sftp_packet sftp_packet_read(sftp_session sftp);
|
||||
ssize_t sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload);
|
||||
void sftp_packet_free(sftp_packet packet);
|
||||
int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr);
|
||||
sftp_attributes sftp_parse_attr(sftp_session session,
|
||||
ssh_buffer buf,
|
||||
int expectname);
|
||||
|
||||
#endif /* SFTP_PRIV_H */
|
||||
@@ -63,6 +63,9 @@ void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks);
|
||||
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s);
|
||||
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle(ssh_socket s);
|
||||
|
||||
int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr);
|
||||
int ssh_socket_connect(ssh_socket s,
|
||||
const char *host,
|
||||
uint16_t port,
|
||||
const char *bind_addr);
|
||||
|
||||
#endif /* SOCKET_H_ */
|
||||
|
||||
@@ -1 +1 @@
|
||||
4.8.3
|
||||
4.8.8
|
||||
421
src/ABI/libssh-4.8.4.symbols
Normal file
421
src/ABI/libssh-4.8.4.symbols
Normal file
@@ -0,0 +1,421 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_init
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
421
src/ABI/libssh-4.8.5.symbols
Normal file
421
src/ABI/libssh-4.8.5.symbols
Normal file
@@ -0,0 +1,421 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_init
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
421
src/ABI/libssh-4.8.6.symbols
Normal file
421
src/ABI/libssh-4.8.6.symbols
Normal file
@@ -0,0 +1,421 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_init
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
421
src/ABI/libssh-4.8.7.symbols
Normal file
421
src/ABI/libssh-4.8.7.symbols
Normal file
@@ -0,0 +1,421 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_init
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
421
src/ABI/libssh-4.8.8.symbols
Normal file
421
src/ABI/libssh-4.8.8.symbols
Normal file
@@ -0,0 +1,421 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_init
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
@@ -1,6 +1,7 @@
|
||||
set(LIBSSH_PUBLIC_INCLUDE_DIRS ${libssh_SOURCE_DIR}/include)
|
||||
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${libssh_BINARY_DIR}/include
|
||||
${libssh_BINARY_DIR}
|
||||
)
|
||||
|
||||
@@ -15,7 +16,7 @@ if (WIN32)
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
if (OPENSSL_CRYPTO_LIBRARY)
|
||||
if (OPENSSL_CRYPTO_LIBRARIES)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
@@ -23,9 +24,9 @@ if (OPENSSL_CRYPTO_LIBRARY)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
${OPENSSL_CRYPTO_LIBRARY}
|
||||
${OPENSSL_CRYPTO_LIBRARIES}
|
||||
)
|
||||
endif (OPENSSL_CRYPTO_LIBRARY)
|
||||
endif (OPENSSL_CRYPTO_LIBRARIES)
|
||||
|
||||
if (MBEDTLS_CRYPTO_LIBRARY)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
@@ -85,6 +86,13 @@ if (WITH_NACL AND NACL_FOUND)
|
||||
)
|
||||
endif (WITH_NACL AND NACL_FOUND)
|
||||
|
||||
if (MINGW AND Threads_FOUND)
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
Threads::Threads
|
||||
)
|
||||
endif()
|
||||
|
||||
if (BUILD_STATIC_LIB)
|
||||
set(LIBSSH_STATIC_LIBRARY
|
||||
ssh_static
|
||||
@@ -322,6 +330,10 @@ target_include_directories(ssh
|
||||
target_link_libraries(ssh
|
||||
PRIVATE ${LIBSSH_LINK_LIBRARIES})
|
||||
|
||||
if (WIN32 AND NOT BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(ssh PUBLIC "LIBSSH_STATIC")
|
||||
endif ()
|
||||
|
||||
add_library(ssh::ssh ALIAS ssh)
|
||||
|
||||
if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
@@ -330,9 +342,7 @@ if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
set(MAP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_dev.map")
|
||||
endif (ABIMAP_FOUND)
|
||||
|
||||
set_target_properties(ssh
|
||||
PROPERTIES LINK_FLAGS
|
||||
"-Wl,--version-script,\"${MAP_PATH}\"")
|
||||
target_link_libraries(ssh PRIVATE "-Wl,--version-script,\"${MAP_PATH}\"")
|
||||
endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
|
||||
set_target_properties(ssh
|
||||
@@ -346,11 +356,12 @@ set_target_properties(ssh
|
||||
)
|
||||
|
||||
if (WITH_VISIBILITY_HIDDEN)
|
||||
set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
set_target_properties(ssh PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
endif (WITH_VISIBILITY_HIDDEN)
|
||||
|
||||
if (MINGW)
|
||||
set_target_properties(ssh PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup")
|
||||
target_link_libraries(ssh PRIVATE "-Wl,--enable-stdcall-fixup")
|
||||
target_compile_definitions(ssh PRIVATE "_POSIX_SOURCE")
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -399,12 +410,7 @@ if (BUILD_STATIC_LIB)
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
set_target_properties(
|
||||
ssh-static
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-DLIBSSH_STATIC"
|
||||
)
|
||||
target_compile_definitions(ssh-static PUBLIC "LIBSSH_STATIC")
|
||||
endif (WIN32)
|
||||
endif (BUILD_STATIC_LIB)
|
||||
|
||||
|
||||
191
src/agent.c
191
src/agent.c
@@ -196,7 +196,7 @@ void ssh_agent_close(struct ssh_agent_struct *agent) {
|
||||
void ssh_agent_free(ssh_agent agent) {
|
||||
if (agent) {
|
||||
if (agent->ident) {
|
||||
ssh_buffer_free(agent->ident);
|
||||
SSH_BUFFER_FREE(agent->ident);
|
||||
}
|
||||
if (agent->sock) {
|
||||
ssh_agent_close(agent);
|
||||
@@ -307,90 +307,91 @@ static int agent_talk(struct ssh_session_struct *session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
ssh_buffer request = NULL;
|
||||
ssh_buffer reply = NULL;
|
||||
unsigned int type = 0;
|
||||
uint32_t count = 0;
|
||||
int rc;
|
||||
uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session)
|
||||
{
|
||||
ssh_buffer request = NULL;
|
||||
ssh_buffer reply = NULL;
|
||||
unsigned int type = 0;
|
||||
uint32_t count = 0;
|
||||
int rc;
|
||||
|
||||
/* send message to the agent requesting the list of identities */
|
||||
request = ssh_buffer_new();
|
||||
if (request == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
if (ssh_buffer_add_u8(request, SSH2_AGENTC_REQUEST_IDENTITIES) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(request);
|
||||
return -1;
|
||||
}
|
||||
/* send message to the agent requesting the list of identities */
|
||||
request = ssh_buffer_new();
|
||||
if (request == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return 0;
|
||||
}
|
||||
if (ssh_buffer_add_u8(request, SSH2_AGENTC_REQUEST_IDENTITIES) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return 0;
|
||||
}
|
||||
|
||||
reply = ssh_buffer_new();
|
||||
if (reply == NULL) {
|
||||
ssh_buffer_free(request);
|
||||
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
||||
return -1;
|
||||
}
|
||||
reply = ssh_buffer_new();
|
||||
if (reply == NULL) {
|
||||
SSH_BUFFER_FREE(request);
|
||||
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (agent_talk(session, request, reply) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
ssh_buffer_free(reply);
|
||||
return 0;
|
||||
}
|
||||
ssh_buffer_free(request);
|
||||
if (agent_talk(session, request, reply) < 0) {
|
||||
SSH_BUFFER_FREE(request);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return 0;
|
||||
}
|
||||
SSH_BUFFER_FREE(request);
|
||||
|
||||
/* get message type and verify the answer */
|
||||
rc = ssh_buffer_get_u8(reply, (uint8_t *) &type);
|
||||
if (rc != sizeof(uint8_t)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad authentication reply size: %d", rc);
|
||||
ssh_buffer_free(reply);
|
||||
return -1;
|
||||
}
|
||||
/* get message type and verify the answer */
|
||||
rc = ssh_buffer_get_u8(reply, (uint8_t *) &type);
|
||||
if (rc != sizeof(uint8_t)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad authentication reply size: %d", rc);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return 0;
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
type = bswap_32(type);
|
||||
type = bswap_32(type);
|
||||
#endif
|
||||
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Answer type: %d, expected answer: %d",
|
||||
type, SSH2_AGENT_IDENTITIES_ANSWER);
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Answer type: %d, expected answer: %d",
|
||||
type, SSH2_AGENT_IDENTITIES_ANSWER);
|
||||
|
||||
if (agent_failed(type)) {
|
||||
ssh_buffer_free(reply);
|
||||
return 0;
|
||||
} else if (type != SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad authentication reply message type: %u", type);
|
||||
ssh_buffer_free(reply);
|
||||
return -1;
|
||||
}
|
||||
if (agent_failed(type)) {
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return 0;
|
||||
} else if (type != SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad authentication reply message type: %u", type);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_get_u32(reply, &count);
|
||||
if (rc != 4) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to read count");
|
||||
ssh_buffer_free(reply);
|
||||
return -1;
|
||||
}
|
||||
session->agent->count = ntohl(count);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Agent count: %d",
|
||||
session->agent->count);
|
||||
if (session->agent->count > 1024) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Too many identities in authentication reply: %d",
|
||||
session->agent->count);
|
||||
ssh_buffer_free(reply);
|
||||
return -1;
|
||||
}
|
||||
rc = ssh_buffer_get_u32(reply, &count);
|
||||
if (rc != 4) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to read count");
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return 0;
|
||||
}
|
||||
session->agent->count = ntohl(count);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Agent count: %d",
|
||||
session->agent->count);
|
||||
if (session->agent->count > 1024) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Too many identities in authentication reply: %d",
|
||||
session->agent->count);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (session->agent->ident) {
|
||||
ssh_buffer_reinit(session->agent->ident);
|
||||
}
|
||||
session->agent->ident = reply;
|
||||
if (session->agent->ident) {
|
||||
ssh_buffer_reinit(session->agent->ident);
|
||||
}
|
||||
session->agent->ident = reply;
|
||||
|
||||
return session->agent->count;
|
||||
return session->agent->count;
|
||||
}
|
||||
|
||||
/* caller has to free commment */
|
||||
@@ -424,7 +425,7 @@ ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
|
||||
/* get the comment */
|
||||
tmp = ssh_buffer_get_ssh_string(session->agent->ident);
|
||||
if (tmp == NULL) {
|
||||
ssh_string_free(blob);
|
||||
SSH_STRING_FREE(blob);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -432,12 +433,12 @@ ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
|
||||
if (comment) {
|
||||
*comment = ssh_string_to_char(tmp);
|
||||
} else {
|
||||
ssh_string_free(blob);
|
||||
ssh_string_free(tmp);
|
||||
SSH_STRING_FREE(blob);
|
||||
SSH_STRING_FREE(tmp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
ssh_string_free(tmp);
|
||||
SSH_STRING_FREE(tmp);
|
||||
|
||||
/* get key from blob */
|
||||
rc = ssh_pki_import_pubkey_blob(blob, &key);
|
||||
@@ -445,7 +446,7 @@ ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
|
||||
/* Try again as a cert. */
|
||||
rc = ssh_pki_import_cert_blob(blob, &key);
|
||||
}
|
||||
ssh_string_free(blob);
|
||||
SSH_STRING_FREE(blob);
|
||||
if (rc == SSH_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -491,13 +492,13 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
|
||||
/* create request */
|
||||
if (ssh_buffer_add_u8(request, SSH2_AGENTC_SIGN_REQUEST) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_pki_export_pubkey_blob(pubkey, &key_blob);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -512,26 +513,26 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
sizeof(uint32_t) * 2 +
|
||||
ssh_string_len(key_blob));
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* adds len + blob */
|
||||
rc = ssh_buffer_add_ssh_string(request, key_blob);
|
||||
ssh_string_free(key_blob);
|
||||
SSH_STRING_FREE(key_blob);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add data */
|
||||
dlen = ssh_buffer_get_len(data);
|
||||
if (ssh_buffer_add_u32(request, htonl(dlen)) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
if (ssh_buffer_add_data(request, ssh_buffer_get(data), dlen) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -544,27 +545,27 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
}
|
||||
}
|
||||
if (ssh_buffer_add_u32(request, htonl(flags)) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reply = ssh_buffer_new();
|
||||
if (reply == NULL) {
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* send the request */
|
||||
if (agent_talk(session, request, reply) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
ssh_buffer_free(reply);
|
||||
SSH_BUFFER_FREE(request);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return NULL;
|
||||
}
|
||||
ssh_buffer_free(request);
|
||||
SSH_BUFFER_FREE(request);
|
||||
|
||||
/* check if reply is valid */
|
||||
if (ssh_buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) {
|
||||
ssh_buffer_free(reply);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
@@ -573,19 +574,19 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
|
||||
if (agent_failed(type)) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Agent reports failure in signing the key");
|
||||
ssh_buffer_free(reply);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return NULL;
|
||||
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Bad authentication response: %u",
|
||||
type);
|
||||
ssh_buffer_free(reply);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig_blob = ssh_buffer_get_ssh_string(reply);
|
||||
ssh_buffer_free(reply);
|
||||
SSH_BUFFER_FREE(reply);
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
34
src/auth.c
34
src/auth.c
@@ -205,7 +205,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_banner) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Received SSH_USERAUTH_BANNER packet");
|
||||
if (session->banner != NULL)
|
||||
ssh_string_free(session->banner);
|
||||
SSH_STRING_FREE(session->banner);
|
||||
session->banner = banner;
|
||||
}
|
||||
|
||||
@@ -558,7 +558,7 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ssh_string_free(pubkey_s);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
session->auth.state = SSH_AUTH_STATE_PUBKEY_OFFER_SENT;
|
||||
@@ -576,7 +576,7 @@ pending:
|
||||
|
||||
return rc;
|
||||
fail:
|
||||
ssh_string_free(pubkey_s);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
|
||||
@@ -681,7 +681,7 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
|
||||
/* Get the hash type to be used in the signature based on the key type */
|
||||
hash_type = ssh_key_type_to_hash(session, privkey->type);
|
||||
@@ -693,7 +693,7 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, str);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
str = NULL;
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
@@ -715,7 +715,7 @@ pending:
|
||||
|
||||
return rc;
|
||||
fail:
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
|
||||
@@ -841,7 +841,7 @@ void ssh_agent_state_free(void *data) {
|
||||
struct ssh_agent_state_struct *state = data;
|
||||
|
||||
if (state) {
|
||||
ssh_string_free_char(state->comment);
|
||||
SSH_STRING_FREE_CHAR(state->comment);
|
||||
ssh_key_free(state->pubkey);
|
||||
free (state);
|
||||
}
|
||||
@@ -919,7 +919,7 @@ int ssh_userauth_agent(ssh_session session,
|
||||
} else if (rc != SSH_AUTH_SUCCESS) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Public key of %s refused by server", state->comment);
|
||||
ssh_string_free_char(state->comment);
|
||||
SSH_STRING_FREE_CHAR(state->comment);
|
||||
state->comment = NULL;
|
||||
ssh_key_free(state->pubkey);
|
||||
state->pubkey = ssh_agent_get_next_ident(session, &state->comment);
|
||||
@@ -935,7 +935,7 @@ int ssh_userauth_agent(ssh_session session,
|
||||
rc = ssh_userauth_agent_publickey(session, username, state->pubkey);
|
||||
if (rc == SSH_AUTH_AGAIN)
|
||||
return rc;
|
||||
ssh_string_free_char(state->comment);
|
||||
SSH_STRING_FREE_CHAR(state->comment);
|
||||
state->comment = NULL;
|
||||
if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_PARTIAL) {
|
||||
ssh_agent_state_free (session->agent_state);
|
||||
@@ -1031,6 +1031,9 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Set state explicitly */
|
||||
session->auth.auto_state->state = SSH_AUTH_AUTO_STATE_NONE;
|
||||
}
|
||||
state = session->auth.auto_state;
|
||||
if (state->state == SSH_AUTH_AUTO_STATE_NONE) {
|
||||
@@ -1113,7 +1116,9 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
"Public key authentication error for %s",
|
||||
privkey_file);
|
||||
ssh_key_free(state->privkey);
|
||||
state->privkey = NULL;
|
||||
ssh_key_free(state->pubkey);
|
||||
state->pubkey = NULL;
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_AGAIN) {
|
||||
@@ -1179,6 +1184,9 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
return rc;
|
||||
}
|
||||
|
||||
ssh_key_free(state->privkey);
|
||||
ssh_key_free(state->pubkey);
|
||||
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"The server accepted the public key but refused the signature");
|
||||
state->it = state->it->next;
|
||||
@@ -1330,7 +1338,7 @@ ssh_kbdint ssh_kbdint_new(void) {
|
||||
|
||||
|
||||
void ssh_kbdint_free(ssh_kbdint kbd) {
|
||||
int i, n;
|
||||
size_t i, n;
|
||||
|
||||
if (kbd == NULL) {
|
||||
return;
|
||||
@@ -1366,7 +1374,7 @@ void ssh_kbdint_free(ssh_kbdint kbd) {
|
||||
}
|
||||
|
||||
void ssh_kbdint_clean(ssh_kbdint kbd) {
|
||||
int i, n;
|
||||
size_t i, n;
|
||||
|
||||
if (kbd == NULL) {
|
||||
return;
|
||||
@@ -1555,7 +1563,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
||||
);
|
||||
|
||||
/* We don't care about tmp */
|
||||
ssh_string_free(tmp);
|
||||
SSH_STRING_FREE(tmp);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg");
|
||||
@@ -1779,7 +1787,7 @@ const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
|
||||
}
|
||||
|
||||
if (echo) {
|
||||
*echo = session->kbdint->echo[i];
|
||||
*echo = (char)session->kbdint->echo[i];
|
||||
}
|
||||
|
||||
return session->kbdint->prompts[i];
|
||||
|
||||
98
src/base64.c
98
src/base64.c
@@ -29,7 +29,8 @@
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
|
||||
static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
static
|
||||
const uint8_t alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
@@ -167,19 +168,19 @@ ssh_buffer base64_to_bin(const char *source) {
|
||||
|
||||
error:
|
||||
SAFE_FREE(base64);
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define BLOCK(letter, n) do {ptr = strchr(alphabet, source[n]); \
|
||||
#define BLOCK(letter, n) do {ptr = strchr((const char *)alphabet, source[n]); \
|
||||
if(!ptr) return -1; \
|
||||
i = ptr - alphabet; \
|
||||
i = ptr - (const char *)alphabet; \
|
||||
SET_##letter(*block, i); \
|
||||
} while(0)
|
||||
|
||||
/* Returns 0 if ok, -1 if not (ie invalid char into the stuff) */
|
||||
static int to_block4(unsigned long *block, const char *source, int num) {
|
||||
char *ptr;
|
||||
const char *ptr = NULL;
|
||||
unsigned int i;
|
||||
|
||||
*block = 0;
|
||||
@@ -234,29 +235,32 @@ static int get_equals(char *string) {
|
||||
}
|
||||
|
||||
/* thanks sysk for debugging my mess :) */
|
||||
static void _bin_to_base64(uint8_t *dest,
|
||||
const uint8_t source[3],
|
||||
size_t len)
|
||||
{
|
||||
#define BITS(n) ((1 << (n)) - 1)
|
||||
static void _bin_to_base64(unsigned char *dest, const unsigned char source[3],
|
||||
int len) {
|
||||
switch (len) {
|
||||
case 1:
|
||||
dest[0] = alphabet[(source[0] >> 2)];
|
||||
dest[1] = alphabet[((source[0] & BITS(2)) << 4)];
|
||||
dest[2] = '=';
|
||||
dest[3] = '=';
|
||||
break;
|
||||
case 2:
|
||||
dest[0] = alphabet[source[0] >> 2];
|
||||
dest[1] = alphabet[(source[1] >> 4) | ((source[0] & BITS(2)) << 4)];
|
||||
dest[2] = alphabet[(source[1] & BITS(4)) << 2];
|
||||
dest[3] = '=';
|
||||
break;
|
||||
case 3:
|
||||
dest[0] = alphabet[(source[0] >> 2)];
|
||||
dest[1] = alphabet[(source[1] >> 4) | ((source[0] & BITS(2)) << 4)];
|
||||
dest[2] = alphabet[ (source[2] >> 6) | (source[1] & BITS(4)) << 2];
|
||||
dest[3] = alphabet[source[2] & BITS(6)];
|
||||
break;
|
||||
}
|
||||
switch (len) {
|
||||
case 1:
|
||||
dest[0] = alphabet[(source[0] >> 2)];
|
||||
dest[1] = alphabet[((source[0] & BITS(2)) << 4)];
|
||||
dest[2] = '=';
|
||||
dest[3] = '=';
|
||||
break;
|
||||
case 2:
|
||||
dest[0] = alphabet[source[0] >> 2];
|
||||
dest[1] = alphabet[(source[1] >> 4) | ((source[0] & BITS(2)) << 4)];
|
||||
dest[2] = alphabet[(source[1] & BITS(4)) << 2];
|
||||
dest[3] = '=';
|
||||
break;
|
||||
case 3:
|
||||
dest[0] = alphabet[(source[0] >> 2)];
|
||||
dest[1] = alphabet[(source[1] >> 4) | ((source[0] & BITS(2)) << 4)];
|
||||
dest[2] = alphabet[(source[2] >> 6) | (source[1] & BITS(4)) << 2];
|
||||
dest[3] = alphabet[source[2] & BITS(6)];
|
||||
break;
|
||||
}
|
||||
#undef BITS
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,25 +270,29 @@ static void _bin_to_base64(unsigned char *dest, const unsigned char source[3],
|
||||
*
|
||||
* @returns the converted string
|
||||
*/
|
||||
unsigned char *bin_to_base64(const unsigned char *source, int len) {
|
||||
unsigned char *base64;
|
||||
unsigned char *ptr;
|
||||
int flen = len + (3 - (len % 3)); /* round to upper 3 multiple */
|
||||
flen = (4 * flen) / 3 + 1;
|
||||
uint8_t *bin_to_base64(const uint8_t *source, size_t len)
|
||||
{
|
||||
uint8_t *base64 = NULL;
|
||||
uint8_t *ptr = NULL;
|
||||
size_t flen = len + (3 - (len % 3)); /* round to upper 3 multiple */
|
||||
flen = (4 * flen) / 3 + 1;
|
||||
|
||||
base64 = malloc(flen);
|
||||
if (base64 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = base64;
|
||||
base64 = malloc(flen);
|
||||
if (base64 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = base64;
|
||||
|
||||
while(len > 0){
|
||||
_bin_to_base64(ptr, source, len > 3 ? 3 : len);
|
||||
ptr += 4;
|
||||
source += 3;
|
||||
len -= 3;
|
||||
}
|
||||
ptr[0] = '\0';
|
||||
while(len > 0){
|
||||
_bin_to_base64(ptr, source, len > 3 ? 3 : len);
|
||||
ptr += 4;
|
||||
if (len < 3) {
|
||||
break;
|
||||
}
|
||||
source += 3;
|
||||
len -= 3;
|
||||
}
|
||||
ptr[0] = '\0';
|
||||
|
||||
return base64;
|
||||
return base64;
|
||||
}
|
||||
|
||||
13
src/bignum.c
13
src/bignum.c
@@ -29,9 +29,9 @@
|
||||
|
||||
ssh_string ssh_make_bignum_string(bignum num) {
|
||||
ssh_string ptr = NULL;
|
||||
int pad = 0;
|
||||
unsigned int len = bignum_num_bytes(num);
|
||||
unsigned int bits = bignum_num_bits(num);
|
||||
size_t pad = 0;
|
||||
size_t len = bignum_num_bytes(num);
|
||||
size_t bits = bignum_num_bits(num);
|
||||
|
||||
if (len == 0) {
|
||||
return NULL;
|
||||
@@ -43,7 +43,9 @@ ssh_string ssh_make_bignum_string(bignum num) {
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
fprintf(stderr, "%d bits, %d bytes, %d padding\n", bits, len, pad);
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"%zu bits, %zu bytes, %zu padding\n",
|
||||
bits, len, pad);
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
ptr = ssh_string_new(len + pad);
|
||||
@@ -67,7 +69,8 @@ bignum ssh_make_string_bn(ssh_string string)
|
||||
size_t len = ssh_string_len(string);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
fprintf(stderr, "Importing a %zu bits, %zu bytes object ...\n",
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Importing a %zu bits, %zu bytes object ...\n",
|
||||
len * 8, len);
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
|
||||
@@ -411,7 +411,7 @@ void ssh_bind_free(ssh_bind sshbind){
|
||||
ssh_key_free(sshbind->ed25519);
|
||||
sshbind->ed25519 = NULL;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
if (sshbind->wanted_methods[i]) {
|
||||
SAFE_FREE(sshbind->wanted_methods[i]);
|
||||
}
|
||||
@@ -442,7 +442,7 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
||||
session->server = 1;
|
||||
|
||||
/* Copy options from bind to session */
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
if (sshbind->wanted_methods[i]) {
|
||||
session->opts.wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
|
||||
if (session->opts.wanted_methods[i] == NULL) {
|
||||
|
||||
45
src/buffer.c
45
src/buffer.c
@@ -299,28 +299,33 @@ int ssh_buffer_reinit(struct ssh_buffer_struct *buffer)
|
||||
*/
|
||||
int ssh_buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len)
|
||||
{
|
||||
buffer_verify(buffer);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->used + len < len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->allocated < (buffer->used + len)) {
|
||||
if(buffer->pos > 0)
|
||||
buffer_shift(buffer);
|
||||
if (realloc_buffer(buffer, buffer->used + len) < 0) {
|
||||
return -1;
|
||||
if (buffer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buffer->data+buffer->used, data, len);
|
||||
buffer->used+=len;
|
||||
buffer_verify(buffer);
|
||||
return 0;
|
||||
buffer_verify(buffer);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->used + len < len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->allocated < (buffer->used + len)) {
|
||||
if (buffer->pos > 0) {
|
||||
buffer_shift(buffer);
|
||||
}
|
||||
if (realloc_buffer(buffer, buffer->used + len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buffer->data + buffer->used, data, len);
|
||||
buffer->used += len;
|
||||
buffer_verify(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
231
src/channels.c
231
src/channels.c
@@ -29,6 +29,9 @@
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif /* HAVE_SYS_TIME_H */
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
@@ -106,7 +109,7 @@ ssh_channel ssh_channel_new(ssh_session session)
|
||||
channel->stderr_buffer = ssh_buffer_new();
|
||||
if (channel->stderr_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
SSH_BUFFER_FREE(channel->stdout_buffer);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
@@ -117,10 +120,21 @@ ssh_channel ssh_channel_new(ssh_session session)
|
||||
|
||||
if (session->channels == NULL) {
|
||||
session->channels = ssh_list_new();
|
||||
if (session->channels == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SSH_BUFFER_FREE(channel->stdout_buffer);
|
||||
SSH_BUFFER_FREE(channel->stderr_buffer);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ssh_list_prepend(session->channels, channel);
|
||||
|
||||
/* Set states explicitly */
|
||||
channel->state = SSH_CHANNEL_STATE_NOT_OPEN;
|
||||
channel->request_state = SSH_CHANNEL_REQ_STATE_NONE;
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
@@ -280,8 +294,8 @@ static int ssh_channel_open_termination(void *c){
|
||||
static int
|
||||
channel_open(ssh_channel channel,
|
||||
const char *type,
|
||||
int window,
|
||||
int maxpacket,
|
||||
uint32_t window,
|
||||
uint32_t maxpacket,
|
||||
ssh_buffer payload)
|
||||
{
|
||||
ssh_session session = channel->session;
|
||||
@@ -388,7 +402,10 @@ ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id) {
|
||||
* @param minimumsize The minimum acceptable size for the new window.
|
||||
* @return SSH_OK if successful; SSH_ERROR otherwise.
|
||||
*/
|
||||
static int grow_window(ssh_session session, ssh_channel channel, int minimumsize) {
|
||||
static int grow_window(ssh_session session,
|
||||
ssh_channel channel,
|
||||
uint32_t minimumsize)
|
||||
{
|
||||
uint32_t new_window = minimumsize > WINDOWBASE ? minimumsize : WINDOWBASE;
|
||||
int rc;
|
||||
|
||||
@@ -553,7 +570,7 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
|
||||
|
||||
if (channel_default_bufferize(channel, ssh_string_data(str), len,
|
||||
is_stderr) < 0) {
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
@@ -569,7 +586,7 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
|
||||
channel->local_window,
|
||||
channel->remote_window);
|
||||
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
|
||||
if (is_stderr) {
|
||||
buf = channel->stderr_buffer;
|
||||
@@ -837,8 +854,10 @@ SSH_PACKET_CALLBACK(channel_rcv_request) {
|
||||
*
|
||||
* FIXME is the window changed?
|
||||
*/
|
||||
int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
int is_stderr) {
|
||||
int channel_default_bufferize(ssh_channel channel,
|
||||
void *data, size_t len,
|
||||
bool is_stderr)
|
||||
{
|
||||
ssh_session session;
|
||||
|
||||
if(channel == NULL) {
|
||||
@@ -853,8 +872,10 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"placing %d bytes into channel buffer (stderr=%d)", len, is_stderr);
|
||||
if (is_stderr == 0) {
|
||||
"placing %zu bytes into channel buffer (%s)",
|
||||
len,
|
||||
is_stderr ? "stderr" : "stdout");
|
||||
if (!is_stderr) {
|
||||
/* stdout */
|
||||
if (channel->stdout_buffer == NULL) {
|
||||
channel->stdout_buffer = ssh_buffer_new();
|
||||
@@ -866,7 +887,7 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
|
||||
if (ssh_buffer_add_data(channel->stdout_buffer, data, len) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
SSH_BUFFER_FREE(channel->stdout_buffer);
|
||||
channel->stdout_buffer = NULL;
|
||||
return -1;
|
||||
}
|
||||
@@ -882,7 +903,7 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
|
||||
if (ssh_buffer_add_data(channel->stderr_buffer, data, len) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stderr_buffer);
|
||||
SSH_BUFFER_FREE(channel->stderr_buffer);
|
||||
channel->stderr_buffer = NULL;
|
||||
return -1;
|
||||
}
|
||||
@@ -1013,8 +1034,8 @@ int ssh_channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||
payload);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(payload);
|
||||
ssh_string_free(str);
|
||||
SSH_BUFFER_FREE(payload);
|
||||
SSH_STRING_FREE(str);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1096,8 +1117,8 @@ int ssh_channel_open_forward_unix(ssh_channel channel,
|
||||
payload);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(payload);
|
||||
ssh_string_free(str);
|
||||
SSH_BUFFER_FREE(payload);
|
||||
SSH_STRING_FREE(str);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1830,7 +1851,7 @@ int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal,
|
||||
pending:
|
||||
rc = channel_request(channel, "pty-req", buffer, 1);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1890,7 +1911,7 @@ int ssh_channel_change_pty_size(ssh_channel channel, int cols, int rows) {
|
||||
|
||||
rc = channel_request(channel, "window-change", buffer, 0);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1959,7 +1980,7 @@ int ssh_channel_request_subsystem(ssh_channel channel, const char *subsys) {
|
||||
pending:
|
||||
rc = channel_request(channel, "subsystem", buffer, 1);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -2075,7 +2096,7 @@ pending:
|
||||
rc = channel_request(channel, "x11-req", buffer, 1);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2388,7 +2409,7 @@ pending:
|
||||
}
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2460,7 +2481,7 @@ pending:
|
||||
rc = ssh_global_request(session, "cancel-tcpip-forward", buffer, 1);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2518,7 +2539,7 @@ int ssh_channel_request_env(ssh_channel channel, const char *name, const char *v
|
||||
pending:
|
||||
rc = channel_request(channel, "env", buffer,1);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -2587,7 +2608,7 @@ int ssh_channel_request_exec(ssh_channel channel, const char *cmd) {
|
||||
pending:
|
||||
rc = channel_request(channel, "exec", buffer, 1);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2650,7 +2671,7 @@ int ssh_channel_request_send_signal(ssh_channel channel, const char *sig) {
|
||||
|
||||
rc = channel_request(channel, "signal", buffer, 0);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2693,7 +2714,7 @@ int ssh_channel_request_send_break(ssh_channel channel, uint32_t length) {
|
||||
rc = channel_request(channel, "break", buffer, 0);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2921,15 +2942,16 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
/* If the server closed the channel properly, there is nothing to do */
|
||||
if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (channel->state == SSH_CHANNEL_STATE_CLOSED) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Remote channel is closed.");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = ssh_buffer_get_len(stdbuf);
|
||||
/* Read count bytes if len is greater, everything otherwise */
|
||||
len = (len > count ? count : len);
|
||||
@@ -2969,42 +2991,45 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
*
|
||||
* @see ssh_channel_is_eof()
|
||||
*/
|
||||
int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr) {
|
||||
ssh_session session;
|
||||
int to_read;
|
||||
int rc;
|
||||
int blocking;
|
||||
int ssh_channel_read_nonblocking(ssh_channel channel,
|
||||
void *dest,
|
||||
uint32_t count,
|
||||
int is_stderr)
|
||||
{
|
||||
ssh_session session;
|
||||
ssize_t to_read;
|
||||
int rc;
|
||||
int blocking;
|
||||
|
||||
if(channel == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(dest == NULL) {
|
||||
ssh_set_error_invalid(channel->session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(channel == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(dest == NULL) {
|
||||
ssh_set_error_invalid(channel->session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session = channel->session;
|
||||
session = channel->session;
|
||||
|
||||
to_read = ssh_channel_poll(channel, is_stderr);
|
||||
to_read = ssh_channel_poll(channel, is_stderr);
|
||||
|
||||
if (to_read <= 0) {
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (to_read <= 0) {
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return to_read; /* may be an error code */
|
||||
}
|
||||
return to_read; /* may be an error code */
|
||||
}
|
||||
|
||||
if (to_read > (int)count) {
|
||||
to_read = (int)count;
|
||||
}
|
||||
blocking = ssh_is_blocking(session);
|
||||
ssh_set_blocking(session, 0);
|
||||
rc = ssh_channel_read(channel, dest, to_read, is_stderr);
|
||||
ssh_set_blocking(session,blocking);
|
||||
if ((size_t)to_read > count) {
|
||||
to_read = (ssize_t)count;
|
||||
}
|
||||
blocking = ssh_is_blocking(session);
|
||||
ssh_set_blocking(session, 0);
|
||||
rc = ssh_channel_read(channel, dest, (uint32_t)to_read, is_stderr);
|
||||
ssh_set_blocking(session,blocking);
|
||||
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3073,38 +3098,57 @@ int ssh_channel_poll(ssh_channel channel, int is_stderr){
|
||||
*
|
||||
* @see ssh_channel_is_eof()
|
||||
*/
|
||||
int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr){
|
||||
ssh_session session;
|
||||
ssh_buffer stdbuf;
|
||||
struct ssh_channel_read_termination_struct ctx;
|
||||
int rc;
|
||||
int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
|
||||
{
|
||||
ssh_session session;
|
||||
ssh_buffer stdbuf;
|
||||
struct ssh_channel_read_termination_struct ctx;
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
if(channel == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (channel == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session = channel->session;
|
||||
stdbuf = channel->stdout_buffer;
|
||||
session = channel->session;
|
||||
stdbuf = channel->stdout_buffer;
|
||||
|
||||
if (is_stderr) {
|
||||
stdbuf = channel->stderr_buffer;
|
||||
}
|
||||
ctx.buffer = stdbuf;
|
||||
ctx.channel = channel;
|
||||
ctx.count = 1;
|
||||
rc = ssh_handle_packets_termination(channel->session, timeout,
|
||||
ssh_channel_read_termination, &ctx);
|
||||
if(rc ==SSH_ERROR || session->session_state == SSH_SESSION_STATE_ERROR){
|
||||
rc = SSH_ERROR;
|
||||
goto end;
|
||||
}
|
||||
rc = ssh_buffer_get_len(stdbuf);
|
||||
if(rc > 0)
|
||||
goto end;
|
||||
if (channel->remote_eof)
|
||||
rc = SSH_EOF;
|
||||
end:
|
||||
return rc;
|
||||
if (is_stderr) {
|
||||
stdbuf = channel->stderr_buffer;
|
||||
}
|
||||
ctx.buffer = stdbuf;
|
||||
ctx.channel = channel;
|
||||
ctx.count = 1;
|
||||
rc = ssh_handle_packets_termination(channel->session,
|
||||
timeout,
|
||||
ssh_channel_read_termination,
|
||||
&ctx);
|
||||
if (rc == SSH_ERROR ||
|
||||
session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
} else if (rc == SSH_AGAIN) {
|
||||
/* If the above timeout expired, it is ok and we do not need to
|
||||
* attempt to check the read buffer. The calling functions do not
|
||||
* expect us to return SSH_AGAIN either here. */
|
||||
rc = SSH_OK;
|
||||
goto out;
|
||||
}
|
||||
len = ssh_buffer_get_len(stdbuf);
|
||||
if (len > 0) {
|
||||
if (len > INT_MAX) {
|
||||
rc = SSH_ERROR;
|
||||
} else {
|
||||
rc = (int)len;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
if (channel->remote_eof) {
|
||||
rc = SSH_EOF;
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3223,8 +3267,9 @@ static int channel_protocol_select(ssh_channel *rchans, ssh_channel *wchans,
|
||||
}
|
||||
|
||||
/* Just count number of pointers in the array */
|
||||
static int count_ptrs(ssh_channel *ptrs) {
|
||||
int c;
|
||||
static size_t count_ptrs(ssh_channel *ptrs)
|
||||
{
|
||||
size_t c;
|
||||
for (c = 0; ptrs[c] != NULL; c++)
|
||||
;
|
||||
|
||||
@@ -3478,7 +3523,7 @@ pending:
|
||||
payload);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(payload);
|
||||
SSH_BUFFER_FREE(payload);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -3540,7 +3585,7 @@ pending:
|
||||
payload);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(payload);
|
||||
SSH_BUFFER_FREE(payload);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -3581,7 +3626,7 @@ int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status) {
|
||||
|
||||
rc = channel_request(channel, "exit-status", buffer, 0);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3636,7 +3681,7 @@ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig,
|
||||
|
||||
rc = channel_request(channel, "exit-signal", buffer, 0);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
380
src/client.c
380
src/client.c
@@ -243,15 +243,19 @@ end:
|
||||
* @warning this function returning is no proof that DH handshake is
|
||||
* completed
|
||||
*/
|
||||
static int dh_handshake(ssh_session session) {
|
||||
|
||||
int dh_handshake(ssh_session session)
|
||||
{
|
||||
int rc = SSH_AGAIN;
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "dh_handshake_state = %d, kex_type = %d",
|
||||
session->dh_handshake_state, session->next_crypto->kex_type);
|
||||
|
||||
switch (session->dh_handshake_state) {
|
||||
case DH_STATE_INIT:
|
||||
switch(session->next_crypto->kex_type){
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc = ssh_client_dh_init(session);
|
||||
@@ -385,95 +389,101 @@ static void ssh_client_connection_callback(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch(session->session_state) {
|
||||
case SSH_SESSION_STATE_NONE:
|
||||
case SSH_SESSION_STATE_CONNECTING:
|
||||
break;
|
||||
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
||||
ssh_set_fd_towrite(session);
|
||||
ssh_send_banner(session, 0);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "session_state=%d", session->session_state);
|
||||
|
||||
break;
|
||||
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
||||
if (session->serverbanner == NULL) {
|
||||
goto error;
|
||||
}
|
||||
set_status(session, 0.4f);
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"SSH server banner: %s", session->serverbanner);
|
||||
switch (session->session_state) {
|
||||
case SSH_SESSION_STATE_NONE:
|
||||
case SSH_SESSION_STATE_CONNECTING:
|
||||
break;
|
||||
case SSH_SESSION_STATE_SOCKET_CONNECTED:
|
||||
ssh_set_fd_towrite(session);
|
||||
ssh_send_banner(session, 0);
|
||||
|
||||
/* Here we analyze the different protocols the server allows. */
|
||||
rc = ssh_analyze_banner(session, 0);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"No version of SSH protocol usable (banner: %s)",
|
||||
session->serverbanner);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_SESSION_STATE_BANNER_RECEIVED:
|
||||
if (session->serverbanner == NULL) {
|
||||
goto error;
|
||||
}
|
||||
set_status(session, 0.4f);
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"SSH server banner: %s", session->serverbanner);
|
||||
|
||||
ssh_packet_register_socket_callback(session, session->socket);
|
||||
/* Here we analyze the different protocols the server allows. */
|
||||
rc = ssh_analyze_banner(session, 0);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"No version of SSH protocol usable (banner: %s)",
|
||||
session->serverbanner);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_packet_set_default_callbacks(session);
|
||||
session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
|
||||
ssh_packet_register_socket_callback(session, session->socket);
|
||||
|
||||
ssh_packet_set_default_callbacks(session);
|
||||
session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
|
||||
rc = ssh_set_client_kex(session);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_send_kex(session);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
set_status(session, 0.5f);
|
||||
|
||||
break;
|
||||
case SSH_SESSION_STATE_INITIAL_KEX:
|
||||
/* TODO: This state should disappear in favor of get_key handle */
|
||||
break;
|
||||
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
||||
set_status(session, 0.6f);
|
||||
ssh_list_kex(&session->next_crypto->server_kex);
|
||||
if ((session->flags & SSH_SESSION_FLAG_KEXINIT_SENT) == 0) {
|
||||
/* in rekeying state if next_crypto client_kex might be empty */
|
||||
rc = ssh_set_client_kex(session);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_send_kex(session, 0);
|
||||
rc = ssh_send_kex(session);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
set_status(session, 0.5f);
|
||||
|
||||
break;
|
||||
case SSH_SESSION_STATE_INITIAL_KEX:
|
||||
/* TODO: This state should disappear in favor of get_key handle */
|
||||
break;
|
||||
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
|
||||
set_status(session,0.6f);
|
||||
ssh_list_kex(&session->next_crypto->server_kex);
|
||||
if (session->next_crypto->client_kex.methods[0] == NULL) {
|
||||
/* in rekeying state if next_crypto client_kex is empty */
|
||||
rc = ssh_set_client_kex(session);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_send_kex(session, 0);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (ssh_kex_select_methods(session) == SSH_ERROR)
|
||||
goto error;
|
||||
set_status(session,0.8f);
|
||||
session->session_state=SSH_SESSION_STATE_DH;
|
||||
if (dh_handshake(session) == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case SSH_SESSION_STATE_DH:
|
||||
if(session->dh_handshake_state==DH_STATE_FINISHED){
|
||||
set_status(session,1.0f);
|
||||
session->connected = 1;
|
||||
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
||||
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
||||
else
|
||||
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
||||
}
|
||||
break;
|
||||
case SSH_SESSION_STATE_AUTHENTICATING:
|
||||
break;
|
||||
case SSH_SESSION_STATE_ERROR:
|
||||
}
|
||||
if (ssh_kex_select_methods(session) == SSH_ERROR)
|
||||
goto error;
|
||||
default:
|
||||
ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
|
||||
set_status(session, 0.8f);
|
||||
session->session_state = SSH_SESSION_STATE_DH;
|
||||
|
||||
/* If the init packet was already sent in previous step, this will be no
|
||||
* operation */
|
||||
if (dh_handshake(session) == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
case SSH_SESSION_STATE_DH:
|
||||
if (session->dh_handshake_state == DH_STATE_FINISHED) {
|
||||
set_status(session, 1.0f);
|
||||
session->connected = 1;
|
||||
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
||||
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
||||
else
|
||||
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
||||
}
|
||||
break;
|
||||
case SSH_SESSION_STATE_AUTHENTICATING:
|
||||
break;
|
||||
case SSH_SESSION_STATE_ERROR:
|
||||
goto error;
|
||||
default:
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid state %d",
|
||||
session->session_state);
|
||||
}
|
||||
|
||||
return;
|
||||
error:
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive = 0;
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
|
||||
}
|
||||
|
||||
@@ -504,119 +514,138 @@ static int ssh_connect_termination(void *user){
|
||||
* @see ssh_new()
|
||||
* @see ssh_disconnect()
|
||||
*/
|
||||
int ssh_connect(ssh_session session) {
|
||||
int ret;
|
||||
int ssh_connect(ssh_session session)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (session == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (!is_ssh_initialized()) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Library not initialized.");
|
||||
|
||||
switch(session->pending_call_state){
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_CONNECT:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,SSH_FATAL,"Bad call during pending SSH call in ssh_connect");
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session->alive = 0;
|
||||
session->client = 1;
|
||||
|
||||
if (session->opts.fd == SSH_INVALID_SOCKET &&
|
||||
session->opts.host == NULL &&
|
||||
session->opts.ProxyCommand == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Hostname required");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* If the system configuration files were not yet processed, do it now */
|
||||
if (!session->opts.config_processed) {
|
||||
ret = ssh_options_parse_config(session, NULL);
|
||||
if (ret != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to process system configuration files");
|
||||
return SSH_ERROR;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ssh_options_apply(session);
|
||||
if (ret < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (session == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"libssh %s, using threading %s",
|
||||
ssh_copyright(),
|
||||
ssh_threads_get_type());
|
||||
switch(session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_CONNECT:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad call during pending SSH call in ssh_connect");
|
||||
|
||||
session->ssh_connection_callback = ssh_client_connection_callback;
|
||||
session->session_state=SSH_SESSION_STATE_CONNECTING;
|
||||
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
|
||||
session->socket_callbacks.connected=socket_callback_connected;
|
||||
session->socket_callbacks.data=callback_receive_banner;
|
||||
session->socket_callbacks.exception=ssh_socket_exception_callback;
|
||||
session->socket_callbacks.userdata=session;
|
||||
if (session->opts.fd != SSH_INVALID_SOCKET) {
|
||||
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||
ssh_socket_set_fd(session->socket, session->opts.fd);
|
||||
ret=SSH_OK;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session->alive = 0;
|
||||
session->client = 1;
|
||||
|
||||
if (session->opts.fd == SSH_INVALID_SOCKET &&
|
||||
session->opts.host == NULL &&
|
||||
session->opts.ProxyCommand == NULL)
|
||||
{
|
||||
ssh_set_error(session, SSH_FATAL, "Hostname required");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* If the system configuration files were not yet processed, do it now */
|
||||
if (!session->opts.config_processed) {
|
||||
ret = ssh_options_parse_config(session, NULL);
|
||||
if (ret != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to process system configuration files");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ssh_options_apply(session);
|
||||
if (ret < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"libssh %s, using threading %s",
|
||||
ssh_copyright(),
|
||||
ssh_threads_get_type());
|
||||
|
||||
session->ssh_connection_callback = ssh_client_connection_callback;
|
||||
session->session_state = SSH_SESSION_STATE_CONNECTING;
|
||||
ssh_socket_set_callbacks(session->socket, &session->socket_callbacks);
|
||||
session->socket_callbacks.connected = socket_callback_connected;
|
||||
session->socket_callbacks.data = callback_receive_banner;
|
||||
session->socket_callbacks.exception = ssh_socket_exception_callback;
|
||||
session->socket_callbacks.userdata = session;
|
||||
|
||||
if (session->opts.fd != SSH_INVALID_SOCKET) {
|
||||
session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||
ssh_socket_set_fd(session->socket, session->opts.fd);
|
||||
ret = SSH_OK;
|
||||
#ifndef _WIN32
|
||||
} else if (session->opts.ProxyCommand != NULL){
|
||||
ret = ssh_socket_connect_proxycommand(session->socket,
|
||||
session->opts.ProxyCommand);
|
||||
} else if (session->opts.ProxyCommand != NULL) {
|
||||
ret = ssh_socket_connect_proxycommand(session->socket,
|
||||
session->opts.ProxyCommand);
|
||||
#endif
|
||||
} else {
|
||||
ret=ssh_socket_connect(session->socket,
|
||||
session->opts.host,
|
||||
session->opts.port > 0 ? session->opts.port : 22,
|
||||
session->opts.bindaddr);
|
||||
}
|
||||
if (ret == SSH_ERROR) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
} else {
|
||||
ret = ssh_socket_connect(session->socket,
|
||||
session->opts.host,
|
||||
session->opts.port > 0 ? session->opts.port : 22,
|
||||
session->opts.bindaddr);
|
||||
}
|
||||
if (ret == SSH_ERROR) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
set_status(session, 0.2f);
|
||||
set_status(session, 0.2f);
|
||||
|
||||
session->alive = 1;
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"Socket connecting, now waiting for the callbacks to work");
|
||||
|
||||
session->alive = 1;
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
|
||||
pending:
|
||||
session->pending_call_state=SSH_PENDING_CALL_CONNECT;
|
||||
if(ssh_is_blocking(session)) {
|
||||
int timeout = (session->opts.timeout * 1000) +
|
||||
(session->opts.timeout_usec / 1000);
|
||||
if (timeout == 0) {
|
||||
timeout = 10 * 1000;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET,"Actual timeout : %d", timeout);
|
||||
ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
|
||||
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
||||
(ret == SSH_ERROR || !ssh_connect_termination(session))) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Timeout connecting to %s", session->opts.host);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = ssh_handle_packets_termination(session,
|
||||
SSH_TIMEOUT_NONBLOCKING,
|
||||
ssh_connect_termination,
|
||||
session);
|
||||
if (ret == SSH_ERROR) {
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET,"current state : %d",session->session_state);
|
||||
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
|
||||
return SSH_AGAIN;
|
||||
}
|
||||
session->pending_call_state = SSH_PENDING_CALL_CONNECT;
|
||||
if(ssh_is_blocking(session)) {
|
||||
int timeout = (session->opts.timeout * 1000) +
|
||||
(session->opts.timeout_usec / 1000);
|
||||
if (timeout == 0) {
|
||||
timeout = 10 * 1000;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Actual timeout : %d", timeout);
|
||||
ret = ssh_handle_packets_termination(session, timeout,
|
||||
ssh_connect_termination, session);
|
||||
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
||||
(ret == SSH_ERROR || !ssh_connect_termination(session)))
|
||||
{
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Timeout connecting to %s", session->opts.host);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
}
|
||||
} else {
|
||||
ret = ssh_handle_packets_termination(session,
|
||||
SSH_TIMEOUT_NONBLOCKING,
|
||||
ssh_connect_termination,
|
||||
session);
|
||||
if (ret == SSH_ERROR) {
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
session->pending_call_state=SSH_PENDING_CALL_NONE;
|
||||
if(session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED)
|
||||
return SSH_ERROR;
|
||||
return SSH_OK;
|
||||
SSH_LOG(SSH_LOG_PACKET, "current state : %d", session->session_state);
|
||||
if (!ssh_is_blocking(session) && !ssh_connect_termination(session)) {
|
||||
return SSH_AGAIN;
|
||||
}
|
||||
|
||||
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||
session->session_state == SSH_SESSION_STATE_DISCONNECTED)
|
||||
{
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -701,6 +730,7 @@ error:
|
||||
}
|
||||
session->opts.fd = SSH_INVALID_SOCKET;
|
||||
session->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));
|
||||
@@ -750,7 +780,7 @@ error:
|
||||
}
|
||||
|
||||
const char *ssh_copyright(void) {
|
||||
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2019 "
|
||||
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2021 "
|
||||
"Aris Adamantiadis, Andreas Schneider "
|
||||
"and libssh contributors. "
|
||||
"Distributed under the LGPL, please refer to COPYING "
|
||||
|
||||
@@ -394,6 +394,11 @@ ssh_config_parse_line(ssh_session session,
|
||||
long l;
|
||||
int64_t ll;
|
||||
|
||||
/* Ignore empty lines */
|
||||
if (line == NULL || *line == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
x = s = strdup(line);
|
||||
if (s == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
@@ -420,6 +425,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
opcode != SOC_HOST &&
|
||||
opcode != SOC_MATCH &&
|
||||
opcode != SOC_INCLUDE &&
|
||||
opcode != SOC_IDENTITY &&
|
||||
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
|
||||
/* Skip all the options that were already applied */
|
||||
if (seen[opcode] != 0) {
|
||||
|
||||
@@ -25,9 +25,13 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif /* HAVE_SYS_TIME_H */
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
@@ -172,6 +172,11 @@ int ssh_client_curve25519_init(ssh_session session)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void ssh_client_curve25519_remove_callbacks(ssh_session session)
|
||||
{
|
||||
ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks);
|
||||
}
|
||||
|
||||
static int ssh_curve25519_build_k(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey k;
|
||||
@@ -179,8 +184,8 @@ static int ssh_curve25519_build_k(ssh_session session)
|
||||
#ifdef HAVE_OPENSSL_X25519
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
||||
size_t shared_key_len;
|
||||
int rc;
|
||||
size_t shared_key_len = sizeof(k);
|
||||
int rc, ret = SSH_ERROR;
|
||||
|
||||
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
@@ -197,8 +202,7 @@ static int ssh_curve25519_build_k(ssh_session session)
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_init(pctx);
|
||||
@@ -206,9 +210,7 @@ static int ssh_curve25519_build_k(ssh_session session)
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 key derivation: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
@@ -224,9 +226,7 @@ static int ssh_curve25519_build_k(ssh_session session)
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 public key EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
|
||||
@@ -234,23 +234,23 @@ static int ssh_curve25519_build_k(ssh_session session)
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to set peer X25519 public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_free(pubkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive(pctx,
|
||||
k,
|
||||
&shared_key_len);
|
||||
rc = EVP_PKEY_derive(pctx, k, &shared_key_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to derive X25519 shared secret: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_free(pubkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
ret = SSH_OK;
|
||||
out:
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_free(pubkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (ret == SSH_ERROR) {
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
if (session->server) {
|
||||
@@ -290,7 +290,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks);
|
||||
ssh_client_curve25519_remove_callbacks(session);
|
||||
|
||||
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if (pubkey_blob == NULL) {
|
||||
@@ -299,7 +299,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
|
||||
}
|
||||
|
||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||
ssh_string_free(pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
@@ -315,11 +315,11 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
|
||||
if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){
|
||||
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
|
||||
(int)ssh_string_len(q_s_string));
|
||||
ssh_string_free(q_s_string);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
goto error;
|
||||
}
|
||||
memcpy(session->next_crypto->curve25519_server_pubkey, ssh_string_data(q_s_string), CURVE25519_PUBKEY_SIZE);
|
||||
ssh_string_free(q_s_string);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
|
||||
signature = ssh_buffer_get_ssh_string(packet);
|
||||
if (signature == NULL) {
|
||||
@@ -382,12 +382,12 @@ void ssh_server_curve25519_init(ssh_session session){
|
||||
*/
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
/* ECDH keys */
|
||||
ssh_string q_c_string;
|
||||
ssh_string q_s_string;
|
||||
ssh_string q_c_string = NULL;
|
||||
ssh_string q_s_string = NULL;
|
||||
ssh_string server_pubkey_blob = NULL;
|
||||
|
||||
/* SSH host keys (rsa,dsa,ecdsa) */
|
||||
ssh_key privkey;
|
||||
ssh_key privkey = NULL;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
int rc;
|
||||
@@ -407,13 +407,12 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
SSH_FATAL,
|
||||
"Incorrect size for server Curve25519 public key: %zu",
|
||||
ssh_string_len(q_c_string));
|
||||
ssh_string_free(q_c_string);
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(session->next_crypto->curve25519_client_pubkey,
|
||||
ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
|
||||
ssh_string_free(q_c_string);
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
/* Build server's keypair */
|
||||
|
||||
rc = ssh_curve25519_init(session);
|
||||
@@ -456,7 +455,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
/* add host's public key */
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer,
|
||||
server_pubkey_blob);
|
||||
ssh_string_free(server_pubkey_blob);
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
@@ -465,15 +464,20 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
/* add ecdh public key */
|
||||
q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
|
||||
if (q_s_string == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_string_fill(q_s_string,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
rc = ssh_string_fill(q_s_string,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not copy public key");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, q_s_string);
|
||||
ssh_string_free(q_s_string);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
@@ -486,7 +490,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, sig_blob);
|
||||
ssh_string_free(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
@@ -513,6 +517,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
error:
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
21
src/dh-gex.c
21
src/dh-gex.c
@@ -238,6 +238,11 @@ error:
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
void ssh_client_dhgex_remove_callbacks(ssh_session session)
|
||||
{
|
||||
ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks);
|
||||
}
|
||||
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto=session->next_crypto;
|
||||
@@ -248,7 +253,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
||||
(void)user;
|
||||
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_REPLY received");
|
||||
|
||||
ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks);
|
||||
ssh_client_dhgex_remove_callbacks(session);
|
||||
rc = ssh_buffer_unpack(packet,
|
||||
"SBS",
|
||||
&pubkey_blob, &server_pubkey,
|
||||
@@ -263,9 +268,11 @@ 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);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
if (rc != 0) {
|
||||
goto error;
|
||||
}
|
||||
@@ -293,6 +300,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
error:
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
ssh_dh_cleanup(session->next_crypto);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
|
||||
@@ -366,8 +374,13 @@ static bool dhgroup_better_size(uint32_t pmin,
|
||||
*/
|
||||
static bool invn_chance(int n)
|
||||
{
|
||||
uint32_t nounce;
|
||||
ssh_get_random(&nounce, sizeof(nounce), 0);
|
||||
uint32_t nounce = 0;
|
||||
int ok;
|
||||
|
||||
ok = ssh_get_random(&nounce, sizeof(nounce), 0);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
return (nounce % n) == 0;
|
||||
}
|
||||
|
||||
|
||||
34
src/dh.c
34
src/dh.c
@@ -342,6 +342,11 @@ error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
void ssh_client_dh_remove_callbacks(ssh_session session)
|
||||
{
|
||||
ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
||||
struct ssh_crypto_struct *crypto=session->next_crypto;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
@@ -351,7 +356,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
|
||||
ssh_client_dh_remove_callbacks(session);
|
||||
|
||||
rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey,
|
||||
&crypto->dh_server_signature);
|
||||
@@ -361,11 +366,12 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
||||
rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR,
|
||||
NULL, server_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
bignum_safe_free(server_pubkey);
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||
ssh_string_free(pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
if (rc != 0) {
|
||||
goto error;
|
||||
}
|
||||
@@ -482,6 +488,7 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
|
||||
switch (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:
|
||||
packet_type = SSH2_MSG_KEXDH_REPLY;
|
||||
@@ -696,13 +703,16 @@ static char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len)
|
||||
/**
|
||||
* @brief Get a hash as a human-readable hex- or base64-string.
|
||||
*
|
||||
* This gets an allocated fingerprint hash. It is a hex strings if the given
|
||||
* hash is a md5 sum. If it is a SHA sum, it will return an unpadded base64
|
||||
* strings. Either way, the output is prepended by the hash-type.
|
||||
* This gets an allocated fingerprint hash. If it is a SHA sum, it will
|
||||
* return an unpadded base64 strings. If it is a MD5 sum, it will return hex
|
||||
* string. Either way, the output is prepended by the hash-type.
|
||||
*
|
||||
* @param type Which sort of hash is given.
|
||||
* @warning Do NOT use MD5 or SHA1! Those hash functions are being deprecated.
|
||||
*
|
||||
* @param hash What should be converted to a base64 string.
|
||||
* @param type Which sort of hash is given, use
|
||||
* SSH_PUBLICKEY_HASH_SHA256 or better.
|
||||
*
|
||||
* @param hash The hash to be converted to fingerprint.
|
||||
*
|
||||
* @param len Length of the buffer to convert.
|
||||
*
|
||||
@@ -769,13 +779,13 @@ char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
|
||||
/**
|
||||
* @brief Print a hash as a human-readable hex- or base64-string.
|
||||
*
|
||||
* This function prints hex strings if the given hash is a md5 sum.
|
||||
* But prints unpadded base64 strings for sha sums.
|
||||
* Either way, the output is prepended by the hash-type.
|
||||
* This prints an unpadded base64 strings for SHA sums and hex strings for MD5
|
||||
* sum. Either way, the output is prepended by the hash-type.
|
||||
*
|
||||
* @param type Which sort of hash is given.
|
||||
* @param type Which sort of hash is given. Use
|
||||
* SSH_PUBLICKEY_HASH_SHA256 or better.
|
||||
*
|
||||
* @param hash What should be converted to a base64 string.
|
||||
* @param hash The hash to be converted to fingerprint.
|
||||
*
|
||||
* @param len Length of the buffer to convert.
|
||||
*
|
||||
|
||||
@@ -179,6 +179,7 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
||||
rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator);
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator);
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
|
||||
@@ -247,6 +247,7 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
||||
rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator);
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator);
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
|
||||
@@ -43,6 +43,11 @@ struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks = {
|
||||
.user = NULL
|
||||
};
|
||||
|
||||
void ssh_client_ecdh_remove_callbacks(ssh_session session)
|
||||
{
|
||||
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
|
||||
* a SSH_MSG_NEWKEYS
|
||||
@@ -55,7 +60,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
|
||||
ssh_client_ecdh_remove_callbacks(session);
|
||||
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if (pubkey_blob == NULL) {
|
||||
ssh_set_error(session,SSH_FATAL, "No public key in packet");
|
||||
@@ -63,7 +68,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){
|
||||
}
|
||||
|
||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||
ssh_string_free(pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
if (rc != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ int ssh_client_ecdh_init(ssh_session session){
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer,client_pubkey);
|
||||
if (rc < 0) {
|
||||
EC_KEY_free(key);
|
||||
ssh_string_free(client_pubkey);
|
||||
SSH_STRING_FREE(client_pubkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not export server public key");
|
||||
ssh_string_free(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -309,8 +309,8 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
q_s_string, /* ecdh public key */
|
||||
sig_blob); /* signature blob */
|
||||
|
||||
ssh_string_free(sig_blob);
|
||||
ssh_string_free(pubkey_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
|
||||
@@ -115,7 +115,7 @@ int ssh_client_ecdh_init(ssh_session session)
|
||||
out:
|
||||
gcry_sexp_release(param);
|
||||
gcry_sexp_release(key);
|
||||
ssh_string_free(client_pubkey);
|
||||
SSH_STRING_FREE(client_pubkey);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -215,13 +215,13 @@ int ecdh_build_k(ssh_session session)
|
||||
k_len = 133;
|
||||
} else {
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ssh_string_len(s) != k_len) {
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ int ecdh_build_k(ssh_session session)
|
||||
k_len / 2,
|
||||
NULL);
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
@@ -254,7 +254,7 @@ int ecdh_build_k(ssh_session session)
|
||||
gcry_sexp_release(data);
|
||||
gcry_sexp_release(result);
|
||||
ssh_string_burn(privkey);
|
||||
ssh_string_free(privkey);
|
||||
SSH_STRING_FREE(privkey);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not export server public key");
|
||||
ssh_string_free(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -358,8 +358,8 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
q_s_string, /* ecdh public key */
|
||||
sig_blob); /* signature blob */
|
||||
|
||||
ssh_string_free(sig_blob);
|
||||
ssh_string_free(pubkey_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
|
||||
@@ -113,7 +113,7 @@ int ssh_client_ecdh_init(ssh_session session)
|
||||
|
||||
out:
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
ssh_string_free(client_pubkey);
|
||||
SSH_STRING_FREE(client_pubkey);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -274,7 +274,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not export server public key");
|
||||
ssh_string_free(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -284,8 +284,8 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
q_s_string, /* ecdh public key */
|
||||
sig_blob); /* signature blob */
|
||||
|
||||
ssh_string_free(sig_blob);
|
||||
ssh_string_free(pubkey_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
|
||||
2
src/external/bcrypt_pbkdf.c
vendored
2
src/external/bcrypt_pbkdf.c
vendored
@@ -87,7 +87,7 @@ bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
|
||||
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
|
||||
&j);
|
||||
for (i = 0; i < 64; i++)
|
||||
ssh_blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
|
||||
ssh_blf_enc(&state, cdata, BCRYPT_BLOCKS/2);
|
||||
|
||||
/* copy out */
|
||||
for (i = 0; i < BCRYPT_BLOCKS; i++) {
|
||||
|
||||
8
src/external/ed25519.c
vendored
8
src/external/ed25519.c
vendored
@@ -77,8 +77,8 @@ static void get_hram(unsigned char *hram,
|
||||
}
|
||||
|
||||
|
||||
int crypto_sign_ed25519_keypair(unsigned char *pk,
|
||||
unsigned char *sk)
|
||||
int crypto_sign_ed25519_keypair(ed25519_pubkey pk,
|
||||
ed25519_privkey sk)
|
||||
{
|
||||
sc25519 scsk;
|
||||
ge25519 gepk;
|
||||
@@ -114,7 +114,7 @@ int crypto_sign_ed25519(unsigned char *sm,
|
||||
uint64_t *smlen,
|
||||
const unsigned char *m,
|
||||
uint64_t mlen,
|
||||
const unsigned char *sk)
|
||||
const ed25519_privkey sk)
|
||||
{
|
||||
sc25519 sck, scs, scsk;
|
||||
ge25519 ger;
|
||||
@@ -177,7 +177,7 @@ int crypto_sign_ed25519_open(unsigned char *m,
|
||||
uint64_t *mlen,
|
||||
const unsigned char *sm,
|
||||
uint64_t smlen,
|
||||
const unsigned char *pk)
|
||||
const ed25519_pubkey pk)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
4
src/external/fe25519.c
vendored
4
src/external/fe25519.c
vendored
@@ -120,10 +120,10 @@ void fe25519_pack(unsigned char r[32], const fe25519 *x)
|
||||
}
|
||||
}
|
||||
|
||||
int fe25519_iszero(const fe25519 *x)
|
||||
uint32_t fe25519_iszero(const fe25519 *x)
|
||||
{
|
||||
int i;
|
||||
int r;
|
||||
uint32_t r;
|
||||
|
||||
fe25519 t = *x;
|
||||
fe25519_freeze(&t);
|
||||
|
||||
4
src/external/sc25519.c
vendored
4
src/external/sc25519.c
vendored
@@ -223,7 +223,7 @@ int sc25519_lt_vartime(const sc25519 *x, const sc25519 *y)
|
||||
|
||||
void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y)
|
||||
{
|
||||
int i, carry;
|
||||
uint32_t i, carry;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
r->v[i] = x->v[i] + y->v[i];
|
||||
@@ -253,7 +253,7 @@ void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y)
|
||||
|
||||
void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y)
|
||||
{
|
||||
int i,j,carry;
|
||||
uint32_t i,j,carry;
|
||||
uint32_t t[64];
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
|
||||
@@ -255,7 +255,11 @@ int ssh_getpass(const char *prompt,
|
||||
|
||||
/* disable nonblocking I/O */
|
||||
if (fd & O_NDELAY) {
|
||||
fcntl(0, F_SETFL, fd & ~O_NDELAY);
|
||||
ok = fcntl(0, F_SETFL, fd & ~O_NDELAY);
|
||||
if (ok < 0) {
|
||||
perror("fcntl");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ok = ssh_gets(prompt, buf, len, verify);
|
||||
@@ -267,7 +271,11 @@ int ssh_getpass(const char *prompt,
|
||||
|
||||
/* close fd */
|
||||
if (fd & O_NDELAY) {
|
||||
fcntl(0, F_SETFL, fd);
|
||||
ok = fcntl(0, F_SETFL, fd);
|
||||
if (ok < 0) {
|
||||
perror("fcntl");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
|
||||
100
src/gssapi.c
100
src/gssapi.c
@@ -208,7 +208,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
return SSH_ERROR;
|
||||
session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN;
|
||||
rc = ssh_gssapi_send_response(session, oid_s);
|
||||
ssh_string_free(oid_s);
|
||||
SSH_STRING_FREE(oid_s);
|
||||
return rc;
|
||||
} else {
|
||||
return ssh_auth_reply_default(session,0);
|
||||
@@ -223,6 +223,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
"indicate mechs",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
gss_release_oid_set(&min_stat, &both_supported);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -235,6 +236,10 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
for (i=0 ; i< n_oid ; ++i){
|
||||
unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]);
|
||||
size_t len = ssh_string_len(oids[i]);
|
||||
|
||||
if (oid_s == NULL) {
|
||||
continue;
|
||||
}
|
||||
if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){
|
||||
SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID");
|
||||
continue;
|
||||
@@ -255,8 +260,10 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
return SSH_OK;
|
||||
}
|
||||
/* from now we have room for context */
|
||||
if (ssh_gssapi_init(session) == SSH_ERROR)
|
||||
if (ssh_gssapi_init(session) == SSH_ERROR) {
|
||||
gss_release_oid_set(&min_stat, &both_supported);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
name_buf.value = service_name;
|
||||
name_buf.length = strlen(name_buf.value) + 1;
|
||||
@@ -268,6 +275,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
"importing name",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
gss_release_oid_set(&min_stat, &both_supported);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -293,6 +301,10 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
for (i=0 ; i< n_oid ; ++i){
|
||||
unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]);
|
||||
size_t len = ssh_string_len(oids[i]);
|
||||
|
||||
if (oid_s == NULL) {
|
||||
continue;
|
||||
}
|
||||
if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){
|
||||
SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID");
|
||||
continue;
|
||||
@@ -330,6 +342,7 @@ static char *ssh_gssapi_name_to_char(gss_name_t name){
|
||||
min_stat);
|
||||
ptr = malloc(buffer.length + 1);
|
||||
if (ptr == NULL) {
|
||||
gss_release_buffer(&min_stat, &buffer);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(ptr, buffer.value, buffer.length);
|
||||
@@ -384,7 +397,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
ssh_packet_send(session);
|
||||
ssh_string_free(out_token);
|
||||
SSH_STRING_FREE(out_token);
|
||||
} else {
|
||||
session->gssapi->state = SSH_GSSAPI_STATE_RCV_MIC;
|
||||
}
|
||||
@@ -403,7 +416,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
||||
"accepting token",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
ssh_string_free(token);
|
||||
SSH_STRING_FREE(token);
|
||||
if (client_name != GSS_C_NO_NAME){
|
||||
session->gssapi->client_name = client_name;
|
||||
session->gssapi->canonic_user = ssh_gssapi_name_to_char(client_name);
|
||||
@@ -413,6 +426,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
||||
"Gssapi error",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
gss_release_buffer(&min_stat, &output_token);
|
||||
ssh_auth_reply_default(session,0);
|
||||
ssh_gssapi_free(session);
|
||||
session->gssapi=NULL;
|
||||
@@ -430,6 +444,9 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){
|
||||
(size_t)output_token.length, output_token.value);
|
||||
ssh_packet_send(session);
|
||||
}
|
||||
|
||||
gss_release_buffer(&min_stat, &output_token);
|
||||
|
||||
if(maj_stat == GSS_S_COMPLETE){
|
||||
session->gssapi->state = SSH_GSSAPI_STATE_RCV_MIC;
|
||||
}
|
||||
@@ -444,24 +461,28 @@ static ssh_buffer ssh_gssapi_build_mic(ssh_session session)
|
||||
ssh_buffer mic_buffer = NULL;
|
||||
int rc;
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_BOTH);
|
||||
if (crypto == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mic_buffer = ssh_buffer_new();
|
||||
if (mic_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_BOTH);
|
||||
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",
|
||||
"gssapi-with-mic");
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(mic_buffer);
|
||||
SSH_BUFFER_FREE(mic_buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -545,10 +566,10 @@ error:
|
||||
end:
|
||||
ssh_gssapi_free(session);
|
||||
if (mic_buffer != NULL) {
|
||||
ssh_buffer_free(mic_buffer);
|
||||
SSH_BUFFER_FREE(mic_buffer);
|
||||
}
|
||||
if (mic_token != NULL) {
|
||||
ssh_string_free(mic_token);
|
||||
SSH_STRING_FREE(mic_token);
|
||||
}
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
@@ -626,7 +647,7 @@ fail:
|
||||
static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
|
||||
{
|
||||
OM_uint32 maj_stat, min_stat, lifetime;
|
||||
gss_OID_set actual_mechs;
|
||||
gss_OID_set actual_mechs = GSS_C_NO_OID_SET;
|
||||
gss_buffer_desc namebuf;
|
||||
gss_name_t client_id = GSS_C_NO_NAME;
|
||||
gss_OID oid;
|
||||
@@ -688,6 +709,7 @@ static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
|
||||
ret = SSH_OK;
|
||||
|
||||
end:
|
||||
gss_release_oid_set(&min_stat, &actual_mechs);
|
||||
gss_release_name(&min_stat, &client_id);
|
||||
return ret;
|
||||
}
|
||||
@@ -700,13 +722,13 @@ end:
|
||||
* later.
|
||||
*/
|
||||
int ssh_gssapi_auth_mic(ssh_session session){
|
||||
int i;
|
||||
gss_OID_set selected; /* oid selected for authentication */
|
||||
ssh_string *oids;
|
||||
size_t i;
|
||||
gss_OID_set selected = GSS_C_NO_OID_SET; /* oid selected for authentication */
|
||||
ssh_string *oids = NULL;
|
||||
int rc;
|
||||
int n_oids = 0;
|
||||
size_t n_oids = 0;
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
char name_buf[256];
|
||||
char name_buf[256] = {0};
|
||||
gss_buffer_desc hostname;
|
||||
const char *gss_host = session->opts.host;
|
||||
|
||||
@@ -750,7 +772,7 @@ int ssh_gssapi_auth_mic(ssh_session session){
|
||||
}
|
||||
|
||||
n_oids = selected->count;
|
||||
SSH_LOG(SSH_LOG_PROTOCOL, "Sending %d oids", n_oids);
|
||||
SSH_LOG(SSH_LOG_PROTOCOL, "Sending %zu oids", n_oids);
|
||||
|
||||
oids = calloc(n_oids, sizeof(ssh_string));
|
||||
if (oids == NULL) {
|
||||
@@ -760,6 +782,11 @@ int ssh_gssapi_auth_mic(ssh_session session){
|
||||
|
||||
for (i=0; i<n_oids; ++i){
|
||||
oids[i] = ssh_string_new(selected->elements[i].length + 2);
|
||||
if (oids[i] == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
((unsigned char *)oids[i]->data)[0] = SSH_OID_TAG;
|
||||
((unsigned char *)oids[i]->data)[1] = selected->elements[i].length;
|
||||
memcpy((unsigned char *)oids[i]->data + 2, selected->elements[i].elements,
|
||||
@@ -767,10 +794,14 @@ int ssh_gssapi_auth_mic(ssh_session session){
|
||||
}
|
||||
|
||||
rc = ssh_gssapi_send_auth_mic(session, oids, n_oids);
|
||||
|
||||
out:
|
||||
for (i = 0; i < n_oids; i++) {
|
||||
ssh_string_free(oids[i]);
|
||||
SSH_STRING_FREE(oids[i]);
|
||||
}
|
||||
free(oids);
|
||||
gss_release_oid_set(&min_stat, &selected);
|
||||
|
||||
if (rc != SSH_ERROR) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
}
|
||||
@@ -778,13 +809,13 @@ int ssh_gssapi_auth_mic(ssh_session session){
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
static gss_OID ssh_gssapi_oid_from_string(ssh_string oid_s){
|
||||
gss_OID ret;
|
||||
static gss_OID ssh_gssapi_oid_from_string(ssh_string oid_s)
|
||||
{
|
||||
gss_OID ret = NULL;
|
||||
unsigned char *data = ssh_string_data(oid_s);
|
||||
size_t len = ssh_string_len(oid_s);
|
||||
|
||||
ret = malloc(sizeof(gss_OID_desc));
|
||||
if (ret == NULL) {
|
||||
if (data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -792,10 +823,17 @@ static gss_OID ssh_gssapi_oid_from_string(ssh_string oid_s){
|
||||
SAFE_FREE(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data[0] != SSH_OID_TAG || data[1] != len - 2) {
|
||||
SAFE_FREE(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = malloc(sizeof(gss_OID_desc));
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->elements = malloc(len - 2);
|
||||
if (ret->elements == NULL) {
|
||||
SAFE_FREE(ret);
|
||||
@@ -828,7 +866,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){
|
||||
goto error;
|
||||
}
|
||||
session->gssapi->client.oid = ssh_gssapi_oid_from_string(oid_s);
|
||||
ssh_string_free(oid_s);
|
||||
SSH_STRING_FREE(oid_s);
|
||||
if (!session->gssapi->client.oid) {
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid OID");
|
||||
goto error;
|
||||
@@ -867,6 +905,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){
|
||||
ssh_packet_send(session);
|
||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN;
|
||||
}
|
||||
|
||||
gss_release_buffer(&min_stat, &output_token);
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
@@ -895,9 +935,11 @@ static int ssh_gssapi_send_mic(ssh_session session){
|
||||
|
||||
maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT,
|
||||
&mic_buf, &mic_token_buf);
|
||||
|
||||
SSH_BUFFER_FREE(mic_buffer);
|
||||
|
||||
if (GSS_ERROR(maj_stat)){
|
||||
ssh_buffer_free(mic_buffer);
|
||||
ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
|
||||
ssh_gssapi_log_error(SSH_LOG_DEBUG,
|
||||
"generating MIC",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
@@ -909,8 +951,10 @@ static int ssh_gssapi_send_mic(ssh_session session){
|
||||
SSH2_MSG_USERAUTH_GSSAPI_MIC,
|
||||
mic_token_buf.length,
|
||||
(size_t)mic_token_buf.length, mic_token_buf.value);
|
||||
|
||||
gss_release_buffer(&min_stat, &mic_token_buf);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_buffer_free(mic_buffer);
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -958,7 +1002,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
||||
"accepting token",
|
||||
maj_stat,
|
||||
min_stat);
|
||||
ssh_string_free(token);
|
||||
SSH_STRING_FREE(token);
|
||||
if (GSS_ERROR(maj_stat)){
|
||||
ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
|
||||
"Gssapi error",
|
||||
@@ -979,6 +1023,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
||||
ssh_packet_send(session);
|
||||
}
|
||||
|
||||
gss_release_buffer(&min_stat, &output_token);
|
||||
|
||||
if (maj_stat == GSS_S_COMPLETE) {
|
||||
ssh_gssapi_send_mic(session);
|
||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT;
|
||||
|
||||
26
src/gzip.c
26
src/gzip.c
@@ -90,14 +90,14 @@ static ssh_buffer gzip_compress(ssh_session session, ssh_buffer source, int leve
|
||||
zout->avail_out = BLOCKSIZE;
|
||||
status = deflate(zout, Z_PARTIAL_FLUSH);
|
||||
if (status != Z_OK) {
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"status %d deflating zlib packet", status);
|
||||
return NULL;
|
||||
}
|
||||
len = BLOCKSIZE - zout->avail_out;
|
||||
if (ssh_buffer_add_data(dest, out_buf, len) < 0) {
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return NULL;
|
||||
}
|
||||
zout->next_out = out_buf;
|
||||
@@ -115,16 +115,16 @@ int compress_buffer(ssh_session session, ssh_buffer buf) {
|
||||
}
|
||||
|
||||
if (ssh_buffer_reinit(buf) < 0) {
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssh_buffer_add_data(buf, ssh_buffer_get(dest), ssh_buffer_get_len(dest)) < 0) {
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -162,6 +162,10 @@ static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t
|
||||
int status;
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||
if (crypto == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zin = crypto->compress_in_ctx;
|
||||
if (zin == NULL) {
|
||||
zin = crypto->compress_in_ctx = initdecompress(session);
|
||||
@@ -185,18 +189,18 @@ static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t
|
||||
if (status != Z_OK && status != Z_BUF_ERROR) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"status %d inflating zlib packet", status);
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = BLOCKSIZE - zin->avail_out;
|
||||
if (ssh_buffer_add_data(dest,out_buf,len) < 0) {
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return NULL;
|
||||
}
|
||||
if (ssh_buffer_get_len(dest) > maxlen){
|
||||
/* Size of packet exceeded, avoid a denial of service attack */
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return NULL;
|
||||
}
|
||||
zin->next_out = out_buf;
|
||||
@@ -214,15 +218,15 @@ int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen){
|
||||
}
|
||||
|
||||
if (ssh_buffer_reinit(buf) < 0) {
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssh_buffer_add_data(buf, ssh_buffer_get(dest), ssh_buffer_get_len(dest)) < 0) {
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssh_buffer_free(dest);
|
||||
SSH_BUFFER_FREE(dest);
|
||||
return 0;
|
||||
}
|
||||
|
||||
47
src/init.c
47
src/init.c
@@ -106,7 +106,6 @@ _ret:
|
||||
*
|
||||
* This functions is automatically called when the library is loaded.
|
||||
*
|
||||
* @returns 0 on success, -1 if an error occured.
|
||||
*/
|
||||
void libssh_constructor(void)
|
||||
{
|
||||
@@ -136,14 +135,20 @@ void libssh_constructor(void)
|
||||
/**
|
||||
* @brief Initialize global cryptographic data structures.
|
||||
*
|
||||
* Since version 0.8.0, it is not necessary to call this function on systems
|
||||
* which are fully supported with regards to threading (that is, system with
|
||||
* pthreads available).
|
||||
* Since version 0.8.0, when libssh is dynamically linked, it is not necessary
|
||||
* to call this function on systems which are fully supported with regards to
|
||||
* threading (that is, system with pthreads available).
|
||||
*
|
||||
* If libssh is statically linked, it is necessary to explicitly call ssh_init()
|
||||
* before calling any other provided API, and it is necessary to explicitly call
|
||||
* ssh_finalize() to free the allocated resources before exiting.
|
||||
*
|
||||
* If the library is already initialized, increments the _ssh_initialized
|
||||
* counter and return the error code cached in _ssh_init_ret.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*
|
||||
* @see ssh_finalize()
|
||||
*/
|
||||
int ssh_init(void) {
|
||||
return _ssh_init(0);
|
||||
@@ -188,8 +193,6 @@ _ret:
|
||||
*
|
||||
* This function is automatically called when the library is unloaded.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*
|
||||
*/
|
||||
void libssh_destructor(void)
|
||||
{
|
||||
@@ -205,8 +208,13 @@ void libssh_destructor(void)
|
||||
/**
|
||||
* @brief Finalize and cleanup all libssh and cryptographic data structures.
|
||||
*
|
||||
* Since version 0.8.0, it is not necessary to call this function, since it is
|
||||
* automatically called when the library is unloaded.
|
||||
* Since version 0.8.0, when libssh is dynamically linked, it is not necessary
|
||||
* to call this function, since it is automatically called when the library is
|
||||
* unloaded.
|
||||
*
|
||||
* If libssh is statically linked, it is necessary to explicitly call ssh_init()
|
||||
* before calling any other provided API, and it is necessary to explicitly call
|
||||
* ssh_finalize() to free the allocated resources before exiting.
|
||||
*
|
||||
* If ssh_init() is called explicitly, then ssh_finalize() must be called
|
||||
* explicitly.
|
||||
@@ -214,9 +222,9 @@ void libssh_destructor(void)
|
||||
* When called, decrements the counter _ssh_initialized. If the counter reaches
|
||||
* zero, then the libssh and cryptographic data structures are cleaned up.
|
||||
*
|
||||
* @returns 0 on succes, -1 if an error occured.
|
||||
* @returns 0 on success, -1 if an error occurred.
|
||||
*
|
||||
@returns 0 otherwise
|
||||
* @see ssh_init()
|
||||
*/
|
||||
int ssh_finalize(void) {
|
||||
return _ssh_finalize(0);
|
||||
@@ -253,4 +261,23 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief Return whether the library is initialized
|
||||
*
|
||||
* @returns true if the library is initialized; false otherwise.
|
||||
*
|
||||
* @see ssh_init()
|
||||
*/
|
||||
bool is_ssh_initialized(void) {
|
||||
|
||||
bool is_initialized = false;
|
||||
|
||||
ssh_mutex_lock(&ssh_init_mutex);
|
||||
is_initialized = _ssh_initialized > 0;
|
||||
ssh_mutex_unlock(&ssh_init_mutex);
|
||||
|
||||
return is_initialized;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -138,7 +138,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
||||
ssh_mac_update(ctx, key, key_len);
|
||||
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||
ssh_mac_update(ctx, &letter, 1);
|
||||
ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
|
||||
ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len);
|
||||
ssh_mac_final(digest, ctx);
|
||||
|
||||
if (requested_len < output_len) {
|
||||
|
||||
549
src/kex.c
549
src/kex.c
@@ -28,6 +28,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/dh.h"
|
||||
@@ -154,13 +155,12 @@
|
||||
ECDH \
|
||||
"diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \
|
||||
GEX_SHA256 \
|
||||
"diffie-hellman-group14-sha256," \
|
||||
"diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
||||
#define KEY_EXCHANGE_SUPPORTED \
|
||||
GEX_SHA1 \
|
||||
KEY_EXCHANGE
|
||||
|
||||
#define KEX_METHODS_SIZE 10
|
||||
|
||||
/* RFC 8308 */
|
||||
#define KEX_EXTENSION_CLIENT "ext-info-c"
|
||||
|
||||
@@ -185,6 +185,7 @@
|
||||
"ecdh-sha2-nistp384,"\
|
||||
"ecdh-sha2-nistp521,"\
|
||||
"diffie-hellman-group-exchange-sha256,"\
|
||||
"diffie-hellman-group14-sha256,"\
|
||||
"diffie-hellman-group16-sha512,"\
|
||||
"diffie-hellman-group18-sha512"
|
||||
|
||||
@@ -257,7 +258,7 @@ static const char *ssh_kex_descriptions[] = {
|
||||
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo)
|
||||
{
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -266,7 +267,7 @@ const char *ssh_kex_get_default_methods(uint32_t algo)
|
||||
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo)
|
||||
{
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -274,7 +275,7 @@ const char *ssh_kex_get_supported_method(uint32_t algo)
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_description(uint32_t algo) {
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -282,7 +283,7 @@ const char *ssh_kex_get_description(uint32_t algo) {
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_fips_methods(uint32_t algo) {
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -305,6 +306,10 @@ static int cmp_first_kex_algo(const char *client_str,
|
||||
|
||||
int is_wrong = 1;
|
||||
|
||||
if (client_str == NULL || server_str == NULL) {
|
||||
return is_wrong;
|
||||
}
|
||||
|
||||
colon = strchr(client_str, ',');
|
||||
if (colon == NULL) {
|
||||
client_kex_len = strlen(client_str);
|
||||
@@ -331,11 +336,13 @@ static int cmp_first_kex_algo(const char *client_str,
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
{
|
||||
int i, ok;
|
||||
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||
int server_kex = session->server;
|
||||
ssh_string str = NULL;
|
||||
char *strings[KEX_METHODS_SIZE] = {0};
|
||||
char *strings[SSH_KEX_METHODS] = {0};
|
||||
char *rsa_sig_ext = NULL;
|
||||
int rc = SSH_ERROR;
|
||||
size_t len;
|
||||
|
||||
uint8_t first_kex_packet_follows = 0;
|
||||
uint32_t kexinit_reserved = 0;
|
||||
@@ -343,40 +350,72 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "KEXINIT received");
|
||||
|
||||
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
SSH_LOG(SSH_LOG_INFO, "Initiating key re-exchange");
|
||||
if (session->dh_handshake_state == DH_STATE_FINISHED) {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Peer initiated key re-exchange");
|
||||
/* Reset the sent flag if the re-kex was initiated by the peer */
|
||||
session->flags &= ~SSH_SESSION_FLAG_KEXINIT_SENT;
|
||||
} else if (session->flags & SSH_SESSION_FLAG_KEXINIT_SENT &&
|
||||
session->dh_handshake_state == DH_STATE_INIT_SENT) {
|
||||
/* This happens only when we are sending our-guessed first kex
|
||||
* packet right after our KEXINIT packet. */
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Received peer kexinit answer.");
|
||||
} else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"SSH_KEXINIT received in wrong state");
|
||||
goto error;
|
||||
}
|
||||
} else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
|
||||
ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state");
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"SSH_KEXINIT received in wrong state");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (server_kex) {
|
||||
rc = ssh_buffer_get_data(packet,session->next_crypto->client_kex.cookie, 16);
|
||||
if (rc != 16) {
|
||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet");
|
||||
#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");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_hashbufin_add_cookie(session, session->next_crypto->client_kex.cookie);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed");
|
||||
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");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ok = server_set_kex(session);
|
||||
if (ok == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
rc = ssh_buffer_get_data(packet,session->next_crypto->server_kex.cookie, 16);
|
||||
if (rc != 16) {
|
||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet");
|
||||
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");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_hashbufin_add_cookie(session, session->next_crypto->server_kex.cookie);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed");
|
||||
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");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ok = ssh_set_client_kex(session);
|
||||
if (ok == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
str = ssh_buffer_get_ssh_string(packet);
|
||||
if (str == NULL) {
|
||||
goto error;
|
||||
@@ -384,7 +423,8 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->in_hashbuf, str);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Error adding string in hash buffer");
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Error adding string in hash buffer");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -393,18 +433,18 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,30 +458,48 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
* that its value is included when computing the session ID (see
|
||||
* 'make_sessionid').
|
||||
*/
|
||||
rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows);
|
||||
if (rc != 1) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember whether 'first_kex_packet_follows' was set and the client
|
||||
* guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
|
||||
* must be ignored on the server side.
|
||||
* Client needs to start the Key exchange over with the correct method
|
||||
*/
|
||||
if (first_kex_packet_follows || session->send_first_kex_follows) {
|
||||
char **client_methods = crypto->client_kex.methods;
|
||||
char **server_methods = crypto->server_kex.methods;
|
||||
session->first_kex_follows_guess_wrong =
|
||||
cmp_first_kex_algo(client_methods[SSH_KEX],
|
||||
server_methods[SSH_KEX]) ||
|
||||
cmp_first_kex_algo(client_methods[SSH_HOSTKEYS],
|
||||
server_methods[SSH_HOSTKEYS]);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "The initial guess was %s.",
|
||||
session->first_kex_follows_guess_wrong ? "wrong" : "right");
|
||||
}
|
||||
|
||||
if (server_kex) {
|
||||
rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows);
|
||||
if (rc != 1) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If client sent a ext-info-c message in the kex list, it supports
|
||||
* RFC 8308 extension negotiation.
|
||||
*/
|
||||
ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX],
|
||||
ok = ssh_match_group(crypto->client_kex.methods[SSH_KEX],
|
||||
KEX_EXTENSION_CLIENT);
|
||||
if (ok) {
|
||||
const char *hostkeys = NULL;
|
||||
const char *hostkeys = NULL, *wanted_hostkeys = NULL;
|
||||
|
||||
/* The client supports extension negotiation */
|
||||
session->extensions |= SSH_EXT_NEGOTIATION;
|
||||
@@ -451,14 +509,14 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
* by the client and enable the respective extensions to provide
|
||||
* correct signature in the next packet if RSA is negotiated
|
||||
*/
|
||||
hostkeys = session->next_crypto->client_kex.methods[SSH_HOSTKEYS];
|
||||
hostkeys = crypto->client_kex.methods[SSH_HOSTKEYS];
|
||||
wanted_hostkeys = session->opts.wanted_methods[SSH_HOSTKEYS];
|
||||
ok = ssh_match_group(hostkeys, "rsa-sha2-512");
|
||||
if (ok) {
|
||||
/* Check if rsa-sha2-512 is allowed by config */
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) {
|
||||
char *is_allowed =
|
||||
ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS],
|
||||
"rsa-sha2-512");
|
||||
if (wanted_hostkeys != NULL) {
|
||||
char *is_allowed = ssh_find_matching(wanted_hostkeys,
|
||||
"rsa-sha2-512");
|
||||
if (is_allowed != NULL) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA512;
|
||||
}
|
||||
@@ -468,10 +526,9 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
ok = ssh_match_group(hostkeys, "rsa-sha2-256");
|
||||
if (ok) {
|
||||
/* Check if rsa-sha2-256 is allowed by config */
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) {
|
||||
char *is_allowed =
|
||||
ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS],
|
||||
"rsa-sha2-256");
|
||||
if (wanted_hostkeys != NULL) {
|
||||
char *is_allowed = ssh_find_matching(wanted_hostkeys,
|
||||
"rsa-sha2-256");
|
||||
if (is_allowed != NULL) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
|
||||
}
|
||||
@@ -487,7 +544,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
(session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
|
||||
session->extensions &= ~(SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512);
|
||||
rsa_sig_ext = ssh_find_matching("rsa-sha2-512,rsa-sha2-256",
|
||||
session->next_crypto->client_kex.methods[SSH_HOSTKEYS]);
|
||||
hostkeys);
|
||||
if (rsa_sig_ext == NULL) {
|
||||
goto error; /* should never happen */
|
||||
} else if (strcmp(rsa_sig_ext, "rsa-sha2-512") == 0) {
|
||||
@@ -506,29 +563,21 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "",
|
||||
session->extensions & SSH_EXT_SIG_RSA_SHA512 ? " SHA512" : "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember whether 'first_kex_packet_follows' was set and the client
|
||||
* guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
|
||||
* must be ignored.
|
||||
*/
|
||||
if (first_kex_packet_follows) {
|
||||
session->first_kex_follows_guess_wrong =
|
||||
cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_KEX],
|
||||
session->next_crypto->server_kex.methods[SSH_KEX]) ||
|
||||
cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_HOSTKEYS],
|
||||
session->next_crypto->server_kex.methods[SSH_HOSTKEYS]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note, that his overwrites authenticated state in case of rekeying */
|
||||
session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED;
|
||||
session->dh_handshake_state = DH_STATE_INIT;
|
||||
/* if we already sent our initial key exchange packet, do not reset the
|
||||
* DH state. We will know if we were right with our guess only in
|
||||
* dh_handshake_state() */
|
||||
if (session->send_first_kex_follows == false) {
|
||||
session->dh_handshake_state = DH_STATE_INIT;
|
||||
}
|
||||
session->ssh_connection_callback(session);
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
if (server_kex) {
|
||||
session->next_crypto->client_kex.methods[i] = NULL;
|
||||
@@ -671,17 +720,21 @@ int ssh_set_client_kex(ssh_session session)
|
||||
int i;
|
||||
size_t kex_len, len;
|
||||
|
||||
/* Skip if already set, for example for the rekey or when we do the guessing
|
||||
* it could have been already used to make some protocol decisions. */
|
||||
if (client->methods[0] != NULL) {
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
ok = ssh_get_random(client->cookie, 16, 0);
|
||||
if (!ok) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **));
|
||||
|
||||
/* Set the list of allowed algorithms in order of preference, if it hadn't
|
||||
* been set yet. */
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
if (i == SSH_HOSTKEYS) {
|
||||
/* Set the hostkeys in the following order:
|
||||
* - First: keys present in known_hosts files ordered by preference
|
||||
@@ -734,13 +787,103 @@ int ssh_set_client_kex(ssh_session session)
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static const char *ssh_find_aead_hmac(const char *cipher)
|
||||
{
|
||||
if (cipher == NULL) {
|
||||
return NULL;
|
||||
} else if (strcmp(cipher, "chacha20-poly1305@openssh.com") == 0) {
|
||||
return "aead-poly1305";
|
||||
} else if (strcmp(cipher, "aes256-gcm@openssh.com") == 0) {
|
||||
return "aead-gcm";
|
||||
} else if (strcmp(cipher, "aes128-gcm@openssh.com") == 0) {
|
||||
return "aead-gcm";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum ssh_key_exchange_e
|
||||
kex_select_kex_type(const char *kex)
|
||||
{
|
||||
if (strcmp(kex, "diffie-hellman-group1-sha1") == 0) {
|
||||
return SSH_KEX_DH_GROUP1_SHA1;
|
||||
} else if (strcmp(kex, "diffie-hellman-group14-sha1") == 0) {
|
||||
return SSH_KEX_DH_GROUP14_SHA1;
|
||||
} else if (strcmp(kex, "diffie-hellman-group14-sha256") == 0) {
|
||||
return SSH_KEX_DH_GROUP14_SHA256;
|
||||
} else if (strcmp(kex, "diffie-hellman-group16-sha512") == 0) {
|
||||
return SSH_KEX_DH_GROUP16_SHA512;
|
||||
} else if (strcmp(kex, "diffie-hellman-group18-sha512") == 0) {
|
||||
return SSH_KEX_DH_GROUP18_SHA512;
|
||||
#ifdef WITH_GEX
|
||||
} else if (strcmp(kex, "diffie-hellman-group-exchange-sha1") == 0) {
|
||||
return SSH_KEX_DH_GEX_SHA1;
|
||||
} else if (strcmp(kex, "diffie-hellman-group-exchange-sha256") == 0) {
|
||||
return SSH_KEX_DH_GEX_SHA256;
|
||||
#endif /* WITH_GEX */
|
||||
} else if (strcmp(kex, "ecdh-sha2-nistp256") == 0) {
|
||||
return SSH_KEX_ECDH_SHA2_NISTP256;
|
||||
} else if (strcmp(kex, "ecdh-sha2-nistp384") == 0) {
|
||||
return SSH_KEX_ECDH_SHA2_NISTP384;
|
||||
} else if (strcmp(kex, "ecdh-sha2-nistp521") == 0) {
|
||||
return SSH_KEX_ECDH_SHA2_NISTP521;
|
||||
} else if (strcmp(kex, "curve25519-sha256@libssh.org") == 0) {
|
||||
return SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
|
||||
} else if (strcmp(kex, "curve25519-sha256") == 0) {
|
||||
return SSH_KEX_CURVE25519_SHA256;
|
||||
}
|
||||
/* should not happen. We should be getting only valid names at this stage */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @internal
|
||||
* @brief Reverts guessed callbacks set during the dh_handshake()
|
||||
* @param session session handle
|
||||
* @returns void
|
||||
*/
|
||||
static void revert_kex_callbacks(ssh_session session)
|
||||
{
|
||||
switch (session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
ssh_client_dh_remove_callbacks(session);
|
||||
break;
|
||||
#ifdef WITH_GEX
|
||||
case SSH_KEX_DH_GEX_SHA1:
|
||||
case SSH_KEX_DH_GEX_SHA256:
|
||||
ssh_client_dhgex_remove_callbacks(session);
|
||||
break;
|
||||
#endif /* WITH_GEX */
|
||||
#ifdef HAVE_ECDH
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP384:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
ssh_client_ecdh_remove_callbacks(session);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_CURVE25519
|
||||
case SSH_KEX_CURVE25519_SHA256:
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
ssh_client_curve25519_remove_callbacks(session);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Select the different methods on basis of client's and
|
||||
* server's kex messages, and watches out if a match is possible.
|
||||
*/
|
||||
int ssh_kex_select_methods (ssh_session session){
|
||||
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
|
||||
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
|
||||
int ssh_kex_select_methods (ssh_session session)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||
struct ssh_kex_struct *server = &crypto->server_kex;
|
||||
struct ssh_kex_struct *client = &crypto->client_kex;
|
||||
char *ext_start = NULL;
|
||||
const char *aead_hmac = NULL;
|
||||
enum ssh_key_exchange_e kex_type;
|
||||
int i;
|
||||
|
||||
/* Here we should drop the ext-info-c from the list so we avoid matching.
|
||||
@@ -750,42 +893,41 @@ int ssh_kex_select_methods (ssh_session session){
|
||||
ext_start[0] = '\0';
|
||||
}
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; 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]);
|
||||
for (i = 0; i < SSH_KEX_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-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],
|
||||
@@ -803,62 +945,116 @@ int ssh_kex_select_methods (ssh_session session){
|
||||
|
||||
|
||||
/* this function only sends the predefined set of kex methods */
|
||||
int ssh_send_kex(ssh_session session, int server_kex) {
|
||||
struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex :
|
||||
&session->next_crypto->client_kex);
|
||||
ssh_string str = NULL;
|
||||
int i;
|
||||
int rc;
|
||||
int ssh_send_kex(ssh_session session)
|
||||
{
|
||||
struct ssh_kex_struct *kex = (session->server ?
|
||||
&session->next_crypto->server_kex :
|
||||
&session->next_crypto->client_kex);
|
||||
ssh_string str = NULL;
|
||||
int i;
|
||||
int rc;
|
||||
int first_kex_packet_follows = 0;
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bP",
|
||||
SSH2_MSG_KEXINIT,
|
||||
16,
|
||||
kex->cookie); /* cookie */
|
||||
if (rc != SSH_OK)
|
||||
goto error;
|
||||
if (ssh_hashbufout_add_cookie(session) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_list_kex(kex);
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
str = ssh_string_from_char(kex->methods[i]);
|
||||
if (str == NULL) {
|
||||
goto error;
|
||||
/* Only client can initiate the handshake methods we implement. If we
|
||||
* already received the peer mechanisms, there is no point in guessing */
|
||||
if (session->client &&
|
||||
session->session_state != SSH_SESSION_STATE_KEXINIT_RECEIVED &&
|
||||
session->send_first_kex_follows) {
|
||||
first_kex_packet_follows = 1;
|
||||
}
|
||||
|
||||
if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) {
|
||||
goto error;
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Sending KEXINIT packet, first_kex_packet_follows = %d",
|
||||
first_kex_packet_follows);
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bP",
|
||||
SSH2_MSG_KEXINIT,
|
||||
16,
|
||||
kex->cookie); /* cookie */
|
||||
if (rc != SSH_OK)
|
||||
goto error;
|
||||
if (ssh_hashbufout_add_cookie(session) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) {
|
||||
goto error;
|
||||
|
||||
ssh_list_kex(kex);
|
||||
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
str = ssh_string_from_char(kex->methods[i]);
|
||||
if (str == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->out_hashbuf, str);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, str);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
SSH_STRING_FREE(str);
|
||||
str = NULL;
|
||||
}
|
||||
ssh_string_free(str);
|
||||
str = NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bd",
|
||||
0,
|
||||
0);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bd",
|
||||
first_kex_packet_follows,
|
||||
0);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
/* Prepare also the first_kex_packet_follows and reserved to 0 */
|
||||
rc = ssh_buffer_add_u8(session->out_hashbuf, first_kex_packet_follows);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_buffer_add_u32(session->out_hashbuf, 0);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->flags |= SSH_SESSION_FLAG_KEXINIT_SENT;
|
||||
SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent");
|
||||
|
||||
/* If we indicated that we are sending the guessed key exchange packet,
|
||||
* do it now. The packet is simple, but we need to do some preparations */
|
||||
if (first_kex_packet_follows) {
|
||||
char *list = kex->methods[SSH_KEX];
|
||||
char *colon = strchr(list, ',');
|
||||
size_t kex_name_len = colon ? (size_t)(colon - list) : strlen(list);
|
||||
char *kex_name = calloc(kex_name_len + 1, 1);
|
||||
if (kex_name == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
snprintf(kex_name, kex_name_len + 1, "%.*s", (int)kex_name_len, list);
|
||||
SSH_LOG(SSH_LOG_TRACE, "Sending the first kex packet for %s", kex_name);
|
||||
|
||||
session->next_crypto->kex_type = kex_select_kex_type(kex_name);
|
||||
free(kex_name);
|
||||
|
||||
/* run the first step of the DH handshake */
|
||||
session->dh_handshake_state = DH_STATE_INIT;
|
||||
if (dh_handshake(session) == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent");
|
||||
return 0;
|
||||
error:
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
ssh_buffer_reinit(session->out_hashbuf);
|
||||
ssh_string_free(str);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
ssh_buffer_reinit(session->out_hashbuf);
|
||||
SSH_STRING_FREE(str);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -901,7 +1097,7 @@ int ssh_send_rekex(ssh_session session)
|
||||
}
|
||||
|
||||
session->dh_handshake_state = DH_STATE_INIT;
|
||||
rc = ssh_send_kex(session, session->server);
|
||||
rc = ssh_send_kex(session);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to send kex");
|
||||
return rc;
|
||||
@@ -978,33 +1174,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
client_hash = session->in_hashbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the two final fields for the KEXINIT message (RFC 4253 7.1):
|
||||
*
|
||||
* boolean first_kex_packet_follows
|
||||
* uint32 0 (reserved for future extension)
|
||||
*/
|
||||
rc = ssh_buffer_add_u8(server_hash, 0);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_buffer_add_u32(server_hash, 0);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* These fields are handled for the server case in ssh_packet_kexinit. */
|
||||
if (session->client) {
|
||||
rc = ssh_buffer_add_u8(client_hash, 0);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_buffer_add_u32(client_hash, 0);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
@@ -1019,14 +1188,15 @@ int ssh_make_sessionid(ssh_session session)
|
||||
ssh_buffer_get_len(server_hash),
|
||||
ssh_buffer_get(server_hash),
|
||||
server_pubkey_blob);
|
||||
ssh_string_free(server_pubkey_blob);
|
||||
if(rc != SSH_OK){
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
if (rc != SSH_OK){
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch(session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
|
||||
@@ -1138,6 +1308,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
|
||||
session->next_crypto->secret_hash);
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
case SSH_KEX_CURVE25519_SHA256:
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
@@ -1192,23 +1363,25 @@ int ssh_make_sessionid(ssh_session session)
|
||||
}
|
||||
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
||||
session->next_crypto->digest_len);
|
||||
/* Initial length is the same as secret hash */
|
||||
session->next_crypto->session_id_len = session->next_crypto->digest_len;
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
printf("Session hash: \n");
|
||||
ssh_log_hexdump("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
|
||||
ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
|
||||
ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->session_id_len);
|
||||
#endif
|
||||
|
||||
rc = SSH_OK;
|
||||
error:
|
||||
ssh_buffer_free(buf);
|
||||
ssh_buffer_free(client_hash);
|
||||
ssh_buffer_free(server_hash);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
SSH_BUFFER_FREE(client_hash);
|
||||
SSH_BUFFER_FREE(server_hash);
|
||||
|
||||
session->in_hashbuf = NULL;
|
||||
session->out_hashbuf = NULL;
|
||||
|
||||
ssh_string_free(num);
|
||||
SSH_STRING_FREE(num);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1398,7 +1571,7 @@ int ssh_generate_session_keys(ssh_session session)
|
||||
rc = 0;
|
||||
error:
|
||||
ssh_string_burn(k_string);
|
||||
ssh_string_free(k_string);
|
||||
SSH_STRING_FREE(k_string);
|
||||
if (rc != 0) {
|
||||
free(IV_cli_to_srv);
|
||||
free(IV_srv_to_cli);
|
||||
|
||||
@@ -129,8 +129,8 @@ static int match_hashed_hostname(const char *host, const char *hashed_host)
|
||||
|
||||
error:
|
||||
free(hashed);
|
||||
ssh_buffer_free(salt);
|
||||
ssh_buffer_free(hash);
|
||||
SSH_BUFFER_FREE(salt);
|
||||
SSH_BUFFER_FREE(hash);
|
||||
|
||||
return match;
|
||||
}
|
||||
@@ -372,6 +372,7 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
||||
|
||||
list = ssh_list_new();
|
||||
if (list == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(host_port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ void publickey_free(ssh_public_key key) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_release(key->dsa_pub);
|
||||
#elif HAVE_LIBCRYPTO
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
DSA_free(key->dsa_pub);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -280,6 +280,12 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
HMAC_CTX *HMAC_CTX_new(void)
|
||||
{
|
||||
HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
|
||||
@@ -394,3 +400,12 @@ int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *OpenSSL_version(int type)
|
||||
{
|
||||
return SSLeay_version(type);
|
||||
}
|
||||
unsigned long OpenSSL_version_num(void)
|
||||
{
|
||||
return SSLeay();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
|
||||
EVP_MD_CTX *EVP_MD_CTX_new(void);
|
||||
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
|
||||
|
||||
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
|
||||
|
||||
HMAC_CTX *HMAC_CTX_new(void);
|
||||
int HMAC_CTX_reset(HMAC_CTX *ctx);
|
||||
void HMAC_CTX_free(HMAC_CTX *ctx);
|
||||
@@ -44,6 +46,10 @@ int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
|
||||
void DH_get0_key(const DH *dh,
|
||||
const BIGNUM **pub_key, const BIGNUM **priv_key);
|
||||
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
|
||||
|
||||
const char *OpenSSL_version(int type);
|
||||
unsigned long OpenSSL_version_num(void);
|
||||
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
#endif /* LIBCRYPTO_COMPAT_H */
|
||||
|
||||
@@ -392,7 +392,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||
goto out;
|
||||
}
|
||||
rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
|
||||
crypto->session_id, crypto->digest_len);
|
||||
crypto->session_id, crypto->session_id_len);
|
||||
if (rc != 1) {
|
||||
goto out;
|
||||
}
|
||||
@@ -536,7 +536,7 @@ static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher,
|
||||
int rc;
|
||||
|
||||
evp_cipher_init(cipher);
|
||||
EVP_CIPHER_CTX_init(cipher->ctx);
|
||||
EVP_CIPHER_CTX_reset(cipher->ctx);
|
||||
|
||||
rc = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
|
||||
if (rc != 1){
|
||||
@@ -569,7 +569,7 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher,
|
||||
int rc;
|
||||
|
||||
evp_cipher_init(cipher);
|
||||
EVP_CIPHER_CTX_init(cipher->ctx);
|
||||
EVP_CIPHER_CTX_reset(cipher->ctx);
|
||||
|
||||
rc = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
|
||||
if (rc != 1){
|
||||
@@ -652,7 +652,6 @@ static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher,
|
||||
|
||||
static void evp_cipher_cleanup(struct ssh_cipher_struct *cipher) {
|
||||
if (cipher->ctx != NULL) {
|
||||
EVP_CIPHER_CTX_cleanup(cipher->ctx);
|
||||
EVP_CIPHER_CTX_free(cipher->ctx);
|
||||
}
|
||||
}
|
||||
@@ -708,8 +707,12 @@ aes_ctr_encrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){
|
||||
explicit_bzero(cipher->aes_key, sizeof(*cipher->aes_key));
|
||||
SAFE_FREE(cipher->aes_key);
|
||||
if (cipher != NULL) {
|
||||
if (cipher->aes_key != NULL) {
|
||||
explicit_bzero(cipher->aes_key, sizeof(*cipher->aes_key));
|
||||
}
|
||||
SAFE_FREE(cipher->aes_key);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_OPENSSL_EVP_AES_CTR */
|
||||
@@ -1080,11 +1083,11 @@ int ssh_crypto_init(void)
|
||||
if (libcrypto_initialized) {
|
||||
return SSH_OK;
|
||||
}
|
||||
if (SSLeay() != OPENSSL_VERSION_NUMBER){
|
||||
if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER){
|
||||
SSH_LOG(SSH_LOG_WARNING, "libssh compiled with %s "
|
||||
"headers, currently running with %s.",
|
||||
OPENSSL_VERSION_TEXT,
|
||||
SSLeay_version(SSLeay())
|
||||
OpenSSL_version(OpenSSL_version_num())
|
||||
);
|
||||
}
|
||||
#ifdef CAN_DISABLE_AESNI
|
||||
|
||||
@@ -328,6 +328,10 @@ static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARNING, "Unksupported key length %u.", cipher->keysize);
|
||||
SAFE_FREE(cipher->key);
|
||||
return -1;
|
||||
}
|
||||
if (gcry_cipher_setkey(cipher->key[0], key, cipher->keysize / 8)) {
|
||||
SAFE_FREE(cipher->key);
|
||||
@@ -738,7 +742,7 @@ ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp,
|
||||
err = gcry_mpi_print(outformat, ssh_string_data(result), size, NULL, mpi);
|
||||
if (err != 0) {
|
||||
ssh_string_burn(result);
|
||||
ssh_string_free(result);
|
||||
SSH_STRING_FREE(result);
|
||||
result = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -687,7 +687,7 @@ static void cipher_encrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len)
|
||||
size_t len)
|
||||
{
|
||||
size_t outlen = 0;
|
||||
int rc = 0;
|
||||
@@ -745,7 +745,7 @@ static void cipher_decrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len)
|
||||
size_t len)
|
||||
{
|
||||
size_t outlen = 0;
|
||||
int rc = 0;
|
||||
|
||||
22
src/match.c
22
src/match.c
@@ -38,16 +38,21 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "libssh/priv.h"
|
||||
|
||||
#define MAX_MATCH_RECURSION 32
|
||||
|
||||
/*
|
||||
* Returns true if the given string matches the pattern (which may contain ?
|
||||
* and * as wildcards), and zero if it does not match.
|
||||
*/
|
||||
static int match_pattern(const char *s, const char *pattern) {
|
||||
if (s == NULL || pattern == NULL) {
|
||||
static int match_pattern(const char *s, const char *pattern, size_t limit)
|
||||
{
|
||||
bool had_asterisk = false;
|
||||
if (s == NULL || pattern == NULL || limit <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,23 +62,26 @@ static int match_pattern(const char *s, const char *pattern) {
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
if (*pattern == '*') {
|
||||
while (*pattern == '*') {
|
||||
/* Skip the asterisk. */
|
||||
had_asterisk = true;
|
||||
pattern++;
|
||||
}
|
||||
|
||||
if (had_asterisk) {
|
||||
/* If at end of pattern, accept immediately. */
|
||||
if (!*pattern)
|
||||
return 1;
|
||||
|
||||
/* If next character in pattern is known, optimize. */
|
||||
if (*pattern != '?' && *pattern != '*') {
|
||||
if (*pattern != '?') {
|
||||
/*
|
||||
* Look instances of the next character in
|
||||
* pattern, and try to match starting from
|
||||
* those.
|
||||
*/
|
||||
for (; *s; s++)
|
||||
if (*s == *pattern && match_pattern(s + 1, pattern + 1)) {
|
||||
if (*s == *pattern && match_pattern(s + 1, pattern + 1, limit - 1)) {
|
||||
return 1;
|
||||
}
|
||||
/* Failed. */
|
||||
@@ -84,7 +92,7 @@ static int match_pattern(const char *s, const char *pattern) {
|
||||
* match at each position.
|
||||
*/
|
||||
for (; *s; s++) {
|
||||
if (match_pattern(s, pattern)) {
|
||||
if (match_pattern(s, pattern, limit - 1)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -161,7 +169,7 @@ int match_pattern_list(const char *string, const char *pattern,
|
||||
sub[subi] = '\0';
|
||||
|
||||
/* Try to match the subpattern against the string. */
|
||||
if (match_pattern(string, sub)) {
|
||||
if (match_pattern(string, sub, MAX_MATCH_RECURSION)) {
|
||||
if (negated) {
|
||||
return -1; /* Negative */
|
||||
} else {
|
||||
|
||||
@@ -104,6 +104,9 @@ int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom)
|
||||
|
||||
if (top == 0) {
|
||||
rc = mbedtls_mpi_set_bit(rnd, bits - 1, 0);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (top == 1) {
|
||||
@@ -149,7 +152,8 @@ int ssh_mbedcry_rand_range(bignum dest, bignum max)
|
||||
return 0;
|
||||
}
|
||||
rc = bignum_rand(rnd, bits);
|
||||
if (rc != 1){
|
||||
if (rc != 1) {
|
||||
bignum_safe_free(rnd);
|
||||
return rc;
|
||||
}
|
||||
mbedtls_mpi_mod_mpi(dest, rnd, max);
|
||||
|
||||
@@ -71,6 +71,9 @@ static ssh_message ssh_message_new(ssh_session session)
|
||||
}
|
||||
msg->session = session;
|
||||
|
||||
/* Set states explicitly */
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -510,24 +513,30 @@ static int ssh_message_termination(void *s){
|
||||
* @warning This function blocks until a message has been received. Betterset up
|
||||
* a callback if this behavior is unwanted.
|
||||
*/
|
||||
ssh_message ssh_message_get(ssh_session session) {
|
||||
ssh_message msg = NULL;
|
||||
int rc;
|
||||
ssh_message ssh_message_get(ssh_session session)
|
||||
{
|
||||
ssh_message msg = NULL;
|
||||
int rc;
|
||||
|
||||
msg=ssh_message_pop_head(session);
|
||||
if(msg) {
|
||||
return msg;
|
||||
}
|
||||
if(session->ssh_message_list == NULL) {
|
||||
session->ssh_message_list = ssh_list_new();
|
||||
}
|
||||
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
|
||||
ssh_message_termination, session);
|
||||
if(rc || session->session_state == SSH_SESSION_STATE_ERROR)
|
||||
return NULL;
|
||||
msg=ssh_list_pop_head(ssh_message, session->ssh_message_list);
|
||||
msg = ssh_message_pop_head(session);
|
||||
if (msg != NULL) {
|
||||
return msg;
|
||||
}
|
||||
if (session->ssh_message_list == NULL) {
|
||||
session->ssh_message_list = ssh_list_new();
|
||||
if (session->ssh_message_list == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
|
||||
ssh_message_termination, session);
|
||||
if (rc || session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
msg = ssh_list_pop_head(ssh_message, session->ssh_message_list);
|
||||
|
||||
return msg;
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -689,6 +698,9 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
int rc;
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||
if (crypto == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
@@ -696,14 +708,14 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
}
|
||||
rc = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &str);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -712,10 +724,10 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
ssh_string_get_char(algo), /* pubkey algorithm */
|
||||
str); /* public key as a blob */
|
||||
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -797,7 +809,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
* 3.1. Initial Exchange
|
||||
* "The language tag is deprecated and SHOULD be the empty string."
|
||||
*/
|
||||
ssh_string_free(lang);
|
||||
SSH_STRING_FREE(lang);
|
||||
|
||||
submethods = ssh_buffer_get_ssh_string(packet);
|
||||
if (submethods == NULL) {
|
||||
@@ -809,7 +821,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
* server is that, unless the user may use multiple different
|
||||
* submethods, the server ignores this field."
|
||||
*/
|
||||
ssh_string_free(submethods);
|
||||
SSH_STRING_FREE(submethods);
|
||||
|
||||
goto end;
|
||||
}
|
||||
@@ -832,10 +844,10 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey);
|
||||
ssh_string_free(pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
pubkey_blob = NULL;
|
||||
if (rc < 0) {
|
||||
ssh_string_free(algo);
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
@@ -849,16 +861,16 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
if(sig_blob == NULL) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Invalid signature packet from peer");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
|
||||
ssh_string_free(algo);
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
digest = ssh_msg_userauth_build_digest(session, msg, service, algo);
|
||||
ssh_string_free(algo);
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
if (digest == NULL) {
|
||||
ssh_string_free(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to get digest");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
|
||||
goto error;
|
||||
@@ -891,8 +903,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
ssh_buffer_get_len(digest));
|
||||
}
|
||||
}
|
||||
ssh_string_free(sig_blob);
|
||||
ssh_buffer_free(digest);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_BUFFER_FREE(digest);
|
||||
ssh_signature_free(sig);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(
|
||||
@@ -906,7 +918,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
|
||||
}
|
||||
ssh_string_free(algo);
|
||||
SSH_STRING_FREE(algo);
|
||||
goto end;
|
||||
}
|
||||
#ifdef WITH_GSSAPI
|
||||
@@ -1094,7 +1106,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
|
||||
goto error;
|
||||
}
|
||||
session->kbdint->answers[i] = ssh_string_to_char(tmp);
|
||||
ssh_string_free(tmp);
|
||||
SSH_STRING_FREE(tmp);
|
||||
if (session->kbdint->answers[i] == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
session->kbdint->nanswers = i;
|
||||
|
||||
240
src/misc.c
240
src/misc.c
@@ -1164,14 +1164,13 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
|
||||
x = strdup(session->opts.username);
|
||||
break;
|
||||
case 'p':
|
||||
if (session->opts.port < 65536) {
|
||||
char tmp[6];
|
||||
{
|
||||
char tmp[6];
|
||||
|
||||
snprintf(tmp,
|
||||
sizeof(tmp),
|
||||
"%u",
|
||||
session->opts.port > 0 ? session->opts.port : 22);
|
||||
x = strdup(tmp);
|
||||
snprintf(tmp, sizeof(tmp), "%hu",
|
||||
(uint16_t)(session->opts.port > 0 ? session->opts.port
|
||||
: 22));
|
||||
x = strdup(tmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1508,4 +1507,231 @@ uint64_inc(unsigned char *counter)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Quote file name to be used on shell.
|
||||
*
|
||||
* Try to put the given file name between single quotes. There are special
|
||||
* cases:
|
||||
*
|
||||
* - When the '\'' char is found in the file name, it is double quoted
|
||||
* - example:
|
||||
* input: a'b
|
||||
* output: 'a'"'"'b'
|
||||
* - When the '!' char is found in the file name, it is replaced by an unquoted
|
||||
* verbatim char "\!"
|
||||
* - example:
|
||||
* input: a!b
|
||||
* output 'a'\!'b'
|
||||
*
|
||||
* @param[in] file_name File name string to be quoted before used on shell
|
||||
* @param[out] buf Buffer to receive the final quoted file name. Must
|
||||
* have room for the final quoted string. The maximum
|
||||
* output length would be (3 * strlen(file_name) + 1)
|
||||
* since in the worst case each character would be
|
||||
* replaced by 3 characters, plus the terminating '\0'.
|
||||
* @param[in] buf_len The size of the provided output buffer
|
||||
*
|
||||
* @returns SSH_ERROR on error; length of the resulting string not counting the
|
||||
* string terminator '\0'
|
||||
* */
|
||||
int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len)
|
||||
{
|
||||
const char *src = NULL;
|
||||
char *dst = NULL;
|
||||
size_t required_buf_len;
|
||||
|
||||
enum ssh_quote_state_e state = NO_QUOTE;
|
||||
|
||||
if (file_name == NULL || buf == NULL || buf_len == 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "Invalid parameter");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Only allow file names smaller than 32kb. */
|
||||
if (strlen(file_name) > 32 * 1024) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "File name too long");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Paranoia check */
|
||||
required_buf_len = (size_t)3 * strlen(file_name) + 1;
|
||||
if (required_buf_len > buf_len) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "Buffer too small");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
src = file_name;
|
||||
dst = buf;
|
||||
|
||||
while ((*src != '\0')) {
|
||||
switch (*src) {
|
||||
|
||||
/* The '\'' char is double quoted */
|
||||
|
||||
case '\'':
|
||||
switch (state) {
|
||||
case NO_QUOTE:
|
||||
/* Start a new double quoted string. The '\'' char will be
|
||||
* copied to the beginning of it at the end of the loop. */
|
||||
*dst++ = '"';
|
||||
break;
|
||||
case SINGLE_QUOTE:
|
||||
/* Close the current single quoted string and start a new double
|
||||
* quoted string. The '\'' char will be copied to the beginning
|
||||
* of it at the end of the loop. */
|
||||
*dst++ = '\'';
|
||||
*dst++ = '"';
|
||||
break;
|
||||
case DOUBLE_QUOTE:
|
||||
/* If already in the double quoted string, keep copying the
|
||||
* sequence of chars. */
|
||||
break;
|
||||
default:
|
||||
/* Should never be reached */
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* When the '\'' char is found, the resulting state will be
|
||||
* DOUBLE_QUOTE in any case*/
|
||||
state = DOUBLE_QUOTE;
|
||||
break;
|
||||
|
||||
/* The '!' char is replaced by unquoted "\!" */
|
||||
|
||||
case '!':
|
||||
switch (state) {
|
||||
case NO_QUOTE:
|
||||
/* The '!' char is interpreted in some shells (e.g. CSH) even
|
||||
* when is quoted with single quotes. Replace it with unquoted
|
||||
* "\!" which is correctly interpreted as the '!' character. */
|
||||
*dst++ = '\\';
|
||||
break;
|
||||
case SINGLE_QUOTE:
|
||||
/* Close the current quoted string and replace '!' for unquoted
|
||||
* "\!" */
|
||||
*dst++ = '\'';
|
||||
*dst++ = '\\';
|
||||
break;
|
||||
case DOUBLE_QUOTE:
|
||||
/* Close current quoted string and replace "!" for unquoted
|
||||
* "\!" */
|
||||
*dst++ = '"';
|
||||
*dst++ = '\\';
|
||||
break;
|
||||
default:
|
||||
/* Should never be reached */
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* When the '!' char is found, the resulting state will be NO_QUOTE
|
||||
* in any case*/
|
||||
state = NO_QUOTE;
|
||||
break;
|
||||
|
||||
/* Ordinary chars are single quoted */
|
||||
|
||||
default:
|
||||
switch (state) {
|
||||
case NO_QUOTE:
|
||||
/* Start a new single quoted string */
|
||||
*dst++ = '\'';
|
||||
break;
|
||||
case SINGLE_QUOTE:
|
||||
/* If already in the single quoted string, keep copying the
|
||||
* sequence of chars. */
|
||||
break;
|
||||
case DOUBLE_QUOTE:
|
||||
/* Close current double quoted string and start a new single
|
||||
* quoted string. */
|
||||
*dst++ = '"';
|
||||
*dst++ = '\'';
|
||||
break;
|
||||
default:
|
||||
/* Should never be reached */
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* When an ordinary char is found, the resulting state will be
|
||||
* SINGLE_QUOTE in any case*/
|
||||
state = SINGLE_QUOTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the current char to output */
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
/* Close the quoted string when necessary */
|
||||
|
||||
switch (state) {
|
||||
case NO_QUOTE:
|
||||
/* No open string */
|
||||
break;
|
||||
case SINGLE_QUOTE:
|
||||
/* Close current single quoted string */
|
||||
*dst++ = '\'';
|
||||
break;
|
||||
case DOUBLE_QUOTE:
|
||||
/* Close current double quoted string */
|
||||
*dst++ = '"';
|
||||
break;
|
||||
default:
|
||||
/* Should never be reached */
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Put the string terminator */
|
||||
*dst = '\0';
|
||||
|
||||
return dst - buf;
|
||||
|
||||
error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Given a string, encode existing newlines as the string "\\n"
|
||||
*
|
||||
* @param[in] string Input string
|
||||
* @param[out] buf Output buffer. This buffer must be at least (2 *
|
||||
* strlen(string)) + 1 long. In the worst case,
|
||||
* each character can be encoded as 2 characters plus the
|
||||
* terminating '\0'.
|
||||
* @param[in] buf_len Size of the provided output buffer
|
||||
*
|
||||
* @returns SSH_ERROR on error; length of the resulting string not counting the
|
||||
* terminating '\0' otherwise
|
||||
*/
|
||||
int ssh_newline_vis(const char *string, char *buf, size_t buf_len)
|
||||
{
|
||||
const char *in = NULL;
|
||||
char *out = NULL;
|
||||
|
||||
if (string == NULL || buf == NULL || buf_len == 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if ((2 * strlen(string) + 1) > buf_len) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "Buffer too small");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
out = buf;
|
||||
for (in = string; *in != '\0'; in++) {
|
||||
if (*in == '\n') {
|
||||
*out++ = '\\';
|
||||
*out++ = 'n';
|
||||
} else {
|
||||
*out++ = *in;
|
||||
}
|
||||
}
|
||||
*out = '\0';
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -154,7 +154,7 @@ int ssh_options_copy(ssh_session src, ssh_session *dest)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
if (src->opts.wanted_methods[i] != NULL) {
|
||||
new->opts.wanted_methods[i] = strdup(src->opts.wanted_methods[i]);
|
||||
if (new->opts.wanted_methods[i] == NULL) {
|
||||
@@ -531,7 +531,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->opts.port = *x & 0xffff;
|
||||
session->opts.port = *x & 0xffffU;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_PORT_STR:
|
||||
@@ -555,7 +555,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->opts.port = i & 0xffff;
|
||||
session->opts.port = i & 0xffffU;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_FD:
|
||||
@@ -693,7 +693,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->opts.timeout = *x & 0xffffffff;
|
||||
session->opts.timeout = *x & 0xffffffffU;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_TIMEOUT_USEC:
|
||||
@@ -707,7 +707,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->opts.timeout_usec = *x & 0xffffffff;
|
||||
session->opts.timeout_usec = *x & 0xffffffffU;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_SSH1:
|
||||
@@ -725,8 +725,8 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->common.log_verbosity = *x & 0xffff;
|
||||
ssh_set_log_level(*x & 0xffff);
|
||||
session->common.log_verbosity = *x & 0xffffU;
|
||||
ssh_set_log_level(*x & 0xffffU);
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_LOG_VERBOSITY_STR:
|
||||
@@ -751,8 +751,8 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->common.log_verbosity = i & 0xffff;
|
||||
ssh_set_log_level(i & 0xffff);
|
||||
session->common.log_verbosity = i & 0xffffU;
|
||||
ssh_set_log_level(i & 0xffffU);
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_CIPHERS_C_S:
|
||||
@@ -968,7 +968,6 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
case SSH_OPTIONS_PUBKEY_AUTH:
|
||||
case SSH_OPTIONS_KBDINT_AUTH:
|
||||
case SSH_OPTIONS_GSSAPI_AUTH:
|
||||
u = 0;
|
||||
if (value == NULL) {
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
@@ -1805,12 +1804,12 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
||||
return -1;
|
||||
} else {
|
||||
int *x = (int *) value;
|
||||
sshbind->bindport = *x & 0xffff;
|
||||
sshbind->bindport = *x & 0xffffU;
|
||||
}
|
||||
break;
|
||||
case SSH_BIND_OPTIONS_BINDPORT_STR:
|
||||
if (value == NULL) {
|
||||
sshbind->bindport = 22 & 0xffff;
|
||||
sshbind->bindport = 22 & 0xffffU;
|
||||
} else {
|
||||
q = strdup(value);
|
||||
if (q == NULL) {
|
||||
@@ -1823,7 +1822,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
||||
}
|
||||
SAFE_FREE(q);
|
||||
|
||||
sshbind->bindport = i & 0xffff;
|
||||
sshbind->bindport = i & 0xffffU;
|
||||
}
|
||||
break;
|
||||
case SSH_BIND_OPTIONS_LOG_VERBOSITY:
|
||||
@@ -1832,7 +1831,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
||||
return -1;
|
||||
} else {
|
||||
int *x = (int *) value;
|
||||
ssh_set_log_level(*x & 0xffff);
|
||||
ssh_set_log_level(*x & 0xffffU);
|
||||
}
|
||||
break;
|
||||
case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
|
||||
@@ -1850,7 +1849,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
||||
}
|
||||
SAFE_FREE(q);
|
||||
|
||||
ssh_set_log_level(i & 0xffff);
|
||||
ssh_set_log_level(i & 0xffffU);
|
||||
}
|
||||
break;
|
||||
case SSH_BIND_OPTIONS_DSAKEY:
|
||||
|
||||
144
src/packet.c
144
src/packet.c
@@ -366,6 +366,11 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
||||
* */
|
||||
|
||||
if (!session->server) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
@@ -688,10 +693,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* Transitions:
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
*
|
||||
* If not in a pending state, message is ignored in the callback handler.
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
@@ -699,21 +706,18 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_REQUEST_FAILURE: // 82
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* Transitions:
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED
|
||||
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
*
|
||||
* If not in a pending state, message is ignored in the callback handler.
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
@@ -721,11 +725,6 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_OPEN: // 90
|
||||
@@ -878,10 +877,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* Transitions:
|
||||
* - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
*
|
||||
* If not in a pending state, message is ignored in the callback handler.
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
@@ -895,10 +896,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* Transitions:
|
||||
* - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED
|
||||
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
*
|
||||
* If not in a pending state, message is ignored in the callback handler.
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
@@ -939,18 +942,38 @@ struct ssh_crypto_struct *
|
||||
ssh_packet_get_current_crypto(ssh_session session,
|
||||
enum ssh_crypto_direction_e direction)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto = NULL;
|
||||
|
||||
if (session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (session->current_crypto != NULL &&
|
||||
session->current_crypto->used & direction) {
|
||||
return session->current_crypto;
|
||||
crypto = session->current_crypto;
|
||||
} else if (session->next_crypto != NULL &&
|
||||
session->next_crypto->used & direction) {
|
||||
crypto = session->next_crypto;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (session->next_crypto != NULL &&
|
||||
session->next_crypto->used & direction) {
|
||||
return session->next_crypto;
|
||||
switch (direction) {
|
||||
case SSH_DIRECTION_IN:
|
||||
if (crypto->in_cipher != NULL) {
|
||||
return crypto;
|
||||
}
|
||||
break;
|
||||
case SSH_DIRECTION_OUT:
|
||||
if (crypto->out_cipher != NULL) {
|
||||
return crypto;
|
||||
}
|
||||
break;
|
||||
case SSH_DIRECTION_BOTH:
|
||||
if (crypto->in_cipher != NULL &&
|
||||
crypto->out_cipher != NULL) {
|
||||
return crypto;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1039,8 +1062,8 @@ static bool ssh_packet_need_rekey(ssh_session session,
|
||||
int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
{
|
||||
ssh_session session = (ssh_session)user;
|
||||
unsigned int blocksize = 8;
|
||||
unsigned int lenfield_blocksize = 8;
|
||||
uint32_t blocksize = 8;
|
||||
uint32_t lenfield_blocksize = 8;
|
||||
size_t current_macsize = 0;
|
||||
uint8_t *ptr = NULL;
|
||||
int to_be_read;
|
||||
@@ -1055,7 +1078,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
enum ssh_packet_filter_result_e filter_result;
|
||||
struct ssh_crypto_struct *crypto = NULL;
|
||||
bool etm = false;
|
||||
int etm_packet_offset = 0;
|
||||
uint32_t etm_packet_offset = 0;
|
||||
bool ok;
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||
@@ -1392,31 +1415,41 @@ static void ssh_packet_socket_controlflow_callback(int code, void *userdata)
|
||||
}
|
||||
}
|
||||
|
||||
void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){
|
||||
session->socket_callbacks.data=ssh_packet_socket_callback;
|
||||
session->socket_callbacks.connected=NULL;
|
||||
session->socket_callbacks.controlflow = ssh_packet_socket_controlflow_callback;
|
||||
session->socket_callbacks.userdata=session;
|
||||
ssh_socket_set_callbacks(s,&session->socket_callbacks);
|
||||
void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s)
|
||||
{
|
||||
struct ssh_socket_callbacks_struct *callbacks = &session->socket_callbacks;
|
||||
|
||||
callbacks->data = ssh_packet_socket_callback;
|
||||
callbacks->connected = NULL;
|
||||
callbacks->controlflow = ssh_packet_socket_controlflow_callback;
|
||||
callbacks->userdata = session;
|
||||
ssh_socket_set_callbacks(s, callbacks);
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief sets the callbacks for the packet layer
|
||||
*/
|
||||
void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks){
|
||||
if(session->packet_callbacks == NULL){
|
||||
session->packet_callbacks = ssh_list_new();
|
||||
}
|
||||
if (session->packet_callbacks != NULL) {
|
||||
void
|
||||
ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks)
|
||||
{
|
||||
if (session->packet_callbacks == NULL) {
|
||||
session->packet_callbacks = ssh_list_new();
|
||||
if (session->packet_callbacks == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ssh_list_append(session->packet_callbacks, callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief remove the callbacks from the packet layer
|
||||
*/
|
||||
void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks){
|
||||
void
|
||||
ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks)
|
||||
{
|
||||
struct ssh_iterator *it = NULL;
|
||||
|
||||
it = ssh_list_find(session->packet_callbacks, callbacks);
|
||||
if (it != NULL) {
|
||||
ssh_list_remove(session->packet_callbacks, it);
|
||||
@@ -1426,12 +1459,15 @@ void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callb
|
||||
/** @internal
|
||||
* @brief sets the default packet handlers
|
||||
*/
|
||||
void ssh_packet_set_default_callbacks(ssh_session session){
|
||||
session->default_packet_callbacks.start=1;
|
||||
session->default_packet_callbacks.n_callbacks=sizeof(default_packet_handlers)/sizeof(ssh_packet_callback);
|
||||
session->default_packet_callbacks.user=session;
|
||||
session->default_packet_callbacks.callbacks=default_packet_handlers;
|
||||
ssh_packet_set_callbacks(session, &session->default_packet_callbacks);
|
||||
void ssh_packet_set_default_callbacks(ssh_session session)
|
||||
{
|
||||
struct ssh_packet_callbacks_struct *c = &session->default_packet_callbacks;
|
||||
|
||||
c->start = 1;
|
||||
c->n_callbacks = sizeof(default_packet_handlers) / sizeof(ssh_packet_callback);
|
||||
c->user = session;
|
||||
c->callbacks = default_packet_handlers;
|
||||
ssh_packet_set_callbacks(session, c);
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@@ -1806,7 +1842,7 @@ int ssh_packet_send(ssh_session session)
|
||||
SSH_LOG(SSH_LOG_PACKET, "Queued packet triggered rekey");
|
||||
return ssh_send_rekex(session);
|
||||
}
|
||||
ssh_buffer_free(session->out_buffer);
|
||||
SSH_BUFFER_FREE(session->out_buffer);
|
||||
session->out_buffer = ssh_list_pop_head(struct ssh_buffer_struct *,
|
||||
session->out_queue);
|
||||
payload = (uint8_t *)ssh_buffer_get(session->out_buffer);
|
||||
@@ -1864,6 +1900,10 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
direction & SSH_DIRECTION_IN ? " IN " : "",
|
||||
direction & SSH_DIRECTION_OUT ? " OUT " : "");
|
||||
|
||||
if (session->next_crypto == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->next_crypto->used |= direction;
|
||||
if (session->current_crypto != NULL) {
|
||||
if (session->current_crypto->used & direction) {
|
||||
@@ -1875,7 +1915,7 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
|
||||
/* Both sides switched: do the actual switch now */
|
||||
if (session->next_crypto->used == SSH_DIRECTION_BOTH) {
|
||||
size_t digest_len;
|
||||
size_t session_id_len;
|
||||
|
||||
if (session->current_crypto != NULL) {
|
||||
crypto_free(session->current_crypto);
|
||||
@@ -1892,8 +1932,8 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
digest_len = session->current_crypto->digest_len;
|
||||
session->next_crypto->session_id = malloc(digest_len);
|
||||
session_id_len = session->current_crypto->session_id_len;
|
||||
session->next_crypto->session_id = malloc(session_id_len);
|
||||
if (session->next_crypto->session_id == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
@@ -1901,7 +1941,8 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
|
||||
memcpy(session->next_crypto->session_id,
|
||||
session->current_crypto->session_id,
|
||||
digest_len);
|
||||
session_id_len);
|
||||
session->next_crypto->session_id_len = session_id_len;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@@ -1929,6 +1970,11 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->next_crypto->in_cipher == NULL ||
|
||||
session->next_crypto->out_cipher == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize rekeying states */
|
||||
ssh_init_rekey_state(session,
|
||||
session->next_crypto->out_cipher);
|
||||
|
||||
@@ -61,7 +61,7 @@ SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){
|
||||
error_s = ssh_buffer_get_ssh_string(packet);
|
||||
if (error_s != NULL) {
|
||||
error = ssh_string_to_char(error_s);
|
||||
ssh_string_free(error_s);
|
||||
SSH_STRING_FREE(error_s);
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT %d:%s",
|
||||
code, error != NULL ? error : "no error");
|
||||
@@ -129,6 +129,8 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_signature_blob(sig_blob, server_key, &sig);
|
||||
ssh_string_burn(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
@@ -152,11 +154,11 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
server_key,
|
||||
session->next_crypto->secret_hash,
|
||||
session->next_crypto->digest_len);
|
||||
ssh_string_burn(sig_blob);
|
||||
ssh_string_free(sig_blob);
|
||||
ssh_signature_free(sig);
|
||||
sig_blob = NULL;
|
||||
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");
|
||||
@@ -171,6 +173,9 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
session->ssh_connection_callback(session);
|
||||
return SSH_PACKET_USED;
|
||||
error:
|
||||
SSH_SIGNATURE_FREE(sig);
|
||||
ssh_string_burn(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ uint32_t ssh_packet_decrypt_len(ssh_session session,
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||
if (crypto != NULL) {
|
||||
if (crypto->in_cipher->aead_decrypt_length != NULL) {
|
||||
crypto->in_cipher->aead_decrypt_length(
|
||||
rc = crypto->in_cipher->aead_decrypt_length(
|
||||
crypto->in_cipher, source, destination,
|
||||
crypto->in_cipher->lenfield_blocksize,
|
||||
session->recv_seq);
|
||||
@@ -71,9 +71,9 @@ uint32_t ssh_packet_decrypt_len(ssh_session session,
|
||||
source,
|
||||
0,
|
||||
crypto->in_cipher->blocksize);
|
||||
if (rc < 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (rc < 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
memcpy(destination, source, 8);
|
||||
@@ -103,6 +103,9 @@ int ssh_packet_decrypt(ssh_session session,
|
||||
}
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||
if (crypto == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
cipher = crypto->in_cipher;
|
||||
|
||||
if (encrypted_size % cipher->blocksize != 0) {
|
||||
@@ -252,6 +255,10 @@ int ssh_packet_hmac_verify(ssh_session session,
|
||||
}
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||
if (crypto == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ctx = hmac_init(crypto->decryptMAC, hmac_digest_len(type), type);
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
|
||||
@@ -193,7 +193,7 @@ int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t o
|
||||
}
|
||||
err=ssh_pcap_file_write(pcap,header);
|
||||
error:
|
||||
ssh_buffer_free(header);
|
||||
SSH_BUFFER_FREE(header);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename){
|
||||
}
|
||||
err=ssh_pcap_file_write(pcap,header);
|
||||
error:
|
||||
ssh_buffer_free(header);
|
||||
SSH_BUFFER_FREE(header);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,
|
||||
rc = ssh_pcap_file_write_packet(ctx->file, ip, origlen + TCPIPHDR_LEN);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(ip);
|
||||
SSH_BUFFER_FREE(ip);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
158
src/pki.c
158
src/pki.c
@@ -174,7 +174,7 @@ void ssh_key_clean (ssh_key key){
|
||||
}
|
||||
SAFE_FREE(key->ed25519_pubkey);
|
||||
if (key->cert != NULL) {
|
||||
ssh_buffer_free(key->cert);
|
||||
SSH_BUFFER_FREE(key->cert);
|
||||
}
|
||||
key->cert_type = SSH_KEYTYPE_UNKNOWN;
|
||||
key->flags=SSH_KEY_FLAG_EMPTY;
|
||||
@@ -705,7 +705,7 @@ void ssh_signature_free(ssh_signature sig)
|
||||
|
||||
/* Explicitly zero the signature content before free */
|
||||
ssh_string_burn(sig->raw_sig);
|
||||
ssh_string_free(sig->raw_sig);
|
||||
SSH_STRING_FREE(sig->raw_sig);
|
||||
SAFE_FREE(sig);
|
||||
}
|
||||
|
||||
@@ -817,7 +817,7 @@ int ssh_pki_export_privkey_base64(const ssh_key privkey,
|
||||
}
|
||||
|
||||
b64 = strndup(ssh_string_data(blob), ssh_string_len(blob));
|
||||
ssh_string_free(blob);
|
||||
SSH_STRING_FREE(blob);
|
||||
if (b64 == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -979,7 +979,7 @@ int ssh_pki_export_privkey_file(const ssh_key privkey,
|
||||
}
|
||||
|
||||
rc = fwrite(ssh_string_data(blob), ssh_string_len(blob), 1, fp);
|
||||
ssh_string_free(blob);
|
||||
SSH_STRING_FREE(blob);
|
||||
if (rc != 1 || ferror(fp)) {
|
||||
fclose(fp);
|
||||
unlink(filename);
|
||||
@@ -1083,15 +1083,15 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
ssh_string_len(privkey));
|
||||
#endif
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
SSH_STRING_FREE(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
SSH_STRING_FREE(q);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
SSH_STRING_FREE(g);
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
SSH_STRING_FREE(pubkey);
|
||||
ssh_string_burn(privkey);
|
||||
ssh_string_free(privkey);
|
||||
SSH_STRING_FREE(privkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1124,17 +1124,17 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
ssh_log_hexdump("q", ssh_string_data(q), ssh_string_len(q));
|
||||
#endif
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
ssh_string_burn(d);
|
||||
ssh_string_free(d);
|
||||
SSH_STRING_FREE(d);
|
||||
ssh_string_burn(iqmp);
|
||||
ssh_string_free(iqmp);
|
||||
SSH_STRING_FREE(iqmp);
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
SSH_STRING_FREE(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
SSH_STRING_FREE(q);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build RSA private key");
|
||||
goto fail;
|
||||
@@ -1158,16 +1158,20 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
}
|
||||
|
||||
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
|
||||
ssh_string_free(i);
|
||||
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;
|
||||
}
|
||||
|
||||
rc = pki_privkey_build_ecdsa(key, nid, e, exp);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
ssh_string_burn(exp);
|
||||
ssh_string_free(exp);
|
||||
SSH_STRING_FREE(exp);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA private key");
|
||||
goto fail;
|
||||
@@ -1187,8 +1191,8 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
|
||||
rc = pki_privkey_build_ed25519(key, pubkey, privkey);
|
||||
ssh_string_burn(privkey);
|
||||
ssh_string_free(privkey);
|
||||
ssh_string_free(pubkey);
|
||||
SSH_STRING_FREE(privkey);
|
||||
SSH_STRING_FREE(pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ed25519 key");
|
||||
goto fail;
|
||||
@@ -1252,13 +1256,13 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
ssh_log_hexdump("g", ssh_string_data(g), ssh_string_len(g));
|
||||
#endif
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
SSH_STRING_FREE(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
SSH_STRING_FREE(q);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
SSH_STRING_FREE(g);
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
SSH_STRING_FREE(pubkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build DSA public key");
|
||||
goto fail;
|
||||
@@ -1282,9 +1286,9 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
ssh_log_hexdump("n", ssh_string_data(n), ssh_string_len(n));
|
||||
#endif
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build RSA public key");
|
||||
goto fail;
|
||||
@@ -1308,14 +1312,14 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
}
|
||||
|
||||
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
|
||||
ssh_string_free(i);
|
||||
SSH_STRING_FREE(i);
|
||||
if (nid == -1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = pki_pubkey_build_ecdsa(key, nid, e);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA public key");
|
||||
goto fail;
|
||||
@@ -1334,20 +1338,20 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
if (ssh_string_len(pubkey) != ED25519_KEY_LEN) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid public key length");
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
SSH_STRING_FREE(pubkey);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
SSH_STRING_FREE(pubkey);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_KEY_LEN);
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
SSH_STRING_FREE(pubkey);
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
@@ -1449,7 +1453,7 @@ static int pki_import_cert_buffer(ssh_buffer buffer,
|
||||
|
||||
fail:
|
||||
ssh_key_free(key);
|
||||
ssh_buffer_free(cert);
|
||||
SSH_BUFFER_FREE(cert);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -1485,17 +1489,17 @@ int ssh_pki_import_pubkey_base64(const char *b64_key,
|
||||
|
||||
type_s = ssh_buffer_get_ssh_string(buffer);
|
||||
if (type_s == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
ssh_string_free(type_s);
|
||||
SSH_STRING_FREE(type_s);
|
||||
|
||||
if (is_cert_type(type)) {
|
||||
rc = pki_import_cert_buffer(buffer, type, pkey);
|
||||
} else {
|
||||
rc = pki_import_pubkey_buffer(buffer, type, pkey);
|
||||
}
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1550,7 +1554,7 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown key type found!");
|
||||
goto fail;
|
||||
}
|
||||
ssh_string_free(type_s);
|
||||
SSH_STRING_FREE(type_s);
|
||||
|
||||
if (is_cert_type(type)) {
|
||||
rc = pki_import_cert_buffer(buffer, type, pkey);
|
||||
@@ -1558,12 +1562,12 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
|
||||
rc = pki_import_pubkey_buffer(buffer, type, pkey);
|
||||
}
|
||||
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
return rc;
|
||||
fail:
|
||||
ssh_buffer_free(buffer);
|
||||
ssh_string_free(type_s);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
SSH_STRING_FREE(type_s);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -1881,7 +1885,7 @@ int ssh_pki_export_privkey_to_pubkey(const ssh_key privkey,
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR otherwise.
|
||||
*
|
||||
* @see ssh_string_free()
|
||||
* @see SSH_STRING_FREE()
|
||||
*/
|
||||
int ssh_pki_export_pubkey_blob(const ssh_key key,
|
||||
ssh_string *pblob)
|
||||
@@ -1911,7 +1915,7 @@ int ssh_pki_export_pubkey_blob(const ssh_key key,
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*
|
||||
* @see ssh_string_free_char()
|
||||
* @see SSH_STRING_FREE_CHAR()
|
||||
*/
|
||||
int ssh_pki_export_pubkey_base64(const ssh_key key,
|
||||
char **b64_key)
|
||||
@@ -1929,7 +1933,7 @@ int ssh_pki_export_pubkey_base64(const ssh_key key,
|
||||
}
|
||||
|
||||
b64 = bin_to_base64(ssh_string_data(key_blob), ssh_string_len(key_blob));
|
||||
ssh_string_free(key_blob);
|
||||
SSH_STRING_FREE(key_blob);
|
||||
if (b64 == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -2029,7 +2033,7 @@ int ssh_pki_copy_cert_to_privkey(const ssh_key certkey, ssh_key privkey) {
|
||||
|
||||
rc = ssh_buffer_add_buffer(cert_buffer, certkey->cert);
|
||||
if (rc != 0) {
|
||||
ssh_buffer_free(cert_buffer);
|
||||
SSH_BUFFER_FREE(cert_buffer);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -2056,38 +2060,42 @@ int ssh_pki_export_signature_blob(const ssh_signature sig,
|
||||
|
||||
str = ssh_string_from_char(sig->type_c);
|
||||
if (str == NULL) {
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buf, str);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
str = pki_signature_to_blob(sig);
|
||||
if (str == NULL) {
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buf, str);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
str = ssh_string_new(ssh_buffer_get_len(buf));
|
||||
if (str == NULL) {
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
||||
ssh_buffer_free(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;
|
||||
|
||||
@@ -2119,29 +2127,29 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
ssh_string_data(sig_blob),
|
||||
ssh_string_len(sig_blob));
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
algorithm = ssh_buffer_get_ssh_string(buf);
|
||||
if (algorithm == NULL) {
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
alg = ssh_string_get_char(algorithm);
|
||||
type = ssh_key_type_from_signature_name(alg);
|
||||
hash_type = ssh_key_hash_from_name(alg);
|
||||
ssh_string_free(algorithm);
|
||||
SSH_STRING_FREE(algorithm);
|
||||
|
||||
blob = ssh_buffer_get_ssh_string(buf);
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
if (blob == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
sig = pki_signature_from_blob(pubkey, blob, type, hash_type);
|
||||
ssh_string_free(blob);
|
||||
SSH_STRING_FREE(blob);
|
||||
if (sig == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -2328,11 +2336,14 @@ ssh_string ssh_pki_do_sign(ssh_session session,
|
||||
}
|
||||
|
||||
/* Get the session ID */
|
||||
session_id = ssh_string_new(crypto->digest_len);
|
||||
session_id = ssh_string_new(crypto->session_id_len);
|
||||
if (session_id == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ssh_string_fill(session_id, crypto->session_id, crypto->digest_len);
|
||||
rc = ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len);
|
||||
if (rc < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Fill the input */
|
||||
sign_input = ssh_buffer_new();
|
||||
@@ -2366,8 +2377,8 @@ ssh_string ssh_pki_do_sign(ssh_session session,
|
||||
|
||||
end:
|
||||
ssh_signature_free(sig);
|
||||
ssh_buffer_free(sign_input);
|
||||
ssh_string_free(session_id);
|
||||
SSH_BUFFER_FREE(sign_input);
|
||||
SSH_STRING_FREE(session_id);
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
@@ -2384,38 +2395,45 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session,
|
||||
int rc;
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_BOTH);
|
||||
if (crypto == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
ssh_string_free(session_id);
|
||||
SSH_STRING_FREE(session_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(sig_buf, session_id);
|
||||
if (rc < 0) {
|
||||
ssh_string_free(session_id);
|
||||
ssh_buffer_free(sig_buf);
|
||||
SSH_STRING_FREE(session_id);
|
||||
SSH_BUFFER_FREE(sig_buf);
|
||||
return NULL;
|
||||
}
|
||||
ssh_string_free(session_id);
|
||||
SSH_STRING_FREE(session_id);
|
||||
|
||||
/* append out buffer */
|
||||
if (ssh_buffer_add_buffer(sig_buf, buf) < 0) {
|
||||
ssh_buffer_free(sig_buf);
|
||||
SSH_BUFFER_FREE(sig_buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create signature */
|
||||
sig_blob = ssh_agent_sign_data(session, pubkey, sig_buf);
|
||||
|
||||
ssh_buffer_free(sig_buf);
|
||||
SSH_BUFFER_FREE(sig_buf);
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
@@ -2479,7 +2497,7 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
|
||||
end:
|
||||
ssh_signature_free(sig);
|
||||
ssh_buffer_free(sign_input);
|
||||
SSH_BUFFER_FREE(sign_input);
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
@@ -108,11 +108,11 @@ static int pki_private_key_decrypt(ssh_string blob,
|
||||
{
|
||||
struct ssh_cipher_struct *ciphers = ssh_get_ciphertab();
|
||||
struct ssh_cipher_struct cipher;
|
||||
uint8_t key_material[128];
|
||||
char passphrase_buffer[128];
|
||||
uint8_t key_material[128] = {0};
|
||||
char passphrase_buffer[128] = {0};
|
||||
size_t key_material_len;
|
||||
ssh_buffer buffer;
|
||||
ssh_string salt;
|
||||
ssh_buffer buffer = NULL;
|
||||
ssh_string salt = NULL;
|
||||
uint32_t rounds;
|
||||
int cmp;
|
||||
int rc;
|
||||
@@ -159,7 +159,7 @@ static int pki_private_key_decrypt(ssh_string blob,
|
||||
if (rc != SSH_ERROR){
|
||||
rc = ssh_buffer_unpack(buffer, "Sd", &salt, &rounds);
|
||||
}
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
if (rc == SSH_ERROR){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -364,11 +364,11 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
}
|
||||
out:
|
||||
if (buffer != NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
if (privkey_buffer != NULL) {
|
||||
ssh_buffer_free(privkey_buffer);
|
||||
SSH_BUFFER_FREE(privkey_buffer);
|
||||
privkey_buffer = NULL;
|
||||
}
|
||||
SAFE_FREE(magic);
|
||||
@@ -440,9 +440,9 @@ static int pki_private_key_encrypt(ssh_buffer privkey_buffer,
|
||||
{
|
||||
struct ssh_cipher_struct *ciphers = ssh_get_ciphertab();
|
||||
struct ssh_cipher_struct cipher;
|
||||
uint8_t key_material[128];
|
||||
uint8_t key_material[128] = {0};
|
||||
size_t key_material_len;
|
||||
char passphrase_buffer[128];
|
||||
char passphrase_buffer[128] = {0};
|
||||
int rc;
|
||||
int i;
|
||||
int cmp;
|
||||
@@ -620,26 +620,26 @@ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
||||
|
||||
salt = ssh_string_new(16);
|
||||
if (salt == NULL){
|
||||
ssh_buffer_free(kdf_buf);
|
||||
SSH_BUFFER_FREE(kdf_buf);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ok = ssh_get_random(ssh_string_data(salt), 16, 0);
|
||||
if (!ok) {
|
||||
ssh_buffer_free(kdf_buf);
|
||||
SSH_BUFFER_FREE(kdf_buf);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_buffer_pack(kdf_buf, "Sd", salt, rounds);
|
||||
kdf_options = ssh_string_new(ssh_buffer_get_len(kdf_buf));
|
||||
if (kdf_options == NULL){
|
||||
ssh_buffer_free(kdf_buf);
|
||||
SSH_BUFFER_FREE(kdf_buf);
|
||||
goto error;
|
||||
}
|
||||
memcpy(ssh_string_data(kdf_options),
|
||||
ssh_buffer_get(kdf_buf),
|
||||
ssh_buffer_get_len(kdf_buf));
|
||||
ssh_buffer_free(kdf_buf);
|
||||
SSH_BUFFER_FREE(kdf_buf);
|
||||
rc = pki_private_key_encrypt(privkey_buffer,
|
||||
passphrase,
|
||||
"aes128-cbc",
|
||||
@@ -701,7 +701,7 @@ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
||||
str_len = ssh_buffer_get_len(buffer);
|
||||
len = ssh_buffer_get_data(buffer, ssh_string_data(str), str_len);
|
||||
if (str_len != len) {
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
str = NULL;
|
||||
}
|
||||
|
||||
@@ -709,13 +709,13 @@ error:
|
||||
if (privkey_buffer != NULL) {
|
||||
void *bufptr = ssh_buffer_get(privkey_buffer);
|
||||
explicit_bzero(bufptr, ssh_buffer_get_len(privkey_buffer));
|
||||
ssh_buffer_free(privkey_buffer);
|
||||
SSH_BUFFER_FREE(privkey_buffer);
|
||||
}
|
||||
SAFE_FREE(pubkey_s);
|
||||
SAFE_FREE(kdf_options);
|
||||
SAFE_FREE(salt);
|
||||
if (buffer != NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user