mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 12:20:42 +09:00
Compare commits
258 Commits
f333d95013
...
libssh-0.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
389efc234b | ||
|
|
f1e44a79a9 | ||
|
|
54cf7b92ed | ||
|
|
f0b676a9f0 | ||
|
|
cc190b21b2 | ||
|
|
a775324c35 | ||
|
|
5de765ebd5 | ||
|
|
9de970160d | ||
|
|
8a7abf2480 | ||
|
|
920c08eaf8 | ||
|
|
c0fa85a43d | ||
|
|
be16481be2 | ||
|
|
c4ac076607 | ||
|
|
ff534bc2fe | ||
|
|
27096c3c0f | ||
|
|
8a6ddc0a48 | ||
|
|
0c951b9f27 | ||
|
|
37529f16a8 | ||
|
|
e89106b9f7 | ||
|
|
67c0ce3d21 | ||
|
|
f618689c82 | ||
|
|
aaeaca8c6e | ||
|
|
58c26f4823 | ||
|
|
c888d9c690 | ||
|
|
07df7bb4e6 | ||
|
|
5aecfb5a96 | ||
|
|
50b37f2991 | ||
|
|
a47a291303 | ||
|
|
f199bd4879 | ||
|
|
4f7cb6076a | ||
|
|
3f6820694e | ||
|
|
0da6597fe4 | ||
|
|
0a13045f68 | ||
|
|
b56ffd8424 | ||
|
|
c60ac3fe02 | ||
|
|
84eab65edc | ||
|
|
7c3e37bf4c | ||
|
|
ab9921ee6a | ||
|
|
9296bcd4bb | ||
|
|
24f39761f3 | ||
|
|
49e8a4ef19 | ||
|
|
d7e1141c1e | ||
|
|
fd5c598477 | ||
|
|
de4034bfe0 | ||
|
|
6ccd84bae9 | ||
|
|
e4c281c7ce | ||
|
|
93541fe150 | ||
|
|
e6ba98a0aa | ||
|
|
6dcb960501 | ||
|
|
fcacc7fe8c | ||
|
|
f078f53911 | ||
|
|
27f5bfd129 | ||
|
|
4a0cbe396d | ||
|
|
a1812e9ac1 | ||
|
|
0e3dbd6c69 | ||
|
|
d2af62624d | ||
|
|
93113ccfb9 | ||
|
|
9ffaa12012 | ||
|
|
ae5146f7ba | ||
|
|
dd554ebb32 | ||
|
|
fae61f1d09 | ||
|
|
9e8e5f5cb2 | ||
|
|
80c1dbdb61 | ||
|
|
4505c076b3 | ||
|
|
99dc2002b9 | ||
|
|
878d8320c1 | ||
|
|
80e729fe33 | ||
|
|
47945671af | ||
|
|
b2e7ef6836 | ||
|
|
651fea9f14 | ||
|
|
f10db964b5 | ||
|
|
703f0a0f36 | ||
|
|
7b8d57fbb6 | ||
|
|
8e793d930e | ||
|
|
cc2feabe73 | ||
|
|
4d57d73faf | ||
|
|
4bd9041afb | ||
|
|
74e084f76c | ||
|
|
6c80718c0d | ||
|
|
a330806e4b | ||
|
|
3b01c328ab | ||
|
|
5b981a9e3d | ||
|
|
36dc66da81 | ||
|
|
2a3718de51 | ||
|
|
1fd68ec732 | ||
|
|
fa3caa61fd | ||
|
|
aaa978ad06 | ||
|
|
b9530cedbe | ||
|
|
7ff0af7543 | ||
|
|
b040856ccf | ||
|
|
79900e5246 | ||
|
|
63b0399373 | ||
|
|
39665fd9c5 | ||
|
|
83f0be1f04 | ||
|
|
3bc5f88f77 | ||
|
|
466ca07626 | ||
|
|
b6e757d692 | ||
|
|
3f2375e948 | ||
|
|
4d06c2f283 | ||
|
|
0298bfbbf0 | ||
|
|
2399a9f8de | ||
|
|
79756c5c56 | ||
|
|
e8510043d2 | ||
|
|
1f7889f271 | ||
|
|
89efd56217 | ||
|
|
e3fca31c59 | ||
|
|
d71a7976dd | ||
|
|
8fe8d13e29 | ||
|
|
722f979790 | ||
|
|
2c60ef04d9 | ||
|
|
ec486d13db | ||
|
|
ebfe46f6ad | ||
|
|
3c0897b975 | ||
|
|
993e0df81e | ||
|
|
551188d99b | ||
|
|
cafafe8f5a | ||
|
|
c6c7856b51 | ||
|
|
ea71af9c22 | ||
|
|
bb98413fc1 | ||
|
|
2a8cd81e8f |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,6 +4,8 @@
|
||||
*.swp
|
||||
*~$
|
||||
cscope.*
|
||||
compile_commands.json
|
||||
/.clangd
|
||||
tags
|
||||
/build
|
||||
/obj*
|
||||
|
||||
@@ -4,9 +4,8 @@ variables:
|
||||
CENTOS7_BUILD: buildenv-centos7
|
||||
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
||||
MINGW_BUILD: buildenv-mingw
|
||||
DEBIAN_CROSS_BUILD: buildenv-debian-cross
|
||||
|
||||
# torture_auth fails on centos7 docker images, so we don't use -DCLIENT_TESTING=ON
|
||||
# pkd tests fail on CentOS7 docker images, so we don't use -DSERVER_TESTING=ON
|
||||
centos7/openssl_1.0.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD
|
||||
script:
|
||||
@@ -14,7 +13,7 @@ centos7/openssl_1.0.x/x86_64:
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -34,6 +33,7 @@ fedora/openssl_1.1.x/x86_64:
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_BLOWFISH_CIPHER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DWITH_DEBUG_CRYPTO=ON
|
||||
-DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
@@ -153,6 +153,8 @@ fedora/undefined-sanitizer:
|
||||
- obj/
|
||||
|
||||
fedora/csbuild:
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- |
|
||||
@@ -168,8 +170,7 @@ fedora/csbuild:
|
||||
|
||||
- csbuild
|
||||
--build-dir=obj-csbuild
|
||||
--prep-cmd="rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@"
|
||||
--build-cmd "make clean && make -j$(nproc)"
|
||||
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@ && make clean && make -j$(nproc)"
|
||||
--git-commit-range $CI_COMMIT_RANGE
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
@@ -215,7 +216,7 @@ fedora/libgcrypt/x86_64:
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
-DWITH_GCRYPT=ON .. &&
|
||||
-DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -235,7 +236,7 @@ fedora/mbedtls/x86_64:
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
-DWITH_MBEDTLS=ON .. &&
|
||||
-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -295,33 +296,6 @@ fedora/mingw32:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
.Debian.cross.template: &Debian_cross_template
|
||||
stage: test
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$DEBIAN_CROSS_BUILD
|
||||
script:
|
||||
- build=$(dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
- host="${CI_JOB_NAME#*.cross.}"
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_C_COMPILER="$(which $host-gcc)"
|
||||
-DCMAKE_CXX_COMPILER="$(which $host-g++)"
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DUNIT_TESTING=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
.Debian.cross.mips-linux-gnu:
|
||||
<<: *Debian_cross_template
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86_64/gcc:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
@@ -330,7 +304,7 @@ tumbleweed/openssl_1.1.x/x86_64/gcc:
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
-DUNIT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -371,7 +345,7 @@ tumbleweed/openssl_1.1.x/x86_64/gcc7:
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
-DUNIT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -413,7 +387,8 @@ tumbleweed/openssl_1.1.x/x86_64/clang:
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
-DUNIT_TESTING=ON
|
||||
-DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -446,7 +421,7 @@ tumbleweed/undefined-sanitizer:
|
||||
-DCMAKE_BUILD_TYPE=UndefinedSanitizer
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
-DUNIT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -468,7 +443,7 @@ tumbleweed/static-analysis:
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
-DUNIT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
scan-build --status-bugs -o scan make -j$(nproc)
|
||||
tags:
|
||||
- shared
|
||||
|
||||
@@ -10,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
|
||||
project(libssh VERSION 0.8.90 LANGUAGES C)
|
||||
project(libssh VERSION 0.9.3 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -22,16 +22,16 @@ 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.1")
|
||||
set(LIBRARY_VERSION "4.8.4")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
|
||||
# add definitions
|
||||
include(DefinePlatformDefaults)
|
||||
include(DefineInstallationPaths)
|
||||
include(DefineOptions.cmake)
|
||||
include(CPackConfig.cmake)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(CompilerChecks.cmake)
|
||||
|
||||
@@ -117,7 +117,7 @@ install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/pkgconfig
|
||||
${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
COMPONENT
|
||||
pkgconfig
|
||||
)
|
||||
@@ -133,21 +133,13 @@ write_basic_package_version_file(libssh-config-version.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
# libssh-config.cmake
|
||||
configure_package_config_file(${PROJECT_NAME}-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
|
||||
PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
|
||||
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
COMPONENT
|
||||
devel
|
||||
)
|
||||
devel)
|
||||
|
||||
if (WITH_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
@@ -213,6 +205,11 @@ endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
|
||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET})
|
||||
|
||||
# Link compile database for clangd
|
||||
execute_process(COMMAND cmake -E create_symlink
|
||||
"${CMAKE_BINARY_DIR}/compile_commands.json"
|
||||
"${CMAKE_SOURCE_DIR}/compile_commands.json")
|
||||
|
||||
message(STATUS "********************************************")
|
||||
message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
||||
|
||||
@@ -225,7 +222,7 @@ message(STATUS "Server support : ${WITH_SERVER}")
|
||||
message(STATUS "GSSAPI support : ${WITH_GSSAPI}")
|
||||
message(STATUS "GEX support : ${WITH_GEX}")
|
||||
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
|
||||
message(STATUS "With static library: ${WITH_STATIC_LIB}")
|
||||
message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}")
|
||||
message(STATUS "Unit testing: ${UNIT_TESTING}")
|
||||
message(STATUS "Client code testing: ${CLIENT_TESTING}")
|
||||
message(STATUS "Blowfish cipher support: ${WITH_BLOWFISH_CIPHER}")
|
||||
|
||||
@@ -10,7 +10,7 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
|
||||
# SOURCE GENERATOR
|
||||
set(CPACK_SOURCE_GENERATOR "TXZ")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;.gitignore;/build*;/obj*;tags;cscope.*")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;/[.]clangd/;.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)
|
||||
|
||||
|
||||
102
ChangeLog
102
ChangeLog
@@ -1,7 +1,41 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.9.0 (released 2019-02-xx)
|
||||
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)
|
||||
* Fixed detection of OpenSSL ed25519 support (T197)
|
||||
|
||||
version 0.9.1 (released 2019-10-25)
|
||||
* Added support for Ed25519 via OpenSSL
|
||||
* Added support for X25519 via OpenSSL
|
||||
* Added support for localuser in Match keyword
|
||||
* Fixed Match keyword to be case sensitive
|
||||
* Fixed compilation with LibreSSL
|
||||
* Fixed error report of channel open (T75)
|
||||
* Fixed sftp documentation (T137)
|
||||
* Fixed known_hosts parsing (T156)
|
||||
* Fixed build issue with MinGW (T157)
|
||||
* Fixed build with gcc 9 (T164)
|
||||
* Fixed deprecation issues (T165)
|
||||
* Fixed known_hosts directory creation (T166)
|
||||
|
||||
version 0.9.0 (released 2019-06-28)
|
||||
* Added support for AES-GCM
|
||||
* Added improved rekeying support
|
||||
* Added performance improvements
|
||||
@@ -11,10 +45,76 @@ version 0.9.0 (released 2019-02-xx)
|
||||
* Added support for Encrypt-then-MAC mode
|
||||
* Added support for parsing server side configuration file
|
||||
* Added support for ECDSA/Ed25519 certificates
|
||||
* Added FIPS 140-2 compatibility
|
||||
* Improved known_hosts parsing
|
||||
* Improved documentation
|
||||
* Improved OpenSSL API usage for KEX, DH, and signatures
|
||||
|
||||
version 0.8.7 (released 2019-02-25)
|
||||
* Fixed handling extension flags in the server implementation
|
||||
* Fixed exporting ed25519 private keys
|
||||
* Fixed corner cases for rsa-sha2 signatures
|
||||
* Fixed some issues with connector
|
||||
|
||||
version 0.8.6 (released 2018-12-24)
|
||||
* Fixed compilation issues with different OpenSSL versions
|
||||
* Fixed StrictHostKeyChecking in new knownhosts API
|
||||
* Fixed ssh_send_keepalive() with packet filter
|
||||
* Fixed possible crash with knownhosts options
|
||||
* Fixed issus with rekeying
|
||||
* Fixed strong ECDSA keys
|
||||
* Fixed some issues with rsa-sha2 extentions
|
||||
* Fixed access violation in ssh_init() (static linking)
|
||||
* Fixed ssh_channel_close() handling
|
||||
|
||||
version 0.8.5 (released 2018-10-29)
|
||||
* Added support to get known_hosts locations with ssh_options_get()
|
||||
* Fixed preferred algorithm for known hosts negotiations
|
||||
* Fixed KEX with some server implementations (e.g. Cisco)
|
||||
* Fixed issues with MSVC
|
||||
* Fixed keyboard-interactive auth in server mode
|
||||
(regression from CVE-2018-10933)
|
||||
* Fixed gssapi auth in server mode (regression from CVE-2018-10933)
|
||||
* Fixed socket fd handling with proxy command
|
||||
* Fixed a memory leak with OpenSSL
|
||||
|
||||
version 0.8.4 (released 2018-10-16)
|
||||
* Fixed CVE-2018-10933
|
||||
* Fixed building without globbing support
|
||||
* Fixed possible memory leaks
|
||||
* Avoid SIGPIPE on sockets
|
||||
|
||||
version 0.8.3 (released 2018-09-21)
|
||||
* Added support for rsa-sha2
|
||||
* Added support to parse private keys in openssh container format
|
||||
(other than ed25519)
|
||||
* Added support for diffie-hellman-group18-sha512 and
|
||||
diffie-hellman-group16-sha512
|
||||
* Added ssh_get_fingerprint_hash()
|
||||
* Added ssh_pki_export_privkey_base64()
|
||||
* Added support for Match keyword in config file
|
||||
* Improved performance and reduced memory footprint for sftp
|
||||
* Fixed ecdsa publickey auth
|
||||
* Fixed reading a closed channel
|
||||
* Added support to announce posix-rename@openssh.com and
|
||||
hardlink@openssh.com in the sftp server
|
||||
|
||||
version 0.8.2 (released 2018-08-30)
|
||||
* Added sha256 fingerprints for pubkeys
|
||||
* Improved compiler flag detection
|
||||
* Fixed race condition in reading sftp messages
|
||||
* Fixed doxygen generation and added modern style
|
||||
* Fixed library initialization on Windows
|
||||
* Fixed __bounded__ attribute detection
|
||||
* Fixed a bug in the options parser
|
||||
* Fixed documentation for new knwon_hosts API
|
||||
|
||||
version 0.8.1 (released 2018-08-13)
|
||||
* Fixed version number in the header
|
||||
* Fixed version number in pkg-config and cmake config
|
||||
* Fixed library initialization
|
||||
* Fixed attribute detection
|
||||
|
||||
version 0.8.0 (released 2018-08-10)
|
||||
* Removed support for deprecated SSHv1 protocol
|
||||
* Added new connector API for clients
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -9,10 +9,7 @@ include(TestBigEndian)
|
||||
|
||||
set(PACKAGE ${PROJECT_NAME})
|
||||
set(VERSION ${PROJECT_VERSION})
|
||||
set(DATADIR ${DATA_INSTALL_DIR})
|
||||
set(LIBDIR ${LIB_INSTALL_DIR})
|
||||
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
|
||||
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
||||
set(SYSCONFDIR ${CMAKE_INSTALL_SYSCONFDIR})
|
||||
|
||||
set(BINARYDIR ${CMAKE_BINARY_DIR})
|
||||
set(SOURCEDIR ${CMAKE_SOURCE_DIR})
|
||||
@@ -131,12 +128,37 @@ if (OPENSSL_FOUND)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
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})
|
||||
check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
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})
|
||||
check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
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})
|
||||
check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519)
|
||||
|
||||
if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND
|
||||
FOUND_OPENSSL_ED25519)
|
||||
set(HAVE_OPENSSL_ED25519 1)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519)
|
||||
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif()
|
||||
|
||||
@@ -2,7 +2,6 @@ option(WITH_GSSAPI "Build with GSSAPI support" ON)
|
||||
option(WITH_ZLIB "Build with ZLIB support" ON)
|
||||
option(WITH_SFTP "Build with SFTP support" ON)
|
||||
option(WITH_SERVER "Build with SSH server support" ON)
|
||||
option(WITH_STATIC_LIB "Build with a static library" OFF)
|
||||
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
|
||||
option(WITH_DEBUG_PACKET "Build with packet debug output" OFF)
|
||||
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
|
||||
@@ -11,6 +10,7 @@ option(WITH_MBEDTLS "Compile against libmbedtls" OFF)
|
||||
option(WITH_BLOWFISH_CIPHER "Compile with blowfish support" OFF)
|
||||
option(WITH_PCAP "Compile with Pcap generation support" ON)
|
||||
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
option(UNIT_TESTING "Build with unit tests" OFF)
|
||||
option(CLIENT_TESTING "Build with client tests; requires openssh" OFF)
|
||||
option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF)
|
||||
@@ -34,13 +34,9 @@ if (WITH_BENCHMARKS)
|
||||
set(CLIENT_TESTING ON)
|
||||
endif()
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
set(BUILD_STATIC_LIB ON)
|
||||
endif (WITH_STATIC_LIB)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
if (UNIT_TESTING OR CLIENT_TESTING OR SERVER_TESTING)
|
||||
set(BUILD_STATIC_LIB ON)
|
||||
endif (UNIT_TESTING)
|
||||
endif()
|
||||
|
||||
if (WITH_NACL)
|
||||
set(WITH_NACL ON)
|
||||
|
||||
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
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
if (UNIX OR OS2)
|
||||
IF (NOT APPLICATION_NAME)
|
||||
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
|
||||
SET(APPLICATION_NAME ${PROJECT_NAME})
|
||||
ENDIF (NOT APPLICATION_NAME)
|
||||
|
||||
# Suffix for Linux
|
||||
SET(LIB_SUFFIX
|
||||
CACHE STRING "Define suffix of directory name (32/64)"
|
||||
)
|
||||
|
||||
SET(EXEC_INSTALL_PREFIX
|
||||
"${CMAKE_INSTALL_PREFIX}"
|
||||
CACHE PATH "Base directory for executables and libraries"
|
||||
)
|
||||
SET(SHARE_INSTALL_PREFIX
|
||||
"${CMAKE_INSTALL_PREFIX}/share"
|
||||
CACHE PATH "Base directory for files which go to share/"
|
||||
)
|
||||
SET(DATA_INSTALL_PREFIX
|
||||
"${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}"
|
||||
CACHE PATH "The parent directory where applications can install their data")
|
||||
|
||||
# The following are directories where stuff will be installed to
|
||||
SET(BIN_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/bin"
|
||||
CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)"
|
||||
)
|
||||
SET(SBIN_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/sbin"
|
||||
CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)"
|
||||
)
|
||||
SET(LIB_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)"
|
||||
)
|
||||
SET(LIBEXEC_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/libexec"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)"
|
||||
)
|
||||
SET(PLUGIN_INSTALL_DIR
|
||||
"${LIB_INSTALL_DIR}/${APPLICATION_NAME}"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})"
|
||||
)
|
||||
SET(INCLUDE_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/include"
|
||||
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
|
||||
)
|
||||
|
||||
set(CMAKE_INSTALL_DIR
|
||||
"${LIB_INSTALL_DIR}/cmake"
|
||||
CACHE PATH "The subdirectory to install cmake config files")
|
||||
|
||||
SET(DATA_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}"
|
||||
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
|
||||
)
|
||||
SET(HTML_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}/doc/HTML"
|
||||
CACHE PATH "The HTML install dir for documentation (default data/doc/html)"
|
||||
)
|
||||
SET(ICON_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}/icons"
|
||||
CACHE PATH "The icon install dir (default data/icons/)"
|
||||
)
|
||||
SET(SOUND_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}/sounds"
|
||||
CACHE PATH "The install dir for sound files (default data/sounds)"
|
||||
)
|
||||
|
||||
SET(LOCALE_INSTALL_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/locale"
|
||||
CACHE PATH "The install dir for translations (default prefix/share/locale)"
|
||||
)
|
||||
|
||||
SET(XDG_APPS_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/applications/"
|
||||
CACHE PATH "The XDG apps dir"
|
||||
)
|
||||
SET(XDG_DIRECTORY_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/desktop-directories"
|
||||
CACHE PATH "The XDG directory"
|
||||
)
|
||||
|
||||
SET(SYSCONF_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/etc"
|
||||
CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)"
|
||||
)
|
||||
SET(MAN_INSTALL_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/man"
|
||||
CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)"
|
||||
)
|
||||
SET(INFO_INSTALL_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/info"
|
||||
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
|
||||
)
|
||||
else()
|
||||
# Same same
|
||||
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
|
||||
set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-")
|
||||
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-")
|
||||
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
|
||||
set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-")
|
||||
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
|
||||
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
|
||||
set(ICON_INSTALL_DIR "icons" CACHE PATH "-")
|
||||
set(SOUND_INSTALL_DIR "soudns" CACHE PATH "-")
|
||||
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
|
||||
endif ()
|
||||
@@ -4,10 +4,6 @@
|
||||
/* Version number of package */
|
||||
#cmakedefine VERSION "${PROJECT_VERSION}"
|
||||
|
||||
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
|
||||
#cmakedefine DATADIR "${DATADIR}"
|
||||
#cmakedefine LIBDIR "${LIBDIR}"
|
||||
#cmakedefine PLUGINDIR "${PLUGINDIR}"
|
||||
#cmakedefine SYSCONFDIR "${SYSCONFDIR}"
|
||||
#cmakedefine BINARYDIR "${BINARYDIR}"
|
||||
#cmakedefine SOURCEDIR "${SOURCEDIR}"
|
||||
@@ -101,6 +97,12 @@
|
||||
/* Define to 1 if you have gl_flags as a glob_t sturct member */
|
||||
#cmakedefine HAVE_GLOB_GL_FLAGS_MEMBER 1
|
||||
|
||||
/* Define to 1 if you have OpenSSL with Ed25519 support */
|
||||
#cmakedefine HAVE_OPENSSL_ED25519 1
|
||||
|
||||
/* Define to 1 if you have OpenSSL with X25519 support */
|
||||
#cmakedefine HAVE_OPENSSL_X25519 1
|
||||
|
||||
/*************************** FUNCTIONS ***************************/
|
||||
|
||||
/* Define to 1 if you have the `EVP_aes128_ctr' function. */
|
||||
@@ -124,6 +126,15 @@
|
||||
/* Define to 1 if you have the `EVP_KDF_CTX_new_id' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID 1
|
||||
|
||||
/* Define to 1 if you have the `FIPS_mode' function. */
|
||||
#cmakedefine HAVE_OPENSSL_FIPS_MODE 1
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestSign' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_DIGESTSIGN 1
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestVerify' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_DIGESTVERIFY 1
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_ia32cap_loc' function. */
|
||||
#cmakedefine HAVE_OPENSSL_IA32CAP_LOC 1
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,10 +6,7 @@ set(examples_SRCS
|
||||
connect_ssh.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
include_directories(${libssh_BINARY_DIR})
|
||||
|
||||
if (ARGP_INCLUDE_DIR)
|
||||
include_directories(${ARGP_INCLUDE_DIR})
|
||||
@@ -18,68 +15,68 @@ endif()
|
||||
if (UNIX AND NOT WIN32)
|
||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||
target_compile_options(libssh_scp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(libssh_scp ssh::ssh)
|
||||
|
||||
add_executable(scp_download scp_download.c ${examples_SRCS})
|
||||
target_compile_options(scp_download PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(scp_download ssh::ssh)
|
||||
|
||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||
target_compile_options(sshnetcat PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(sshnetcat ssh::ssh)
|
||||
|
||||
if (WITH_SFTP)
|
||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||
target_compile_options(samplesftp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(samplesftp ssh::ssh)
|
||||
endif (WITH_SFTP)
|
||||
|
||||
add_executable(ssh-client ssh_client.c ${examples_SRCS})
|
||||
target_compile_options(ssh-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(ssh-client ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(ssh-client ssh::ssh)
|
||||
|
||||
if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H))
|
||||
if (HAVE_LIBUTIL)
|
||||
add_executable(ssh_server_fork ssh_server_fork.c)
|
||||
target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(ssh_server_fork ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARY} util)
|
||||
target_link_libraries(ssh_server_fork ssh::ssh ${ARGP_LIBRARY} util)
|
||||
endif (HAVE_LIBUTIL)
|
||||
|
||||
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
add_executable(samplesshd-cb samplesshd-cb.c)
|
||||
target_compile_options(samplesshd-cb PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(samplesshd-cb ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARY})
|
||||
target_link_libraries(samplesshd-cb ssh::ssh ${ARGP_LIBRARY})
|
||||
|
||||
add_executable(proxy proxy.c)
|
||||
target_compile_options(proxy PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(proxy ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARY})
|
||||
target_link_libraries(proxy ssh::ssh ${ARGP_LIBRARY})
|
||||
|
||||
add_executable(sshd_direct-tcpip sshd_direct-tcpip.c)
|
||||
target_compile_options(sshd_direct-tcpip PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(sshd_direct-tcpip ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARY})
|
||||
target_link_libraries(sshd_direct-tcpip ssh::ssh ${ARGP_LIBRARY})
|
||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
|
||||
add_executable(samplesshd-kbdint samplesshd-kbdint.c)
|
||||
target_compile_options(samplesshd-kbdint PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(samplesshd-kbdint ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARY})
|
||||
target_link_libraries(samplesshd-kbdint ssh::ssh ${ARGP_LIBRARY})
|
||||
|
||||
endif()
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
add_executable(exec exec.c ${examples_SRCS})
|
||||
target_compile_options(exec PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(exec ssh::ssh)
|
||||
|
||||
add_executable(senddata senddata.c ${examples_SRCS})
|
||||
target_compile_options(senddata PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(senddata ssh::ssh)
|
||||
|
||||
add_executable(keygen keygen.c)
|
||||
target_compile_options(keygen PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(keygen ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(keygen ssh::ssh)
|
||||
|
||||
add_executable(libsshpp libsshpp.cpp)
|
||||
target_link_libraries(libsshpp ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(libsshpp ssh::ssh)
|
||||
|
||||
add_executable(libsshpp_noexcept libsshpp_noexcept.cpp)
|
||||
target_link_libraries(libsshpp_noexcept ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(libsshpp_noexcept ssh::ssh)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
/* client.c */
|
||||
/* ssh_client.c */
|
||||
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
* Copyright 2003-2015 Aris Adamantiadis
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* You are free to copy this file, modify it in any way, consider it being public
|
||||
* domain. This does not apply to the rest of the library though, but it is
|
||||
* allowed to cut-and-paste working code from this file to any license of
|
||||
* program.
|
||||
* The goal is to show the API in action. It's not a reference on how terminal
|
||||
* clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
@@ -197,19 +198,20 @@ static void sizechanged(void)
|
||||
static void select_loop(ssh_session session,ssh_channel channel)
|
||||
{
|
||||
ssh_connector connector_in, connector_out, connector_err;
|
||||
int rc;
|
||||
|
||||
ssh_event event = ssh_event_new();
|
||||
|
||||
/* stdin */
|
||||
connector_in = ssh_connector_new(session);
|
||||
ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDOUT);
|
||||
ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDINOUT);
|
||||
ssh_connector_set_in_fd(connector_in, 0);
|
||||
ssh_event_add_connector(event, connector_in);
|
||||
|
||||
/* stdout */
|
||||
connector_out = ssh_connector_new(session);
|
||||
ssh_connector_set_out_fd(connector_out, 1);
|
||||
ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDOUT);
|
||||
ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDINOUT);
|
||||
ssh_event_add_connector(event, connector_out);
|
||||
|
||||
/* stderr */
|
||||
@@ -222,7 +224,11 @@ static void select_loop(ssh_session session,ssh_channel channel)
|
||||
if (signal_delayed) {
|
||||
sizechanged();
|
||||
}
|
||||
ssh_event_dopoll(event, 60000);
|
||||
rc = ssh_event_dopoll(event, 60000);
|
||||
if (rc == SSH_ERROR) {
|
||||
fprintf(stderr, "Error in ssh_event_dopoll()\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ssh_event_remove_connector(event, connector_in);
|
||||
ssh_event_remove_connector(event, connector_out);
|
||||
@@ -233,7 +239,6 @@ static void select_loop(ssh_session session,ssh_channel channel)
|
||||
ssh_connector_free(connector_err);
|
||||
|
||||
ssh_event_free(event);
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
static void shell(ssh_session session)
|
||||
@@ -241,7 +246,11 @@ static void shell(ssh_session session)
|
||||
ssh_channel channel;
|
||||
struct termios terminal_local;
|
||||
int interactive=isatty(0);
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (interactive) {
|
||||
tcgetattr(0, &terminal_local);
|
||||
@@ -250,6 +259,7 @@ static void shell(ssh_session session)
|
||||
|
||||
if (ssh_channel_open_session(channel)) {
|
||||
printf("Error opening channel : %s\n", ssh_get_error(session));
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
chan = channel;
|
||||
@@ -260,6 +270,7 @@ static void shell(ssh_session session)
|
||||
|
||||
if (ssh_channel_request_shell(channel)) {
|
||||
printf("Requesting shell : %s\n", ssh_get_error(session));
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -273,6 +284,7 @@ static void shell(ssh_session session)
|
||||
if (interactive) {
|
||||
do_cleanup(0);
|
||||
}
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
static void batch_shell(ssh_session session)
|
||||
@@ -289,12 +301,18 @@ static void batch_shell(ssh_session session)
|
||||
}
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ssh_channel_open_session(channel);
|
||||
if (ssh_channel_request_exec(channel, buffer)) {
|
||||
printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session));
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
select_loop(session, channel);
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
static int client(ssh_session session)
|
||||
|
||||
@@ -70,6 +70,8 @@ static void set_default_keys(ssh_bind sshbind,
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY,
|
||||
KEYS_FOLDER "ssh_host_ecdsa_key");
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
|
||||
KEYS_FOLDER "ssh_host_ed25519_key");
|
||||
}
|
||||
#define DEF_STR_SIZE 1024
|
||||
char authorizedkeys[DEF_STR_SIZE] = {0};
|
||||
|
||||
@@ -23,7 +23,6 @@ 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>
|
||||
@@ -34,6 +33,20 @@ clients must be made or how a client should react.
|
||||
#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
|
||||
@@ -218,7 +231,9 @@ static void my_channel_close_function(ssh_session session, ssh_channel channel,
|
||||
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);
|
||||
}
|
||||
@@ -227,7 +242,10 @@ static void my_channel_eof_function(ssh_session session, ssh_channel channel, vo
|
||||
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);
|
||||
}
|
||||
@@ -236,7 +254,10 @@ static void my_channel_exit_status_function(ssh_session session, ssh_channel cha
|
||||
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,
|
||||
@@ -253,7 +274,11 @@ 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);
|
||||
}
|
||||
@@ -313,8 +338,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);
|
||||
|
||||
@@ -26,7 +26,7 @@ install(
|
||||
FILES
|
||||
${libssh_HDRS}
|
||||
DESTINATION
|
||||
${INCLUDE_INSTALL_DIR}/${APPLICATION_NAME}
|
||||
${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);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
bignum ssh_make_string_bn(ssh_string string);
|
||||
ssh_string ssh_make_bignum_string(bignum num);
|
||||
void ssh_print_bignum(const char *which, const bignum num);
|
||||
void ssh_print_bignum(const char *which, const_bignum num);
|
||||
|
||||
|
||||
#endif /* BIGNUM_H_ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -105,7 +105,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
|
||||
|
||||
@@ -48,6 +48,8 @@ int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer,
|
||||
int ssh_dh_compute_shared_secret(struct dh_ctx *ctx, int local, int remote,
|
||||
bignum *dest);
|
||||
|
||||
void ssh_dh_debug_crypto(struct ssh_crypto_struct *c);
|
||||
|
||||
/* common functions */
|
||||
int ssh_dh_init(void);
|
||||
void ssh_dh_finalize(void);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define SSH_KNOWNHOSTS_H_
|
||||
|
||||
struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session);
|
||||
char *ssh_known_hosts_get_algorithms_names(ssh_session session);
|
||||
enum ssh_known_hosts_e
|
||||
ssh_session_get_known_hosts_entry_file(ssh_session session,
|
||||
const char *filename,
|
||||
|
||||
@@ -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)
|
||||
@@ -112,7 +112,11 @@ typedef BN_CTX* bignum_CTX;
|
||||
|
||||
|
||||
/* Returns true if the OpenSSL is operating in FIPS mode */
|
||||
#ifdef HAVE_OPENSSL_FIPS_MODE
|
||||
#define ssh_fips_mode() (FIPS_mode() != 0)
|
||||
#else
|
||||
#define ssh_fips_mode() false
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
|
||||
@@ -78,7 +78,10 @@ int ssh_gcry_rand_range(bignum rnd, bignum max);
|
||||
#define bignum_bin2bn(data,datalen,dest) gcry_mpi_scan(dest,GCRYMPI_FMT_USG,data,datalen,NULL)
|
||||
#define bignum_bn2dec(num) ssh_gcry_bn2dec(num)
|
||||
#define bignum_dec2bn(num, data) ssh_gcry_dec2bn(data, num)
|
||||
#define bignum_bn2hex(num,data) gcry_mpi_aprint(GCRYMPI_FMT_HEX,data,NULL,num)
|
||||
|
||||
#define bignum_bn2hex(num, data) \
|
||||
gcry_mpi_aprint(GCRYMPI_FMT_HEX, data, NULL, (const gcry_mpi_t)num)
|
||||
|
||||
#define bignum_hex2bn(data, num) (gcry_mpi_scan(num,GCRYMPI_FMT_HEX,data,0,NULL)==0?1:0)
|
||||
#define bignum_rand(num,bits) 1,gcry_mpi_randomize(num,bits,GCRY_STRONG_RANDOM),gcry_mpi_set_bit(num,bits-1),gcry_mpi_set_bit(num,0)
|
||||
#define bignum_mod_exp(dest,generator,exp,modulo, ctx) 1,gcry_mpi_powm(dest,generator,exp,modulo)
|
||||
|
||||
@@ -75,7 +75,7 @@ struct mbedtls_ecdsa_sig {
|
||||
|
||||
bignum ssh_mbedcry_bn_new(void);
|
||||
void ssh_mbedcry_bn_free(bignum num);
|
||||
unsigned char *ssh_mbedcry_bn2num(bignum num, int radix);
|
||||
unsigned char *ssh_mbedcry_bn2num(const_bignum num, int radix);
|
||||
int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom);
|
||||
int ssh_mbedcry_is_bit_set(bignum num, size_t pos);
|
||||
int ssh_mbedcry_rand_range(bignum dest, bignum max);
|
||||
|
||||
@@ -78,8 +78,8 @@
|
||||
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 8
|
||||
#define LIBSSH_VERSION_MICRO 90
|
||||
#define LIBSSH_VERSION_MINOR 9
|
||||
#define LIBSSH_VERSION_MICRO 3
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
@@ -168,13 +168,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 {
|
||||
@@ -441,6 +441,7 @@ enum ssh_scp_request_types {
|
||||
enum ssh_connector_flags_e {
|
||||
/** Only the standard stream of the channel */
|
||||
SSH_CONNECTOR_STDOUT = 1,
|
||||
SSH_CONNECTOR_STDINOUT = 1,
|
||||
/** Only the exception stream of the channel */
|
||||
SSH_CONNECTOR_STDERR = 2,
|
||||
/** Merge both standard and exception streams */
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
char *ssh_get_user_home_dir(void);
|
||||
char *ssh_get_local_username(void);
|
||||
int ssh_file_readaccess_ok(const char *file);
|
||||
int ssh_dir_writeable(const char *path);
|
||||
|
||||
char *ssh_path_expand_tilde(const char *d);
|
||||
char *ssh_path_expand_escape(ssh_session session, const char *s);
|
||||
@@ -50,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);
|
||||
@@ -83,4 +90,11 @@ int ssh_match_group(const char *group, const char *object);
|
||||
|
||||
void uint64_inc(unsigned char *counter);
|
||||
|
||||
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_ */
|
||||
|
||||
@@ -30,7 +30,15 @@
|
||||
#endif
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* If using OpenSSL implementation, define the signature lenght which would be
|
||||
* defined in libssh/ed25519.h otherwise */
|
||||
#define ED25519_SIG_LEN 64
|
||||
#else
|
||||
#include "libssh/ed25519.h"
|
||||
#endif
|
||||
/* This definition is used for both OpenSSL and internal implementations */
|
||||
#define ED25519_KEY_LEN 32
|
||||
|
||||
#define MAX_PUBKEY_SIZE 0x100000 /* 1M */
|
||||
#define MAX_PRIVKEY_SIZE 0x400000 /* 4M */
|
||||
@@ -61,8 +69,13 @@ struct ssh_key_struct {
|
||||
void *ecdsa;
|
||||
# endif /* HAVE_OPENSSL_EC_H */
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
uint8_t *ed25519_pubkey;
|
||||
uint8_t *ed25519_privkey;
|
||||
#else
|
||||
ed25519_pubkey *ed25519_pubkey;
|
||||
ed25519_privkey *ed25519_privkey;
|
||||
#endif
|
||||
void *cert;
|
||||
enum ssh_keytypes_e cert_type;
|
||||
};
|
||||
@@ -79,7 +92,9 @@ struct ssh_signature_struct {
|
||||
ssh_string rsa_sig;
|
||||
struct mbedtls_ecdsa_sig ecdsa_sig;
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
ed25519_signature *ed25519_sig;
|
||||
#endif
|
||||
ssh_string raw_sig;
|
||||
};
|
||||
|
||||
@@ -96,6 +111,7 @@ enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name);
|
||||
enum ssh_keytypes_e ssh_key_type_plain(enum ssh_keytypes_e type);
|
||||
enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
|
||||
enum ssh_keytypes_e type);
|
||||
enum ssh_digest_e ssh_key_hash_from_name(const char *name);
|
||||
|
||||
#define is_ecdsa_key_type(t) \
|
||||
((t) >= SSH_KEYTYPE_ECDSA_P256 && (t) <= SSH_KEYTYPE_ECDSA_P521)
|
||||
@@ -118,7 +134,7 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
int ssh_pki_signature_verify(ssh_session session,
|
||||
ssh_signature sig,
|
||||
const ssh_key key,
|
||||
unsigned char *digest,
|
||||
const unsigned char *digest,
|
||||
size_t dlen);
|
||||
|
||||
/* SSH Public Key Functions */
|
||||
@@ -138,7 +154,8 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session,
|
||||
struct ssh_buffer_struct *buf,
|
||||
const ssh_key pubkey);
|
||||
ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
const ssh_key privkey);
|
||||
const ssh_key privkey,
|
||||
const enum ssh_digest_e digest);
|
||||
|
||||
/* Temporary functions, to be removed after migration to ssh_key */
|
||||
ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key);
|
||||
|
||||
@@ -124,11 +124,6 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
const ssh_string sig_blob,
|
||||
enum ssh_keytypes_e type,
|
||||
enum ssh_digest_e hash_type);
|
||||
int pki_signature_verify(ssh_session session,
|
||||
const ssh_signature sig,
|
||||
const ssh_key key,
|
||||
const unsigned char *input,
|
||||
size_t input_len);
|
||||
|
||||
/* SSH Signing Functions */
|
||||
ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
@@ -148,8 +143,8 @@ int pki_ed25519_key_cmp(const ssh_key k1,
|
||||
enum ssh_keycmp_e what);
|
||||
int pki_ed25519_key_dup(ssh_key new, const ssh_key key);
|
||||
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key);
|
||||
ssh_string pki_ed25519_sig_to_blob(ssh_signature sig);
|
||||
int pki_ed25519_sig_from_blob(ssh_signature sig, ssh_string sig_blob);
|
||||
ssh_string pki_ed25519_signature_to_blob(ssh_signature sig);
|
||||
int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob);
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey);
|
||||
|
||||
@@ -221,7 +221,17 @@ int gettimeofday(struct timeval *__p, void *__t);
|
||||
struct ssh_common_struct;
|
||||
struct ssh_kex_struct;
|
||||
|
||||
int ssh_get_key_params(ssh_session session, ssh_key *privkey);
|
||||
enum ssh_digest_e {
|
||||
SSH_DIGEST_AUTO=0,
|
||||
SSH_DIGEST_SHA1=1,
|
||||
SSH_DIGEST_SHA256,
|
||||
SSH_DIGEST_SHA384,
|
||||
SSH_DIGEST_SHA512,
|
||||
};
|
||||
|
||||
int ssh_get_key_params(ssh_session session,
|
||||
ssh_key *privkey,
|
||||
enum ssh_digest_e *digest);
|
||||
|
||||
/* LOGGING */
|
||||
void ssh_log_function(int verbosity,
|
||||
@@ -272,14 +282,12 @@ int ssh_auth_reply_success(ssh_session session, int partial);
|
||||
int ssh_send_banner(ssh_session session, int is_server);
|
||||
|
||||
/* connect.c */
|
||||
socket_t ssh_connect_host(ssh_session session, const char *host,const char
|
||||
*bind_addr, int port, long timeout, long usec);
|
||||
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
const char *bind_addr, int port);
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -145,7 +145,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;
|
||||
@@ -188,6 +188,7 @@ struct ssh_session_struct {
|
||||
ssh_key ed25519_key;
|
||||
/* The type of host key wanted by client */
|
||||
enum ssh_keytypes_e hostkey;
|
||||
enum ssh_digest_e hostkey_digest;
|
||||
} srv;
|
||||
|
||||
/* auths accepted by server */
|
||||
@@ -212,7 +213,7 @@ 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;
|
||||
|
||||
@@ -201,13 +201,18 @@ struct sftp_statvfs_struct {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Start a new sftp session.
|
||||
* @brief Creates a new sftp session.
|
||||
*
|
||||
* This function creates a new sftp session and allocates a new sftp channel
|
||||
* with the server inside of the provided ssh session. This function call is
|
||||
* usually followed by the sftp_init(), which initializes SFTP protocol itself.
|
||||
*
|
||||
* @param session The ssh session to use.
|
||||
*
|
||||
* @return A new sftp session or NULL on error.
|
||||
*
|
||||
* @see sftp_free()
|
||||
* @see sftp_init()
|
||||
*/
|
||||
LIBSSH_API sftp_session sftp_new(ssh_session session);
|
||||
|
||||
@@ -232,7 +237,10 @@ LIBSSH_API sftp_session sftp_new_channel(ssh_session session, ssh_channel channe
|
||||
LIBSSH_API void sftp_free(sftp_session sftp);
|
||||
|
||||
/**
|
||||
* @brief Initialize the sftp session with the server.
|
||||
* @brief Initialize the sftp protocol with the server.
|
||||
*
|
||||
* This function involves the SFTP protocol initialization (as described
|
||||
* in the SFTP specification), including the version and extensions negotiation.
|
||||
*
|
||||
* @param sftp The sftp session to initialize.
|
||||
*
|
||||
@@ -862,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_ */
|
||||
|
||||
@@ -38,7 +38,11 @@ void ssh_tokens_free(struct ssh_tokens_st *tokens);
|
||||
char *ssh_find_matching(const char *available_d,
|
||||
const char *preferred_d);
|
||||
|
||||
|
||||
char *ssh_find_all_matching(const char *available_d,
|
||||
const char *preferred_d);
|
||||
|
||||
char *ssh_remove_duplicates(const char *list);
|
||||
|
||||
char *ssh_append_without_duplicates(const char *list,
|
||||
const char *appended_list);
|
||||
#endif /* TOKEN_H_ */
|
||||
|
||||
@@ -29,14 +29,6 @@
|
||||
#include "libssh/libgcrypt.h"
|
||||
#include "libssh/libmbedcrypto.h"
|
||||
|
||||
enum ssh_digest_e {
|
||||
SSH_DIGEST_AUTO=0,
|
||||
SSH_DIGEST_SHA1=1,
|
||||
SSH_DIGEST_SHA256,
|
||||
SSH_DIGEST_SHA384,
|
||||
SSH_DIGEST_SHA512,
|
||||
};
|
||||
|
||||
enum ssh_kdf_digest {
|
||||
SSH_KDF_SHA1=1,
|
||||
SSH_KDF_SHA256,
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/CMakeCache.txt")
|
||||
# In tree build
|
||||
set_and_check(LIBSSH_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include")
|
||||
set_and_check(LIBSSH_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/@LIBSSH_LIBRARY_NAME@")
|
||||
else()
|
||||
set_and_check(LIBSSH_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
|
||||
set_and_check(LIBSSH_LIBRARIES "@PACKAGE_LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@")
|
||||
endif()
|
||||
|
||||
# For backward compatibility
|
||||
set(LIBSSH_LIBRARY ${LIBSSH_LIBRARIES})
|
||||
|
||||
mark_as_advanced(LIBSSH_LIBRARIES LIBSSH_LIBRARY LIBSSH_INCLUDE_DIR)
|
||||
@@ -1,6 +1,6 @@
|
||||
Name: ${PROJECT_NAME}
|
||||
Description: The SSH Library
|
||||
Version: ${PROJECT_VERSION}
|
||||
Libs: -L${LIB_INSTALL_DIR} -lssh
|
||||
Cflags: -I${INCLUDE_INSTALL_DIR}
|
||||
Libs: -L${CMAKE_INSTALL_FULL_LIBDIR} -lssh
|
||||
Cflags: -I${CMAKE_INSTALL_FULL_INCLUDEDIR}
|
||||
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Last Change: 2008-06-18 14:13:46
|
||||
#
|
||||
# Script to build libssh on UNIX.
|
||||
#
|
||||
# Copyright (c) 2006-2007 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
|
||||
SOURCE_DIR=".."
|
||||
|
||||
LANG=C
|
||||
export LANG
|
||||
|
||||
SCRIPT="$0"
|
||||
COUNT=0
|
||||
while [ -L "${SCRIPT}" ]
|
||||
do
|
||||
SCRIPT=$(readlink ${SCRIPT})
|
||||
COUNT=$(expr ${COUNT} + 1)
|
||||
if [ ${COUNT} -gt 100 ]; then
|
||||
echo "Too many symbolic links"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
BUILDDIR=$(dirname ${SCRIPT})
|
||||
|
||||
cleanup_and_exit () {
|
||||
if test "$1" = 0 -o -z "$1" ; then
|
||||
exit 0
|
||||
else
|
||||
exit $1
|
||||
fi
|
||||
}
|
||||
|
||||
function configure() {
|
||||
if [ -n "${CMAKEDIR}" ]; then
|
||||
${CMAKEDIR}/bin/cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
|
||||
else
|
||||
cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
|
||||
fi
|
||||
}
|
||||
|
||||
function compile() {
|
||||
if [ -f /proc/cpuinfo ]; then
|
||||
CPUCOUNT=$(grep -c processor /proc/cpuinfo)
|
||||
elif test `uname` = "SunOS" ; then
|
||||
CPUCOUNT=$(psrinfo -p)
|
||||
else
|
||||
CPUCOUNT="1"
|
||||
fi
|
||||
|
||||
if [ "${CPUCOUNT}" -gt "1" ]; then
|
||||
${MAKE} -j${CPUCOUNT} $1 || cleanup_and_exit $?
|
||||
else
|
||||
${MAKE} $1 || exit $?
|
||||
fi
|
||||
}
|
||||
|
||||
function clean_build_dir() {
|
||||
find ! -path "*.svn*" ! -name "*.bat" ! -name "*.sh" ! -name "." -print0 | xargs -0 rm -rf
|
||||
}
|
||||
|
||||
function usage () {
|
||||
echo "Usage: `basename $0` [--prefix /install_prefix|--build [debug|final]|--clean|--verbose|--libsuffix (32|64)|--help|--clang|--cmakedir /directory|--make
|
||||
(gmake|make)|--ccompiler(gcc|cc)|--withstaticlib|--unittesting|--clientunittesting|--withserver|--withoutsymbolversioning]"
|
||||
cleanup_and_exit
|
||||
}
|
||||
|
||||
cd ${BUILDDIR}
|
||||
|
||||
# the default CMake options:
|
||||
OPTIONS="--graphviz=${BUILDDIR}/libssh.dot"
|
||||
|
||||
# the default 'make' utility:
|
||||
MAKE="make"
|
||||
|
||||
while test -n "$1"; do
|
||||
PARAM="$1"
|
||||
ARG="$2"
|
||||
shift
|
||||
case ${PARAM} in
|
||||
*-*=*)
|
||||
ARG=${PARAM#*=}
|
||||
PARAM=${PARAM%%=*}
|
||||
set -- "----noarg=${PARAM}" "$@"
|
||||
esac
|
||||
case ${PARAM} in
|
||||
*-help|-h)
|
||||
#echo_help
|
||||
usage
|
||||
cleanup_and_exit
|
||||
;;
|
||||
*-build)
|
||||
DOMAKE="1"
|
||||
BUILD_TYPE="${ARG}"
|
||||
test -n "${BUILD_TYPE}" && shift
|
||||
;;
|
||||
*-clean)
|
||||
clean_build_dir
|
||||
cleanup_and_exit
|
||||
;;
|
||||
*-clang)
|
||||
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
|
||||
;;
|
||||
*-verbose)
|
||||
DOVERBOSE="1"
|
||||
;;
|
||||
*-memtest)
|
||||
OPTIONS="${OPTIONS} -DMEM_NULL_TESTS=ON"
|
||||
;;
|
||||
*-libsuffix)
|
||||
OPTIONS="${OPTIONS} -DLIB_SUFFIX=${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-prefix)
|
||||
OPTIONS="${OPTIONS} -DCMAKE_INSTALL_PREFIX=${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-sysconfdir)
|
||||
OPTIONS="${OPTIONS} -DSYSCONF_INSTALL_DIR=${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-cmakedir)
|
||||
CMAKEDIR="${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-make)
|
||||
MAKE="${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-ccompiler)
|
||||
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-withstaticlib)
|
||||
OPTIONS="${OPTIONS} -DWITH_STATIC_LIB=ON"
|
||||
;;
|
||||
*-unittesting)
|
||||
OPTIONS="${OPTIONS} -DUNIT_TESTING=ON"
|
||||
;;
|
||||
*-clientunittesting)
|
||||
OPTIONS="${OPTIONS} -DCLIENT_TESTING=ON"
|
||||
;;
|
||||
*-withserver)
|
||||
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
|
||||
;;
|
||||
*-withoutsymbolversioning)
|
||||
OPTIONS="${OPTIONS} -DWITH_SYMBOL_VERSIONING=OFF"
|
||||
;;
|
||||
*-finalrelease)
|
||||
OPTIONS="${OPTIONS} -DWITH_FINAL=ON"
|
||||
;;
|
||||
----noarg)
|
||||
echo "$ARG does not take an argument"
|
||||
cleanup_and_exit
|
||||
;;
|
||||
-*)
|
||||
echo Unknown Option "$PARAM". Exit.
|
||||
cleanup_and_exit 1
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "${DOMAKE}" == "1" ]; then
|
||||
OPTIONS="${OPTIONS} -DCMAKE_BUILD_TYPE=${BUILD_TYPE}"
|
||||
fi
|
||||
|
||||
if [ -n "${DOVERBOSE}" ]; then
|
||||
OPTIONS="${OPTIONS} -DCMAKE_VERBOSE_MAKEFILE=1"
|
||||
else
|
||||
OPTIONS="${OPTIONS} -DCMAKE_VERBOSE_MAKEFILE=0"
|
||||
fi
|
||||
|
||||
test -f "${BUILDDIR}/.build.log" && rm -f ${BUILDDIR}/.build.log
|
||||
touch ${BUILDDIR}/.build.log
|
||||
# log everything from here to .build.log
|
||||
exec 1> >(exec -a 'build logging tee' tee -a ${BUILDDIR}/.build.log) 2>&1
|
||||
echo "${HOST} started build at $(date)."
|
||||
echo
|
||||
|
||||
configure ${OPTIONS} "$@"
|
||||
|
||||
if [ -n "${DOMAKE}" ]; then
|
||||
test -n "${DOVERBOSE}" && compile VERBOSE=1 || compile
|
||||
fi
|
||||
|
||||
DOT=$(which dot 2>/dev/null)
|
||||
if [ -n "${DOT}" ]; then
|
||||
${DOT} -Tpng -o${BUILDDIR}/libssh.png ${BUILDDIR}/libssh.dot
|
||||
${DOT} -Tsvg -o${BUILDDIR}/libssh.svg ${BUILDDIR}/libssh.dot
|
||||
fi
|
||||
|
||||
exec >&0 2>&0 # so that the logging tee finishes
|
||||
sleep 1 # wait till tee terminates
|
||||
|
||||
cleanup_and_exit 0
|
||||
@@ -1 +1 @@
|
||||
4.8.1
|
||||
4.8.4
|
||||
421
src/ABI/libssh-4.8.2.symbols
Normal file
421
src/ABI/libssh-4.8.2.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.3.symbols
Normal file
421
src/ABI/libssh-4.8.3.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.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
|
||||
@@ -1,7 +1,4 @@
|
||||
set(LIBSSH_PUBLIC_INCLUDE_DIRS
|
||||
${libssh_SOURCE_DIR}/include
|
||||
CACHE INTERNAL "libssh public include directories"
|
||||
)
|
||||
set(LIBSSH_PUBLIC_INCLUDE_DIRS ${libssh_SOURCE_DIR}/include)
|
||||
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${libssh_BINARY_DIR}
|
||||
@@ -18,13 +15,6 @@ if (WIN32)
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
if (HAVE_LIBSOCKET)
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
socket
|
||||
)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
|
||||
if (OPENSSL_CRYPTO_LIBRARY)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
@@ -95,16 +85,6 @@ if (WITH_NACL AND NACL_FOUND)
|
||||
)
|
||||
endif (WITH_NACL AND NACL_FOUND)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
CACHE INTERNAL "libssh link libraries"
|
||||
)
|
||||
|
||||
set(LIBSSH_SHARED_LIBRARY
|
||||
ssh_shared
|
||||
CACHE INTERNAL "libssh shared library"
|
||||
)
|
||||
|
||||
if (BUILD_STATIC_LIB)
|
||||
set(LIBSSH_STATIC_LIBRARY
|
||||
ssh_static
|
||||
@@ -146,7 +126,6 @@ set(libssh_SRCS
|
||||
pcap.c
|
||||
pki.c
|
||||
pki_container_openssh.c
|
||||
pki_ed25519.c
|
||||
poll.c
|
||||
session.c
|
||||
scp.c
|
||||
@@ -157,14 +136,11 @@ set(libssh_SRCS
|
||||
external/bcrypt_pbkdf.c
|
||||
external/blowfish.c
|
||||
external/chacha.c
|
||||
external/ed25519.c
|
||||
external/fe25519.c
|
||||
external/ge25519.c
|
||||
external/poly1305.c
|
||||
external/sc25519.c
|
||||
chachapoly.c
|
||||
config_parser.c
|
||||
token.c
|
||||
pki_ed25519_common.c
|
||||
)
|
||||
|
||||
if (DEFAULT_C_NO_DEPRECATION_FLAGS)
|
||||
@@ -201,6 +177,11 @@ if (WITH_GCRYPT)
|
||||
pki_gcrypt.c
|
||||
ecdh_gcrypt.c
|
||||
dh_key.c
|
||||
pki_ed25519.c
|
||||
external/ed25519.c
|
||||
external/fe25519.c
|
||||
external/ge25519.c
|
||||
external/sc25519.c
|
||||
)
|
||||
elseif (WITH_MBEDTLS)
|
||||
set(libssh_SRCS
|
||||
@@ -211,6 +192,11 @@ elseif (WITH_MBEDTLS)
|
||||
pki_mbedcrypto.c
|
||||
ecdh_mbedcrypto.c
|
||||
dh_key.c
|
||||
pki_ed25519.c
|
||||
external/ed25519.c
|
||||
external/fe25519.c
|
||||
external/ge25519.c
|
||||
external/sc25519.c
|
||||
)
|
||||
else (WITH_GCRYPT)
|
||||
set(libssh_SRCS
|
||||
@@ -221,6 +207,16 @@ else (WITH_GCRYPT)
|
||||
libcrypto.c
|
||||
dh_crypto.c
|
||||
)
|
||||
if (NOT HAVE_OPENSSL_ED25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
pki_ed25519.c
|
||||
external/ed25519.c
|
||||
external/fe25519.c
|
||||
external/ge25519.c
|
||||
external/sc25519.c
|
||||
)
|
||||
endif (NOT HAVE_OPENSSL_ED25519)
|
||||
if(OPENSSL_VERSION VERSION_LESS "1.1.0")
|
||||
set(libssh_SRCS ${libssh_SRCS} libcrypto-compat.c)
|
||||
endif()
|
||||
@@ -271,17 +267,14 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
|
||||
if (NOT WITH_NACL)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
external/curve25519_ref.c
|
||||
)
|
||||
if (NOT HAVE_OPENSSL_ED25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
external/curve25519_ref.c
|
||||
)
|
||||
endif (NOT HAVE_OPENSSL_ED25519)
|
||||
endif (NOT WITH_NACL)
|
||||
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# Set the path to the default map file
|
||||
set(MAP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.map")
|
||||
|
||||
@@ -313,13 +306,27 @@ if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT AND ABIMAP_FOUND)
|
||||
)
|
||||
endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT AND ABIMAP_FOUND)
|
||||
|
||||
add_library(${LIBSSH_SHARED_LIBRARY} SHARED ${libssh_SRCS})
|
||||
target_compile_options(${LIBSSH_SHARED_LIBRARY}
|
||||
# This gets built as a static library, if -DBUILD_SHARED_LIBS=OFF is passed to
|
||||
# cmake.
|
||||
add_library(ssh ${libssh_SRCS})
|
||||
target_compile_options(ssh
|
||||
PRIVATE
|
||||
${DEFAULT_C_COMPILE_FLAGS}
|
||||
-D_GNU_SOURCE)
|
||||
target_include_directories(ssh
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${libssh_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${LIBSSH_PRIVATE_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(${LIBSSH_SHARED_LIBRARY} ${LIBSSH_LINK_LIBRARIES})
|
||||
target_link_libraries(ssh
|
||||
PRIVATE ${LIBSSH_LINK_LIBRARIES})
|
||||
|
||||
if (WIN32 AND NOT BUILD_SHARED_LIBS)
|
||||
set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-DLIBSSH_STATIC")
|
||||
endif ()
|
||||
|
||||
add_library(ssh::ssh ALIAS ssh)
|
||||
|
||||
if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
if (ABIMAP_FOUND)
|
||||
@@ -327,56 +334,63 @@ 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(${LIBSSH_SHARED_LIBRARY}
|
||||
set_target_properties(ssh
|
||||
PROPERTIES LINK_FLAGS
|
||||
"-Wl,--version-script,\"${MAP_PATH}\"")
|
||||
endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
|
||||
set_target_properties(
|
||||
${LIBSSH_SHARED_LIBRARY}
|
||||
set_target_properties(ssh
|
||||
PROPERTIES
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
SOVERSION
|
||||
${LIBRARY_SOVERSION}
|
||||
OUTPUT_NAME
|
||||
ssh
|
||||
DEFINE_SYMBOL
|
||||
LIBSSH_EXPORTS
|
||||
)
|
||||
|
||||
if (WITH_VISIBILITY_HIDDEN)
|
||||
set_target_properties(${LIBSSH_SHARED_LIBRARY} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
endif (WITH_VISIBILITY_HIDDEN)
|
||||
|
||||
if (MINGW)
|
||||
set_target_properties(${LIBSSH_SHARED_LIBRARY} PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup")
|
||||
set_target_properties(ssh PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup")
|
||||
endif ()
|
||||
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
${LIBSSH_SHARED_LIBRARY}
|
||||
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
COMPONENT libraries
|
||||
)
|
||||
install(TARGETS ssh
|
||||
EXPORT libssh-config
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT libraries)
|
||||
|
||||
install(EXPORT libssh-config
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
||||
|
||||
if (BUILD_STATIC_LIB)
|
||||
add_library(${LIBSSH_STATIC_LIBRARY} STATIC ${libssh_SRCS})
|
||||
target_compile_options(${LIBSSH_STATIC_LIBRARY}
|
||||
add_library(ssh-static STATIC ${libssh_SRCS})
|
||||
target_compile_options(ssh-static
|
||||
PRIVATE
|
||||
${DEFAULT_C_COMPILE_FLAGS}
|
||||
-D_GNU_SOURCE)
|
||||
|
||||
target_include_directories(ssh-static
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${libssh_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE ${LIBSSH_PRIVATE_INCLUDE_DIRS})
|
||||
target_link_libraries(ssh-static
|
||||
PUBLIC ${LIBSSH_LINK_LIBRARIES})
|
||||
add_library(ssh::static ALIAS ssh-static)
|
||||
|
||||
if (MSVC)
|
||||
set(OUTPUT_SUFFIX static)
|
||||
else (MSVC)
|
||||
set(OUTPUT_SUFFIX )
|
||||
endif (MSVC)
|
||||
set_target_properties(
|
||||
${LIBSSH_STATIC_LIBRARY}
|
||||
ssh-static
|
||||
PROPERTIES
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
@@ -390,21 +404,12 @@ if (BUILD_STATIC_LIB)
|
||||
|
||||
if (WIN32)
|
||||
set_target_properties(
|
||||
${LIBSSH_STATIC_LIBRARY}
|
||||
ssh-static
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-DLIBSSH_STATIC"
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
install(TARGETS
|
||||
${LIBSSH_STATIC_LIBRARY}
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
|
||||
COMPONENT
|
||||
libraries)
|
||||
endif (WITH_STATIC_LIB)
|
||||
endif (BUILD_STATIC_LIB)
|
||||
|
||||
message(STATUS "Threads_FOUND=${Threads_FOUND}")
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
32
src/auth.c
32
src/auth.c
@@ -25,6 +25,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
@@ -69,7 +70,7 @@ static int ssh_userauth_request_service(ssh_session session) {
|
||||
int rc;
|
||||
|
||||
rc = ssh_service_request(session, "ssh-userauth");
|
||||
if (rc != SSH_OK) {
|
||||
if ((rc != SSH_OK) && (rc != SSH_AGAIN)) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Failed to request \"ssh-userauth\" service");
|
||||
}
|
||||
@@ -204,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;
|
||||
}
|
||||
|
||||
@@ -557,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;
|
||||
@@ -575,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);
|
||||
|
||||
@@ -680,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);
|
||||
@@ -692,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;
|
||||
@@ -714,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);
|
||||
|
||||
@@ -840,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);
|
||||
}
|
||||
@@ -918,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);
|
||||
@@ -934,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);
|
||||
@@ -1030,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) {
|
||||
@@ -1329,7 +1333,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;
|
||||
@@ -1365,7 +1369,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;
|
||||
@@ -1554,7 +1558,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");
|
||||
@@ -1778,7 +1782,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;
|
||||
}
|
||||
|
||||
15
src/bignum.c
15
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 */
|
||||
|
||||
@@ -77,7 +80,7 @@ bignum ssh_make_string_bn(ssh_string string)
|
||||
}
|
||||
|
||||
/* prints the bignum on stderr */
|
||||
void ssh_print_bignum(const char *name, const bignum num)
|
||||
void ssh_print_bignum(const char *name, const_bignum num)
|
||||
{
|
||||
unsigned char *hex = NULL;
|
||||
if (num != NULL) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
27
src/buffer.c
27
src/buffer.c
@@ -1119,6 +1119,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = SSH_ERROR;
|
||||
switch (*p) {
|
||||
case 'b':
|
||||
o.byte = va_arg(ap, uint8_t *);
|
||||
@@ -1128,27 +1129,32 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
case 'w':
|
||||
o.word = va_arg(ap, uint16_t *);
|
||||
rlen = ssh_buffer_get_data(buffer, o.word, sizeof(uint16_t));
|
||||
*o.word = ntohs(*o.word);
|
||||
rc = rlen==2 ? SSH_OK : SSH_ERROR;
|
||||
if (rlen == 2) {
|
||||
*o.word = ntohs(*o.word);
|
||||
rc = SSH_OK;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
o.dword = va_arg(ap, uint32_t *);
|
||||
rlen = ssh_buffer_get_u32(buffer, o.dword);
|
||||
*o.dword = ntohl(*o.dword);
|
||||
rc = rlen==4 ? SSH_OK : SSH_ERROR;
|
||||
if (rlen == 4) {
|
||||
*o.dword = ntohl(*o.dword);
|
||||
rc = SSH_OK;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
o.qword = va_arg(ap, uint64_t*);
|
||||
rlen = ssh_buffer_get_u64(buffer, o.qword);
|
||||
*o.qword = ntohll(*o.qword);
|
||||
rc = rlen==8 ? SSH_OK : SSH_ERROR;
|
||||
if (rlen == 8) {
|
||||
*o.qword = ntohll(*o.qword);
|
||||
rc = SSH_OK;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
o.bignum = va_arg(ap, bignum *);
|
||||
*o.bignum = NULL;
|
||||
tmp_string = ssh_buffer_get_ssh_string(buffer);
|
||||
if (tmp_string == NULL) {
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
*o.bignum = ssh_make_string_bn(tmp_string);
|
||||
@@ -1167,14 +1173,12 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
|
||||
o.cstring = va_arg(ap, char **);
|
||||
*o.cstring = NULL;
|
||||
rc = ssh_buffer_get_u32(buffer, &u32len);
|
||||
if (rc != 4){
|
||||
rc = SSH_ERROR;
|
||||
rlen = ssh_buffer_get_u32(buffer, &u32len);
|
||||
if (rlen != 4){
|
||||
break;
|
||||
}
|
||||
len = ntohl(u32len);
|
||||
if (len > max_len - 1) {
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1230,7 +1234,6 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
if (rc != SSH_OK) {
|
||||
break;
|
||||
|
||||
@@ -109,11 +109,11 @@ static void chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
out_packet->payload,
|
||||
len - sizeof(uint32_t));
|
||||
|
||||
/* ssh_print_hexa("poly1305_ctx", poly1305_ctx, sizeof(poly1305_ctx)); */
|
||||
/* ssh_log_hexdump("poly1305_ctx", poly1305_ctx, sizeof(poly1305_ctx)); */
|
||||
/* step 4, compute the MAC */
|
||||
poly1305_auth(tag, (uint8_t *)out_packet, len, poly1305_ctx);
|
||||
/* ssh_print_hexa("poly1305 src", (uint8_t *)out_packet, len);
|
||||
ssh_print_hexa("poly1305 tag", tag, POLY1305_TAGLEN); */
|
||||
/* ssh_log_hexdump("poly1305 src", (uint8_t *)out_packet, len);
|
||||
ssh_log_hexdump("poly1305 tag", tag, POLY1305_TAGLEN); */
|
||||
}
|
||||
|
||||
static int chacha20_poly1305_aead_decrypt_length(
|
||||
@@ -159,17 +159,17 @@ static int chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
poly1305_ctx,
|
||||
POLY1305_KEYLEN);
|
||||
#if 0
|
||||
ssh_print_hexa("poly1305_ctx", poly1305_ctx, sizeof(poly1305_ctx));
|
||||
ssh_log_hexdump("poly1305_ctx", poly1305_ctx, sizeof(poly1305_ctx));
|
||||
#endif
|
||||
|
||||
poly1305_auth(tag, (uint8_t *)complete_packet, encrypted_size +
|
||||
sizeof(uint32_t), poly1305_ctx);
|
||||
#if 0
|
||||
ssh_print_hexa("poly1305 src",
|
||||
ssh_log_hexdump("poly1305 src",
|
||||
(uint8_t*)complete_packet,
|
||||
encrypted_size + 4);
|
||||
ssh_print_hexa("poly1305 tag", tag, POLY1305_TAGLEN);
|
||||
ssh_print_hexa("received tag", mac, POLY1305_TAGLEN);
|
||||
ssh_log_hexdump("poly1305 tag", tag, POLY1305_TAGLEN);
|
||||
ssh_log_hexdump("received tag", mac, POLY1305_TAGLEN);
|
||||
#endif
|
||||
|
||||
cmp = memcmp(tag, mac, POLY1305_TAGLEN);
|
||||
|
||||
358
src/channels.c
358
src/channels.c
@@ -106,7 +106,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;
|
||||
}
|
||||
@@ -121,6 +121,10 @@ ssh_channel ssh_channel_new(ssh_session session)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -277,74 +281,89 @@ static int ssh_channel_open_termination(void *c){
|
||||
*
|
||||
* @return SSH_OK if successful; SSH_ERROR otherwise.
|
||||
*/
|
||||
static int channel_open(ssh_channel channel, const char *type, int window,
|
||||
int maxpacket, ssh_buffer payload) {
|
||||
ssh_session session = channel->session;
|
||||
int err=SSH_ERROR;
|
||||
int rc;
|
||||
static int
|
||||
channel_open(ssh_channel channel,
|
||||
const char *type,
|
||||
uint32_t window,
|
||||
uint32_t maxpacket,
|
||||
ssh_buffer payload)
|
||||
{
|
||||
ssh_session session = channel->session;
|
||||
int err = SSH_ERROR;
|
||||
int rc;
|
||||
|
||||
switch(channel->state){
|
||||
case SSH_CHANNEL_STATE_NOT_OPEN:
|
||||
break;
|
||||
case SSH_CHANNEL_STATE_OPENING:
|
||||
goto pending;
|
||||
case SSH_CHANNEL_STATE_OPEN:
|
||||
case SSH_CHANNEL_STATE_CLOSED:
|
||||
case SSH_CHANNEL_STATE_OPEN_DENIED:
|
||||
goto end;
|
||||
default:
|
||||
ssh_set_error(session,SSH_FATAL,"Bad state in channel_open: %d",channel->state);
|
||||
}
|
||||
channel->local_channel = ssh_channel_new_id(session);
|
||||
channel->local_maxpacket = maxpacket;
|
||||
channel->local_window = window;
|
||||
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"Creating a channel %d with %d window and %d max packet",
|
||||
channel->local_channel, window, maxpacket);
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bsddd",
|
||||
SSH2_MSG_CHANNEL_OPEN,
|
||||
type,
|
||||
channel->local_channel,
|
||||
channel->local_window,
|
||||
channel->local_maxpacket);
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error_oom(session);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (payload != NULL) {
|
||||
if (ssh_buffer_add_buffer(session->out_buffer, payload) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
|
||||
return err;
|
||||
switch (channel->state) {
|
||||
case SSH_CHANNEL_STATE_NOT_OPEN:
|
||||
break;
|
||||
case SSH_CHANNEL_STATE_OPENING:
|
||||
goto pending;
|
||||
case SSH_CHANNEL_STATE_OPEN:
|
||||
case SSH_CHANNEL_STATE_CLOSED:
|
||||
case SSH_CHANNEL_STATE_OPEN_DENIED:
|
||||
goto end;
|
||||
default:
|
||||
ssh_set_error(session, SSH_FATAL, "Bad state in channel_open: %d",
|
||||
channel->state);
|
||||
}
|
||||
|
||||
channel->local_channel = ssh_channel_new_id(session);
|
||||
channel->local_maxpacket = maxpacket;
|
||||
channel->local_window = window;
|
||||
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"Creating a channel %d with %d window and %d max packet",
|
||||
channel->local_channel, window, maxpacket);
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bsddd",
|
||||
SSH2_MSG_CHANNEL_OPEN,
|
||||
type,
|
||||
channel->local_channel,
|
||||
channel->local_window,
|
||||
channel->local_maxpacket);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (payload != NULL) {
|
||||
if (ssh_buffer_add_buffer(session->out_buffer, payload) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
channel->state = SSH_CHANNEL_STATE_OPENING;
|
||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
||||
return err;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %d",
|
||||
type, channel->local_channel);
|
||||
|
||||
pending:
|
||||
/* wait until channel is opened by server */
|
||||
err = ssh_handle_packets_termination(session,
|
||||
SSH_TIMEOUT_DEFAULT,
|
||||
ssh_channel_open_termination,
|
||||
channel);
|
||||
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR) {
|
||||
err = SSH_ERROR;
|
||||
}
|
||||
|
||||
end:
|
||||
/* This needs to pass the SSH_AGAIN from the above,
|
||||
* but needs to catch failed channel states */
|
||||
if (channel->state == SSH_CHANNEL_STATE_OPEN) {
|
||||
err = SSH_OK;
|
||||
} else if (err != SSH_AGAIN) {
|
||||
/* Messages were handled correctly, but he channel state is invalid */
|
||||
err = SSH_ERROR;
|
||||
}
|
||||
}
|
||||
channel->state = SSH_CHANNEL_STATE_OPENING;
|
||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %d",
|
||||
type, channel->local_channel);
|
||||
pending:
|
||||
/* wait until channel is opened by server */
|
||||
err = ssh_handle_packets_termination(session,
|
||||
SSH_TIMEOUT_DEFAULT,
|
||||
ssh_channel_open_termination,
|
||||
channel);
|
||||
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR)
|
||||
err = SSH_ERROR;
|
||||
end:
|
||||
if(channel->state == SSH_CHANNEL_STATE_OPEN)
|
||||
err=SSH_OK;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* return channel with corresponding local id, or NULL if not found */
|
||||
@@ -373,7 +392,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;
|
||||
|
||||
@@ -538,7 +560,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;
|
||||
}
|
||||
@@ -554,7 +576,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;
|
||||
@@ -822,8 +844,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) {
|
||||
@@ -838,8 +862,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();
|
||||
@@ -851,7 +877,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;
|
||||
}
|
||||
@@ -867,7 +893,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;
|
||||
}
|
||||
@@ -998,8 +1024,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;
|
||||
}
|
||||
@@ -1081,8 +1107,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;
|
||||
}
|
||||
@@ -1815,7 +1841,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;
|
||||
}
|
||||
@@ -1875,7 +1901,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;
|
||||
}
|
||||
@@ -1944,11 +1970,23 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request sftp subsystem on the channel
|
||||
*
|
||||
* @param[in] channel The channel to request the sftp subsystem.
|
||||
*
|
||||
* @return SSH_OK on success,
|
||||
* SSH_ERROR if an error occurred,
|
||||
* SSH_AGAIN if in nonblocking mode and call has
|
||||
* to be done again.
|
||||
*
|
||||
* @note You should use sftp_new() which does this for you.
|
||||
*/
|
||||
int ssh_channel_request_sftp( ssh_channel channel){
|
||||
if(channel == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -2048,7 +2086,7 @@ pending:
|
||||
rc = channel_request(channel, "x11-req", buffer, 1);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2361,7 +2399,7 @@ pending:
|
||||
}
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2433,7 +2471,7 @@ pending:
|
||||
rc = ssh_global_request(session, "cancel-tcpip-forward", buffer, 1);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2491,7 +2529,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;
|
||||
}
|
||||
@@ -2513,12 +2551,12 @@ error:
|
||||
*
|
||||
* Example:
|
||||
@code
|
||||
rc = channel_request_exec(channel, "ps aux");
|
||||
rc = ssh_channel_request_exec(channel, "ps aux");
|
||||
if (rc > 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((rc = channel_read(channel, buffer, sizeof(buffer), 0)) > 0) {
|
||||
while ((rc = ssh_channel_read(channel, buffer, sizeof(buffer), 0)) > 0) {
|
||||
if (fwrite(buffer, 1, rc, stdout) != (unsigned int) rc) {
|
||||
return -1;
|
||||
}
|
||||
@@ -2560,7 +2598,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;
|
||||
}
|
||||
|
||||
@@ -2623,7 +2661,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;
|
||||
}
|
||||
|
||||
@@ -2666,7 +2704,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;
|
||||
}
|
||||
|
||||
@@ -2942,42 +2980,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3046,38 +3087,46 @@ 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;
|
||||
}
|
||||
len = ssh_buffer_get_len(stdbuf);
|
||||
if (len > 0) {
|
||||
goto out;
|
||||
}
|
||||
if (channel->remote_eof) {
|
||||
rc = SSH_EOF;
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3196,8 +3245,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++)
|
||||
;
|
||||
|
||||
@@ -3451,7 +3501,7 @@ pending:
|
||||
payload);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(payload);
|
||||
SSH_BUFFER_FREE(payload);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -3513,7 +3563,7 @@ pending:
|
||||
payload);
|
||||
|
||||
error:
|
||||
ssh_buffer_free(payload);
|
||||
SSH_BUFFER_FREE(payload);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -3554,7 +3604,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;
|
||||
}
|
||||
|
||||
@@ -3609,7 +3659,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;
|
||||
}
|
||||
|
||||
|
||||
34
src/config.c
34
src/config.c
@@ -274,10 +274,8 @@ static int
|
||||
ssh_config_match(char *value, const char *pattern, bool negate)
|
||||
{
|
||||
int ok, result = 0;
|
||||
char *lowervalue;
|
||||
|
||||
lowervalue = (value) ? ssh_lowercase(value) : NULL;
|
||||
ok = match_pattern_list(lowervalue, pattern, strlen(pattern), 0);
|
||||
ok = match_pattern_list(value, pattern, strlen(pattern), 0);
|
||||
if (ok <= 0 && negate == true) {
|
||||
result = 1;
|
||||
} else if (ok > 0 && negate == false) {
|
||||
@@ -286,7 +284,6 @@ ssh_config_match(char *value, const char *pattern, bool negate)
|
||||
SSH_LOG(SSH_LOG_TRACE, "%s '%s' against pattern '%s'%s (ok=%d)",
|
||||
result == 1 ? "Matched" : "Not matched", value, pattern,
|
||||
negate == true ? " (negated)" : "", ok);
|
||||
SAFE_FREE(lowervalue);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -397,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);
|
||||
@@ -450,6 +452,7 @@ ssh_config_parse_line(ssh_session session,
|
||||
int result = 1;
|
||||
size_t args = 0;
|
||||
enum ssh_config_match_e opt;
|
||||
char *localuser = NULL;
|
||||
|
||||
*parsing = 0;
|
||||
do {
|
||||
@@ -515,8 +518,29 @@ ssh_config_parse_line(ssh_session session,
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case MATCH_ORIGINALHOST:
|
||||
case MATCH_LOCALUSER:
|
||||
/* Here we match only one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL || p[0] == '\0') {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"line %d: ERROR - Match user keyword "
|
||||
"requires argument", count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
localuser = ssh_get_local_username();
|
||||
if (localuser == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARN, "line %d: Can not get local username "
|
||||
"for conditional matching.", count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
result &= ssh_config_match(localuser, p, negate);
|
||||
SAFE_FREE(localuser);
|
||||
args++;
|
||||
break;
|
||||
|
||||
case MATCH_ORIGINALHOST:
|
||||
/* Skip one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL || p[0] == '\0') {
|
||||
|
||||
538
src/connect.c
538
src/connect.c
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -90,131 +91,55 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef gai_strerror
|
||||
char WSAAPI *gai_strerrorA(int code) {
|
||||
static char buf[256];
|
||||
char WSAAPI *gai_strerrorA(int code)
|
||||
{
|
||||
static char buf[256];
|
||||
|
||||
snprintf(buf, sizeof(buf), "Undetermined error code (%d)", code);
|
||||
snprintf(buf, sizeof(buf), "Undetermined error code (%d)", code);
|
||||
|
||||
return buf;
|
||||
return buf;
|
||||
}
|
||||
#endif /* gai_strerror */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
static int ssh_connect_socket_close(socket_t s){
|
||||
static int ssh_connect_socket_close(socket_t s)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return closesocket(s);
|
||||
return closesocket(s);
|
||||
#else
|
||||
return close(s);
|
||||
return close(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int getai(const char *host, int port, struct addrinfo **ai)
|
||||
{
|
||||
const char *service = NULL;
|
||||
struct addrinfo hints;
|
||||
char s_port[10];
|
||||
|
||||
static int getai(const char *host, int port, struct addrinfo **ai) {
|
||||
const char *service = NULL;
|
||||
struct addrinfo hints;
|
||||
char s_port[10];
|
||||
ZERO_STRUCT(hints);
|
||||
|
||||
ZERO_STRUCT(hints);
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (port == 0) {
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
} else {
|
||||
snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port);
|
||||
service = s_port;
|
||||
if (port == 0) {
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
} else {
|
||||
snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port);
|
||||
service = s_port;
|
||||
#ifdef AI_NUMERICSERV
|
||||
hints.ai_flags=AI_NUMERICSERV;
|
||||
hints.ai_flags = AI_NUMERICSERV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_is_ipaddr(host)) {
|
||||
/* this is an IP address */
|
||||
SSH_LOG(SSH_LOG_PACKET,"host %s matches an IP address",host);
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
}
|
||||
if (ssh_is_ipaddr(host)) {
|
||||
/* this is an IP address */
|
||||
SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host);
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
}
|
||||
|
||||
return getaddrinfo(host, service, &hints, ai);
|
||||
}
|
||||
|
||||
static int ssh_connect_ai_timeout(ssh_session session, const char *host,
|
||||
int port, struct addrinfo *ai, long timeout, long usec, socket_t s) {
|
||||
int timeout_ms;
|
||||
ssh_pollfd_t fds;
|
||||
int rc = 0;
|
||||
int ret;
|
||||
socklen_t len = sizeof(rc);
|
||||
|
||||
/* I know we're losing some precision. But it's not like poll-like family
|
||||
* type of mechanisms are precise up to the microsecond.
|
||||
*/
|
||||
timeout_ms=timeout * 1000 + usec / 1000;
|
||||
|
||||
rc = ssh_socket_set_nonblocking(s);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to set socket non-blocking for %s:%d", host, port);
|
||||
ssh_connect_socket_close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_RARE, "Trying to connect to host: %s:%d with "
|
||||
"timeout %d ms", host, port, timeout_ms);
|
||||
|
||||
/* The return value is checked later */
|
||||
connect(s, ai->ai_addr, ai->ai_addrlen);
|
||||
freeaddrinfo(ai);
|
||||
|
||||
fds.fd=s;
|
||||
fds.revents=0;
|
||||
fds.events=POLLOUT;
|
||||
#ifdef _WIN32
|
||||
fds.events |= POLLWRNORM;
|
||||
#endif
|
||||
rc = ssh_poll(&fds,1,timeout_ms);
|
||||
|
||||
if (rc == 0) {
|
||||
/* timeout */
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Timeout while connecting to %s:%d", host, port);
|
||||
ssh_connect_socket_close(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"poll error: %s", strerror(errno));
|
||||
ssh_connect_socket_close(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
rc = -1;
|
||||
|
||||
/* Get connect(2) return code. Zero means no error */
|
||||
ret = getsockopt(s, SOL_SOCKET, SO_ERROR,(char *) &rc, &len);
|
||||
if (ret < 0 || rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Connect to %s:%d failed: %s", host, port, strerror(rc));
|
||||
ssh_connect_socket_close(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* s is connected ? */
|
||||
SSH_LOG(SSH_LOG_PACKET, "Socket connected with timeout");
|
||||
ret = ssh_socket_set_blocking(s);
|
||||
if (ret < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to set socket as blocking connecting to %s:%d failed: %s",
|
||||
host, port, strerror(errno));
|
||||
ssh_connect_socket_close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
return getaddrinfo(host, service, &hints, ai);
|
||||
}
|
||||
|
||||
static int set_tcp_nodelay(socket_t socket)
|
||||
@@ -228,99 +153,6 @@ static int set_tcp_nodelay(socket_t socket)
|
||||
sizeof(opt));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Connect to an IPv4 or IPv6 host specified by its IP address or
|
||||
* hostname.
|
||||
*
|
||||
* @returns A file descriptor, < 0 on error.
|
||||
*/
|
||||
socket_t ssh_connect_host(ssh_session session, const char *host,
|
||||
const char *bind_addr, int port, long timeout, long usec) {
|
||||
socket_t s = -1;
|
||||
int rc;
|
||||
struct addrinfo *ai;
|
||||
struct addrinfo *itr;
|
||||
|
||||
rc = getai(host, port, &ai);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to resolve hostname %s (%s)", host, gai_strerror(rc));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (itr = ai; itr != NULL; itr = itr->ai_next){
|
||||
/* create socket */
|
||||
s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
|
||||
if (s < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Socket create failed: %s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bind_addr) {
|
||||
struct addrinfo *bind_ai;
|
||||
struct addrinfo *bind_itr;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr);
|
||||
|
||||
rc = getai(bind_addr, 0, &bind_ai);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to resolve bind address %s (%s)",
|
||||
bind_addr,
|
||||
gai_strerror(rc));
|
||||
freeaddrinfo(ai);
|
||||
close(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (bind_itr = bind_ai; bind_itr != NULL; bind_itr = bind_itr->ai_next) {
|
||||
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Binding local address: %s", strerror(errno));
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(bind_ai);
|
||||
|
||||
/* Cannot bind to any local addresses */
|
||||
if (bind_itr == NULL) {
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout || usec) {
|
||||
socket_t ret = ssh_connect_ai_timeout(session, host, port, itr,
|
||||
timeout, usec, s);
|
||||
|
||||
freeaddrinfo(ai);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (connect(s, itr->ai_addr, itr->ai_addrlen) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Connect failed: %s", strerror(errno));
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
} else {
|
||||
/* We are connected */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
@@ -331,102 +163,109 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
|
||||
* @warning very ugly !!!
|
||||
*/
|
||||
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
const char *bind_addr, int port) {
|
||||
socket_t s = -1;
|
||||
int rc;
|
||||
struct addrinfo *ai;
|
||||
struct addrinfo *itr;
|
||||
const char *bind_addr, int port)
|
||||
{
|
||||
socket_t s = -1;
|
||||
int rc;
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo *itr = NULL;
|
||||
|
||||
rc = getai(host, port, &ai);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to resolve hostname %s (%s)", host, gai_strerror(rc));
|
||||
rc = getai(host, port, &ai);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to resolve hostname %s (%s)",
|
||||
host, gai_strerror(rc));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (itr = ai; itr != NULL; itr = itr->ai_next){
|
||||
/* create socket */
|
||||
s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
|
||||
if (s < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Socket create failed: %s", strerror(errno));
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bind_addr) {
|
||||
struct addrinfo *bind_ai;
|
||||
struct addrinfo *bind_itr;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr);
|
||||
|
||||
rc = getai(bind_addr, 0, &bind_ai);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to resolve bind address %s (%s)",
|
||||
bind_addr,
|
||||
gai_strerror(rc));
|
||||
ssh_connect_socket_close(s);
|
||||
s=-1;
|
||||
break;
|
||||
}
|
||||
|
||||
for (bind_itr = bind_ai; bind_itr != NULL; bind_itr = bind_itr->ai_next) {
|
||||
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Binding local address: %s", strerror(errno));
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
for (itr = ai; itr != NULL; itr = itr->ai_next) {
|
||||
/* create socket */
|
||||
s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
|
||||
if (s < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Socket create failed: %s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(bind_ai);
|
||||
|
||||
/* Cannot bind to any local addresses */
|
||||
if (bind_itr == NULL) {
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (bind_addr) {
|
||||
struct addrinfo *bind_ai;
|
||||
struct addrinfo *bind_itr;
|
||||
|
||||
rc = ssh_socket_set_nonblocking(s);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to set socket non-blocking for %s:%d", host, port);
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr);
|
||||
|
||||
if (session->opts.nodelay) {
|
||||
/* For winsock, socket options are only effective before connect */
|
||||
rc = set_tcp_nodelay(s);
|
||||
rc = getai(bind_addr, 0, &bind_ai);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to resolve bind address %s (%s)",
|
||||
bind_addr,
|
||||
gai_strerror(rc));
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
for (bind_itr = bind_ai;
|
||||
bind_itr != NULL;
|
||||
bind_itr = bind_itr->ai_next)
|
||||
{
|
||||
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Binding local address: %s", strerror(errno));
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(bind_ai);
|
||||
|
||||
/* Cannot bind to any local addresses */
|
||||
if (bind_itr == NULL) {
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_socket_set_nonblocking(s);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to set TCP_NODELAY on socket: %s", strerror(errno));
|
||||
"Failed to set socket non-blocking for %s:%d",
|
||||
host, port);
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (session->opts.nodelay) {
|
||||
/* For winsock, socket options are only effective before connect */
|
||||
rc = set_tcp_nodelay(s);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to set TCP_NODELAY on socket: %s",
|
||||
strerror(errno));
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
|
||||
if (rc == -1 && (errno != 0) && (errno != EINPROGRESS)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to connect: %s", strerror(errno));
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
|
||||
if (rc == -1 && (errno != 0) && (errno != EINPROGRESS)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to connect: %s", strerror(errno));
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
freeaddrinfo(ai);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,11 +274,13 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int ssh_select_cb (socket_t fd, int revents, void *userdata){
|
||||
fd_set *set = (fd_set *)userdata;
|
||||
if(revents & POLLIN)
|
||||
FD_SET(fd, set);
|
||||
return 0;
|
||||
static int ssh_select_cb (socket_t fd, int revents, void *userdata)
|
||||
{
|
||||
fd_set *set = (fd_set *)userdata;
|
||||
if (revents & POLLIN) {
|
||||
FD_SET(fd, set);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -473,73 +314,84 @@ static int ssh_select_cb (socket_t fd, int revents, void *userdata){
|
||||
* @see select(2)
|
||||
*/
|
||||
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
||||
fd_set *readfds, struct timeval *timeout) {
|
||||
fd_set origfds;
|
||||
socket_t fd;
|
||||
size_t i, j;
|
||||
int rc;
|
||||
int base_tm, tm;
|
||||
struct ssh_timestamp ts;
|
||||
ssh_event event = ssh_event_new();
|
||||
int firstround=1;
|
||||
fd_set *readfds, struct timeval *timeout)
|
||||
{
|
||||
fd_set origfds;
|
||||
socket_t fd;
|
||||
size_t i, j;
|
||||
int rc;
|
||||
int base_tm, tm;
|
||||
struct ssh_timestamp ts;
|
||||
ssh_event event = ssh_event_new();
|
||||
int firstround = 1;
|
||||
|
||||
base_tm = tm=timeout->tv_sec * 1000 + timeout->tv_usec/1000;
|
||||
for (i=0 ; channels[i] != NULL; ++i){
|
||||
ssh_event_add_session(event, channels[i]->session);
|
||||
}
|
||||
|
||||
ZERO_STRUCT(origfds);
|
||||
FD_ZERO(&origfds);
|
||||
for (fd = 0; fd < maxfd ; fd++) {
|
||||
if (FD_ISSET(fd, readfds)) {
|
||||
ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
|
||||
FD_SET(fd, &origfds);
|
||||
}
|
||||
}
|
||||
outchannels[0] = NULL;
|
||||
FD_ZERO(readfds);
|
||||
ssh_timestamp_init(&ts);
|
||||
do {
|
||||
/* Poll every channel */
|
||||
j = 0;
|
||||
for (i = 0; channels[i]; i++) {
|
||||
if(ssh_channel_poll(channels[i], 0) != 0) {
|
||||
outchannels[j] = channels[i];
|
||||
j++;
|
||||
} else if(ssh_channel_poll(channels[i], 1) != 0) {
|
||||
outchannels[j] = channels[i];
|
||||
j++;
|
||||
}
|
||||
base_tm = tm = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
|
||||
for (i = 0 ; channels[i] != NULL; ++i) {
|
||||
ssh_event_add_session(event, channels[i]->session);
|
||||
}
|
||||
outchannels[j] = NULL;
|
||||
if(j != 0)
|
||||
break;
|
||||
/* watch if a user socket was triggered */
|
||||
for (fd = 0; fd < maxfd; fd++) {
|
||||
|
||||
ZERO_STRUCT(origfds);
|
||||
FD_ZERO(&origfds);
|
||||
for (fd = 0; fd < maxfd ; fd++) {
|
||||
if (FD_ISSET(fd, readfds)) {
|
||||
goto out;
|
||||
ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
|
||||
FD_SET(fd, &origfds);
|
||||
}
|
||||
}
|
||||
outchannels[0] = NULL;
|
||||
FD_ZERO(readfds);
|
||||
ssh_timestamp_init(&ts);
|
||||
do {
|
||||
/* Poll every channel */
|
||||
j = 0;
|
||||
for (i = 0; channels[i]; i++) {
|
||||
rc = ssh_channel_poll(channels[i], 0);
|
||||
if (rc != 0) {
|
||||
outchannels[j] = channels[i];
|
||||
j++;
|
||||
} else {
|
||||
rc = ssh_channel_poll(channels[i], 1);
|
||||
if (rc != 0) {
|
||||
outchannels[j] = channels[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the timeout is elapsed, we should go out */
|
||||
if(!firstround && ssh_timeout_elapsed(&ts, base_tm))
|
||||
goto out;
|
||||
/* since there's nothing, let's fire the polling */
|
||||
rc = ssh_event_dopoll(event,tm);
|
||||
if (rc == SSH_ERROR){
|
||||
goto out;
|
||||
}
|
||||
tm = ssh_timeout_update(&ts, base_tm);
|
||||
firstround=0;
|
||||
} while (1);
|
||||
outchannels[j] = NULL;
|
||||
if (j != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* watch if a user socket was triggered */
|
||||
for (fd = 0; fd < maxfd; fd++) {
|
||||
if (FD_ISSET(fd, readfds)) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the timeout is elapsed, we should go out */
|
||||
if (!firstround && ssh_timeout_elapsed(&ts, base_tm)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* since there's nothing, let's fire the polling */
|
||||
rc = ssh_event_dopoll(event,tm);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
tm = ssh_timeout_update(&ts, base_tm);
|
||||
firstround = 0;
|
||||
} while (1);
|
||||
out:
|
||||
for (fd = 0; fd < maxfd; fd++) {
|
||||
if (FD_ISSET(fd, &origfds)) {
|
||||
ssh_event_remove_fd(event, fd);
|
||||
for (fd = 0; fd < maxfd; fd++) {
|
||||
if (FD_ISSET(fd, &origfds)) {
|
||||
ssh_event_remove_fd(event, fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
ssh_event_free(event);
|
||||
return SSH_OK;
|
||||
ssh_event_free(event);
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
276
src/curve25519.c
276
src/curve25519.c
@@ -39,6 +39,10 @@
|
||||
#include "libssh/pki.h"
|
||||
#include "libssh/bignum.h"
|
||||
|
||||
#ifdef HAVE_OPENSSL_X25519
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply);
|
||||
|
||||
static ssh_packet_callback dh_client_callbacks[] = {
|
||||
@@ -52,58 +56,221 @@ static struct ssh_packet_callbacks_struct ssh_curve25519_client_callbacks = {
|
||||
.user = NULL
|
||||
};
|
||||
|
||||
static int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
#ifdef HAVE_OPENSSL_X25519
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t pubkey_len = CURVE25519_PUBKEY_SIZE;
|
||||
size_t pkey_len = CURVE25519_PRIVKEY_SIZE;
|
||||
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_keygen_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 keygen: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_keygen(pctx, &pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate X25519 keys: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
rc = EVP_PKEY_get_raw_public_key(pkey,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
&pubkey_len);
|
||||
} else {
|
||||
rc = EVP_PKEY_get_raw_public_key(pkey,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
&pubkey_len);
|
||||
}
|
||||
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get X25519 raw public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_get_raw_private_key(pkey,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
&pkey_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get X25519 raw private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
EVP_PKEY_free(pkey);
|
||||
#else
|
||||
rc = ssh_get_random(session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE, 1);
|
||||
if (rc != 1) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
} else {
|
||||
crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
}
|
||||
#endif /* HAVE_OPENSSL_X25519 */
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief Starts curve25519-sha256@libssh.org / curve25519-sha256 key exchange
|
||||
*/
|
||||
int ssh_client_curve25519_init(ssh_session session){
|
||||
int rc;
|
||||
int ok;
|
||||
int ssh_client_curve25519_init(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
ok = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
|
||||
if (!ok) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rc = ssh_curve25519_init(session);
|
||||
if (rc != SSH_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bdP",
|
||||
SSH2_MSG_KEX_ECDH_INIT,
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE,
|
||||
session->next_crypto->curve25519_client_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bdP",
|
||||
SSH2_MSG_KEX_ECDH_INIT,
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
/* register the packet callbacks */
|
||||
ssh_packet_set_callbacks(session, &ssh_curve25519_client_callbacks);
|
||||
session->dh_handshake_state = DH_STATE_INIT_SENT;
|
||||
rc = ssh_packet_send(session);
|
||||
/* register the packet callbacks */
|
||||
ssh_packet_set_callbacks(session, &ssh_curve25519_client_callbacks);
|
||||
session->dh_handshake_state = DH_STATE_INIT_SENT;
|
||||
rc = ssh_packet_send(session);
|
||||
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ssh_curve25519_build_k(ssh_session session) {
|
||||
ssh_curve25519_pubkey k;
|
||||
static int ssh_curve25519_build_k(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey k;
|
||||
|
||||
if (session->server)
|
||||
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||
session->next_crypto->curve25519_client_pubkey);
|
||||
else
|
||||
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||
session->next_crypto->curve25519_server_pubkey);
|
||||
#ifdef HAVE_OPENSSL_X25519
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
||||
size_t shared_key_len;
|
||||
int rc;
|
||||
|
||||
bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, &session->next_crypto->shared_secret);
|
||||
if (session->next_crypto->shared_secret == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE);
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 key derivation: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
} else {
|
||||
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
}
|
||||
if (pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 public key EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to set peer X25519 public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_free(pubkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#else
|
||||
if (session->server) {
|
||||
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||
session->next_crypto->curve25519_client_pubkey);
|
||||
} else {
|
||||
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||
session->next_crypto->curve25519_server_pubkey);
|
||||
}
|
||||
#endif /* HAVE_OPENSSL_X25519 */
|
||||
|
||||
bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, &session->next_crypto->shared_secret);
|
||||
if (session->next_crypto->shared_secret == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Session server cookie",
|
||||
ssh_log_hexdump("Session server cookie",
|
||||
session->next_crypto->server_kex.cookie, 16);
|
||||
ssh_print_hexa("Session client cookie",
|
||||
ssh_log_hexdump("Session client cookie",
|
||||
session->next_crypto->client_kex.cookie, 16);
|
||||
ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret);
|
||||
#endif
|
||||
@@ -132,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,
|
||||
@@ -148,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) {
|
||||
@@ -221,8 +388,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
|
||||
/* SSH host keys (rsa,dsa,ecdsa) */
|
||||
ssh_key privkey;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
int ok;
|
||||
int rc;
|
||||
(void)type;
|
||||
(void)user;
|
||||
@@ -240,24 +407,21 @@ 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);
|
||||
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_data(q_c_string), CURVE25519_PUBKEY_SIZE);
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
/* Build server's keypair */
|
||||
|
||||
ok = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
|
||||
if (!ok) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
rc = ssh_curve25519_init(session);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to generate curve25519 keys");
|
||||
goto error;
|
||||
}
|
||||
|
||||
crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
|
||||
rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_REPLY);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
@@ -272,7 +436,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
}
|
||||
|
||||
/* privkey is not allocated */
|
||||
rc = ssh_get_key_params(session, &privkey);
|
||||
rc = ssh_get_key_params(session, &privkey, &digest);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
@@ -292,7 +456,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;
|
||||
@@ -309,20 +473,20 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
|
||||
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;
|
||||
}
|
||||
/* add signature blob */
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
|
||||
if (sig_blob == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||
goto error;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
26
src/dh-gex.c
26
src/dh-gex.c
@@ -107,7 +107,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group)
|
||||
int blen;
|
||||
bignum pmin1 = NULL, one = NULL;
|
||||
bignum_CTX ctx = bignum_ctx_new();
|
||||
bignum modulus, generator;
|
||||
bignum modulus = NULL, generator = NULL;
|
||||
const_bignum pubkey;
|
||||
(void) type;
|
||||
(void) user;
|
||||
@@ -179,14 +179,18 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group)
|
||||
bignum_ctx_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
/* all checks passed, set parameters */
|
||||
/* all checks passed, set parameters (the BNs are copied in openssl backend) */
|
||||
rc = ssh_dh_set_parameters(session->next_crypto->dh_ctx,
|
||||
modulus, generator);
|
||||
if (rc != SSH_OK) {
|
||||
bignum_safe_free(modulus);
|
||||
bignum_safe_free(generator);
|
||||
goto error;
|
||||
}
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
bignum_safe_free(modulus);
|
||||
bignum_safe_free(generator);
|
||||
#endif
|
||||
modulus = NULL;
|
||||
generator = NULL;
|
||||
|
||||
/* compute and send DH public parameter */
|
||||
rc = ssh_dh_keypair_gen_keys(session->next_crypto->dh_ctx,
|
||||
@@ -194,8 +198,13 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group)
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
|
||||
DH_CLIENT_KEYPAIR, NULL, &pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bB",
|
||||
SSH2_MSG_KEX_DH_GEX_INIT,
|
||||
@@ -216,6 +225,8 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group)
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
bignum_safe_free(modulus);
|
||||
bignum_safe_free(generator);
|
||||
bignum_safe_free(one);
|
||||
bignum_safe_free(pmin1);
|
||||
if(!bignum_ctx_invalid(ctx)) {
|
||||
@@ -254,7 +265,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_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;
|
||||
}
|
||||
@@ -262,6 +273,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
|
||||
rc = ssh_dh_compute_shared_secret(session->next_crypto->dh_ctx,
|
||||
DH_CLIENT_KEYPAIR, DH_SERVER_KEYPAIR,
|
||||
&session->next_crypto->shared_secret);
|
||||
ssh_dh_debug_crypto(session->next_crypto);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not generate shared secret");
|
||||
goto error;
|
||||
@@ -636,8 +648,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_dhgex_request)
|
||||
generator);
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
bignum_safe_free(generator);
|
||||
bignum_safe_free(modulus);
|
||||
bignum_safe_free(generator);
|
||||
bignum_safe_free(modulus);
|
||||
#endif
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
|
||||
32
src/dh.c
32
src/dh.c
@@ -365,7 +365,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
||||
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;
|
||||
}
|
||||
@@ -373,6 +373,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
|
||||
rc = ssh_dh_compute_shared_secret(session->next_crypto->dh_ctx,
|
||||
DH_CLIENT_KEYPAIR, DH_SERVER_KEYPAIR,
|
||||
&session->next_crypto->shared_secret);
|
||||
ssh_dh_debug_crypto(session->next_crypto);
|
||||
if (rc == SSH_ERROR){
|
||||
ssh_set_error(session, SSH_FATAL, "Could not generate shared secret");
|
||||
goto error;
|
||||
@@ -430,6 +431,7 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||
ssh_key privkey = NULL;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
bignum client_pubkey;
|
||||
@@ -455,13 +457,14 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_get_key_params(session, &privkey);
|
||||
rc = ssh_get_key_params(session, &privkey, &digest);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_dh_compute_shared_secret(crypto->dh_ctx,
|
||||
DH_SERVER_KEYPAIR, DH_CLIENT_KEYPAIR,
|
||||
&crypto->shared_secret);
|
||||
ssh_dh_debug_crypto(crypto);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not generate shared secret");
|
||||
goto error;
|
||||
@@ -471,7 +474,7 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
|
||||
ssh_set_error(session, SSH_FATAL, "Could not create a session id");
|
||||
goto error;
|
||||
}
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
|
||||
if (sig_blob == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||
goto error;
|
||||
@@ -693,13 +696,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.
|
||||
*
|
||||
@@ -766,13 +772,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.
|
||||
*
|
||||
|
||||
@@ -41,6 +41,27 @@ struct dh_ctx {
|
||||
DH *keypair[2];
|
||||
};
|
||||
|
||||
void ssh_dh_debug_crypto(struct ssh_crypto_struct *c)
|
||||
{
|
||||
#ifdef DEBUG_CRYPTO
|
||||
const_bignum x = NULL, y = NULL, e = NULL, f = NULL;
|
||||
|
||||
ssh_dh_keypair_get_keys(c->dh_ctx, DH_CLIENT_KEYPAIR, &x, &e);
|
||||
ssh_dh_keypair_get_keys(c->dh_ctx, DH_SERVER_KEYPAIR, &y, &f);
|
||||
ssh_print_bignum("x", x);
|
||||
ssh_print_bignum("y", y);
|
||||
ssh_print_bignum("e", e);
|
||||
ssh_print_bignum("f", f);
|
||||
|
||||
ssh_log_hexdump("Session server cookie", c->server_kex.cookie, 16);
|
||||
ssh_log_hexdump("Session client cookie", c->client_kex.cookie, 16);
|
||||
ssh_print_bignum("k", c->shared_secret);
|
||||
|
||||
#else
|
||||
(void)c; /* UNUSED_PARAM */
|
||||
#endif
|
||||
}
|
||||
|
||||
int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer,
|
||||
const_bignum *priv, const_bignum *pub)
|
||||
{
|
||||
@@ -96,12 +117,14 @@ int ssh_dh_get_parameters(struct dh_ctx *ctx,
|
||||
int ssh_dh_set_parameters(struct dh_ctx *ctx,
|
||||
const bignum modulus, const bignum generator)
|
||||
{
|
||||
size_t i;
|
||||
int rc;
|
||||
|
||||
if ((ctx == NULL) || (modulus == NULL) || (generator == NULL)) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
bignum p = NULL;
|
||||
bignum g = NULL;
|
||||
|
||||
|
||||
47
src/dh_key.c
47
src/dh_key.c
@@ -60,6 +60,28 @@ struct dh_ctx {
|
||||
bignum modulus;
|
||||
};
|
||||
|
||||
void ssh_dh_debug_crypto(struct ssh_crypto_struct *c)
|
||||
{
|
||||
#ifdef DEBUG_CRYPTO
|
||||
const_bignum x = NULL, y = NULL, e = NULL, f = NULL;
|
||||
|
||||
ssh_dh_keypair_get_keys(c->dh_ctx, DH_CLIENT_KEYPAIR, &x, &e);
|
||||
ssh_dh_keypair_get_keys(c->dh_ctx, DH_SERVER_KEYPAIR, &y, &f);
|
||||
ssh_print_bignum("p", c->dh_ctx->modulus);
|
||||
ssh_print_bignum("g", c->dh_ctx->generator);
|
||||
ssh_print_bignum("x", x);
|
||||
ssh_print_bignum("y", y);
|
||||
ssh_print_bignum("e", e);
|
||||
ssh_print_bignum("f", f);
|
||||
|
||||
ssh_log_hexdump("Session server cookie", c->server_kex.cookie, 16);
|
||||
ssh_log_hexdump("Session client cookie", c->client_kex.cookie, 16);
|
||||
ssh_print_bignum("k", c->shared_secret);
|
||||
#else
|
||||
(void)c; /* UNUSED_PARAM */
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ssh_dh_free_modulus(struct dh_ctx *ctx)
|
||||
{
|
||||
if ((ctx->modulus != ssh_dh_group1) &&
|
||||
@@ -263,30 +285,6 @@ void ssh_dh_cleanup(struct ssh_crypto_struct *crypto)
|
||||
crypto->dh_ctx = NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
static void ssh_dh_debug(ssh_session session)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||
const_bignum x, y, e, f;
|
||||
ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR, &x, &e);
|
||||
ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR, &y, &f);
|
||||
ssh_print_bignum("p", crypto->dh_ctx->modulus);
|
||||
ssh_print_bignum("g", crypto->dh_ctx->generator);
|
||||
ssh_print_bignum("x", x);
|
||||
ssh_print_bignum("y", y);
|
||||
ssh_print_bignum("e", e);
|
||||
ssh_print_bignum("f", f);
|
||||
|
||||
ssh_print_hexa("Session server cookie",
|
||||
session->next_crypto->server_kex.cookie, 16);
|
||||
ssh_print_hexa("Session client cookie",
|
||||
session->next_crypto->client_kex.cookie, 16);
|
||||
ssh_print_bignum("k", session->next_crypto->shared_secret);
|
||||
}
|
||||
#else
|
||||
#define ssh_dh_debug(session)
|
||||
#endif
|
||||
|
||||
/** @internal
|
||||
* @brief generates a secret DH parameter of at least DH_SECURITY_BITS
|
||||
* security as well as the corresponding public key.
|
||||
@@ -370,7 +368,6 @@ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote,
|
||||
|
||||
done:
|
||||
bignum_ctx_free(ctx);
|
||||
ssh_dh_debug(session);
|
||||
if (rc != 1) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,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;
|
||||
}
|
||||
|
||||
@@ -181,9 +181,9 @@ int ecdh_build_k(ssh_session session) {
|
||||
session->next_crypto->ecdh_privkey = NULL;
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Session server cookie",
|
||||
ssh_log_hexdump("Session server cookie",
|
||||
session->next_crypto->server_kex.cookie, 16);
|
||||
ssh_print_hexa("Session client cookie",
|
||||
ssh_log_hexdump("Session client cookie",
|
||||
session->next_crypto->client_kex.cookie, 16);
|
||||
ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret);
|
||||
#endif
|
||||
@@ -206,6 +206,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
bignum_CTX ctx;
|
||||
/* SSH host keys (rsa,dsa,ecdsa) */
|
||||
ssh_key privkey;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
int curve;
|
||||
@@ -277,7 +278,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
}
|
||||
|
||||
/* privkey is not allocated */
|
||||
rc = ssh_get_key_params(session, &privkey);
|
||||
rc = ssh_get_key_params(session, &privkey, &digest);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
@@ -288,7 +289,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
goto error;
|
||||
}
|
||||
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
|
||||
if (sig_blob == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||
goto error;
|
||||
@@ -297,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;
|
||||
}
|
||||
|
||||
@@ -308,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;
|
||||
}
|
||||
@@ -242,9 +242,9 @@ int ecdh_build_k(ssh_session session)
|
||||
session->next_crypto->ecdh_privkey = NULL;
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Session server cookie",
|
||||
ssh_log_hexdump("Session server cookie",
|
||||
session->next_crypto->server_kex.cookie, 16);
|
||||
ssh_print_hexa("Session client cookie",
|
||||
ssh_log_hexdump("Session client cookie",
|
||||
session->next_crypto->client_kex.cookie, 16);
|
||||
ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret);
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -273,6 +273,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
gcry_sexp_t key = NULL;
|
||||
/* SSH host keys (rsa,dsa,ecdsa) */
|
||||
ssh_key privkey;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
int rc = SSH_ERROR;
|
||||
@@ -325,7 +326,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
}
|
||||
|
||||
/* privkey is not allocated */
|
||||
rc = ssh_get_key_params(session, &privkey);
|
||||
rc = ssh_get_key_params(session, &privkey, &digest);
|
||||
if (rc != SSH_OK) {
|
||||
goto out;
|
||||
}
|
||||
@@ -336,7 +337,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
goto out;
|
||||
}
|
||||
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
|
||||
if (sig_blob == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||
rc = SSH_ERROR;
|
||||
@@ -346,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;
|
||||
}
|
||||
|
||||
@@ -357,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;
|
||||
}
|
||||
@@ -188,6 +188,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
ssh_string q_s_string = NULL;
|
||||
mbedtls_ecp_group grp;
|
||||
ssh_key privkey = NULL;
|
||||
enum ssh_digest_e digest = SSH_DIGEST_AUTO;
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
int rc;
|
||||
@@ -250,7 +251,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
}
|
||||
|
||||
/* privkey is not allocated */
|
||||
rc = ssh_get_key_params(session, &privkey);
|
||||
rc = ssh_get_key_params(session, &privkey, &digest);
|
||||
if (rc == SSH_ERROR) {
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
@@ -263,7 +264,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
|
||||
goto out;
|
||||
}
|
||||
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
|
||||
if (sig_blob == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||
rc = SSH_ERROR;
|
||||
@@ -273,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;
|
||||
}
|
||||
|
||||
@@ -283,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);
|
||||
|
||||
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++) {
|
||||
|
||||
68
src/gssapi.c
68
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);
|
||||
@@ -235,6 +235,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;
|
||||
@@ -293,6 +297,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;
|
||||
@@ -384,7 +392,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 +411,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);
|
||||
@@ -444,13 +452,17 @@ 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,
|
||||
@@ -461,7 +473,7 @@ static ssh_buffer ssh_gssapi_build_mic(ssh_session session)
|
||||
"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 +557,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;
|
||||
@@ -700,13 +712,13 @@ end:
|
||||
* later.
|
||||
*/
|
||||
int ssh_gssapi_auth_mic(ssh_session session){
|
||||
int i;
|
||||
size_t i;
|
||||
gss_OID_set selected; /* oid selected for authentication */
|
||||
ssh_string *oids;
|
||||
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 +762,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 +772,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,8 +784,10 @@ 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);
|
||||
if (rc != SSH_ERROR) {
|
||||
@@ -778,13 +797,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 +811,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 +854,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;
|
||||
@@ -896,7 +922,7 @@ 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);
|
||||
if (GSS_ERROR(maj_stat)){
|
||||
ssh_buffer_free(mic_buffer);
|
||||
SSH_BUFFER_FREE(mic_buffer);
|
||||
ssh_gssapi_log_error(SSH_LOG_PROTOCOL,
|
||||
"generating MIC",
|
||||
maj_stat,
|
||||
@@ -910,7 +936,7 @@ static int ssh_gssapi_send_mic(ssh_session session){
|
||||
mic_token_buf.length,
|
||||
(size_t)mic_token_buf.length, mic_token_buf.value);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_buffer_free(mic_buffer);
|
||||
SSH_BUFFER_FREE(mic_buffer);
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -958,7 +984,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",
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
248
src/kex.c
248
src/kex.c
@@ -159,8 +159,6 @@
|
||||
GEX_SHA1 \
|
||||
KEY_EXCHANGE
|
||||
|
||||
#define KEX_METHODS_SIZE 10
|
||||
|
||||
/* RFC 8308 */
|
||||
#define KEX_EXTENSION_CLIENT "ext-info-c"
|
||||
|
||||
@@ -257,7 +255,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 +264,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 +272,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 +280,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;
|
||||
}
|
||||
|
||||
@@ -333,9 +331,10 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
int i, ok;
|
||||
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;
|
||||
@@ -351,32 +350,32 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
}
|
||||
|
||||
if (server_kex) {
|
||||
rc = ssh_buffer_get_data(packet,session->next_crypto->client_kex.cookie, 16);
|
||||
if (rc != 16) {
|
||||
len = ssh_buffer_get_data(packet,session->next_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) {
|
||||
len = ssh_hashbufin_add_cookie(session, session->next_crypto->client_kex.cookie);
|
||||
if (len < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed");
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
rc = ssh_buffer_get_data(packet,session->next_crypto->server_kex.cookie, 16);
|
||||
if (rc != 16) {
|
||||
len = ssh_buffer_get_data(packet,session->next_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) {
|
||||
len = ssh_hashbufin_add_cookie(session, session->next_crypto->server_kex.cookie);
|
||||
if (len < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed");
|
||||
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;
|
||||
@@ -393,7 +392,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
str = NULL;
|
||||
}
|
||||
|
||||
@@ -528,7 +527,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
|
||||
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;
|
||||
@@ -547,7 +546,7 @@ void ssh_list_kex(struct ssh_kex_struct *kex) {
|
||||
int i = 0;
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("session cookie", kex->cookie, 16);
|
||||
ssh_log_hexdump("session cookie", kex->cookie, 16);
|
||||
#endif
|
||||
|
||||
for(i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
@@ -561,103 +560,94 @@ void ssh_list_kex(struct ssh_kex_struct *kex) {
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief selects the hostkey mechanisms to be chosen for the key exchange,
|
||||
* as some hostkey mechanisms may be present in known_hosts file and preferred
|
||||
* as some hostkey mechanisms may be present in known_hosts files.
|
||||
*
|
||||
* @returns a cstring containing a comma-separated list of hostkey methods.
|
||||
* NULL if no method matches
|
||||
*/
|
||||
char *ssh_client_select_hostkeys(ssh_session session)
|
||||
{
|
||||
char methods_buffer[128]={0};
|
||||
char tail_buffer[128]={0};
|
||||
const char *wanted = NULL;
|
||||
char *wanted_without_certs = NULL;
|
||||
char *known_hosts_algorithms = NULL;
|
||||
char *known_hosts_ordered = NULL;
|
||||
char *new_hostkeys = NULL;
|
||||
static const char *preferred_hostkeys[] = {
|
||||
"ssh-ed25519",
|
||||
"ecdsa-sha2-nistp521",
|
||||
"ecdsa-sha2-nistp384",
|
||||
"ecdsa-sha2-nistp256",
|
||||
"rsa-sha2-512",
|
||||
"rsa-sha2-256",
|
||||
"ssh-rsa",
|
||||
#ifdef HAVE_DSA
|
||||
"ssh-dss",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
struct ssh_list *algo_list = NULL;
|
||||
struct ssh_iterator *it = NULL;
|
||||
size_t algo_count;
|
||||
int needcomma = 0;
|
||||
size_t i, len;
|
||||
char *fips_hostkeys = NULL;
|
||||
|
||||
algo_list = ssh_known_hosts_get_algorithms(session);
|
||||
if (algo_list == NULL) {
|
||||
wanted = session->opts.wanted_methods[SSH_HOSTKEYS];
|
||||
if (wanted == NULL) {
|
||||
if (ssh_fips_mode()) {
|
||||
wanted = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
||||
} else {
|
||||
wanted = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
||||
}
|
||||
}
|
||||
|
||||
/* This removes the certificate types, unsupported for now */
|
||||
wanted_without_certs = ssh_find_all_matching(HOSTKEYS, wanted);
|
||||
if (wanted_without_certs == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARNING,
|
||||
"List of allowed host key algorithms is empty or contains only "
|
||||
"unsupported algorithms");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
algo_count = ssh_list_count(algo_list);
|
||||
if (algo_count == 0) {
|
||||
ssh_list_free(algo_list);
|
||||
return NULL;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Order of wanted host keys: \"%s\"",
|
||||
wanted_without_certs);
|
||||
|
||||
for (i = 0; preferred_hostkeys[i] != NULL; ++i) {
|
||||
bool found = false;
|
||||
/* This is a signature type: We list also the SHA2 extensions */
|
||||
enum ssh_keytypes_e base_preferred =
|
||||
ssh_key_type_from_signature_name(preferred_hostkeys[i]);
|
||||
|
||||
for (it = ssh_list_get_iterator(algo_list);
|
||||
it != NULL;
|
||||
it = it->next) {
|
||||
const char *algo = ssh_iterator_value(const char *, it);
|
||||
/* This is always key type so we do not have to care for the
|
||||
* SHA2 extension */
|
||||
enum ssh_keytypes_e base_algo = ssh_key_type_from_name(algo);
|
||||
|
||||
if (base_preferred == base_algo) {
|
||||
/* Matching the keys already verified it is a known type */
|
||||
if (needcomma) {
|
||||
strncat(methods_buffer,
|
||||
",",
|
||||
sizeof(methods_buffer) - strlen(methods_buffer) - 1);
|
||||
}
|
||||
strncat(methods_buffer,
|
||||
preferred_hostkeys[i],
|
||||
sizeof(methods_buffer) - strlen(methods_buffer) - 1);
|
||||
needcomma = 1;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
/* Collect the rest of the algorithms in other buffer, that will
|
||||
* follow the preferred buffer. This will signalize all the algorithms
|
||||
* we are willing to accept.
|
||||
*/
|
||||
if (!found) {
|
||||
snprintf(tail_buffer + strlen(tail_buffer),
|
||||
sizeof(tail_buffer) - strlen(tail_buffer),
|
||||
",%s", preferred_hostkeys[i]);
|
||||
}
|
||||
}
|
||||
ssh_list_free(algo_list);
|
||||
|
||||
if (strlen(methods_buffer) == 0) {
|
||||
known_hosts_algorithms = ssh_known_hosts_get_algorithms_names(session);
|
||||
if (known_hosts_algorithms == NULL) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"No supported kex method for existing key in known_hosts file");
|
||||
return NULL;
|
||||
"No key found in known_hosts; "
|
||||
"changing host key method to \"%s\"",
|
||||
wanted_without_certs);
|
||||
|
||||
return wanted_without_certs;
|
||||
}
|
||||
|
||||
/* Append the supported list to the preferred.
|
||||
* The length is maximum 128 + 128 + 1, which will not overflow
|
||||
*/
|
||||
len = strlen(methods_buffer) + strlen(tail_buffer) + 1;
|
||||
new_hostkeys = malloc(len);
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Algorithms found in known_hosts files: \"%s\"",
|
||||
known_hosts_algorithms);
|
||||
|
||||
/* Filter and order the keys from known_hosts according to wanted list */
|
||||
known_hosts_ordered = ssh_find_all_matching(known_hosts_algorithms,
|
||||
wanted_without_certs);
|
||||
SAFE_FREE(known_hosts_algorithms);
|
||||
if (known_hosts_ordered == NULL) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"No key found in known_hosts is allowed; "
|
||||
"changing host key method to \"%s\"",
|
||||
wanted_without_certs);
|
||||
|
||||
return wanted_without_certs;
|
||||
}
|
||||
|
||||
/* Append the other supported keys after the preferred ones
|
||||
* This function tolerates NULL pointers in parameters */
|
||||
new_hostkeys = ssh_append_without_duplicates(known_hosts_ordered,
|
||||
wanted_without_certs);
|
||||
SAFE_FREE(known_hosts_ordered);
|
||||
SAFE_FREE(wanted_without_certs);
|
||||
if (new_hostkeys == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
snprintf(new_hostkeys, len,
|
||||
"%s%s", methods_buffer, tail_buffer);
|
||||
|
||||
if (ssh_fips_mode()) {
|
||||
/* Filter out algorithms not allowed in FIPS mode */
|
||||
fips_hostkeys = ssh_keep_fips_algos(SSH_HOSTKEYS, new_hostkeys);
|
||||
SAFE_FREE(new_hostkeys);
|
||||
if (fips_hostkeys == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARNING,
|
||||
"None of the wanted host keys or keys in known_hosts files "
|
||||
"is allowed in FIPS mode.");
|
||||
return NULL;
|
||||
}
|
||||
new_hostkeys = fips_hostkeys;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Changing host key method to \"%s\"",
|
||||
@@ -672,7 +662,7 @@ char *ssh_client_select_hostkeys(ssh_session session)
|
||||
*/
|
||||
int ssh_set_client_kex(ssh_session session)
|
||||
{
|
||||
struct ssh_kex_struct *client= &session->next_crypto->client_kex;
|
||||
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
|
||||
const char *wanted;
|
||||
char *kex = NULL;
|
||||
char *kex_tmp = NULL;
|
||||
@@ -686,15 +676,23 @@ int ssh_set_client_kex(ssh_session session)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **));
|
||||
/* first check if we have specific host key methods */
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS] == NULL) {
|
||||
/* Only if no override */
|
||||
session->opts.wanted_methods[SSH_HOSTKEYS] =
|
||||
ssh_client_select_hostkeys(session);
|
||||
}
|
||||
memset(client->methods, 0, SSH_KEX_METHODS * sizeof(char **));
|
||||
|
||||
/* Set the list of allowed algorithms in order of preference, if it hadn't
|
||||
* been set yet. */
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
if (i == SSH_HOSTKEYS) {
|
||||
/* Set the hostkeys in the following order:
|
||||
* - First: keys present in known_hosts files ordered by preference
|
||||
* - Next: other wanted algorithms ordered by preference */
|
||||
client->methods[i] = ssh_client_select_hostkeys(session);
|
||||
if (client->methods[i] == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
wanted = session->opts.wanted_methods[i];
|
||||
if (wanted == NULL) {
|
||||
if (ssh_fips_mode()) {
|
||||
@@ -751,7 +749,7 @@ int ssh_kex_select_methods (ssh_session session){
|
||||
ext_start[0] = '\0';
|
||||
}
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]);
|
||||
if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){
|
||||
ssh_set_error(session,SSH_FATAL,"kex error : no match for method %s: server [%s], client [%s]",
|
||||
@@ -824,7 +822,7 @@ int ssh_send_kex(ssh_session session, int server_kex) {
|
||||
|
||||
ssh_list_kex(kex);
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
str = ssh_string_from_char(kex->methods[i]);
|
||||
if (str == NULL) {
|
||||
goto error;
|
||||
@@ -836,7 +834,7 @@ int ssh_send_kex(ssh_session session, int server_kex) {
|
||||
if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) {
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
str = NULL;
|
||||
}
|
||||
|
||||
@@ -857,7 +855,7 @@ int ssh_send_kex(ssh_session session, int server_kex) {
|
||||
error:
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
ssh_buffer_reinit(session->out_hashbuf);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -1020,7 +1018,7 @@ 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);
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
if(rc != SSH_OK){
|
||||
goto error;
|
||||
}
|
||||
@@ -1120,7 +1118,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
||||
ssh_log_hexdump("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
||||
#endif
|
||||
|
||||
switch (session->next_crypto->kex_type) {
|
||||
@@ -1196,20 +1194,20 @@ int ssh_make_sessionid(ssh_session session)
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
printf("Session hash: \n");
|
||||
ssh_print_hexa("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
|
||||
ssh_print_hexa("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
|
||||
ssh_log_hexdump("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
|
||||
ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
|
||||
#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;
|
||||
}
|
||||
@@ -1384,22 +1382,22 @@ int ssh_generate_session_keys(ssh_session session)
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Client to Server IV", IV_cli_to_srv, IV_len);
|
||||
ssh_print_hexa("Server to Client IV", IV_srv_to_cli, IV_len);
|
||||
ssh_print_hexa("Client to Server Encryption Key", enckey_cli_to_srv,
|
||||
ssh_log_hexdump("Client to Server IV", IV_cli_to_srv, IV_len);
|
||||
ssh_log_hexdump("Server to Client IV", IV_srv_to_cli, IV_len);
|
||||
ssh_log_hexdump("Client to Server Encryption Key", enckey_cli_to_srv,
|
||||
enckey_cli_to_srv_len);
|
||||
ssh_print_hexa("Server to Client Encryption Key", enckey_srv_to_cli,
|
||||
ssh_log_hexdump("Server to Client Encryption Key", enckey_srv_to_cli,
|
||||
enckey_srv_to_cli_len);
|
||||
ssh_print_hexa("Client to Server Integrity Key", intkey_cli_to_srv,
|
||||
ssh_log_hexdump("Client to Server Integrity Key", intkey_cli_to_srv,
|
||||
intkey_cli_to_srv_len);
|
||||
ssh_print_hexa("Server to Client Integrity Key", intkey_srv_to_cli,
|
||||
ssh_log_hexdump("Server to Client Integrity Key", intkey_srv_to_cli,
|
||||
intkey_srv_to_cli_len);
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
@@ -405,8 +405,12 @@ int ssh_is_server_known(ssh_session session)
|
||||
|
||||
if ((ret == SSH_SERVER_NOT_KNOWN) &&
|
||||
(session->opts.StrictHostKeyChecking == 0)) {
|
||||
ssh_write_knownhost(session);
|
||||
ret = SSH_SERVER_KNOWN_OK;
|
||||
int rv = ssh_session_update_known_hosts(session);
|
||||
if (rv != SSH_OK) {
|
||||
ret = SSH_SERVER_ERROR;
|
||||
} else {
|
||||
ret = SSH_SERVER_KNOWN_OK;
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_FREE(host);
|
||||
@@ -492,10 +496,12 @@ char * ssh_dump_knownhost(ssh_session session) {
|
||||
* @deprecated Please use ssh_session_update_known_hosts()
|
||||
* @brief This function is deprecated
|
||||
*/
|
||||
int ssh_write_knownhost(ssh_session session) {
|
||||
int ssh_write_knownhost(ssh_session session)
|
||||
{
|
||||
FILE *file;
|
||||
char *buffer;
|
||||
char *buffer = NULL;
|
||||
char *dir;
|
||||
int rc;
|
||||
|
||||
if (session->opts.knownhosts == NULL) {
|
||||
if (ssh_options_apply(session) < 0) {
|
||||
@@ -504,33 +510,45 @@ int ssh_write_knownhost(ssh_session session) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if directory exists and create it if not */
|
||||
dir = ssh_dirname(session->opts.knownhosts);
|
||||
if (dir == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
errno = 0;
|
||||
file = fopen(session->opts.knownhosts, "a");
|
||||
if (file == NULL) {
|
||||
if (errno == ENOENT) {
|
||||
dir = ssh_dirname(session->opts.knownhosts);
|
||||
if (dir == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (!ssh_file_readaccess_ok(dir)) {
|
||||
if (ssh_mkdir(dir, 0700) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Cannot create %s directory.", dir);
|
||||
rc = ssh_mkdirs(dir, 0700);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Cannot create %s directory: %s",
|
||||
dir, strerror(errno));
|
||||
SAFE_FREE(dir);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SAFE_FREE(dir);
|
||||
|
||||
errno = 0;
|
||||
file = fopen(session->opts.knownhosts, "a");
|
||||
if (file == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Couldn't open known_hosts file %s"
|
||||
" for appending: %s",
|
||||
session->opts.knownhosts, strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
} else {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Couldn't open known_hosts file %s for appending: %s",
|
||||
session->opts.knownhosts, strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
SAFE_FREE(dir);
|
||||
|
||||
file = fopen(session->opts.knownhosts, "a");
|
||||
if (file == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Couldn't open known_hosts file %s for appending: %s",
|
||||
session->opts.knownhosts, strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
buffer = ssh_dump_knownhost(session);
|
||||
if (buffer == NULL) {
|
||||
rc = ssh_session_export_known_hosts_entry(session, &buffer);
|
||||
if (rc != SSH_OK) {
|
||||
fclose(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
250
src/knownhosts.c
250
src/knownhosts.c
@@ -42,6 +42,7 @@
|
||||
#include "libssh/pki.h"
|
||||
#include "libssh/dh.h"
|
||||
#include "libssh/knownhosts.h"
|
||||
#include "libssh/token.h"
|
||||
|
||||
/**
|
||||
* @addtogroup libssh_session
|
||||
@@ -128,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;
|
||||
}
|
||||
@@ -306,7 +307,7 @@ static char *ssh_session_get_host_port(ssh_session session)
|
||||
if (session->opts.host == NULL) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Can't verify server inn known hosts if the host we "
|
||||
"Can't verify server in known hosts if the host we "
|
||||
"should connect to has not been set");
|
||||
|
||||
return NULL;
|
||||
@@ -451,6 +452,146 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Returns a static string containing a list of the signature types the
|
||||
* given key type can generate.
|
||||
*
|
||||
* @returns A static cstring containing the signature types the key is able to
|
||||
* generate separated by commas; NULL in case of error
|
||||
*/
|
||||
static const char *ssh_known_host_sigs_from_hostkey_type(enum ssh_keytypes_e type)
|
||||
{
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
return "rsa-sha2-512,rsa-sha2-256,ssh-rsa";
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
return "ssh-ed25519";
|
||||
#ifdef HAVE_DSA
|
||||
case SSH_KEYTYPE_DSS:
|
||||
return "ssh-dss";
|
||||
#endif
|
||||
#ifdef HAVE_ECDH
|
||||
case SSH_KEYTYPE_ECDSA_P256:
|
||||
return "ecdsa-sha2-nistp256";
|
||||
case SSH_KEYTYPE_ECDSA_P384:
|
||||
return "ecdsa-sha2-nistp384";
|
||||
case SSH_KEYTYPE_ECDSA_P521:
|
||||
return "ecdsa-sha2-nistp521";
|
||||
#endif
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "The given type %d is not a base private key type "
|
||||
"or is unsupported", type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief Get the host keys algorithms identifiers from the known_hosts files
|
||||
*
|
||||
* This expands the signatures types that can be generated from the keys types
|
||||
* present in the known_hosts files
|
||||
*
|
||||
* @param[in] session The ssh session to use.
|
||||
*
|
||||
* @return A newly allocated cstring containing a list of signature algorithms
|
||||
* that can be generated by the host using the keys listed in the known_hosts
|
||||
* files, NULL on error.
|
||||
*/
|
||||
char *ssh_known_hosts_get_algorithms_names(ssh_session session)
|
||||
{
|
||||
char methods_buffer[256 + 1] = {0};
|
||||
struct ssh_list *entry_list = NULL;
|
||||
struct ssh_iterator *it = NULL;
|
||||
char *host_port = NULL;
|
||||
size_t count;
|
||||
bool needcomma = false;
|
||||
char *names;
|
||||
|
||||
int rc;
|
||||
|
||||
if (session->opts.knownhosts == NULL ||
|
||||
session->opts.global_knownhosts == NULL) {
|
||||
if (ssh_options_apply(session) < 0) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Can't find a known_hosts file");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
host_port = ssh_session_get_host_port(session);
|
||||
if (host_port == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_known_hosts_read_entries(host_port,
|
||||
session->opts.knownhosts,
|
||||
&entry_list);
|
||||
if (rc != 0) {
|
||||
SAFE_FREE(host_port);
|
||||
ssh_list_free(entry_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_known_hosts_read_entries(host_port,
|
||||
session->opts.global_knownhosts,
|
||||
&entry_list);
|
||||
SAFE_FREE(host_port);
|
||||
if (rc != 0) {
|
||||
ssh_list_free(entry_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (entry_list == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
count = ssh_list_count(entry_list);
|
||||
if (count == 0) {
|
||||
ssh_list_free(entry_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (it = ssh_list_get_iterator(entry_list);
|
||||
it != NULL;
|
||||
it = ssh_list_get_iterator(entry_list))
|
||||
{
|
||||
struct ssh_knownhosts_entry *entry = NULL;
|
||||
const char *algo = NULL;
|
||||
|
||||
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
||||
algo = ssh_known_host_sigs_from_hostkey_type(entry->publickey->type);
|
||||
if (algo == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (needcomma) {
|
||||
strncat(methods_buffer,
|
||||
",",
|
||||
sizeof(methods_buffer) - strlen(methods_buffer) - 1);
|
||||
}
|
||||
|
||||
strncat(methods_buffer,
|
||||
algo,
|
||||
sizeof(methods_buffer) - strlen(methods_buffer) - 1);
|
||||
needcomma = true;
|
||||
|
||||
ssh_knownhosts_entry_free(entry);
|
||||
ssh_list_remove(entry_list, it);
|
||||
}
|
||||
|
||||
ssh_list_free(entry_list);
|
||||
|
||||
names = ssh_remove_duplicates(methods_buffer);
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse a line from a known_hosts entry into a structure
|
||||
*
|
||||
@@ -638,14 +779,15 @@ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
||||
struct ssh_list *entry_list = NULL;
|
||||
struct ssh_iterator *it = NULL;
|
||||
char *host_port = NULL;
|
||||
bool ok;
|
||||
bool global_known_hosts_found = false;
|
||||
bool known_hosts_found = false;
|
||||
int rc;
|
||||
|
||||
if (session->opts.knownhosts == NULL) {
|
||||
if (ssh_options_apply(session) < 0) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Can't find a known_hosts file");
|
||||
"Cannot find a known_hosts file");
|
||||
|
||||
return SSH_KNOWN_HOSTS_NOT_FOUND;
|
||||
}
|
||||
@@ -653,50 +795,67 @@ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
||||
|
||||
if (session->opts.knownhosts == NULL &&
|
||||
session->opts.global_knownhosts == NULL) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"No path set for a known_hosts file");
|
||||
|
||||
return SSH_KNOWN_HOSTS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (session->opts.knownhosts != NULL) {
|
||||
ok = ssh_file_readaccess_ok(session->opts.knownhosts);
|
||||
if (!ok) {
|
||||
return SSH_KNOWN_HOSTS_NOT_FOUND;
|
||||
known_hosts_found = ssh_file_readaccess_ok(session->opts.knownhosts);
|
||||
if (!known_hosts_found) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Cannot access file %s",
|
||||
session->opts.knownhosts);
|
||||
}
|
||||
}
|
||||
|
||||
if (session->opts.global_knownhosts != NULL) {
|
||||
ok = ssh_file_readaccess_ok(session->opts.global_knownhosts);
|
||||
if (!ok) {
|
||||
return SSH_KNOWN_HOSTS_NOT_FOUND;
|
||||
global_known_hosts_found =
|
||||
ssh_file_readaccess_ok(session->opts.global_knownhosts);
|
||||
if (!global_known_hosts_found) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Cannot access file %s",
|
||||
session->opts.global_knownhosts);
|
||||
}
|
||||
}
|
||||
|
||||
if ((!known_hosts_found) && (!global_known_hosts_found)) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Cannot find a known_hosts file");
|
||||
|
||||
return SSH_KNOWN_HOSTS_NOT_FOUND;
|
||||
}
|
||||
|
||||
host_port = ssh_session_get_host_port(session);
|
||||
if (host_port == NULL) {
|
||||
return SSH_KNOWN_HOSTS_ERROR;
|
||||
}
|
||||
|
||||
if (session->opts.knownhosts != NULL) {
|
||||
if (known_hosts_found) {
|
||||
rc = ssh_known_hosts_read_entries(host_port,
|
||||
session->opts.knownhosts,
|
||||
&entry_list);
|
||||
if (rc != 0) {
|
||||
SAFE_FREE(host_port);
|
||||
ssh_list_free(entry_list);
|
||||
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||
return SSH_KNOWN_HOSTS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (session->opts.global_knownhosts != NULL) {
|
||||
if (global_known_hosts_found) {
|
||||
rc = ssh_known_hosts_read_entries(host_port,
|
||||
session->opts.global_knownhosts,
|
||||
&entry_list);
|
||||
SAFE_FREE(host_port);
|
||||
if (rc != 0) {
|
||||
SAFE_FREE(host_port);
|
||||
ssh_list_free(entry_list);
|
||||
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||
return SSH_KNOWN_HOSTS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_FREE(host_port);
|
||||
|
||||
if (ssh_list_count(entry_list) == 0) {
|
||||
ssh_list_free(entry_list);
|
||||
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||
@@ -820,34 +979,41 @@ int ssh_session_update_known_hosts(ssh_session session)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if directory exists and create it if not */
|
||||
dir = ssh_dirname(session->opts.knownhosts);
|
||||
if (dir == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_file_readaccess_ok(dir);
|
||||
if (rc == 0) {
|
||||
rc = ssh_mkdir(dir, 0700);
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Cannot create %s directory.", dir);
|
||||
SAFE_FREE(dir);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SAFE_FREE(dir);
|
||||
|
||||
errno = 0;
|
||||
fp = fopen(session->opts.knownhosts, "a");
|
||||
if (fp == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Couldn't open known_hosts file %s for appending: %s",
|
||||
session->opts.knownhosts, strerror(errno));
|
||||
return SSH_ERROR;
|
||||
if (errno == ENOENT) {
|
||||
dir = ssh_dirname(session->opts.knownhosts);
|
||||
if (dir == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_mkdirs(dir, 0700);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Cannot create %s directory: %s",
|
||||
dir, strerror(errno));
|
||||
SAFE_FREE(dir);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SAFE_FREE(dir);
|
||||
|
||||
errno = 0;
|
||||
fp = fopen(session->opts.knownhosts, "a");
|
||||
if (fp == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Couldn't open known_hosts file %s"
|
||||
" for appending: %s",
|
||||
session->opts.knownhosts, strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
} else {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Couldn't open known_hosts file %s for appending: %s",
|
||||
session->opts.knownhosts, strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_session_export_known_hosts_entry(session, &entry);
|
||||
|
||||
@@ -686,8 +686,12 @@ static int aes_ctr_set_key(struct ssh_cipher_struct *cipher, void *key,
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static void aes_ctr_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
unsigned long len) {
|
||||
static void
|
||||
aes_ctr_encrypt(struct ssh_cipher_struct *cipher,
|
||||
void *in,
|
||||
void *out,
|
||||
size_t len)
|
||||
{
|
||||
unsigned char tmp_buffer[AES_BLOCK_SIZE];
|
||||
unsigned int num=0;
|
||||
/* Some things are special with ctr128 :
|
||||
|
||||
@@ -738,7 +738,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;
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@@ -45,7 +45,7 @@ void ssh_mbedcry_bn_free(bignum bn)
|
||||
SAFE_FREE(bn);
|
||||
}
|
||||
|
||||
unsigned char *ssh_mbedcry_bn2num(bignum num, int radix)
|
||||
unsigned char *ssh_mbedcry_bn2num(const_bignum num, int radix)
|
||||
{
|
||||
char *buf = NULL;
|
||||
size_t olen;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -696,7 +699,7 @@ 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;
|
||||
}
|
||||
|
||||
@@ -712,10 +715,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 +800,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 +812,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 +835,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 +852,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 +894,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 +909,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 +1097,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;
|
||||
@@ -1491,12 +1494,18 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
|
||||
msg->type = SSH_REQUEST_GLOBAL;
|
||||
|
||||
if (strcmp(request, "tcpip-forward") == 0) {
|
||||
|
||||
/* According to RFC4254, the client SHOULD reject this message */
|
||||
if (session->client) {
|
||||
goto reply_with_failure;
|
||||
}
|
||||
|
||||
r = ssh_buffer_unpack(packet, "sd",
|
||||
&msg->global_request.bind_address,
|
||||
&msg->global_request.bind_port
|
||||
);
|
||||
if (r != SSH_OK){
|
||||
goto error;
|
||||
goto reply_with_failure;
|
||||
}
|
||||
msg->global_request.type = SSH_GLOBAL_REQUEST_TCPIP_FORWARD;
|
||||
msg->global_request.want_reply = want_reply;
|
||||
@@ -1516,11 +1525,17 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
|
||||
return rc;
|
||||
}
|
||||
} else if (strcmp(request, "cancel-tcpip-forward") == 0) {
|
||||
|
||||
/* According to RFC4254, the client SHOULD reject this message */
|
||||
if (session->client) {
|
||||
goto reply_with_failure;
|
||||
}
|
||||
|
||||
r = ssh_buffer_unpack(packet, "sd",
|
||||
&msg->global_request.bind_address,
|
||||
&msg->global_request.bind_port);
|
||||
if (r != SSH_OK){
|
||||
goto error;
|
||||
goto reply_with_failure;
|
||||
}
|
||||
msg->global_request.type = SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD;
|
||||
msg->global_request.want_reply = want_reply;
|
||||
@@ -1546,18 +1561,41 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
|
||||
ssh_message_global_request_reply_success(msg, 0);
|
||||
}
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply);
|
||||
rc = SSH_PACKET_NOT_USED;
|
||||
SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s, "
|
||||
"want_reply = %d", request, want_reply);
|
||||
goto reply_with_failure;
|
||||
}
|
||||
|
||||
SAFE_FREE(msg);
|
||||
SAFE_FREE(request);
|
||||
return rc;
|
||||
|
||||
reply_with_failure:
|
||||
/* Only report the failure if requested */
|
||||
if (want_reply) {
|
||||
r = ssh_buffer_add_u8(session->out_buffer,
|
||||
SSH2_MSG_REQUEST_FAILURE);
|
||||
if (r < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = ssh_packet_send(session);
|
||||
if (r != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"The requester doesn't want to know the request failed!");
|
||||
}
|
||||
|
||||
/* Consume the message to avoid sending UNIMPLEMENTED later */
|
||||
rc = SSH_PACKET_USED;
|
||||
error:
|
||||
SAFE_FREE(msg);
|
||||
SAFE_FREE(request);
|
||||
SSH_LOG(SSH_LOG_WARNING, "Invalid SSH_MSG_GLOBAL_REQUEST packet");
|
||||
return SSH_PACKET_NOT_USED;
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
544
src/misc.c
544
src/misc.c
@@ -130,6 +130,31 @@ int ssh_file_readaccess_ok(const char *file) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the given path is an existing directory and that is
|
||||
* accessible for writing.
|
||||
*
|
||||
* @param[in] path Path to the directory to be checked
|
||||
*
|
||||
* @return Return 1 if the directory exists and is accessible; 0 otherwise
|
||||
* */
|
||||
int ssh_dir_writeable(const char *path)
|
||||
{
|
||||
struct _stat buffer;
|
||||
int rc;
|
||||
|
||||
rc = _stat(path, &buffer);
|
||||
if (rc < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((buffer.st_mode & _S_IFDIR) && (buffer.st_mode & _S_IWRITE)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SSH_USEC_IN_SEC 1000000LL
|
||||
#define SSH_SECONDS_SINCE_1601 11644473600LL
|
||||
|
||||
@@ -247,6 +272,31 @@ int ssh_file_readaccess_ok(const char *file)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the given path is an existing directory and that is
|
||||
* accessible for writing.
|
||||
*
|
||||
* @param[in] path Path to the directory to be checked
|
||||
*
|
||||
* @return Return 1 if the directory exists and is accessible; 0 otherwise
|
||||
* */
|
||||
int ssh_dir_writeable(const char *path)
|
||||
{
|
||||
struct stat buffer;
|
||||
int rc;
|
||||
|
||||
rc = stat(path, &buffer);
|
||||
if (rc < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (S_ISDIR(buffer.st_mode) && (buffer.st_mode & S_IWRITE)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *ssh_get_local_username(void)
|
||||
{
|
||||
struct passwd pwd;
|
||||
@@ -389,6 +439,193 @@ void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
|
||||
free(hexa);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log the content of a buffer in hexadecimal format, similar to the
|
||||
* output of 'hexdump -C' command.
|
||||
*
|
||||
* The first logged line is the given description followed by the length.
|
||||
* Then the content of the buffer is logged 16 bytes per line in the following
|
||||
* format:
|
||||
*
|
||||
* (offset) (first 8 bytes) (last 8 bytes) (the 16 bytes as ASCII char values)
|
||||
*
|
||||
* The output for a 16 bytes array containing values from 0x00 to 0x0f would be:
|
||||
*
|
||||
* "Example (16 bytes):"
|
||||
* " 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................"
|
||||
*
|
||||
* The value for each byte as corresponding ASCII character is printed at the
|
||||
* end if the value is printable. Otherwise it is replace with '.'.
|
||||
*
|
||||
* @param[in] descr A description for the content to be logged
|
||||
* @param[in] what The buffer to be logged
|
||||
* @param[in] len The length of the buffer given in what
|
||||
*
|
||||
* @note If a too long description is provided (which would result in a first
|
||||
* line longer than 80 bytes), the function will fail.
|
||||
*/
|
||||
void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
char ascii[17];
|
||||
const unsigned char *pc = NULL;
|
||||
size_t count = 0;
|
||||
ssize_t printed = 0;
|
||||
|
||||
/* The required buffer size is calculated from:
|
||||
*
|
||||
* 2 bytes for spaces at the beginning
|
||||
* 8 bytes for the offset
|
||||
* 2 bytes for spaces
|
||||
* 24 bytes to print the first 8 bytes + spaces
|
||||
* 1 byte for an extra space
|
||||
* 24 bytes to print next 8 bytes + spaces
|
||||
* 2 bytes for extra spaces
|
||||
* 16 bytes for the content as ASCII characters at the end
|
||||
* 1 byte for the ending '\0'
|
||||
*
|
||||
* Resulting in 80 bytes.
|
||||
*
|
||||
* Except for the first line (description + size), all lines have fixed
|
||||
* length. If a too long description is used, the function will fail.
|
||||
* */
|
||||
char buffer[80];
|
||||
|
||||
/* Print description */
|
||||
if (descr != NULL) {
|
||||
printed = snprintf(buffer, sizeof(buffer), "%s ", descr);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
} else {
|
||||
printed = snprintf(buffer, sizeof(buffer), "(NULL description) ");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
"(zero length):");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
return;
|
||||
} else {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
"(%zu bytes):", len);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
|
||||
if (what == NULL) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
"(NULL)");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
|
||||
/* Reset state */
|
||||
count = 0;
|
||||
pc = what;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
/* Add one space after printing 8 bytes */
|
||||
if ((i % 8) == 0) {
|
||||
if (i != 0) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Log previous line and reset state for new line */
|
||||
if ((i % 16) == 0) {
|
||||
if (i != 0) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
" %s", ascii);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/* Start a new line with the offset */
|
||||
printed = snprintf(buffer, sizeof(buffer),
|
||||
" %08zx ", i);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
|
||||
/* Print the current byte hexadecimal representation */
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
" %02x", pc[i]);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
|
||||
/* If printable, store the ASCII character */
|
||||
if (isprint(pc[i])) {
|
||||
ascii[i % 16] = pc[i];
|
||||
} else {
|
||||
ascii[i % 16] = '.';
|
||||
}
|
||||
ascii[(i % 16) + 1] = '\0';
|
||||
}
|
||||
|
||||
/* Add padding if not exactly 16 characters */
|
||||
while ((i % 16) != 0) {
|
||||
/* Add one space after printing 8 bytes */
|
||||
if ((i % 8) == 0) {
|
||||
if (i != 0) {
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
}
|
||||
}
|
||||
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
count += printed;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Print the last printable part */
|
||||
printed = snprintf(buffer + count, sizeof(buffer) - count,
|
||||
" %s", ascii);
|
||||
if (printed < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
SSH_LOG(SSH_LOG_WARN, "Could not print to buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if libssh is the required version or get the version
|
||||
* string.
|
||||
@@ -713,16 +950,81 @@ char *ssh_basename (const char *path) {
|
||||
*
|
||||
* @return 0 on success, < 0 on error with errno set.
|
||||
*/
|
||||
int ssh_mkdir(const char *pathname, mode_t mode) {
|
||||
int r;
|
||||
|
||||
int ssh_mkdir(const char *pathname, mode_t mode)
|
||||
{
|
||||
int r;
|
||||
#ifdef _WIN32
|
||||
r = _mkdir(pathname);
|
||||
r = _mkdir(pathname);
|
||||
#else
|
||||
r = mkdir(pathname, mode);
|
||||
r = mkdir(pathname, mode);
|
||||
#endif
|
||||
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempts to create a directory with the given pathname. The missing
|
||||
* directories in the given pathname are created recursively.
|
||||
*
|
||||
* @param[in] pathname The path name to create the directory.
|
||||
*
|
||||
* @param[in] mode The permissions to use.
|
||||
*
|
||||
* @return 0 on success, < 0 on error with errno set.
|
||||
*
|
||||
* @note mode is ignored on Windows systems.
|
||||
*/
|
||||
int ssh_mkdirs(const char *pathname, mode_t mode)
|
||||
{
|
||||
int rc = 0;
|
||||
char *parent = NULL;
|
||||
|
||||
if (pathname == NULL ||
|
||||
pathname[0] == '\0' ||
|
||||
!strcmp(pathname, "/") ||
|
||||
!strcmp(pathname, "."))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
rc = _mkdir(pathname);
|
||||
#else
|
||||
rc = mkdir(pathname, mode);
|
||||
#endif
|
||||
|
||||
if (rc < 0) {
|
||||
/* If a directory was missing, try to create the parent */
|
||||
if (errno == ENOENT) {
|
||||
parent = ssh_dirname(pathname);
|
||||
if (parent == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ssh_mkdirs(parent, mode);
|
||||
if (rc < 0) {
|
||||
/* We could not create the parent */
|
||||
SAFE_FREE(parent);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SAFE_FREE(parent);
|
||||
|
||||
/* Try again */
|
||||
errno = 0;
|
||||
#ifdef _WIN32
|
||||
rc = _mkdir(pathname);
|
||||
#else
|
||||
rc = mkdir(pathname, mode);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -825,6 +1127,7 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
|
||||
|
||||
for (i = 0; *p != '\0'; p++) {
|
||||
if (*p != '%') {
|
||||
escape:
|
||||
buf[i] = *p;
|
||||
i++;
|
||||
if (i >= MAX_BUF_SIZE) {
|
||||
@@ -841,6 +1144,8 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
|
||||
}
|
||||
|
||||
switch (*p) {
|
||||
case '%':
|
||||
goto escape;
|
||||
case 'd':
|
||||
x = strdup(session->opts.sshdir);
|
||||
break;
|
||||
@@ -1203,4 +1508,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:
|
||||
@@ -1472,6 +1472,13 @@ int ssh_options_apply(ssh_session session) {
|
||||
it != NULL;
|
||||
it = it->next) {
|
||||
char *id = (char *) it->data;
|
||||
if (strncmp(id, "pkcs11:", 6) == 0) {
|
||||
/* PKCS#11 URIs are using percent-encoding so we can not mix
|
||||
* it with ssh expansion of ssh escape characters.
|
||||
* Skip these identities now, before we will have PKCS#11 support
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
tmp = ssh_path_expand_escape(session, id);
|
||||
if (tmp == NULL) {
|
||||
return -1;
|
||||
@@ -1798,12 +1805,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) {
|
||||
@@ -1816,7 +1823,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:
|
||||
@@ -1825,7 +1832,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:
|
||||
@@ -1843,7 +1850,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:
|
||||
|
||||
124
src/packet.c
124
src/packet.c
@@ -939,18 +939,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 +1059,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 +1075,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);
|
||||
@@ -1438,37 +1458,54 @@ void ssh_packet_set_default_callbacks(ssh_session session){
|
||||
* @brief dispatch the call of packet handlers callbacks for a received packet
|
||||
* @param type type of packet
|
||||
*/
|
||||
void ssh_packet_process(ssh_session session, uint8_t type){
|
||||
struct ssh_iterator *i;
|
||||
int r=SSH_PACKET_NOT_USED;
|
||||
ssh_packet_callbacks cb;
|
||||
void ssh_packet_process(ssh_session session, uint8_t type)
|
||||
{
|
||||
struct ssh_iterator *i = NULL;
|
||||
int rc = SSH_PACKET_NOT_USED;
|
||||
ssh_packet_callbacks cb;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Dispatching handler for packet type %d",type);
|
||||
if(session->packet_callbacks == NULL){
|
||||
SSH_LOG(SSH_LOG_RARE,"Packet callback is not initialized !");
|
||||
SSH_LOG(SSH_LOG_PACKET, "Dispatching handler for packet type %d", type);
|
||||
if (session->packet_callbacks == NULL) {
|
||||
SSH_LOG(SSH_LOG_RARE, "Packet callback is not initialized !");
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
i=ssh_list_get_iterator(session->packet_callbacks);
|
||||
while(i != NULL){
|
||||
cb=ssh_iterator_value(ssh_packet_callbacks,i);
|
||||
i=i->next;
|
||||
if(!cb)
|
||||
continue;
|
||||
if(cb->start > type)
|
||||
continue;
|
||||
if(cb->start + cb->n_callbacks <= type)
|
||||
continue;
|
||||
if(cb->callbacks[type - cb->start]==NULL)
|
||||
continue;
|
||||
r=cb->callbacks[type - cb->start](session,type,session->in_buffer,cb->user);
|
||||
if(r==SSH_PACKET_USED)
|
||||
break;
|
||||
}
|
||||
if(r==SSH_PACKET_NOT_USED){
|
||||
SSH_LOG(SSH_LOG_RARE,"Couldn't do anything with packet type %d",type);
|
||||
ssh_packet_send_unimplemented(session, session->recv_seq-1);
|
||||
}
|
||||
i = ssh_list_get_iterator(session->packet_callbacks);
|
||||
while (i != NULL) {
|
||||
cb = ssh_iterator_value(ssh_packet_callbacks, i);
|
||||
i = i->next;
|
||||
|
||||
if (!cb) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cb->start > type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cb->start + cb->n_callbacks <= type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cb->callbacks[type - cb->start] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = cb->callbacks[type - cb->start](session, type, session->in_buffer,
|
||||
cb->user);
|
||||
if (rc == SSH_PACKET_USED) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == SSH_PACKET_NOT_USED) {
|
||||
SSH_LOG(SSH_LOG_RARE, "Couldn't do anything with packet type %d", type);
|
||||
rc = ssh_packet_send_unimplemented(session, session->recv_seq - 1);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_RARE, "Failed to send unimplemented: %s",
|
||||
ssh_get_error(session));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@@ -1789,7 +1826,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);
|
||||
@@ -1847,6 +1884,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) {
|
||||
@@ -1912,6 +1953,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);
|
||||
@@ -1929,6 +1975,8 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
session->next_crypto->decryptkey,
|
||||
session->next_crypto->decryptIV);
|
||||
if (rc < 0) {
|
||||
/* On error, make sure it is not used */
|
||||
session->next_crypto->used = 0;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -1937,6 +1985,8 @@ ssh_packet_set_newkeys(ssh_session session,
|
||||
session->next_crypto->encryptkey,
|
||||
session->next_crypto->encryptIV);
|
||||
if (rc < 0) {
|
||||
/* On error, make sure it is not used */
|
||||
session->next_crypto->used = 0;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
@@ -153,9 +153,8 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
||||
session->next_crypto->secret_hash,
|
||||
session->next_crypto->digest_len);
|
||||
ssh_string_burn(sig_blob);
|
||||
ssh_string_free(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
ssh_signature_free(sig);
|
||||
sig_blob = NULL;
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
@@ -196,11 +199,11 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
|
||||
hmac_final(ctx, crypto->hmacbuf, &finallen);
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("mac: ",data,hmac_digest_len(type));
|
||||
ssh_log_hexdump("mac: ", data, len);
|
||||
if (finallen != hmac_digest_len(type)) {
|
||||
printf("Final len is %d\n",finallen);
|
||||
printf("Final len is %d\n", finallen);
|
||||
}
|
||||
ssh_print_hexa("Packet hmac", crypto->hmacbuf, hmac_digest_len(type));
|
||||
ssh_log_hexdump("Packet hmac", crypto->hmacbuf, hmac_digest_len(type));
|
||||
#endif
|
||||
}
|
||||
explicit_bzero(out, len);
|
||||
@@ -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;
|
||||
@@ -264,9 +271,9 @@ int ssh_packet_hmac_verify(ssh_session session,
|
||||
hmac_final(ctx, hmacbuf, &hmaclen);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("received mac",mac,hmaclen);
|
||||
ssh_print_hexa("Computed mac",hmacbuf,hmaclen);
|
||||
ssh_print_hexa("seq",(unsigned char *)&seq,sizeof(uint32_t));
|
||||
ssh_log_hexdump("received mac",mac,hmaclen);
|
||||
ssh_log_hexdump("Computed mac",hmacbuf,hmaclen);
|
||||
ssh_log_hexdump("seq",(unsigned char *)&seq,sizeof(uint32_t));
|
||||
#endif
|
||||
if (secure_memcmp(mac, hmacbuf, hmaclen) == 0) {
|
||||
return 0;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
253
src/pki.c
253
src/pki.c
@@ -64,16 +64,22 @@
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/agent.h"
|
||||
|
||||
enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey) {
|
||||
if (strncmp(privkey, DSA_HEADER_BEGIN, strlen(DSA_HEADER_BEGIN)) == 0) {
|
||||
enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey)
|
||||
{
|
||||
char *start = NULL;
|
||||
|
||||
start = strstr(privkey, DSA_HEADER_BEGIN);
|
||||
if (start != NULL) {
|
||||
return SSH_KEYTYPE_DSS;
|
||||
}
|
||||
|
||||
if (strncmp(privkey, RSA_HEADER_BEGIN, strlen(RSA_HEADER_BEGIN)) == 0) {
|
||||
start = strstr(privkey, RSA_HEADER_BEGIN);
|
||||
if (start != NULL) {
|
||||
return SSH_KEYTYPE_RSA;
|
||||
}
|
||||
|
||||
if (strncmp(privkey, ECDSA_HEADER_BEGIN, strlen(ECDSA_HEADER_BEGIN)) == 0) {
|
||||
start = strstr(privkey, ECDSA_HEADER_BEGIN);
|
||||
if (start != 0) {
|
||||
/* We don't know what the curve is at this point, so we don't actually
|
||||
* know the type. We figure out the actual curve and fix things up in
|
||||
* pki_private_key_from_base64 */
|
||||
@@ -156,12 +162,19 @@ void ssh_key_clean (ssh_key key){
|
||||
}
|
||||
#endif
|
||||
if (key->ed25519_privkey != NULL){
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL implementation the private key is only the private
|
||||
* original seed. In the internal implementation the private key is the
|
||||
* concatenation of the original private seed with the public key.*/
|
||||
explicit_bzero(key->ed25519_privkey, ED25519_KEY_LEN);
|
||||
#else
|
||||
explicit_bzero(key->ed25519_privkey, sizeof(ed25519_privkey));
|
||||
#endif
|
||||
SAFE_FREE(key->ed25519_privkey);
|
||||
}
|
||||
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;
|
||||
@@ -292,7 +305,7 @@ const char *ssh_key_type_to_char(enum ssh_keytypes_e type) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum ssh_digest_e ssh_key_hash_from_name(const char *name)
|
||||
enum ssh_digest_e ssh_key_hash_from_name(const char *name)
|
||||
{
|
||||
if (name == NULL) {
|
||||
/* TODO we should rather fail */
|
||||
@@ -382,6 +395,19 @@ enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
|
||||
case SSH_KEYTYPE_DSS:
|
||||
return SSH_DIGEST_SHA1;
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
/* If we are talking to an old OpenSSH version which does not support
|
||||
* SHA2 in certificates */
|
||||
if ((session->openssh > 0) &&
|
||||
(session->openssh < SSH_VERSION_INT(7, 2, 0)))
|
||||
{
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"We are talking to an old OpenSSH (%x); "
|
||||
"returning SSH_DIGEST_SHA1",
|
||||
session->openssh);
|
||||
|
||||
return SSH_DIGEST_SHA1;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
if (ssh_key_algorithm_allowed(session, "rsa-sha2-512") &&
|
||||
(session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
|
||||
@@ -435,6 +461,21 @@ ssh_key_get_signature_algorithm(ssh_session session,
|
||||
{
|
||||
enum ssh_digest_e hash_type;
|
||||
|
||||
if (type == SSH_KEYTYPE_RSA_CERT01) {
|
||||
/* If we are talking to an old OpenSSH version which does not support
|
||||
* rsa-sha2-{256,512}-cert-v01@openssh.com */
|
||||
if ((session->openssh > 0) &&
|
||||
(session->openssh < SSH_VERSION_INT(7, 8, 0)))
|
||||
{
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"We are talking to an old OpenSSH (%x); "
|
||||
"using old cert format",
|
||||
session->openssh);
|
||||
|
||||
return "ssh-rsa-cert-v01@openssh.com";
|
||||
}
|
||||
}
|
||||
|
||||
hash_type = ssh_key_type_to_hash(session, type);
|
||||
|
||||
return ssh_key_signature_to_char(type, hash_type);
|
||||
@@ -645,7 +686,10 @@ void ssh_signature_free(ssh_signature sig)
|
||||
#endif
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
/* When using OpenSSL, the signature is stored in sig->raw_sig */
|
||||
SAFE_FREE(sig->ed25519_sig);
|
||||
#endif
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
@@ -661,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);
|
||||
}
|
||||
|
||||
@@ -690,7 +734,7 @@ int ssh_pki_import_privkey_base64(const char *b64_key,
|
||||
ssh_key *pkey)
|
||||
{
|
||||
ssh_key key;
|
||||
int cmp;
|
||||
char *openssh_header = NULL;
|
||||
|
||||
if (b64_key == NULL || pkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -705,9 +749,9 @@ int ssh_pki_import_privkey_base64(const char *b64_key,
|
||||
passphrase ? "true" : "false");
|
||||
|
||||
/* Test for OpenSSH key format first */
|
||||
cmp = strncmp(b64_key, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN));
|
||||
if (cmp == 0) {
|
||||
key = ssh_pki_openssh_privkey_import(b64_key,
|
||||
openssh_header = strstr(b64_key, OPENSSH_HEADER_BEGIN);
|
||||
if (openssh_header != NULL) {
|
||||
key = ssh_pki_openssh_privkey_import(openssh_header,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
@@ -773,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;
|
||||
}
|
||||
@@ -935,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);
|
||||
@@ -1030,24 +1074,24 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
|
||||
rc = pki_privkey_build_dss(key, p, q, g, pubkey, privkey);
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
|
||||
ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
|
||||
ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
|
||||
ssh_print_hexa("pubkey", ssh_string_data(pubkey),
|
||||
ssh_log_hexdump("p", ssh_string_data(p), ssh_string_len(p));
|
||||
ssh_log_hexdump("q", ssh_string_data(q), ssh_string_len(q));
|
||||
ssh_log_hexdump("g", ssh_string_data(g), ssh_string_len(g));
|
||||
ssh_log_hexdump("pubkey", ssh_string_data(pubkey),
|
||||
ssh_string_len(pubkey));
|
||||
ssh_print_hexa("privkey", ssh_string_data(privkey),
|
||||
ssh_log_hexdump("privkey", ssh_string_data(privkey),
|
||||
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;
|
||||
}
|
||||
@@ -1071,26 +1115,26 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
|
||||
rc = pki_privkey_build_rsa(key, n, e, d, iqmp, p, q);
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
|
||||
ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
|
||||
ssh_print_hexa("d", ssh_string_data(d), ssh_string_len(d));
|
||||
ssh_print_hexa("iqmp", ssh_string_data(iqmp),
|
||||
ssh_log_hexdump("n", ssh_string_data(n), ssh_string_len(n));
|
||||
ssh_log_hexdump("e", ssh_string_data(e), ssh_string_len(e));
|
||||
ssh_log_hexdump("d", ssh_string_data(d), ssh_string_len(d));
|
||||
ssh_log_hexdump("iqmp", ssh_string_data(iqmp),
|
||||
ssh_string_len(iqmp));
|
||||
ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
|
||||
ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
|
||||
ssh_log_hexdump("p", ssh_string_data(p), ssh_string_len(p));
|
||||
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;
|
||||
@@ -1114,16 +1158,16 @@ 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) {
|
||||
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;
|
||||
@@ -1143,8 +1187,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;
|
||||
@@ -1203,18 +1247,18 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
|
||||
rc = pki_pubkey_build_dss(key, p, q, g, pubkey);
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
|
||||
ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
|
||||
ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
|
||||
ssh_log_hexdump("p", ssh_string_data(p), ssh_string_len(p));
|
||||
ssh_log_hexdump("q", ssh_string_data(q), ssh_string_len(q));
|
||||
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;
|
||||
@@ -1234,13 +1278,13 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
|
||||
rc = pki_pubkey_build_rsa(key, e, n);
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
|
||||
ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
|
||||
ssh_log_hexdump("e", ssh_string_data(e), ssh_string_len(e));
|
||||
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;
|
||||
@@ -1264,14 +1308,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;
|
||||
@@ -1287,23 +1331,23 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
{
|
||||
ssh_string pubkey = ssh_buffer_get_ssh_string(buffer);
|
||||
if (ssh_string_len(pubkey) != ED25519_PK_LEN) {
|
||||
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_PK_LEN);
|
||||
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_PK_LEN);
|
||||
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:
|
||||
@@ -1405,7 +1449,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;
|
||||
}
|
||||
|
||||
@@ -1441,17 +1485,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;
|
||||
}
|
||||
@@ -1506,7 +1550,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);
|
||||
@@ -1514,12 +1558,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;
|
||||
}
|
||||
@@ -1837,7 +1881,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)
|
||||
@@ -1867,7 +1911,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)
|
||||
@@ -1885,7 +1929,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;
|
||||
}
|
||||
@@ -1985,7 +2029,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;
|
||||
}
|
||||
|
||||
@@ -2012,38 +2056,38 @@ 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);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
|
||||
*sig_blob = str;
|
||||
|
||||
@@ -2075,29 +2119,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;
|
||||
}
|
||||
@@ -2195,7 +2239,7 @@ int pki_key_check_hash_compatible(ssh_key key,
|
||||
int ssh_pki_signature_verify(ssh_session session,
|
||||
ssh_signature sig,
|
||||
const ssh_key key,
|
||||
unsigned char *input,
|
||||
const unsigned char *input,
|
||||
size_t input_len)
|
||||
{
|
||||
int rc;
|
||||
@@ -2225,7 +2269,7 @@ int ssh_pki_signature_verify(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = pki_signature_verify(session, sig, key, input, input_len);
|
||||
rc = pki_verify_data_signature(sig, key, input, input_len);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -2249,12 +2293,6 @@ ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519 ||
|
||||
privkey->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
return pki_do_sign_hash(privkey, input, input_len, SSH_DIGEST_AUTO);
|
||||
}
|
||||
|
||||
return pki_sign_data(privkey, hash_type, input, input_len);
|
||||
}
|
||||
|
||||
@@ -2328,8 +2366,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;
|
||||
}
|
||||
@@ -2346,6 +2384,9 @@ 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);
|
||||
@@ -2356,28 +2397,28 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session,
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -2385,7 +2426,8 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session,
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
const ssh_key privkey)
|
||||
const ssh_key privkey,
|
||||
const enum ssh_digest_e digest)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto = NULL;
|
||||
|
||||
@@ -2394,8 +2436,6 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
|
||||
ssh_buffer sign_input = NULL;
|
||||
|
||||
enum ssh_digest_e hash_type;
|
||||
|
||||
int rc;
|
||||
|
||||
if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) {
|
||||
@@ -2410,9 +2450,6 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the hash type from the key type */
|
||||
hash_type = ssh_key_type_to_hash(session, privkey->type);
|
||||
|
||||
/* Fill the input */
|
||||
sign_input = ssh_buffer_new();
|
||||
if (sign_input == NULL) {
|
||||
@@ -2432,7 +2469,7 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
sig = pki_do_sign(privkey,
|
||||
ssh_buffer_get(sign_input),
|
||||
ssh_buffer_get_len(sign_input),
|
||||
hash_type);
|
||||
digest);
|
||||
if (sig == NULL) {
|
||||
goto end;
|
||||
}
|
||||
@@ -2445,7 +2482,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;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
void *auth_data,
|
||||
bool private)
|
||||
{
|
||||
const char *ptr=text_key;
|
||||
const char *ptr = text_key;
|
||||
const char *end;
|
||||
char *base64;
|
||||
int cmp;
|
||||
@@ -250,7 +250,7 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
uint8_t padding;
|
||||
|
||||
cmp = strncmp(ptr, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN));
|
||||
if (cmp != 0){
|
||||
if (cmp != 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no header)");
|
||||
goto out;
|
||||
}
|
||||
@@ -259,15 +259,15 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
ptr++;
|
||||
}
|
||||
end = strstr(ptr, OPENSSH_HEADER_END);
|
||||
if (end == NULL){
|
||||
if (end == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no footer)");
|
||||
goto out;
|
||||
}
|
||||
base64 = malloc(end - ptr + 1);
|
||||
if (base64 == NULL){
|
||||
if (base64 == NULL) {
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; ptr < end; ptr++){
|
||||
for (i = 0; ptr < end; ptr++) {
|
||||
if (!isspace((int)ptr[0])) {
|
||||
base64[i] = ptr[0];
|
||||
i++;
|
||||
@@ -276,7 +276,7 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
base64[i] = '\0';
|
||||
buffer = base64_to_bin(base64);
|
||||
SAFE_FREE(base64);
|
||||
if (buffer == NULL){
|
||||
if (buffer == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (base64 error)");
|
||||
goto out;
|
||||
}
|
||||
@@ -289,21 +289,21 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
&nkeys,
|
||||
&pubkey0,
|
||||
&privkeys);
|
||||
if (rc == SSH_ERROR){
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (unpack error)");
|
||||
goto out;
|
||||
}
|
||||
cmp = strncmp(magic, OPENSSH_AUTH_MAGIC, strlen(OPENSSH_AUTH_MAGIC));
|
||||
if (cmp != 0){
|
||||
if (cmp != 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (bad magic)");
|
||||
goto out;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Opening OpenSSH private key: ciphername: %s, kdf: %s, nkeys: %d\n",
|
||||
"Opening OpenSSH private key: ciphername: %s, kdf: %s, nkeys: %d",
|
||||
ciphername,
|
||||
kdfname,
|
||||
nkeys);
|
||||
if (nkeys != 1){
|
||||
if (nkeys != 1) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Opening OpenSSH private key: only 1 key supported (%d available)", nkeys);
|
||||
goto out;
|
||||
}
|
||||
@@ -327,7 +327,7 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
kdfoptions,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
if (rc == SSH_ERROR){
|
||||
if (rc == SSH_ERROR) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -342,20 +342,20 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
ssh_string_len(privkeys));
|
||||
|
||||
rc = ssh_buffer_unpack(privkey_buffer, "dd", &checkint1, &checkint2);
|
||||
if (rc == SSH_ERROR || checkint1 != checkint2){
|
||||
if (rc == SSH_ERROR || checkint1 != checkint2) {
|
||||
SSH_LOG(SSH_LOG_WARN, "OpenSSH private key unpack error (correct password?)");
|
||||
goto out;
|
||||
}
|
||||
rc = pki_openssh_import_privkey_blob(privkey_buffer, &key);
|
||||
if (rc == SSH_ERROR){
|
||||
if (rc == SSH_ERROR) {
|
||||
goto out;
|
||||
}
|
||||
comment = ssh_buffer_get_ssh_string(privkey_buffer);
|
||||
SAFE_FREE(comment);
|
||||
/* verify that the remaining data is correct padding */
|
||||
for (i=1; ssh_buffer_get_len(privkey_buffer) > 0; ++i){
|
||||
for (i = 1; ssh_buffer_get_len(privkey_buffer) > 0; ++i) {
|
||||
ssh_buffer_get_u8(privkey_buffer, &padding);
|
||||
if (padding != i){
|
||||
if (padding != i) {
|
||||
ssh_key_free(key);
|
||||
key = NULL;
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid padding");
|
||||
@@ -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);
|
||||
@@ -415,12 +415,13 @@ static int pki_openssh_export_privkey_blob(const ssh_key privkey,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"sdPdP",
|
||||
"sdPdPP",
|
||||
privkey->type_c,
|
||||
(uint32_t)ED25519_PK_LEN,
|
||||
(size_t)ED25519_PK_LEN, privkey->ed25519_pubkey,
|
||||
(uint32_t)ED25519_SK_LEN,
|
||||
(size_t)ED25519_SK_LEN, privkey->ed25519_privkey);
|
||||
(uint32_t)ED25519_KEY_LEN,
|
||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey,
|
||||
(uint32_t)(2 * ED25519_KEY_LEN),
|
||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_privkey,
|
||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -439,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;
|
||||
@@ -619,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",
|
||||
@@ -700,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;
|
||||
}
|
||||
|
||||
@@ -708,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;
|
||||
|
||||
492
src/pki_crypto.c
492
src/pki_crypto.c
@@ -183,7 +183,7 @@ static ssh_string make_ecpoint_string(const EC_GROUP *g,
|
||||
ssh_string_len(s),
|
||||
NULL);
|
||||
if (len != ssh_string_len(s)) {
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -529,7 +529,7 @@ int pki_key_generate_rsa(ssh_key key, int parameter){
|
||||
|
||||
BN_free(e);
|
||||
|
||||
if (rc == -1 || key->rsa == NULL)
|
||||
if (rc <= 0 || key->rsa == NULL)
|
||||
return SSH_ERROR;
|
||||
return SSH_OK;
|
||||
}
|
||||
@@ -730,29 +730,58 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (key->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_set1_DSA(pkey, key->dsa);
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_set1_RSA(pkey, key->rsa);
|
||||
break;
|
||||
#ifdef HAVE_ECC
|
||||
case SSH_KEYTYPE_ECDSA_P256:
|
||||
case SSH_KEYTYPE_ECDSA_P384:
|
||||
case SSH_KEYTYPE_ECDSA_P521:
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
|
||||
break;
|
||||
#endif
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL, the input is the private key seed only, which means
|
||||
* the first half of the SSH private key (the second half is the
|
||||
* public key) */
|
||||
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
|
||||
(const uint8_t *)key->ed25519_privkey,
|
||||
ED25519_KEY_LEN);
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create ed25519 EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Mark the operation as successful as for the other key types */
|
||||
rc = 1;
|
||||
break;
|
||||
#else
|
||||
SSH_LOG(SSH_LOG_WARN, "PEM output not supported for key type ssh-ed25519");
|
||||
goto err;
|
||||
#endif
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
case SSH_KEYTYPE_ECDSA_P256_CERT01:
|
||||
@@ -821,7 +850,11 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
||||
BIO *mem = NULL;
|
||||
DSA *dsa = NULL;
|
||||
RSA *rsa = NULL;
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
uint8_t *ed25519 = NULL;
|
||||
#else
|
||||
ed25519_privkey *ed25519 = NULL;
|
||||
#endif
|
||||
ssh_key key = NULL;
|
||||
enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN;
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
@@ -861,7 +894,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Parsing private key: %s",
|
||||
ERR_error_string(ERR_get_error(),NULL));
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
type = SSH_KEYTYPE_DSS;
|
||||
break;
|
||||
@@ -871,7 +904,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Parsing private key: %s",
|
||||
ERR_error_string(ERR_get_error(),NULL));
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
type = SSH_KEYTYPE_RSA;
|
||||
break;
|
||||
@@ -882,7 +915,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Parsing private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* pki_privatekey_type_from_string always returns P256 for ECDSA
|
||||
@@ -894,6 +927,43 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
case EVP_PKEY_ED25519:
|
||||
{
|
||||
size_t key_len;
|
||||
int evp_rc = 0;
|
||||
|
||||
/* Get the key length */
|
||||
evp_rc = EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get ed25519 raw private key length: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (key_len != ED25519_KEY_LEN) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ed25519 = malloc(key_len);
|
||||
if (ed25519 == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Out of memory");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_get_raw_private_key(pkey, (uint8_t *)ed25519,
|
||||
&key_len);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get ed25519 raw private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto fail;
|
||||
}
|
||||
type = SSH_KEYTYPE_ED25519;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
EVP_PKEY_free(pkey);
|
||||
@@ -923,13 +993,16 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
|
||||
|
||||
return key;
|
||||
fail:
|
||||
EVP_PKEY_free(pkey);
|
||||
ssh_key_free(key);
|
||||
DSA_free(dsa);
|
||||
RSA_free(rsa);
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
EC_KEY_free(ecdsa);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
SAFE_FREE(ed25519);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1117,7 +1190,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
if (key->cert != NULL) {
|
||||
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
goto makestring;
|
||||
@@ -1125,14 +1198,14 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
|
||||
type_s = ssh_string_from_char(key->type_c);
|
||||
if (type_s == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
||||
ssh_string_free(type_s);
|
||||
SSH_STRING_FREE(type_s);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1175,16 +1248,16 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
}
|
||||
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
SSH_STRING_FREE(p);
|
||||
p = NULL;
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
SSH_STRING_FREE(g);
|
||||
g = NULL;
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
SSH_STRING_FREE(q);
|
||||
q = NULL;
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
n = NULL;
|
||||
|
||||
break;
|
||||
@@ -1211,10 +1284,10 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
}
|
||||
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
e = NULL;
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
n = NULL;
|
||||
|
||||
break;
|
||||
@@ -1231,21 +1304,21 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
|
||||
if (type_s == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
||||
ssh_string_free(type_s);
|
||||
SSH_STRING_FREE(type_s);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa),
|
||||
EC_KEY_get0_public_key(key->ecdsa));
|
||||
if (e == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1255,7 +1328,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
}
|
||||
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
e = NULL;
|
||||
|
||||
break;
|
||||
@@ -1275,23 +1348,23 @@ makestring:
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
return str;
|
||||
fail:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
ssh_string_burn(str);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
SSH_STRING_FREE(p);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
SSH_STRING_FREE(g);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
SSH_STRING_FREE(q);
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1358,8 +1431,8 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
|
||||
s_len - s_offset_in);
|
||||
|
||||
DSA_SIG_free(dsa_sig);
|
||||
ssh_string_free(r);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(r);
|
||||
SSH_STRING_FREE(s);
|
||||
|
||||
sig_blob = ssh_string_new(40);
|
||||
if (sig_blob == NULL) {
|
||||
@@ -1372,8 +1445,8 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
|
||||
|
||||
error:
|
||||
DSA_SIG_free(dsa_sig);
|
||||
ssh_string_free(r);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(r);
|
||||
SSH_STRING_FREE(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1445,18 +1518,18 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig)
|
||||
|
||||
ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
||||
|
||||
ssh_string_free(r);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(r);
|
||||
SSH_STRING_FREE(s);
|
||||
ECDSA_SIG_free(ecdsa_sig);
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
|
||||
return sig_blob;
|
||||
|
||||
error:
|
||||
ssh_string_free(r);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(r);
|
||||
SSH_STRING_FREE(s);
|
||||
ECDSA_SIG_free(ecdsa_sig);
|
||||
ssh_buffer_free(buf);
|
||||
SSH_BUFFER_FREE(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1473,7 +1546,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
sig_blob = ssh_string_copy(sig->raw_sig);
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
sig_blob = pki_ed25519_sig_to_blob(sig);
|
||||
sig_blob = pki_ed25519_signature_to_blob(sig);
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA_P256:
|
||||
case SSH_KEYTYPE_ECDSA_P384:
|
||||
@@ -1519,7 +1592,7 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey,
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len);
|
||||
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
|
||||
ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len);
|
||||
#endif
|
||||
|
||||
if (len == rsalen) {
|
||||
@@ -1541,6 +1614,10 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey,
|
||||
blob_padded_data = (char *) ssh_string_data(sig_blob_padded);
|
||||
blob_orig = (char *) ssh_string_data(sig_blob);
|
||||
|
||||
if (blob_padded_data == NULL || blob_orig == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* front-pad the buffer with zeroes */
|
||||
explicit_bzero(blob_padded_data, pad_len);
|
||||
/* fill the rest with the actual signature blob */
|
||||
@@ -1583,8 +1660,8 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("r", ssh_string_data(sig_blob), 20);
|
||||
ssh_print_hexa("s", (unsigned char *)ssh_string_data(sig_blob) + 20, 20);
|
||||
ssh_log_hexdump("r", ssh_string_data(sig_blob), 20);
|
||||
ssh_log_hexdump("s", (unsigned char *)ssh_string_data(sig_blob) + 20, 20);
|
||||
#endif
|
||||
|
||||
r = ssh_string_new(20);
|
||||
@@ -1595,7 +1672,7 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
||||
|
||||
pr = ssh_make_string_bn(r);
|
||||
ssh_string_burn(r);
|
||||
ssh_string_free(r);
|
||||
SSH_STRING_FREE(r);
|
||||
if (pr == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@@ -1608,7 +1685,7 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
||||
|
||||
ps = ssh_make_string_bn(s);
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
if (ps == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@@ -1695,12 +1772,12 @@ static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
|
||||
ssh_log_hexdump("r", ssh_string_data(r), ssh_string_len(r));
|
||||
#endif
|
||||
|
||||
pr = ssh_make_string_bn(r);
|
||||
ssh_string_burn(r);
|
||||
ssh_string_free(r);
|
||||
SSH_STRING_FREE(r);
|
||||
if (pr == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@@ -1714,7 +1791,7 @@ static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
||||
|
||||
if (rlen != 0) {
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Signature has remaining bytes in inner "
|
||||
"sigblob: %lu",
|
||||
@@ -1723,12 +1800,12 @@ static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey),
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
|
||||
ssh_log_hexdump("s", ssh_string_data(s), ssh_string_len(s));
|
||||
#endif
|
||||
|
||||
ps = ssh_make_string_bn(s);
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
if (ps == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@@ -1821,7 +1898,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
rc = pki_ed25519_sig_from_blob(sig, sig_blob);
|
||||
rc = pki_signature_from_ed25519_blob(sig, sig_blob);
|
||||
if (rc != SSH_OK){
|
||||
goto error;
|
||||
}
|
||||
@@ -1852,54 +1929,6 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pki_signature_verify(ssh_session session,
|
||||
const ssh_signature sig,
|
||||
const ssh_key key,
|
||||
const unsigned char *input,
|
||||
size_t input_len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (session == NULL || sig == NULL || key == NULL || input == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to "
|
||||
"pki_signature_verify()");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (ssh_key_type_plain(key->type) != sig->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Can not verify %s signature with %s key",
|
||||
sig->type_c,
|
||||
key->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Check if public key and hash type are compatible */
|
||||
rc = pki_key_check_hash_compatible(key, sig->hash_type);
|
||||
if (rc != SSH_OK) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* For ed25519 keys, verify using the input directly */
|
||||
if (key->type == SSH_KEYTYPE_ED25519 ||
|
||||
key->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
rc = pki_ed25519_verify(key, sig, input, input_len);
|
||||
} else {
|
||||
/* For the other key types, calculate the hash and verify the signature */
|
||||
rc = pki_verify_data_signature(sig, key, input, input_len);
|
||||
}
|
||||
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Signature verification error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static const EVP_MD *pki_digest_to_md(enum ssh_digest_e hash_type)
|
||||
{
|
||||
const EVP_MD *md = NULL;
|
||||
@@ -1918,6 +1947,8 @@ static const EVP_MD *pki_digest_to_md(enum ssh_digest_e hash_type)
|
||||
md = EVP_sha1();
|
||||
break;
|
||||
case SSH_DIGEST_AUTO:
|
||||
md = NULL;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d",
|
||||
hash_type);
|
||||
@@ -1931,12 +1962,6 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(key->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
@@ -1944,6 +1969,12 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->dsa");
|
||||
goto error;
|
||||
}
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_PKEY_set1_DSA(pkey, key->dsa);
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
@@ -1953,6 +1984,12 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->rsa");
|
||||
goto error;
|
||||
}
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_PKEY_set1_RSA(pkey, key->rsa);
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA_P256:
|
||||
@@ -1966,12 +2003,46 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->ecdsa");
|
||||
goto error;
|
||||
}
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
|
||||
break;
|
||||
# endif
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
/* Not supported yet. This type requires the use of EVP_DigestSign*()
|
||||
* API and ECX keys. There is no EVP_set1_ECX_KEY() or equivalent yet. */
|
||||
case SSH_KEYTYPE_ED25519_CERT01:
|
||||
# if defined(HAVE_OPENSSL_ED25519)
|
||||
if (ssh_key_is_private(key)) {
|
||||
if (key->ed25519_privkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_privkey");
|
||||
goto error;
|
||||
}
|
||||
/* In OpenSSL, the input is the private key seed only, which means
|
||||
* the first half of the SSH private key (the second half is the
|
||||
* public key). Both keys have the same length (32 bytes) */
|
||||
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
|
||||
(const uint8_t *)key->ed25519_privkey,
|
||||
ED25519_KEY_LEN);
|
||||
} else {
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_pubkey");
|
||||
goto error;
|
||||
}
|
||||
pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
|
||||
(const uint8_t *)key->ed25519_pubkey,
|
||||
ED25519_KEY_LEN);
|
||||
}
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create ed25519 EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown private key algorithm for type: %d",
|
||||
@@ -2009,7 +2080,7 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
||||
unsigned char *raw_sig_data = NULL;
|
||||
unsigned int raw_sig_len;
|
||||
size_t raw_sig_len;
|
||||
|
||||
ssh_signature sig = NULL;
|
||||
|
||||
@@ -2027,10 +2098,20 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519 ||
|
||||
privkey->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
return pki_do_sign_hash(privkey, input, input_len, hash_type);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set hash algorithm to be used */
|
||||
md = pki_digest_to_md(hash_type);
|
||||
if (md == NULL) {
|
||||
return NULL;
|
||||
if (hash_type != SSH_DIGEST_AUTO) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup private key EVP_PKEY */
|
||||
@@ -2040,7 +2121,7 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
}
|
||||
|
||||
/* Allocate buffer for signature */
|
||||
raw_sig_len = EVP_PKEY_size(pkey);
|
||||
raw_sig_len = (size_t)EVP_PKEY_size(pkey);
|
||||
raw_sig_data = (unsigned char *)malloc(raw_sig_len);
|
||||
if (raw_sig_data == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
@@ -2055,26 +2136,42 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
}
|
||||
|
||||
/* Sign the data */
|
||||
rc = EVP_SignInit_ex(ctx, md, NULL);
|
||||
if (!rc){
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_SignInit() failed");
|
||||
rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey);
|
||||
if (rc != 1){
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"EVP_DigestSignInit() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_SignUpdate(ctx, input, input_len);
|
||||
if (!rc) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_SignUpdate() failed");
|
||||
#ifdef HAVE_OPENSSL_EVP_DIGESTSIGN
|
||||
rc = EVP_DigestSign(ctx, raw_sig_data, &raw_sig_len, input, input_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"EVP_DigestSign() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
rc = EVP_DigestSignUpdate(ctx, input, input_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"EVP_DigestSignUpdate() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_SignFinal(ctx, raw_sig_data, &raw_sig_len, pkey);
|
||||
if (!rc) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_SignFinal() failed");
|
||||
rc = EVP_DigestSignFinal(ctx, raw_sig_data, &raw_sig_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"EVP_DigestSignFinal() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Generated signature", raw_sig_data, raw_sig_len);
|
||||
ssh_log_hexdump("Generated signature", raw_sig_data, raw_sig_len);
|
||||
#endif
|
||||
|
||||
/* Allocate and fill output signature */
|
||||
@@ -2144,7 +2241,11 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
int evp_rc;
|
||||
|
||||
if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL ||
|
||||
signature == NULL || signature->raw_sig == NULL)
|
||||
signature == NULL || (signature->raw_sig == NULL
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
&& signature->ed25519_sig == NULL
|
||||
#endif
|
||||
))
|
||||
{
|
||||
SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to "
|
||||
"pki_verify_data_signature()");
|
||||
@@ -2157,6 +2258,14 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifndef HAVE_OPENSSL_ED25519
|
||||
if (pubkey->type == SSH_KEYTYPE_ED25519 ||
|
||||
pubkey->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
return pki_ed25519_verify(pubkey, signature, input, input_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the signature to be verified */
|
||||
raw_sig_data = ssh_string_data(signature->raw_sig);
|
||||
raw_sig_len = ssh_string_len(signature->raw_sig);
|
||||
@@ -2167,7 +2276,9 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
/* Set hash algorithm to be used */
|
||||
md = pki_digest_to_md(signature->hash_type);
|
||||
if (md == NULL) {
|
||||
return SSH_ERROR;
|
||||
if (signature->hash_type != SSH_DIGEST_AUTO) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup public key EVP_PKEY */
|
||||
@@ -2179,33 +2290,42 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
/* Create the context */
|
||||
ctx = EVP_MD_CTX_create();
|
||||
if (ctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create EVP_MD_CTX: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Verify the signature */
|
||||
evp_rc = EVP_VerifyInit_ex(ctx, md, NULL);
|
||||
if (!evp_rc){
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_SignInit() failed");
|
||||
evp_rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey);
|
||||
if (evp_rc != 1){
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"EVP_DigestVerifyInit() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
evp_rc = EVP_VerifyUpdate(ctx, input, input_len);
|
||||
if (!evp_rc) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_SignUpdate() failed");
|
||||
#ifdef HAVE_OPENSSL_EVP_DIGESTVERIFY
|
||||
evp_rc = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len);
|
||||
#else
|
||||
evp_rc = EVP_DigestVerifyUpdate(ctx, input, input_len);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"EVP_DigestVerifyUpdate() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
evp_rc = EVP_VerifyFinal(ctx, raw_sig_data, raw_sig_len, pkey);
|
||||
if (evp_rc < 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_SignFinal() failed");
|
||||
rc = SSH_ERROR;
|
||||
} else if (evp_rc == 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Signature invalid");
|
||||
rc = SSH_ERROR;
|
||||
} else if (evp_rc == 1) {
|
||||
evp_rc = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len);
|
||||
#endif
|
||||
if (evp_rc == 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Signature valid");
|
||||
rc = SSH_OK;
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Signature invalid: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -2218,6 +2338,92 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
int pki_key_generate_ed25519(ssh_key key)
|
||||
{
|
||||
int evp_rc;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t privkey_len = ED25519_KEY_LEN;
|
||||
size_t pubkey_len = ED25519_KEY_LEN;
|
||||
|
||||
if (key == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create ed25519 EVP_PKEY_CTX: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_keygen_init(pctx);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize ed25519 key generation: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_keygen(pctx, &pkey);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate ed25519 key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
key->ed25519_privkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_privkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to allocate memory for ed25519 private key");
|
||||
goto error;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to allocate memory for ed25519 public key");
|
||||
goto error;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_get_raw_private_key(pkey, (uint8_t *)key->ed25519_privkey,
|
||||
&privkey_len);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get ed25519 raw private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
evp_rc = EVP_PKEY_get_raw_public_key(pkey, (uint8_t *)key->ed25519_pubkey,
|
||||
&pubkey_len);
|
||||
if (evp_rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get ed25519 raw public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto error;
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_OK;
|
||||
|
||||
error:
|
||||
if (pctx != NULL) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
}
|
||||
if (pkey != NULL) {
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
SAFE_FREE(key->ed25519_privkey);
|
||||
SAFE_FREE(key->ed25519_pubkey);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#else
|
||||
ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
@@ -2250,4 +2456,6 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
|
||||
return sig;
|
||||
}
|
||||
#endif /* HAVE_OPENSSL_ED25519 */
|
||||
|
||||
#endif /* _PKI_CRYPTO_H */
|
||||
|
||||
@@ -56,28 +56,6 @@ error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey)
|
||||
{
|
||||
if (ssh_string_len(pubkey) != ED25519_PK_LEN ||
|
||||
ssh_string_len(privkey) != ED25519_SK_LEN) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
key->ed25519_privkey = malloc(ED25519_SK_LEN);
|
||||
key->ed25519_pubkey = malloc(ED25519_PK_LEN);
|
||||
if (key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey),
|
||||
ED25519_SK_LEN);
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey),
|
||||
ED25519_PK_LEN);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int pki_ed25519_sign(const ssh_key privkey,
|
||||
ssh_signature sig,
|
||||
const unsigned char *hash,
|
||||
@@ -170,165 +148,3 @@ error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Compare ed25519 keys if they are equal.
|
||||
*
|
||||
* @param[in] k1 The first key to compare.
|
||||
*
|
||||
* @param[in] k2 The second key to compare.
|
||||
*
|
||||
* @param[in] what What part or type of the key do you want to compare.
|
||||
*
|
||||
* @return 0 if equal, 1 if not.
|
||||
*/
|
||||
int pki_ed25519_key_cmp(const ssh_key k1,
|
||||
const ssh_key k2,
|
||||
enum ssh_keycmp_e what)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
switch(what) {
|
||||
case SSH_KEY_CMP_PRIVATE:
|
||||
if (k1->ed25519_privkey == NULL || k2->ed25519_privkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, ED25519_SK_LEN);
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case SSH_KEY_CMP_PUBLIC:
|
||||
if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_PK_LEN);
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief duplicate an ed25519 key
|
||||
*
|
||||
* @param[out\ new preinitialized output ssh_ke
|
||||
*
|
||||
* @param[in] key key to copy
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_key_dup(ssh_key new, const ssh_key key)
|
||||
{
|
||||
if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (key->ed25519_privkey != NULL) {
|
||||
new->ed25519_privkey = malloc(ED25519_SK_LEN);
|
||||
if (new->ed25519_privkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_SK_LEN);
|
||||
}
|
||||
|
||||
if (key->ed25519_pubkey != NULL) {
|
||||
new->ed25519_pubkey = malloc(ED25519_PK_LEN);
|
||||
if (new->ed25519_pubkey == NULL) {
|
||||
SAFE_FREE(new->ed25519_privkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_PK_LEN);
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief outputs an ed25519 public key in a blob buffer.
|
||||
*
|
||||
* @param[out] buffer output buffer
|
||||
*
|
||||
* @param[in] key key to output
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (key->ed25519_pubkey == NULL){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"dP",
|
||||
(uint32_t)ED25519_PK_LEN,
|
||||
(size_t)ED25519_PK_LEN, key->ed25519_pubkey);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief output a signature blob from an ed25519 signature
|
||||
*
|
||||
* @param[in] sig signature to convert
|
||||
*
|
||||
* @return Signature blob in SSH string, or NULL on error
|
||||
*/
|
||||
ssh_string pki_ed25519_sig_to_blob(ssh_signature sig)
|
||||
{
|
||||
ssh_string sig_blob;
|
||||
|
||||
if (sig->ed25519_sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig_blob = ssh_string_new(ED25519_SIG_LEN);
|
||||
if (sig_blob == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN);
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Convert a signature blob in an ed25519 signature.
|
||||
*
|
||||
* @param[out] sig a preinitialized signature
|
||||
*
|
||||
* @param[in] sig_blob a signature blob
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_sig_from_blob(ssh_signature sig, ssh_string sig_blob)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = ssh_string_len(sig_blob);
|
||||
if (len != ED25519_SIG_LEN){
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid ssh-ed25519 signature len: %zu", len);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
sig->ed25519_sig = malloc(ED25519_SIG_LEN);
|
||||
if (sig->ed25519_sig == NULL){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
memcpy(sig->ed25519_sig, ssh_string_data(sig_blob), ED25519_SIG_LEN);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
280
src/pki_ed25519_common.c
Normal file
280
src/pki_ed25519_common.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* pki_ed25519_common.c - Common ed25519 functions
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2014 by Aris Adamantiadis
|
||||
*
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libssh/pki.h"
|
||||
#include "libssh/pki_priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey)
|
||||
{
|
||||
if (ssh_string_len(pubkey) != ED25519_KEY_LEN ||
|
||||
ssh_string_len(privkey) != (2 * ED25519_KEY_LEN))
|
||||
{
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL implementation, the private key is the original private seed,
|
||||
* without the public key. */
|
||||
key->ed25519_privkey = malloc(ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation of
|
||||
* the private seed with the public key. */
|
||||
key->ed25519_privkey = malloc(2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (key->ed25519_privkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey),
|
||||
ED25519_KEY_LEN);
|
||||
#else
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey),
|
||||
2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey),
|
||||
ED25519_KEY_LEN);
|
||||
|
||||
return SSH_OK;
|
||||
|
||||
error:
|
||||
SAFE_FREE(key->ed25519_privkey);
|
||||
SAFE_FREE(key->ed25519_pubkey);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Compare ed25519 keys if they are equal.
|
||||
*
|
||||
* @param[in] k1 The first key to compare.
|
||||
*
|
||||
* @param[in] k2 The second key to compare.
|
||||
*
|
||||
* @param[in] what What part or type of the key do you want to compare.
|
||||
*
|
||||
* @return 0 if equal, 1 if not.
|
||||
*/
|
||||
int pki_ed25519_key_cmp(const ssh_key k1,
|
||||
const ssh_key k2,
|
||||
enum ssh_keycmp_e what)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
switch(what) {
|
||||
case SSH_KEY_CMP_PRIVATE:
|
||||
if (k1->ed25519_privkey == NULL || k2->ed25519_privkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL implementation, the private key is the original private
|
||||
* seed, without the public key. */
|
||||
cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation
|
||||
* of the private seed with the public key. */
|
||||
cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey,
|
||||
2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case SSH_KEY_CMP_PUBLIC:
|
||||
if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_KEY_LEN);
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Duplicate an Ed25519 key
|
||||
*
|
||||
* @param[out] new Pre-initialized ssh_key structure
|
||||
*
|
||||
* @param[in] key Key to copy
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_key_dup(ssh_key new, const ssh_key key)
|
||||
{
|
||||
if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (key->ed25519_privkey != NULL) {
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* In OpenSSL implementation, the private key is the original private
|
||||
* seed, without the public key. */
|
||||
new->ed25519_privkey = malloc(ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation
|
||||
* of the private seed with the public key. */
|
||||
new->ed25519_privkey = malloc(2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (new->ed25519_privkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_KEY_LEN);
|
||||
#else
|
||||
memcpy(new->ed25519_privkey, key->ed25519_privkey, 2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (key->ed25519_pubkey != NULL) {
|
||||
new->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (new->ed25519_pubkey == NULL) {
|
||||
SAFE_FREE(new->ed25519_privkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_KEY_LEN);
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Outputs an Ed25519 public key in a blob buffer.
|
||||
*
|
||||
* @param[out] buffer Output buffer
|
||||
*
|
||||
* @param[in] key Key to output
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (key->ed25519_pubkey == NULL){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"dP",
|
||||
(uint32_t)ED25519_KEY_LEN,
|
||||
(size_t)ED25519_KEY_LEN, key->ed25519_pubkey);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief output a signature blob from an ed25519 signature
|
||||
*
|
||||
* @param[in] sig signature to convert
|
||||
*
|
||||
* @return Signature blob in SSH string, or NULL on error
|
||||
*/
|
||||
ssh_string pki_ed25519_signature_to_blob(ssh_signature sig)
|
||||
{
|
||||
ssh_string sig_blob;
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
/* When using the OpenSSL implementation, the signature is stored in raw_sig
|
||||
* which is shared by all algorithms.*/
|
||||
if (sig->raw_sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
/* When using the internal implementation, the signature is stored in an
|
||||
* algorithm specific field. */
|
||||
if (sig->ed25519_sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
sig_blob = ssh_string_new(ED25519_SIG_LEN);
|
||||
if (sig_blob == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig),
|
||||
ssh_string_len(sig->raw_sig));
|
||||
#else
|
||||
ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN);
|
||||
#endif
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Convert a signature blob in an ed25519 signature.
|
||||
*
|
||||
* @param[out] sig a preinitialized signature
|
||||
*
|
||||
* @param[in] sig_blob a signature blob
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = ssh_string_len(sig_blob);
|
||||
if (len != ED25519_SIG_LEN){
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid ssh-ed25519 signature len: %zu", len);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ED25519
|
||||
sig->raw_sig = ssh_string_copy(sig_blob);
|
||||
#else
|
||||
sig->ed25519_sig = malloc(ED25519_SIG_LEN);
|
||||
if (sig->ed25519_sig == NULL){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(sig->ed25519_sig, ssh_string_data(sig_blob), ED25519_SIG_LEN);
|
||||
#endif
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
268
src/pki_gcrypt.c
268
src/pki_gcrypt.c
@@ -139,7 +139,7 @@ static ssh_string asn1_get(ssh_buffer buffer, unsigned char want) {
|
||||
}
|
||||
|
||||
if (ssh_buffer_get_data(buffer, ssh_string_data(str), size) == 0) {
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -177,14 +177,14 @@ static ssh_string asn1_get_bit_string(ssh_buffer buffer)
|
||||
|
||||
len = ssh_buffer_get_data(buffer, &unused, 1);
|
||||
if (len == 0) {
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (unused == 0) {
|
||||
len = ssh_buffer_get_data(buffer, ssh_string_data(str), size);
|
||||
if (len == 0) {
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
@@ -197,7 +197,7 @@ static ssh_string asn1_get_bit_string(ssh_buffer buffer)
|
||||
|
||||
len = ssh_buffer_get_data(buffer, &c, 1);
|
||||
if (len == 0) {
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
*p = last | (c >> unused);
|
||||
@@ -434,7 +434,7 @@ static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type,
|
||||
header_end = ECDSA_HEADER_END;
|
||||
break;
|
||||
default:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -450,14 +450,14 @@ static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type,
|
||||
get_next_line(p, len);
|
||||
}
|
||||
if (eol) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* skip header line */
|
||||
get_next_line(p, len);
|
||||
if (eol) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@ static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type,
|
||||
/* skip line */
|
||||
get_next_line(p, len);
|
||||
if (eol) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -474,24 +474,24 @@ static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type,
|
||||
len = 0;
|
||||
get_next_line(p, len);
|
||||
if (eol) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
if (privatekey_dek_header(p, len, &algo, &mode, &key_len,
|
||||
&iv, &iv_len) < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
SAFE_FREE(iv);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
SAFE_FREE(iv);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if(len > 0) {
|
||||
if (ssh_buffer_add_data(buffer, p, len) < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
SAFE_FREE(iv);
|
||||
return NULL;
|
||||
}
|
||||
@@ -501,7 +501,7 @@ static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type,
|
||||
get_next_line(p, len);
|
||||
while(!eol && strncmp(p, header_end, header_end_size) != 0) {
|
||||
if (ssh_buffer_add_data(buffer, p, len) < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
SAFE_FREE(iv);
|
||||
return NULL;
|
||||
}
|
||||
@@ -509,19 +509,19 @@ static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type,
|
||||
}
|
||||
|
||||
if (eol || strncmp(p, header_end, header_end_size) != 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
SAFE_FREE(iv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ssh_buffer_add_data(buffer, "\0", 1) < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
SAFE_FREE(iv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = base64_to_bin(ssh_buffer_get(buffer));
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
if (out == NULL) {
|
||||
SAFE_FREE(iv);
|
||||
return NULL;
|
||||
@@ -530,7 +530,7 @@ static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type,
|
||||
if (algo) {
|
||||
if (privatekey_decrypt(algo, mode, key_len, iv, iv_len, out,
|
||||
cb, userdata, desc) < 0) {
|
||||
ssh_buffer_free(out);
|
||||
SSH_BUFFER_FREE(out);
|
||||
SAFE_FREE(iv);
|
||||
return NULL;
|
||||
}
|
||||
@@ -561,20 +561,20 @@ static int b64decode_rsa_privatekey(const char *pkey, gcry_sexp_t *r,
|
||||
}
|
||||
|
||||
if (!asn1_check_sequence(buffer)) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
v = asn1_get_int(buffer);
|
||||
if (v == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = ssh_string_data(v);
|
||||
if (ssh_string_len(v) != 1 || data[0] != 0) {
|
||||
ssh_string_free(v);
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_STRING_FREE(v);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -587,7 +587,7 @@ static int b64decode_rsa_privatekey(const char *pkey, gcry_sexp_t *r,
|
||||
unused2 = asn1_get_int(buffer);
|
||||
u = asn1_get_int(buffer);
|
||||
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
if (n == NULL || e == NULL || d == NULL || p == NULL || q == NULL ||
|
||||
unused1 == NULL || unused2 == NULL|| u == NULL) {
|
||||
@@ -608,20 +608,20 @@ static int b64decode_rsa_privatekey(const char *pkey, gcry_sexp_t *r,
|
||||
|
||||
error:
|
||||
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(p);
|
||||
ssh_string_free(p);
|
||||
SSH_STRING_FREE(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
ssh_string_free(unused1);
|
||||
ssh_string_free(unused2);
|
||||
SSH_STRING_FREE(q);
|
||||
SSH_STRING_FREE(unused1);
|
||||
SSH_STRING_FREE(unused2);
|
||||
ssh_string_burn(u);
|
||||
ssh_string_free(u);
|
||||
ssh_string_free(v);
|
||||
SSH_STRING_FREE(u);
|
||||
SSH_STRING_FREE(v);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -644,20 +644,20 @@ static int b64decode_dsa_privatekey(const char *pkey, gcry_sexp_t *r, ssh_auth_c
|
||||
}
|
||||
|
||||
if (!asn1_check_sequence(buffer)) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
v = asn1_get_int(buffer);
|
||||
if (v == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = ssh_string_data(v);
|
||||
if (ssh_string_len(v) != 1 || data[0] != 0) {
|
||||
ssh_string_free(v);
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_STRING_FREE(v);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -666,7 +666,7 @@ static int b64decode_dsa_privatekey(const char *pkey, gcry_sexp_t *r, ssh_auth_c
|
||||
g = asn1_get_int(buffer);
|
||||
y = asn1_get_int(buffer);
|
||||
x = asn1_get_int(buffer);
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
if (p == NULL || q == NULL || g == NULL || y == NULL || x == NULL) {
|
||||
rc = 0;
|
||||
@@ -685,16 +685,16 @@ static int b64decode_dsa_privatekey(const char *pkey, gcry_sexp_t *r, ssh_auth_c
|
||||
|
||||
error:
|
||||
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(y);
|
||||
ssh_string_free(y);
|
||||
SSH_STRING_FREE(y);
|
||||
ssh_string_burn(x);
|
||||
ssh_string_free(x);
|
||||
ssh_string_free(v);
|
||||
SSH_STRING_FREE(x);
|
||||
SSH_STRING_FREE(v);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -916,13 +916,13 @@ static int b64decode_ecdsa_privatekey(const char *pkey, gcry_sexp_t *r,
|
||||
}
|
||||
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
ssh_string_free(v);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
SSH_STRING_FREE(v);
|
||||
ssh_string_burn(d);
|
||||
ssh_string_free(d);
|
||||
ssh_string_free(oi);
|
||||
SSH_STRING_FREE(d);
|
||||
SSH_STRING_FREE(oi);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
SSH_STRING_FREE(q);
|
||||
|
||||
return valid;
|
||||
}
|
||||
@@ -1560,7 +1560,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
if (key->cert != NULL) {
|
||||
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
goto makestring;
|
||||
@@ -1568,14 +1568,14 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
|
||||
type_s = ssh_string_from_char(key->type_c);
|
||||
if (type_s == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
||||
ssh_string_free(type_s);
|
||||
SSH_STRING_FREE(type_s);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1631,13 +1631,13 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
}
|
||||
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
SSH_STRING_FREE(p);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
SSH_STRING_FREE(g);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
SSH_STRING_FREE(q);
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
@@ -1667,9 +1667,9 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
}
|
||||
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
@@ -1685,21 +1685,21 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
type_s = ssh_string_from_char(
|
||||
pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
|
||||
if (type_s == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
||||
ssh_string_free(type_s);
|
||||
SSH_STRING_FREE(type_s);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e = ssh_sexp_extract_mpi(key->ecdsa, "q", GCRYMPI_FMT_STD,
|
||||
GCRYMPI_FMT_STD);
|
||||
if (e == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1709,7 +1709,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
}
|
||||
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
e = NULL;
|
||||
break;
|
||||
#endif
|
||||
@@ -1729,23 +1729,23 @@ makestring:
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
|
||||
return str;
|
||||
fail:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
ssh_string_burn(str);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
SSH_STRING_FREE(p);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
SSH_STRING_FREE(g);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
SSH_STRING_FREE(q);
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1832,7 +1832,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
gcry_sexp_release(sexp);
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
sig_blob = pki_ed25519_sig_to_blob(sig);
|
||||
sig_blob = pki_ed25519_signature_to_blob(sig);
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA_P256:
|
||||
case SSH_KEYTYPE_ECDSA_P384:
|
||||
@@ -1852,40 +1852,40 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
R = ssh_sexp_extract_mpi(sig->ecdsa_sig, "r",
|
||||
GCRYMPI_FMT_USG, GCRYMPI_FMT_STD);
|
||||
if (R == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(b, R);
|
||||
ssh_string_free(R);
|
||||
SSH_STRING_FREE(R);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
S = ssh_sexp_extract_mpi(sig->ecdsa_sig, "s",
|
||||
GCRYMPI_FMT_USG, GCRYMPI_FMT_STD);
|
||||
if (S == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(b, S);
|
||||
ssh_string_free(S);
|
||||
SSH_STRING_FREE(S);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig_blob = ssh_string_new(ssh_buffer_get_len(b));
|
||||
if (sig_blob == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh_string_fill(sig_blob,
|
||||
ssh_buffer_get(b), ssh_buffer_get_len(b));
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1945,7 +1945,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"DSA signature len: %lu",
|
||||
(unsigned long)len);
|
||||
ssh_print_hexa("DSA signature", ssh_string_data(sig_blob), len);
|
||||
ssh_log_hexdump("DSA signature", ssh_string_data(sig_blob), len);
|
||||
#endif
|
||||
|
||||
err = gcry_sexp_build(&sig->dsa_sig,
|
||||
@@ -1980,7 +1980,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
SSH_LOG(SSH_LOG_DEBUG, "RSA signature len: %lu", (unsigned long)len);
|
||||
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
|
||||
ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len);
|
||||
#endif
|
||||
|
||||
err = gcry_sexp_build(&sig->rsa_sig,
|
||||
@@ -1994,7 +1994,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
rc = pki_ed25519_sig_from_blob(sig, sig_blob);
|
||||
rc = pki_signature_from_ed25519_blob(sig, sig_blob);
|
||||
if (rc != SSH_OK){
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
@@ -2019,24 +2019,24 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
ssh_string_data(sig_blob),
|
||||
ssh_string_len(sig_blob));
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = ssh_buffer_get_ssh_string(b);
|
||||
if (r == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = ssh_buffer_get_ssh_string(b);
|
||||
rlen = ssh_buffer_get_len(b);
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
if (s == NULL) {
|
||||
ssh_string_burn(r);
|
||||
ssh_string_free(r);
|
||||
SSH_STRING_FREE(r);
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
@@ -2047,16 +2047,16 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
"sigblob: %lu",
|
||||
(unsigned long)rlen);
|
||||
ssh_string_burn(r);
|
||||
ssh_string_free(r);
|
||||
SSH_STRING_FREE(r);
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
|
||||
ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
|
||||
ssh_log_hexdump("r", ssh_string_data(r), ssh_string_len(r));
|
||||
ssh_log_hexdump("s", ssh_string_data(s), ssh_string_len(s));
|
||||
#endif
|
||||
|
||||
err = gcry_sexp_build(&sig->ecdsa_sig,
|
||||
@@ -2067,9 +2067,9 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
ssh_string_len(s),
|
||||
ssh_string_data(s));
|
||||
ssh_string_burn(r);
|
||||
ssh_string_free(r);
|
||||
SSH_STRING_FREE(r);
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
if (err) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
@@ -2087,54 +2087,6 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
return sig;
|
||||
}
|
||||
|
||||
int pki_signature_verify(ssh_session session,
|
||||
const ssh_signature sig,
|
||||
const ssh_key key,
|
||||
const unsigned char *input,
|
||||
size_t input_len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (session == NULL || sig == NULL || key == NULL || input == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to "
|
||||
"pki_signature_verify()");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (ssh_key_type_plain(key->type) != sig->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Can not verify %s signature with %s key",
|
||||
sig->type_c,
|
||||
key->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Check if public key and hash type are compatible */
|
||||
rc = pki_key_check_hash_compatible(key, sig->hash_type);
|
||||
if (rc != SSH_OK) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* For ed25519 keys, verify using the input directly */
|
||||
if (key->type == SSH_KEYTYPE_ED25519 ||
|
||||
key->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
rc = pki_ed25519_verify(key, sig, input, input_len);
|
||||
} else {
|
||||
/* For the other key types, calculate the hash and verify the signature */
|
||||
rc = pki_verify_data_signature(sig, key, input, input_len);
|
||||
}
|
||||
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Signature verification error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
@@ -2268,6 +2220,7 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
size_t input_len)
|
||||
{
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
const unsigned char *sign_input = NULL;
|
||||
uint32_t hlen = 0;
|
||||
int rc;
|
||||
|
||||
@@ -2287,27 +2240,38 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(input, input_len, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
sign_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA384:
|
||||
sha384(input, input_len, hash);
|
||||
hlen = SHA384_DIGEST_LEN;
|
||||
sign_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(input, input_len, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
sign_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
sha1(input, input_len, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
sign_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_AUTO:
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519) {
|
||||
/* SSH_DIGEST_AUTO should only be used with ed25519 */
|
||||
sign_input = input;
|
||||
hlen = input_len;
|
||||
break;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d",
|
||||
hash_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pki_do_sign_hash(privkey, hash, hlen, hash_type);
|
||||
return pki_do_sign_hash(privkey, sign_input, hlen, hash_type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2336,6 +2300,8 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
unsigned char *hash = ghash + 1;
|
||||
uint32_t hlen = 0;
|
||||
|
||||
const unsigned char *verify_input = NULL;
|
||||
|
||||
int rc;
|
||||
|
||||
if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL ||
|
||||
@@ -2357,23 +2323,35 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
sha256(input, input_len, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
hash_type = "sha256";
|
||||
verify_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA384:
|
||||
sha384(input, input_len, hash);
|
||||
hlen = SHA384_DIGEST_LEN;
|
||||
hash_type = "sha384";
|
||||
verify_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(input, input_len, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
hash_type = "sha512";
|
||||
verify_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
sha1(input, input_len, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
hash_type = "sha1";
|
||||
verify_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_AUTO:
|
||||
if (pubkey->type == SSH_KEYTYPE_ED25519 ||
|
||||
pubkey->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
verify_input = input;
|
||||
hlen = input_len;
|
||||
break;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->hash_type: %d", signature->hash_type);
|
||||
return SSH_ERROR;
|
||||
@@ -2461,6 +2439,14 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
case SSH_KEYTYPE_ED25519_CERT01:
|
||||
rc = pki_ed25519_verify(pubkey, signature, verify_input, hlen);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "ED25519 error: Signature invalid");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
default:
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "libssh/pki_priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/bignum.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
#define MAX_PASSPHRASE_SIZE 1024
|
||||
#define MAX_KEY_SIZE 32
|
||||
@@ -595,7 +596,7 @@ ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const
|
||||
rc = mbedtls_ecp_point_write_binary(g, p, MBEDTLS_ECP_PF_UNCOMPRESSED,
|
||||
&len, ssh_string_data(s), ssh_string_len(s));
|
||||
if (rc == MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) {
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
|
||||
s = ssh_string_new(len);
|
||||
if (s == NULL) {
|
||||
@@ -607,12 +608,12 @@ ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len != ssh_string_len(s)) {
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -652,7 +653,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
if (key->cert != NULL) {
|
||||
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -661,14 +662,14 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
|
||||
type_s = ssh_string_from_char(key->type_c);
|
||||
if (type_s == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
||||
ssh_string_free(type_s);
|
||||
SSH_STRING_FREE(type_s);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -676,7 +677,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
case SSH_KEYTYPE_RSA: {
|
||||
mbedtls_rsa_context *rsa;
|
||||
if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) == 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -701,10 +702,10 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
}
|
||||
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
e = NULL;
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
n = NULL;
|
||||
|
||||
break;
|
||||
@@ -715,21 +716,21 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
type_s =
|
||||
ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
|
||||
if (type_s == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
||||
ssh_string_free(type_s);
|
||||
SSH_STRING_FREE(type_s);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e = make_ecpoint_string(&key->ecdsa->grp, &key->ecdsa->Q);
|
||||
|
||||
if (e == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -739,7 +740,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
}
|
||||
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
e = NULL;
|
||||
|
||||
break;
|
||||
@@ -764,16 +765,16 @@ makestring:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return str;
|
||||
fail:
|
||||
ssh_buffer_free(buffer);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
ssh_string_burn(str);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(str);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
SSH_STRING_FREE(e);
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
SSH_STRING_FREE(n);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -801,42 +802,42 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
|
||||
r = ssh_make_bignum_string(sig->ecdsa_sig.r);
|
||||
if (r == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(b, r);
|
||||
ssh_string_free(r);
|
||||
SSH_STRING_FREE(r);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = ssh_make_bignum_string(sig->ecdsa_sig.s);
|
||||
if (s == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(b, s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig_blob = ssh_string_new(ssh_buffer_get_len(b));
|
||||
if (sig_blob == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b));
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
break;
|
||||
}
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
sig_blob = pki_ed25519_sig_to_blob(sig);
|
||||
sig_blob = pki_ed25519_signature_to_blob(sig);
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s",
|
||||
@@ -873,7 +874,7 @@ static ssh_signature pki_signature_from_rsa_blob(const ssh_key pubkey, const
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len);
|
||||
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
|
||||
ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len);
|
||||
#endif
|
||||
|
||||
if (len == rsalen) {
|
||||
@@ -954,43 +955,43 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
ssh_string_len(sig_blob));
|
||||
|
||||
if (rc < 0) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = ssh_buffer_get_ssh_string(b);
|
||||
if (r == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
|
||||
ssh_log_hexdump("r", ssh_string_data(r), ssh_string_len(r));
|
||||
#endif
|
||||
sig->ecdsa_sig.r = ssh_make_string_bn(r);
|
||||
ssh_string_burn(r);
|
||||
ssh_string_free(r);
|
||||
SSH_STRING_FREE(r);
|
||||
if (sig->ecdsa_sig.r == NULL) {
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = ssh_buffer_get_ssh_string(b);
|
||||
rlen = ssh_buffer_get_len(b);
|
||||
ssh_buffer_free(b);
|
||||
SSH_BUFFER_FREE(b);
|
||||
if (s == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
|
||||
ssh_log_hexdump("s", ssh_string_data(s), ssh_string_len(s));
|
||||
#endif
|
||||
sig->ecdsa_sig.s = ssh_make_string_bn(s);
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
SSH_STRING_FREE(s);
|
||||
if (sig->ecdsa_sig.s == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
@@ -1007,7 +1008,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
break;
|
||||
}
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
rc = pki_ed25519_sig_from_blob(sig, sig_blob);
|
||||
rc = pki_signature_from_ed25519_blob(sig, sig_blob);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
@@ -1021,51 +1022,6 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
return sig;
|
||||
}
|
||||
|
||||
int pki_signature_verify(ssh_session session, const ssh_signature sig, const
|
||||
ssh_key key, const unsigned char *input, size_t input_len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (session == NULL || sig == NULL || key == NULL || input == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to "
|
||||
"pki_signature_verify()");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (ssh_key_type_plain(key->type) != sig->type) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Can not verify %s signature with %s key",
|
||||
sig->type_c,
|
||||
key->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Check if public key and hash type are compatible */
|
||||
rc = pki_key_check_hash_compatible(key, sig->hash_type);
|
||||
if (rc != SSH_OK) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* For ed25519 keys, verify using the input directly */
|
||||
if (key->type == SSH_KEYTYPE_ED25519 ||
|
||||
key->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
rc = pki_ed25519_verify(key, sig, input, input_len);
|
||||
} else {
|
||||
/* For the other key types, calculate the hash and verify the signature */
|
||||
rc = pki_verify_data_signature(sig, key, input, input_len);
|
||||
}
|
||||
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Signature verification error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static ssh_string rsa_do_sign_hash(const unsigned char *digest,
|
||||
int dlen,
|
||||
mbedtls_pk_context *privkey,
|
||||
@@ -1213,6 +1169,7 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
size_t input_len)
|
||||
{
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
const unsigned char *sign_input = NULL;
|
||||
uint32_t hlen = 0;
|
||||
int rc;
|
||||
|
||||
@@ -1232,27 +1189,38 @@ ssh_signature pki_sign_data(const ssh_key privkey,
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(input, input_len, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
sign_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA384:
|
||||
sha384(input, input_len, hash);
|
||||
hlen = SHA384_DIGEST_LEN;
|
||||
sign_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(input, input_len, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
sign_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
sha1(input, input_len, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
sign_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_AUTO:
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519) {
|
||||
/* SSH_DIGEST_AUTO should only be used with ed25519 */
|
||||
sign_input = input;
|
||||
hlen = input_len;
|
||||
break;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d",
|
||||
hash_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pki_do_sign_hash(privkey, hash, hlen, hash_type);
|
||||
return pki_do_sign_hash(privkey, sign_input, hlen, hash_type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1275,6 +1243,7 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
{
|
||||
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
const unsigned char *verify_input = NULL;
|
||||
uint32_t hlen = 0;
|
||||
|
||||
mbedtls_md_type_t md = 0;
|
||||
@@ -1300,23 +1269,35 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
sha256(input, input_len, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
verify_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA384:
|
||||
sha384(input, input_len, hash);
|
||||
hlen = SHA384_DIGEST_LEN;
|
||||
md = MBEDTLS_MD_SHA384;
|
||||
verify_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(input, input_len, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
verify_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
sha1(input, input_len, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
verify_input = hash;
|
||||
break;
|
||||
case SSH_DIGEST_AUTO:
|
||||
if (pubkey->type == SSH_KEYTYPE_ED25519 ||
|
||||
pubkey->type == SSH_KEYTYPE_ED25519_CERT01)
|
||||
{
|
||||
verify_input = input;
|
||||
hlen = input_len;
|
||||
break;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->hash_type: %d",
|
||||
signature->hash_type);
|
||||
@@ -1353,6 +1334,14 @@ int pki_verify_data_signature(ssh_signature signature,
|
||||
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
case SSH_KEYTYPE_ED25519_CERT01:
|
||||
rc = pki_ed25519_verify(pubkey, signature, verify_input, hlen);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "ED25519 error: Signature invalid");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown public key type");
|
||||
return SSH_ERROR;
|
||||
|
||||
43
src/server.c
43
src/server.c
@@ -166,15 +166,22 @@ int server_set_kex(ssh_session session)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
wanted = session->opts.wanted_methods[i];
|
||||
if (wanted == NULL) {
|
||||
if (wanted == NULL) {
|
||||
if (ssh_fips_mode()) {
|
||||
wanted = ssh_kex_get_fips_methods(i);
|
||||
} else {
|
||||
wanted = ssh_kex_get_default_methods(i);
|
||||
}
|
||||
}
|
||||
if (wanted == NULL) {
|
||||
for (j = 0; j < i; j++) {
|
||||
SAFE_FREE(server->methods[j]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
server->methods[i] = strdup(wanted);
|
||||
if (server->methods[i] == NULL) {
|
||||
for (j = 0; j < i; j++) {
|
||||
@@ -195,7 +202,7 @@ int ssh_server_init_kex(ssh_session session) {
|
||||
}
|
||||
|
||||
/* free any currently-set methods: server_set_kex will allocate new ones */
|
||||
for (i = 0; i < 10 /* SSH_KEX_METHODS */; i++) {
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
SAFE_FREE(session->next_crypto->server_kex.methods[i]);
|
||||
}
|
||||
|
||||
@@ -264,7 +271,11 @@ SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
|
||||
return SSH_PACKET_NOT_USED;
|
||||
}
|
||||
|
||||
int ssh_get_key_params(ssh_session session, ssh_key *privkey){
|
||||
int
|
||||
ssh_get_key_params(ssh_session session,
|
||||
ssh_key *privkey,
|
||||
enum ssh_digest_e *digest)
|
||||
{
|
||||
ssh_key pubkey;
|
||||
ssh_string pubkey_blob;
|
||||
int rc;
|
||||
@@ -290,6 +301,7 @@ int ssh_get_key_params(ssh_session session, ssh_key *privkey){
|
||||
*privkey = NULL;
|
||||
}
|
||||
|
||||
*digest = session->srv.hostkey_digest;
|
||||
rc = ssh_pki_export_privkey_to_pubkey(*privkey, &pubkey);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
@@ -306,7 +318,7 @@ int ssh_get_key_params(ssh_session session, ssh_key *privkey){
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -505,9 +517,11 @@ static int ssh_server_kex_termination(void *s){
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ssh_set_auth_methods(ssh_session session, int auth_methods){
|
||||
/* accept only methods in range */
|
||||
session->auth.supported_methods = auth_methods & 0x3f;
|
||||
/* FIXME: auth_methods should be unsigned */
|
||||
void ssh_set_auth_methods(ssh_session session, int auth_methods)
|
||||
{
|
||||
/* accept only methods in range */
|
||||
session->auth.supported_methods = (uint32_t)auth_methods & 0x3fU;
|
||||
}
|
||||
|
||||
/* Do the banner and key exchange */
|
||||
@@ -815,12 +829,17 @@ int ssh_message_auth_kbdint_is_response(ssh_message msg) {
|
||||
return msg->auth_request.kbdint_response != 0;
|
||||
}
|
||||
|
||||
/* FIXME: methods should be unsigned */
|
||||
int ssh_message_auth_set_methods(ssh_message msg, int methods) {
|
||||
if (msg == NULL || msg->session == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg->session->auth.supported_methods = methods;
|
||||
if (methods < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg->session->auth.supported_methods = (uint32_t)methods;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1013,14 +1032,14 @@ int ssh_message_auth_reply_pk_ok_simple(ssh_message msg) {
|
||||
|
||||
ret = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &pubkey_blob);
|
||||
if (ret < 0) {
|
||||
ssh_string_free(algo);
|
||||
SSH_STRING_FREE(algo);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ret = ssh_message_auth_reply_pk_ok(msg, algo, pubkey_blob);
|
||||
|
||||
ssh_string_free(algo);
|
||||
ssh_string_free(pubkey_blob);
|
||||
SSH_STRING_FREE(algo);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user