mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 21:00:33 +09:00
Compare commits
188 Commits
libssh-0.8
...
libssh-0.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c91f530610 | ||
|
|
69740ea841 | ||
|
|
1bb7895cd9 | ||
|
|
a028b88aed | ||
|
|
8a25f6bb07 | ||
|
|
2db453db16 | ||
|
|
03134c2932 | ||
|
|
95d0c143b3 | ||
|
|
3dcdafa6d7 | ||
|
|
75c446c529 | ||
|
|
4a9c32fc81 | ||
|
|
1634c5a91a | ||
|
|
dfa7593c27 | ||
|
|
034af66338 | ||
|
|
55c7b93a0a | ||
|
|
4818cf5606 | ||
|
|
316a3a42a4 | ||
|
|
546d9da185 | ||
|
|
3b7d997b54 | ||
|
|
129744692c | ||
|
|
83f6ce0928 | ||
|
|
b5c7f07064 | ||
|
|
223ba36d54 | ||
|
|
9141e9d4fe | ||
|
|
ead42db7c8 | ||
|
|
d5a68bedfd | ||
|
|
4307489702 | ||
|
|
f0da1f2e03 | ||
|
|
50477cb80b | ||
|
|
ded4a81ffe | ||
|
|
c2bc4e62dd | ||
|
|
f7ab481b22 | ||
|
|
628b529a91 | ||
|
|
7e25963130 | ||
|
|
91d8f1a256 | ||
|
|
61dcc023b0 | ||
|
|
4468a78ee2 | ||
|
|
8f18063b6d | ||
|
|
a167faee3e | ||
|
|
0e8f6aaee5 | ||
|
|
f0a1b94d0d | ||
|
|
5d1ddf5920 | ||
|
|
152ae623c2 | ||
|
|
e7bd9d02bc | ||
|
|
9196639940 | ||
|
|
786d7e39a3 | ||
|
|
c33710d112 | ||
|
|
a14a80f35f | ||
|
|
0389ff6d9d | ||
|
|
8954fccfdb | ||
|
|
332df98fc9 | ||
|
|
d4cc3f69c6 | ||
|
|
534c58c475 | ||
|
|
84fd910423 | ||
|
|
d51f77c2b1 | ||
|
|
47376cbc77 | ||
|
|
85c3db3e89 | ||
|
|
3f8a522c7f | ||
|
|
eb08802b7c | ||
|
|
dc587045bf | ||
|
|
9b495b72c5 | ||
|
|
2ce6c56609 | ||
|
|
9caef95899 | ||
|
|
66c2630aaf | ||
|
|
b8f63ee2df | ||
|
|
68adb49996 | ||
|
|
12e94bfd18 | ||
|
|
4fc3d7a27f | ||
|
|
466bb332c1 | ||
|
|
ff25b45367 | ||
|
|
df83f4fb57 | ||
|
|
5bda3ab9f6 | ||
|
|
9a057159a2 | ||
|
|
9c0875dd5d | ||
|
|
1fa5a2a504 | ||
|
|
a08a2f52fb | ||
|
|
21d37f8605 | ||
|
|
e43586b4de | ||
|
|
dc7e1bdb39 | ||
|
|
03d559b066 | ||
|
|
3191c1f6be | ||
|
|
d46f01cb7c | ||
|
|
04e290a19b | ||
|
|
bad407f5e2 | ||
|
|
2787756efe | ||
|
|
7b35afdf6b | ||
|
|
dba2903e38 | ||
|
|
965014b035 | ||
|
|
c4ec92f375 | ||
|
|
54cf9d1364 | ||
|
|
23ce6d7156 | ||
|
|
07473976e1 | ||
|
|
51063fe07e | ||
|
|
9cc1af1d53 | ||
|
|
8a83bc0569 | ||
|
|
0181f5b5ed | ||
|
|
eaae8ce086 | ||
|
|
0b2072dd30 | ||
|
|
2e77cf6b34 | ||
|
|
ad3c052e1c | ||
|
|
57d9d97866 | ||
|
|
22747c862a | ||
|
|
fed755eee5 | ||
|
|
804410f8ad | ||
|
|
df57a9a81d | ||
|
|
97076780a5 | ||
|
|
899553f9f7 | ||
|
|
2edff5e69e | ||
|
|
37f451171b | ||
|
|
2efc1721d8 | ||
|
|
e9613e6b52 | ||
|
|
73fbe68ccd | ||
|
|
0cb282df99 | ||
|
|
fdb0c0a29b | ||
|
|
2e56db3b2f | ||
|
|
4eb759bf40 | ||
|
|
c3987a9796 | ||
|
|
a070c942e7 | ||
|
|
113b1872cf | ||
|
|
c7dc2937fc | ||
|
|
075895da40 | ||
|
|
7930086a37 | ||
|
|
3f376f848d | ||
|
|
3cee61a65b | ||
|
|
90321f732e | ||
|
|
c6140b1a4c | ||
|
|
9290d89570 | ||
|
|
da9ab71f88 | ||
|
|
53dfee98d2 | ||
|
|
bb14611f86 | ||
|
|
b1aca92268 | ||
|
|
2b524655ae | ||
|
|
b51594c34a | ||
|
|
b409b7d092 | ||
|
|
4256936fed | ||
|
|
fdb6dc7069 | ||
|
|
6291900234 | ||
|
|
216bd2abd8 | ||
|
|
574f279f00 | ||
|
|
d886870bbf | ||
|
|
f56c93cccd | ||
|
|
bbd17bc97a | ||
|
|
26fa923b55 | ||
|
|
177a082974 | ||
|
|
ce3ee332d4 | ||
|
|
eb95f8fa85 | ||
|
|
8d3db75724 | ||
|
|
e1fbc02209 | ||
|
|
766041d956 | ||
|
|
f880a7728f | ||
|
|
013203301f | ||
|
|
bfb60befa7 | ||
|
|
4d34890624 | ||
|
|
6751c0e2c3 | ||
|
|
a641b6ea79 | ||
|
|
fa3c73016d | ||
|
|
ffabd8c6ed | ||
|
|
219a311925 | ||
|
|
8e3af4d859 | ||
|
|
9fa614a36d | ||
|
|
3d207f72a0 | ||
|
|
f53d2f7511 | ||
|
|
b853d99546 | ||
|
|
a09976e3d6 | ||
|
|
1ba0432524 | ||
|
|
7dcd749ee1 | ||
|
|
30368fb06a | ||
|
|
fd6b7db1ce | ||
|
|
53514b2a40 | ||
|
|
0e20418296 | ||
|
|
92b59ace9e | ||
|
|
af7b5b78ee | ||
|
|
2b67e2d54c | ||
|
|
f44994f1e6 | ||
|
|
97d6eb84a4 | ||
|
|
33f2211cae | ||
|
|
03aff19b80 | ||
|
|
cf660fe27c | ||
|
|
f9d60e1360 | ||
|
|
1098280e43 | ||
|
|
62301834f4 | ||
|
|
3e0ac84001 | ||
|
|
4d26e08789 | ||
|
|
3c4403c400 | ||
|
|
8dcde7a74f | ||
|
|
bb7cd8e22b | ||
|
|
7458e95ee5 | ||
|
|
2f69c5f022 |
@@ -60,14 +60,15 @@ fedora/openssl_1.1.x/x86-64/release:
|
||||
- obj/
|
||||
|
||||
# Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite
|
||||
.fedora/address-sanitizer:
|
||||
# so, this is only enabled for unit tests right now.
|
||||
# TODO: add -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
fedora/address-sanitizer:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_C_FLAGS="-O2 -g -fsanitize=address"
|
||||
-DCMAKE_LINK_FLAGS="-fsanitize=address -static-libasan"
|
||||
-DCMAKE_BUILD_TYPE=AddressSanitizer
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.3.0)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
|
||||
project(libssh VERSION 0.8.2 LANGUAGES C)
|
||||
# Specify search path for CMake modules to be loaded by include()
|
||||
# and find_package()
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
|
||||
# Add defaults for cmake
|
||||
# Those need to be set before the project() call.
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
|
||||
project(libssh VERSION 0.8.3 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -13,16 +22,12 @@ 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.6.0")
|
||||
set(LIBRARY_VERSION "4.7.0")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules
|
||||
)
|
||||
|
||||
# add definitions
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefinePlatformDefaults)
|
||||
include(DefineInstallationPaths)
|
||||
include(DefineOptions.cmake)
|
||||
|
||||
15
ChangeLog
15
ChangeLog
@@ -1,6 +1,21 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
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
|
||||
|
||||
@@ -17,8 +17,7 @@ if (UNIX)
|
||||
endif()
|
||||
|
||||
add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-pedantic" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-pedantic-errors" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wmissing-prototypes" SUPPORTED_COMPILER_FLAGS)
|
||||
@@ -63,9 +62,19 @@ if (UNIX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
|
||||
check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG)
|
||||
if (WITH_STACK_PROTECTOR_STRONG)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong")
|
||||
else (WITH_STACK_PROTECTOR_STRONG)
|
||||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
|
||||
endif()
|
||||
endif (WITH_STACK_PROTECTOR_STRONG)
|
||||
|
||||
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
|
||||
if (WITH_STACK_CLASH_PROTECTION)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
|
||||
endif()
|
||||
|
||||
if (PICKY_DEVELOPER)
|
||||
|
||||
@@ -4,7 +4,7 @@ include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckTypeSize)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckStructHasMember)
|
||||
include(TestBigEndian)
|
||||
|
||||
set(PACKAGE ${PROJECT_NAME})
|
||||
@@ -156,7 +156,8 @@ check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
|
||||
check_function_exists(memset_s HAVE_MEMSET_S)
|
||||
|
||||
if (HAVE_GLOB_H)
|
||||
check_function_exists(glob HAVE_GLOB)
|
||||
check_struct_has_member(glob_t gl_flags glob.h HAVE_GLOB_GL_FLAGS_MEMBER)
|
||||
check_function_exists(glob HAVE_GLOB)
|
||||
endif (HAVE_GLOB_H)
|
||||
|
||||
if (NOT WIN32)
|
||||
|
||||
@@ -27,9 +27,10 @@ else (WITH_ZLIB)
|
||||
set(WITH_LIBZ OFF)
|
||||
endif (WITH_ZLIB)
|
||||
|
||||
if(WITH_BENCHMARKS)
|
||||
if (WITH_BENCHMARKS)
|
||||
set(UNIT_TESTING ON)
|
||||
endif(WITH_BENCHMARKS)
|
||||
set(CLIENT_TESTING ON)
|
||||
endif()
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
set(BUILD_STATIC_LIB ON)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
|
||||
# - add_cmocka_test(test_name test_source linklib1 ... linklibN)
|
||||
|
||||
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
||||
# Copyright (c) 2007-2010 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2007-2018 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
@@ -9,20 +9,6 @@
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
# Profiling
|
||||
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
|
||||
# Address Sanitizer
|
||||
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Address sanitizer compiler flags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer shared linker flags")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer module linker flags")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer executable linker flags")
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
if (WIN32)
|
||||
find_program(WINE_EXECUTABLE
|
||||
@@ -31,8 +17,10 @@ if (CMAKE_CROSSCOMPILING)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function (ADD_CMOCKA_TEST _testName _testSource)
|
||||
function(ADD_CMOCKA_TEST _testName _testSource)
|
||||
add_executable(${_testName} ${_testSource})
|
||||
|
||||
target_link_libraries(${_testName} ${ARGN})
|
||||
|
||||
add_test(${_testName} ${TARGET_SYSTEM_EMULATOR} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}${CMAKE_EXECUTABLE_SUFFIX})
|
||||
endfunction (ADD_CMOCKA_TEST)
|
||||
|
||||
@@ -14,17 +14,5 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
|
||||
# since cmake 2.4.0
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
|
||||
# Define the generic version of the libraries here
|
||||
set(GENERIC_LIB_VERSION "0.1.0")
|
||||
set(GENERIC_LIB_SOVERSION "0")
|
||||
|
||||
# Set the default build type to release with debug info
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo
|
||||
CACHE STRING
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
||||
)
|
||||
endif (NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
# Create the compile command database for clang by default
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
25
cmake/Modules/DefineCompilerFlags.cmake
Normal file
25
cmake/Modules/DefineCompilerFlags.cmake
Normal file
@@ -0,0 +1,25 @@
|
||||
if (UNIX AND NOT WIN32)
|
||||
# Activate with: -DCMAKE_BUILD_TYPE=Profiling
|
||||
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C compiler during PROFILING builds.")
|
||||
set(CMAKE_CXX_FLAGS_PROFILING "-g -O0 -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the CXX compiler during PROFILING builds.")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the linker during PROFILING builds.")
|
||||
|
||||
# Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer
|
||||
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
|
||||
CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
|
||||
CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
||||
CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.")
|
||||
endif()
|
||||
@@ -89,6 +89,9 @@
|
||||
/* Define to 1 if you have DSA */
|
||||
#cmakedefine HAVE_DSA 1
|
||||
|
||||
/* Define to 1 if you have gl_flags as a glob_t sturct member */
|
||||
#cmakedefine HAVE_GLOB_GL_FLAGS_MEMBER 1
|
||||
|
||||
/*************************** FUNCTIONS ***************************/
|
||||
|
||||
/* Define to 1 if you have the `EVP_aes128_ctr' function. */
|
||||
|
||||
@@ -20,7 +20,7 @@ the interesting functions as you go.
|
||||
The libssh library provides:
|
||||
|
||||
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
|
||||
- <strong>Hostkey Types</strong>: <i>ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521</i>, ssh-dss, ssh-rsa
|
||||
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256,ssh-dss
|
||||
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc, none
|
||||
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
|
||||
- <strong>MAC hashes</strong>: hmac-sha1, hmac-sha2-256, hmac-sha2-384, hmac-sha2-512, hmac-md5, none
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
Basic styling for fragments shared by all themes.
|
||||
*/
|
||||
|
||||
div.fragment {
|
||||
padding: 0;
|
||||
margin: 4px 8px 4px 2px;
|
||||
color: #bebebe;
|
||||
background-color: #323232;
|
||||
border: 3px solid #e8e8e8;
|
||||
border-radius: 2px;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
div.line {
|
||||
font-family: monospace, fixed;
|
||||
font-size: 13px;
|
||||
min-height: 13px;
|
||||
line-height: 1.0;
|
||||
text-indent: -53px;
|
||||
margin: 0px;
|
||||
padding: 1px 0 1px 53px;
|
||||
white-space: pre;
|
||||
|
||||
@include transition-property(background-color);
|
||||
@include transition-duration(0s);
|
||||
|
||||
&:hover {
|
||||
background-color: #1a1a1a;
|
||||
}
|
||||
|
||||
&::after {
|
||||
// insert linefeed
|
||||
content:"\000A";
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
|
||||
span.lineno {
|
||||
padding-right: 4px;
|
||||
text-align: right;
|
||||
color: black;
|
||||
height: 100px;
|
||||
white-space: pre;
|
||||
border-right: 3px solid #1d7567;
|
||||
background-color: #a0a0a0;
|
||||
}
|
||||
|
||||
span.lineno a, span.lineno a:visited {
|
||||
background-color: inherit;
|
||||
color: #1e595a;
|
||||
}
|
||||
|
||||
span.lineno a:hover {
|
||||
background-color: #C8C8C8;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.lineno {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
// colours of code view
|
||||
|
||||
div.fragment {
|
||||
color: #bebebe;
|
||||
background-color: #323232;
|
||||
}
|
||||
|
||||
div.fragment::before {
|
||||
background-color: #1a1a1a;
|
||||
border-right: 1px solid #3e3e3e;
|
||||
}
|
||||
|
||||
div.line:hover {
|
||||
background-color: #1a1a1a;
|
||||
}
|
||||
|
||||
span.lineno {
|
||||
color: #969696;
|
||||
background-color: #1a1a1a;
|
||||
border-right: 1px solid #3e3e3e;
|
||||
}
|
||||
|
||||
span.lineno a, span.lineno a:visited {
|
||||
background-color: inherit;
|
||||
color: #dcdcdc;
|
||||
}
|
||||
|
||||
span.lineno a:hover {
|
||||
background-color: #323232;
|
||||
}
|
||||
|
||||
|
||||
// syntax highlighting
|
||||
|
||||
a.code, a.code:visited {
|
||||
color: #6cc7eb;
|
||||
}
|
||||
|
||||
a.codeRef, a.codeRef:visited {
|
||||
color: #3d95e6;
|
||||
}
|
||||
|
||||
span.keyword {
|
||||
color: #98f77a;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.keywordtype {
|
||||
color: #ffa0a0;
|
||||
}
|
||||
|
||||
span.keywordflow {
|
||||
color: #98f77a;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.comment {
|
||||
// color: #dadbb1;
|
||||
color: #999;
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
span.preprocessor {
|
||||
color: #cd5c57;
|
||||
}
|
||||
|
||||
span.stringliteral {
|
||||
color: #64b041;
|
||||
}
|
||||
|
||||
span.charliteral {
|
||||
color: #64b041;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
background-color: #F7F8FB;
|
||||
border-left: 2px solid #9CAFD4;
|
||||
margin: 0 24px 0 4px;
|
||||
padding: 0 12px 0 16px;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* The main menu at the top
|
||||
*/
|
||||
|
||||
#main-menu {
|
||||
background-image: none;
|
||||
background: $background-color-dark;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sm-dox {
|
||||
// :not(:last-child) -> do not style search box
|
||||
&> li:not(:last-child) > a {
|
||||
background-image: none;
|
||||
text-shadow: none;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
letter-spacing: 1px;
|
||||
font-size: 11pt;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
&> li:not(:last-child) > a:hover,
|
||||
&> li:not(:last-child) > a.highlighted {
|
||||
background-color: $primary-color;
|
||||
}
|
||||
|
||||
a span.sub-arrow {
|
||||
// this sets the color of the arrow
|
||||
border-color: white transparent transparent;
|
||||
}
|
||||
|
||||
ul {
|
||||
// sub menus
|
||||
border: none;
|
||||
@include border-radius(0 !important);
|
||||
padding: 0;
|
||||
background: $background-color-dark;
|
||||
@include box-shadow(0 0 4px rgba(0,0,0,0.35), 0 0 8px rgba(0,0,0,0.2));
|
||||
|
||||
a {
|
||||
background: inherit;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
letter-spacing: 1px;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: $primary-color;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
letter-spacing: 1px;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
a.highlighted {
|
||||
background: $primary-color;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
letter-spacing: 1px;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
a span.sub-arrow {
|
||||
/* this sets the color of the arrow */
|
||||
border-color: white transparent transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
@mixin box-shadow($args...) {
|
||||
-moz-box-shadow: $args;
|
||||
-webkit-box-shadow: $args;
|
||||
-o-box-shadow: $args;
|
||||
box-shadow: $args;
|
||||
}
|
||||
|
||||
@mixin border-radius($args...) {
|
||||
-moz-border-radius: $args;
|
||||
-webkit-border-radius: $args;
|
||||
border-radius: $args;
|
||||
}
|
||||
|
||||
@mixin transition($args...) {
|
||||
-webkit-transition: $args;
|
||||
-moz-transition: $args;
|
||||
-o-transition: $args;
|
||||
transition: $args;
|
||||
}
|
||||
|
||||
@mixin transition-property($arg) {
|
||||
-webkit-transition: $arg;
|
||||
-moz-transition: $arg;
|
||||
-o-transition: $arg;
|
||||
transition: $arg;
|
||||
}
|
||||
|
||||
@mixin transition-duration($arg) {
|
||||
-webkit-duration: $arg;
|
||||
-moz-duration: $arg;
|
||||
-o-duration: $arg;
|
||||
duration: $arg;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* The tree view on the left
|
||||
*/
|
||||
|
||||
.arrow {
|
||||
color:black;
|
||||
cursor: pointer;
|
||||
font-size: 80%;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 22px;
|
||||
margin-left: 4px;
|
||||
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
#selected .arrow {
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
color: #d2d2d2;
|
||||
}
|
||||
}
|
||||
|
||||
#nav-tree {
|
||||
background-image: none;
|
||||
background-color: white;
|
||||
|
||||
.item {
|
||||
margin: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: #d2d2d2;
|
||||
}
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-image: none;
|
||||
background-color: $primary-color;
|
||||
color: white;
|
||||
text-shadow: none;
|
||||
|
||||
&:hover {
|
||||
background-image: none;
|
||||
background-color: $primary-color;
|
||||
color: white;
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-resizable-e {
|
||||
background: #808080 url("splitbar_handle.svg") no-repeat center;
|
||||
border-right: solid 1px #c0c0c0;
|
||||
border-left: solid 1px black;
|
||||
|
||||
&:hover {
|
||||
background-color: #606060;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* The line at the bottom
|
||||
*/
|
||||
|
||||
.navpath {
|
||||
ul {
|
||||
font-size: 11px;
|
||||
background-image: none;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
color: black;
|
||||
border: none;
|
||||
border-top: 1px solid #808080;
|
||||
overflow: hidden;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* intermediate navelems */
|
||||
li:not(:first-child) {
|
||||
list-style-type: none;
|
||||
float: left;
|
||||
padding-left: 18px;
|
||||
padding-right: 10px;
|
||||
color: black;
|
||||
background-color: white;
|
||||
background-image: url('nav_edge_inter.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: left -1px;
|
||||
background-size: auto 100%;
|
||||
}
|
||||
|
||||
/* first navelem */
|
||||
li:first-child {
|
||||
list-style-type: none;
|
||||
float: left;
|
||||
padding-left: 15px;
|
||||
padding-right: 10px;
|
||||
color: black;
|
||||
background-color: white;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
/* last navelem */
|
||||
li:nth-last-child(2) {
|
||||
list-style-type: none;
|
||||
float: left;
|
||||
padding-left:10px;
|
||||
padding-right:15px;
|
||||
color: white;
|
||||
background-color: $primary-color;
|
||||
background-image: url('nav_edge_right.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: right -1px;
|
||||
background-size: auto 100%;
|
||||
|
||||
}
|
||||
|
||||
li:nth-last-child(2):not(:first-child) {
|
||||
list-style-type: none;
|
||||
float: left;
|
||||
padding-left:15px;
|
||||
padding-right:15px;
|
||||
color: white;
|
||||
background-color: $primary-color;
|
||||
background-image: url('nav_edge_left.svg'), url('nav_edge_right.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: -1px -1px, right -1px;
|
||||
background-size: auto 100%;
|
||||
}
|
||||
|
||||
li.navelem a, .navpath li.navelem b {
|
||||
height:32px;
|
||||
display:block;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
font-family: Roboto,sans-serif;
|
||||
text-shadow: none;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
li.navelem a:hover {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
// the "doxygen" logo at the right
|
||||
li.footer {
|
||||
list-style-type: none;
|
||||
float: right;
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
background-color: #d5d5d5;
|
||||
background-image: none;
|
||||
color: black;
|
||||
font-size: 8pt;
|
||||
|
||||
// show the edge image
|
||||
&:before {
|
||||
content: "";
|
||||
width: 13px;
|
||||
height: 30px;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
background-image: url("nav_edge_right.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 0;
|
||||
background-size: auto 100%;
|
||||
|
||||
/* flip the element horizontally */
|
||||
-moz-transform: scaleX(-1);
|
||||
-o-transform: scaleX(-1);
|
||||
-webkit-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
filter: FlipH;
|
||||
-ms-filter: "FlipH";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* The search box
|
||||
*/
|
||||
|
||||
.sm-dox > li:last-child {
|
||||
margin-right: 10pt;
|
||||
}
|
||||
|
||||
#MSearchBox {
|
||||
border: 2px inset black;
|
||||
display: table;
|
||||
width: 350px;
|
||||
height: 26px;
|
||||
background: white;
|
||||
margin-top: 5px;
|
||||
|
||||
.left {
|
||||
background-image: none;
|
||||
display: table-cell;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
// don't need this element
|
||||
.right {
|
||||
background-image: none;
|
||||
width: 0;
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
// override for when there is no main menu
|
||||
nav > #MSearchBox {
|
||||
border: 2px solid #666666;
|
||||
margin: 5px 10pt 0 0;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
#MSearchSelect, .left #MSearchSelect {
|
||||
left: 0;
|
||||
background-image: url("mag_glass.svg");
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
padding: 22px 22px 0 0 ;
|
||||
margin: 0 4px 0 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#MSearchField {
|
||||
background-image: none;
|
||||
display: table-cell;
|
||||
margin: 0;
|
||||
// leave room for #MSearchSelect and a bit more for the border
|
||||
margin-left: 30px;
|
||||
width: calc(100% - 34px);
|
||||
height: 22px;
|
||||
font: 11pt sans-serif;
|
||||
}
|
||||
|
||||
#MSearchSelectWindow {
|
||||
background-color: $background-color-dark;
|
||||
padding: 0;
|
||||
border: solid 1px black;
|
||||
@include border-radius(0);
|
||||
@include box-shadow(0 0 4px rgba(0,0,0,0.35), 0 0 8px rgba(0,0,0,0.2));
|
||||
}
|
||||
|
||||
a.SelectItem {
|
||||
color: white;
|
||||
padding: 3px 4px;
|
||||
font: 10pt sans-serif;
|
||||
letter-spacing: 1px;
|
||||
|
||||
&:hover {
|
||||
background-color: $primary-color;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:focus, &:active {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
#MSearchResultsWindow {
|
||||
background-color: white;
|
||||
@include box-shadow(0 0 4px rgba(0,0,0,0.35), 0 0 8px rgba(0,0,0,0.2));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -152,10 +152,14 @@ a.elRef, a.elRef:visited {
|
||||
letter-spacing: 1px;
|
||||
font-size: 11pt;
|
||||
text-transform: uppercase; }
|
||||
.sm-dox > li:not(:last-child) > a:hover, .sm-dox > li:not(:last-child) > a.highlighted {
|
||||
|
||||
.sm-dox > li:not(:last-child) > a:hover,
|
||||
.sm-dox > li:not(:last-child) > a.highlighted {
|
||||
background-color: #5f082b; }
|
||||
|
||||
.sm-dox a span.sub-arrow {
|
||||
border-color: white transparent transparent; }
|
||||
|
||||
.sm-dox ul {
|
||||
border: none;
|
||||
-moz-border-radius: 0 !important;
|
||||
@@ -262,7 +266,7 @@ img.footer {
|
||||
Basic styling for fragments shared by all themes.
|
||||
*/
|
||||
div.fragment {
|
||||
padding: 0;
|
||||
padding: 4px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
color: #bebebe;
|
||||
background-color: #323232;
|
||||
@@ -302,7 +306,7 @@ span.lineno {
|
||||
height: 100px;
|
||||
white-space: pre;
|
||||
border-right: 3px solid #1d7567;
|
||||
background-color: #a0a0a0; }
|
||||
background-color: #323232; }
|
||||
|
||||
span.lineno a, span.lineno a:visited {
|
||||
background-color: inherit;
|
||||
@@ -333,7 +337,7 @@ div.line:hover {
|
||||
|
||||
span.lineno {
|
||||
color: #969696;
|
||||
background-color: #1a1a1a;
|
||||
background-color: #323232;
|
||||
border-right: 1px solid #3e3e3e; }
|
||||
|
||||
span.lineno a, span.lineno a:visited {
|
||||
@@ -539,9 +543,9 @@ th.markdownTableHeadCenter, th.markdownTableHeadNone {
|
||||
width: 100%; }
|
||||
|
||||
.memTemplParams {
|
||||
color: #4665A2;
|
||||
color: black;
|
||||
white-space: nowrap;
|
||||
font-size: 80%; }
|
||||
font-size: 100%; }
|
||||
|
||||
/* Styles for detailed member documentation */
|
||||
.memtitle {
|
||||
@@ -1406,25 +1410,18 @@ div.toc {
|
||||
@media print {
|
||||
#top {
|
||||
display: none; }
|
||||
|
||||
#side-nav {
|
||||
display: none; }
|
||||
|
||||
#nav-path {
|
||||
display: none; }
|
||||
|
||||
body {
|
||||
overflow: visible; }
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
page-break-after: avoid; }
|
||||
|
||||
.summary {
|
||||
display: none; }
|
||||
|
||||
.memitem {
|
||||
page-break-inside: avoid; }
|
||||
|
||||
#doc-content {
|
||||
margin-left: 0 !important;
|
||||
height: auto !important;
|
||||
@@ -1432,5 +1429,3 @@ div.toc {
|
||||
overflow: inherit;
|
||||
display: inline;
|
||||
background-color: white; } }
|
||||
|
||||
/*# sourceMappingURL=that_style.css.map */
|
||||
|
||||
@@ -24,7 +24,8 @@ clients must be made or how a client should react.
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
int authenticate_kbdint(ssh_session session, const char *password) {
|
||||
int authenticate_kbdint(ssh_session session, const char *password)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
@@ -99,78 +100,80 @@ int authenticate_kbdint(ssh_session session, const char *password) {
|
||||
return err;
|
||||
}
|
||||
|
||||
static void error(ssh_session session){
|
||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
||||
static void error(ssh_session session)
|
||||
{
|
||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
||||
}
|
||||
|
||||
int authenticate_console(ssh_session session){
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *banner;
|
||||
int authenticate_console(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *banner;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
}
|
||||
|
||||
method = ssh_userauth_list(session, NULL);
|
||||
while (rc != SSH_AUTH_SUCCESS) {
|
||||
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
|
||||
rc = ssh_userauth_gssapi(session);
|
||||
if(rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Try to authenticate with public key first
|
||||
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to authenticate with keyboard interactive";
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||
rc = authenticate_kbdint(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
// Try to authenticate with password
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD) {
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(password, 0, sizeof(password));
|
||||
}
|
||||
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n",banner);
|
||||
ssh_string_free_char(banner);
|
||||
}
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
}
|
||||
|
||||
method = ssh_userauth_list(session, NULL);
|
||||
while (rc != SSH_AUTH_SUCCESS) {
|
||||
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
|
||||
rc = ssh_userauth_gssapi(session);
|
||||
if(rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Try to authenticate with public key first
|
||||
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to authenticate with keyboard interactive";
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||
rc = authenticate_kbdint(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
// Try to authenticate with password
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD) {
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(password, 0, sizeof(password));
|
||||
}
|
||||
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n",banner);
|
||||
ssh_string_free_char(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -33,236 +33,259 @@ static int verbosity;
|
||||
static char *destination;
|
||||
|
||||
#define DATALEN 65536
|
||||
static void do_sftp(ssh_session session){
|
||||
sftp_session sftp=sftp_new(session);
|
||||
|
||||
static void do_sftp(ssh_session session) {
|
||||
sftp_session sftp = sftp_new(session);
|
||||
sftp_dir dir;
|
||||
sftp_attributes file;
|
||||
sftp_statvfs_t sftpstatvfs;
|
||||
struct statvfs sysstatvfs;
|
||||
sftp_file fichier;
|
||||
sftp_file to;
|
||||
int len=1;
|
||||
int len = 1;
|
||||
unsigned int i;
|
||||
char data[DATALEN]={0};
|
||||
char data[DATALEN] = {0};
|
||||
char *lnk;
|
||||
|
||||
unsigned int count;
|
||||
|
||||
if(!sftp){
|
||||
if (!sftp) {
|
||||
fprintf(stderr, "sftp error initialising channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
if(sftp_init(sftp)){
|
||||
|
||||
if (sftp_init(sftp)) {
|
||||
fprintf(stderr, "error initialising sftp: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("Additional SFTP extensions provided by the server:\n");
|
||||
count = sftp_extensions_get_count(sftp);
|
||||
for (i = 0; i < count; i++) {
|
||||
printf("\t%s, version: %s\n",
|
||||
sftp_extensions_get_name(sftp, i),
|
||||
sftp_extensions_get_data(sftp, i));
|
||||
printf("\t%s, version: %s\n",
|
||||
sftp_extensions_get_name(sftp, i),
|
||||
sftp_extensions_get_data(sftp, i));
|
||||
}
|
||||
|
||||
/* test symlink and readlink */
|
||||
if (sftp_symlink(sftp, "/tmp/this_is_the_link",
|
||||
"/tmp/sftp_symlink_test") < 0) {
|
||||
fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
"/tmp/sftp_symlink_test") < 0)
|
||||
{
|
||||
fprintf(stderr, "Could not create link (%s)\n",
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
|
||||
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
||||
if (lnk == NULL) {
|
||||
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
|
||||
|
||||
sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
||||
|
||||
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
|
||||
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
||||
if (sftpstatvfs == NULL) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
||||
if (sftpstatvfs == NULL) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("sftp statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sftpstatvfs->f_bsize,
|
||||
(unsigned long long) sftpstatvfs->f_frsize,
|
||||
(unsigned long long) sftpstatvfs->f_blocks,
|
||||
(unsigned long long) sftpstatvfs->f_bfree,
|
||||
(unsigned long long) sftpstatvfs->f_bavail,
|
||||
(unsigned long long) sftpstatvfs->f_files,
|
||||
(unsigned long long) sftpstatvfs->f_ffree,
|
||||
(unsigned long long) sftpstatvfs->f_favail,
|
||||
(unsigned long long) sftpstatvfs->f_fsid,
|
||||
(unsigned long long) sftpstatvfs->f_flag,
|
||||
(unsigned long long) sftpstatvfs->f_namemax);
|
||||
printf("sftp statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sftpstatvfs->f_bsize,
|
||||
(unsigned long long) sftpstatvfs->f_frsize,
|
||||
(unsigned long long) sftpstatvfs->f_blocks,
|
||||
(unsigned long long) sftpstatvfs->f_bfree,
|
||||
(unsigned long long) sftpstatvfs->f_bavail,
|
||||
(unsigned long long) sftpstatvfs->f_files,
|
||||
(unsigned long long) sftpstatvfs->f_ffree,
|
||||
(unsigned long long) sftpstatvfs->f_favail,
|
||||
(unsigned long long) sftpstatvfs->f_fsid,
|
||||
(unsigned long long) sftpstatvfs->f_flag,
|
||||
(unsigned long long) sftpstatvfs->f_namemax);
|
||||
|
||||
sftp_statvfs_free(sftpstatvfs);
|
||||
sftp_statvfs_free(sftpstatvfs);
|
||||
|
||||
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("sys statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sysstatvfs.f_bsize,
|
||||
(unsigned long long) sysstatvfs.f_frsize,
|
||||
(unsigned long long) sysstatvfs.f_blocks,
|
||||
(unsigned long long) sysstatvfs.f_bfree,
|
||||
(unsigned long long) sysstatvfs.f_bavail,
|
||||
(unsigned long long) sysstatvfs.f_files,
|
||||
(unsigned long long) sysstatvfs.f_ffree,
|
||||
(unsigned long long) sysstatvfs.f_favail,
|
||||
(unsigned long long) sysstatvfs.f_fsid,
|
||||
(unsigned long long) sysstatvfs.f_flag,
|
||||
(unsigned long long) sysstatvfs.f_namemax);
|
||||
printf("sys statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sysstatvfs.f_bsize,
|
||||
(unsigned long long) sysstatvfs.f_frsize,
|
||||
(unsigned long long) sysstatvfs.f_blocks,
|
||||
(unsigned long long) sysstatvfs.f_bfree,
|
||||
(unsigned long long) sysstatvfs.f_bavail,
|
||||
(unsigned long long) sysstatvfs.f_files,
|
||||
(unsigned long long) sysstatvfs.f_ffree,
|
||||
(unsigned long long) sysstatvfs.f_favail,
|
||||
(unsigned long long) sysstatvfs.f_fsid,
|
||||
(unsigned long long) sysstatvfs.f_flag,
|
||||
(unsigned long long) sysstatvfs.f_namemax);
|
||||
}
|
||||
|
||||
/* the connection is made */
|
||||
/* opening a directory */
|
||||
dir=sftp_opendir(sftp,"./");
|
||||
if(!dir) {
|
||||
dir = sftp_opendir(sftp, "./");
|
||||
if (!dir) {
|
||||
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
|
||||
return ;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* reading the whole directory, file by file */
|
||||
while((file=sftp_readdir(sftp,dir))){
|
||||
while ((file = sftp_readdir(sftp, dir))) {
|
||||
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
|
||||
file->name,
|
||||
file->permissions,
|
||||
file->owner,
|
||||
file->uid,
|
||||
file->group,
|
||||
file->gid,
|
||||
(long long unsigned int) file->size);
|
||||
file->name,
|
||||
file->permissions,
|
||||
file->owner,
|
||||
file->uid,
|
||||
file->group,
|
||||
file->gid,
|
||||
(long long unsigned int) file->size);
|
||||
sftp_attributes_free(file);
|
||||
}
|
||||
/* when file=NULL, an error has occured OR the directory listing is end of file */
|
||||
if(!sftp_dir_eof(dir)){
|
||||
|
||||
/* when file = NULL, an error has occured OR the directory listing is end of
|
||||
* file */
|
||||
if (!sftp_dir_eof(dir)) {
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
if(sftp_closedir(dir)){
|
||||
|
||||
if (sftp_closedir(dir)) {
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
/* this will open a file and copy it into your /home directory */
|
||||
/* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */
|
||||
/* the small buffer size was intended to stress the library. of course, you
|
||||
* can use a buffer till 20kbytes without problem */
|
||||
|
||||
fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0);
|
||||
if(!fichier){
|
||||
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
||||
if (!fichier) {
|
||||
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* open a file for writing... */
|
||||
to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700);
|
||||
if(!to){
|
||||
to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700);
|
||||
if (!to) {
|
||||
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
ssh_get_error(session));
|
||||
sftp_close(fichier);
|
||||
goto end;
|
||||
}
|
||||
while((len=sftp_read(fichier,data,4096)) > 0){
|
||||
if(sftp_write(to,data,len)!=len){
|
||||
|
||||
while ((len = sftp_read(fichier, data, 4096)) > 0) {
|
||||
if (sftp_write(to, data, len) != len) {
|
||||
fprintf(stderr, "Error writing %d bytes: %s\n",
|
||||
len, ssh_get_error(session));
|
||||
return;
|
||||
len, ssh_get_error(session));
|
||||
sftp_close(to);
|
||||
sftp_close(fichier);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
printf("finished\n");
|
||||
if(len<0)
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
|
||||
}
|
||||
|
||||
sftp_close(fichier);
|
||||
sftp_close(to);
|
||||
printf("fichiers ferm\n");
|
||||
to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
|
||||
for(i=0;i<1000;++i){
|
||||
len=sftp_write(to,data,DATALEN);
|
||||
printf("wrote %d bytes\n",len);
|
||||
if(len != DATALEN){
|
||||
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
|
||||
to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644);
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
len = sftp_write(to, data, DATALEN);
|
||||
printf("wrote %d bytes\n", len);
|
||||
if (len != DATALEN) {
|
||||
printf("chunk %d : %d (%s)\n", i, len, ssh_get_error(session));
|
||||
}
|
||||
}
|
||||
sftp_close(to);
|
||||
|
||||
sftp_close(to);
|
||||
end:
|
||||
/* close the sftp session */
|
||||
sftp_free(sftp);
|
||||
printf("sftp session terminated\n");
|
||||
}
|
||||
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [-v] remotehost\n"
|
||||
"sample sftp test client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -v : increase log verbosity\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
static void usage(const char *argv0) {
|
||||
fprintf(stderr, "Usage : %s [-v] remotehost\n"
|
||||
"sample sftp test client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -v : increase log verbosity\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
static int opts(int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
while ((i = getopt(argc, argv, "v")) != -1) {
|
||||
switch(i) {
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown option %c\n", optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
destination = argv[optind];
|
||||
if (destination == NULL) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
destination=argv[optind];
|
||||
if(destination == NULL){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
session=connect_ssh(destination,NULL,verbosity);
|
||||
if(session == NULL)
|
||||
return EXIT_FAILURE;
|
||||
do_sftp(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return 0;
|
||||
int main(int argc, char **argv) {
|
||||
ssh_session session;
|
||||
|
||||
if (opts(argc, argv) < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
session = connect_ssh(destination, NULL, verbosity);
|
||||
if (session == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
do_sftp(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,12 +48,17 @@ static char *user;
|
||||
static char *cmds[MAXCMD];
|
||||
static struct termios terminal;
|
||||
|
||||
static char *pcap_file=NULL;
|
||||
static char *pcap_file = NULL;
|
||||
|
||||
static char *proxycommand;
|
||||
|
||||
static int auth_callback(const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata) {
|
||||
static int auth_callback(const char *prompt,
|
||||
char *buf,
|
||||
size_t len,
|
||||
int echo,
|
||||
int verify,
|
||||
void *userdata)
|
||||
{
|
||||
(void) verify;
|
||||
(void) userdata;
|
||||
|
||||
@@ -61,11 +66,12 @@ static int auth_callback(const char *prompt, char *buf, size_t len,
|
||||
}
|
||||
|
||||
struct ssh_callbacks_struct cb = {
|
||||
.auth_function=auth_callback,
|
||||
.userdata=NULL
|
||||
.auth_function = auth_callback,
|
||||
.userdata = NULL,
|
||||
};
|
||||
|
||||
static void add_cmd(char *cmd){
|
||||
static void add_cmd(char *cmd)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
|
||||
@@ -73,7 +79,8 @@ static void add_cmd(char *cmd){
|
||||
if (n == MAXCMD) {
|
||||
return;
|
||||
}
|
||||
cmds[n]=strdup(cmd);
|
||||
|
||||
cmds[n] = strdup(cmd);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
@@ -98,37 +105,43 @@ static void usage(void)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
static int opts(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
// for(i=0;i<argc;i++)
|
||||
// printf("%d : %s\n",i,argv[i]);
|
||||
/* insert your own arguments here */
|
||||
while((i=getopt(argc,argv,"T:P:"))!=-1){
|
||||
|
||||
while((i = getopt(argc,argv,"T:P:")) != -1) {
|
||||
switch(i){
|
||||
case 'P':
|
||||
pcap_file=optarg;
|
||||
break;
|
||||
case 'P':
|
||||
pcap_file = optarg;
|
||||
break;
|
||||
#ifndef _WIN32
|
||||
case 'T':
|
||||
proxycommand=optarg;
|
||||
case 'T':
|
||||
proxycommand = optarg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage();
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", optopt);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if(optind < argc)
|
||||
host=argv[optind++];
|
||||
while(optind < argc)
|
||||
if (optind < argc) {
|
||||
host = argv[optind++];
|
||||
}
|
||||
|
||||
while(optind < argc) {
|
||||
add_cmd(argv[optind++]);
|
||||
if(host==NULL)
|
||||
}
|
||||
|
||||
if (host == NULL) {
|
||||
usage();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_CFMAKERAW
|
||||
static void cfmakeraw(struct termios *termios_p){
|
||||
static void cfmakeraw(struct termios *termios_p)
|
||||
{
|
||||
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
||||
termios_p->c_oflag &= ~OPOST;
|
||||
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
@@ -138,44 +151,53 @@ static void cfmakeraw(struct termios *termios_p){
|
||||
#endif
|
||||
|
||||
|
||||
static void do_cleanup(int i) {
|
||||
static void do_cleanup(int i)
|
||||
{
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
|
||||
tcsetattr(0,TCSANOW,&terminal);
|
||||
tcsetattr(0, TCSANOW, &terminal);
|
||||
}
|
||||
|
||||
static void do_exit(int i) {
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
static void do_exit(int i)
|
||||
{
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
|
||||
do_cleanup(0);
|
||||
exit(0);
|
||||
do_cleanup(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ssh_channel chan;
|
||||
int signal_delayed=0;
|
||||
static ssh_channel chan;
|
||||
static int signal_delayed = 0;
|
||||
|
||||
static void sigwindowchanged(int i){
|
||||
(void) i;
|
||||
signal_delayed=1;
|
||||
static void sigwindowchanged(int i)
|
||||
{
|
||||
(void) i;
|
||||
signal_delayed = 1;
|
||||
}
|
||||
|
||||
static void setsignal(void){
|
||||
static void setsignal(void)
|
||||
{
|
||||
signal(SIGWINCH, sigwindowchanged);
|
||||
signal_delayed=0;
|
||||
signal_delayed = 0;
|
||||
}
|
||||
|
||||
static void sizechanged(void){
|
||||
struct winsize win = { 0, 0, 0, 0 };
|
||||
static void sizechanged(void)
|
||||
{
|
||||
struct winsize win = {
|
||||
.ws_row = 0,
|
||||
};
|
||||
|
||||
ioctl(1, TIOCGWINSZ, &win);
|
||||
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
|
||||
// printf("Changed pty size\n");
|
||||
setsignal();
|
||||
}
|
||||
|
||||
static void select_loop(ssh_session session,ssh_channel channel){
|
||||
static void select_loop(ssh_session session,ssh_channel channel)
|
||||
{
|
||||
ssh_connector connector_in, connector_out, connector_err;
|
||||
|
||||
ssh_event event = ssh_event_new();
|
||||
|
||||
/* stdin */
|
||||
@@ -196,9 +218,10 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR);
|
||||
ssh_event_add_connector(event, connector_err);
|
||||
|
||||
while(ssh_channel_is_open(channel)){
|
||||
if(signal_delayed)
|
||||
while (ssh_channel_is_open(channel)) {
|
||||
if (signal_delayed) {
|
||||
sizechanged();
|
||||
}
|
||||
ssh_event_dopoll(event, 60000);
|
||||
}
|
||||
ssh_event_remove_connector(event, connector_in);
|
||||
@@ -213,121 +236,148 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
static void shell(ssh_session session){
|
||||
static void shell(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
struct termios terminal_local;
|
||||
int interactive=isatty(0);
|
||||
channel = ssh_channel_new(session);
|
||||
if(interactive){
|
||||
tcgetattr(0,&terminal_local);
|
||||
memcpy(&terminal,&terminal_local,sizeof(struct termios));
|
||||
|
||||
if (interactive) {
|
||||
tcgetattr(0, &terminal_local);
|
||||
memcpy(&terminal, &terminal_local, sizeof(struct termios));
|
||||
}
|
||||
if(ssh_channel_open_session(channel)){
|
||||
printf("error opening channel : %s\n",ssh_get_error(session));
|
||||
|
||||
if (ssh_channel_open_session(channel)) {
|
||||
printf("Error opening channel : %s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
chan=channel;
|
||||
if(interactive){
|
||||
chan = channel;
|
||||
if (interactive) {
|
||||
ssh_channel_request_pty(channel);
|
||||
sizechanged();
|
||||
}
|
||||
if(ssh_channel_request_shell(channel)){
|
||||
printf("Requesting shell : %s\n",ssh_get_error(session));
|
||||
|
||||
if (ssh_channel_request_shell(channel)) {
|
||||
printf("Requesting shell : %s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(interactive){
|
||||
|
||||
if (interactive) {
|
||||
cfmakeraw(&terminal_local);
|
||||
tcsetattr(0,TCSANOW,&terminal_local);
|
||||
tcsetattr(0, TCSANOW, &terminal_local);
|
||||
setsignal();
|
||||
}
|
||||
signal(SIGTERM,do_cleanup);
|
||||
select_loop(session,channel);
|
||||
if(interactive)
|
||||
do_cleanup(0);
|
||||
signal(SIGTERM, do_cleanup);
|
||||
select_loop(session, channel);
|
||||
if (interactive) {
|
||||
do_cleanup(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void batch_shell(ssh_session session){
|
||||
static void batch_shell(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
char buffer[1024];
|
||||
int i,s=0;
|
||||
for(i=0;i<MAXCMD && cmds[i];++i) {
|
||||
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
|
||||
free(cmds[i]);
|
||||
cmds[i] = NULL;
|
||||
}
|
||||
channel=ssh_channel_new(session);
|
||||
size_t i;
|
||||
int s = 0;
|
||||
|
||||
for (i = 0; i < MAXCMD && cmds[i]; ++i) {
|
||||
s += snprintf(buffer + s, sizeof(buffer) - s, "%s ", cmds[i]);
|
||||
free(cmds[i]);
|
||||
cmds[i] = NULL;
|
||||
}
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
ssh_channel_open_session(channel);
|
||||
if(ssh_channel_request_exec(channel,buffer)){
|
||||
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
|
||||
if (ssh_channel_request_exec(channel, buffer)) {
|
||||
printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
select_loop(session,channel);
|
||||
select_loop(session, channel);
|
||||
}
|
||||
|
||||
static int client(ssh_session session){
|
||||
int auth=0;
|
||||
char *banner;
|
||||
int state;
|
||||
if (user)
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0)
|
||||
return -1;
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
|
||||
return -1;
|
||||
if (proxycommand != NULL){
|
||||
if(ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand))
|
||||
return -1;
|
||||
}
|
||||
ssh_options_parse_config(session, NULL);
|
||||
static int client(ssh_session session)
|
||||
{
|
||||
int auth = 0;
|
||||
char *banner;
|
||||
int state;
|
||||
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
state=verify_knownhost(session);
|
||||
if (state != 0)
|
||||
return -1;
|
||||
ssh_userauth_none(session, NULL);
|
||||
banner=ssh_get_issue_banner(session);
|
||||
if(banner){
|
||||
printf("%s\n",banner);
|
||||
free(banner);
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
if(auth != SSH_AUTH_SUCCESS){
|
||||
return -1;
|
||||
}
|
||||
if(!cmds[0])
|
||||
shell(session);
|
||||
else
|
||||
batch_shell(session);
|
||||
return 0;
|
||||
if (user) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (proxycommand != NULL) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ssh_options_parse_config(session, NULL);
|
||||
|
||||
if (ssh_connect(session)) {
|
||||
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
|
||||
state = verify_knownhost(session);
|
||||
if (state != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssh_userauth_none(session, NULL);
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n", banner);
|
||||
free(banner);
|
||||
}
|
||||
auth = authenticate_console(session);
|
||||
if (auth != SSH_AUTH_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
if (cmds[0] == NULL) {
|
||||
shell(session);
|
||||
} else {
|
||||
batch_shell(session);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssh_pcap_file pcap;
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(!pcap)
|
||||
return;
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
static ssh_pcap_file pcap;
|
||||
static void set_pcap(ssh_session session)
|
||||
{
|
||||
if (pcap_file == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pcap = ssh_pcap_file_new();
|
||||
if (pcap == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ssh_pcap_file_open(pcap, pcap_file) == SSH_ERROR) {
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap = NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session, pcap);
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
if(pcap)
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
static void cleanup_pcap(void)
|
||||
{
|
||||
if (pcap != NULL) {
|
||||
ssh_pcap_file_free(pcap);
|
||||
}
|
||||
pcap = NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session;
|
||||
|
||||
session = ssh_new();
|
||||
@@ -335,12 +385,13 @@ int main(int argc, char **argv){
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_callbacks(session,&cb);
|
||||
|
||||
if(ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr, "error parsing command line :%s\n",
|
||||
ssh_get_error(session));
|
||||
usage();
|
||||
if (ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr,
|
||||
"Error parsing command line: %s\n",
|
||||
ssh_get_error(session));
|
||||
usage();
|
||||
}
|
||||
opts(argc,argv);
|
||||
opts(argc, argv);
|
||||
signal(SIGTERM, do_exit);
|
||||
|
||||
set_pcap(session);
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
#define SSH_COM_AGENT2_FAILURE 102
|
||||
|
||||
#define SSH_AGENT_OLD_SIGNATURE 0x01
|
||||
/* Signature flags from draft-miller-ssh-agent-02 */
|
||||
#define SSH_AGENT_RSA_SHA2_256 0x02
|
||||
#define SSH_AGENT_RSA_SHA2_512 0x04
|
||||
|
||||
struct ssh_agent_struct {
|
||||
struct ssh_socket_struct *sock;
|
||||
|
||||
@@ -24,20 +24,6 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
/*
|
||||
* Describes a buffer state
|
||||
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
|
||||
* ^ ^ ^ ^]
|
||||
* \_data points\_pos points here \_used points here | /
|
||||
* here Allocated
|
||||
*/
|
||||
struct ssh_buffer_struct {
|
||||
char *data;
|
||||
uint32_t used;
|
||||
uint32_t allocated;
|
||||
uint32_t pos;
|
||||
int secure;
|
||||
};
|
||||
|
||||
#define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3)
|
||||
|
||||
|
||||
@@ -62,7 +62,11 @@ enum ssh_key_exchange_e {
|
||||
/* curve25519-sha256@libssh.org */
|
||||
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
|
||||
/* curve25519-sha256 */
|
||||
SSH_KEX_CURVE25519_SHA256
|
||||
SSH_KEX_CURVE25519_SHA256,
|
||||
/* diffie-hellman-group16-sha512 */
|
||||
SSH_KEX_DH_GROUP16_SHA512,
|
||||
/* diffie-hellman-group18-sha512 */
|
||||
SSH_KEX_DH_GROUP18_SHA512,
|
||||
};
|
||||
|
||||
enum ssh_cipher_e {
|
||||
|
||||
@@ -43,6 +43,7 @@ char **ssh_space_tokenize(const char *chain);
|
||||
int ssh_get_kex1(ssh_session session);
|
||||
char *ssh_find_matching(const char *in_d, const char *what_d);
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo);
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo);
|
||||
const char *ssh_kex_get_description(uint32_t algo);
|
||||
|
||||
#endif /* KEX_H_ */
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 8
|
||||
#define LIBSSH_VERSION_MICRO 2
|
||||
#define LIBSSH_VERSION_MICRO 3
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
@@ -404,6 +404,7 @@ enum ssh_options_e {
|
||||
SSH_OPTIONS_GSSAPI_AUTH,
|
||||
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
|
||||
SSH_OPTIONS_NODELAY,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -646,6 +647,11 @@ LIBSSH_API int ssh_pki_import_privkey_base64(const char *b64_key,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
ssh_key *pkey);
|
||||
LIBSSH_API int ssh_pki_export_privkey_base64(const ssh_key privkey,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
char **b64_key);
|
||||
LIBSSH_API int ssh_pki_import_privkey_file(const char *filename,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
@@ -681,6 +687,9 @@ LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key,
|
||||
|
||||
LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key);
|
||||
|
||||
LIBSSH_API char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
|
||||
unsigned char *hash,
|
||||
size_t len);
|
||||
LIBSSH_API void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len);
|
||||
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
|
||||
LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data);
|
||||
@@ -756,12 +765,16 @@ LIBSSH_API void ssh_string_burn(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_copy(ssh_string str);
|
||||
LIBSSH_API void *ssh_string_data(ssh_string str);
|
||||
LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len);
|
||||
#define SSH_STRING_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_string_free(x); x = NULL; } } while(0)
|
||||
LIBSSH_API void ssh_string_free(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_from_char(const char *what);
|
||||
LIBSSH_API size_t ssh_string_len(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_new(size_t size);
|
||||
LIBSSH_API const char *ssh_string_get_char(ssh_string str);
|
||||
LIBSSH_API char *ssh_string_to_char(ssh_string str);
|
||||
#define SSH_STRING_FREE_CHAR(x) \
|
||||
do { if ((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0)
|
||||
LIBSSH_API void ssh_string_free_char(char *s);
|
||||
|
||||
LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo,
|
||||
@@ -790,6 +803,8 @@ LIBSSH_API const char* ssh_get_hmac_out(ssh_session session);
|
||||
|
||||
LIBSSH_API ssh_buffer ssh_buffer_new(void);
|
||||
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
|
||||
#define SSH_BUFFER_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_buffer_free(x); x = NULL; } } while(0)
|
||||
LIBSSH_API int ssh_buffer_reinit(ssh_buffer buffer);
|
||||
LIBSSH_API int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
|
||||
LIBSSH_API uint32_t ssh_buffer_get_data(ssh_buffer buffer, void *data, uint32_t requestedlen);
|
||||
|
||||
@@ -335,11 +335,10 @@ public:
|
||||
* @see ssh_get_issue_banner
|
||||
*/
|
||||
std::string getIssueBanner(){
|
||||
char *banner=ssh_get_issue_banner(c_session);
|
||||
std::string ret;
|
||||
if (banner)
|
||||
{
|
||||
ret= std::string(banner);
|
||||
char *banner = ssh_get_issue_banner(c_session);
|
||||
std::string ret = "";
|
||||
if (banner != NULL) {
|
||||
ret = std::string(banner);
|
||||
::free(banner);
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -51,6 +51,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ignore_callback);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_dh_reply);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_newkeys);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_service_accept);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_ext_info);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init);
|
||||
|
||||
@@ -69,6 +69,7 @@ struct ssh_key_struct {
|
||||
|
||||
struct ssh_signature_struct {
|
||||
enum ssh_keytypes_e type;
|
||||
enum ssh_digest_e hash_type;
|
||||
const char *type_c;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa_sig;
|
||||
@@ -95,6 +96,11 @@ typedef struct ssh_signature_struct *ssh_signature;
|
||||
ssh_key ssh_key_dup(const ssh_key key);
|
||||
void ssh_key_clean (ssh_key key);
|
||||
|
||||
const char *
|
||||
ssh_key_get_signature_algorithm(ssh_session session,
|
||||
enum ssh_keytypes_e type);
|
||||
enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name);
|
||||
|
||||
/* SSH Signature Functions */
|
||||
ssh_signature ssh_signature_new(void);
|
||||
void ssh_signature_free(ssh_signature sign);
|
||||
@@ -133,4 +139,5 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key);
|
||||
ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key);
|
||||
|
||||
int ssh_key_algorithm_allowed(ssh_session session, const char *type);
|
||||
#endif /* PKI_H_ */
|
||||
|
||||
@@ -45,6 +45,10 @@ int bcrypt_pbkdf(const char *pass,
|
||||
|
||||
int pki_key_ecdsa_nid_from_name(const char *name);
|
||||
const char *pki_key_ecdsa_nid_to_name(int nid);
|
||||
const char *ssh_key_signature_to_char(enum ssh_keytypes_e type,
|
||||
enum ssh_digest_e hash_type);
|
||||
enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
|
||||
enum ssh_keytypes_e type);
|
||||
|
||||
/* SSH Key Functions */
|
||||
ssh_key pki_key_dup(const ssh_key key, int demote);
|
||||
@@ -68,6 +72,9 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data);
|
||||
int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
ssh_buffer buffer,
|
||||
ssh_key *pkey);
|
||||
|
||||
/* SSH Public Key Functions */
|
||||
int pki_pubkey_build_dss(ssh_key key,
|
||||
@@ -81,11 +88,32 @@ int pki_pubkey_build_rsa(ssh_key key,
|
||||
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e);
|
||||
ssh_string pki_publickey_to_blob(const ssh_key key);
|
||||
|
||||
/* SSH Private Key Functions */
|
||||
int pki_privkey_build_dss(ssh_key key,
|
||||
ssh_string p,
|
||||
ssh_string q,
|
||||
ssh_string g,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey);
|
||||
int pki_privkey_build_rsa(ssh_key key,
|
||||
ssh_string n,
|
||||
ssh_string e,
|
||||
ssh_string d,
|
||||
ssh_string iqmp,
|
||||
ssh_string p,
|
||||
ssh_string q);
|
||||
int pki_privkey_build_ecdsa(ssh_key key,
|
||||
int nid,
|
||||
ssh_string e,
|
||||
ssh_string exp);
|
||||
ssh_string pki_publickey_to_blob(const ssh_key key);
|
||||
|
||||
/* SSH Signature Functions */
|
||||
ssh_string pki_signature_to_blob(const ssh_signature sign);
|
||||
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
const ssh_string sig_blob,
|
||||
enum ssh_keytypes_e type);
|
||||
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,
|
||||
@@ -93,12 +121,18 @@ int pki_signature_verify(ssh_session session,
|
||||
size_t hlen);
|
||||
|
||||
/* SSH Signing Functions */
|
||||
ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen);
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen);
|
||||
#define pki_do_sign(key, hash, hlen) \
|
||||
pki_do_sign_hash(key, hash, hlen, SSH_DIGEST_AUTO)
|
||||
ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type);
|
||||
#define pki_do_sign_sessionid(key, hash, hlen) \
|
||||
pki_do_sign_sessionid_hash(key, hash, hlen, SSH_DIGEST_AUTO)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type);
|
||||
int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig,
|
||||
const unsigned char *hash, size_t hlen);
|
||||
int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig,
|
||||
@@ -110,8 +144,12 @@ 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);
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey);
|
||||
|
||||
/* PKI Container OpenSSH */
|
||||
ssh_key ssh_pki_openssh_pubkey_import(const char *text_key);
|
||||
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
const char *passphrase, ssh_auth_callback auth_fn, void *auth_data);
|
||||
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
||||
|
||||
@@ -262,6 +262,8 @@ int compress_buffer(ssh_session session,ssh_buffer buf);
|
||||
int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
|
||||
|
||||
/* match.c */
|
||||
int match_pattern_list(const char *string, const char *pattern,
|
||||
unsigned int len, int dolower);
|
||||
int match_hostname(const char *host, const char *pattern, unsigned int len);
|
||||
|
||||
/* connector.c */
|
||||
|
||||
@@ -86,6 +86,12 @@ enum ssh_pending_call_e {
|
||||
#define SSH_OPT_FLAG_KBDINT_AUTH 0x4
|
||||
#define SSH_OPT_FLAG_GSSAPI_AUTH 0x8
|
||||
|
||||
/* extensions flags */
|
||||
/* server-sig-algs extension */
|
||||
#define SSH_EXT_SIG_RSA_SHA256 0x01
|
||||
#define SSH_EXT_SIG_RSA_SHA512 0x02
|
||||
#define SSH_EXT_ALL SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512
|
||||
|
||||
/* members that are common to ssh_session and ssh_bind */
|
||||
struct ssh_common_struct {
|
||||
struct error_struct error;
|
||||
@@ -114,6 +120,9 @@ struct ssh_session_struct {
|
||||
/* session flags (SSH_SESSION_FLAG_*) */
|
||||
int flags;
|
||||
|
||||
/* Extensions negotiated using RFC 8308 */
|
||||
uint32_t extensions;
|
||||
|
||||
ssh_string banner; /* that's the issue banner from
|
||||
the server */
|
||||
char *discon_msg; /* disconnect message from
|
||||
@@ -196,6 +205,7 @@ struct ssh_session_struct {
|
||||
char *knownhosts;
|
||||
char *global_knownhosts;
|
||||
char *wanted_methods[10];
|
||||
char *pubkey_accepted_types;
|
||||
char *ProxyCommand;
|
||||
char *custombanner;
|
||||
unsigned long timeout; /* seconds */
|
||||
|
||||
@@ -84,6 +84,7 @@ struct sftp_session_struct {
|
||||
int errnum;
|
||||
void **handles;
|
||||
sftp_ext ext;
|
||||
sftp_packet read_packet;
|
||||
};
|
||||
|
||||
struct sftp_packet_struct {
|
||||
@@ -134,6 +135,7 @@ struct sftp_client_message_struct {
|
||||
ssh_string data; /* can be newpath of rename() */
|
||||
ssh_buffer complete_message; /* complete message in case of retransmission*/
|
||||
char *str_data; /* cstring version of data */
|
||||
char *submessage; /* for extended messages */
|
||||
};
|
||||
|
||||
struct sftp_request_queue_struct {
|
||||
@@ -862,6 +864,7 @@ LIBSSH_API const char *sftp_client_message_get_filename(sftp_client_message msg)
|
||||
LIBSSH_API void sftp_client_message_set_filename(sftp_client_message msg, const char *newname);
|
||||
LIBSSH_API const char *sftp_client_message_get_data(sftp_client_message msg);
|
||||
LIBSSH_API uint32_t sftp_client_message_get_flags(sftp_client_message msg);
|
||||
LIBSSH_API const char *sftp_client_message_get_submessage(sftp_client_message msg);
|
||||
LIBSSH_API int sftp_send_client_message(sftp_session sftp, sftp_client_message msg);
|
||||
LIBSSH_API int sftp_reply_name(sftp_client_message msg, const char *name,
|
||||
sftp_attributes attr);
|
||||
@@ -1011,6 +1014,7 @@ LIBSSH_API void sftp_handle_remove(sftp_session sftp, void *handle);
|
||||
#define SFTP_RENAME SSH_FXP_RENAME
|
||||
#define SFTP_READLINK SSH_FXP_READLINK
|
||||
#define SFTP_SYMLINK SSH_FXP_SYMLINK
|
||||
#define SFTP_EXTENDED SSH_FXP_EXTENDED
|
||||
|
||||
/* openssh flags */
|
||||
#define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define SSH2_MSG_DEBUG 4
|
||||
#define SSH2_MSG_SERVICE_REQUEST 5
|
||||
#define SSH2_MSG_SERVICE_ACCEPT 6
|
||||
#define SSH2_MSG_EXT_INFO 7
|
||||
|
||||
#define SSH2_MSG_KEXINIT 20
|
||||
#define SSH2_MSG_NEWKEYS 21
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
#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_SHA512
|
||||
};
|
||||
|
||||
enum ssh_mac_e {
|
||||
SSH_MAC_SHA1=1,
|
||||
SSH_MAC_SHA256,
|
||||
|
||||
@@ -1 +1 @@
|
||||
4.6.0
|
||||
4.7.0
|
||||
415
src/ABI/libssh-4.7.0.symbols
Normal file
415
src/ABI/libssh-4.7.0.symbols
Normal file
@@ -0,0 +1,415 @@
|
||||
_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_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_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_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_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_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_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
|
||||
@@ -548,6 +548,14 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add Flags: SHA2 extension (RFC 8332) if negotiated */
|
||||
if (pubkey->type == SSH_KEYTYPE_RSA) {
|
||||
if (session->extensions & SSH_EXT_SIG_RSA_SHA512) {
|
||||
flags |= SSH_AGENT_RSA_SHA2_512;
|
||||
} else if (session->extensions & SSH_EXT_SIG_RSA_SHA256) {
|
||||
flags |= SSH_AGENT_RSA_SHA2_256;
|
||||
}
|
||||
}
|
||||
if (ssh_buffer_add_u32(request, htonl(flags)) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
return NULL;
|
||||
|
||||
109
src/auth.c
109
src/auth.c
@@ -470,6 +470,7 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
const ssh_key pubkey)
|
||||
{
|
||||
ssh_string pubkey_s = NULL;
|
||||
const char *sig_type_c = NULL;
|
||||
int rc;
|
||||
|
||||
if (session == NULL) {
|
||||
@@ -494,6 +495,34 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch (pubkey->type) {
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
return SSH_AUTH_DENIED;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
sig_type_c = ssh_pki_key_ecdsa_name(pubkey);
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS:
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
@@ -514,7 +543,7 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
0, /* private key ? */
|
||||
pubkey->type_c, /* algo */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
if (rc < 0) {
|
||||
@@ -575,7 +604,7 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
{
|
||||
ssh_string str = NULL;
|
||||
int rc;
|
||||
const char *type_c;
|
||||
const char *sig_type_c = NULL;
|
||||
enum ssh_keytypes_e key_type;
|
||||
|
||||
if (session == NULL) {
|
||||
@@ -599,6 +628,37 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Cert auth requires presenting the cert type name (*-cert@openssh.com) */
|
||||
key_type = privkey->cert != NULL ? privkey->cert_type : privkey->type;
|
||||
|
||||
switch (key_type) {
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
return SSH_AUTH_DENIED;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
sig_type_c = ssh_pki_key_ecdsa_name(privkey);
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS:
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, key_type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
@@ -606,10 +666,6 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Cert auth requires presenting the cert type name (*-cert@openssh.com) */
|
||||
key_type = privkey->cert != NULL ? privkey->cert_type : privkey->type;
|
||||
type_c = ssh_key_type_to_char(key_type);
|
||||
|
||||
/* get public key or cert */
|
||||
rc = ssh_pki_export_pubkey_blob(privkey, &str);
|
||||
if (rc < 0) {
|
||||
@@ -623,7 +679,7 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
type_c, /* algo */
|
||||
sig_type_c, /* algo */
|
||||
str /* public key or cert */
|
||||
);
|
||||
if (rc < 0) {
|
||||
@@ -672,7 +728,9 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
const char *username,
|
||||
ssh_key pubkey)
|
||||
{
|
||||
ssh_string str = NULL;
|
||||
ssh_string pubkey_s = NULL;
|
||||
ssh_string sig_blob = NULL;
|
||||
const char *sig_type_c = NULL;
|
||||
int rc;
|
||||
|
||||
switch(session->pending_call_state) {
|
||||
@@ -694,12 +752,22 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* public key */
|
||||
rc = ssh_pki_export_pubkey_blob(pubkey, &str);
|
||||
rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
|
||||
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||
@@ -708,24 +776,22 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
pubkey->type_c, /* algo */
|
||||
str /* public key */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ssh_string_free(str);
|
||||
|
||||
/* sign the buffer with the private key */
|
||||
str = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
|
||||
if (str == NULL) {
|
||||
sig_blob = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
|
||||
if (sig_blob == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, str);
|
||||
ssh_string_free(str);
|
||||
str = NULL;
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -748,7 +814,7 @@ pending:
|
||||
fail:
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
@@ -1514,7 +1580,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
session->kbdint->echo = malloc(nprompts);
|
||||
session->kbdint->echo = calloc(nprompts, sizeof(unsigned char));
|
||||
if (session->kbdint->echo == NULL) {
|
||||
session->kbdint->nprompts = 0;
|
||||
ssh_set_error_oom(session);
|
||||
@@ -1523,7 +1589,6 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
memset(session->kbdint->echo, 0, nprompts);
|
||||
|
||||
for (i = 0; i < nprompts; i++) {
|
||||
rc = ssh_buffer_unpack(packet, "sb",
|
||||
|
||||
431
src/buffer.c
431
src/buffer.c
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
@@ -36,6 +37,24 @@
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/bignum.h"
|
||||
|
||||
/*
|
||||
* Describes a buffer state
|
||||
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
|
||||
* ^ ^ ^ ^]
|
||||
* \_data points\_pos points here \_used points here | /
|
||||
* here Allocated
|
||||
*/
|
||||
struct ssh_buffer_struct {
|
||||
bool secure;
|
||||
size_t used;
|
||||
size_t allocated;
|
||||
size_t pos;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
/* Buffer size maximum is 256M */
|
||||
#define BUFFER_SIZE_MAX 0x10000000
|
||||
|
||||
/**
|
||||
* @defgroup libssh_buffer The SSH buffer functions.
|
||||
* @ingroup libssh
|
||||
@@ -54,24 +73,38 @@
|
||||
*
|
||||
* @param[in] buf The buffer to check.
|
||||
*/
|
||||
static void buffer_verify(ssh_buffer buf){
|
||||
int doabort=0;
|
||||
if(buf->data == NULL)
|
||||
return;
|
||||
if(buf->used > buf->allocated){
|
||||
fprintf(stderr,"Buffer error : allocated %u, used %u\n",buf->allocated, buf->used);
|
||||
doabort=1;
|
||||
}
|
||||
if(buf->pos > buf->used){
|
||||
fprintf(stderr,"Buffer error : position %u, used %u\n",buf->pos, buf->used);
|
||||
doabort=1;
|
||||
}
|
||||
if(buf->pos > buf->allocated){
|
||||
fprintf(stderr,"Buffer error : position %u, allocated %u\n",buf->pos, buf->allocated);
|
||||
doabort=1;
|
||||
}
|
||||
if(doabort)
|
||||
abort();
|
||||
static void buffer_verify(ssh_buffer buf)
|
||||
{
|
||||
bool do_abort = false;
|
||||
|
||||
if (buf->data == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf->used > buf->allocated) {
|
||||
fprintf(stderr,
|
||||
"BUFFER ERROR: allocated %zu, used %zu\n",
|
||||
buf->allocated,
|
||||
buf->used);
|
||||
do_abort = true;
|
||||
}
|
||||
if (buf->pos > buf->used) {
|
||||
fprintf(stderr,
|
||||
"BUFFER ERROR: position %zu, used %zu\n",
|
||||
buf->pos,
|
||||
buf->used);
|
||||
do_abort = true;
|
||||
}
|
||||
if (buf->pos > buf->allocated) {
|
||||
fprintf(stderr,
|
||||
"BUFFER ERROR: position %zu, allocated %zu\n",
|
||||
buf->pos,
|
||||
buf->allocated);
|
||||
do_abort = true;
|
||||
}
|
||||
if (do_abort) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -83,15 +116,29 @@ static void buffer_verify(ssh_buffer buf){
|
||||
*
|
||||
* @return A newly initialized SSH buffer, NULL on error.
|
||||
*/
|
||||
struct ssh_buffer_struct *ssh_buffer_new(void) {
|
||||
struct ssh_buffer_struct *buf =
|
||||
calloc(1, sizeof(struct ssh_buffer_struct));
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
struct ssh_buffer_struct *ssh_buffer_new(void)
|
||||
{
|
||||
struct ssh_buffer_struct *buf = NULL;
|
||||
int rc;
|
||||
|
||||
buffer_verify(buf);
|
||||
return buf;
|
||||
buf = calloc(1, sizeof(struct ssh_buffer_struct));
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always preallocate 64 bytes.
|
||||
*
|
||||
* -1 for ralloc_buffer magic.
|
||||
*/
|
||||
rc = ssh_buffer_allocate_size(buf, 64 - 1);
|
||||
if (rc != 0) {
|
||||
SAFE_FREE(buf);
|
||||
return NULL;
|
||||
}
|
||||
buffer_verify(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,19 +146,23 @@ struct ssh_buffer_struct *ssh_buffer_new(void) {
|
||||
*
|
||||
* \param[in] buffer The buffer to free.
|
||||
*/
|
||||
void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
buffer_verify(buffer);
|
||||
void ssh_buffer_free(struct ssh_buffer_struct *buffer)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
buffer_verify(buffer);
|
||||
|
||||
if (buffer->data) {
|
||||
/* burn the data */
|
||||
explicit_bzero(buffer->data, buffer->allocated);
|
||||
SAFE_FREE(buffer->data);
|
||||
}
|
||||
explicit_bzero(buffer, sizeof(struct ssh_buffer_struct));
|
||||
SAFE_FREE(buffer);
|
||||
if (buffer->secure && buffer->allocated > 0) {
|
||||
/* burn the data */
|
||||
explicit_bzero(buffer->data, buffer->allocated);
|
||||
SAFE_FREE(buffer->data);
|
||||
|
||||
explicit_bzero(buffer, sizeof(struct ssh_buffer_struct));
|
||||
} else {
|
||||
SAFE_FREE(buffer->data);
|
||||
}
|
||||
SAFE_FREE(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,13 +173,15 @@ void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
|
||||
*
|
||||
* @param[in] buffer buffer to set secure.
|
||||
*/
|
||||
void ssh_buffer_set_secure(ssh_buffer buffer){
|
||||
buffer->secure = 1;
|
||||
void ssh_buffer_set_secure(ssh_buffer buffer)
|
||||
{
|
||||
buffer->secure = true;
|
||||
}
|
||||
|
||||
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
||||
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed)
|
||||
{
|
||||
size_t smallest = 1;
|
||||
char *new;
|
||||
uint8_t *new = NULL;
|
||||
|
||||
buffer_verify(buffer);
|
||||
|
||||
@@ -140,25 +193,28 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
||||
smallest <<= 1;
|
||||
}
|
||||
needed = smallest;
|
||||
if (buffer->secure){
|
||||
|
||||
if (needed > BUFFER_SIZE_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->secure) {
|
||||
new = malloc(needed);
|
||||
if (new == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (buffer->used > 0) {
|
||||
memcpy(new, buffer->data,buffer->used);
|
||||
explicit_bzero(buffer->data, buffer->used);
|
||||
SAFE_FREE(buffer->data);
|
||||
}
|
||||
memcpy(new, buffer->data, buffer->used);
|
||||
explicit_bzero(buffer->data, buffer->used);
|
||||
SAFE_FREE(buffer->data);
|
||||
} else {
|
||||
new = realloc(buffer->data, needed);
|
||||
if (new == NULL) {
|
||||
buffer->data = NULL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
buffer->data = new;
|
||||
buffer->allocated = needed;
|
||||
|
||||
buffer_verify(buffer);
|
||||
return 0;
|
||||
}
|
||||
@@ -167,45 +223,64 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
||||
* @brief shifts a buffer to remove unused data in the beginning
|
||||
* @param buffer SSH buffer
|
||||
*/
|
||||
static void buffer_shift(ssh_buffer buffer){
|
||||
uint32_t burn_pos = buffer->pos;
|
||||
static void buffer_shift(ssh_buffer buffer)
|
||||
{
|
||||
size_t burn_pos = buffer->pos;
|
||||
|
||||
buffer_verify(buffer);
|
||||
if(buffer->pos==0)
|
||||
return;
|
||||
memmove(buffer->data, buffer->data + buffer->pos, buffer->used - buffer->pos);
|
||||
buffer->used -= buffer->pos;
|
||||
buffer->pos=0;
|
||||
buffer_verify(buffer);
|
||||
|
||||
if (buffer->secure){
|
||||
void *ptr = buffer->data + buffer->used;
|
||||
explicit_bzero(ptr, burn_pos);
|
||||
}
|
||||
if (buffer->pos == 0) {
|
||||
return;
|
||||
}
|
||||
memmove(buffer->data,
|
||||
buffer->data + buffer->pos,
|
||||
buffer->used - buffer->pos);
|
||||
buffer->used -= buffer->pos;
|
||||
buffer->pos = 0;
|
||||
|
||||
buffer_verify(buffer);
|
||||
if (buffer->secure) {
|
||||
void *ptr = buffer->data + buffer->used;
|
||||
explicit_bzero(ptr, burn_pos);
|
||||
}
|
||||
|
||||
buffer_verify(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reinitialize a SSH buffer.
|
||||
*
|
||||
* In case the buffer has exceeded 64K in size, the buffer will be reallocated
|
||||
* to 64K.
|
||||
*
|
||||
* @param[in] buffer The buffer to reinitialize.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
int ssh_buffer_reinit(struct ssh_buffer_struct *buffer)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_verify(buffer);
|
||||
if (buffer->used > 0) {
|
||||
explicit_bzero(buffer->data, buffer->used);
|
||||
|
||||
if (buffer->secure && buffer->allocated > 0) {
|
||||
explicit_bzero(buffer->data, buffer->allocated);
|
||||
}
|
||||
buffer->used = 0;
|
||||
buffer->pos = 0;
|
||||
|
||||
if (buffer->allocated > 127) {
|
||||
if (realloc_buffer(buffer, 127) < 0) {
|
||||
/* If the buffer is bigger then 64K, reset it to 64K */
|
||||
if (buffer->allocated > 65536) {
|
||||
int rc;
|
||||
|
||||
/* -1 for realloc_buffer magic */
|
||||
rc = realloc_buffer(buffer, 65536 - 1);
|
||||
if (rc != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_verify(buffer);
|
||||
|
||||
return 0;
|
||||
@@ -683,32 +758,153 @@ int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len)
|
||||
*
|
||||
* @returns The SSH String, NULL on error.
|
||||
*/
|
||||
struct ssh_string_struct *ssh_buffer_get_ssh_string(struct ssh_buffer_struct *buffer) {
|
||||
uint32_t stringlen;
|
||||
uint32_t hostlen;
|
||||
struct ssh_string_struct *str = NULL;
|
||||
int rc;
|
||||
struct ssh_string_struct *
|
||||
ssh_buffer_get_ssh_string(struct ssh_buffer_struct *buffer)
|
||||
{
|
||||
uint32_t stringlen;
|
||||
uint32_t hostlen;
|
||||
struct ssh_string_struct *str = NULL;
|
||||
int rc;
|
||||
|
||||
if (ssh_buffer_get_u32(buffer, &stringlen) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
hostlen = ntohl(stringlen);
|
||||
/* verify if there is enough space in buffer to get it */
|
||||
rc = ssh_buffer_validate_length(buffer, hostlen);
|
||||
if (rc != SSH_OK) {
|
||||
return NULL; /* it is indeed */
|
||||
}
|
||||
str = ssh_string_new(hostlen);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (ssh_buffer_get_data(buffer, ssh_string_data(str), hostlen) != hostlen) {
|
||||
/* should never happen */
|
||||
SAFE_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
rc = ssh_buffer_get_u32(buffer, &stringlen);
|
||||
if (rc == 0) {
|
||||
return NULL;
|
||||
}
|
||||
hostlen = ntohl(stringlen);
|
||||
/* verify if there is enough space in buffer to get it */
|
||||
rc = ssh_buffer_validate_length(buffer, hostlen);
|
||||
if (rc != SSH_OK) {
|
||||
return NULL; /* it is indeed */
|
||||
}
|
||||
str = ssh_string_new(hostlen);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
stringlen = ssh_buffer_get_data(buffer, ssh_string_data(str), hostlen);
|
||||
if (stringlen != hostlen) {
|
||||
/* should never happen */
|
||||
SAFE_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pre-calculate the size we need for packing the buffer.
|
||||
*
|
||||
* This makes sure that enough memory is allocated for packing the buffer and
|
||||
* we only have to do one memory allocation.
|
||||
*
|
||||
* @param[in] buffer The buffer to allocate
|
||||
*
|
||||
* @param[in] format A format string of arguments.
|
||||
*
|
||||
* @param[in] argc The number of arguments.
|
||||
*
|
||||
* @param[in] ap The va_list of arguments.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
va_list ap)
|
||||
{
|
||||
const char *p = NULL;
|
||||
ssh_string string = NULL;
|
||||
char *cstring = NULL;
|
||||
size_t needed_size = 0;
|
||||
size_t count;
|
||||
size_t len;
|
||||
int rc = SSH_OK;
|
||||
|
||||
for (p = format, count = 0; *p != '\0'; p++, count++) {
|
||||
/* Invalid number of arguments passed */
|
||||
if (argc != -1 && count > argc) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch(*p) {
|
||||
case 'b':
|
||||
va_arg(ap, unsigned int);
|
||||
needed_size += sizeof(uint8_t);
|
||||
break;
|
||||
case 'w':
|
||||
va_arg(ap, unsigned int);
|
||||
needed_size += sizeof(uint16_t);
|
||||
break;
|
||||
case 'd':
|
||||
va_arg(ap, uint32_t);
|
||||
needed_size += sizeof(uint32_t);
|
||||
break;
|
||||
case 'q':
|
||||
va_arg(ap, uint64_t);
|
||||
needed_size += sizeof(uint64_t);
|
||||
break;
|
||||
case 'S':
|
||||
string = va_arg(ap, ssh_string);
|
||||
needed_size += 4 + ssh_string_len(string);
|
||||
string = NULL;
|
||||
break;
|
||||
case 's':
|
||||
cstring = va_arg(ap, char *);
|
||||
needed_size += sizeof(uint32_t) + strlen(cstring);
|
||||
cstring = NULL;
|
||||
break;
|
||||
case 'P':
|
||||
len = va_arg(ap, size_t);
|
||||
needed_size += len;
|
||||
va_arg(ap, void *);
|
||||
count++; /* increase argument count */
|
||||
break;
|
||||
case 'B':
|
||||
va_arg(ap, bignum);
|
||||
/*
|
||||
* Use a fixed size for a bignum
|
||||
* (they should normaly be around 32)
|
||||
*/
|
||||
needed_size += 64;
|
||||
break;
|
||||
case 't':
|
||||
cstring = va_arg(ap, char *);
|
||||
needed_size += strlen(cstring);
|
||||
cstring = NULL;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
if (rc != SSH_OK){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != -1 && argc != count) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (rc != SSH_ERROR){
|
||||
/*
|
||||
* Check if our canary is intact, if not, something really bad happened.
|
||||
*/
|
||||
uint32_t canary = va_arg(ap, uint32_t);
|
||||
if (canary != SSH_BUFFER_PACK_END) {
|
||||
if (argc == -1){
|
||||
return SSH_ERROR;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_buffer_allocate_size(buffer, needed_size);
|
||||
if (rc != 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@@ -860,9 +1056,18 @@ int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
|
||||
va_list ap;
|
||||
int rc;
|
||||
|
||||
va_start(ap, argc);
|
||||
rc = ssh_buffer_pack_allocate_va(buffer, format, argc, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
va_start(ap, argc);
|
||||
rc = ssh_buffer_pack_va(buffer, format, argc, ap);
|
||||
va_end(ap);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -903,8 +1108,8 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
for (p = format, count = 0; *p != '\0'; p++, count++) {
|
||||
/* Invalid number of arguments passed */
|
||||
if (argc != -1 && count > argc) {
|
||||
va_end(ap_copy);
|
||||
return SSH_ERROR;
|
||||
rc = SSH_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
switch (*p) {
|
||||
@@ -1016,8 +1221,9 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (rc != SSH_ERROR){
|
||||
/* Check if our canary is intact, if not somthing really bad happened */
|
||||
/* Check if our canary is intact, if not something really bad happened */
|
||||
uint32_t canary = va_arg(ap, uint32_t);
|
||||
if (canary != SSH_BUFFER_PACK_END){
|
||||
if (argc == -1){
|
||||
@@ -1034,22 +1240,53 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
for(p=format;p<last;++p){
|
||||
switch(*p){
|
||||
case 'b':
|
||||
o.byte = va_arg(ap_copy, uint8_t *);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(o.byte, sizeof(uint8_t));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
o.word = va_arg(ap_copy, uint16_t *);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(o.word, sizeof(uint16_t));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
o.dword = va_arg(ap_copy, uint32_t *);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(o.dword, sizeof(uint32_t));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
(void)va_arg(ap_copy, void *);
|
||||
o.qword = va_arg(ap_copy, uint64_t *);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(o.qword, sizeof(uint64_t));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
o.string=va_arg(ap_copy, ssh_string *);
|
||||
o.string = va_arg(ap_copy, ssh_string *);
|
||||
if (buffer->secure) {
|
||||
ssh_string_burn(*o.string);
|
||||
}
|
||||
SAFE_FREE(*o.string);
|
||||
break;
|
||||
case 's':
|
||||
o.cstring=va_arg(ap_copy, char **);
|
||||
o.cstring = va_arg(ap_copy, char **);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(*o.cstring, strlen(*o.cstring));
|
||||
}
|
||||
SAFE_FREE(*o.cstring);
|
||||
break;
|
||||
case 'P':
|
||||
(void)va_arg(ap_copy, size_t);
|
||||
len = va_arg(ap_copy, size_t);
|
||||
o.data = va_arg(ap_copy, void **);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(*o.data, len);
|
||||
}
|
||||
SAFE_FREE(*o.data);
|
||||
break;
|
||||
default:
|
||||
|
||||
113
src/channels.c
113
src/channels.c
@@ -76,44 +76,46 @@ static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet);
|
||||
*
|
||||
* @return A pointer to a newly allocated channel, NULL on error.
|
||||
*/
|
||||
ssh_channel ssh_channel_new(ssh_session session) {
|
||||
ssh_channel channel = NULL;
|
||||
ssh_channel ssh_channel_new(ssh_session session)
|
||||
{
|
||||
ssh_channel channel = NULL;
|
||||
|
||||
if(session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel = malloc(sizeof(struct ssh_channel_struct));
|
||||
if (channel == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
memset(channel,0,sizeof(struct ssh_channel_struct));
|
||||
channel = calloc(1, sizeof(struct ssh_channel_struct));
|
||||
if (channel == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel->stdout_buffer = ssh_buffer_new();
|
||||
if (channel->stdout_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
channel->stdout_buffer = ssh_buffer_new();
|
||||
if (channel->stdout_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel->stderr_buffer = ssh_buffer_new();
|
||||
if (channel->stderr_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
channel->stderr_buffer = ssh_buffer_new();
|
||||
if (channel->stderr_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel->session = session;
|
||||
channel->exit_status = -1;
|
||||
channel->flags = SSH_CHANNEL_FLAG_NOT_BOUND;
|
||||
channel->session = session;
|
||||
channel->exit_status = -1;
|
||||
channel->flags = SSH_CHANNEL_FLAG_NOT_BOUND;
|
||||
|
||||
if(session->channels == NULL) {
|
||||
session->channels = ssh_list_new();
|
||||
}
|
||||
ssh_list_prepend(session->channels, channel);
|
||||
return channel;
|
||||
if (session->channels == NULL) {
|
||||
session->channels = ssh_list_new();
|
||||
}
|
||||
|
||||
ssh_list_prepend(session->channels, channel);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1005,22 +1007,24 @@ void ssh_channel_free(ssh_channel channel) {
|
||||
* @brief Effectively free a channel, without caring about flags
|
||||
*/
|
||||
|
||||
void ssh_channel_do_free(ssh_channel channel){
|
||||
struct ssh_iterator *it;
|
||||
ssh_session session = channel->session;
|
||||
it = ssh_list_find(session->channels, channel);
|
||||
if(it != NULL){
|
||||
ssh_list_remove(session->channels, it);
|
||||
}
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
ssh_buffer_free(channel->stderr_buffer);
|
||||
if (channel->callbacks != NULL){
|
||||
ssh_list_free(channel->callbacks);
|
||||
}
|
||||
void ssh_channel_do_free(ssh_channel channel)
|
||||
{
|
||||
struct ssh_iterator *it = NULL;
|
||||
ssh_session session = channel->session;
|
||||
|
||||
/* debug trick to catch use after frees */
|
||||
memset(channel, 'X', sizeof(struct ssh_channel_struct));
|
||||
SAFE_FREE(channel);
|
||||
it = ssh_list_find(session->channels, channel);
|
||||
if (it != NULL) {
|
||||
ssh_list_remove(session->channels, it);
|
||||
}
|
||||
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
ssh_buffer_free(channel->stderr_buffer);
|
||||
|
||||
if (channel->callbacks != NULL) {
|
||||
ssh_list_free(channel->callbacks);
|
||||
}
|
||||
|
||||
SAFE_FREE(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2631,7 +2635,11 @@ static int ssh_channel_read_termination(void *s){
|
||||
*/
|
||||
int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr)
|
||||
{
|
||||
return ssh_channel_read_timeout(channel, dest, count, is_stderr, -1);
|
||||
return ssh_channel_read_timeout(channel,
|
||||
dest,
|
||||
count,
|
||||
is_stderr,
|
||||
SSH_TIMEOUT_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2712,7 +2720,7 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
ctx.count = 1;
|
||||
|
||||
if (timeout_ms < 0) {
|
||||
timeout_ms = SSH_TIMEOUT_DEFAULT;
|
||||
timeout_ms = SSH_TIMEOUT_INFINITE;
|
||||
}
|
||||
|
||||
rc = ssh_handle_packets_termination(session,
|
||||
@@ -2722,7 +2730,12 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
if (rc == SSH_ERROR){
|
||||
return rc;
|
||||
}
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR){
|
||||
|
||||
/*
|
||||
* If the channel is closed or in an error state, reading from it is an error
|
||||
*/
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||
channel->state == SSH_CHANNEL_STATE_CLOSED) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {
|
||||
|
||||
@@ -250,6 +250,8 @@ static int dh_handshake(ssh_session session) {
|
||||
switch(session->next_crypto->kex_type){
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc = ssh_client_dh_init(session);
|
||||
break;
|
||||
#ifdef HAVE_ECDH
|
||||
|
||||
192
src/config.c
192
src/config.c
@@ -30,6 +30,7 @@
|
||||
#ifdef HAVE_GLOB_H
|
||||
# include <glob.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
@@ -72,6 +73,7 @@ enum ssh_config_opcode_e {
|
||||
SOC_KBDINTERACTIVEAUTHENTICATION,
|
||||
SOC_PASSWORDAUTHENTICATION,
|
||||
SOC_PUBKEYAUTHENTICATION,
|
||||
SOC_PUBKEYACCEPTEDTYPES,
|
||||
|
||||
SOC_END /* Keep this one last in the list */
|
||||
};
|
||||
@@ -144,7 +146,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
||||
{ "preferredauthentications", SOC_UNSUPPORTED},
|
||||
{ "proxyjump", SOC_UNSUPPORTED},
|
||||
{ "proxyusefdpass", SOC_UNSUPPORTED},
|
||||
{ "pubkeyacceptedtypes", SOC_UNSUPPORTED},
|
||||
{ "pubkeyacceptedtypes", SOC_PUBKEYACCEPTEDTYPES},
|
||||
{ "rekeylimit", SOC_UNSUPPORTED},
|
||||
{ "remotecommand", SOC_UNSUPPORTED},
|
||||
{ "revokedhostkeys", SOC_UNSUPPORTED},
|
||||
@@ -184,6 +186,32 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
||||
{ NULL, SOC_UNKNOWN }
|
||||
};
|
||||
|
||||
enum ssh_config_match_e {
|
||||
MATCH_UNKNOWN = -1,
|
||||
MATCH_ALL,
|
||||
MATCH_CANONICAL,
|
||||
MATCH_EXEC,
|
||||
MATCH_HOST,
|
||||
MATCH_ORIGINALHOST,
|
||||
MATCH_USER,
|
||||
MATCH_LOCALUSER
|
||||
};
|
||||
|
||||
struct ssh_config_match_keyword_table_s {
|
||||
const char *name;
|
||||
enum ssh_config_match_e opcode;
|
||||
};
|
||||
|
||||
static struct ssh_config_match_keyword_table_s ssh_config_match_keyword_table[] = {
|
||||
{ "all", MATCH_ALL },
|
||||
{ "canonical", MATCH_CANONICAL },
|
||||
{ "exec", MATCH_EXEC },
|
||||
{ "host", MATCH_HOST },
|
||||
{ "originalhost", MATCH_ORIGINALHOST },
|
||||
{ "user", MATCH_USER },
|
||||
{ "localuser", MATCH_LOCALUSER },
|
||||
};
|
||||
|
||||
static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
unsigned int count, int *parsing, int seen[]);
|
||||
|
||||
@@ -319,7 +347,7 @@ static void local_parse_file(ssh_session session, const char *filename, int *par
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
|
||||
static void local_parse_glob(ssh_session session,
|
||||
const char *fileglob,
|
||||
int *parsing,
|
||||
@@ -348,7 +376,41 @@ static void local_parse_glob(ssh_session session,
|
||||
|
||||
globfree(&globbuf);
|
||||
}
|
||||
#endif /* HAVE_GLOB */
|
||||
#endif /* HAVE_GLOB HAVE_GLOB_GL_FLAGS_MEMBER */
|
||||
|
||||
static enum ssh_config_match_e
|
||||
ssh_config_get_match_opcode(const char *keyword)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; ssh_config_match_keyword_table[i].name != NULL; i++) {
|
||||
if (strcasecmp(keyword, ssh_config_match_keyword_table[i].name) == 0) {
|
||||
return ssh_config_match_keyword_table[i].opcode;
|
||||
}
|
||||
}
|
||||
|
||||
return MATCH_UNKNOWN;
|
||||
}
|
||||
|
||||
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);
|
||||
if (ok <= 0 && negate == true) {
|
||||
result = 1;
|
||||
} else if (ok > 0 && negate == false) {
|
||||
result = 1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
unsigned int count, int *parsing, int seen[]) {
|
||||
@@ -383,7 +445,10 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
}
|
||||
|
||||
opcode = ssh_config_get_opcode(keyword);
|
||||
if (*parsing == 1 && opcode != SOC_HOST && opcode != SOC_INCLUDE &&
|
||||
if (*parsing == 1 &&
|
||||
opcode != SOC_HOST &&
|
||||
opcode != SOC_MATCH &&
|
||||
opcode != SOC_INCLUDE &&
|
||||
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
|
||||
if (seen[opcode] != 0) {
|
||||
SAFE_FREE(x);
|
||||
@@ -404,8 +469,108 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
#endif /* HAVE_GLOB */
|
||||
}
|
||||
break;
|
||||
|
||||
case SOC_MATCH: {
|
||||
bool negate;
|
||||
int result = 1;
|
||||
size_t args = 0;
|
||||
enum ssh_config_match_e opt;
|
||||
|
||||
*parsing = 0;
|
||||
do {
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL || p[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
args++;
|
||||
SSH_LOG(SSH_LOG_TRACE, "line %d: Processing Match keyword '%s'",
|
||||
count, p);
|
||||
|
||||
/* If the option is prefixed with ! the result should be negated */
|
||||
negate = false;
|
||||
if (p[0] == '!') {
|
||||
negate = true;
|
||||
p++;
|
||||
}
|
||||
|
||||
opt = ssh_config_get_match_opcode(p);
|
||||
switch (opt) {
|
||||
case MATCH_ALL:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (args == 1 && (p == NULL || p[0] == '\0')) {
|
||||
/* The first argument and end of line */
|
||||
if (negate == true) {
|
||||
result = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"line %d: ERROR - Match all can not be combined with "
|
||||
"other Match attributes", count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
|
||||
case MATCH_EXEC:
|
||||
case MATCH_ORIGINALHOST:
|
||||
case MATCH_LOCALUSER:
|
||||
/* Skip one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
args++;
|
||||
FALL_THROUGH;
|
||||
case MATCH_CANONICAL:
|
||||
SSH_LOG(SSH_LOG_WARN, "line: %d: Unsupported Match keyword "
|
||||
"'%s', Ignoring\n", count, p);
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case MATCH_HOST:
|
||||
/* 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 host keyword "
|
||||
"requires argument", count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
result &= ssh_config_match(session->opts.host, p, negate);
|
||||
args++;
|
||||
break;
|
||||
|
||||
case MATCH_USER:
|
||||
/* 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;
|
||||
}
|
||||
result &= ssh_config_match(session->opts.username, p, negate);
|
||||
args++;
|
||||
break;
|
||||
|
||||
case MATCH_UNKNOWN:
|
||||
default:
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"ERROR - Unknown argument '%s' for Match keyword", p);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
} while (p != NULL && p[0] != '\0');
|
||||
if (args == 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"ERROR - Match keyword requires an argument");
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
*parsing = result;
|
||||
break;
|
||||
}
|
||||
case SOC_HOST: {
|
||||
int ok = 0;
|
||||
int ok = 0, result = -1;
|
||||
|
||||
*parsing = 0;
|
||||
lowerhost = (session->opts.host) ? ssh_lowercase(session->opts.host) : NULL;
|
||||
@@ -414,14 +579,17 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
p = ssh_config_get_str_tok(&s, NULL)) {
|
||||
if (ok >= 0) {
|
||||
ok = match_hostname(lowerhost, p, strlen(p));
|
||||
if (ok < 0) {
|
||||
*parsing = 0;
|
||||
} else if (ok > 0) {
|
||||
*parsing = 1;
|
||||
if (result == -1 && ok < 0) {
|
||||
result = 0;
|
||||
} else if (result == -1 && ok > 0) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_FREE(lowerhost);
|
||||
if (result != -1) {
|
||||
*parsing = result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SOC_HOSTNAME:
|
||||
@@ -592,6 +760,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, p);
|
||||
}
|
||||
break;
|
||||
case SOC_PUBKEYACCEPTEDTYPES:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, p);
|
||||
}
|
||||
break;
|
||||
case SOC_KEXALGORITHMS:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
|
||||
416
src/dh.c
416
src/dh.c
@@ -112,14 +112,164 @@ static unsigned char p_group14_value[] = {
|
||||
|
||||
#define P_GROUP14_LEN 256 /* Size in bytes of the p number for group 14 */
|
||||
|
||||
static unsigned char p_group16_value[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
|
||||
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
||||
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
|
||||
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
|
||||
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
|
||||
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
|
||||
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
|
||||
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
|
||||
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
||||
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
|
||||
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
|
||||
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
||||
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
|
||||
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
|
||||
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
|
||||
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
|
||||
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
|
||||
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
|
||||
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
|
||||
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
|
||||
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
|
||||
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
|
||||
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
|
||||
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
|
||||
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
|
||||
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
#define P_GROUP16_LEN 512 /* Size in bytes of the p number for group 16 */
|
||||
|
||||
static unsigned char p_group18_value[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
|
||||
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
||||
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
|
||||
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
|
||||
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
|
||||
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
|
||||
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
|
||||
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
|
||||
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
||||
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
|
||||
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
|
||||
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
||||
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
|
||||
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
|
||||
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
|
||||
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
|
||||
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
|
||||
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
|
||||
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
|
||||
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
|
||||
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
|
||||
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
|
||||
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
|
||||
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
|
||||
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
|
||||
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
|
||||
0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
|
||||
0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
|
||||
0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
|
||||
0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
|
||||
0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
|
||||
0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
|
||||
0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
|
||||
0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
|
||||
0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
|
||||
0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
|
||||
0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
|
||||
0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
|
||||
0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
|
||||
0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
|
||||
0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
|
||||
0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
|
||||
0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
|
||||
0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
|
||||
0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
|
||||
0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
|
||||
0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
|
||||
0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
|
||||
0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0,
|
||||
0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
|
||||
0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93,
|
||||
0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
|
||||
0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB,
|
||||
0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
|
||||
0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8,
|
||||
0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
|
||||
0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F,
|
||||
0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
|
||||
0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8,
|
||||
0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
|
||||
0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5,
|
||||
0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
|
||||
0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3,
|
||||
0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
|
||||
0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E,
|
||||
0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
|
||||
0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2,
|
||||
0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
|
||||
0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
#define P_GROUP18_LEN 1024 /* Size in bytes of the p number for group 18 */
|
||||
|
||||
static unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */
|
||||
static bignum g;
|
||||
static bignum p_group1;
|
||||
static bignum p_group14;
|
||||
static bignum p_group16;
|
||||
static bignum p_group18;
|
||||
static int dh_crypto_initialized;
|
||||
|
||||
static bignum select_p(enum ssh_key_exchange_e type) {
|
||||
return type == SSH_KEX_DH_GROUP14_SHA1 ? p_group14 : p_group1;
|
||||
switch(type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
return p_group1;
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
return p_group14;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
return p_group16;
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
return p_group18;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,6 +301,23 @@ int ssh_dh_init(void)
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, &p_group16);
|
||||
if (p_group16 == NULL) {
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, &p_group18);
|
||||
if (p_group18 == NULL) {
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
bignum_safe_free(p_group16);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
@@ -170,12 +337,39 @@ int ssh_dh_init(void)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
|
||||
|
||||
p_group16 = bignum_new();
|
||||
if (p_group16 == NULL) {
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, p_group16);
|
||||
|
||||
p_group18 = bignum_new();
|
||||
if (p_group18 == NULL) {
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
bignum_safe_free(p_group16);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, p_group18);
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
p_group1 = bignum_new();
|
||||
bignum_bin2bn(p_group1_value, P_GROUP1_LEN, p_group1);
|
||||
|
||||
p_group14 = bignum_new();
|
||||
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
|
||||
|
||||
p_group16 = bignum_new();
|
||||
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, p_group16);
|
||||
|
||||
p_group18 = bignum_new();
|
||||
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, p_group18);
|
||||
#endif
|
||||
dh_crypto_initialized = 1;
|
||||
|
||||
@@ -195,53 +389,83 @@ void ssh_dh_finalize(void)
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
bignum_safe_free(p_group16);
|
||||
bignum_safe_free(p_group18);
|
||||
|
||||
dh_crypto_initialized = 0;
|
||||
}
|
||||
|
||||
int ssh_dh_generate_x(ssh_session session) {
|
||||
int keysize;
|
||||
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
|
||||
keysize = 1023;
|
||||
} else {
|
||||
keysize = 2047;
|
||||
}
|
||||
session->next_crypto->x = bignum_new();
|
||||
if (session->next_crypto->x == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int ssh_dh_generate_x(ssh_session session)
|
||||
{
|
||||
size_t keysize;
|
||||
|
||||
bignum_rand(session->next_crypto->x, keysize);
|
||||
switch(session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
keysize = 1023;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
keysize = 2047;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
keysize = 4095;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
keysize = 8191;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* not harder than this */
|
||||
session->next_crypto->x = bignum_new();
|
||||
if (session->next_crypto->x == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bignum_rand(session->next_crypto->x, keysize);
|
||||
|
||||
/* not harder than this */
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_bignum("x", session->next_crypto->x);
|
||||
ssh_print_bignum("x", session->next_crypto->x);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* used by server */
|
||||
int ssh_dh_generate_y(ssh_session session) {
|
||||
int keysize;
|
||||
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
|
||||
keysize = 1023;
|
||||
} else {
|
||||
keysize = 2047;
|
||||
}
|
||||
session->next_crypto->y = bignum_new();
|
||||
if (session->next_crypto->y == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int ssh_dh_generate_y(ssh_session session)
|
||||
{
|
||||
size_t keysize;
|
||||
|
||||
bignum_rand(session->next_crypto->y, keysize);
|
||||
switch(session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
keysize = 1023;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
keysize = 2047;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
keysize = 4095;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
keysize = 8191;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* not harder than this */
|
||||
session->next_crypto->y = bignum_new();
|
||||
if (session->next_crypto->y == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bignum_rand(session->next_crypto->y, keysize);
|
||||
|
||||
/* not harder than this */
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_bignum("y", session->next_crypto->y);
|
||||
ssh_print_bignum("y", session->next_crypto->y);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* used by server */
|
||||
@@ -597,8 +821,11 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1 ||
|
||||
session->next_crypto->kex_type == SSH_KEX_DH_GROUP14_SHA1) {
|
||||
switch(session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"BB",
|
||||
session->next_crypto->e,
|
||||
@@ -606,11 +833,11 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
break;
|
||||
#ifdef HAVE_ECDH
|
||||
} else if ((session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP256) ||
|
||||
(session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP384) ||
|
||||
(session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP521)) {
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP384:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
if (session->next_crypto->ecdh_client_pubkey == NULL ||
|
||||
session->next_crypto->ecdh_server_pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing");
|
||||
@@ -623,10 +850,11 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_CURVE25519
|
||||
} else if ((session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256) ||
|
||||
(session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG)) {
|
||||
case SSH_KEX_CURVE25519_SHA256:
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"dPdP",
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
@@ -637,6 +865,7 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
rc = ssh_buffer_pack(buf, "B", session->next_crypto->k);
|
||||
@@ -685,6 +914,8 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
sha384(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
|
||||
session->next_crypto->secret_hash);
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
|
||||
session->next_crypto->mac_type = SSH_MAC_SHA512;
|
||||
@@ -693,8 +924,9 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
sha512(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
|
||||
session->next_crypto->secret_hash);
|
||||
sha512(ssh_buffer_get(buf),
|
||||
ssh_buffer_get_len(buf),
|
||||
session->next_crypto->secret_hash);
|
||||
break;
|
||||
}
|
||||
/* During the first kex, secret hash and session ID are equal. However, after
|
||||
@@ -1269,6 +1501,79 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) {
|
||||
return hexa;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* @param type Which sort of hash is given.
|
||||
*
|
||||
* @param hash What should be converted to a base64 string.
|
||||
*
|
||||
* @param len Length of the buffer to convert.
|
||||
*
|
||||
* @return Returns the allocated fingerprint hash or NULL on error.
|
||||
*
|
||||
* @see ssh_string_free_char()
|
||||
*/
|
||||
char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
|
||||
unsigned char *hash,
|
||||
size_t len)
|
||||
{
|
||||
const char *prefix = "UNKNOWN";
|
||||
char *fingerprint = NULL;
|
||||
char *str = NULL;
|
||||
size_t str_len;
|
||||
int rc;
|
||||
|
||||
switch (type) {
|
||||
case SSH_PUBLICKEY_HASH_SHA1:
|
||||
case SSH_PUBLICKEY_HASH_SHA256:
|
||||
fingerprint = ssh_get_b64_unpadded(hash, len);
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_MD5:
|
||||
fingerprint = ssh_get_hexa(hash, len);
|
||||
break;
|
||||
}
|
||||
if (fingerprint == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SSH_PUBLICKEY_HASH_MD5:
|
||||
prefix = "MD5";
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_SHA1:
|
||||
prefix = "SHA1";
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_SHA256:
|
||||
prefix = "SHA256";
|
||||
break;
|
||||
}
|
||||
|
||||
str_len = strlen(prefix);
|
||||
if (str_len + 1 + strlen(fingerprint) + 1 < str_len) {
|
||||
SAFE_FREE(fingerprint);
|
||||
return NULL;
|
||||
}
|
||||
str_len += 1 + strlen(fingerprint) + 1;
|
||||
|
||||
str = malloc(str_len);
|
||||
if (str == NULL) {
|
||||
SAFE_FREE(fingerprint);
|
||||
return NULL;
|
||||
}
|
||||
rc = snprintf(str, str_len, "%s:%s", prefix, fingerprint);
|
||||
SAFE_FREE(fingerprint);
|
||||
if (rc < 0 || rc < (int)(str_len - 1)) {
|
||||
SAFE_FREE(str);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a hash as a human-readable hex- or base64-string.
|
||||
*
|
||||
@@ -1284,35 +1589,18 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) {
|
||||
*/
|
||||
void ssh_print_hash(enum ssh_publickey_hash_type type,
|
||||
unsigned char *hash,
|
||||
size_t len) {
|
||||
const char *prefix = "UNKNOWN";
|
||||
size_t len)
|
||||
{
|
||||
char *fingerprint = NULL;
|
||||
|
||||
switch (type) {
|
||||
case SSH_PUBLICKEY_HASH_SHA1:
|
||||
case SSH_PUBLICKEY_HASH_SHA256:
|
||||
fingerprint = ssh_get_b64_unpadded(hash, len);
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_MD5:
|
||||
fingerprint = ssh_get_hexa(hash, len);
|
||||
break;
|
||||
}
|
||||
fingerprint = ssh_get_fingerprint_hash(type,
|
||||
hash,
|
||||
len);
|
||||
if (fingerprint == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SSH_PUBLICKEY_HASH_MD5:
|
||||
prefix = "MD5";
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_SHA1:
|
||||
prefix = "SHA1";
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_SHA256:
|
||||
prefix = "SHA256";
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "%s:%s\n", prefix, fingerprint);
|
||||
fprintf(stderr, "%s\n", fingerprint);
|
||||
|
||||
SAFE_FREE(fingerprint);
|
||||
}
|
||||
|
||||
@@ -49,11 +49,10 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
|
||||
char *ptr = NULL;
|
||||
int ok = 0;
|
||||
|
||||
tmp = malloc(len);
|
||||
tmp = calloc(1, len);
|
||||
if (tmp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memset(tmp,'\0',len);
|
||||
|
||||
/* read the password */
|
||||
while (!ok) {
|
||||
@@ -80,16 +79,15 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
|
||||
if (verify) {
|
||||
char *key_string;
|
||||
|
||||
key_string = malloc(len);
|
||||
key_string = calloc(1, len);
|
||||
if (key_string == NULL) {
|
||||
break;
|
||||
}
|
||||
memset(key_string, '\0', len);
|
||||
|
||||
fprintf(stdout, "\nVerifying, please re-enter. %s", prompt);
|
||||
fflush(stdout);
|
||||
if (! fgets(key_string, len, stdin)) {
|
||||
memset(key_string, '\0', len);
|
||||
explicit_bzero(key_string, len);
|
||||
SAFE_FREE(key_string);
|
||||
clearerr(stdin);
|
||||
continue;
|
||||
@@ -100,17 +98,17 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
|
||||
fprintf(stdout, "\n");
|
||||
if (strcmp(buf, key_string)) {
|
||||
printf("\n\07\07Mismatch - try again\n");
|
||||
memset(key_string, '\0', len);
|
||||
explicit_bzero(key_string, len);
|
||||
SAFE_FREE(key_string);
|
||||
fflush(stdout);
|
||||
continue;
|
||||
}
|
||||
memset(key_string, '\0', len);
|
||||
explicit_bzero(key_string, len);
|
||||
SAFE_FREE(key_string);
|
||||
}
|
||||
ok = 1;
|
||||
}
|
||||
memset(tmp, '\0', len);
|
||||
explicit_bzero(tmp, len);
|
||||
free(tmp);
|
||||
|
||||
return ok;
|
||||
@@ -152,7 +150,7 @@ int ssh_getpass(const char *prompt,
|
||||
SetConsoleMode(h, mode);
|
||||
|
||||
if (!ok) {
|
||||
memset (buf, '\0', len);
|
||||
explicit_bzero(buf, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -273,7 +271,7 @@ int ssh_getpass(const char *prompt,
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
memset (buf, '\0', len);
|
||||
explicit_bzero(buf, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,10 @@ static z_stream *initcompress(ssh_session session, int level) {
|
||||
z_stream *stream = NULL;
|
||||
int status;
|
||||
|
||||
stream = malloc(sizeof(z_stream));
|
||||
stream = calloc(1, sizeof(z_stream));
|
||||
if (stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(stream, 0, sizeof(z_stream));
|
||||
|
||||
status = deflateInit(stream, level);
|
||||
if (status != Z_OK) {
|
||||
@@ -128,11 +127,10 @@ static z_stream *initdecompress(ssh_session session) {
|
||||
z_stream *stream = NULL;
|
||||
int status;
|
||||
|
||||
stream = malloc(sizeof(z_stream));
|
||||
stream = calloc(1, sizeof(z_stream));
|
||||
if (stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(stream,0,sizeof(z_stream));
|
||||
|
||||
status = inflateInit(stream);
|
||||
if (status != Z_OK) {
|
||||
|
||||
80
src/kex.c
80
src/kex.c
@@ -86,25 +86,28 @@
|
||||
|
||||
#ifdef HAVE_ECDH
|
||||
#define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
|
||||
#define HOSTKEYS "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-dss"
|
||||
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss"
|
||||
#else
|
||||
#ifdef HAVE_DSA
|
||||
#define HOSTKEYS "ssh-ed25519,ssh-rsa,ssh-dss"
|
||||
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss"
|
||||
#else
|
||||
#define HOSTKEYS "ssh-ed25519,ssh-rsa"
|
||||
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ssh-rsa,rsa-sha2-512,rsa-sha2-256"
|
||||
#endif
|
||||
#define ECDH ""
|
||||
#endif
|
||||
|
||||
#define CHACHA20 "chacha20-poly1305@openssh.com,"
|
||||
|
||||
#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
||||
#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
||||
#define KEX_METHODS_SIZE 10
|
||||
|
||||
/* RFC 8308 */
|
||||
#define KEX_EXTENSION_CLIENT "ext-info-c"
|
||||
|
||||
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
|
||||
static const char *default_methods[] = {
|
||||
KEY_EXCHANGE,
|
||||
HOSTKEYS,
|
||||
PUBLIC_KEY_ALGORITHMS,
|
||||
AES BLOWFISH DES,
|
||||
AES BLOWFISH DES,
|
||||
"hmac-sha2-256,hmac-sha2-512,hmac-sha1",
|
||||
@@ -119,7 +122,7 @@ static const char *default_methods[] = {
|
||||
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
|
||||
static const char *supported_methods[] = {
|
||||
KEY_EXCHANGE,
|
||||
HOSTKEYS,
|
||||
PUBLIC_KEY_ALGORITHMS,
|
||||
CHACHA20 AES BLOWFISH DES_SUPPORTED,
|
||||
CHACHA20 AES BLOWFISH DES_SUPPORTED,
|
||||
"hmac-sha2-256,hmac-sha2-512,hmac-sha1",
|
||||
@@ -232,6 +235,15 @@ char **ssh_space_tokenize(const char *chain){
|
||||
return tokens;
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo)
|
||||
{
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return default_methods[algo];
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo) {
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
return NULL;
|
||||
@@ -403,10 +415,10 @@ out:
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
int i;
|
||||
int i, ok;
|
||||
int server_kex=session->server;
|
||||
ssh_string str = NULL;
|
||||
char *strings[KEX_METHODS_SIZE];
|
||||
char *strings[KEX_METHODS_SIZE] = {0};
|
||||
int rc = SSH_ERROR;
|
||||
|
||||
uint8_t first_kex_packet_follows = 0;
|
||||
@@ -415,7 +427,6 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
memset(strings, 0, sizeof(strings));
|
||||
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED){
|
||||
SSH_LOG(SSH_LOG_WARNING, "Other side initiating key re-exchange");
|
||||
} else if(session->session_state != SSH_SESSION_STATE_INITIAL_KEX){
|
||||
@@ -507,6 +518,22 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If client sent a ext-info-c message in the kex list, it supports
|
||||
* RFC 8308 extension negotiation.
|
||||
*/
|
||||
ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX],
|
||||
KEX_EXTENSION_CLIENT);
|
||||
if (ok) {
|
||||
/*
|
||||
* Enable all the supported extensions and when the time comes
|
||||
* (after NEWKEYS) send them to the client.
|
||||
*/
|
||||
SSH_LOG(SSH_LOG_DEBUG, "The client supports extension "
|
||||
"negotiation: enabling all extensions");
|
||||
session->extensions = SSH_EXT_ALL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember whether 'first_kex_packet_follows' was set and the client
|
||||
* guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
|
||||
@@ -642,11 +669,15 @@ static char *ssh_client_select_hostkeys(ssh_session session)
|
||||
* @brief sets the key exchange parameters to be sent to the server,
|
||||
* in function of the options and available methods.
|
||||
*/
|
||||
int ssh_set_client_kex(ssh_session session){
|
||||
int ssh_set_client_kex(ssh_session session)
|
||||
{
|
||||
struct ssh_kex_struct *client= &session->next_crypto->client_kex;
|
||||
const char *wanted;
|
||||
char *kex = NULL;
|
||||
char *kex_tmp = NULL;
|
||||
int ok;
|
||||
int i;
|
||||
size_t kex_len, len;
|
||||
|
||||
ok = ssh_get_random(client->cookie, 16, 0);
|
||||
if (!ok) {
|
||||
@@ -673,6 +704,23 @@ int ssh_set_client_kex(ssh_session session){
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we append ext-info-c to the list of kex algorithms */
|
||||
kex = client->methods[SSH_KEX];
|
||||
len = strlen(kex);
|
||||
if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) {
|
||||
/* Overflow */
|
||||
return SSH_ERROR;
|
||||
}
|
||||
kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */
|
||||
kex_tmp = realloc(kex, kex_len);
|
||||
if (kex_tmp == NULL) {
|
||||
free(kex);
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT);
|
||||
client->methods[SSH_KEX] = kex_tmp;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
@@ -682,8 +730,16 @@ int ssh_set_client_kex(ssh_session session){
|
||||
int ssh_kex_select_methods (ssh_session session){
|
||||
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
|
||||
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
|
||||
char *ext_start = NULL;
|
||||
int i;
|
||||
|
||||
/* Here we should drop the ext-info-c from the list so we avoid matching.
|
||||
* it. We added it to the end, so we can just truncate the string here */
|
||||
ext_start = strstr(client->methods[SSH_KEX], ","KEX_EXTENSION_CLIENT);
|
||||
if (ext_start != NULL) {
|
||||
ext_start[0] = '\0';
|
||||
}
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]);
|
||||
if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){
|
||||
@@ -699,6 +755,10 @@ int ssh_kex_select_methods (ssh_session session){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){
|
||||
|
||||
@@ -172,7 +172,7 @@ void evp_update(EVPCTX ctx, const void *data, unsigned long len)
|
||||
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
|
||||
{
|
||||
*mdlen = mbedtls_md_get_size(ctx->md_info);
|
||||
mbedtls_md_hmac_finish(ctx, md);
|
||||
mbedtls_md_finish(ctx, md);
|
||||
mbedtls_md_free(ctx);
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
|
||||
@@ -424,3 +424,10 @@ LIBSSH_4_6_0 # Released
|
||||
ssh_print_hash;
|
||||
} LIBSSH_4_5_0;
|
||||
|
||||
LIBSSH_4_7_0 # Released
|
||||
{
|
||||
global:
|
||||
sftp_client_message_get_submessage;
|
||||
ssh_get_fingerprint_hash;
|
||||
ssh_pki_export_privkey_base64;
|
||||
} LIBSSH_4_6_0;
|
||||
|
||||
@@ -119,7 +119,7 @@ static int match_pattern(const char *s, const char *pattern) {
|
||||
* Returns -1 if negation matches, 1 if there is a positive match, 0 if there is
|
||||
* no match at all.
|
||||
*/
|
||||
static int match_pattern_list(const char *string, const char *pattern,
|
||||
int match_pattern_list(const char *string, const char *pattern,
|
||||
unsigned int len, int dolower) {
|
||||
char sub[1024];
|
||||
int negated;
|
||||
|
||||
@@ -645,7 +645,8 @@ error:
|
||||
*/
|
||||
static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
ssh_message msg,
|
||||
const char *service)
|
||||
const char *service,
|
||||
ssh_string algo)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto =
|
||||
session->current_crypto ? session->current_crypto :
|
||||
@@ -673,7 +674,7 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
service,
|
||||
"publickey", /* method */
|
||||
1, /* has to be signed (true) */
|
||||
msg->auth_request.pubkey->type_c, /* pubkey algorithm */
|
||||
ssh_string_get_char(algo), /* pubkey algorithm */
|
||||
str); /* public key as a blob */
|
||||
|
||||
ssh_string_free(str);
|
||||
@@ -785,13 +786,13 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(algo);
|
||||
algo = NULL;
|
||||
|
||||
rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey);
|
||||
ssh_string_free(pubkey_blob);
|
||||
pubkey_blob = NULL;
|
||||
if (rc < 0) {
|
||||
ssh_string_free(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
|
||||
@@ -804,10 +805,14 @@ 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);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
digest = ssh_msg_userauth_build_digest(session, msg, service);
|
||||
digest = ssh_msg_userauth_build_digest(session, msg, service, algo);
|
||||
ssh_string_free(algo);
|
||||
algo = NULL;
|
||||
if (digest == NULL) {
|
||||
ssh_string_free(sig_blob);
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to get digest");
|
||||
@@ -834,6 +839,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
|
||||
}
|
||||
ssh_string_free(algo);
|
||||
goto end;
|
||||
}
|
||||
#ifdef WITH_GSSAPI
|
||||
|
||||
@@ -217,7 +217,7 @@ char *ssh_get_user_home_dir(void) {
|
||||
char *szPath = NULL;
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdbuf;
|
||||
char buf[NSS_BUFLEN_PASSWD];
|
||||
char buf[NSS_BUFLEN_PASSWD] = {0};
|
||||
int rc;
|
||||
|
||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||
@@ -226,7 +226,6 @@ char *ssh_get_user_home_dir(void) {
|
||||
if (szPath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
snprintf(buf, sizeof(buf), "%s", szPath);
|
||||
|
||||
return strdup(buf);
|
||||
|
||||
@@ -147,6 +147,14 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (src->opts.pubkey_accepted_types != NULL) {
|
||||
new->opts.pubkey_accepted_types = strdup(src->opts.pubkey_accepted_types);
|
||||
if (new->opts.pubkey_accepted_types == NULL) {
|
||||
ssh_free(new);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
new->opts.fd = src->opts.fd;
|
||||
new->opts.port = src->opts.port;
|
||||
new->opts.timeout = src->opts.timeout;
|
||||
@@ -343,6 +351,11 @@ int ssh_options_set_algo(ssh_session session,
|
||||
* comma-separated list). ex:
|
||||
* "ssh-rsa,ssh-dss,ecdh-sha2-nistp256"
|
||||
*
|
||||
* - SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
|
||||
* Set the preferred public key algorithms to be used for
|
||||
* authentication (const char *, comma-separated list). ex:
|
||||
* "ssh-rsa,rsa-sha2-256,ssh-dss,ecdh-sha2-nistp256"
|
||||
*
|
||||
* - SSH_OPTIONS_COMPRESSION_C_S:
|
||||
* Set the compression to use for client to server
|
||||
* communication (const char *, "yes", "no" or a specific
|
||||
@@ -743,6 +756,24 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
|
||||
v = value;
|
||||
if (v == NULL || v[0] == '\0') {
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
} else {
|
||||
p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
|
||||
if (p == NULL) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Setting method: no known public key algorithm (%s)",
|
||||
v);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SAFE_FREE(session->opts.pubkey_accepted_types);
|
||||
session->opts.pubkey_accepted_types = p;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_HMAC_C_S:
|
||||
v = value;
|
||||
if (v == NULL || v[0] == '\0') {
|
||||
|
||||
35
src/packet.c
35
src/packet.c
@@ -59,8 +59,9 @@ static ssh_packet_callback default_packet_handlers[]= {
|
||||
NULL,
|
||||
#endif
|
||||
ssh_packet_service_accept, // SSH2_MSG_SERVICE_ACCEPT 6
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, // 7-19
|
||||
ssh_packet_ext_info, // SSH2_MSG_EXT_INFO 7
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, // 8-19
|
||||
ssh_packet_kexinit, // SSH2_MSG_KEXINIT 20
|
||||
ssh_packet_newkeys, // SSH2_MSG_NEWKEYS 21
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -198,7 +199,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&session->in_packet, 0, sizeof(PACKET));
|
||||
session->in_packet = (struct packet_struct) {
|
||||
.type = 0,
|
||||
};
|
||||
|
||||
if (session->in_buffer) {
|
||||
rc = ssh_buffer_reinit(session->in_buffer);
|
||||
@@ -514,20 +517,24 @@ SSH_PACKET_CALLBACK(ssh_packet_unimplemented){
|
||||
/** @internal
|
||||
* @parse the "Type" header field of a packet and updates the session
|
||||
*/
|
||||
int ssh_packet_parse_type(ssh_session session) {
|
||||
memset(&session->in_packet, 0, sizeof(PACKET));
|
||||
if(session->in_buffer == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
int ssh_packet_parse_type(struct ssh_session_struct *session)
|
||||
{
|
||||
session->in_packet = (struct packet_struct) {
|
||||
.type = 0,
|
||||
};
|
||||
|
||||
if(ssh_buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Packet too short to read type");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (session->in_buffer == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->in_packet.valid = 1;
|
||||
if (ssh_buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Packet too short to read type");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
session->in_packet.valid = 1;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -106,6 +106,8 @@ SSH_PACKET_CALLBACK(ssh_packet_dh_reply){
|
||||
switch(session->next_crypto->kex_type){
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc=ssh_client_dh_reply(session, packet);
|
||||
break;
|
||||
#ifdef HAVE_ECDH
|
||||
@@ -270,3 +272,61 @@ SSH_PACKET_CALLBACK(ssh_packet_service_accept){
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief handles a SSH2_MSG_EXT_INFO packet defined in RFC 8308
|
||||
*
|
||||
*/
|
||||
SSH_PACKET_CALLBACK(ssh_packet_ext_info)
|
||||
{
|
||||
int rc;
|
||||
uint32_t nr_extensions = 0;
|
||||
uint32_t i;
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_EXT_INFO");
|
||||
|
||||
rc = ssh_buffer_get_u32(packet, &nr_extensions);
|
||||
if (rc == 0) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to read number of extensions");
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
nr_extensions = ntohl(nr_extensions);
|
||||
if (nr_extensions > 128) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Invalid number of extensions");
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Follows %u extensions", nr_extensions);
|
||||
|
||||
for (i = 0; i < nr_extensions; i++) {
|
||||
char *name = NULL;
|
||||
char *value = NULL;
|
||||
int cmp;
|
||||
|
||||
rc = ssh_buffer_unpack(packet, "ss", &name, &value);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Error reading extension name-value pair");
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
cmp = strcmp(name, "server-sig-algs");
|
||||
if (cmp == 0) {
|
||||
/* TODO check for NULL bytes */
|
||||
SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value);
|
||||
if (ssh_match_group(value, "rsa-sha2-512")) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA512;
|
||||
}
|
||||
if (ssh_match_group(value, "rsa-sha2-256")) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
|
||||
}
|
||||
}
|
||||
free(name);
|
||||
free(value);
|
||||
}
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
597
src/pki.c
597
src/pki.c
@@ -193,6 +193,36 @@ enum ssh_keytypes_e ssh_key_type(const ssh_key key){
|
||||
return key->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a signature type to a string.
|
||||
*
|
||||
* @param[in] type The algorithm type to convert.
|
||||
*
|
||||
* @return A string for the keytype or NULL if unknown.
|
||||
*/
|
||||
const char *
|
||||
ssh_key_signature_to_char(enum ssh_keytypes_e type,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
if (type != SSH_KEYTYPE_RSA) {
|
||||
return ssh_key_type_to_char(type);
|
||||
}
|
||||
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
return "rsa-sha2-256";
|
||||
case SSH_DIGEST_SHA512:
|
||||
return "rsa-sha2-512";
|
||||
case SSH_DIGEST_SHA1:
|
||||
return "ssh-rsa";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We should never reach this */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a key type to a string.
|
||||
*
|
||||
@@ -223,6 +253,124 @@ 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)
|
||||
{
|
||||
if (name == NULL) {
|
||||
/* TODO we should rather fail */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
|
||||
if (strcmp(name, "ssh-rsa") == 0) {
|
||||
return SSH_DIGEST_SHA1;
|
||||
} else if (strcmp(name, "rsa-sha2-256") == 0) {
|
||||
return SSH_DIGEST_SHA256;
|
||||
} else if (strcmp(name, "rsa-sha2-512") == 0) {
|
||||
return SSH_DIGEST_SHA512;
|
||||
}
|
||||
|
||||
/* we do not care for others now */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
/**
|
||||
* @brief Checks the given key against the configured allowed
|
||||
* public key algorithm types
|
||||
*
|
||||
* @param[in] session The SSH session
|
||||
* @parma[in] type The key algorithm to check
|
||||
* @returns 1 if the key algorithm is allowed 0 otherwise
|
||||
*/
|
||||
int ssh_key_algorithm_allowed(ssh_session session, const char *type)
|
||||
{
|
||||
const char *allowed_list;
|
||||
|
||||
allowed_list = session->opts.pubkey_accepted_types;
|
||||
if (allowed_list == NULL) {
|
||||
allowed_list = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Checking %s with list <%s>", type, allowed_list);
|
||||
return ssh_match_group(allowed_list, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a key type to a hash type. This is usually unambiguous
|
||||
* for all the key types, unless the SHA2 extension (RFC 8332) is
|
||||
* negotiated during key exchange.
|
||||
*
|
||||
* @param[in] session SSH Session.
|
||||
*
|
||||
* @param[in] type The type to convert.
|
||||
*
|
||||
* @return A hash type to be used.
|
||||
*/
|
||||
enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
|
||||
enum ssh_keytypes_e type)
|
||||
{
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
if (ssh_key_algorithm_allowed(session, "rsa-sha2-512") &&
|
||||
(session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
|
||||
return SSH_DIGEST_SHA512;
|
||||
}
|
||||
|
||||
if (ssh_key_algorithm_allowed(session, "rsa-sha2-256") &&
|
||||
(session->extensions & SSH_EXT_SIG_RSA_SHA256)) {
|
||||
return SSH_DIGEST_SHA256;
|
||||
}
|
||||
|
||||
/* Default algorithm for RSA is SHA1 */
|
||||
return SSH_DIGEST_SHA1;
|
||||
|
||||
default:
|
||||
/* Other key types use the default value (not used) */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
|
||||
/* We should never reach this */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets signature algorithm name to be used with the given
|
||||
* key type.
|
||||
*
|
||||
* @param[in] session SSH session.
|
||||
* @param[in] type The algorithm type to convert.
|
||||
*
|
||||
* @return A string for the keytype or NULL if unknown.
|
||||
*/
|
||||
const char *
|
||||
ssh_key_get_signature_algorithm(ssh_session session,
|
||||
enum ssh_keytypes_e type)
|
||||
{
|
||||
enum ssh_digest_e hash_type;
|
||||
|
||||
hash_type = ssh_key_type_to_hash(session, type);
|
||||
|
||||
return ssh_key_signature_to_char(type, hash_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a ssh key algorithm name to a ssh key algorithm type.
|
||||
*
|
||||
* @param[in] name The name to convert.
|
||||
*
|
||||
* @return The enum ssh key algorithm type.
|
||||
*/
|
||||
enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name) {
|
||||
if (name == NULL) {
|
||||
return SSH_KEYTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if ((strcmp(name, "rsa-sha2-256") == 0) ||
|
||||
(strcmp(name, "rsa-sha2-512") == 0)) {
|
||||
return SSH_KEYTYPE_RSA;
|
||||
}
|
||||
|
||||
/* Otherwise the key type matches the signature type */
|
||||
return ssh_key_type_from_name(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a ssh key name to a ssh key type.
|
||||
*
|
||||
@@ -448,6 +596,62 @@ int ssh_pki_import_privkey_base64(const char *b64_key,
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
/**
|
||||
* @brief Convert a private key to a pem base64 encoded key, or OpenSSH format for
|
||||
* keytype ssh-ed25519
|
||||
*
|
||||
* @param[in] privkey The private key to export.
|
||||
*
|
||||
* @param[in] passphrase The passphrase to use to encrypt the key with or
|
||||
* NULL. An empty string means no passphrase.
|
||||
*
|
||||
* @param[in] auth_fn An auth function you may want to use or NULL.
|
||||
*
|
||||
* @param[in] auth_data Private data passed to the auth function.
|
||||
*
|
||||
* @param[out] b64_key A pointer to store the allocated base64 encoded key. You
|
||||
* need to free the buffer.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
int ssh_pki_export_privkey_base64(const ssh_key privkey,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
char **b64_key)
|
||||
{
|
||||
ssh_string blob = NULL;
|
||||
char *b64 = NULL;
|
||||
|
||||
if (privkey == NULL || !ssh_key_is_private(privkey)) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519){
|
||||
blob = ssh_pki_openssh_privkey_export(privkey,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
} else {
|
||||
blob = pki_private_key_to_pem(privkey,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
}
|
||||
if (blob == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
b64 = strndup(ssh_string_data(blob), ssh_string_len(blob));
|
||||
ssh_string_free(blob);
|
||||
if (b64 == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
*b64_key = b64;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Import a key from a file.
|
||||
@@ -662,10 +866,183 @@ ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) {
|
||||
return privkey;
|
||||
}
|
||||
|
||||
int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
ssh_buffer buffer,
|
||||
ssh_key *pkey)
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
key = ssh_key_new();
|
||||
if (key == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
key->type = type;
|
||||
key->type_c = ssh_key_type_to_char(type);
|
||||
key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
|
||||
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
{
|
||||
ssh_string p = NULL;
|
||||
ssh_string q = NULL;
|
||||
ssh_string g = NULL;
|
||||
ssh_string pubkey = NULL;
|
||||
ssh_string privkey = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SSSSS", &p, &q, &g,
|
||||
&pubkey, &privkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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_string_len(pubkey));
|
||||
ssh_print_hexa("privkey", ssh_string_data(privkey),
|
||||
ssh_string_len(privkey));
|
||||
#endif
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
ssh_string_burn(privkey);
|
||||
ssh_string_free(privkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
{
|
||||
ssh_string n = NULL;
|
||||
ssh_string e = NULL;
|
||||
ssh_string d = NULL;
|
||||
ssh_string iqmp = NULL;
|
||||
ssh_string p = NULL;
|
||||
ssh_string q = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SSSSSS", &n, &e, &d,
|
||||
&iqmp, &p, &q);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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_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));
|
||||
#endif
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
ssh_string_burn(d);
|
||||
ssh_string_free(d);
|
||||
ssh_string_burn(iqmp);
|
||||
ssh_string_free(iqmp);
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build RSA private key");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_ECC
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
{
|
||||
ssh_string e = NULL;
|
||||
ssh_string exp = NULL;
|
||||
ssh_string i = NULL;
|
||||
int nid;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SSS", &i, &e, &exp);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(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_burn(exp);
|
||||
ssh_string_free(exp);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA private key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Update key type */
|
||||
key->type_c = ssh_pki_key_ecdsa_name(key);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
{
|
||||
ssh_string pubkey = NULL, privkey = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SS", &pubkey, &privkey);
|
||||
if (rc != SSH_OK){
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = pki_privkey_build_ed25519(key, pubkey, privkey);
|
||||
ssh_string_burn(privkey);
|
||||
ssh_string_free(privkey);
|
||||
ssh_string_free(pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ed25519 key");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown private key type (%d)", type);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*pkey = key;
|
||||
return SSH_OK;
|
||||
fail:
|
||||
ssh_key_free(key);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
enum ssh_keytypes_e type,
|
||||
ssh_key *pkey) {
|
||||
ssh_key key;
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
key = ssh_key_new();
|
||||
@@ -680,40 +1057,14 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
{
|
||||
ssh_string p;
|
||||
ssh_string q;
|
||||
ssh_string g;
|
||||
ssh_string pubkey;
|
||||
|
||||
p = ssh_buffer_get_ssh_string(buffer);
|
||||
if (p == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
q = ssh_buffer_get_ssh_string(buffer);
|
||||
if (q == NULL) {
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
g = ssh_buffer_get_ssh_string(buffer);
|
||||
if (g == NULL) {
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
pubkey = ssh_buffer_get_ssh_string(buffer);
|
||||
if (pubkey == NULL) {
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
ssh_string p = NULL;
|
||||
ssh_string q = NULL;
|
||||
ssh_string g = NULL;
|
||||
ssh_string pubkey = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SSSS", &p, &q, &g, &pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -732,24 +1083,19 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build DSA public key");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
{
|
||||
ssh_string e;
|
||||
ssh_string n;
|
||||
|
||||
e = ssh_buffer_get_ssh_string(buffer);
|
||||
if (e == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
n = ssh_buffer_get_ssh_string(buffer);
|
||||
if (n == NULL) {
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
ssh_string e = NULL;
|
||||
ssh_string n = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SS", &e, &n);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -763,6 +1109,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build RSA public key");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@@ -770,30 +1117,27 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
#ifdef HAVE_ECC
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
{
|
||||
ssh_string e;
|
||||
ssh_string i;
|
||||
ssh_string e = NULL;
|
||||
ssh_string i = NULL;
|
||||
int nid;
|
||||
|
||||
i = ssh_buffer_get_ssh_string(buffer);
|
||||
if (i == NULL) {
|
||||
rc = ssh_buffer_unpack(buffer, "SS", &i, &e);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
|
||||
ssh_string_free(i);
|
||||
if (nid == -1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
e = ssh_buffer_get_ssh_string(buffer);
|
||||
if (e == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = pki_pubkey_build_ecdsa(key, nid, e);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA public key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -910,8 +1254,8 @@ fail:
|
||||
int ssh_pki_import_pubkey_base64(const char *b64_key,
|
||||
enum ssh_keytypes_e type,
|
||||
ssh_key *pkey) {
|
||||
ssh_buffer buffer;
|
||||
ssh_string type_s;
|
||||
ssh_buffer buffer = NULL;
|
||||
ssh_string type_s = NULL;
|
||||
int rc;
|
||||
|
||||
if (b64_key == NULL || pkey == NULL) {
|
||||
@@ -958,7 +1302,7 @@ int ssh_pki_import_pubkey_base64(const char *b64_key,
|
||||
*/
|
||||
int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
|
||||
ssh_key *pkey) {
|
||||
ssh_buffer buffer;
|
||||
ssh_buffer buffer = NULL;
|
||||
ssh_string type_s = NULL;
|
||||
enum ssh_keytypes_e type;
|
||||
int rc;
|
||||
@@ -1032,7 +1376,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
|
||||
const char *q;
|
||||
FILE *file;
|
||||
off_t size;
|
||||
int rc;
|
||||
int rc, cmp;
|
||||
|
||||
if (pkey == NULL || filename == NULL || *filename == '\0') {
|
||||
return SSH_ERROR;
|
||||
@@ -1082,6 +1426,20 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
|
||||
key_buf[size] = '\0';
|
||||
buflen = strlen(key_buf);
|
||||
|
||||
/* Test for new OpenSSH key format first */
|
||||
cmp = strncmp(key_buf, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN));
|
||||
if (cmp == 0) {
|
||||
*pkey = ssh_pki_openssh_pubkey_import(key_buf);
|
||||
SAFE_FREE(key_buf);
|
||||
if (*pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to import public key from OpenSSH"
|
||||
" private key file");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/* This the old one-line public key format */
|
||||
q = p = key_buf;
|
||||
for (i = 0; i < buflen; i++) {
|
||||
if (isspace((int)p[i])) {
|
||||
@@ -1507,8 +1865,10 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
{
|
||||
ssh_signature sig;
|
||||
enum ssh_keytypes_e type;
|
||||
enum ssh_digest_e hash_type;
|
||||
ssh_string str;
|
||||
ssh_buffer buf;
|
||||
const char *alg = NULL;
|
||||
int rc;
|
||||
|
||||
if (sig_blob == NULL || psig == NULL) {
|
||||
@@ -1534,7 +1894,9 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
type = ssh_key_type_from_name(ssh_string_get_char(str));
|
||||
alg = ssh_string_get_char(str);
|
||||
type = ssh_key_type_from_signature_name(alg);
|
||||
hash_type = ssh_key_hash_from_name(alg);
|
||||
ssh_string_free(str);
|
||||
|
||||
str = ssh_buffer_get_ssh_string(buf);
|
||||
@@ -1543,7 +1905,7 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
sig = pki_signature_from_blob(pubkey, str, type);
|
||||
sig = pki_signature_from_blob(pubkey, str, type, hash_type);
|
||||
ssh_string_free(str);
|
||||
if (sig == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -1593,22 +1955,45 @@ int ssh_pki_signature_verify_blob(ssh_session session,
|
||||
} else if (key->type == SSH_KEYTYPE_ED25519) {
|
||||
rc = pki_signature_verify(session, sig, key, digest, dlen);
|
||||
} else {
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
uint32_t hlen = 0;
|
||||
|
||||
sha1(digest, dlen, hash);
|
||||
if (sig->type != SSH_KEYTYPE_RSA && sig->hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Only RSA keys support non-SHA1 hashes.");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch (sig->hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(digest, dlen, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(digest, dlen, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
sha1(digest, dlen, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->hash_type: %d", sig->hash_type);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa(key->type == SSH_KEYTYPE_DSS
|
||||
? "Hash to be verified with DSA"
|
||||
: "Hash to be verified with RSA",
|
||||
hash,
|
||||
SHA_DIGEST_LEN);
|
||||
hlen);
|
||||
#endif
|
||||
|
||||
rc = pki_signature_verify(session,
|
||||
sig,
|
||||
key,
|
||||
hash,
|
||||
SHA_DIGEST_LEN);
|
||||
hlen);
|
||||
}
|
||||
|
||||
ssh_signature_free(sig);
|
||||
@@ -1687,24 +2072,57 @@ ssh_string ssh_pki_do_sign(ssh_session session,
|
||||
ssh_buffer_get_len(buf));
|
||||
ssh_buffer_free(buf);
|
||||
} else {
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
SHACTX ctx;
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
uint32_t hlen = 0;
|
||||
enum ssh_digest_e hash_type;
|
||||
ssh_buffer buf;
|
||||
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
buf = ssh_buffer_new();
|
||||
if (buf == NULL) {
|
||||
ssh_string_free(session_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sha1_update(ctx, session_id, ssh_string_len(session_id) + 4);
|
||||
sha1_update(ctx, ssh_buffer_get(sigbuf), ssh_buffer_get_len(sigbuf));
|
||||
sha1_final(hash, ctx);
|
||||
ssh_buffer_set_secure(buf);
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"SP",
|
||||
session_id,
|
||||
ssh_buffer_get_len(sigbuf), ssh_buffer_get(sigbuf));
|
||||
if (rc != SSH_OK) {
|
||||
ssh_string_free(session_id);
|
||||
ssh_buffer_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hash_type = ssh_key_type_to_hash(session, privkey->type);
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d",
|
||||
sig->type);
|
||||
ssh_string_free(session_id);
|
||||
ssh_buffer_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
ssh_buffer_free(buf);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
|
||||
ssh_print_hexa("Hash being signed", hash, hlen);
|
||||
#endif
|
||||
|
||||
sig = pki_do_sign(privkey, hash, SHA_DIGEST_LEN);
|
||||
sig = pki_do_sign_hash(privkey, hash, hlen, hash_type);
|
||||
}
|
||||
ssh_string_free(session_id);
|
||||
if (sig == NULL) {
|
||||
@@ -1827,21 +2245,36 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
sig = NULL;
|
||||
}
|
||||
} else {
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
SHACTX ctx;
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
uint32_t hlen = 0;
|
||||
enum ssh_digest_e hash_type;
|
||||
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
hash_type = ssh_key_type_to_hash(session, privkey->type);
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
sha1(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->type: %d", sig->type);
|
||||
return NULL;
|
||||
}
|
||||
sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||
sha1_final(hash, ctx);
|
||||
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
|
||||
ssh_print_hexa("Hash being signed", hash, hlen);
|
||||
#endif
|
||||
|
||||
sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
|
||||
sig = pki_do_sign_sessionid_hash(privkey, hash, hlen, hash_type);
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/priv.h"
|
||||
@@ -60,7 +61,6 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
|
||||
enum ssh_keytypes_e type;
|
||||
char *type_s = NULL;
|
||||
ssh_key key = NULL;
|
||||
ssh_string pubkey = NULL, privkey = NULL;
|
||||
int rc;
|
||||
|
||||
if (pkey == NULL) {
|
||||
@@ -75,57 +75,14 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
|
||||
|
||||
type = ssh_key_type_from_name(type_s);
|
||||
if (type == SSH_KEYTYPE_UNKNOWN) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown key type found!");
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown key type '%s' found!", type_s);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
SAFE_FREE(type_s);
|
||||
|
||||
key = ssh_key_new();
|
||||
if (key == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Out of memory");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
key->type = type;
|
||||
key->type_c = ssh_key_type_to_char(type);
|
||||
key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
|
||||
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
rc = ssh_buffer_unpack(key_blob_buffer, "SS", &pubkey, &privkey);
|
||||
if (rc != SSH_OK){
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
if(ssh_string_len(pubkey) != ED25519_PK_LEN ||
|
||||
ssh_string_len(privkey) != ED25519_SK_LEN){
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len");
|
||||
goto fail;
|
||||
}
|
||||
key->ed25519_privkey = malloc(ED25519_SK_LEN);
|
||||
key->ed25519_pubkey = malloc(ED25519_PK_LEN);
|
||||
if(key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL){
|
||||
goto fail;
|
||||
}
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey), ED25519_SK_LEN);
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN);
|
||||
explicit_bzero(ssh_string_data(privkey), ED25519_SK_LEN);
|
||||
SAFE_FREE(privkey);
|
||||
SAFE_FREE(pubkey);
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_DSS:
|
||||
/* p,q,g,pub_key,priv_key */
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
case SSH_KEYTYPE_RSA:
|
||||
/* n,e,d,iqmp,p,q */
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
/* curve_name, group, privkey */
|
||||
SSH_LOG(SSH_LOG_WARN, "Unsupported private key method %s", key->type_c);
|
||||
goto fail;
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown private key protocol %s", key->type_c);
|
||||
rc = pki_import_privkey_buffer(type, key_blob_buffer, &key);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to read key in OpenSSH format");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -133,11 +90,6 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
|
||||
return SSH_OK;
|
||||
fail:
|
||||
ssh_key_free(key);
|
||||
if(privkey != NULL){
|
||||
memset(ssh_string_data(privkey), 0, ssh_string_len(privkey));
|
||||
}
|
||||
SAFE_FREE(pubkey);
|
||||
SAFE_FREE(privkey);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -274,10 +226,12 @@ static int pki_private_key_decrypt(ssh_string blob,
|
||||
* @brief Import a private key in OpenSSH (new) format. This format is
|
||||
* typically used with ed25519 keys but can be used for others.
|
||||
*/
|
||||
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data)
|
||||
static ssh_key
|
||||
ssh_pki_openssh_import(const char *text_key,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
bool private)
|
||||
{
|
||||
const char *ptr=text_key;
|
||||
const char *end;
|
||||
@@ -298,7 +252,7 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
cmp = strncmp(ptr, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN));
|
||||
if (cmp != 0){
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no header)");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
ptr += strlen(OPENSSH_HEADER_BEGIN);
|
||||
while(ptr[0] != '\0' && !isspace((int)ptr[0])) {
|
||||
@@ -307,11 +261,11 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
end = strstr(ptr, OPENSSH_HEADER_END);
|
||||
if (end == NULL){
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no footer)");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
base64 = malloc(end - ptr + 1);
|
||||
if (base64 == NULL){
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; ptr < end; ptr++){
|
||||
if (!isspace((int)ptr[0])) {
|
||||
@@ -324,7 +278,7 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
SAFE_FREE(base64);
|
||||
if (buffer == NULL){
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (base64 error)");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
rc = ssh_buffer_unpack(buffer, "PssSdSS",
|
||||
strlen(OPENSSH_AUTH_MAGIC) + 1,
|
||||
@@ -337,12 +291,12 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
&privkeys);
|
||||
if (rc == SSH_ERROR){
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (unpack error)");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
cmp = strncmp(magic, OPENSSH_AUTH_MAGIC, strlen(OPENSSH_AUTH_MAGIC));
|
||||
if (cmp != 0){
|
||||
SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (bad magic)");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Opening OpenSSH private key: ciphername: %s, kdf: %s, nkeys: %d\n",
|
||||
@@ -351,8 +305,18 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
nkeys);
|
||||
if (nkeys != 1){
|
||||
SSH_LOG(SSH_LOG_WARN, "Opening OpenSSH private key: only 1 key supported (%d available)", nkeys);
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If we are interested only in public key do not progress
|
||||
* to the key decryption later
|
||||
*/
|
||||
if (!private) {
|
||||
rc = ssh_pki_import_pubkey_blob(pubkey0, &key);
|
||||
/* in either case we clean up here */
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = pki_private_key_decrypt(privkeys,
|
||||
passphrase,
|
||||
ciphername,
|
||||
@@ -361,13 +325,13 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
if (rc == SSH_ERROR){
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
privkey_buffer = ssh_buffer_new();
|
||||
if (privkey_buffer == NULL) {
|
||||
rc = SSH_ERROR;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ssh_buffer_set_secure(privkey_buffer);
|
||||
@@ -378,11 +342,11 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
rc = ssh_buffer_unpack(privkey_buffer, "dd", &checkint1, &checkint2);
|
||||
if (rc == SSH_ERROR || checkint1 != checkint2){
|
||||
SSH_LOG(SSH_LOG_WARN, "OpenSSH private key unpack error (correct password?)");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
rc = pki_openssh_import_privkey_blob(privkey_buffer, &key);
|
||||
if (rc == SSH_ERROR){
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
comment = ssh_buffer_get_ssh_string(privkey_buffer);
|
||||
SAFE_FREE(comment);
|
||||
@@ -393,15 +357,15 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
ssh_key_free(key);
|
||||
key = NULL;
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid padding");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
error:
|
||||
if(buffer != NULL){
|
||||
out:
|
||||
if (buffer != NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
if(privkey_buffer != NULL){
|
||||
if (privkey_buffer != NULL) {
|
||||
ssh_buffer_free(privkey_buffer);
|
||||
privkey_buffer = NULL;
|
||||
}
|
||||
@@ -414,6 +378,19 @@ error:
|
||||
return key;
|
||||
}
|
||||
|
||||
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data)
|
||||
{
|
||||
return ssh_pki_openssh_import(text_key, passphrase, auth_fn, auth_data, true);
|
||||
}
|
||||
|
||||
ssh_key ssh_pki_openssh_pubkey_import(const char *text_key)
|
||||
{
|
||||
return ssh_pki_openssh_import(text_key, NULL, NULL, NULL, false);
|
||||
}
|
||||
|
||||
|
||||
/** @internal
|
||||
* @brief exports a private key to a string blob.
|
||||
|
||||
268
src/pki_crypto.c
268
src/pki_crypto.c
@@ -172,10 +172,65 @@ static ssh_string make_ecpoint_string(const EC_GROUP *g,
|
||||
return s;
|
||||
}
|
||||
|
||||
int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
|
||||
{
|
||||
EC_POINT *p = NULL;
|
||||
const EC_GROUP *g = NULL;
|
||||
int ok;
|
||||
BIGNUM *bexp = NULL;
|
||||
|
||||
key->ecdsa_nid = nid;
|
||||
key->type_c = pki_key_ecdsa_nid_to_name(nid);
|
||||
|
||||
key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
|
||||
if (key->ecdsa == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
g = EC_KEY_get0_group(key->ecdsa);
|
||||
|
||||
p = EC_POINT_new(g);
|
||||
if (p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ok = EC_POINT_oct2point(g,
|
||||
p,
|
||||
ssh_string_data(e),
|
||||
ssh_string_len(e),
|
||||
NULL);
|
||||
if (!ok) {
|
||||
EC_POINT_free(p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* EC_KEY_set_public_key duplicates p */
|
||||
ok = EC_KEY_set_public_key(key->ecdsa, p);
|
||||
EC_POINT_free(p);
|
||||
if (!ok) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bexp = ssh_make_string_bn(exp);
|
||||
if (bexp == NULL) {
|
||||
EC_KEY_free(key->ecdsa);
|
||||
return -1;
|
||||
}
|
||||
/* EC_KEY_set_private_key duplicates exp */
|
||||
ok = EC_KEY_set_private_key(key->ecdsa, bexp);
|
||||
BN_free(bexp);
|
||||
if (!ok) {
|
||||
EC_KEY_free(key->ecdsa);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
|
||||
{
|
||||
EC_POINT *p;
|
||||
const EC_GROUP *g;
|
||||
EC_POINT *p = NULL;
|
||||
const EC_GROUP *g = NULL;
|
||||
int ok;
|
||||
|
||||
key->ecdsa_nid = nid;
|
||||
@@ -260,6 +315,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of np, nq and ng is transfered to DSA object */
|
||||
rc = DSA_set0_pqg(new->dsa, np, nq, ng);
|
||||
if (rc == 0) {
|
||||
BN_free(np);
|
||||
@@ -274,6 +330,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of npubkey is transfered to DSA object */
|
||||
rc = DSA_set0_key(new->dsa, npub_key, NULL);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
@@ -285,6 +342,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of npriv_key is transfered to DSA object */
|
||||
rc = DSA_set0_key(new->dsa, NULL, npriv_key);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
@@ -321,6 +379,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of nn and ne is transfered to RSA object */
|
||||
rc = RSA_set0_key(new->rsa, nn, ne, NULL);
|
||||
if (rc == 0) {
|
||||
BN_free(nn);
|
||||
@@ -338,6 +397,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of nd is transfered to RSA object */
|
||||
rc = RSA_set0_key(new->rsa, NULL, NULL, nd);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
@@ -356,6 +416,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of np and nq is transfered to RSA object */
|
||||
rc = RSA_set0_factors(new->rsa, np, nq);
|
||||
if (rc == 0) {
|
||||
BN_free(np);
|
||||
@@ -376,6 +437,8 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of ndmp1, ndmq1 and niqmp is transfered
|
||||
* to RSA object */
|
||||
rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp);
|
||||
if (rc == 0) {
|
||||
BN_free(ndmp1);
|
||||
@@ -888,13 +951,56 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pki_privkey_build_dss(ssh_key key,
|
||||
ssh_string p,
|
||||
ssh_string q,
|
||||
ssh_string g,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey)
|
||||
{
|
||||
int rc;
|
||||
BIGNUM *bp, *bq, *bg, *bpub_key, *bpriv_key;
|
||||
|
||||
key->dsa = DSA_new();
|
||||
if (key->dsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
bp = ssh_make_string_bn(p);
|
||||
bq = ssh_make_string_bn(q);
|
||||
bg = ssh_make_string_bn(g);
|
||||
bpub_key = ssh_make_string_bn(pubkey);
|
||||
bpriv_key = ssh_make_string_bn(privkey);
|
||||
if (bp == NULL || bq == NULL ||
|
||||
bg == NULL || bpub_key == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of bp, qq and bg is transfered to DSA object */
|
||||
rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of bpub_key and bpriv_key is transfered to DSA object */
|
||||
rc = DSA_set0_key(key->dsa, bpub_key, bpriv_key);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
fail:
|
||||
DSA_free(key->dsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_dss(ssh_key key,
|
||||
ssh_string p,
|
||||
ssh_string q,
|
||||
ssh_string g,
|
||||
ssh_string pubkey) {
|
||||
int rc;
|
||||
BIGNUM *bp, *bq, *bg, *bpub_key;
|
||||
BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL;
|
||||
|
||||
key->dsa = DSA_new();
|
||||
if (key->dsa == NULL) {
|
||||
@@ -910,11 +1016,13 @@ int pki_pubkey_build_dss(ssh_key key,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of bp, bq and bg is transfered to DSA object */
|
||||
rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of npub_key is transfered to DSA object */
|
||||
rc = DSA_set0_key(key->dsa, bpub_key, NULL);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
@@ -926,11 +1034,63 @@ fail:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int pki_privkey_build_rsa(ssh_key key,
|
||||
ssh_string n,
|
||||
ssh_string e,
|
||||
ssh_string d,
|
||||
ssh_string iqmp,
|
||||
ssh_string p,
|
||||
ssh_string q)
|
||||
{
|
||||
int rc;
|
||||
BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq;
|
||||
|
||||
key->rsa = RSA_new();
|
||||
if (key->rsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
bn = ssh_make_string_bn(n);
|
||||
be = ssh_make_string_bn(e);
|
||||
bd = ssh_make_string_bn(d);
|
||||
/*biqmp = ssh_make_string_bn(iqmp);*/
|
||||
bp = ssh_make_string_bn(p);
|
||||
bq = ssh_make_string_bn(q);
|
||||
if (be == NULL || bn == NULL || bd == NULL ||
|
||||
/*biqmp == NULL ||*/ bp == NULL || bq == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of be, bn and bd is transfered to RSA object */
|
||||
rc = RSA_set0_key(key->rsa, bn, be, bd);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of bp and bq is transfered to RSA object */
|
||||
rc = RSA_set0_factors(key->rsa, bp, bq);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the RSA
|
||||
* operations are much faster when these values are available.
|
||||
* https://www.openssl.org/docs/man1.0.2/crypto/rsa.html
|
||||
*/
|
||||
/* RSA_set0_crt_params(key->rsa, biqmp, NULL, NULL);
|
||||
TODO calculate missing crt_params */
|
||||
|
||||
return SSH_OK;
|
||||
fail:
|
||||
RSA_free(key->rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_rsa(ssh_key key,
|
||||
ssh_string e,
|
||||
ssh_string n) {
|
||||
int rc;
|
||||
BIGNUM *be, *bn;
|
||||
BIGNUM *be = NULL, *bn = NULL;
|
||||
|
||||
key->rsa = RSA_new();
|
||||
if (key->rsa == NULL) {
|
||||
@@ -943,6 +1103,7 @@ int pki_pubkey_build_rsa(ssh_key key,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Memory management of bn and be is transfered to RSA object */
|
||||
rc = RSA_set0_key(key->rsa, bn, be, NULL);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
@@ -1181,23 +1342,43 @@ fail:
|
||||
*
|
||||
* @param[in] privkey The private rsa key to use for signing.
|
||||
*
|
||||
* @param[in] hash_type The hash algorithm to use.
|
||||
*
|
||||
* @return A newly allocated rsa sig blob or NULL on error.
|
||||
*/
|
||||
static ssh_string _RSA_do_sign(const unsigned char *digest,
|
||||
int dlen,
|
||||
RSA *privkey)
|
||||
static ssh_string _RSA_do_sign_hash(const unsigned char *digest,
|
||||
int dlen,
|
||||
RSA *privkey,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_string sig_blob;
|
||||
unsigned char *sig;
|
||||
unsigned int slen;
|
||||
int ok;
|
||||
int nid = 0;
|
||||
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
nid = NID_sha1;
|
||||
break;
|
||||
case SSH_DIGEST_SHA256:
|
||||
nid = NID_sha256;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
nid = NID_sha512;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Incomplatible hash type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = malloc(RSA_size(privkey));
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ok = RSA_sign(NID_sha1, digest, dlen, sig, &slen, privkey);
|
||||
ok = RSA_sign(nid, digest, dlen, sig, &slen, privkey);
|
||||
if (!ok) {
|
||||
SAFE_FREE(sig);
|
||||
return NULL;
|
||||
@@ -1210,7 +1391,7 @@ static ssh_string _RSA_do_sign(const unsigned char *digest,
|
||||
}
|
||||
|
||||
ssh_string_fill(sig_blob, sig, slen);
|
||||
memset(sig, 'd', slen);
|
||||
explicit_bzero(sig, slen);
|
||||
SAFE_FREE(sig);
|
||||
|
||||
return sig_blob;
|
||||
@@ -1409,7 +1590,8 @@ errout:
|
||||
|
||||
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
const ssh_string sig_blob,
|
||||
enum ssh_keytypes_e type)
|
||||
enum ssh_keytypes_e type,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_signature sig;
|
||||
ssh_string r;
|
||||
@@ -1424,7 +1606,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
}
|
||||
|
||||
sig->type = type;
|
||||
sig->type_c = ssh_key_type_to_char(type);
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
|
||||
len = ssh_string_len(sig_blob);
|
||||
|
||||
@@ -1478,6 +1661,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Memory management of pr and ps is transfered to DSA signature
|
||||
* object */
|
||||
rc = DSA_SIG_set0(sig->dsa_sig, pr, ps);
|
||||
if (rc == 0) {
|
||||
ssh_signature_free(sig);
|
||||
@@ -1556,6 +1741,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Memory management of pr and ps is transfered to
|
||||
* ECDSA signature object */
|
||||
rc = ECDSA_SIG_set0(sig->ecdsa_sig, pr, ps);
|
||||
if (rc == 0) {
|
||||
ssh_signature_free(sig);
|
||||
@@ -1598,6 +1785,7 @@ int pki_signature_verify(ssh_session session,
|
||||
size_t hlen)
|
||||
{
|
||||
int rc;
|
||||
int nid;
|
||||
|
||||
switch(key->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
@@ -1615,13 +1803,33 @@ int pki_signature_verify(ssh_session session,
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
rc = RSA_verify(NID_sha1,
|
||||
switch (sig->hash_type) {
|
||||
case SSH_DIGEST_AUTO:
|
||||
case SSH_DIGEST_SHA1:
|
||||
nid = NID_sha1;
|
||||
break;
|
||||
case SSH_DIGEST_SHA256:
|
||||
nid = NID_sha256;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
nid = NID_sha512;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown hash type %d", sig->hash_type);
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Unexpected hash type %d during RSA verify",
|
||||
sig->hash_type);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rc = RSA_verify(nid,
|
||||
hash,
|
||||
hlen,
|
||||
ssh_string_data(sig->rsa_sig),
|
||||
ssh_string_len(sig->rsa_sig),
|
||||
key->rsa);
|
||||
if (rc <= 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "RSA verify failed");
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"RSA error: %s",
|
||||
@@ -1655,6 +1863,7 @@ int pki_signature_verify(ssh_session session,
|
||||
#endif
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown key type");
|
||||
ssh_set_error(session, SSH_FATAL, "Unknown public key type");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -1662,18 +1871,27 @@ int pki_signature_verify(ssh_session session,
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen) {
|
||||
ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_signature sig;
|
||||
int rc;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (privkey->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig->type = privkey->type;
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = privkey->type_c;
|
||||
|
||||
switch(privkey->type) {
|
||||
@@ -1696,7 +1914,8 @@ ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
sig->rsa_sig = _RSA_do_sign(hash, hlen, privkey->rsa);
|
||||
sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
|
||||
sig->rsa_sig = _RSA_do_sign_hash(hash, hlen, privkey->rsa, hash_type);
|
||||
if (sig->rsa_sig == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
@@ -1739,16 +1958,24 @@ ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_signature sig;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig->type = key->type;
|
||||
sig->type_c = key->type_c;
|
||||
|
||||
@@ -1762,7 +1989,8 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
sig->rsa_sig = _RSA_do_sign(hash, hlen, key->rsa);
|
||||
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
|
||||
sig->rsa_sig = _RSA_do_sign_hash(hash, hlen, key->rsa, hash_type);
|
||||
if (sig->rsa_sig == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
|
||||
@@ -56,6 +56,28 @@ 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,
|
||||
|
||||
163
src/pki_gcrypt.c
163
src/pki_gcrypt.c
@@ -1030,6 +1030,27 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pki_privkey_build_dss(ssh_key key,
|
||||
ssh_string p,
|
||||
ssh_string q,
|
||||
ssh_string g,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey)
|
||||
{
|
||||
gcry_sexp_build(&key->dsa, NULL,
|
||||
"(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))",
|
||||
ssh_string_len(p), ssh_string_data(p),
|
||||
ssh_string_len(q), ssh_string_data(q),
|
||||
ssh_string_len(g), ssh_string_data(g),
|
||||
ssh_string_len(pubkey), ssh_string_data(pubkey),
|
||||
ssh_string_len(privkey), ssh_string_data(privkey));
|
||||
if (key->dsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_dss(ssh_key key,
|
||||
ssh_string p,
|
||||
ssh_string q,
|
||||
@@ -1048,6 +1069,32 @@ int pki_pubkey_build_dss(ssh_key key,
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int pki_privkey_build_rsa(ssh_key key,
|
||||
ssh_string n,
|
||||
ssh_string e,
|
||||
ssh_string d,
|
||||
ssh_string iqmp,
|
||||
ssh_string p,
|
||||
ssh_string q)
|
||||
{
|
||||
/* in gcrypt, there is no iqmp (inverse of q mod p) argument,
|
||||
* but it is ipmq (inverse of p mod q) so we need to swap
|
||||
* the p and q arguments */
|
||||
gcry_sexp_build(&key->rsa, NULL,
|
||||
"(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
|
||||
ssh_string_len(n), ssh_string_data(n),
|
||||
ssh_string_len(e), ssh_string_data(e),
|
||||
ssh_string_len(d), ssh_string_data(d),
|
||||
ssh_string_len(q), ssh_string_data(q),
|
||||
ssh_string_len(p), ssh_string_data(p),
|
||||
ssh_string_len(iqmp), ssh_string_data(iqmp));
|
||||
if (key->rsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_rsa(ssh_key key,
|
||||
ssh_string e,
|
||||
ssh_string n) {
|
||||
@@ -1063,6 +1110,25 @@ int pki_pubkey_build_rsa(ssh_key key,
|
||||
}
|
||||
|
||||
#ifdef HAVE_GCRYPT_ECC
|
||||
int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
key->ecdsa_nid = nid;
|
||||
key->type_c = pki_key_ecdsa_nid_to_name(nid);
|
||||
|
||||
err = gcry_sexp_build(&key->ecdsa, NULL,
|
||||
"(private-key(ecdsa(curve %s)(d %b)(q %b)))",
|
||||
pki_key_ecdsa_nid_to_gcrypt_name(nid),
|
||||
ssh_string_len(exp), ssh_string_data(exp),
|
||||
ssh_string_len(e), ssh_string_data(e));
|
||||
if (err) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
|
||||
{
|
||||
gpg_error_t err;
|
||||
@@ -1773,7 +1839,8 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
|
||||
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
const ssh_string sig_blob,
|
||||
enum ssh_keytypes_e type)
|
||||
enum ssh_keytypes_e type,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_signature sig;
|
||||
gcry_error_t err;
|
||||
@@ -1787,6 +1854,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
}
|
||||
|
||||
sig->type = type;
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
|
||||
len = ssh_string_len(sig_blob);
|
||||
|
||||
@@ -1952,6 +2021,7 @@ int pki_signature_verify(ssh_session session,
|
||||
size_t hlen)
|
||||
{
|
||||
unsigned char ghash[hlen + 1];
|
||||
const char *hash_type = NULL;
|
||||
gcry_sexp_t sexp;
|
||||
gcry_error_t err;
|
||||
|
||||
@@ -1986,10 +2056,29 @@ int pki_signature_verify(ssh_session session,
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
switch (sig->hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
hash_type = "sha256";
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
hash_type = "sha512";
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
hash_type = "sha1";
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig type %d", sig->hash_type);
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Unexpected signature type %d during RSA verify",
|
||||
sig->hash_type);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
err = gcry_sexp_build(&sexp,
|
||||
NULL,
|
||||
"(data(flags pkcs1)(hash sha1 %b))",
|
||||
hlen, hash);
|
||||
"(data(flags pkcs1)(hash %s %b))",
|
||||
hash_type, hlen, hash);
|
||||
if (err) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
@@ -2056,19 +2145,29 @@ int pki_signature_verify(ssh_session session,
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen) {
|
||||
ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
unsigned char ghash[hlen + 1];
|
||||
const char *hash_c = NULL;
|
||||
ssh_signature sig;
|
||||
gcry_sexp_t sexp;
|
||||
gcry_error_t err;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (privkey->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sig->type = privkey->type;
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = privkey->type_c;
|
||||
switch (privkey->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
@@ -2094,9 +2193,26 @@ ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
hash_c = "sha1";
|
||||
break;
|
||||
case SSH_DIGEST_SHA256:
|
||||
hash_c = "sha256";
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
hash_c = "sha512";
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Incomplatible key algorithm");
|
||||
return NULL;
|
||||
}
|
||||
err = gcry_sexp_build(&sexp,
|
||||
NULL,
|
||||
"(data(flags pkcs1)(hash sha1 %b))",
|
||||
"(data(flags pkcs1)(hash %s %b))",
|
||||
hash_c,
|
||||
hlen,
|
||||
hash);
|
||||
if (err) {
|
||||
@@ -2149,19 +2265,28 @@ ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
unsigned char ghash[hlen + 1];
|
||||
const char *hash_c = NULL;
|
||||
ssh_signature sig;
|
||||
gcry_sexp_t sexp;
|
||||
gcry_error_t err;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig->type = key->type;
|
||||
sig->type_c = key->type_c;
|
||||
|
||||
@@ -2188,9 +2313,25 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
hash_c = "sha1";
|
||||
break;
|
||||
case SSH_DIGEST_SHA256:
|
||||
hash_c = "sha256";
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
hash_c = "sha512";
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Incomplatible key algorithm");
|
||||
return NULL;
|
||||
}
|
||||
err = gcry_sexp_build(&sexp,
|
||||
NULL,
|
||||
"(data(flags pkcs1)(hash sha1 %b))",
|
||||
"(data(flags pkcs1)(hash %s %b))",
|
||||
hash_c,
|
||||
hlen,
|
||||
hash);
|
||||
if (err) {
|
||||
|
||||
@@ -214,6 +214,64 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pki_privkey_build_rsa(ssh_key key,
|
||||
ssh_string n,
|
||||
ssh_string e,
|
||||
ssh_string d,
|
||||
ssh_string iqmp,
|
||||
ssh_string p,
|
||||
ssh_string q)
|
||||
{
|
||||
mbedtls_rsa_context *rsa = NULL;
|
||||
const mbedtls_pk_info_t *pk_info = NULL;
|
||||
int rc;
|
||||
|
||||
key->rsa = malloc(sizeof(mbedtls_pk_context));
|
||||
if (key->rsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
mbedtls_pk_init(key->rsa);
|
||||
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
|
||||
mbedtls_pk_setup(key->rsa, pk_info);
|
||||
|
||||
rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rsa = mbedtls_pk_rsa(*key->rsa);
|
||||
rc = mbedtls_rsa_import_raw(rsa,
|
||||
ssh_string_data(n), ssh_string_len(n),
|
||||
ssh_string_data(p), ssh_string_len(p),
|
||||
ssh_string_data(q), ssh_string_len(q),
|
||||
ssh_string_data(d), ssh_string_len(d),
|
||||
ssh_string_data(e), ssh_string_len(e));
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to import private RSA key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = mbedtls_rsa_complete(rsa);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to complete private RSA key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = mbedtls_rsa_check_privkey(rsa);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Inconsistent private RSA key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
|
||||
fail:
|
||||
mbedtls_pk_free(key->rsa);
|
||||
SAFE_FREE(key->rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n)
|
||||
{
|
||||
mbedtls_rsa_context *rsa = NULL;
|
||||
@@ -229,25 +287,31 @@ int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n)
|
||||
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
|
||||
mbedtls_pk_setup(key->rsa, pk_info);
|
||||
|
||||
if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA)) {
|
||||
rsa = mbedtls_pk_rsa(*key->rsa);
|
||||
rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n),
|
||||
ssh_string_len(n));
|
||||
if (rc != 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e),
|
||||
ssh_string_len(e));
|
||||
if (rc != 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3;
|
||||
} else {
|
||||
return SSH_ERROR;
|
||||
rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
|
||||
if (rc == 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rsa = mbedtls_pk_rsa(*key->rsa);
|
||||
rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n),
|
||||
ssh_string_len(n));
|
||||
if (rc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e),
|
||||
ssh_string_len(e));
|
||||
if (rc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3;
|
||||
|
||||
return SSH_OK;
|
||||
|
||||
fail:
|
||||
mbedtls_pk_free(key->rsa);
|
||||
SAFE_FREE(key->rsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
@@ -825,8 +889,10 @@ errout:
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string
|
||||
sig_blob, enum ssh_keytypes_e type)
|
||||
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)
|
||||
{
|
||||
ssh_signature sig = NULL;
|
||||
int rc;
|
||||
@@ -837,7 +903,8 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string
|
||||
}
|
||||
|
||||
sig->type = type;
|
||||
sig->type_c = ssh_key_type_to_char(type);
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = ssh_key_signature_to_char(type, hash_type);
|
||||
|
||||
switch(type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
@@ -930,10 +997,30 @@ int pki_signature_verify(ssh_session session, const ssh_signature sig, const
|
||||
ssh_key key, const unsigned char *hash, size_t hlen)
|
||||
{
|
||||
int rc;
|
||||
mbedtls_md_type_t md = 0;
|
||||
|
||||
switch (key->type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
rc = mbedtls_pk_verify(key->rsa, MBEDTLS_MD_SHA1, hash, hlen,
|
||||
switch (sig->hash_type) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
break;
|
||||
case SSH_DIGEST_SHA256:
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig type %d", sig->hash_type);
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Unexpected signature hash type %d during RSA verify",
|
||||
sig->hash_type);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rc = mbedtls_pk_verify(key->rsa, md, hash, hlen,
|
||||
ssh_string_data(sig->rsa_sig),
|
||||
ssh_string_len(sig->rsa_sig));
|
||||
if (rc != 0) {
|
||||
@@ -970,21 +1057,40 @@ int pki_signature_verify(ssh_session session, const ssh_signature sig, const
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static ssh_string rsa_do_sign(const unsigned char *digest, int dlen,
|
||||
mbedtls_pk_context *privkey)
|
||||
static ssh_string rsa_do_sign_hash(const unsigned char *digest,
|
||||
int dlen,
|
||||
mbedtls_pk_context *privkey,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_string sig_blob = NULL;
|
||||
mbedtls_md_type_t md = 0;
|
||||
unsigned char *sig = NULL;
|
||||
size_t slen;
|
||||
int ok;
|
||||
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
md = MBEDTLS_MD_SHA1;
|
||||
break;
|
||||
case SSH_DIGEST_SHA256:
|
||||
md = MBEDTLS_MD_SHA256;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
md = MBEDTLS_MD_SHA512;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Incomplatible key algorithm");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = malloc(mbedtls_pk_get_bitlen(privkey) / 8);
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ok = mbedtls_pk_sign(privkey,
|
||||
MBEDTLS_MD_SHA1,
|
||||
md,
|
||||
digest,
|
||||
dlen,
|
||||
sig,
|
||||
@@ -1004,30 +1110,40 @@ static ssh_string rsa_do_sign(const unsigned char *digest, int dlen,
|
||||
}
|
||||
|
||||
ssh_string_fill(sig_blob, sig, slen);
|
||||
memset(sig, 'd', slen);
|
||||
explicit_bzero(sig, slen);
|
||||
SAFE_FREE(sig);
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
|
||||
ssh_signature pki_do_sign(const ssh_key privkey, const unsigned char *hash,
|
||||
size_t hlen)
|
||||
ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_signature sig = NULL;
|
||||
int rc;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (privkey->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig->type = privkey->type;
|
||||
sig->hash_type = hash_type;
|
||||
sig->type_c = privkey->type_c;
|
||||
|
||||
switch(privkey->type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
sig->rsa_sig = rsa_do_sign(hash, hlen, privkey->rsa);
|
||||
sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
|
||||
sig->rsa_sig = rsa_do_sign_hash(hash, hlen, privkey->rsa, hash_type);
|
||||
if (sig->rsa_sig == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
@@ -1075,22 +1191,32 @@ ssh_signature pki_do_sign(const ssh_key privkey, const unsigned char *hash,
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key, const unsigned char
|
||||
*hash, size_t hlen)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_signature sig = NULL;
|
||||
int rc;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig->type = key->type;
|
||||
sig->type_c = key->type_c;
|
||||
|
||||
switch (key->type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
sig->rsa_sig = rsa_do_sign(hash, hlen, key->rsa);
|
||||
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
|
||||
sig->rsa_sig = rsa_do_sign_hash(hash, hlen, key->rsa, hash_type);
|
||||
if (sig->rsa_sig == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
@@ -1175,6 +1301,73 @@ static mbedtls_ecp_group_id pki_key_ecdsa_nid_to_mbed_gid(int nid)
|
||||
return MBEDTLS_ECP_DP_NONE;
|
||||
}
|
||||
|
||||
int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
|
||||
{
|
||||
int rc;
|
||||
mbedtls_ecp_keypair keypair;
|
||||
mbedtls_ecp_group group;
|
||||
mbedtls_ecp_point Q;
|
||||
|
||||
key->ecdsa_nid = nid;
|
||||
key->type_c = pki_key_ecdsa_nid_to_name(nid);
|
||||
|
||||
key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
|
||||
if (key->ecdsa == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
mbedtls_ecdsa_init(key->ecdsa);
|
||||
mbedtls_ecp_keypair_init(&keypair);
|
||||
mbedtls_ecp_group_init(&group);
|
||||
mbedtls_ecp_point_init(&Q);
|
||||
|
||||
rc = mbedtls_ecp_group_load(&group,
|
||||
pki_key_ecdsa_nid_to_mbed_gid(nid));
|
||||
if (rc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = mbedtls_ecp_point_read_binary(&group, &Q, ssh_string_data(e),
|
||||
ssh_string_len(e));
|
||||
if (rc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = mbedtls_ecp_copy(&keypair.Q, &Q);
|
||||
if (rc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = mbedtls_ecp_group_copy(&keypair.grp, &group);
|
||||
if (rc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_read_binary(&keypair.d, ssh_string_data(exp),
|
||||
ssh_string_len(exp));
|
||||
if (rc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair);
|
||||
if (rc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mbedtls_ecp_point_free(&Q);
|
||||
mbedtls_ecp_group_free(&group);
|
||||
mbedtls_ecp_keypair_free(&keypair);
|
||||
return SSH_OK;
|
||||
|
||||
fail:
|
||||
mbedtls_ecdsa_free(key->ecdsa);
|
||||
mbedtls_ecp_point_free(&Q);
|
||||
mbedtls_ecp_group_free(&group);
|
||||
mbedtls_ecp_keypair_free(&keypair);
|
||||
SAFE_FREE(key->ecdsa);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
|
||||
{
|
||||
int rc;
|
||||
@@ -1279,6 +1472,18 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter)
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int pki_privkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g,
|
||||
ssh_string pubkey, ssh_string privkey)
|
||||
{
|
||||
(void) key;
|
||||
(void) p;
|
||||
(void) q;
|
||||
(void) g;
|
||||
(void) pubkey;
|
||||
(void) privkey;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int pki_pubkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g,
|
||||
ssh_string pubkey)
|
||||
{
|
||||
|
||||
17
src/poll.c
17
src/poll.c
@@ -1013,17 +1013,20 @@ int ssh_event_remove_connector(ssh_event event, ssh_connector connector){
|
||||
* fds before freeing the event object.
|
||||
*
|
||||
*/
|
||||
void ssh_event_free(ssh_event event) {
|
||||
int used, i;
|
||||
ssh_poll_handle p;
|
||||
if(event == NULL) {
|
||||
void ssh_event_free(ssh_event event)
|
||||
{
|
||||
size_t used, i;
|
||||
ssh_poll_handle p;
|
||||
|
||||
if(event == NULL) {
|
||||
return;
|
||||
}
|
||||
if(event->ctx != NULL) {
|
||||
|
||||
if (event->ctx != NULL) {
|
||||
used = event->ctx->polls_used;
|
||||
for(i = 0; i < used; i++) {
|
||||
p = event->ctx->pollptrs[i];
|
||||
if(p->session != NULL){
|
||||
p = event->ctx->pollptrs[i];
|
||||
if (p->session != NULL) {
|
||||
ssh_poll_ctx_remove(event->ctx, p);
|
||||
ssh_poll_ctx_add(p->session->default_poll_ctx, p);
|
||||
p->session = NULL;
|
||||
|
||||
50
src/server.c
50
src/server.c
@@ -67,7 +67,6 @@
|
||||
|
||||
static int dh_handshake_server(ssh_session session);
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup libssh_server
|
||||
*
|
||||
@@ -87,7 +86,7 @@ static int server_set_kex(ssh_session session) {
|
||||
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
|
||||
int i, j, rc;
|
||||
const char *wanted;
|
||||
char hostkeys[64] = {0};
|
||||
char hostkeys[128] = {0};
|
||||
enum ssh_keytypes_e keytype;
|
||||
size_t len;
|
||||
int ok;
|
||||
@@ -123,6 +122,11 @@ static int server_set_kex(ssh_session session) {
|
||||
}
|
||||
#endif
|
||||
if (session->srv.rsa_key != NULL) {
|
||||
/* We support also the SHA2 variants */
|
||||
len = strlen(hostkeys);
|
||||
snprintf(hostkeys + len, sizeof(hostkeys) - len,
|
||||
",rsa-sha2-512,rsa-sha2-256");
|
||||
|
||||
len = strlen(hostkeys);
|
||||
keytype = ssh_key_type(session->srv.rsa_key);
|
||||
|
||||
@@ -194,6 +198,37 @@ static int ssh_server_kexdh_init(ssh_session session, ssh_buffer packet){
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int ssh_server_send_extensions(ssh_session session) {
|
||||
int rc;
|
||||
const char *hostkey_algorithms;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO");
|
||||
/*
|
||||
* We can list here all the default hostkey methods, since
|
||||
* they already contain the SHA2 extension algorithms
|
||||
*/
|
||||
hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bdss",
|
||||
SSH2_MSG_EXT_INFO,
|
||||
1, /* nr. of extensions */
|
||||
"server-sig-algs",
|
||||
hostkey_algorithms);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
|
||||
int rc = SSH_ERROR;
|
||||
(void)type;
|
||||
@@ -217,6 +252,8 @@ SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
|
||||
switch(session->next_crypto->kex_type){
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc=ssh_server_kexdh_init(session, packet);
|
||||
break;
|
||||
#ifdef HAVE_ECDH
|
||||
@@ -486,6 +523,15 @@ static void ssh_server_connection_callback(ssh_session session){
|
||||
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
||||
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
|
||||
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
||||
|
||||
/*
|
||||
* If the client supports extension negotiation, we will send
|
||||
* our supported extensions now. This is the first message after
|
||||
* sending NEWKEYS message and after turning on crypto.
|
||||
*/
|
||||
if (session->extensions) {
|
||||
ssh_server_send_extensions(session);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSH_SESSION_STATE_AUTHENTICATING:
|
||||
|
||||
@@ -282,6 +282,7 @@ void ssh_free(ssh_session session) {
|
||||
SAFE_FREE(session->opts.ProxyCommand);
|
||||
SAFE_FREE(session->opts.gss_server_identity);
|
||||
SAFE_FREE(session->opts.gss_client_identity);
|
||||
SAFE_FREE(session->opts.pubkey_accepted_types);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (session->opts.wanted_methods[i]) {
|
||||
@@ -341,6 +342,10 @@ const char* ssh_get_kex_algo(ssh_session session) {
|
||||
return "diffie-hellman-group1-sha1";
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
return "diffie-hellman-group14-sha1";
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
return "diffie-hellman-group16-sha512";
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
return "diffie-hellman-group18-sha512";
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
return "ecdh-sha2-nistp256";
|
||||
case SSH_KEX_ECDH_SHA2_NISTP384:
|
||||
|
||||
2497
src/sftp.c
2497
src/sftp.c
File diff suppressed because it is too large
Load Diff
@@ -202,6 +202,29 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_EXTENDED:
|
||||
rc = ssh_buffer_unpack(payload,
|
||||
"s",
|
||||
&msg->submessage);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(msg->submessage, "hardlink@openssh.com") == 0 ||
|
||||
strcmp(msg->submessage, "posix-rename@openssh.com") == 0) {
|
||||
rc = ssh_buffer_unpack(payload,
|
||||
"sS",
|
||||
&msg->filename,
|
||||
&msg->data);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received unhandled sftp message %d", msg->type);
|
||||
@@ -242,12 +265,17 @@ uint32_t sftp_client_message_get_flags(sftp_client_message msg){
|
||||
return msg->flags;
|
||||
}
|
||||
|
||||
const char *sftp_client_message_get_submessage(sftp_client_message msg){
|
||||
return msg->submessage;
|
||||
}
|
||||
|
||||
void sftp_client_message_free(sftp_client_message msg) {
|
||||
if (msg == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
SAFE_FREE(msg->filename);
|
||||
SAFE_FREE(msg->submessage);
|
||||
ssh_string_free(msg->data);
|
||||
ssh_string_free(msg->handle);
|
||||
sftp_attributes_free(msg->attr);
|
||||
|
||||
31
src/string.c
31
src/string.c
@@ -34,6 +34,9 @@
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/string.h"
|
||||
|
||||
/* String maximum size is 256M */
|
||||
#define STRING_SIZE_MAX 0x10000000
|
||||
|
||||
/**
|
||||
* @defgroup libssh_string The SSH string functions
|
||||
* @ingroup libssh
|
||||
@@ -50,22 +53,24 @@
|
||||
*
|
||||
* @return The newly allocated string, NULL on error.
|
||||
*/
|
||||
struct ssh_string_struct *ssh_string_new(size_t size) {
|
||||
struct ssh_string_struct *str = NULL;
|
||||
struct ssh_string_struct *ssh_string_new(size_t size)
|
||||
{
|
||||
struct ssh_string_struct *str = NULL;
|
||||
|
||||
if (size > UINT_MAX - sizeof(struct ssh_string_struct)) {
|
||||
return NULL;
|
||||
}
|
||||
if (size > STRING_SIZE_MAX) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = malloc(sizeof(struct ssh_string_struct) + size);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
str = malloc(sizeof(struct ssh_string_struct) + size);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str->size = htonl(size);
|
||||
str->data[0] = 0;
|
||||
str->size = htonl(size);
|
||||
str->data[0] = 0;
|
||||
|
||||
return str;
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +141,7 @@ size_t ssh_string_len(struct ssh_string_struct *s) {
|
||||
}
|
||||
|
||||
size = ntohl(s->size);
|
||||
if (size > 0 && size < UINT_MAX) {
|
||||
if (size > 0 && size <= STRING_SIZE_MAX) {
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
114
src/wrapper.c
114
src/wrapper.c
@@ -146,81 +146,79 @@ struct ssh_crypto_struct *crypto_new(void) {
|
||||
return crypto;
|
||||
}
|
||||
|
||||
void crypto_free(struct ssh_crypto_struct *crypto){
|
||||
int i;
|
||||
if (crypto == NULL) {
|
||||
return;
|
||||
}
|
||||
void crypto_free(struct ssh_crypto_struct *crypto)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
ssh_key_free(crypto->server_pubkey);
|
||||
if (crypto == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cipher_free(crypto->in_cipher);
|
||||
cipher_free(crypto->out_cipher);
|
||||
ssh_key_free(crypto->server_pubkey);
|
||||
|
||||
bignum_safe_free(crypto->e);
|
||||
bignum_safe_free(crypto->f);
|
||||
bignum_safe_free(crypto->x);
|
||||
bignum_safe_free(crypto->y);
|
||||
bignum_safe_free(crypto->k);
|
||||
cipher_free(crypto->in_cipher);
|
||||
cipher_free(crypto->out_cipher);
|
||||
|
||||
bignum_safe_free(crypto->e);
|
||||
bignum_safe_free(crypto->f);
|
||||
bignum_safe_free(crypto->x);
|
||||
bignum_safe_free(crypto->y);
|
||||
bignum_safe_free(crypto->k);
|
||||
#ifdef HAVE_ECDH
|
||||
SAFE_FREE(crypto->ecdh_client_pubkey);
|
||||
SAFE_FREE(crypto->ecdh_server_pubkey);
|
||||
if(crypto->ecdh_privkey != NULL){
|
||||
SAFE_FREE(crypto->ecdh_client_pubkey);
|
||||
SAFE_FREE(crypto->ecdh_server_pubkey);
|
||||
if(crypto->ecdh_privkey != NULL){
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
EC_KEY_free(crypto->ecdh_privkey);
|
||||
EC_KEY_free(crypto->ecdh_privkey);
|
||||
#elif defined HAVE_GCRYPT_ECC
|
||||
gcry_sexp_release(crypto->ecdh_privkey);
|
||||
gcry_sexp_release(crypto->ecdh_privkey);
|
||||
#endif
|
||||
crypto->ecdh_privkey = NULL;
|
||||
}
|
||||
crypto->ecdh_privkey = NULL;
|
||||
}
|
||||
#endif
|
||||
if(crypto->session_id != NULL){
|
||||
memset(crypto->session_id, '\0', crypto->digest_len);
|
||||
SAFE_FREE(crypto->session_id);
|
||||
}
|
||||
if(crypto->secret_hash != NULL){
|
||||
memset(crypto->secret_hash, '\0', crypto->digest_len);
|
||||
SAFE_FREE(crypto->secret_hash);
|
||||
}
|
||||
if (crypto->session_id != NULL) {
|
||||
explicit_bzero(crypto->session_id, crypto->digest_len);
|
||||
SAFE_FREE(crypto->session_id);
|
||||
}
|
||||
if (crypto->secret_hash != NULL) {
|
||||
explicit_bzero(crypto->secret_hash, crypto->digest_len);
|
||||
SAFE_FREE(crypto->secret_hash);
|
||||
}
|
||||
#ifdef WITH_ZLIB
|
||||
if (crypto->compress_out_ctx &&
|
||||
(deflateEnd(crypto->compress_out_ctx) != 0)) {
|
||||
inflateEnd(crypto->compress_out_ctx);
|
||||
}
|
||||
SAFE_FREE(crypto->compress_out_ctx);
|
||||
if (crypto->compress_out_ctx &&
|
||||
(deflateEnd(crypto->compress_out_ctx) != 0)) {
|
||||
inflateEnd(crypto->compress_out_ctx);
|
||||
}
|
||||
SAFE_FREE(crypto->compress_out_ctx);
|
||||
|
||||
if (crypto->compress_in_ctx &&
|
||||
(deflateEnd(crypto->compress_in_ctx) != 0)) {
|
||||
inflateEnd(crypto->compress_in_ctx);
|
||||
}
|
||||
SAFE_FREE(crypto->compress_in_ctx);
|
||||
if (crypto->compress_in_ctx &&
|
||||
(deflateEnd(crypto->compress_in_ctx) != 0)) {
|
||||
inflateEnd(crypto->compress_in_ctx);
|
||||
}
|
||||
SAFE_FREE(crypto->compress_in_ctx);
|
||||
#endif /* WITH_ZLIB */
|
||||
if(crypto->encryptIV)
|
||||
SAFE_FREE(crypto->encryptIV);
|
||||
if(crypto->decryptIV)
|
||||
SAFE_FREE(crypto->decryptIV);
|
||||
if(crypto->encryptMAC)
|
||||
SAFE_FREE(crypto->encryptMAC);
|
||||
if(crypto->decryptMAC)
|
||||
SAFE_FREE(crypto->decryptMAC);
|
||||
if(crypto->encryptkey){
|
||||
memset(crypto->encryptkey, 0, crypto->digest_len);
|
||||
SAFE_FREE(crypto->encryptkey);
|
||||
}
|
||||
if(crypto->decryptkey){
|
||||
memset(crypto->decryptkey, 0, crypto->digest_len);
|
||||
SAFE_FREE(crypto->decryptkey);
|
||||
}
|
||||
if (crypto->encryptkey != NULL) {
|
||||
explicit_bzero(crypto->encryptkey, crypto->digest_len);
|
||||
SAFE_FREE(crypto->encryptkey);
|
||||
}
|
||||
if (crypto->decryptkey != NULL) {
|
||||
explicit_bzero(crypto->decryptkey, crypto->digest_len);
|
||||
SAFE_FREE(crypto->decryptkey);
|
||||
}
|
||||
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
SAFE_FREE(crypto->client_kex.methods[i]);
|
||||
SAFE_FREE(crypto->server_kex.methods[i]);
|
||||
SAFE_FREE(crypto->kex_methods[i]);
|
||||
}
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
SAFE_FREE(crypto->client_kex.methods[i]);
|
||||
SAFE_FREE(crypto->server_kex.methods[i]);
|
||||
SAFE_FREE(crypto->kex_methods[i]);
|
||||
}
|
||||
|
||||
explicit_bzero(crypto, sizeof(struct ssh_crypto_struct));
|
||||
explicit_bzero(crypto, sizeof(struct ssh_crypto_struct));
|
||||
|
||||
SAFE_FREE(crypto);
|
||||
SAFE_FREE(crypto);
|
||||
}
|
||||
|
||||
static int crypt_set_algorithms2(ssh_session session){
|
||||
@@ -509,7 +507,7 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
}
|
||||
|
||||
method = session->next_crypto->kex_methods[SSH_HOSTKEYS];
|
||||
session->srv.hostkey = ssh_key_type_from_name(method);
|
||||
session->srv.hostkey = ssh_key_type_from_signature_name(method);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ add_library(${TORTURE_LIBRARY}
|
||||
torture_pki.c
|
||||
torture_cmocka.c)
|
||||
target_link_libraries(${TORTURE_LIBRARY} ${TORTURE_LINK_LIBRARIES})
|
||||
target_compile_options(${TORTURE_LIBRARY} PRIVATE
|
||||
-DSSH_PING_EXECUTABLE="${CMAKE_CURRENT_BINARY_DIR}/ssh_ping"
|
||||
)
|
||||
|
||||
if (ARGP_LIBRARY)
|
||||
target_link_libraries(${TORTURE_LIBRARY}
|
||||
@@ -87,6 +90,11 @@ if (CLIENT_TESTING)
|
||||
chroot_wrapper
|
||||
)
|
||||
|
||||
# ssh_ping
|
||||
add_executable(ssh_ping ssh_ping.c)
|
||||
target_compile_options(ssh_ping PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(ssh_ping ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
# homedir will be used in passwd
|
||||
set(HOMEDIR ${CMAKE_CURRENT_BINARY_DIR}/home)
|
||||
|
||||
@@ -111,9 +119,14 @@ if (CLIENT_TESTING)
|
||||
# Give bob some keys
|
||||
file(COPY keys/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
file(COPY keys/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
file(COPY keys/id_ecdsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
file(COPY keys/id_ecdsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
|
||||
# Allow to auth with bob his public keys on alice account
|
||||
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY)
|
||||
# append ECDSA public key
|
||||
file(READ keys/id_ecdsa.pub CONTENTS)
|
||||
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys "${CONTENTS}")
|
||||
|
||||
# Copy the signed key to an alternative directory in bob's homedir.
|
||||
file(COPY keys/certauth/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
|
||||
@@ -15,12 +15,18 @@ set(LIBSSH_CLIENT_TESTS
|
||||
torture_request_env)
|
||||
|
||||
if (WITH_SFTP)
|
||||
if (WITH_BENCHMARKS)
|
||||
set(SFTP_BENCHMARK_TESTS
|
||||
torture_sftp_benchmark)
|
||||
endif()
|
||||
set(LIBSSH_CLIENT_TESTS
|
||||
${LIBSSH_CLIENT_TESTS}
|
||||
torture_sftp_ext
|
||||
torture_sftp_canonicalize_path
|
||||
torture_sftp_dir
|
||||
torture_sftp_read
|
||||
torture_sftp_fsync)
|
||||
torture_sftp_fsync
|
||||
${SFTP_BENCHMARK_TESTS})
|
||||
endif (WITH_SFTP)
|
||||
|
||||
foreach(_CLI_TEST ${LIBSSH_CLIENT_TESTS})
|
||||
|
||||
@@ -547,6 +547,175 @@ static void torture_auth_agent_cert_nonblocking(void **state) {
|
||||
torture_auth_agent_nonblocking(state);
|
||||
}
|
||||
|
||||
static void torture_auth_pubkey_types(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
ssh_session session = s->ssh.session;
|
||||
int rc;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_userauth_none(session,NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
|
||||
/* Disable RSA key types for authentication */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"ssh-dss");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
assert_int_equal(rc, SSH_AUTH_DENIED);
|
||||
|
||||
/* Now enable it and retry */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"rsa-sha2-512,ssh-rsa");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||
}
|
||||
|
||||
static void torture_auth_pubkey_types_ecdsa(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
ssh_session session = s->ssh.session;
|
||||
int rc;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_userauth_none(session,NULL);
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
|
||||
}
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
|
||||
/* We have only the 256b key -- whitelisting only larger should fail */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"ecdsa-sha2-nistp384");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
assert_int_equal(rc, SSH_AUTH_DENIED);
|
||||
|
||||
/* Verify we can use also ECDSA keys with their various names */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"ecdsa-sha2-nistp256");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
static void torture_auth_pubkey_types_nonblocking(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
ssh_session session = s->ssh.session;
|
||||
int rc;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
ssh_set_blocking(session,0);
|
||||
do {
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
} while (rc == SSH_AUTH_AGAIN);
|
||||
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
|
||||
/* Disable RSA key types for authentication */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"ssh-dss");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
do {
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
} while (rc == SSH_AUTH_AGAIN);
|
||||
assert_int_equal(rc, SSH_AUTH_DENIED);
|
||||
|
||||
/* Now enable it and retry */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"rsa-sha2-512,ssh-rsa");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
do {
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
} while (rc == SSH_AUTH_AGAIN);
|
||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
static void torture_auth_pubkey_types_ecdsa_nonblocking(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
ssh_session session = s->ssh.session;
|
||||
int rc;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
ssh_set_blocking(session,0);
|
||||
do {
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
} while (rc == SSH_AUTH_AGAIN);
|
||||
|
||||
/* This request should return a SSH_REQUEST_DENIED error */
|
||||
if (rc == SSH_ERROR) {
|
||||
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||
}
|
||||
|
||||
rc = ssh_userauth_list(session, NULL);
|
||||
assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
|
||||
|
||||
/* We have only the 256b key -- whitelisting only larger should fail */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"ecdsa-sha2-nistp384");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
do {
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
} while (rc == SSH_AUTH_AGAIN);
|
||||
assert_int_equal(rc, SSH_AUTH_DENIED);
|
||||
|
||||
/* Verify we can use also ECDSA keys with their various names */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"ecdsa-sha2-nistp256");
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
do {
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
} while (rc == SSH_AUTH_AGAIN);
|
||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
@@ -590,6 +759,18 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_auth_agent_cert_nonblocking,
|
||||
agent_cert_setup,
|
||||
agent_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types,
|
||||
pubkey_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_nonblocking,
|
||||
pubkey_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa,
|
||||
pubkey_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa_nonblocking,
|
||||
pubkey_setup,
|
||||
session_teardown),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
132
tests/client/torture_sftp_benchmark.c
Normal file
132
tests/client/torture_sftp_benchmark.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "torture.h"
|
||||
#include "sftp.c"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define MAX_XFER_BUF_SIZE 16384
|
||||
|
||||
static int sshd_setup(void **state)
|
||||
{
|
||||
torture_setup_sshd_server(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sshd_teardown(void **state) {
|
||||
torture_teardown_sshd_server(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_setup(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
struct passwd *pwd;
|
||||
int rc;
|
||||
|
||||
pwd = getpwnam("bob");
|
||||
assert_non_null(pwd);
|
||||
|
||||
rc = setuid(pwd->pw_uid);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
s->ssh.session = torture_ssh_session(TORTURE_SSH_SERVER,
|
||||
NULL,
|
||||
TORTURE_SSH_USER_ALICE,
|
||||
NULL);
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
s->ssh.tsftp = torture_sftp_session(s->ssh.session);
|
||||
assert_non_null(s->ssh.tsftp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_teardown(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
|
||||
torture_rmdirs(s->ssh.tsftp->testdir);
|
||||
torture_sftp_close(s->ssh.tsftp);
|
||||
ssh_disconnect(s->ssh.session);
|
||||
ssh_free(s->ssh.session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_sftp_benchmark_write_read(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
struct torture_sftp *t = s->ssh.tsftp;
|
||||
sftp_session sftp = t->sftp;
|
||||
ssh_session session = s->ssh.session;
|
||||
sftp_file file = NULL;
|
||||
struct stat sb = {
|
||||
.st_size = 0,
|
||||
};
|
||||
uint8_t buf_16k[MAX_XFER_BUF_SIZE];
|
||||
char local_path[1024] = {0};
|
||||
ssize_t bwritten, nread;
|
||||
size_t i;
|
||||
int rc;
|
||||
|
||||
memset(buf_16k, 'X', sizeof(buf_16k));
|
||||
|
||||
snprintf(local_path, sizeof(local_path), "%s/128M.dat", t->testdir);
|
||||
|
||||
file = sftp_open(sftp, local_path, O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
||||
assert_non_null(file);
|
||||
|
||||
/* Write 128M */
|
||||
for (i = 0; i < 0x2000; i++) {
|
||||
bwritten = sftp_write(file, buf_16k, sizeof(buf_16k));
|
||||
assert_int_equal(bwritten, sizeof(buf_16k));
|
||||
}
|
||||
|
||||
rc = sftp_close(file);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
/* Check that 128M has been written */
|
||||
rc = stat(local_path, &sb);
|
||||
assert_int_equal(sb.st_size, 0x8000000);
|
||||
|
||||
file = sftp_open(sftp, local_path, O_RDONLY, 0);
|
||||
assert_non_null(file);
|
||||
|
||||
for (;;) {
|
||||
nread = sftp_read(file, buf_16k, sizeof(buf_16k));
|
||||
if (nread == 0) {
|
||||
break; /* EOF */
|
||||
}
|
||||
assert_int_equal(nread, sizeof(buf_16k));
|
||||
}
|
||||
|
||||
rc = sftp_close(file);
|
||||
assert_ssh_return_code(session, rc);
|
||||
|
||||
unlink(local_path);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_sftp_benchmark_write_read,
|
||||
session_setup,
|
||||
session_teardown)
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||
ssh_finalize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
96
tests/client/torture_sftp_canonicalize_path.c
Normal file
96
tests/client/torture_sftp_canonicalize_path.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "config.h"
|
||||
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include "torture.h"
|
||||
#include "sftp.c"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int sshd_setup(void **state)
|
||||
{
|
||||
torture_setup_sshd_server(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sshd_teardown(void **state) {
|
||||
torture_teardown_sshd_server(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_setup(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
struct passwd *pwd;
|
||||
int rc;
|
||||
|
||||
pwd = getpwnam("bob");
|
||||
assert_non_null(pwd);
|
||||
|
||||
rc = setuid(pwd->pw_uid);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
s->ssh.session = torture_ssh_session(TORTURE_SSH_SERVER,
|
||||
NULL,
|
||||
TORTURE_SSH_USER_ALICE,
|
||||
NULL);
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
s->ssh.tsftp = torture_sftp_session(s->ssh.session);
|
||||
assert_non_null(s->ssh.tsftp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_teardown(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
|
||||
torture_rmdirs(s->ssh.tsftp->testdir);
|
||||
torture_sftp_close(s->ssh.tsftp);
|
||||
ssh_disconnect(s->ssh.session);
|
||||
ssh_free(s->ssh.session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_sftp_canonicalize_path(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
struct torture_sftp *t = s->ssh.tsftp;
|
||||
struct passwd *pwd = NULL;
|
||||
char *canonicalized_path = NULL;
|
||||
|
||||
pwd = getpwnam(TORTURE_SSH_USER_ALICE);
|
||||
assert_non_null(pwd);
|
||||
|
||||
canonicalized_path = sftp_canonicalize_path(t->sftp, ".");
|
||||
assert_non_null(canonicalized_path);
|
||||
|
||||
assert_string_equal(canonicalized_path, pwd->pw_dir);
|
||||
|
||||
SSH_STRING_FREE_CHAR(canonicalized_path);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_sftp_canonicalize_path,
|
||||
session_setup,
|
||||
session_teardown)
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ set(CTEST_SOURCE_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/source")
|
||||
set(CTEST_BINARY_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/build")
|
||||
|
||||
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind.supp)
|
||||
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS " --trace-children-skip=sshd")
|
||||
|
||||
find_program(CTEST_GIT_COMMAND NAMES git)
|
||||
find_program(CTEST_COVERAGE_COMMAND NAMES gcov)
|
||||
|
||||
5
tests/keys/id_ecdsa
Normal file
5
tests/keys/id_ecdsa
Normal file
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIHbL0nzpzLS3ImIlhEffbDzPlIw/tn5QcfB64PbSiBl6oAoGCCqGSM49
|
||||
AwEHoUQDQgAERzA8X8OP7C3W/e1UNLh+21xIZVBiQ7i4Qb4xoOebRWuwzitEZon/
|
||||
8Dz+VpE29krJgCagqSt5RLllOx8eS2i8fw==
|
||||
-----END EC PRIVATE KEY-----
|
||||
1
tests/keys/id_ecdsa.pub
Normal file
1
tests/keys/id_ecdsa.pub
Normal file
@@ -0,0 +1 @@
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEcwPF/Dj+wt1v3tVDS4fttcSGVQYkO4uEG+MaDnm0VrsM4rRGaJ//A8/laRNvZKyYAmoKkreUS5ZTsfHktovH8= comment
|
||||
@@ -38,7 +38,7 @@ target_link_libraries(pkd_hello ${pkd_libs})
|
||||
# specified with `-i` and may be helpful for chasing down bugs that
|
||||
# are not 100% reproducible.
|
||||
#
|
||||
add_test(pkd_hello_i1 ${CMAKE_CURRENT_BINARY_DIR}/pkd_hello -i1 -w /tmp/pkd_socket_wrapper_XXXXXX)
|
||||
add_test(pkd_hello_i1 ${CMAKE_CURRENT_BINARY_DIR}/pkd_hello -e -o -i1 -w /tmp/pkd_socket_wrapper_XXXXXX)
|
||||
|
||||
#
|
||||
# Configure environment for cwrap socket wrapper.
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
#define OPENSSH_BINARY "ssh"
|
||||
#define OPENSSH_KEYGEN "ssh-keygen"
|
||||
|
||||
#define OPENSSH_HOSTKEY_ALGOS_DEFAULT "ssh-ed25519,ssh-rsa"
|
||||
#define OPENSSH_PKACCEPTED_DEFAULT "ssh-ed25519,ssh-rsa"
|
||||
#define OPENSSH_HOSTKEY_ALGOS_DEFAULT "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa"
|
||||
#define OPENSSH_PKACCEPTED_DEFAULT "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa"
|
||||
|
||||
#if HAVE_ECC
|
||||
#define OPENSSH_HOSTKEY_ALGOS_ECDSA ",ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"
|
||||
|
||||
@@ -438,6 +438,9 @@ static void *pkd_main(void *args) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ignore SIGPIPE */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
rc = pkd_init_libssh();
|
||||
if (rc != 0) {
|
||||
pkderr("pkd_init_libssh: %d\n", rc);
|
||||
|
||||
@@ -222,6 +222,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, rsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_rsa, teardown) \
|
||||
f(client, rsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_rsa, teardown) \
|
||||
f(client, rsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_rsa, teardown) \
|
||||
f(client, rsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_rsa, teardown) \
|
||||
f(client, rsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_rsa, teardown) \
|
||||
f(client, rsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_rsa, teardown) \
|
||||
f(client, rsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_rsa, teardown) \
|
||||
f(client, dsa_curve25519_sha256, kexcmd("curve25519-sha256"), setup_dsa, teardown) \
|
||||
@@ -229,6 +231,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, dsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_dsa, teardown) \
|
||||
f(client, dsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384 "), setup_dsa, teardown) \
|
||||
f(client, dsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521 "), setup_dsa, teardown) \
|
||||
f(client, dsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_dsa, teardown) \
|
||||
f(client, dsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_dsa, teardown) \
|
||||
f(client, dsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_dsa, teardown) \
|
||||
f(client, dsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_dsa, teardown) \
|
||||
f(client, ecdsa_256_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_256, teardown) \
|
||||
@@ -236,6 +240,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ecdsa_256_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_384, teardown) \
|
||||
@@ -243,6 +249,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ecdsa_384_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_521, teardown) \
|
||||
@@ -250,6 +258,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ecdsa_521_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_521, teardown)
|
||||
#else
|
||||
@@ -260,6 +270,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, rsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_rsa, teardown) \
|
||||
f(client, rsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_rsa, teardown) \
|
||||
f(client, rsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_rsa, teardown) \
|
||||
f(client, rsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_rsa, teardown) \
|
||||
f(client, rsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_rsa, teardown) \
|
||||
f(client, rsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_rsa, teardown) \
|
||||
f(client, rsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_rsa, teardown) \
|
||||
f(client, ecdsa_256_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_256, teardown) \
|
||||
@@ -267,6 +279,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ecdsa_256_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_256_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_256, teardown) \
|
||||
f(client, ecdsa_384_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_384, teardown) \
|
||||
@@ -274,6 +288,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ecdsa_384_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_384_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_384, teardown) \
|
||||
f(client, ecdsa_521_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_521, teardown) \
|
||||
@@ -281,6 +297,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ecdsa_521_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_521, teardown) \
|
||||
f(client, ecdsa_521_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_521, teardown)
|
||||
#endif
|
||||
@@ -294,6 +312,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ed25519_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ed25519, teardown)
|
||||
#else
|
||||
@@ -304,7 +324,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
f(client, ed25519_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_ed25519, teardown) \
|
||||
f(client, ed25519_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ed25519, teardown)
|
||||
#endif
|
||||
|
||||
|
||||
67
tests/ssh_ping.c
Normal file
67
tests/ssh_ping.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ssh_ping.c */
|
||||
/*
|
||||
Copyright 2018 Red Hat, Inc
|
||||
|
||||
Author: Jakub Jelen <jjelen@redhat.com>
|
||||
|
||||
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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <libssh/libssh.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *banner = NULL;
|
||||
ssh_session session = NULL;
|
||||
int rc = 1;
|
||||
|
||||
if (argc < 1 || argv[1] == NULL) {
|
||||
fprintf(stderr, "Error: Need an argument (hostname)\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
session = ssh_new();
|
||||
if (session == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOST, argv[1]);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The automatic username is not available under uid wrapper */
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_USER, "ping");
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = ssh_connect(session);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
|
||||
goto out;
|
||||
}
|
||||
|
||||
banner = ssh_get_serverbanner(session);
|
||||
if (banner == NULL) {
|
||||
fprintf(stderr, "Did not receive SSH banner\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("OK: %s\n", banner);
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
ssh_free(session);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "torture.h"
|
||||
#include "torture_key.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
/* for pattern matching */
|
||||
#include "match.c"
|
||||
@@ -577,7 +578,6 @@ static void torture_setup_create_sshd_config(void **state)
|
||||
"KbdInteractiveAuthentication yes\n"
|
||||
"PubkeyAuthentication yes\n"
|
||||
"\n"
|
||||
"UsePrivilegeSeparation no\n"
|
||||
"StrictModes no\n"
|
||||
"\n"
|
||||
"UsePAM yes\n"
|
||||
@@ -603,6 +603,8 @@ static void torture_setup_create_sshd_config(void **state)
|
||||
"ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
|
||||
"diffie-hellman-group-exchange-sha256,"
|
||||
"diffie-hellman-group-exchange-sha1,"
|
||||
"diffie-hellman-group16-sha512,"
|
||||
"diffie-hellman-group18-sha512,"
|
||||
"diffie-hellman-group14-sha1,"
|
||||
"diffie-hellman-group1-sha1\n"
|
||||
#endif /* OPENSSH_VERSION >= 6.7 */
|
||||
@@ -630,7 +632,7 @@ static void torture_setup_create_sshd_config(void **state)
|
||||
"%s/sshd/ssh_host_ed25519_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(ed25519_hostkey,
|
||||
torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 0));
|
||||
torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0));
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
snprintf(dsa_hostkey,
|
||||
@@ -653,13 +655,6 @@ static void torture_setup_create_sshd_config(void **state)
|
||||
torture_write_file(ecdsa_hostkey,
|
||||
torture_get_testkey(SSH_KEYTYPE_ECDSA, 521, 0));
|
||||
|
||||
snprintf(ed25519_hostkey,
|
||||
sizeof(ed25519_hostkey),
|
||||
"%s/sshd/ssh_host_ed25519_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(ed25519_hostkey,
|
||||
torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 0));
|
||||
|
||||
snprintf(trusted_ca_pubkey,
|
||||
sizeof(trusted_ca_pubkey),
|
||||
"%s/sshd/user_ca.pub",
|
||||
@@ -704,6 +699,24 @@ static void torture_setup_create_sshd_config(void **state)
|
||||
torture_write_file(s->srv_config, sshd_config);
|
||||
}
|
||||
|
||||
static int torture_wait_for_daemon(unsigned int seconds)
|
||||
{
|
||||
struct ssh_timestamp start;
|
||||
int rc;
|
||||
|
||||
ssh_timestamp_init(&start);
|
||||
|
||||
while (!ssh_timeout_elapsed(&start, seconds * 1000)) {
|
||||
rc = system(SSH_PING_EXECUTABLE " " TORTURE_SSH_SERVER);
|
||||
if (rc == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Wait 200 ms before retrying */
|
||||
usleep(200 * 1000);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void torture_setup_sshd_server(void **state)
|
||||
{
|
||||
struct torture_state *s;
|
||||
@@ -726,11 +739,12 @@ void torture_setup_sshd_server(void **state)
|
||||
rc = system(sshd_start_cmd);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
/* Give the process 500ms time to initialize and start */
|
||||
usleep(500 * 1000);
|
||||
|
||||
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1);
|
||||
unsetenv("PAM_WRAPPER");
|
||||
|
||||
/* Wait until the sshd is ready to accept connections */
|
||||
rc = torture_wait_for_daemon(5);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
void torture_teardown_socket_dir(void **state)
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
void _assert_ssh_return_code(ssh_session session,
|
||||
|
||||
@@ -91,6 +91,70 @@ static const char torture_rsa_private_testkey_passphrase[] =
|
||||
"JSvUyxoaZUjQkT7iF94HsF+FVVJdI55UjgnMiZ0d5vKffWyTHYcYHkFYaSloAMWN\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_rsa_private_openssh_testkey_passphrase[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDX\n"
|
||||
"ClCBeHgYyOEqmWpAanz9AAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAAB\n"
|
||||
"AQDXvXuawzaArEwkLIXTz/EWywLOCtqQL3P9yKkrhz6AplXP2PhOh5pyxa1VfGKe\n"
|
||||
"453jNeYBJ0ROto3BshXgZXbo86oLXTkbe0gO5xi3r5WjXxjOFvRRTLot5fPLNDOv\n"
|
||||
"9+TnsPmkNn0iIeyPnfrcPIyjWt5zSWUfkNC8oNHxsiSshjpbJvTXSDipukpUy41d\n"
|
||||
"7jg4uWGuonMTF7yu7HfuHqq7lhb0WlwSpfbqAbfYARBddcdcARyhix4RMWZZqVY2\n"
|
||||
"0H3Vsjq8bjKC+NJXFce1PRg+qcOWQdlXEei4dkzAvHvfQRx1TjzkrBZ6B6thmZty\n"
|
||||
"eb9IsiB0tg2g0JN2VTAGkxqpAAADwG8gm8jZpx+GIKdhV+igcvYvIhzA+fz6UdXf\n"
|
||||
"d/8wnYzMXtg+Ys7XsKUsxtMD8HGPiuwYsTrd/YGiol7SpkJV0STqtW+UZrcKamJ5\n"
|
||||
"reFaDoIU8hhWTXCe/ogplTxH/zNNK7Xx5OAGnNWE3zsR1vbZaCv+Vwwa27eUCbpv\n"
|
||||
"V1+92nBwkah3FCKCbwYDvTVRn1TZHQwnuNxDCRrlwaMjf8eX2ssqLLX7jqrb3j1u\n"
|
||||
"c28GR3fNJ8ENaWshZ77tqexUQCnCx14/qtT434CMvENXnCP5BP/cRmbOlCFQ6Id7\n"
|
||||
"nLMW0uDIy/q3xBsAcdMyV0LJW7sJNXIjTnS4lyXd0XescXrqTAKxTkqd1E0VIBpc\n"
|
||||
"37+7vqv9A9Xxq74jy//L9L4Yrbijc9Vt+oNWFgOuakZGBLIQvm36Oqb0z0oWJcUt\n"
|
||||
"VdZcvkCNMeixBqCnrQ8egO3x0pnZwo6cwH586Me8FgFacOnzWjzuQT6vYJ4EK5ch\n"
|
||||
"YNRQpjtz5+T3rZK7eIF1ZUobM4S6di7A6lW9tycQVhjo5XlhalMfCfajhazgcIrY\n"
|
||||
"Qdaq8+AguP8H+3bvXPZmitL8/mv5uVjqxy1lYh2xLzViTmFnvfdbZ92BWI9C6JBI\n"
|
||||
"+mRWzXeEY71MjfeEaPStwBm5OYBMFwYrXPL7E3JjAXRxbB+LKUksj/lRk3K7aQp4\n"
|
||||
"IDKCzAACgkOixfP39BgKQkrLjAoi6mEDqu5Ajc3GoljXsJEkcbu0j+0tVth+41nV\n"
|
||||
"8yCkP5SVUQTCSKzoduE+0pk6oYO6vrwKLM62cQRPXLl/XNoUqETIe8dklIKojYo6\n"
|
||||
"3ho1RaHgYr9/NAS0029CFt/rGmONWF9ihKON6wMavJRcofZ25FeylKiP2rrqdDIb\n"
|
||||
"EiWULZi3MUJfKBwSeZMwaYYmSpaOZF1U/MgvEfeRkE1UmDp3FmBLSNHBYhAxNazH\n"
|
||||
"R393BTr1zk7h+8s7QK986ZtcKkyUNXEK1NkLLuKlqMwFnjiOdeAIGwz9NEn+Tj60\n"
|
||||
"jE5IcCE06B6ze/MOZcsPp1SoZv4kKmgWY5Gdqv/9O9SyFQ0Yh4MvBSD8l4x0epId\n"
|
||||
"8Xm54ISVWP1SZ1x3Oe8yvtwOGqDkZeOVjnP7EQ7R0+1PZzW5P/x47skACqadGChN\n"
|
||||
"ahbngIl+EhPOqhx+wIfDbtzTmGABgNhcI/d02b8py5MXFnA+uzeSucDREYRdm2TO\n"
|
||||
"TQQ2CtxB6lcatIYG4AhyouQbujLd/AwpZJ05S1i/Qt6NenTgK3YyTWdXLQnjZSMx\n"
|
||||
"FBRkf+Jj9eVXieT4PJKtWuvxNNrJVA==\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_rsa_private_openssh_testkey[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdz\n"
|
||||
"c2gtcnNhAAAAAwEAAQAAAQEA1717msM2gKxMJCyF08/xFssCzgrakC9z/cipK4c+\n"
|
||||
"gKZVz9j4ToeacsWtVXxinuOd4zXmASdETraNwbIV4GV26POqC105G3tIDucYt6+V\n"
|
||||
"o18Yzhb0UUy6LeXzyzQzr/fk57D5pDZ9IiHsj5363DyMo1rec0llH5DQvKDR8bIk\n"
|
||||
"rIY6Wyb010g4qbpKVMuNXe44OLlhrqJzExe8rux37h6qu5YW9FpcEqX26gG32AEQ\n"
|
||||
"XXXHXAEcoYseETFmWalWNtB91bI6vG4ygvjSVxXHtT0YPqnDlkHZVxHouHZMwLx7\n"
|
||||
"30EcdU485KwWegerYZmbcnm/SLIgdLYNoNCTdlUwBpMaqQAAA7iQHqVWkB6lVgAA\n"
|
||||
"AAdzc2gtcnNhAAABAQDXvXuawzaArEwkLIXTz/EWywLOCtqQL3P9yKkrhz6AplXP\n"
|
||||
"2PhOh5pyxa1VfGKe453jNeYBJ0ROto3BshXgZXbo86oLXTkbe0gO5xi3r5WjXxjO\n"
|
||||
"FvRRTLot5fPLNDOv9+TnsPmkNn0iIeyPnfrcPIyjWt5zSWUfkNC8oNHxsiSshjpb\n"
|
||||
"JvTXSDipukpUy41d7jg4uWGuonMTF7yu7HfuHqq7lhb0WlwSpfbqAbfYARBddcdc\n"
|
||||
"ARyhix4RMWZZqVY20H3Vsjq8bjKC+NJXFce1PRg+qcOWQdlXEei4dkzAvHvfQRx1\n"
|
||||
"TjzkrBZ6B6thmZtyeb9IsiB0tg2g0JN2VTAGkxqpAAAAAwEAAQAAAQAdjR3uQAkq\n"
|
||||
"LO+tENAwCE680YgL0x7HG0jnHWJWzQq5so8UjmLM1vRH/l3U1Nnpa8JHyi08QTWx\n"
|
||||
"Fn5qZstqVluoYyAKuHVHF2bya6NOHeYAX9lU+X3z2O+zs8jmL7tYwjr/pZU8ch5H\n"
|
||||
"25+8uGYRXtXg1mScJBSO81Y0UE8RrVYqr2Os583yB657kYiVYYYSZlRGd9wmfXnJ\n"
|
||||
"w0t8LaYcTn+i/lOvrJGa0Q0iV6+4rYmjwYd/D/vyNzF31hUEFrn3vDSgTnJdShgH\n"
|
||||
"VqW0OwNuEDe/4p8KkKR1EVVj6xv4zicwouY7aQI+zT3MwAzvNdvYwytsIj6bhT9x\n"
|
||||
"oyeAAIW0vaKVAAAAgQD6pPfu6tb7DiTlaH3/IPdGh3PTIf0zXHZ/ygxORXBZdoLY\n"
|
||||
"Fq2h/YnBd2Hs8vARAjGJYs78gTPP0FVXPV8ut38xct4DQ2hbPMrjWv5gdhDazq8Q\n"
|
||||
"qaFEa0+DeYONej8ItKwpsV2Rskkv5Pfm7M6EffVty1uzOpIcT8RYDAYUlc5D/wAA\n"
|
||||
"AIEA+44ykLho3BDWnUzshVEm6iNoqlZqcDVcNSpCuYDnCy5UrTDk0zj+OUG9M0Zx\n"
|
||||
"4c7kAmu/poXSimgAgMh9GNCzy3+a70WvH+fBqvG5tXLaSOQCswSdQjltANAnlt5L\n"
|
||||
"YDHzGGJBsS4pYxoz22MKhFbpYUCQJvotXnZJpTQU6hdFRX8AAACBANuNSlFq/vG8\n"
|
||||
"Vf9c2YsPiITmOrYxpUDMiMLvUGQOdyIIc45EAggOFHNF3AdPZEhinpD92EK+LiJc\n"
|
||||
"WYJ26muVcicZoddgmpcHRt2gByC+ckWOM4sLpih6EyQLFZfqTx2X+KOI0ZTt7zEi\n"
|
||||
"zfm1MJUNDFOr3DM0VBIf34Bn1hU/isPXAAAAAAEC\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
|
||||
static const char torture_rsa_public_testkey[] =
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsA5ERRaUFckApnmEAFjLGdFrIN"
|
||||
"k/Vsl4ts9Ur6enF6auEfJmCN1tjcAOi34lHJaO+WXbDYYj7duW3SP7H9lbCMwq79B"
|
||||
@@ -161,6 +225,55 @@ static const char torture_dsa_private_testkey_passphrase[] =
|
||||
"wHBOL6HrOnD+gGs6DUFwzA==\n"
|
||||
"-----END DSA PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_dsa_private_openssh_testkey_passphrase[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBC\n"
|
||||
"UZK61oXs3uKMs4l7G0cpAAAAEAAAAAEAAAGxAAAAB3NzaC1kc3MAAACBAJTK9U8S\n"
|
||||
"SfdSdkOPMLNLNIelOW3OvQRz7WbP8kAKMcwEn0L9b8/C8ffKOR+gWGFES+hjsg+f\n"
|
||||
"AC7ltzHDxOQhKrthE5DjT0+rDA+/LQ3cZSn/6QpLbrwEgn5Uo3nXddF/t4vV7hod\n"
|
||||
"Qn5qX3HUnFOZzpPQYGrWXK74JNRTKHblo0MXAAAAFQCvOI9tBplPs3sI0MLCF7lW\n"
|
||||
"+gvzxwAAAIBeG4hWwnFRAnmdZBEt/ujdcQZD4RxWYc7MwHXEKweNiekSGFyj6v8c\n"
|
||||
"NlIPfWTMN4BlTJzPfVaoYvzJev45lEuoSwYLt3AQDM+JcO6XTMdyXTKIo+tGsuA0\n"
|
||||
"kd4pxPol+UGeAruNBEhVSDcXfXTh9tVravBqeIuXgZIFk9cylR2eDwAAAIB4roDQ\n"
|
||||
"Bfgf8AoSAJAb7y8OVvxt5cT7iqaRMQX2XgtW09Nu9RbUIVS7n2mw3iqZG0xnG3iv\n"
|
||||
"1oL9gwNXMLlf+gLmsqU3788jaEZ9IhZ8VdgHAoHm6UWM7b2uADmhirI6dRZUVO+/\n"
|
||||
"iMGUvDxa66OI4hDV055pbwQhtxupUatThyDzIgAAAeAtGFEW6JZTeSumizZJI4T2\n"
|
||||
"Kha05Ze3juTeW+BMjqTcf77yAL2jvsljogCtu4+5CWWO4g+cr80vyVytji6IYTNM\n"
|
||||
"MPn1qe6dHXnfmgtiegHXxrjr5v5/i1cvD32Bxffy+yjR9kbV9GJYF+K5pfYVpQBa\n"
|
||||
"XVmq6AJUPd/yxKw6jRGZJi8GTcrKbCZAL+VYSPwc0veCrmGPjeeMCgYcEXPvhSui\n"
|
||||
"P0JnG1Ap12FeK+61rIbZBAr7qbTGJi5Z5HlDlgon2tmMZOkIuL1Oytgut4MpmYjP\n"
|
||||
"ph+qrzgwfSwOsjVIuHlb1L0phWRlgbT8lmysEE7McGKWiCOabxgl3NF9lClhDBb9\n"
|
||||
"nzupkK1cg/4p17USYMOdeNhTmJ0DkQT+8UenfBOmzV7kamLlEYXJdDZBN//dZ8UR\n"
|
||||
"KEzAzpaAVIyJQ+wvCUIh/VO8sJP+3q4XQUkv0QcIRlc0+r9qbW2Tqv3vajFcFtK6\n"
|
||||
"nrTmIJVL0pG+z/93Ncpy5susD+JvhJ4yfl7Jet3jy4fWwm3qkLl0WsobJ7Om+GyH\n"
|
||||
"DzHH9RgDk3XuUHS/fz+kTwmtyIH/Rq1jIt+s+T8iA9CzKSX6sBu2yfMo1w2/LbCx\n"
|
||||
"Xy1rHS42TePw28m1cQuUfjqdOC3IBgQ1m3x2f1on7hk=\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_dsa_private_openssh_testkey[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsQAAAAdz\n"
|
||||
"c2gtZHNzAAAAgQCUyvVPEkn3UnZDjzCzSzSHpTltzr0Ec+1mz/JACjHMBJ9C/W/P\n"
|
||||
"wvH3yjkfoFhhREvoY7IPnwAu5bcxw8TkISq7YROQ409PqwwPvy0N3GUp/+kKS268\n"
|
||||
"BIJ+VKN513XRf7eL1e4aHUJ+al9x1JxTmc6T0GBq1lyu+CTUUyh25aNDFwAAABUA\n"
|
||||
"rziPbQaZT7N7CNDCwhe5VvoL88cAAACAXhuIVsJxUQJ5nWQRLf7o3XEGQ+EcVmHO\n"
|
||||
"zMB1xCsHjYnpEhhco+r/HDZSD31kzDeAZUycz31WqGL8yXr+OZRLqEsGC7dwEAzP\n"
|
||||
"iXDul0zHcl0yiKPrRrLgNJHeKcT6JflBngK7jQRIVUg3F3104fbVa2rwaniLl4GS\n"
|
||||
"BZPXMpUdng8AAACAeK6A0AX4H/AKEgCQG+8vDlb8beXE+4qmkTEF9l4LVtPTbvUW\n"
|
||||
"1CFUu59psN4qmRtMZxt4r9aC/YMDVzC5X/oC5rKlN+/PI2hGfSIWfFXYBwKB5ulF\n"
|
||||
"jO29rgA5oYqyOnUWVFTvv4jBlLw8WuujiOIQ1dOeaW8EIbcbqVGrU4cg8yIAAAHY\n"
|
||||
"tbI937WyPd8AAAAHc3NoLWRzcwAAAIEAlMr1TxJJ91J2Q48ws0s0h6U5bc69BHPt\n"
|
||||
"Zs/yQAoxzASfQv1vz8Lx98o5H6BYYURL6GOyD58ALuW3McPE5CEqu2ETkONPT6sM\n"
|
||||
"D78tDdxlKf/pCktuvASCflSjedd10X+3i9XuGh1CfmpfcdScU5nOk9BgatZcrvgk\n"
|
||||
"1FModuWjQxcAAAAVAK84j20GmU+zewjQwsIXuVb6C/PHAAAAgF4biFbCcVECeZ1k\n"
|
||||
"ES3+6N1xBkPhHFZhzszAdcQrB42J6RIYXKPq/xw2Ug99ZMw3gGVMnM99Vqhi/Ml6\n"
|
||||
"/jmUS6hLBgu3cBAMz4lw7pdMx3JdMoij60ay4DSR3inE+iX5QZ4Cu40ESFVINxd9\n"
|
||||
"dOH21Wtq8Gp4i5eBkgWT1zKVHZ4PAAAAgHiugNAF+B/wChIAkBvvLw5W/G3lxPuK\n"
|
||||
"ppExBfZeC1bT0271FtQhVLufabDeKpkbTGcbeK/Wgv2DA1cwuV/6AuaypTfvzyNo\n"
|
||||
"Rn0iFnxV2AcCgebpRYztva4AOaGKsjp1FlRU77+IwZS8PFrro4jiENXTnmlvBCG3\n"
|
||||
"G6lRq1OHIPMiAAAAFQCNR3fP4j87IO2086Db40C/jaMosgAAAAABAg==\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_dsa_public_testkey[] =
|
||||
"ssh-dss AAAAB3NzaC1kc3MAAACBAJTK9U8SSfdSdkOPMLNLNIelOW3OvQRz7WbP8k"
|
||||
"AKMcwEn0L9b8/C8ffKOR+gWGFES+hjsg+fAC7ltzHDxOQhKrthE5DjT0+rDA+/LQ3c"
|
||||
@@ -222,6 +335,29 @@ static const char torture_ecdsa256_private_testkey_passphrase[] =
|
||||
"8VZn2VJDaitLy8ARqA/lMGQfqHSa3EOqti9FzWG/P6s=\n"
|
||||
"-----END EC PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_ecdsa256_private_openssh_testkey[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNl\n"
|
||||
"Y2RzYS1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTH7253zxDkZa0t37Iy\n"
|
||||
"1hpqkLzmD7ZkuntW0UcDQRs0eoFRDGiH4iTz0yWvsBTFwU936QKj40TrKr+Y1Bwv\n"
|
||||
"sTqJAAAAmOuDchHrg3IRAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAy\n"
|
||||
"NTYAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNBGzR6gVEMaIfiJPPT\n"
|
||||
"Ja+wFMXBT3fpAqPjROsqv5jUHC+xOokAAAAgEIN55hgC1fcSew/Stq3BWk1NoD/g\n"
|
||||
"rU3pW8cyJRmVV2EAAAAA\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_ecdsa256_private_openssh_testkey_pasphrase[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABA+\n"
|
||||
"O0w3yPZF2q0FjVBhQjn2AAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAy\n"
|
||||
"NTYAAAAIbmlzdHAyNTYAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNB\n"
|
||||
"GzR6gVEMaIfiJPPTJa+wFMXBT3fpAqPjROsqv5jUHC+xOokAAACghvb4EX8M06UB\n"
|
||||
"zigxOn9bg5cZkZ2yWY8jzxtOWH4YJXsuhON/jePDJuI2ro5u4iKFD1u2JLfcshdh\n"
|
||||
"vKZyjixU9KdewykQQt/wFkrCfNUyCH8jFiQsAqhBfopRFyDJV9pmcUBL/3fJqwut\n"
|
||||
"ZeBSfA7tXORp3xrwFI1tXiiUCM+/nhxiCsFaCJXeiM3tN+kFtwQ8kamINqwaC8Vj\n"
|
||||
"lFLKHDfwJQ==\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_ecdsa256_public_testkey[] =
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNT"
|
||||
"YAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNBGzR6gVEMaIfiJPPTJa+w"
|
||||
@@ -245,6 +381,31 @@ static const char torture_ecdsa384_private_testkey_passphrase[] =
|
||||
"8VZn2VJDaitLy8ARqA/lMGQfqHSa3EOqti9FzWG/P6s=\n"
|
||||
"-----END EC PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_ecdsa384_private_openssh_testkey[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNl\n"
|
||||
"Y2RzYS1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQRXc4BN6BrVo1QMi3+i\n"
|
||||
"/B85Lu7SMuzBi+1PbJti8xz+Szgq64gaBGOK9o+WOdLAd/w7p7DJLdztJ0bYoyT4\n"
|
||||
"V3B3ZqR9RyGq6mYCjkXlc5YbYHjueBbp0oeNXqsXHNAWQZoAAADIITfDfiE3w34A\n"
|
||||
"AAATZWNkc2Etc2hhMi1uaXN0cDM4NAAAAAhuaXN0cDM4NAAAAGEEV3OATega1aNU\n"
|
||||
"DIt/ovwfOS7u0jLswYvtT2ybYvMc/ks4KuuIGgRjivaPljnSwHf8O6ewyS3c7SdG\n"
|
||||
"2KMk+Fdwd2akfUchqupmAo5F5XOWG2B47ngW6dKHjV6rFxzQFkGaAAAAMFjyMRrk\n"
|
||||
"O1HLgBV5NaE8n9Mrbntt6GILe5p8SLpgDagc5GJupfnkQM3DPb0xPjSZBAAAAAA=\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_ecdsa384_private_openssh_testkey_passphrase[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB4N\n"
|
||||
"dKGEoxFeg6dqiR2vTl6AAAAEAAAAAEAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzOD\n"
|
||||
"QAAAAIbmlzdHAzODQAAABhBFdzgE3oGtWjVAyLf6L8Hzku7tIy7MGL7U9sm2LzHP5\n"
|
||||
"LOCrriBoEY4r2j5Y50sB3/DunsMkt3O0nRtijJPhXcHdmpH1HIarqZgKOReVzlhtg\n"
|
||||
"eO54FunSh41eqxcc0BZBmgAAANDOL7sWcylFf8SsjGVFvr36mpyUBpAJ/e7o4RbQg\n"
|
||||
"H8FDu1IxscOfbLDoB3CV7UEIgG58nVsDamfL6rXV/tzWnPxYxi6jUHcKT1BugO/Jt\n"
|
||||
"/ncelMeoAS6MAZhElaGKzU1cJMlMTV9ofmuKuAwllQULG7L8lwHs9whBK4JmWPaGL\n"
|
||||
"pU3i9ZoT33/g6pcvA83vicCNqj7ggl6Vb9MeO/zGW1+oV2HC3WiLTqBsYxEJu4YCM\n"
|
||||
"ewfx9pWeWaCllNy/F1rCBu3cxqzcge9hqIlNtpT7Dq3k\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_ecdsa384_public_testkey[] =
|
||||
"ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzOD"
|
||||
"QAAABhBFdzgE3oGtWjVAyLf6L8Hzku7tIy7MGL7U9sm2LzHP5LOCrriBoEY4r2j5Y5"
|
||||
@@ -272,6 +433,36 @@ static const char torture_ecdsa521_private_testkey_passphrase[] =
|
||||
"uRzL95L05ctOBGYNYqpPNIX3UdQU07kzwNC+yaHOb2s=\n"
|
||||
"-----END EC PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_ecdsa521_private_openssh_testkey[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNl\n"
|
||||
"Y2RzYS1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBzoPvbx1tpCQedI+3\n"
|
||||
"O1pHAnDrcIGXXlzKQHhJde7BZ0060/MGKNRQsxNO8FdutryAvgBN311Ce7CfwpBS\n"
|
||||
"HZP/P4EBGNY8qFwdwbHntelcISRrDMxhodRSdF14USY1GxtfKmx/SYkoBNTeHyDN\n"
|
||||
"MyRuvHwMlMUcQiNcFKGzjgexJhWXdfIAAAEAt6sYz7erGM8AAAATZWNkc2Etc2hh\n"
|
||||
"Mi1uaXN0cDUyMQAAAAhuaXN0cDUyMQAAAIUEAc6D728dbaQkHnSPtztaRwJw63CB\n"
|
||||
"l15cykB4SXXuwWdNOtPzBijUULMTTvBXbra8gL4ATd9dQnuwn8KQUh2T/z+BARjW\n"
|
||||
"PKhcHcGx57XpXCEkawzMYaHUUnRdeFEmNRsbXypsf0mJKATU3h8gzTMkbrx8DJTF\n"
|
||||
"HEIjXBShs44HsSYVl3XyAAAAQgC83nSJ2SLoiBvEku1JteQKWx/Xt6THksgC7rrI\n"
|
||||
"aTUmNzk+60f0sCCmGll0dgrZLmeIw+TtnG1E20VZflCKq+IdkQAAAAABAg==\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
static const char torture_ecdsa521_private_openssh_testkey_passphrase[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAj\n"
|
||||
"9WBFa/piJcPFEE4CGZTKAAAAEAAAAAEAAACsAAAAE2VjZHNhLXNoYTItbmlzdHA1\n"
|
||||
"MjEAAAAIbmlzdHA1MjEAAACFBAHOg+9vHW2kJB50j7c7WkcCcOtwgZdeXMpAeEl1\n"
|
||||
"7sFnTTrT8wYo1FCzE07wV262vIC+AE3fXUJ7sJ/CkFIdk/8/gQEY1jyoXB3Bsee1\n"
|
||||
"6VwhJGsMzGGh1FJ0XXhRJjUbG18qbH9JiSgE1N4fIM0zJG68fAyUxRxCI1wUobOO\n"
|
||||
"B7EmFZd18gAAAQDLjaKp+DLEHFb98f5WnVFg6LgDN847sfeuPZVfVjeSAiIv016O\n"
|
||||
"ld7DXb137B2xYVsuce6sHbypr10dJOvgMTLdzTl+crYNJL+8UufJP0rOIFaDenzQ\n"
|
||||
"RW8wydwiQxwt1ZqtD8ASqFmadxngufJKZzPLGfjCbCz3uATKa2sXN66nRXRZJbVA\n"
|
||||
"IlNYDY8ivAStNhfItUMqyM6PkYlKJECtJw7w7TYKpvts7t72JmtgqVjS45JI/YZ+\n"
|
||||
"kitIG0YmG8rzL9d1vBB5m+MH/fnFz2uJqbQYCH9Ctc8HZodAVoTNDzXHU2mYF9PE\n"
|
||||
"Z6+gi3jd+kOyUk3NifHcre9K6ie7LL33JayM\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
|
||||
static const char torture_ecdsa521_public_testkey[] =
|
||||
"ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1Mj"
|
||||
"EAAACFBAHOg+9vHW2kJB50j7c7WkcCcOtwgZdeXMpAeEl17sFnTTrT8wYo1FCzE07w"
|
||||
@@ -307,54 +498,93 @@ static const char torture_ed25519_public_testkey[] =
|
||||
|
||||
static const char *torture_get_testkey_internal(enum ssh_keytypes_e type,
|
||||
int bits,
|
||||
int with_passphrase,
|
||||
int pubkey)
|
||||
bool with_passphrase,
|
||||
int pubkey,
|
||||
int format)
|
||||
{
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
if (pubkey) {
|
||||
return torture_dsa_public_testkey;
|
||||
} else if (with_passphrase) {
|
||||
if (format == 1) {
|
||||
return torture_dsa_private_openssh_testkey_passphrase;
|
||||
}
|
||||
return torture_dsa_private_testkey_passphrase;
|
||||
}
|
||||
if (format == 1) {
|
||||
return torture_dsa_private_openssh_testkey;
|
||||
}
|
||||
return torture_dsa_private_testkey;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
if (pubkey) {
|
||||
return torture_rsa_public_testkey;
|
||||
} else if (with_passphrase) {
|
||||
if (format == 1) {
|
||||
return torture_rsa_private_openssh_testkey_passphrase;
|
||||
}
|
||||
return torture_rsa_private_testkey_passphrase;
|
||||
}
|
||||
if (format == 1) {
|
||||
return torture_rsa_private_openssh_testkey;
|
||||
}
|
||||
return torture_rsa_private_testkey;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
if (bits == 521) {
|
||||
if (pubkey) {
|
||||
return torture_ecdsa521_public_testkey;
|
||||
} else if (with_passphrase) {
|
||||
if (format == 1) {
|
||||
return torture_ecdsa521_private_openssh_testkey_passphrase;
|
||||
}
|
||||
return torture_ecdsa521_private_testkey_passphrase;
|
||||
}
|
||||
if (format == 1) {
|
||||
return torture_ecdsa521_private_openssh_testkey;
|
||||
}
|
||||
return torture_ecdsa521_private_testkey;
|
||||
} else if (bits == 384) {
|
||||
if (pubkey) {
|
||||
return torture_ecdsa384_public_testkey;
|
||||
} else if (with_passphrase){
|
||||
if (format == 1) {
|
||||
return torture_ecdsa384_private_openssh_testkey_passphrase;
|
||||
}
|
||||
return torture_ecdsa384_private_testkey_passphrase;
|
||||
}
|
||||
if (format == 1) {
|
||||
return torture_ecdsa384_private_openssh_testkey;
|
||||
}
|
||||
return torture_ecdsa384_private_testkey;
|
||||
}
|
||||
|
||||
if (pubkey) {
|
||||
return torture_ecdsa256_public_testkey;
|
||||
} else if (with_passphrase){
|
||||
if (format == 1) {
|
||||
return torture_ecdsa256_private_openssh_testkey_pasphrase;
|
||||
}
|
||||
return torture_ecdsa256_private_testkey_passphrase;
|
||||
}
|
||||
if (format == 1) {
|
||||
return torture_ecdsa256_private_openssh_testkey;
|
||||
}
|
||||
return torture_ecdsa256_private_testkey;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
if (pubkey) {
|
||||
return torture_ed25519_public_testkey;
|
||||
} else if (with_passphrase) {
|
||||
return torture_ed25519_private_testkey_passphrase;
|
||||
if (format == 1) {
|
||||
return torture_ed25519_private_testkey_passphrase;
|
||||
}
|
||||
/* ed25519 keys are not available in legacy PEM format */
|
||||
return NULL;
|
||||
}
|
||||
return torture_ed25519_private_testkey;
|
||||
if (format == 1) {
|
||||
return torture_ed25519_private_testkey;
|
||||
}
|
||||
/* ed25519 keys are not available in legacy PEM format */
|
||||
return NULL;
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
return torture_dsa_testkey_cert;
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
@@ -367,16 +597,25 @@ static const char *torture_get_testkey_internal(enum ssh_keytypes_e type,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the encrypted private key in a new OpenSSH format */
|
||||
const char *torture_get_openssh_testkey(enum ssh_keytypes_e type,
|
||||
int ecda_bits,
|
||||
bool with_passphrase)
|
||||
{
|
||||
return torture_get_testkey_internal(type, ecda_bits, with_passphrase, 0, 1);
|
||||
}
|
||||
|
||||
/* Return the private key in the legacy PEM format */
|
||||
const char *torture_get_testkey(enum ssh_keytypes_e type,
|
||||
int ecda_bits,
|
||||
int with_passphrase)
|
||||
bool with_passphrase)
|
||||
{
|
||||
return torture_get_testkey_internal(type, ecda_bits, with_passphrase, 0);
|
||||
return torture_get_testkey_internal(type, ecda_bits, with_passphrase, 0, 0);
|
||||
}
|
||||
|
||||
const char *torture_get_testkey_pub(enum ssh_keytypes_e type, int ecda_bits)
|
||||
{
|
||||
return torture_get_testkey_internal(type, ecda_bits, 0, 1);
|
||||
return torture_get_testkey_internal(type, ecda_bits, 0, 1, 0);
|
||||
}
|
||||
|
||||
const char *torture_get_testkey_passphrase(void)
|
||||
|
||||
@@ -24,11 +24,19 @@
|
||||
#ifndef _TORTURE_KEY_H
|
||||
#define _TORTURE_KEY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define TORTURE_TESTKEY_PASSWORD "libssh-rocks"
|
||||
|
||||
/* Return the encrypted private key in a new OpenSSH format */
|
||||
const char *torture_get_openssh_testkey(enum ssh_keytypes_e type,
|
||||
int ecdsa_bits,
|
||||
bool with_passphrase);
|
||||
|
||||
/* Return the private key in the legacy PEM format */
|
||||
const char *torture_get_testkey(enum ssh_keytypes_e type,
|
||||
int ecdsa_bits,
|
||||
int with_passphrase);
|
||||
bool with_passphrase);
|
||||
const char *torture_get_testkey_passphrase(void);
|
||||
|
||||
const char *torture_get_testkey_pub(enum ssh_keytypes_e type, int ecdsa_bits);
|
||||
|
||||
@@ -2,95 +2,95 @@ project(unittests C)
|
||||
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
add_cmocka_test(torture_buffer torture_buffer.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_buffer torture_buffer.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_buffer PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_callbacks torture_callbacks.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_callbacks torture_callbacks.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_callbacks PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_crypto torture_crypto.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_crypto torture_crypto.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_crypto PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_init torture_init.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_init torture_init.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_init PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_list torture_list.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_list torture_list.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_list PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_misc torture_misc.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_misc torture_misc.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_misc PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_config torture_config.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_config torture_config.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_config PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_options torture_options.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_options torture_options.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_options PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_isipaddr PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_knownhosts_parsing torture_knownhosts_parsing.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_knownhosts_parsing torture_knownhosts_parsing.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_knownhosts_parsing PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_hashes torture_hashes.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_hashes torture_hashes.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_hashes PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
add_cmocka_test(torture_rand torture_rand.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_rand torture_rand.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_rand PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_rand Threads::Threads)
|
||||
|
||||
add_cmocka_test(torture_threads_init torture_threads_init.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_threads_init torture_threads_init.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_threads_init PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_threads_init Threads::Threads)
|
||||
|
||||
add_cmocka_test(torture_threads_buffer torture_threads_buffer.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_threads_buffer torture_threads_buffer.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_threads_buffer PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_threads_buffer Threads::Threads)
|
||||
|
||||
add_cmocka_test(torture_threads_crypto torture_threads_crypto.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_threads_crypto torture_threads_crypto.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_threads_crypto PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_threads_crypto Threads::Threads)
|
||||
endif ()
|
||||
|
||||
if (UNIX AND NOT WIN32)
|
||||
# this uses a socketpair
|
||||
add_cmocka_test(torture_packet torture_packet.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_packet torture_packet.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_packet PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
# requires ssh-keygen
|
||||
add_cmocka_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_keyfiles torture_keyfiles.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
add_cmocka_test(torture_pki torture_pki.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_pki torture_pki.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_pki_rsa torture_pki_rsa.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_pki_rsa torture_pki_rsa.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki_rsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
add_cmocka_test(torture_pki_ed25519 torture_pki_ed25519.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_pki_ed25519 torture_pki_ed25519.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki_ed25519 PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
if (HAVE_DSA)
|
||||
add_cmocka_test(torture_pki_dsa torture_pki_dsa.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_pki_dsa torture_pki_dsa.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki_dsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
endif()
|
||||
if (HAVE_ECC)
|
||||
add_cmocka_test(torture_pki_ecdsa torture_pki_ecdsa.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_pki_ecdsa torture_pki_ecdsa.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_pki_ecdsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
endif()
|
||||
|
||||
# requires /dev/null
|
||||
add_cmocka_test(torture_channel torture_channel.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_channel torture_channel.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_channel PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
# requires pthread
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
add_cmocka_test(torture_threads_pki_rsa torture_threads_pki_rsa.c ${TORTURE_LIBRARY})
|
||||
add_cmocka_test(torture_threads_pki_rsa torture_threads_pki_rsa.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_threads_pki_rsa PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(torture_threads_pki_rsa Threads::Threads)
|
||||
|
||||
# Not working correctly
|
||||
#if (WITH_SERVER)
|
||||
# add_cmocka_test(torture_server_x11 torture_server_x11.c ${TORTURE_LIBRARY})
|
||||
# add_cmocka_test(torture_server_x11 torture_server_x11.c ${TEST_TARGET_LIBRARIES})
|
||||
#endif (WITH_SERVER)
|
||||
endif ()
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
@@ -17,13 +17,15 @@ extern LIBSSH_THREAD int ssh_log_level;
|
||||
#define LIBSSH_TESTCONFIG7 "libssh_testconfig7.tmp"
|
||||
#define LIBSSH_TESTCONFIG8 "libssh_testconfig8.tmp"
|
||||
#define LIBSSH_TESTCONFIG9 "libssh_testconfig9.tmp"
|
||||
#define LIBSSH_TESTCONFIG10 "libssh_testconfig10.tmp"
|
||||
#define LIBSSH_TESTCONFIGGLOB "libssh_testc*[36].tmp"
|
||||
|
||||
#define USERNAME "testuser"
|
||||
#define PROXYCMD "ssh -q -W %h:%p gateway.example.com"
|
||||
#define ID_FILE "/etc/xxx"
|
||||
#define KEXALGORITHMS "ecdh-sha2-nistp521,diffie-hellman-group14-sha1"
|
||||
#define KEXALGORITHMS "ecdh-sha2-nistp521,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1"
|
||||
#define HOSTKEYALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp521,ssh-rsa"
|
||||
#define PUBKEYACCEPTEDTYPES "rsa-sha2-512,ssh-rsa,ecdsa-sha2-nistp521"
|
||||
#define MACS "hmac-sha1,hmac-sha2-256"
|
||||
#define USER_KNOWN_HOSTS "%d/my_known_hosts"
|
||||
#define GLOBAL_KNOWN_HOSTS "/etc/ssh/my_ssh_known_hosts"
|
||||
@@ -32,6 +34,7 @@ extern LIBSSH_THREAD int ssh_log_level;
|
||||
static int setup_config_files(void **state)
|
||||
{
|
||||
ssh_session session;
|
||||
int verbosity;
|
||||
|
||||
unlink(LIBSSH_TESTCONFIG1);
|
||||
unlink(LIBSSH_TESTCONFIG2);
|
||||
@@ -41,6 +44,7 @@ static int setup_config_files(void **state)
|
||||
unlink(LIBSSH_TESTCONFIG6);
|
||||
unlink(LIBSSH_TESTCONFIG7);
|
||||
unlink(LIBSSH_TESTCONFIG8);
|
||||
unlink(LIBSSH_TESTCONFIG9);
|
||||
|
||||
torture_write_file(LIBSSH_TESTCONFIG1,
|
||||
"User "USERNAME"\nInclude "LIBSSH_TESTCONFIG2"\n\n");
|
||||
@@ -51,6 +55,7 @@ static int setup_config_files(void **state)
|
||||
"\n\nIdentityFile "ID_FILE"\n"
|
||||
"\n\nKexAlgorithms "KEXALGORITHMS"\n"
|
||||
"\n\nHostKeyAlgorithms "HOSTKEYALGORITHMS"\n"
|
||||
"\n\nPubkeyAcceptedTypes "PUBKEYACCEPTEDTYPES"\n"
|
||||
"\n\nMACs "MACS"\n");
|
||||
|
||||
/* Multiple Port settings -> parsing returns early. */
|
||||
@@ -102,7 +107,27 @@ static int setup_config_files(void **state)
|
||||
"VisualHostkey yes\n" /* SOC_UNSUPPORTED */
|
||||
"");
|
||||
|
||||
/* Match keyword */
|
||||
torture_write_file(LIBSSH_TESTCONFIG10,
|
||||
"Match host example\n"
|
||||
"\tHostName example.com\n"
|
||||
"Match host example1,example2\n"
|
||||
"\tHostName exampleN\n"
|
||||
"Match user guest\n"
|
||||
"\tHostName guest.com\n"
|
||||
"Match user tester host testhost\n"
|
||||
"\tHostName testhost.com\n"
|
||||
"Match !user tester host testhost\n"
|
||||
"\tHostName nonuser-testhost.com\n"
|
||||
"Match all\n"
|
||||
"\tHostName all-matched.com\n"
|
||||
"");
|
||||
|
||||
session = ssh_new();
|
||||
|
||||
verbosity = torture_libssh_verbosity();
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
|
||||
*state = session;
|
||||
|
||||
return 0;
|
||||
@@ -119,6 +144,7 @@ static int teardown(void **state)
|
||||
unlink(LIBSSH_TESTCONFIG7);
|
||||
unlink(LIBSSH_TESTCONFIG8);
|
||||
unlink(LIBSSH_TESTCONFIG9);
|
||||
unlink(LIBSSH_TESTCONFIG10);
|
||||
|
||||
ssh_free(*state);
|
||||
|
||||
@@ -141,18 +167,21 @@ static void torture_config_from_file(void **state) {
|
||||
|
||||
ret = ssh_options_get(session, SSH_OPTIONS_PROXYCOMMAND, &v);
|
||||
assert_true(ret == 0);
|
||||
assert_non_null(v);
|
||||
|
||||
assert_string_equal(v, PROXYCMD);
|
||||
ssh_string_free_char(v);
|
||||
|
||||
ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v);
|
||||
assert_true(ret == 0);
|
||||
assert_non_null(v);
|
||||
|
||||
assert_string_equal(v, ID_FILE);
|
||||
ssh_string_free_char(v);
|
||||
|
||||
ret = ssh_options_get(session, SSH_OPTIONS_USER, &v);
|
||||
assert_true(ret == 0);
|
||||
assert_non_null(v);
|
||||
|
||||
assert_string_equal(v, USERNAME);
|
||||
ssh_string_free_char(v);
|
||||
@@ -161,6 +190,8 @@ static void torture_config_from_file(void **state) {
|
||||
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], HOSTKEYALGORITHMS);
|
||||
|
||||
assert_string_equal(session->opts.pubkey_accepted_types, PUBKEYACCEPTEDTYPES);
|
||||
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], MACS);
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], MACS);
|
||||
}
|
||||
@@ -210,7 +241,6 @@ static void torture_config_new(void **state)
|
||||
{
|
||||
ssh_session session = *state;
|
||||
int ret = 0;
|
||||
int verbosity = SSH_LOG_WARNING;
|
||||
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG7);
|
||||
assert_true(ret == 0);
|
||||
@@ -222,9 +252,6 @@ static void torture_config_new(void **state)
|
||||
|
||||
assert_int_equal(ssh_get_log_level(), SSH_LOG_TRACE);
|
||||
assert_int_equal(session->common.log_verbosity, SSH_LOG_TRACE);
|
||||
|
||||
/* reset to something sane */
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,6 +324,61 @@ static void torture_config_unknown(void **state) {
|
||||
assert_true(ret == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Verify the configuration parser accepts Match keyword with
|
||||
* full OpenSSH syntax.
|
||||
*/
|
||||
static void torture_config_match(void **state)
|
||||
{
|
||||
ssh_session session = *state;
|
||||
int ret = 0;
|
||||
|
||||
/* Without any settings we should get all-matched.com hostname */
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "unmatched");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "all-matched.com");
|
||||
|
||||
/* Hostname example does simple hostname matching */
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "example");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "example.com");
|
||||
|
||||
/* We can match also both hosts from a comma separated list */
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "example1");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "exampleN");
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "example2");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "exampleN");
|
||||
|
||||
/* We can match by user */
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, "guest");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "guest.com");
|
||||
|
||||
/* We can combine two options on a single line to match both of them */
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, "tester");
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "testhost.com");
|
||||
|
||||
/* We can also negate conditions */
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, "not-tester");
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost");
|
||||
ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10);
|
||||
assert_true(ret == 0);
|
||||
assert_string_equal(session->opts.host, "nonuser-testhost.com");
|
||||
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
@@ -318,6 +400,9 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_config_unknown,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_config_match,
|
||||
setup_config_files,
|
||||
teardown),
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ static void torture_md5_hash(void **state)
|
||||
assert_true(rc == 0);
|
||||
|
||||
hexa = ssh_get_hexa(hash, hlen);
|
||||
ssh_string_free_char((char *)hash);
|
||||
assert_string_equal(hexa,
|
||||
"50:15:a0:9b:92:bf:33:1c:01:c5:8c:fe:18:fa:ce:78");
|
||||
|
||||
@@ -75,6 +76,7 @@ static void torture_sha1_hash(void **state)
|
||||
assert_true(rc == 0);
|
||||
|
||||
sha1 = ssh_get_b64_unpadded(hash, hlen);
|
||||
ssh_string_free_char((char *)hash);
|
||||
assert_string_equal(sha1, "6wP+houujQmxLBiFugTcoeoODCM");
|
||||
|
||||
ssh_string_free_char(sha1);
|
||||
@@ -92,12 +94,37 @@ static void torture_sha256_hash(void **state)
|
||||
assert_true(rc == 0);
|
||||
|
||||
sha256 = ssh_get_b64_unpadded(hash, hlen);
|
||||
ssh_string_free_char((char *)hash);
|
||||
assert_string_equal(sha256, "jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII");
|
||||
|
||||
ssh_string_free_char(sha256);
|
||||
|
||||
}
|
||||
|
||||
static void torture_sha256_fingerprint(void **state)
|
||||
{
|
||||
ssh_key pubkey = *state;
|
||||
unsigned char *hash = NULL;
|
||||
char *sha256 = NULL;
|
||||
int rc = 0;
|
||||
size_t hlen;
|
||||
|
||||
rc = ssh_get_publickey_hash(pubkey,
|
||||
SSH_PUBLICKEY_HASH_SHA256,
|
||||
&hash,
|
||||
&hlen);
|
||||
assert_true(rc == 0);
|
||||
|
||||
sha256 = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256,
|
||||
hash,
|
||||
hlen);
|
||||
ssh_string_free_char(discard_const(hash));
|
||||
assert_string_equal(sha256,
|
||||
"SHA256:jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII");
|
||||
|
||||
ssh_string_free_char(sha256);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
@@ -110,6 +137,9 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_sha256_hash,
|
||||
setup_rsa_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_sha256_fingerprint,
|
||||
setup_rsa_key,
|
||||
teardown),
|
||||
};
|
||||
|
||||
torture_filter_tests(tests);
|
||||
|
||||
@@ -11,10 +11,18 @@
|
||||
#include "torture_key.h"
|
||||
#include <libssh/session.h>
|
||||
#include <libssh/misc.h>
|
||||
#include <libssh/pki_priv.h>
|
||||
|
||||
static int setup(void **state)
|
||||
{
|
||||
ssh_session session = ssh_new();
|
||||
ssh_session session;
|
||||
int verbosity;
|
||||
|
||||
session = ssh_new();
|
||||
|
||||
verbosity = torture_libssh_verbosity();
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
|
||||
*state = session;
|
||||
|
||||
return 0;
|
||||
@@ -68,18 +76,18 @@ static void torture_options_set_key_exchange(void **state)
|
||||
/* Test known kexes */
|
||||
rc = ssh_options_set(session,
|
||||
SSH_OPTIONS_KEY_EXCHANGE,
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group14-sha1");
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1");
|
||||
assert_true(rc == 0);
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_KEX],
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group14-sha1");
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1");
|
||||
|
||||
/* Test one unknown kex */
|
||||
rc = ssh_options_set(session,
|
||||
SSH_OPTIONS_KEY_EXCHANGE,
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,unknown-crap@example.com,diffie-hellman-group14-sha1");
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,unknown-crap@example.com,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1");
|
||||
assert_true(rc == 0);
|
||||
assert_string_equal(session->opts.wanted_methods[SSH_KEX],
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group14-sha1");
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1");
|
||||
|
||||
/* Test all unknown kexes */
|
||||
rc = ssh_options_set(session,
|
||||
@@ -115,6 +123,54 @@ static void torture_options_set_hostkey(void **state) {
|
||||
assert_false(rc == 0);
|
||||
}
|
||||
|
||||
static void torture_options_set_pubkey_accepted_types(void **state) {
|
||||
ssh_session session = *state;
|
||||
int rc;
|
||||
enum ssh_digest_e type;
|
||||
|
||||
/* Test known public key algorithms */
|
||||
rc = ssh_options_set(session,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
|
||||
assert_true(rc == 0);
|
||||
assert_string_equal(session->opts.pubkey_accepted_types,
|
||||
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
|
||||
|
||||
/* Test one unknown public key algorithms */
|
||||
rc = ssh_options_set(session,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"ssh-ed25519,unknown-crap@example.com,ssh-rsa");
|
||||
assert_true(rc == 0);
|
||||
assert_string_equal(session->opts.pubkey_accepted_types,
|
||||
"ssh-ed25519,ssh-rsa");
|
||||
|
||||
/* Test all unknown public key algorithms */
|
||||
rc = ssh_options_set(session,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"unknown-crap@example.com,more-crap@example.com");
|
||||
assert_false(rc == 0);
|
||||
|
||||
/* Test that the option affects the algorithm selection for RSA keys */
|
||||
/* simulate the SHA2 extension was negotiated */
|
||||
session->extensions = SSH_EXT_SIG_RSA_SHA256;
|
||||
|
||||
/* previous configuration did not list the SHA2 extension algoritms, so
|
||||
* it should not be used */
|
||||
type = ssh_key_type_to_hash(session, SSH_KEYTYPE_RSA);
|
||||
assert_int_equal(type, SSH_DIGEST_SHA1);
|
||||
|
||||
/* now, lets allow the signature from SHA2 extension and expect
|
||||
* it to be used */
|
||||
rc = ssh_options_set(session,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
"rsa-sha2-256,ssh-rsa");
|
||||
assert_true(rc == 0);
|
||||
assert_string_equal(session->opts.pubkey_accepted_types,
|
||||
"rsa-sha2-256,ssh-rsa");
|
||||
type = ssh_key_type_to_hash(session, SSH_KEYTYPE_RSA);
|
||||
assert_int_equal(type, SSH_DIGEST_SHA256);
|
||||
}
|
||||
|
||||
static void torture_options_set_macs(void **state) {
|
||||
ssh_session session = *state;
|
||||
int rc;
|
||||
@@ -194,8 +250,10 @@ static void torture_options_get_user(void **state) {
|
||||
char* user = NULL;
|
||||
int rc;
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_USER, "magicaltrevor");
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
rc = ssh_options_get(session, SSH_OPTIONS_USER, &user);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
assert_non_null(user);
|
||||
assert_string_equal(user, "magicaltrevor");
|
||||
free(user);
|
||||
}
|
||||
@@ -273,15 +331,17 @@ static void torture_options_get_identity(void **state) {
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, "identity1");
|
||||
assert_true(rc == 0);
|
||||
rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
assert_non_null(identity);
|
||||
assert_string_equal(identity, "identity1");
|
||||
SAFE_FREE(identity);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "identity2");
|
||||
assert_true(rc == 0);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
assert_string_equal(session->opts.identity->root->data, "identity2");
|
||||
rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
assert_non_null(identity);
|
||||
assert_string_equal(identity, "identity2");
|
||||
free(identity);
|
||||
}
|
||||
@@ -310,7 +370,10 @@ static void torture_options_config_host(void **state) {
|
||||
/* create a new config file */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Host testhost1\nPort 42\nHost testhost2,testhost3\nPort 43\n", config);
|
||||
fputs("Host testhost1\nPort 42\n"
|
||||
"Host testhost2,testhost3\nPort 43\n"
|
||||
"Host testhost4 testhost5\nPort 44\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost1");
|
||||
@@ -328,9 +391,146 @@ static void torture_options_config_host(void **state) {
|
||||
ssh_options_parse_config(session, "test_config");
|
||||
assert_int_equal(session->opts.port, 43);
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost4");
|
||||
ssh_options_parse_config(session, "test_config");
|
||||
assert_int_equal(session->opts.port, 44);
|
||||
|
||||
session->opts.port = 0;
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost5");
|
||||
ssh_options_parse_config(session, "test_config");
|
||||
assert_int_equal(session->opts.port, 44);
|
||||
|
||||
unlink("test_config");
|
||||
}
|
||||
|
||||
static void torture_options_config_match(void **state)
|
||||
{
|
||||
ssh_session session = *state;
|
||||
FILE *config = NULL;
|
||||
int rv;
|
||||
|
||||
/* Required for options_parse_config() */
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "testhost1");
|
||||
|
||||
/* The Match keyword requires argument */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match all keyword needs to be the only one (start) */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match all host local\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match all keyword needs to be the only one (end) */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match host local all\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match host keyword requires an argument */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match host\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match user keyword requires an argument */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match user\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code_equal(session, rv, SSH_ERROR);
|
||||
|
||||
/* The Match canonical keyword is ignored */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match canonical\n"
|
||||
"\tPort 33\n"
|
||||
"Match all\n"
|
||||
"\tPort 34\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code_equal(session, rv, SSH_OK);
|
||||
assert_int_equal(session->opts.port, 34);
|
||||
|
||||
session->opts.port = 0;
|
||||
|
||||
/* The Match originalhost keyword is ignored */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match originalhost origin\n"
|
||||
"\tPort 33\n"
|
||||
"Match all\n"
|
||||
"\tPort 34\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code(session, rv);
|
||||
assert_int_equal(session->opts.port, 34);
|
||||
|
||||
session->opts.port = 0;
|
||||
|
||||
/* The Match localuser keyword is ignored */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match originalhost origin\n"
|
||||
"\tPort 33\n"
|
||||
"Match all\n"
|
||||
"\tPort 34\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code(session, rv);
|
||||
assert_int_equal(session->opts.port, 34);
|
||||
|
||||
session->opts.port = 0;
|
||||
|
||||
/* The Match exec keyword is ignored */
|
||||
config = fopen("test_config", "w");
|
||||
assert_non_null(config);
|
||||
fputs("Match exec /bin/true\n"
|
||||
"\tPort 33\n"
|
||||
"Match all\n"
|
||||
"\tPort 34\n",
|
||||
config);
|
||||
fclose(config);
|
||||
|
||||
rv = ssh_options_parse_config(session, "test_config");
|
||||
assert_ssh_return_code(session, rv);
|
||||
assert_int_equal(session->opts.port, 34);
|
||||
|
||||
session->opts.port = 0;
|
||||
|
||||
unlink("test_config");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
/* sshbind options */
|
||||
@@ -366,19 +566,26 @@ static void torture_bind_options_import_key(void **state)
|
||||
base64_key = torture_get_testkey(SSH_KEYTYPE_RSA, 0, 0);
|
||||
rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
assert_non_null(key);
|
||||
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
|
||||
assert_int_equal(rc, 0);
|
||||
#ifdef HAVE_DSA
|
||||
/* set dsa key */
|
||||
base64_key = torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0);
|
||||
ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
|
||||
rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
assert_non_null(key);
|
||||
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
|
||||
assert_int_equal(rc, 0);
|
||||
#endif
|
||||
/* set ecdsa key */
|
||||
base64_key = torture_get_testkey(SSH_KEYTYPE_ECDSA, 512, 0);
|
||||
ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
|
||||
rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
assert_non_null(key);
|
||||
|
||||
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
@@ -401,8 +608,11 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_options_set_ciphers, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_options_set_key_exchange, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_options_set_hostkey, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_options_set_pubkey_accepted_types, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_options_set_macs, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown)
|
||||
cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_options_config_match,
|
||||
setup, teardown)
|
||||
};
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
|
||||
@@ -28,7 +28,28 @@ static int setup_dsa_key(void **state)
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY,
|
||||
torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0));
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY_PASSPHRASE,
|
||||
torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0));
|
||||
torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1));
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY ".pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_DSS, 0));
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY "-cert.pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_DSS_CERT01, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_openssh_dsa_key(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
|
||||
unlink(LIBSSH_DSA_TESTKEY);
|
||||
unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_DSA_TESTKEY ".pub");
|
||||
unlink(LIBSSH_DSA_TESTKEY "-cert.pub");
|
||||
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY,
|
||||
torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0, 0));
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY_PASSPHRASE,
|
||||
torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0, 1));
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY ".pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_DSS, 0));
|
||||
torture_write_file(LIBSSH_DSA_TESTKEY "-cert.pub",
|
||||
@@ -49,6 +70,36 @@ static int teardown_dsa_key(void **state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_pki_dsa_import_pubkey_file(void **state)
|
||||
{
|
||||
ssh_key pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
|
||||
/* The key doesn't have the hostname as comment after the key */
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY ".pub", &pubkey);
|
||||
assert_return_code(rc, errno);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_key_free(pubkey);
|
||||
}
|
||||
|
||||
static void torture_pki_dsa_import_pubkey_from_openssh_privkey(void **state)
|
||||
{
|
||||
ssh_key pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
|
||||
/* The key doesn't have the hostname as comment after the key */
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, &pubkey);
|
||||
assert_return_code(rc, errno);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_key_free(pubkey);
|
||||
}
|
||||
|
||||
static void torture_pki_dsa_import_privkey_base64(void **state)
|
||||
{
|
||||
int rc;
|
||||
@@ -98,6 +149,7 @@ static void torture_pki_dsa_write_privkey(void **state)
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(privkey);
|
||||
|
||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||
assert_true(rc == 0);
|
||||
@@ -112,6 +164,7 @@ static void torture_pki_dsa_write_privkey(void **state)
|
||||
NULL,
|
||||
&origkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(origkey);
|
||||
|
||||
unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE);
|
||||
rc = ssh_pki_export_privkey_file(origkey,
|
||||
@@ -205,6 +258,9 @@ static void torture_pki_dsa_import_privkey_base64_passphrase(void **state)
|
||||
&key);
|
||||
assert_true(rc == -1);
|
||||
|
||||
/* This free in unnecessary, but the static analyser does not know */
|
||||
ssh_key_free(key);
|
||||
|
||||
#ifndef HAVE_LIBCRYPTO
|
||||
/* test if it returns -1 if passphrase is NULL */
|
||||
/* libcrypto asks for a passphrase, so skip this test */
|
||||
@@ -214,9 +270,85 @@ static void torture_pki_dsa_import_privkey_base64_passphrase(void **state)
|
||||
NULL,
|
||||
&key);
|
||||
assert_true(rc == -1);
|
||||
|
||||
/* This free in unnecessary, but the static analyser does not know */
|
||||
ssh_key_free(key);
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
}
|
||||
|
||||
static void
|
||||
torture_pki_dsa_import_openssh_privkey_base64_passphrase(void **state)
|
||||
{
|
||||
int rc;
|
||||
ssh_key key = NULL;
|
||||
const char *passphrase = torture_get_testkey_passphrase();
|
||||
const char *keystring = NULL;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0, 1);
|
||||
assert_true(keystring != NULL);
|
||||
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
rc = ssh_key_is_private(key);
|
||||
assert_true(rc == 1);
|
||||
|
||||
ssh_key_free(key);
|
||||
key = NULL;
|
||||
|
||||
/* test if it returns -1 if passphrase is wrong */
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
"wrong passphrase !!",
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_true(rc == -1);
|
||||
|
||||
/* test if it returns -1 if passphrase is NULL */
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_true(rc == -1);
|
||||
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
rc = ssh_key_is_private(key);
|
||||
assert_true(rc == 1);
|
||||
|
||||
ssh_key_free(key);
|
||||
key = NULL;
|
||||
|
||||
/* test if it returns -1 if passphrase is wrong */
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
"wrong passphrase !!",
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_true(rc == -1);
|
||||
|
||||
/* test if it returns -1 if passphrase is NULL */
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_true(rc == -1);
|
||||
}
|
||||
|
||||
|
||||
static void torture_pki_dsa_publickey_from_privatekey(void **state)
|
||||
{
|
||||
int rc;
|
||||
@@ -367,6 +499,7 @@ static void torture_pki_dsa_duplicate_key(void **state)
|
||||
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY ".pub", &pubkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
||||
assert_true(rc == 0);
|
||||
@@ -378,15 +511,19 @@ static void torture_pki_dsa_duplicate_key(void **state)
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(privkey);
|
||||
|
||||
privkey_dup = ssh_key_dup(privkey);
|
||||
assert_true(privkey_dup != NULL);
|
||||
assert_non_null(privkey_dup);
|
||||
|
||||
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key_gen);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(b64_key_gen);
|
||||
|
||||
assert_string_equal(b64_key, b64_key_gen);
|
||||
|
||||
@@ -448,9 +585,18 @@ int torture_run_tests(void)
|
||||
{
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_pubkey_file,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_pubkey_from_openssh_privkey,
|
||||
setup_openssh_dsa_key,
|
||||
teardown_dsa_key),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64,
|
||||
setup_openssh_dsa_key,
|
||||
teardown_dsa_key),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_publickey_from_privatekey,
|
||||
setup_dsa_key,
|
||||
teardown_dsa_key),
|
||||
@@ -463,6 +609,7 @@ int torture_run_tests(void)
|
||||
teardown_dsa_key),
|
||||
#endif
|
||||
cmocka_unit_test(torture_pki_dsa_import_privkey_base64_passphrase),
|
||||
cmocka_unit_test(torture_pki_dsa_import_openssh_privkey_base64_passphrase),
|
||||
|
||||
/* public key */
|
||||
cmocka_unit_test_setup_teardown(torture_pki_dsa_publickey_base64,
|
||||
|
||||
@@ -26,7 +26,30 @@ static int setup_ecdsa_key(void **state, int ecdsa_bits)
|
||||
torture_write_file(LIBSSH_ECDSA_TESTKEY,
|
||||
torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0));
|
||||
torture_write_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE,
|
||||
torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0));
|
||||
torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 1));
|
||||
torture_write_file(LIBSSH_ECDSA_TESTKEY ".pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_ECDSA, ecdsa_bits));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_openssh_ecdsa_key(void **state, int ecdsa_bits)
|
||||
{
|
||||
const char *keystring = NULL;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
unlink(LIBSSH_ECDSA_TESTKEY);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY ".pub");
|
||||
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0);
|
||||
torture_write_file(LIBSSH_ECDSA_TESTKEY,
|
||||
keystring);
|
||||
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 1);
|
||||
torture_write_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE,
|
||||
keystring);
|
||||
torture_write_file(LIBSSH_ECDSA_TESTKEY ".pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_ECDSA, ecdsa_bits));
|
||||
|
||||
@@ -54,6 +77,27 @@ static int setup_ecdsa_key_256(void **state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_openssh_ecdsa_key_521(void **state)
|
||||
{
|
||||
setup_openssh_ecdsa_key(state, 521);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_openssh_ecdsa_key_384(void **state)
|
||||
{
|
||||
setup_openssh_ecdsa_key(state, 384);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_openssh_ecdsa_key_256(void **state)
|
||||
{
|
||||
setup_openssh_ecdsa_key(state, 256);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
@@ -65,6 +109,36 @@ static int teardown(void **state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_pki_ecdsa_import_pubkey_file(void **state)
|
||||
{
|
||||
ssh_key pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
|
||||
/* The key doesn't have the hostname as comment after the key */
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY ".pub", &pubkey);
|
||||
assert_return_code(rc, errno);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_key_free(pubkey);
|
||||
}
|
||||
|
||||
static void torture_pki_ecdsa_import_pubkey_from_openssh_privkey(void **state)
|
||||
{
|
||||
ssh_key pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
|
||||
/* The key doesn't have the hostname as comment after the key */
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, &pubkey);
|
||||
assert_return_code(rc, errno);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_key_free(pubkey);
|
||||
}
|
||||
|
||||
static void torture_pki_ecdsa_import_privkey_base64(void **state)
|
||||
{
|
||||
int rc;
|
||||
@@ -215,6 +289,7 @@ static void torture_pki_ecdsa_duplicate_key(void **state)
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(privkey);
|
||||
|
||||
privkey_dup = ssh_key_dup(privkey);
|
||||
assert_non_null(privkey_dup);
|
||||
@@ -371,6 +446,7 @@ static void torture_pki_ecdsa_write_privkey(void **state)
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(privkey);
|
||||
|
||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||
assert_true(rc == 0);
|
||||
@@ -385,6 +461,7 @@ static void torture_pki_ecdsa_write_privkey(void **state)
|
||||
NULL,
|
||||
&origkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(origkey);
|
||||
|
||||
unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE);
|
||||
rc = ssh_pki_export_privkey_file(origkey,
|
||||
@@ -452,6 +529,24 @@ static void torture_pki_ecdsa_name521(void **state)
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_from_openssh_privkey,
|
||||
setup_openssh_ecdsa_key_256,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_from_openssh_privkey,
|
||||
setup_openssh_ecdsa_key_384,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file,
|
||||
setup_openssh_ecdsa_key_521,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
@@ -461,6 +556,15 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
|
||||
setup_openssh_ecdsa_key_256,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
|
||||
setup_openssh_ecdsa_key_384,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64,
|
||||
setup_openssh_ecdsa_key_521,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_from_privatekey,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
|
||||
@@ -21,16 +21,18 @@ const uint8_t ref_signature[ED25519_SIG_LEN]=
|
||||
|
||||
static int setup_ed25519_key(void **state)
|
||||
{
|
||||
const char *keystring = NULL;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
unlink(LIBSSH_ED25519_TESTKEY);
|
||||
unlink(LIBSSH_ED25519_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_ED25519_TESTKEY ".pub");
|
||||
|
||||
torture_write_file(LIBSSH_ED25519_TESTKEY,
|
||||
torture_get_testkey(SSH_KEYTYPE_ED25519, 0,0));
|
||||
torture_write_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE,
|
||||
torture_get_testkey(SSH_KEYTYPE_ED25519, 0,0));
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0);
|
||||
torture_write_file(LIBSSH_ED25519_TESTKEY, keystring);
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 1);
|
||||
torture_write_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, keystring);
|
||||
|
||||
torture_write_file(LIBSSH_ED25519_TESTKEY ".pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_ED25519,0));
|
||||
@@ -48,6 +50,36 @@ static int teardown(void **state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_pki_ed25519_import_pubkey_file(void **state)
|
||||
{
|
||||
ssh_key pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
|
||||
/* The key doesn't have the hostname as comment after the key */
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_ED25519_TESTKEY ".pub", &pubkey);
|
||||
assert_return_code(rc, errno);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_key_free(pubkey);
|
||||
}
|
||||
|
||||
static void torture_pki_ed25519_import_pubkey_from_openssh_privkey(void **state)
|
||||
{
|
||||
ssh_key pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
|
||||
/* The key doesn't have the hostname as comment after the key */
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, &pubkey);
|
||||
assert_return_code(rc, errno);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_key_free(pubkey);
|
||||
}
|
||||
|
||||
static void torture_pki_ed25519_import_privkey_base64(void **state)
|
||||
{
|
||||
int rc;
|
||||
@@ -78,16 +110,68 @@ static void torture_pki_ed25519_import_privkey_base64(void **state)
|
||||
|
||||
}
|
||||
|
||||
static void torture_pki_ed25519_import_export_privkey_base64(void **state)
|
||||
{
|
||||
char *b64_key = NULL;
|
||||
ssh_key key = NULL;
|
||||
const char *passphrase = torture_get_testkey_passphrase();
|
||||
enum ssh_keytypes_e type;
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = ssh_pki_import_privkey_base64(torture_get_openssh_testkey(SSH_KEYTYPE_ED25519,
|
||||
0,
|
||||
false),
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
type = ssh_key_type(key);
|
||||
assert_true(type == SSH_KEYTYPE_ED25519);
|
||||
|
||||
rc = ssh_key_is_private(key);
|
||||
assert_true(rc == 1);
|
||||
|
||||
rc = ssh_pki_export_privkey_base64(key,
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
&b64_key);
|
||||
assert_return_code(rc, errno);
|
||||
ssh_key_free(key);
|
||||
|
||||
rc = ssh_pki_import_privkey_base64(b64_key,
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
type = ssh_key_type(key);
|
||||
assert_true(type == SSH_KEYTYPE_ED25519);
|
||||
|
||||
rc = ssh_key_is_private(key);
|
||||
assert_true(rc == 1);
|
||||
|
||||
SSH_STRING_FREE_CHAR(b64_key);
|
||||
ssh_key_free(key);
|
||||
}
|
||||
|
||||
static void torture_pki_ed25519_publickey_from_privatekey(void **state)
|
||||
{
|
||||
int rc;
|
||||
ssh_key key = NULL;
|
||||
ssh_key pubkey = NULL;
|
||||
const char *passphrase = NULL;
|
||||
const char *keystring = NULL;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 0),
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0);
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -229,6 +313,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
||||
NULL,
|
||||
&origkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(origkey);
|
||||
|
||||
unlink(LIBSSH_ED25519_TESTKEY);
|
||||
|
||||
@@ -245,6 +330,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(privkey);
|
||||
|
||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||
assert_true(rc == 0);
|
||||
@@ -273,6 +359,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(privkey);
|
||||
|
||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||
assert_true(rc == 0);
|
||||
@@ -288,6 +375,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
||||
NULL,
|
||||
&origkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(origkey);
|
||||
|
||||
unlink(LIBSSH_ED25519_TESTKEY_PASSPHRASE);
|
||||
rc = ssh_pki_export_privkey_file(origkey,
|
||||
@@ -311,6 +399,7 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(privkey);
|
||||
|
||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||
assert_true(rc == 0);
|
||||
@@ -319,10 +408,12 @@ static void torture_pki_ed25519_write_privkey(void **state)
|
||||
ssh_key_free(privkey);
|
||||
}
|
||||
|
||||
static void torture_pki_ed25519_sign(void **state){
|
||||
static void torture_pki_ed25519_sign(void **state)
|
||||
{
|
||||
ssh_key privkey = NULL;
|
||||
ssh_signature sig = NULL;
|
||||
ssh_string blob = NULL;
|
||||
const char *keystring = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
@@ -330,9 +421,8 @@ static void torture_pki_ed25519_sign(void **state){
|
||||
sig = ssh_signature_new();
|
||||
assert_non_null(sig);
|
||||
|
||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519,
|
||||
0,
|
||||
0),
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 0);
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -374,7 +464,7 @@ static void torture_pki_ed25519_verify(void **state){
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN);
|
||||
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519);
|
||||
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO);
|
||||
assert_true(sig != NULL);
|
||||
|
||||
rc = pki_ed25519_verify(pubkey, sig, HASH, sizeof(HASH));
|
||||
@@ -411,7 +501,7 @@ static void torture_pki_ed25519_verify_bad(void **state){
|
||||
for (i=0; i < ED25519_SIG_LEN; ++i){
|
||||
ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN);
|
||||
((uint8_t *)ssh_string_data(blob))[i] ^= 0xff;
|
||||
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519);
|
||||
sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO);
|
||||
assert_true(sig != NULL);
|
||||
|
||||
rc = pki_ed25519_verify(pubkey, sig, HASH, sizeof(HASH));
|
||||
@@ -429,11 +519,13 @@ static void torture_pki_ed25519_import_privkey_base64_passphrase(void **state)
|
||||
int rc;
|
||||
ssh_key key = NULL;
|
||||
const char *passphrase = torture_get_testkey_passphrase();
|
||||
const char *testkey = NULL;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
/* same for ED25519 */
|
||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 1),
|
||||
testkey = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 1);
|
||||
rc = ssh_pki_import_privkey_base64(testkey,
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -447,7 +539,7 @@ static void torture_pki_ed25519_import_privkey_base64_passphrase(void **state)
|
||||
key = NULL;
|
||||
|
||||
/* test if it returns -1 if passphrase is wrong */
|
||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 1),
|
||||
rc = ssh_pki_import_privkey_base64(testkey,
|
||||
"wrong passphrase !!",
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -461,11 +553,13 @@ static void torture_pki_ed25519_privkey_dup(void **state)
|
||||
const char *passphrase = torture_get_testkey_passphrase();
|
||||
ssh_key key = NULL;
|
||||
ssh_key dup = NULL;
|
||||
const char *testkey = NULL;
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_ED25519, 0, 1),
|
||||
testkey = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0, 1);
|
||||
rc = ssh_pki_import_privkey_base64(testkey,
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -521,10 +615,19 @@ static void torture_pki_ed25519_pubkey_dup(void **state)
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
const struct CMUnitTest tests[] = {
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_pubkey_file,
|
||||
setup_ed25519_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_pubkey_from_openssh_privkey,
|
||||
setup_ed25519_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_privkey_base64,
|
||||
setup_ed25519_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_export_privkey_base64,
|
||||
setup_ed25519_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_ed25519_publickey_from_privatekey,
|
||||
setup_ed25519_key,
|
||||
teardown),
|
||||
@@ -547,6 +650,7 @@ int torture_run_tests(void) {
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||
ssh_finalize();
|
||||
return rc;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#define LIBSSH_RSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_rsa"
|
||||
|
||||
const unsigned char RSA_HASH[] = "12345678901234567890";
|
||||
const unsigned char SHA256_HASH[] = "12345678901234567890123456789012";
|
||||
const unsigned char SHA512_HASH[] = "1234567890123456789012345678901234567890"
|
||||
"123456789012345678901234";
|
||||
|
||||
static int setup_rsa_key(void **state)
|
||||
{
|
||||
@@ -31,6 +34,25 @@ static int setup_rsa_key(void **state)
|
||||
torture_get_testkey(SSH_KEYTYPE_RSA, 0, 1));
|
||||
torture_write_file(LIBSSH_RSA_TESTKEY ".pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_RSA, 0));
|
||||
torture_write_file(LIBSSH_RSA_TESTKEY "-cert.pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_RSA_CERT01, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_rsa_openssh_key(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
|
||||
unlink(LIBSSH_RSA_TESTKEY);
|
||||
unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE);
|
||||
unlink(LIBSSH_RSA_TESTKEY ".pub");
|
||||
unlink(LIBSSH_RSA_TESTKEY "-cert.pub");
|
||||
|
||||
torture_write_file(LIBSSH_RSA_TESTKEY,
|
||||
torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0, 0));
|
||||
torture_write_file(LIBSSH_RSA_TESTKEY_PASSPHRASE,
|
||||
torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0, 1));
|
||||
torture_write_file(LIBSSH_RSA_TESTKEY ".pub",
|
||||
torture_get_testkey_pub(SSH_KEYTYPE_RSA, 0));
|
||||
torture_write_file(LIBSSH_RSA_TESTKEY "-cert.pub",
|
||||
@@ -65,6 +87,21 @@ static void torture_pki_rsa_import_pubkey_file(void **state)
|
||||
ssh_key_free(pubkey);
|
||||
}
|
||||
|
||||
static void torture_pki_rsa_import_pubkey_from_openssh_privkey(void **state)
|
||||
{
|
||||
ssh_key pubkey = NULL;
|
||||
int rc;
|
||||
|
||||
(void)state;
|
||||
|
||||
/* The key doesn't have the hostname as comment after the key */
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, &pubkey);
|
||||
assert_return_code(rc, errno);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_key_free(pubkey);
|
||||
}
|
||||
|
||||
static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state)
|
||||
{
|
||||
int rc;
|
||||
@@ -315,6 +352,7 @@ static void torture_pki_rsa_duplicate_key(void **state)
|
||||
|
||||
rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY ".pub", &pubkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key);
|
||||
assert_true(rc == 0);
|
||||
@@ -329,13 +367,15 @@ static void torture_pki_rsa_duplicate_key(void **state)
|
||||
assert_non_null(privkey);
|
||||
|
||||
privkey_dup = ssh_key_dup(privkey);
|
||||
assert_true(privkey_dup != NULL);
|
||||
assert_non_null(privkey_dup);
|
||||
|
||||
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key_gen);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(b64_key_gen);
|
||||
|
||||
assert_string_equal(b64_key, b64_key_gen);
|
||||
|
||||
@@ -393,6 +433,54 @@ static void torture_pki_rsa_generate_key(void **state)
|
||||
ssh_free(session);
|
||||
}
|
||||
|
||||
static void torture_pki_rsa_sha2(void **state)
|
||||
{
|
||||
int rc;
|
||||
ssh_key key = NULL;
|
||||
ssh_signature sign;
|
||||
ssh_session session=ssh_new();
|
||||
(void) state;
|
||||
|
||||
assert_non_null(session);
|
||||
|
||||
/* Setup */
|
||||
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_true(key != NULL);
|
||||
|
||||
/* Sign using automatic digest */
|
||||
sign = pki_do_sign_hash(key, RSA_HASH, 20, SSH_DIGEST_AUTO);
|
||||
assert_true(sign != NULL);
|
||||
rc = pki_signature_verify(session, sign, key, RSA_HASH, 20);
|
||||
assert_ssh_return_code(session, rc);
|
||||
ssh_signature_free(sign);
|
||||
|
||||
/* Sign using old SHA1 digest */
|
||||
sign = pki_do_sign_hash(key, RSA_HASH, 20, SSH_DIGEST_SHA1);
|
||||
assert_true(sign != NULL);
|
||||
rc = pki_signature_verify(session, sign, key, RSA_HASH, 20);
|
||||
assert_ssh_return_code(session, rc);
|
||||
ssh_signature_free(sign);
|
||||
|
||||
/* Sign using new SHA256 digest */
|
||||
sign = pki_do_sign_hash(key, SHA256_HASH, 32, SSH_DIGEST_SHA256);
|
||||
assert_true(sign != NULL);
|
||||
rc = pki_signature_verify(session, sign, key, SHA256_HASH, 32);
|
||||
assert_ssh_return_code(session, rc);
|
||||
ssh_signature_free(sign);
|
||||
|
||||
/* Sign using rsa-sha2-512 algorithm */
|
||||
sign = pki_do_sign_hash(key, SHA512_HASH, 64, SSH_DIGEST_SHA512);
|
||||
assert_true(sign != NULL);
|
||||
rc = pki_signature_verify(session, sign, key, SHA512_HASH, 64);
|
||||
assert_ssh_return_code(session, rc);
|
||||
ssh_signature_free(sign);
|
||||
|
||||
/* Cleanup */
|
||||
ssh_key_free(key);
|
||||
ssh_free(session);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
static void torture_pki_rsa_write_privkey(void **state)
|
||||
{
|
||||
@@ -408,6 +496,7 @@ static void torture_pki_rsa_write_privkey(void **state)
|
||||
NULL,
|
||||
&origkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(origkey);
|
||||
|
||||
unlink(LIBSSH_RSA_TESTKEY);
|
||||
|
||||
@@ -424,6 +513,7 @@ static void torture_pki_rsa_write_privkey(void **state)
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(privkey);
|
||||
|
||||
rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE);
|
||||
assert_true(rc == 0);
|
||||
@@ -438,6 +528,7 @@ static void torture_pki_rsa_write_privkey(void **state)
|
||||
NULL,
|
||||
&origkey);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(origkey);
|
||||
|
||||
unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE);
|
||||
rc = ssh_pki_export_privkey_file(origkey,
|
||||
@@ -517,12 +608,63 @@ static void torture_pki_rsa_import_privkey_base64_passphrase(void **state)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
torture_pki_rsa_import_openssh_privkey_base64_passphrase(void **state)
|
||||
{
|
||||
int rc;
|
||||
ssh_key key = NULL;
|
||||
const char *passphrase = torture_get_testkey_passphrase();
|
||||
const char *keystring = NULL;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
keystring = torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0, 1);
|
||||
assert_true(keystring != NULL);
|
||||
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
passphrase,
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
rc = ssh_key_is_private(key);
|
||||
assert_true(rc == 1);
|
||||
|
||||
ssh_key_free(key);
|
||||
key = NULL;
|
||||
|
||||
/* test if it returns -1 if passphrase is wrong */
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
"wrong passphrase !!",
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_true(rc == -1);
|
||||
ssh_key_free(key);
|
||||
key = NULL;
|
||||
|
||||
/* test if it returns -1 if passphrase is NULL */
|
||||
/* libcrypto asks for a passphrase, so skip this test */
|
||||
rc = ssh_pki_import_privkey_base64(keystring,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&key);
|
||||
assert_true(rc == -1);
|
||||
ssh_key_free(key);
|
||||
key = NULL;
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_file,
|
||||
setup_rsa_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_from_openssh_privkey,
|
||||
setup_rsa_openssh_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_key,
|
||||
setup_rsa_key,
|
||||
teardown),
|
||||
@@ -532,10 +674,14 @@ int torture_run_tests(void) {
|
||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64,
|
||||
setup_rsa_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64,
|
||||
setup_rsa_openssh_key,
|
||||
teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_publickey_from_privatekey,
|
||||
setup_rsa_key,
|
||||
teardown),
|
||||
cmocka_unit_test(torture_pki_rsa_import_privkey_base64_passphrase),
|
||||
cmocka_unit_test(torture_pki_rsa_import_openssh_privkey_base64_passphrase),
|
||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_copy_cert_to_privkey,
|
||||
setup_rsa_key,
|
||||
teardown),
|
||||
@@ -557,6 +703,7 @@ int torture_run_tests(void) {
|
||||
setup_rsa_key,
|
||||
teardown),
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
cmocka_unit_test(torture_pki_rsa_sha2),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
@@ -589,8 +589,14 @@ int torture_run_tests(void)
|
||||
cmocka_unit_test(torture_mixed),
|
||||
};
|
||||
|
||||
/*
|
||||
* If the library is statically linked, ssh_init() is not called
|
||||
* automatically
|
||||
*/
|
||||
ssh_init();
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||
ssh_finalize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,13 @@ int torture_run_tests(void)
|
||||
cmocka_unit_test(torture_crypto_aes256_cbc),
|
||||
};
|
||||
|
||||
/*
|
||||
* If the library is statically linked, ssh_init() is not called
|
||||
* automatically
|
||||
*/
|
||||
ssh_init();
|
||||
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||
ssh_finalize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -88,8 +88,14 @@ int torture_run_tests(void)
|
||||
cmocka_unit_test(torture_ssh_init),
|
||||
};
|
||||
|
||||
/*
|
||||
* If the library is statically linked, ssh_init() is not called
|
||||
* automatically
|
||||
*/
|
||||
ssh_init();
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||
ssh_finalize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -274,12 +274,14 @@ static void *thread_pki_rsa_publickey_from_privatekey(void *threadid)
|
||||
NULL,
|
||||
&key);
|
||||
assert_true(rc == 0);
|
||||
assert_non_null(key);
|
||||
|
||||
ok = ssh_key_is_private(key);
|
||||
assert_true(ok);
|
||||
|
||||
rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey);
|
||||
assert_true(rc == SSH_OK);
|
||||
assert_non_null(pubkey);
|
||||
|
||||
ssh_key_free(key);
|
||||
ssh_key_free(pubkey);
|
||||
|
||||
Reference in New Issue
Block a user