mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-13 19:40:35 +09:00
Compare commits
78 Commits
libssh-0.1
...
libssh-0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca9c055d7c | ||
|
|
c53b0ef3ec | ||
|
|
f49b4442a9 | ||
|
|
a5e4b12090 | ||
|
|
bf390a0426 | ||
|
|
3e1d276a5a | ||
|
|
b156391833 | ||
|
|
6ba5ff1b7b | ||
|
|
6d74aa6138 | ||
|
|
212121971f | ||
|
|
796d85f786 | ||
|
|
4c0c4ea32e | ||
|
|
02c6f5f7ec | ||
|
|
f80670a7ab | ||
|
|
829fae6404 | ||
|
|
74670207bf | ||
|
|
e34e6c8c94 | ||
|
|
7ecca1fd26 | ||
|
|
dbb4c4cc11 | ||
|
|
ce4c81c614 | ||
|
|
441dfa5327 | ||
|
|
c4681304cc | ||
|
|
1887c9dbcd | ||
|
|
9e2ec491de | ||
|
|
ee1f7293cf | ||
|
|
8e85a1067c | ||
|
|
cc1a811ae5 | ||
|
|
463665db9d | ||
|
|
20d78046aa | ||
|
|
39a62cef44 | ||
|
|
7969b6de3c | ||
|
|
b207e39d28 | ||
|
|
6230b24ff5 | ||
|
|
e668b03dd7 | ||
|
|
77ce02d809 | ||
|
|
d61b0dc7cc | ||
|
|
d12eb770ac | ||
|
|
03b29a6874 | ||
|
|
99957fb561 | ||
|
|
3e9175e66a | ||
|
|
bf295abb5b | ||
|
|
7f14df3eac | ||
|
|
c206e5d84e | ||
|
|
274b8f19b3 | ||
|
|
39a88d62c9 | ||
|
|
94f12090b5 | ||
|
|
301d0e16df | ||
|
|
c182a21e11 | ||
|
|
3a28fbe5c6 | ||
|
|
65f363c9e3 | ||
|
|
1c763e29d1 | ||
|
|
7d85085d2a | ||
|
|
8e4d67aa9e | ||
|
|
266174a6d3 | ||
|
|
87db2659ec | ||
|
|
0fad4e6307 | ||
|
|
02cbd41b92 | ||
|
|
750693d10b | ||
|
|
56953f8aab | ||
|
|
0f1723b5c7 | ||
|
|
f1998d6064 | ||
|
|
d0ef7afdfa | ||
|
|
6e459f5756 | ||
|
|
51746e51f0 | ||
|
|
e7ef3f2962 | ||
|
|
b8d92bbcc7 | ||
|
|
f2aaee53df | ||
|
|
b026b24b55 | ||
|
|
028859ce99 | ||
|
|
d64f06f98a | ||
|
|
b298a04f96 | ||
|
|
962012bbf6 | ||
|
|
abfc42fad3 | ||
|
|
1ad67bd66e | ||
|
|
f553a6740a | ||
|
|
bac5d3f10a | ||
|
|
c8c3d418ee | ||
|
|
33be8038fe |
@@ -121,7 +121,7 @@ review:
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# CentOS builds #
|
# CentOS builds #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
centos10s/openssl_3.2.x/x86_64:
|
centos10s/openssl_3.5.x/x86_64:
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
|
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
|
||||||
extends: .tests
|
extends: .tests
|
||||||
variables:
|
variables:
|
||||||
@@ -132,7 +132,7 @@ centos10s/openssl_3.2.x/x86_64:
|
|||||||
make -j$(nproc) &&
|
make -j$(nproc) &&
|
||||||
ctest --output-on-failure
|
ctest --output-on-failure
|
||||||
|
|
||||||
centos10s/openssl_3.2.x/x86_64/fips:
|
centos10s/openssl_3.5.x/x86_64/fips:
|
||||||
extends: .fips
|
extends: .fips
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
|
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
|
||||||
variables:
|
variables:
|
||||||
@@ -143,11 +143,11 @@ centos10s/openssl_3.2.x/x86_64/fips:
|
|||||||
make -j$(nproc) &&
|
make -j$(nproc) &&
|
||||||
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
|
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
|
||||||
|
|
||||||
centos9s/openssl_3.0.x/x86_64:
|
centos9s/openssl_3.5.x/x86_64:
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||||
extends: .tests
|
extends: .tests
|
||||||
variables:
|
variables:
|
||||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
|
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
|
||||||
script:
|
script:
|
||||||
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
|
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
|
||||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||||
@@ -160,7 +160,7 @@ centos9s/mbedtls_2.x/x86_64:
|
|||||||
variables:
|
variables:
|
||||||
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF"
|
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF"
|
||||||
|
|
||||||
centos9s/openssl_3.0.x/x86_64/fips:
|
centos9s/openssl_3.5.x/x86_64/fips:
|
||||||
extends: .fips
|
extends: .fips
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||||
script:
|
script:
|
||||||
|
|||||||
23
CHANGELOG
23
CHANGELOG
@@ -1,6 +1,29 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
version 0.11.4 (released 2026-02-10)
|
||||||
|
* Security:
|
||||||
|
* CVE-2025-14821: libssh loads configuration files from the C:\etc directory
|
||||||
|
on Windows
|
||||||
|
* CVE-2026-0964: SCP Protocol Path Traversal in ssh_scp_pull_request()
|
||||||
|
* CVE-2026-0965: Possible Denial of Service when parsing unexpected
|
||||||
|
configuration files
|
||||||
|
* CVE-2026-0966: Buffer underflow in ssh_get_hexa() on invalid input
|
||||||
|
* CVE-2026-0967: Specially crafted patterns could cause DoS
|
||||||
|
* CVE-2026-0968: OOB Read in sftp_parse_longname()
|
||||||
|
* libssh-2026-sftp-extensions: Read buffer overrun when handling SFTP
|
||||||
|
extensions
|
||||||
|
* Stability and compatibility improvements of ProxyJump
|
||||||
|
|
||||||
|
version 0.11.3 (released 2025-09-09)
|
||||||
|
* Security:
|
||||||
|
* CVE-2025-8114: Fix NULL pointer dereference after allocation failure
|
||||||
|
* CVE-2025-8277: Fix memory leak of ephemeral key pair during repeated wrong KEX
|
||||||
|
* Potential UAF when send() fails during key exchange
|
||||||
|
* Fix possible timeout during KEX if client sends authentication too early (#311)
|
||||||
|
* Cleanup OpenSSL PKCS#11 provider when loaded
|
||||||
|
* Zeroize buffers containing private key blobs during export
|
||||||
|
|
||||||
version 0.11.2 (released 2025-06-24)
|
version 0.11.2 (released 2025-06-24)
|
||||||
* Security:
|
* Security:
|
||||||
* CVE-2025-4877 - Write beyond bounds in binary to base64 conversion
|
* CVE-2025-4877 - Write beyond bounds in binary to base64 conversion
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.12.0)
|
cmake_minimum_required(VERSION 3.14.0)
|
||||||
|
|
||||||
# Specify search path for CMake modules to be loaded by include()
|
# Specify search path for CMake modules to be loaded by include()
|
||||||
# and find_package()
|
# and find_package()
|
||||||
@@ -9,7 +9,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
|||||||
include(DefineCMakeDefaults)
|
include(DefineCMakeDefaults)
|
||||||
include(DefineCompilerFlags)
|
include(DefineCompilerFlags)
|
||||||
|
|
||||||
project(libssh VERSION 0.11.2 LANGUAGES C)
|
project(libssh VERSION 0.11.4 LANGUAGES C)
|
||||||
|
|
||||||
# global needed variable
|
# global needed variable
|
||||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||||
@@ -21,7 +21,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
|||||||
# Increment AGE. Set REVISION to 0
|
# Increment AGE. Set REVISION to 0
|
||||||
# If the source code was changed, but there were no interface changes:
|
# If the source code was changed, but there were no interface changes:
|
||||||
# Increment REVISION.
|
# Increment REVISION.
|
||||||
set(LIBRARY_VERSION "4.10.2")
|
set(LIBRARY_VERSION "4.10.4")
|
||||||
set(LIBRARY_SOVERSION "4")
|
set(LIBRARY_SOVERSION "4")
|
||||||
|
|
||||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||||
@@ -77,7 +77,7 @@ endif (WITH_NACL)
|
|||||||
|
|
||||||
# Disable symbol versioning in non UNIX platforms
|
# Disable symbol versioning in non UNIX platforms
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
find_package(ABIMap 0.3.1)
|
find_package(ABIMap 0.4.0)
|
||||||
else (UNIX)
|
else (UNIX)
|
||||||
set(WITH_SYMBOL_VERSIONING OFF)
|
set(WITH_SYMBOL_VERSIONING OFF)
|
||||||
endif (UNIX)
|
endif (UNIX)
|
||||||
@@ -168,6 +168,10 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
|||||||
set(ALLOW_ABI_BREAK "BREAK_ABI")
|
set(ALLOW_ABI_BREAK "BREAK_ABI")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (WITH_FINAL)
|
||||||
|
set(FINAL "FINAL")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Target we can depend on in 'make dist'
|
# Target we can depend on in 'make dist'
|
||||||
set(_SYMBOL_TARGET "${PROJECT_NAME}.map")
|
set(_SYMBOL_TARGET "${PROJECT_NAME}.map")
|
||||||
|
|
||||||
@@ -180,7 +184,7 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
|||||||
RELEASE_NAME_VERSION ${PROJECT_NAME}_${LIBRARY_VERSION}
|
RELEASE_NAME_VERSION ${PROJECT_NAME}_${LIBRARY_VERSION}
|
||||||
CURRENT_MAP ${MAP_PATH}
|
CURRENT_MAP ${MAP_PATH}
|
||||||
COPY_TO ${MAP_PATH}
|
COPY_TO ${MAP_PATH}
|
||||||
FINAL
|
${FINAL}
|
||||||
${ALLOW_ABI_BREAK})
|
${ALLOW_ABI_BREAK})
|
||||||
|
|
||||||
# Write the current version to the source
|
# Write the current version to the source
|
||||||
|
|||||||
@@ -12,20 +12,35 @@ option(WITH_PCAP "Compile with Pcap generation support" ON)
|
|||||||
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
||||||
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||||
option(WITH_PKCS11_URI "Build with PKCS#11 URI support" OFF)
|
option(WITH_PKCS11_URI "Build with PKCS#11 URI support" OFF)
|
||||||
option(WITH_PKCS11_PROVIDER "Use the PKCS#11 provider for accessing pkcs11 objects" OFF)
|
option(WITH_PKCS11_PROVIDER
|
||||||
|
"Use the PKCS#11 provider for accessing pkcs11 objects" OFF)
|
||||||
option(UNIT_TESTING "Build with unit tests" OFF)
|
option(UNIT_TESTING "Build with unit tests" OFF)
|
||||||
option(CLIENT_TESTING "Build with client tests; requires openssh" OFF)
|
option(CLIENT_TESTING "Build with client tests; requires openssh" OFF)
|
||||||
option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF)
|
option(SERVER_TESTING "Build with server tests; requires openssh and dropbear"
|
||||||
option(GSSAPI_TESTING "Build with GSSAPI tests; requires krb5-server,krb5-libs and krb5-workstation" OFF)
|
OFF)
|
||||||
option(WITH_BENCHMARKS "Build benchmarks tools; enables unit testing and client tests" OFF)
|
option(
|
||||||
|
GSSAPI_TESTING
|
||||||
|
"Build with GSSAPI tests; requires krb5-server,krb5-libs and krb5-workstation"
|
||||||
|
OFF)
|
||||||
|
option(WITH_BENCHMARKS
|
||||||
|
"Build benchmarks tools; enables unit testing and client tests" OFF)
|
||||||
option(WITH_EXAMPLES "Build examples" ON)
|
option(WITH_EXAMPLES "Build examples" ON)
|
||||||
option(WITH_NACL "Build with libnacl (curve25519)" ON)
|
option(WITH_NACL "Build with libnacl (curve25519)" ON)
|
||||||
option(WITH_SYMBOL_VERSIONING "Build with symbol versioning" ON)
|
option(WITH_SYMBOL_VERSIONING "Build with symbol versioning" ON)
|
||||||
option(WITH_ABI_BREAK "Allow ABI break" OFF)
|
option(WITH_ABI_BREAK "Allow ABI break" OFF)
|
||||||
option(WITH_GEX "Enable DH Group exchange mechanisms" ON)
|
option(WITH_GEX "Enable DH Group exchange mechanisms" ON)
|
||||||
option(WITH_INSECURE_NONE "Enable insecure none cipher and MAC algorithms (not suitable for production!)" OFF)
|
option(
|
||||||
option(WITH_EXEC "Enable libssh to execute arbitrary commands from configuration files or options (match exec, proxy commands and OpenSSH-based proxy-jumps)." ON)
|
WITH_INSECURE_NONE
|
||||||
option(FUZZ_TESTING "Build with fuzzer for the server and client (automatically enables none cipher!)" OFF)
|
"Enable insecure none cipher and MAC algorithms (not suitable for production!)"
|
||||||
|
OFF)
|
||||||
|
option(
|
||||||
|
WITH_EXEC
|
||||||
|
"Enable libssh to execute arbitrary commands from configuration files or options (match exec, proxy commands and OpenSSH-based proxy-jumps)."
|
||||||
|
ON)
|
||||||
|
option(
|
||||||
|
FUZZ_TESTING
|
||||||
|
"Build with fuzzer for the server and client (automatically enables none cipher!)"
|
||||||
|
OFF)
|
||||||
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
|
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
|
||||||
|
|
||||||
if (WITH_ZLIB)
|
if (WITH_ZLIB)
|
||||||
@@ -39,7 +54,10 @@ if (WITH_BENCHMARKS)
|
|||||||
set(CLIENT_TESTING ON)
|
set(CLIENT_TESTING ON)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (UNIT_TESTING OR CLIENT_TESTING OR SERVER_TESTING OR GSSAPI_TESTING)
|
if (UNIT_TESTING
|
||||||
|
OR CLIENT_TESTING
|
||||||
|
OR SERVER_TESTING
|
||||||
|
OR GSSAPI_TESTING)
|
||||||
set(BUILD_STATIC_LIB ON)
|
set(BUILD_STATIC_LIB ON)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@@ -51,12 +69,22 @@ if (WITH_ABI_BREAK)
|
|||||||
set(WITH_SYMBOL_VERSIONING ON)
|
set(WITH_SYMBOL_VERSIONING ON)
|
||||||
endif (WITH_ABI_BREAK)
|
endif (WITH_ABI_BREAK)
|
||||||
|
|
||||||
|
set(GLOBAL_CONF_DIR "/etc/ssh")
|
||||||
|
if (WIN32)
|
||||||
|
# Use PROGRAMDATA on Windows
|
||||||
|
if (DEFINED ENV{PROGRAMDATA})
|
||||||
|
set(GLOBAL_CONF_DIR "$ENV{PROGRAMDATA}/ssh")
|
||||||
|
else ()
|
||||||
|
set(GLOBAL_CONF_DIR "C:/ProgramData/ssh")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (NOT GLOBAL_BIND_CONFIG)
|
if (NOT GLOBAL_BIND_CONFIG)
|
||||||
set(GLOBAL_BIND_CONFIG "/etc/ssh/libssh_server_config")
|
set(GLOBAL_BIND_CONFIG "${GLOBAL_CONF_DIR}/libssh_server_config")
|
||||||
endif (NOT GLOBAL_BIND_CONFIG)
|
endif (NOT GLOBAL_BIND_CONFIG)
|
||||||
|
|
||||||
if (NOT GLOBAL_CLIENT_CONFIG)
|
if (NOT GLOBAL_CLIENT_CONFIG)
|
||||||
set(GLOBAL_CLIENT_CONFIG "/etc/ssh/ssh_config")
|
set(GLOBAL_CLIENT_CONFIG "${GLOBAL_CONF_DIR}/ssh_config")
|
||||||
endif (NOT GLOBAL_CLIENT_CONFIG)
|
endif (NOT GLOBAL_CLIENT_CONFIG)
|
||||||
|
|
||||||
if (FUZZ_TESTING)
|
if (FUZZ_TESTING)
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
#cmakedefine BINARYDIR "${BINARYDIR}"
|
#cmakedefine BINARYDIR "${BINARYDIR}"
|
||||||
#cmakedefine SOURCEDIR "${SOURCEDIR}"
|
#cmakedefine SOURCEDIR "${SOURCEDIR}"
|
||||||
|
|
||||||
|
/* Global configuration directory */
|
||||||
|
#cmakedefine USR_GLOBAL_CONF_DIR "${USR_GLOBAL_CONF_DIR}"
|
||||||
|
#cmakedefine GLOBAL_CONF_DIR "${GLOBAL_CONF_DIR}"
|
||||||
|
|
||||||
/* Global bind configuration file path */
|
/* Global bind configuration file path */
|
||||||
#cmakedefine GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}"
|
#cmakedefine GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}"
|
||||||
|
|
||||||
|
|||||||
@@ -190,7 +190,6 @@ int verify_knownhost(ssh_session session)
|
|||||||
ssh_key srv_pubkey = NULL;
|
ssh_key srv_pubkey = NULL;
|
||||||
size_t hlen;
|
size_t hlen;
|
||||||
char buf[10];
|
char buf[10];
|
||||||
char *hexa = NULL;
|
|
||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
int cmp;
|
int cmp;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -201,7 +200,7 @@ int verify_knownhost(ssh_session session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
rc = ssh_get_publickey_hash(srv_pubkey,
|
||||||
SSH_PUBLICKEY_HASH_SHA1,
|
SSH_PUBLICKEY_HASH_SHA256,
|
||||||
&hash,
|
&hash,
|
||||||
&hlen);
|
&hlen);
|
||||||
ssh_key_free(srv_pubkey);
|
ssh_key_free(srv_pubkey);
|
||||||
@@ -217,7 +216,7 @@ int verify_knownhost(ssh_session session)
|
|||||||
break;
|
break;
|
||||||
case SSH_KNOWN_HOSTS_CHANGED:
|
case SSH_KNOWN_HOSTS_CHANGED:
|
||||||
fprintf(stderr, "Host key for server changed: it is now:\n");
|
fprintf(stderr, "Host key for server changed: it is now:\n");
|
||||||
ssh_print_hexa("Public key hash", hash, hlen);
|
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||||
fprintf(stderr, "For security reasons, connection will be stopped\n");
|
fprintf(stderr, "For security reasons, connection will be stopped\n");
|
||||||
ssh_clean_pubkey_hash(&hash);
|
ssh_clean_pubkey_hash(&hash);
|
||||||
|
|
||||||
@@ -238,10 +237,9 @@ int verify_knownhost(ssh_session session)
|
|||||||
/* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
|
/* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
|
||||||
|
|
||||||
case SSH_KNOWN_HOSTS_UNKNOWN:
|
case SSH_KNOWN_HOSTS_UNKNOWN:
|
||||||
hexa = ssh_get_hexa(hash, hlen);
|
|
||||||
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
|
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
|
||||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
fprintf(stderr, "Public key hash: ");
|
||||||
ssh_string_free_char(hexa);
|
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||||
ssh_clean_pubkey_hash(&hash);
|
ssh_clean_pubkey_hash(&hash);
|
||||||
p = fgets(buf, sizeof(buf), stdin);
|
p = fgets(buf, sizeof(buf), stdin);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
|||||||
@@ -223,9 +223,6 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
|
|||||||
size_t requested_len);
|
size_t requested_len);
|
||||||
|
|
||||||
int secure_memcmp(const void *s1, const void *s2, size_t n);
|
int secure_memcmp(const void *s1, const void *s2, size_t n);
|
||||||
#if defined(HAVE_LIBCRYPTO) && !defined(WITH_PKCS11_PROVIDER)
|
|
||||||
ENGINE *pki_get_engine(void);
|
|
||||||
#endif /* HAVE_LIBCRYPTO */
|
|
||||||
|
|
||||||
void compress_cleanup(struct ssh_crypto_struct *crypto);
|
void compress_cleanup(struct ssh_crypto_struct *crypto);
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,15 @@ typedef BN_CTX* bignum_CTX;
|
|||||||
|
|
||||||
ssh_string pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p);
|
ssh_string pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p);
|
||||||
int pki_key_ecgroup_name_to_nid(const char *group);
|
int pki_key_ecgroup_name_to_nid(const char *group);
|
||||||
|
|
||||||
|
#if defined(WITH_PKCS11_URI)
|
||||||
|
#if defined(WITH_PKCS11_PROVIDER)
|
||||||
|
int pki_load_pkcs11_provider(void);
|
||||||
|
#else
|
||||||
|
ENGINE *pki_get_engine(void);
|
||||||
|
#endif
|
||||||
|
#endif /* WITH_PKCS11_PROVIDER */
|
||||||
|
|
||||||
#endif /* HAVE_LIBCRYPTO */
|
#endif /* HAVE_LIBCRYPTO */
|
||||||
|
|
||||||
#endif /* LIBCRYPTO_H_ */
|
#endif /* LIBCRYPTO_H_ */
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -136,6 +137,8 @@ int ssh_check_username_syntax(const char *username);
|
|||||||
void ssh_proxyjumps_free(struct ssh_list *proxy_jump_list);
|
void ssh_proxyjumps_free(struct ssh_list *proxy_jump_list);
|
||||||
bool ssh_libssh_proxy_jumps(void);
|
bool ssh_libssh_proxy_jumps(void);
|
||||||
|
|
||||||
|
FILE *ssh_strict_fopen(const char *filename, size_t max_file_size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx);
|
|||||||
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p);
|
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p);
|
||||||
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s);
|
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s);
|
||||||
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p);
|
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p);
|
||||||
|
bool ssh_poll_is_locked(ssh_poll_handle p);
|
||||||
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout);
|
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout);
|
||||||
ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session);
|
ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session);
|
||||||
int ssh_event_add_poll(ssh_event event, ssh_poll_handle p);
|
int ssh_event_add_poll(ssh_event event, ssh_poll_handle p);
|
||||||
|
|||||||
@@ -473,6 +473,9 @@ char *ssh_strerror(int err_num, char *buf, size_t buflen);
|
|||||||
#define SSH_TTY_MODES_MAX_BUFSIZE (55 * 5 + 1)
|
#define SSH_TTY_MODES_MAX_BUFSIZE (55 * 5 + 1)
|
||||||
int encode_current_tty_opts(unsigned char *buf, size_t buflen);
|
int encode_current_tty_opts(unsigned char *buf, size_t buflen);
|
||||||
|
|
||||||
|
/** The default maximum file size for a configuration file */
|
||||||
|
#define SSH_MAX_CONFIG_FILE_SIZE 16 * 1024 * 1024
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
4.10.2
|
4.10.4
|
||||||
445
src/ABI/libssh-4.10.3.symbols
Normal file
445
src/ABI/libssh-4.10.3.symbols
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
_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_aio_begin_read
|
||||||
|
sftp_aio_begin_write
|
||||||
|
sftp_aio_free
|
||||||
|
sftp_aio_wait_read
|
||||||
|
sftp_aio_wait_write
|
||||||
|
sftp_async_read
|
||||||
|
sftp_async_read_begin
|
||||||
|
sftp_attributes_free
|
||||||
|
sftp_canonicalize_path
|
||||||
|
sftp_channel_default_data_callback
|
||||||
|
sftp_channel_default_subsystem_request
|
||||||
|
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_expand_path
|
||||||
|
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_hardlink
|
||||||
|
sftp_home_directory
|
||||||
|
sftp_init
|
||||||
|
sftp_limits
|
||||||
|
sftp_limits_free
|
||||||
|
sftp_lsetstat
|
||||||
|
sftp_lstat
|
||||||
|
sftp_mkdir
|
||||||
|
sftp_new
|
||||||
|
sftp_new_channel
|
||||||
|
sftp_open
|
||||||
|
sftp_opendir
|
||||||
|
sftp_read
|
||||||
|
sftp_readdir
|
||||||
|
sftp_readlink
|
||||||
|
sftp_rename
|
||||||
|
sftp_reply_attr
|
||||||
|
sftp_reply_data
|
||||||
|
sftp_reply_handle
|
||||||
|
sftp_reply_name
|
||||||
|
sftp_reply_names
|
||||||
|
sftp_reply_names_add
|
||||||
|
sftp_reply_status
|
||||||
|
sftp_rewind
|
||||||
|
sftp_rmdir
|
||||||
|
sftp_seek
|
||||||
|
sftp_seek64
|
||||||
|
sftp_send_client_message
|
||||||
|
sftp_server_free
|
||||||
|
sftp_server_init
|
||||||
|
sftp_server_new
|
||||||
|
sftp_server_version
|
||||||
|
sftp_setstat
|
||||||
|
sftp_stat
|
||||||
|
sftp_statvfs
|
||||||
|
sftp_statvfs_free
|
||||||
|
sftp_symlink
|
||||||
|
sftp_tell
|
||||||
|
sftp_tell64
|
||||||
|
sftp_unlink
|
||||||
|
sftp_utimes
|
||||||
|
sftp_write
|
||||||
|
ssh_accept
|
||||||
|
ssh_add_channel_callbacks
|
||||||
|
ssh_auth_list
|
||||||
|
ssh_basename
|
||||||
|
ssh_bind_accept
|
||||||
|
ssh_bind_accept_fd
|
||||||
|
ssh_bind_fd_toaccept
|
||||||
|
ssh_bind_free
|
||||||
|
ssh_bind_get_fd
|
||||||
|
ssh_bind_listen
|
||||||
|
ssh_bind_new
|
||||||
|
ssh_bind_options_parse_config
|
||||||
|
ssh_bind_options_set
|
||||||
|
ssh_bind_set_blocking
|
||||||
|
ssh_bind_set_callbacks
|
||||||
|
ssh_bind_set_fd
|
||||||
|
ssh_blocking_flush
|
||||||
|
ssh_buffer_add_data
|
||||||
|
ssh_buffer_free
|
||||||
|
ssh_buffer_get
|
||||||
|
ssh_buffer_get_data
|
||||||
|
ssh_buffer_get_len
|
||||||
|
ssh_buffer_new
|
||||||
|
ssh_buffer_reinit
|
||||||
|
ssh_channel_accept_forward
|
||||||
|
ssh_channel_accept_x11
|
||||||
|
ssh_channel_cancel_forward
|
||||||
|
ssh_channel_change_pty_size
|
||||||
|
ssh_channel_close
|
||||||
|
ssh_channel_free
|
||||||
|
ssh_channel_get_exit_state
|
||||||
|
ssh_channel_get_exit_status
|
||||||
|
ssh_channel_get_session
|
||||||
|
ssh_channel_is_closed
|
||||||
|
ssh_channel_is_eof
|
||||||
|
ssh_channel_is_open
|
||||||
|
ssh_channel_listen_forward
|
||||||
|
ssh_channel_new
|
||||||
|
ssh_channel_open_auth_agent
|
||||||
|
ssh_channel_open_forward
|
||||||
|
ssh_channel_open_forward_port
|
||||||
|
ssh_channel_open_forward_unix
|
||||||
|
ssh_channel_open_reverse_forward
|
||||||
|
ssh_channel_open_session
|
||||||
|
ssh_channel_open_x11
|
||||||
|
ssh_channel_poll
|
||||||
|
ssh_channel_poll_timeout
|
||||||
|
ssh_channel_read
|
||||||
|
ssh_channel_read_nonblocking
|
||||||
|
ssh_channel_read_timeout
|
||||||
|
ssh_channel_request_auth_agent
|
||||||
|
ssh_channel_request_env
|
||||||
|
ssh_channel_request_exec
|
||||||
|
ssh_channel_request_pty
|
||||||
|
ssh_channel_request_pty_size
|
||||||
|
ssh_channel_request_pty_size_modes
|
||||||
|
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_dup
|
||||||
|
ssh_key_free
|
||||||
|
ssh_key_is_private
|
||||||
|
ssh_key_is_public
|
||||||
|
ssh_key_new
|
||||||
|
ssh_key_type
|
||||||
|
ssh_key_type_from_name
|
||||||
|
ssh_key_type_to_char
|
||||||
|
ssh_known_hosts_parse_line
|
||||||
|
ssh_knownhosts_entry_free
|
||||||
|
ssh_log
|
||||||
|
ssh_message_auth_interactive_request
|
||||||
|
ssh_message_auth_kbdint_is_response
|
||||||
|
ssh_message_auth_password
|
||||||
|
ssh_message_auth_pubkey
|
||||||
|
ssh_message_auth_publickey
|
||||||
|
ssh_message_auth_publickey_state
|
||||||
|
ssh_message_auth_reply_pk_ok
|
||||||
|
ssh_message_auth_reply_pk_ok_simple
|
||||||
|
ssh_message_auth_reply_success
|
||||||
|
ssh_message_auth_set_methods
|
||||||
|
ssh_message_auth_user
|
||||||
|
ssh_message_channel_request_channel
|
||||||
|
ssh_message_channel_request_command
|
||||||
|
ssh_message_channel_request_env_name
|
||||||
|
ssh_message_channel_request_env_value
|
||||||
|
ssh_message_channel_request_open_destination
|
||||||
|
ssh_message_channel_request_open_destination_port
|
||||||
|
ssh_message_channel_request_open_originator
|
||||||
|
ssh_message_channel_request_open_originator_port
|
||||||
|
ssh_message_channel_request_open_reply_accept
|
||||||
|
ssh_message_channel_request_open_reply_accept_channel
|
||||||
|
ssh_message_channel_request_pty_height
|
||||||
|
ssh_message_channel_request_pty_pxheight
|
||||||
|
ssh_message_channel_request_pty_pxwidth
|
||||||
|
ssh_message_channel_request_pty_term
|
||||||
|
ssh_message_channel_request_pty_width
|
||||||
|
ssh_message_channel_request_reply_success
|
||||||
|
ssh_message_channel_request_subsystem
|
||||||
|
ssh_message_channel_request_x11_auth_cookie
|
||||||
|
ssh_message_channel_request_x11_auth_protocol
|
||||||
|
ssh_message_channel_request_x11_screen_number
|
||||||
|
ssh_message_channel_request_x11_single_connection
|
||||||
|
ssh_message_free
|
||||||
|
ssh_message_get
|
||||||
|
ssh_message_global_request_address
|
||||||
|
ssh_message_global_request_port
|
||||||
|
ssh_message_global_request_reply_success
|
||||||
|
ssh_message_reply_default
|
||||||
|
ssh_message_retrieve
|
||||||
|
ssh_message_service_reply_success
|
||||||
|
ssh_message_service_service
|
||||||
|
ssh_message_subtype
|
||||||
|
ssh_message_type
|
||||||
|
ssh_mkdir
|
||||||
|
ssh_new
|
||||||
|
ssh_options_copy
|
||||||
|
ssh_options_get
|
||||||
|
ssh_options_get_port
|
||||||
|
ssh_options_getopt
|
||||||
|
ssh_options_parse_config
|
||||||
|
ssh_options_set
|
||||||
|
ssh_pcap_file_close
|
||||||
|
ssh_pcap_file_free
|
||||||
|
ssh_pcap_file_new
|
||||||
|
ssh_pcap_file_open
|
||||||
|
ssh_pki_copy_cert_to_privkey
|
||||||
|
ssh_pki_export_privkey_base64
|
||||||
|
ssh_pki_export_privkey_base64_format
|
||||||
|
ssh_pki_export_privkey_file
|
||||||
|
ssh_pki_export_privkey_file_format
|
||||||
|
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_request_no_more_sessions
|
||||||
|
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_issue_banner
|
||||||
|
ssh_send_keepalive
|
||||||
|
ssh_server_init_kex
|
||||||
|
ssh_service_request
|
||||||
|
ssh_session_export_known_hosts_entry
|
||||||
|
ssh_session_get_known_hosts_entry
|
||||||
|
ssh_session_has_known_hosts_entry
|
||||||
|
ssh_session_is_known_server
|
||||||
|
ssh_session_set_disconnect_message
|
||||||
|
ssh_session_update_known_hosts
|
||||||
|
ssh_set_agent_channel
|
||||||
|
ssh_set_agent_socket
|
||||||
|
ssh_set_auth_methods
|
||||||
|
ssh_set_blocking
|
||||||
|
ssh_set_callbacks
|
||||||
|
ssh_set_channel_callbacks
|
||||||
|
ssh_set_counters
|
||||||
|
ssh_set_fd_except
|
||||||
|
ssh_set_fd_toread
|
||||||
|
ssh_set_fd_towrite
|
||||||
|
ssh_set_log_callback
|
||||||
|
ssh_set_log_level
|
||||||
|
ssh_set_log_userdata
|
||||||
|
ssh_set_message_callback
|
||||||
|
ssh_set_pcap_file
|
||||||
|
ssh_set_server_callbacks
|
||||||
|
ssh_silent_disconnect
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_get_char
|
||||||
|
ssh_string_len
|
||||||
|
ssh_string_new
|
||||||
|
ssh_string_to_char
|
||||||
|
ssh_threads_get_default
|
||||||
|
ssh_threads_get_noop
|
||||||
|
ssh_threads_get_pthread
|
||||||
|
ssh_threads_set_callbacks
|
||||||
|
ssh_try_publickey_from_file
|
||||||
|
ssh_userauth_agent
|
||||||
|
ssh_userauth_agent_pubkey
|
||||||
|
ssh_userauth_autopubkey
|
||||||
|
ssh_userauth_gssapi
|
||||||
|
ssh_userauth_kbdint
|
||||||
|
ssh_userauth_kbdint_getanswer
|
||||||
|
ssh_userauth_kbdint_getinstruction
|
||||||
|
ssh_userauth_kbdint_getname
|
||||||
|
ssh_userauth_kbdint_getnanswers
|
||||||
|
ssh_userauth_kbdint_getnprompts
|
||||||
|
ssh_userauth_kbdint_getprompt
|
||||||
|
ssh_userauth_kbdint_setanswer
|
||||||
|
ssh_userauth_list
|
||||||
|
ssh_userauth_none
|
||||||
|
ssh_userauth_offer_pubkey
|
||||||
|
ssh_userauth_password
|
||||||
|
ssh_userauth_privatekey_file
|
||||||
|
ssh_userauth_pubkey
|
||||||
|
ssh_userauth_publickey
|
||||||
|
ssh_userauth_publickey_auto
|
||||||
|
ssh_userauth_publickey_auto_get_current_identity
|
||||||
|
ssh_userauth_try_publickey
|
||||||
|
ssh_version
|
||||||
|
ssh_vlog
|
||||||
|
ssh_write_knownhost
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
445
src/ABI/libssh-4.10.4.symbols
Normal file
445
src/ABI/libssh-4.10.4.symbols
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
_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_aio_begin_read
|
||||||
|
sftp_aio_begin_write
|
||||||
|
sftp_aio_free
|
||||||
|
sftp_aio_wait_read
|
||||||
|
sftp_aio_wait_write
|
||||||
|
sftp_async_read
|
||||||
|
sftp_async_read_begin
|
||||||
|
sftp_attributes_free
|
||||||
|
sftp_canonicalize_path
|
||||||
|
sftp_channel_default_data_callback
|
||||||
|
sftp_channel_default_subsystem_request
|
||||||
|
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_expand_path
|
||||||
|
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_hardlink
|
||||||
|
sftp_home_directory
|
||||||
|
sftp_init
|
||||||
|
sftp_limits
|
||||||
|
sftp_limits_free
|
||||||
|
sftp_lsetstat
|
||||||
|
sftp_lstat
|
||||||
|
sftp_mkdir
|
||||||
|
sftp_new
|
||||||
|
sftp_new_channel
|
||||||
|
sftp_open
|
||||||
|
sftp_opendir
|
||||||
|
sftp_read
|
||||||
|
sftp_readdir
|
||||||
|
sftp_readlink
|
||||||
|
sftp_rename
|
||||||
|
sftp_reply_attr
|
||||||
|
sftp_reply_data
|
||||||
|
sftp_reply_handle
|
||||||
|
sftp_reply_name
|
||||||
|
sftp_reply_names
|
||||||
|
sftp_reply_names_add
|
||||||
|
sftp_reply_status
|
||||||
|
sftp_rewind
|
||||||
|
sftp_rmdir
|
||||||
|
sftp_seek
|
||||||
|
sftp_seek64
|
||||||
|
sftp_send_client_message
|
||||||
|
sftp_server_free
|
||||||
|
sftp_server_init
|
||||||
|
sftp_server_new
|
||||||
|
sftp_server_version
|
||||||
|
sftp_setstat
|
||||||
|
sftp_stat
|
||||||
|
sftp_statvfs
|
||||||
|
sftp_statvfs_free
|
||||||
|
sftp_symlink
|
||||||
|
sftp_tell
|
||||||
|
sftp_tell64
|
||||||
|
sftp_unlink
|
||||||
|
sftp_utimes
|
||||||
|
sftp_write
|
||||||
|
ssh_accept
|
||||||
|
ssh_add_channel_callbacks
|
||||||
|
ssh_auth_list
|
||||||
|
ssh_basename
|
||||||
|
ssh_bind_accept
|
||||||
|
ssh_bind_accept_fd
|
||||||
|
ssh_bind_fd_toaccept
|
||||||
|
ssh_bind_free
|
||||||
|
ssh_bind_get_fd
|
||||||
|
ssh_bind_listen
|
||||||
|
ssh_bind_new
|
||||||
|
ssh_bind_options_parse_config
|
||||||
|
ssh_bind_options_set
|
||||||
|
ssh_bind_set_blocking
|
||||||
|
ssh_bind_set_callbacks
|
||||||
|
ssh_bind_set_fd
|
||||||
|
ssh_blocking_flush
|
||||||
|
ssh_buffer_add_data
|
||||||
|
ssh_buffer_free
|
||||||
|
ssh_buffer_get
|
||||||
|
ssh_buffer_get_data
|
||||||
|
ssh_buffer_get_len
|
||||||
|
ssh_buffer_new
|
||||||
|
ssh_buffer_reinit
|
||||||
|
ssh_channel_accept_forward
|
||||||
|
ssh_channel_accept_x11
|
||||||
|
ssh_channel_cancel_forward
|
||||||
|
ssh_channel_change_pty_size
|
||||||
|
ssh_channel_close
|
||||||
|
ssh_channel_free
|
||||||
|
ssh_channel_get_exit_state
|
||||||
|
ssh_channel_get_exit_status
|
||||||
|
ssh_channel_get_session
|
||||||
|
ssh_channel_is_closed
|
||||||
|
ssh_channel_is_eof
|
||||||
|
ssh_channel_is_open
|
||||||
|
ssh_channel_listen_forward
|
||||||
|
ssh_channel_new
|
||||||
|
ssh_channel_open_auth_agent
|
||||||
|
ssh_channel_open_forward
|
||||||
|
ssh_channel_open_forward_port
|
||||||
|
ssh_channel_open_forward_unix
|
||||||
|
ssh_channel_open_reverse_forward
|
||||||
|
ssh_channel_open_session
|
||||||
|
ssh_channel_open_x11
|
||||||
|
ssh_channel_poll
|
||||||
|
ssh_channel_poll_timeout
|
||||||
|
ssh_channel_read
|
||||||
|
ssh_channel_read_nonblocking
|
||||||
|
ssh_channel_read_timeout
|
||||||
|
ssh_channel_request_auth_agent
|
||||||
|
ssh_channel_request_env
|
||||||
|
ssh_channel_request_exec
|
||||||
|
ssh_channel_request_pty
|
||||||
|
ssh_channel_request_pty_size
|
||||||
|
ssh_channel_request_pty_size_modes
|
||||||
|
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_dup
|
||||||
|
ssh_key_free
|
||||||
|
ssh_key_is_private
|
||||||
|
ssh_key_is_public
|
||||||
|
ssh_key_new
|
||||||
|
ssh_key_type
|
||||||
|
ssh_key_type_from_name
|
||||||
|
ssh_key_type_to_char
|
||||||
|
ssh_known_hosts_parse_line
|
||||||
|
ssh_knownhosts_entry_free
|
||||||
|
ssh_log
|
||||||
|
ssh_message_auth_interactive_request
|
||||||
|
ssh_message_auth_kbdint_is_response
|
||||||
|
ssh_message_auth_password
|
||||||
|
ssh_message_auth_pubkey
|
||||||
|
ssh_message_auth_publickey
|
||||||
|
ssh_message_auth_publickey_state
|
||||||
|
ssh_message_auth_reply_pk_ok
|
||||||
|
ssh_message_auth_reply_pk_ok_simple
|
||||||
|
ssh_message_auth_reply_success
|
||||||
|
ssh_message_auth_set_methods
|
||||||
|
ssh_message_auth_user
|
||||||
|
ssh_message_channel_request_channel
|
||||||
|
ssh_message_channel_request_command
|
||||||
|
ssh_message_channel_request_env_name
|
||||||
|
ssh_message_channel_request_env_value
|
||||||
|
ssh_message_channel_request_open_destination
|
||||||
|
ssh_message_channel_request_open_destination_port
|
||||||
|
ssh_message_channel_request_open_originator
|
||||||
|
ssh_message_channel_request_open_originator_port
|
||||||
|
ssh_message_channel_request_open_reply_accept
|
||||||
|
ssh_message_channel_request_open_reply_accept_channel
|
||||||
|
ssh_message_channel_request_pty_height
|
||||||
|
ssh_message_channel_request_pty_pxheight
|
||||||
|
ssh_message_channel_request_pty_pxwidth
|
||||||
|
ssh_message_channel_request_pty_term
|
||||||
|
ssh_message_channel_request_pty_width
|
||||||
|
ssh_message_channel_request_reply_success
|
||||||
|
ssh_message_channel_request_subsystem
|
||||||
|
ssh_message_channel_request_x11_auth_cookie
|
||||||
|
ssh_message_channel_request_x11_auth_protocol
|
||||||
|
ssh_message_channel_request_x11_screen_number
|
||||||
|
ssh_message_channel_request_x11_single_connection
|
||||||
|
ssh_message_free
|
||||||
|
ssh_message_get
|
||||||
|
ssh_message_global_request_address
|
||||||
|
ssh_message_global_request_port
|
||||||
|
ssh_message_global_request_reply_success
|
||||||
|
ssh_message_reply_default
|
||||||
|
ssh_message_retrieve
|
||||||
|
ssh_message_service_reply_success
|
||||||
|
ssh_message_service_service
|
||||||
|
ssh_message_subtype
|
||||||
|
ssh_message_type
|
||||||
|
ssh_mkdir
|
||||||
|
ssh_new
|
||||||
|
ssh_options_copy
|
||||||
|
ssh_options_get
|
||||||
|
ssh_options_get_port
|
||||||
|
ssh_options_getopt
|
||||||
|
ssh_options_parse_config
|
||||||
|
ssh_options_set
|
||||||
|
ssh_pcap_file_close
|
||||||
|
ssh_pcap_file_free
|
||||||
|
ssh_pcap_file_new
|
||||||
|
ssh_pcap_file_open
|
||||||
|
ssh_pki_copy_cert_to_privkey
|
||||||
|
ssh_pki_export_privkey_base64
|
||||||
|
ssh_pki_export_privkey_base64_format
|
||||||
|
ssh_pki_export_privkey_file
|
||||||
|
ssh_pki_export_privkey_file_format
|
||||||
|
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_request_no_more_sessions
|
||||||
|
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_issue_banner
|
||||||
|
ssh_send_keepalive
|
||||||
|
ssh_server_init_kex
|
||||||
|
ssh_service_request
|
||||||
|
ssh_session_export_known_hosts_entry
|
||||||
|
ssh_session_get_known_hosts_entry
|
||||||
|
ssh_session_has_known_hosts_entry
|
||||||
|
ssh_session_is_known_server
|
||||||
|
ssh_session_set_disconnect_message
|
||||||
|
ssh_session_update_known_hosts
|
||||||
|
ssh_set_agent_channel
|
||||||
|
ssh_set_agent_socket
|
||||||
|
ssh_set_auth_methods
|
||||||
|
ssh_set_blocking
|
||||||
|
ssh_set_callbacks
|
||||||
|
ssh_set_channel_callbacks
|
||||||
|
ssh_set_counters
|
||||||
|
ssh_set_fd_except
|
||||||
|
ssh_set_fd_toread
|
||||||
|
ssh_set_fd_towrite
|
||||||
|
ssh_set_log_callback
|
||||||
|
ssh_set_log_level
|
||||||
|
ssh_set_log_userdata
|
||||||
|
ssh_set_message_callback
|
||||||
|
ssh_set_pcap_file
|
||||||
|
ssh_set_server_callbacks
|
||||||
|
ssh_silent_disconnect
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_get_char
|
||||||
|
ssh_string_len
|
||||||
|
ssh_string_new
|
||||||
|
ssh_string_to_char
|
||||||
|
ssh_threads_get_default
|
||||||
|
ssh_threads_get_noop
|
||||||
|
ssh_threads_get_pthread
|
||||||
|
ssh_threads_set_callbacks
|
||||||
|
ssh_try_publickey_from_file
|
||||||
|
ssh_userauth_agent
|
||||||
|
ssh_userauth_agent_pubkey
|
||||||
|
ssh_userauth_autopubkey
|
||||||
|
ssh_userauth_gssapi
|
||||||
|
ssh_userauth_kbdint
|
||||||
|
ssh_userauth_kbdint_getanswer
|
||||||
|
ssh_userauth_kbdint_getinstruction
|
||||||
|
ssh_userauth_kbdint_getname
|
||||||
|
ssh_userauth_kbdint_getnanswers
|
||||||
|
ssh_userauth_kbdint_getnprompts
|
||||||
|
ssh_userauth_kbdint_getprompt
|
||||||
|
ssh_userauth_kbdint_setanswer
|
||||||
|
ssh_userauth_list
|
||||||
|
ssh_userauth_none
|
||||||
|
ssh_userauth_offer_pubkey
|
||||||
|
ssh_userauth_password
|
||||||
|
ssh_userauth_privatekey_file
|
||||||
|
ssh_userauth_pubkey
|
||||||
|
ssh_userauth_publickey
|
||||||
|
ssh_userauth_publickey_auto
|
||||||
|
ssh_userauth_publickey_auto_get_current_identity
|
||||||
|
ssh_userauth_try_publickey
|
||||||
|
ssh_version
|
||||||
|
ssh_vlog
|
||||||
|
ssh_write_knownhost
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
@@ -1294,6 +1294,11 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
|||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_INFO,
|
||||||
|
"Starting authentication as a user %s",
|
||||||
|
username ? username : session->opts.username);
|
||||||
|
|
||||||
if (! (session->opts.flags & SSH_OPT_FLAG_PUBKEY_AUTH)) {
|
if (! (session->opts.flags & SSH_OPT_FLAG_PUBKEY_AUTH)) {
|
||||||
session->auth.supported_methods &= ~SSH_AUTH_METHOD_PUBLICKEY;
|
session->auth.supported_methods &= ~SSH_AUTH_METHOD_PUBLICKEY;
|
||||||
return SSH_AUTH_DENIED;
|
return SSH_AUTH_DENIED;
|
||||||
|
|||||||
20
src/bind.c
20
src/bind.c
@@ -218,7 +218,8 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssh_bind_listen(ssh_bind sshbind) {
|
int ssh_bind_listen(ssh_bind sshbind)
|
||||||
|
{
|
||||||
const char *host = NULL;
|
const char *host = NULL;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -240,23 +241,6 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
|||||||
sshbind->ed25519key = strdup("/etc/ssh/ssh_host_ed25519_key");
|
sshbind->ed25519key = strdup("/etc/ssh/ssh_host_ed25519_key");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply global bind configurations, if it hasn't been applied before */
|
|
||||||
rc = ssh_bind_options_parse_config(sshbind, NULL);
|
|
||||||
if (rc != 0) {
|
|
||||||
ssh_set_error(sshbind, SSH_FATAL, "Could not parse global config");
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set default hostkey paths if no hostkey was found before */
|
|
||||||
if (sshbind->ecdsakey == NULL &&
|
|
||||||
sshbind->rsakey == NULL &&
|
|
||||||
sshbind->ed25519key == NULL) {
|
|
||||||
|
|
||||||
sshbind->ecdsakey = strdup("/etc/ssh/ssh_host_ecdsa_key");
|
|
||||||
sshbind->rsakey = strdup("/etc/ssh/ssh_host_rsa_key");
|
|
||||||
sshbind->ed25519key = strdup("/etc/ssh/ssh_host_ed25519_key");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sshbind->rsa == NULL &&
|
if (sshbind->rsa == NULL &&
|
||||||
sshbind->ecdsa == NULL &&
|
sshbind->ecdsa == NULL &&
|
||||||
sshbind->ed25519 == NULL) {
|
sshbind->ed25519 == NULL) {
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ local_parse_file(ssh_bind bind,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fopen(filename, "r");
|
f = ssh_strict_fopen(filename, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load",
|
SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load",
|
||||||
filename);
|
filename);
|
||||||
@@ -636,7 +636,7 @@ int ssh_bind_config_parse_file(ssh_bind bind, const char *filename)
|
|||||||
* option to be redefined later by another file. */
|
* option to be redefined later by another file. */
|
||||||
uint8_t seen[BIND_CFG_MAX] = {0};
|
uint8_t seen[BIND_CFG_MAX] = {0};
|
||||||
|
|
||||||
f = fopen(filename, "r");
|
f = ssh_strict_fopen(filename, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -836,6 +836,7 @@ error:
|
|||||||
session->opts.fd = SSH_INVALID_SOCKET;
|
session->opts.fd = SSH_INVALID_SOCKET;
|
||||||
session->session_state = SSH_SESSION_STATE_DISCONNECTED;
|
session->session_state = SSH_SESSION_STATE_DISCONNECTED;
|
||||||
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
||||||
|
session->packet_state = PACKET_STATE_INIT;
|
||||||
|
|
||||||
while ((it = ssh_list_get_iterator(session->channels)) != NULL) {
|
while ((it = ssh_list_get_iterator(session->channels)) != NULL) {
|
||||||
ssh_channel_do_free(ssh_iterator_value(ssh_channel, it));
|
ssh_channel_do_free(ssh_iterator_value(ssh_channel, it));
|
||||||
|
|||||||
10
src/config.c
10
src/config.c
@@ -223,10 +223,9 @@ local_parse_file(ssh_session session,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fopen(filename, "r");
|
f = ssh_strict_fopen(filename, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load",
|
/* The underlying function logs the reasons */
|
||||||
filename);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1066,12 +1065,10 @@ ssh_config_parse_line(ssh_session session,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOC_USERNAME:
|
case SOC_USERNAME:
|
||||||
if (session->opts.username == NULL) {
|
|
||||||
p = ssh_config_get_str_tok(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
if (p && *parsing) {
|
if (p && *parsing) {
|
||||||
ssh_options_set(session, SSH_OPTIONS_USER, p);
|
ssh_options_set(session, SSH_OPTIONS_USER, p);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SOC_IDENTITY:
|
case SOC_IDENTITY:
|
||||||
p = ssh_config_get_str_tok(&s, NULL);
|
p = ssh_config_get_str_tok(&s, NULL);
|
||||||
@@ -1466,8 +1463,9 @@ int ssh_config_parse_file(ssh_session session, const char *filename)
|
|||||||
int parsing, rv;
|
int parsing, rv;
|
||||||
bool global = 0;
|
bool global = 0;
|
||||||
|
|
||||||
f = fopen(filename, "r");
|
f = ssh_strict_fopen(filename, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
|
/* The underlying function logs the reasons */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -281,6 +281,9 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
|||||||
* connection, otherwise return the first address without error or error */
|
* connection, otherwise return the first address without error or error */
|
||||||
if (s == -1) {
|
if (s == -1) {
|
||||||
s = first;
|
s = first;
|
||||||
|
} else if (s != first && first != -1) {
|
||||||
|
/* Clean up the saved socket if any */
|
||||||
|
ssh_connect_socket_close(first);
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|||||||
116
src/connector.c
116
src/connector.c
@@ -166,7 +166,7 @@ int ssh_connector_set_out_channel(ssh_connector connector,
|
|||||||
|
|
||||||
/* Fallback to default value for invalid flags */
|
/* Fallback to default value for invalid flags */
|
||||||
if (!(flags & SSH_CONNECTOR_STDOUT) && !(flags & SSH_CONNECTOR_STDERR)) {
|
if (!(flags & SSH_CONNECTOR_STDOUT) && !(flags & SSH_CONNECTOR_STDERR)) {
|
||||||
connector->in_flags = SSH_CONNECTOR_STDOUT;
|
connector->out_flags = SSH_CONNECTOR_STDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssh_add_channel_callbacks(channel, &connector->out_channel_cb);
|
return ssh_add_channel_callbacks(channel, &connector->out_channel_cb);
|
||||||
@@ -225,6 +225,87 @@ static void ssh_connector_reset_pollevents(ssh_connector connector)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Update the connector's flags after a read-write io
|
||||||
|
* operation
|
||||||
|
*
|
||||||
|
* This should be called after some data is successfully read from
|
||||||
|
* connector's input and written to connector's output.
|
||||||
|
*
|
||||||
|
* @param[in, out] connector Connector for which the io operation occured.
|
||||||
|
*
|
||||||
|
* @warning This does not consider the case when the io indicated failure
|
||||||
|
*
|
||||||
|
* @warning This does not consider the case when the input indicated that
|
||||||
|
* EOF was encountered.
|
||||||
|
*/
|
||||||
|
static void ssh_connector_update_flags_after_io(ssh_connector connector)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* With fds we can afford to mark:
|
||||||
|
* - in_available as 0 after an fd read (even if more pending data can be
|
||||||
|
* immediately read from the fd)
|
||||||
|
*
|
||||||
|
* - out_wontblock as 0 after an fd write (even if more data can
|
||||||
|
* be written to the fd without blocking)
|
||||||
|
*
|
||||||
|
* since poll events set on the fd will get raised to indicate
|
||||||
|
* possibility of read/write in case existing situation is apt
|
||||||
|
* (i.e can read/write occur right now) or if situation becomes
|
||||||
|
* apt in future (read data becomes available, write becomes
|
||||||
|
* possible)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On the other hand, with channels we need to be more careful
|
||||||
|
* before claiming read/write not possible because channel callbacks
|
||||||
|
* are called in limited scenarios.
|
||||||
|
*
|
||||||
|
* (e.g. connector callback to indicate read data available on input
|
||||||
|
* channel is called only when new data is received on channel. It is
|
||||||
|
* not called when we have some pending data in channel's buffers but
|
||||||
|
* don't receive any new data on the channel)
|
||||||
|
*
|
||||||
|
* Hence, in case of channels, blindly setting flag associated with
|
||||||
|
* read/write input/output to 0 after a read/write may not be a good
|
||||||
|
* idea as the callback that sets it back to 1 again may not be ever
|
||||||
|
* called again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t window_size;
|
||||||
|
|
||||||
|
/* update in_available based on input source (fd or channel) */
|
||||||
|
if (connector->in_fd != SSH_INVALID_SOCKET) {
|
||||||
|
connector->in_available = 0;
|
||||||
|
} else if (connector->in_channel != NULL) {
|
||||||
|
if (ssh_channel_poll_timeout(connector->in_channel, 0, 0) > 0) {
|
||||||
|
connector->in_available = 1;
|
||||||
|
} else {
|
||||||
|
connector->in_available = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* connector input is invalid ! */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update out_wontblock based on output source (fd or channel) */
|
||||||
|
if (connector->out_fd != SSH_INVALID_SOCKET) {
|
||||||
|
connector->out_wontblock = 0;
|
||||||
|
} else if (connector->out_channel != NULL) {
|
||||||
|
window_size = ssh_channel_window_size(connector->out_channel);
|
||||||
|
if (window_size > 0) {
|
||||||
|
connector->out_wontblock = 1;
|
||||||
|
} else {
|
||||||
|
connector->out_wontblock = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* connector output is invalid ! */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
@@ -306,8 +387,8 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
|||||||
ssh_set_error(connector->session, SSH_FATAL, "output socket or channel closed");
|
ssh_set_error(connector->session, SSH_FATAL, "output socket or channel closed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connector->out_wontblock = 0;
|
|
||||||
connector->in_available = 0;
|
ssh_connector_update_flags_after_io(connector);
|
||||||
} else {
|
} else {
|
||||||
connector->in_available = 1;
|
connector->in_available = 1;
|
||||||
}
|
}
|
||||||
@@ -359,8 +440,8 @@ ssh_connector_fd_out_cb(ssh_connector connector)
|
|||||||
"Output socket or channel closed");
|
"Output socket or channel closed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connector->in_available = 0;
|
|
||||||
connector->out_wontblock = 0;
|
ssh_connector_update_flags_after_io(connector);
|
||||||
} else {
|
} else {
|
||||||
connector->out_wontblock = 1;
|
connector->out_wontblock = 1;
|
||||||
}
|
}
|
||||||
@@ -381,15 +462,13 @@ ssh_connector_fd_out_cb(ssh_connector connector)
|
|||||||
*
|
*
|
||||||
* @returns 0
|
* @returns 0
|
||||||
*/
|
*/
|
||||||
static int ssh_connector_fd_cb(ssh_poll_handle p,
|
static int ssh_connector_fd_cb(UNUSED_PARAM(ssh_poll_handle p),
|
||||||
socket_t fd,
|
socket_t fd,
|
||||||
int revents,
|
int revents,
|
||||||
void *userdata)
|
void *userdata)
|
||||||
{
|
{
|
||||||
ssh_connector connector = userdata;
|
ssh_connector connector = userdata;
|
||||||
|
|
||||||
(void)p;
|
|
||||||
|
|
||||||
if (revents & POLLERR) {
|
if (revents & POLLERR) {
|
||||||
ssh_connector_except(connector, fd);
|
ssh_connector_except(connector, fd);
|
||||||
} else if((revents & (POLLIN|POLLHUP)) && fd == connector->in_fd) {
|
} else if((revents & (POLLIN|POLLHUP)) && fd == connector->in_fd) {
|
||||||
@@ -419,7 +498,7 @@ static int ssh_connector_fd_cb(ssh_poll_handle p,
|
|||||||
* @returns Amount of data bytes consumed
|
* @returns Amount of data bytes consumed
|
||||||
*/
|
*/
|
||||||
static int ssh_connector_channel_data_cb(ssh_session session,
|
static int ssh_connector_channel_data_cb(ssh_session session,
|
||||||
ssh_channel channel,
|
UNUSED_PARAM(ssh_channel channel),
|
||||||
void *data,
|
void *data,
|
||||||
uint32_t len,
|
uint32_t len,
|
||||||
int is_stderr,
|
int is_stderr,
|
||||||
@@ -429,10 +508,6 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
|||||||
int w;
|
int w;
|
||||||
uint32_t window;
|
uint32_t window;
|
||||||
|
|
||||||
(void) session;
|
|
||||||
(void) channel;
|
|
||||||
(void) is_stderr;
|
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_TRACE,"connector data on channel");
|
SSH_LOG(SSH_LOG_TRACE,"connector data on channel");
|
||||||
|
|
||||||
if (is_stderr && !(connector->in_flags & SSH_CONNECTOR_STDERR)) {
|
if (is_stderr && !(connector->in_flags & SSH_CONNECTOR_STDERR)) {
|
||||||
@@ -484,11 +559,7 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
connector->out_wontblock = 0;
|
ssh_connector_update_flags_after_io(connector);
|
||||||
connector->in_available = 0;
|
|
||||||
if ((unsigned int)w < len) {
|
|
||||||
connector->in_available = 1;
|
|
||||||
}
|
|
||||||
ssh_connector_reset_pollevents(connector);
|
ssh_connector_reset_pollevents(connector);
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
@@ -510,8 +581,9 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
|||||||
*
|
*
|
||||||
* @returns Amount of data bytes consumed
|
* @returns Amount of data bytes consumed
|
||||||
*/
|
*/
|
||||||
static int ssh_connector_channel_write_wontblock_cb(ssh_session session,
|
static int
|
||||||
ssh_channel channel,
|
ssh_connector_channel_write_wontblock_cb(ssh_session session,
|
||||||
|
UNUSED_PARAM(ssh_channel channel),
|
||||||
uint32_t bytes,
|
uint32_t bytes,
|
||||||
void *userdata)
|
void *userdata)
|
||||||
{
|
{
|
||||||
@@ -553,8 +625,8 @@ static int ssh_connector_channel_write_wontblock_cb(ssh_session session,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
connector->in_available = 0;
|
|
||||||
connector->out_wontblock = 0;
|
ssh_connector_update_flags_after_io(connector);
|
||||||
} else {
|
} else {
|
||||||
connector->out_wontblock = 1;
|
connector->out_wontblock = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -519,9 +519,9 @@ static int ssh_retrieve_dhgroup(char *moduli_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (moduli_file != NULL)
|
if (moduli_file != NULL)
|
||||||
moduli = fopen(moduli_file, "r");
|
moduli = ssh_strict_fopen(moduli_file, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
else
|
else
|
||||||
moduli = fopen(MODULI_FILE, "r");
|
moduli = ssh_strict_fopen(MODULI_FILE, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
|
|
||||||
if (moduli == NULL) {
|
if (moduli == NULL) {
|
||||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||||
|
|||||||
@@ -407,6 +407,11 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
|||||||
struct dh_ctx *ctx = NULL;
|
struct dh_ctx *ctx = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* Cleanup any previously allocated dh_ctx */
|
||||||
|
if (crypto->dh_ctx != NULL) {
|
||||||
|
ssh_dh_cleanup(crypto);
|
||||||
|
}
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
|||||||
@@ -237,6 +237,11 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
|||||||
struct dh_ctx *ctx = NULL;
|
struct dh_ctx *ctx = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* Cleanup any previously allocated dh_ctx */
|
||||||
|
if (crypto->dh_ctx != NULL) {
|
||||||
|
ssh_dh_cleanup(crypto);
|
||||||
|
}
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(*ctx));
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
|||||||
@@ -191,6 +191,17 @@ static ssh_string ssh_ecdh_generate(ssh_session session)
|
|||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free any previously allocated privkey */
|
||||||
|
if (session->next_crypto->ecdh_privkey != NULL) {
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
|
EC_KEY_free(session->next_crypto->ecdh_privkey);
|
||||||
|
#else
|
||||||
|
EVP_PKEY_free(session->next_crypto->ecdh_privkey);
|
||||||
|
#endif
|
||||||
|
session->next_crypto->ecdh_privkey = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
session->next_crypto->ecdh_privkey = key;
|
session->next_crypto->ecdh_privkey = key;
|
||||||
return pubkey_string;
|
return pubkey_string;
|
||||||
}
|
}
|
||||||
@@ -219,6 +230,7 @@ int ssh_client_ecdh_init(ssh_session session)
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssh_string_free(session->next_crypto->ecdh_client_pubkey);
|
||||||
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
||||||
|
|
||||||
/* register the packet callbacks */
|
/* register the packet callbacks */
|
||||||
|
|||||||
@@ -101,8 +101,15 @@ int ssh_client_ecdh_init(ssh_session session)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free any previously allocated privkey */
|
||||||
|
if (session->next_crypto->ecdh_privkey != NULL) {
|
||||||
|
gcry_sexp_release(session->next_crypto->ecdh_privkey);
|
||||||
|
session->next_crypto->ecdh_privkey = NULL;
|
||||||
|
}
|
||||||
session->next_crypto->ecdh_privkey = key;
|
session->next_crypto->ecdh_privkey = key;
|
||||||
key = NULL;
|
key = NULL;
|
||||||
|
|
||||||
|
SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey);
|
||||||
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
||||||
client_pubkey = NULL;
|
client_pubkey = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ int ssh_client_ecdh_init(ssh_session session)
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free any previously allocated privkey */
|
||||||
|
if (session->next_crypto->ecdh_privkey != NULL) {
|
||||||
|
mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey);
|
||||||
|
SAFE_FREE(session->next_crypto->ecdh_privkey);
|
||||||
|
}
|
||||||
|
|
||||||
session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair));
|
session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair));
|
||||||
if (session->next_crypto->ecdh_privkey == NULL) {
|
if (session->next_crypto->ecdh_privkey == NULL) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -110,6 +116,7 @@ int ssh_client_ecdh_init(ssh_session session)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey);
|
||||||
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
||||||
client_pubkey = NULL;
|
client_pubkey = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -1487,6 +1487,8 @@ int ssh_make_sessionid(ssh_session session)
|
|||||||
ssh_log_hexdump("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
ssh_log_hexdump("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set rc for the following switch statement in case we goto error. */
|
||||||
|
rc = SSH_ERROR;
|
||||||
switch (session->next_crypto->kex_type) {
|
switch (session->next_crypto->kex_type) {
|
||||||
case SSH_KEX_DH_GROUP1_SHA1:
|
case SSH_KEX_DH_GROUP1_SHA1:
|
||||||
case SSH_KEX_DH_GROUP14_SHA1:
|
case SSH_KEX_DH_GROUP14_SHA1:
|
||||||
@@ -1546,6 +1548,7 @@ int ssh_make_sessionid(ssh_session session)
|
|||||||
session->next_crypto->secret_hash);
|
session->next_crypto->secret_hash);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* During the first kex, secret hash and session ID are equal. However, after
|
/* During the first kex, secret hash and session ID are equal. However, after
|
||||||
* a key re-exchange, a new secret hash is calculated. This hash will not replace
|
* a key re-exchange, a new secret hash is calculated. This hash will not replace
|
||||||
* but complement existing session id.
|
* but complement existing session id.
|
||||||
@@ -1554,6 +1557,7 @@ int ssh_make_sessionid(ssh_session session)
|
|||||||
session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
|
session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
|
||||||
if (session->next_crypto->session_id == NULL) {
|
if (session->next_crypto->session_id == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
|
rc = SSH_ERROR;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static struct ssh_tokens_st *ssh_get_knownhost_line(FILE **file,
|
|||||||
struct ssh_tokens_st *tokens = NULL;
|
struct ssh_tokens_st *tokens = NULL;
|
||||||
|
|
||||||
if (*file == NULL) {
|
if (*file == NULL) {
|
||||||
*file = fopen(filename,"r");
|
*file = ssh_strict_fopen(filename, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
if (*file == NULL) {
|
if (*file == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
108
src/knownhosts.c
108
src/knownhosts.c
@@ -216,11 +216,22 @@ ssh_known_hosts_entries_compare(struct ssh_knownhosts_entry *k1,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This method reads the known_hosts file referenced by the path
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Read entries from filename to provided list
|
||||||
|
*
|
||||||
|
* This method reads the known_hosts file referenced by the path
|
||||||
* in filename argument, and entries matching the match argument
|
* in filename argument, and entries matching the match argument
|
||||||
* will be added to the list in entries argument.
|
* will be added to the list in entries argument.
|
||||||
* If the entries list is NULL, it will allocate a new list. Caller
|
* If the entries list is NULL, it will allocate a new list. Caller
|
||||||
* is responsible to free it even if an error occurs.
|
* is responsible to free it even if an error occurs.
|
||||||
|
*
|
||||||
|
* @param match[in] The host name (with port) to match against
|
||||||
|
* @param filename[in] The known hosts file to parse
|
||||||
|
* @param entries[in,out] The list of entries to append matching ones
|
||||||
|
* @return `SSH_OK` on missing file or success parsing,
|
||||||
|
* `SSH_ERROR` on error
|
||||||
*/
|
*/
|
||||||
static int ssh_known_hosts_read_entries(const char *match,
|
static int ssh_known_hosts_read_entries(const char *match,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
@@ -232,7 +243,7 @@ static int ssh_known_hosts_read_entries(const char *match,
|
|||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
fp = fopen(filename, "r");
|
fp = ssh_strict_fopen(filename, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||||
SSH_LOG(SSH_LOG_TRACE, "Failed to open the known_hosts file '%s': %s",
|
SSH_LOG(SSH_LOG_TRACE, "Failed to open the known_hosts file '%s': %s",
|
||||||
@@ -346,6 +357,33 @@ static char *ssh_session_get_host_port(ssh_session session)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Free known hosts entries list
|
||||||
|
*
|
||||||
|
* @param[in] entry_list The list of ssh_knownhosts_entry items
|
||||||
|
*/
|
||||||
|
static void ssh_knownhosts_entries_free(struct ssh_list *entry_list)
|
||||||
|
{
|
||||||
|
struct ssh_iterator *it = NULL;
|
||||||
|
|
||||||
|
if (entry_list == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (it = ssh_list_get_iterator(entry_list);
|
||||||
|
it != NULL;
|
||||||
|
it = ssh_list_get_iterator(entry_list)) {
|
||||||
|
struct ssh_knownhosts_entry *entry = NULL;
|
||||||
|
|
||||||
|
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
||||||
|
ssh_knownhosts_entry_free(entry);
|
||||||
|
ssh_list_remove(entry_list, it);
|
||||||
|
}
|
||||||
|
ssh_list_free(entry_list);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
* @brief Check which host keys should be preferred for the session.
|
* @brief Check which host keys should be preferred for the session.
|
||||||
*
|
*
|
||||||
* This checks the known_hosts file to find out which algorithms should be
|
* This checks the known_hosts file to find out which algorithms should be
|
||||||
@@ -376,25 +414,23 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
host_port = ssh_session_get_host_port(session);
|
|
||||||
if (host_port == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
list = ssh_list_new();
|
list = ssh_list_new();
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
SAFE_FREE(host_port);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
host_port = ssh_session_get_host_port(session);
|
||||||
|
if (host_port == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
rc = ssh_known_hosts_read_entries(host_port,
|
rc = ssh_known_hosts_read_entries(host_port,
|
||||||
session->opts.knownhosts,
|
session->opts.knownhosts,
|
||||||
&entry_list);
|
&entry_list);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
ssh_list_free(entry_list);
|
SAFE_FREE(host_port);
|
||||||
ssh_list_free(list);
|
goto error;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_known_hosts_read_entries(host_port,
|
rc = ssh_known_hosts_read_entries(host_port,
|
||||||
@@ -402,21 +438,16 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
|||||||
&entry_list);
|
&entry_list);
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
ssh_list_free(entry_list);
|
goto error;
|
||||||
ssh_list_free(list);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry_list == NULL) {
|
if (entry_list == NULL) {
|
||||||
ssh_list_free(list);
|
goto error;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
count = ssh_list_count(entry_list);
|
count = ssh_list_count(entry_list);
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
ssh_list_free(list);
|
goto error;
|
||||||
ssh_list_free(entry_list);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (it = ssh_list_get_iterator(entry_list);
|
for (it = ssh_list_get_iterator(entry_list);
|
||||||
@@ -460,6 +491,7 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
|||||||
|
|
||||||
return list;
|
return list;
|
||||||
error:
|
error:
|
||||||
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
ssh_list_free(list);
|
ssh_list_free(list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -511,6 +543,7 @@ static const char *ssh_known_host_sigs_from_hostkey_type(enum ssh_keytypes_e typ
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
*
|
||||||
* @brief Get the host keys algorithms identifiers from the known_hosts files
|
* @brief Get the host keys algorithms identifiers from the known_hosts files
|
||||||
*
|
*
|
||||||
* This expands the signatures types that can be generated from the keys types
|
* This expands the signatures types that can be generated from the keys types
|
||||||
@@ -555,7 +588,7 @@ char *ssh_known_hosts_get_algorithms_names(ssh_session session)
|
|||||||
&entry_list);
|
&entry_list);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
ssh_list_free(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,7 +597,7 @@ char *ssh_known_hosts_get_algorithms_names(ssh_session session)
|
|||||||
&entry_list);
|
&entry_list);
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
ssh_list_free(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,7 +838,6 @@ out:
|
|||||||
enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
||||||
{
|
{
|
||||||
struct ssh_list *entry_list = NULL;
|
struct ssh_list *entry_list = NULL;
|
||||||
struct ssh_iterator *it = NULL;
|
|
||||||
char *host_port = NULL;
|
char *host_port = NULL;
|
||||||
bool global_known_hosts_found = false;
|
bool global_known_hosts_found = false;
|
||||||
bool known_hosts_found = false;
|
bool known_hosts_found = false;
|
||||||
@@ -866,7 +898,7 @@ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
|||||||
&entry_list);
|
&entry_list);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
ssh_list_free(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
return SSH_KNOWN_HOSTS_ERROR;
|
return SSH_KNOWN_HOSTS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -877,7 +909,7 @@ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
|||||||
&entry_list);
|
&entry_list);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
SAFE_FREE(host_port);
|
SAFE_FREE(host_port);
|
||||||
ssh_list_free(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
return SSH_KNOWN_HOSTS_ERROR;
|
return SSH_KNOWN_HOSTS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -889,16 +921,7 @@ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
|||||||
return SSH_KNOWN_HOSTS_UNKNOWN;
|
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (it = ssh_list_get_iterator(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
it != NULL;
|
|
||||||
it = ssh_list_get_iterator(entry_list)) {
|
|
||||||
struct ssh_knownhosts_entry *entry = NULL;
|
|
||||||
|
|
||||||
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
|
||||||
ssh_knownhosts_entry_free(entry);
|
|
||||||
ssh_list_remove(entry_list, it);
|
|
||||||
}
|
|
||||||
ssh_list_free(entry_list);
|
|
||||||
|
|
||||||
return SSH_KNOWN_HOSTS_OK;
|
return SSH_KNOWN_HOSTS_OK;
|
||||||
}
|
}
|
||||||
@@ -1085,13 +1108,13 @@ ssh_known_hosts_check_server_key(const char *hosts_entry,
|
|||||||
filename,
|
filename,
|
||||||
&entry_list);
|
&entry_list);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
ssh_list_free(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
return SSH_KNOWN_HOSTS_UNKNOWN;
|
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
it = ssh_list_get_iterator(entry_list);
|
it = ssh_list_get_iterator(entry_list);
|
||||||
if (it == NULL) {
|
if (it == NULL) {
|
||||||
ssh_list_free(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
return SSH_KNOWN_HOSTS_UNKNOWN;
|
return SSH_KNOWN_HOSTS_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1121,16 +1144,7 @@ ssh_known_hosts_check_server_key(const char *hosts_entry,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (it = ssh_list_get_iterator(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
it != NULL;
|
|
||||||
it = ssh_list_get_iterator(entry_list)) {
|
|
||||||
struct ssh_knownhosts_entry *entry = NULL;
|
|
||||||
|
|
||||||
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
|
|
||||||
ssh_knownhosts_entry_free(entry);
|
|
||||||
ssh_list_remove(entry_list, it);
|
|
||||||
}
|
|
||||||
ssh_list_free(entry_list);
|
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
@@ -1202,6 +1216,8 @@ ssh_session_get_known_hosts_entry(ssh_session session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
* @brief Get the known_hosts entry for the current connected session
|
* @brief Get the known_hosts entry for the current connected session
|
||||||
* from the given known_hosts file.
|
* from the given known_hosts file.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -49,8 +49,9 @@
|
|||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/hmac.h>
|
#include <openssl/hmac.h>
|
||||||
#else
|
#else
|
||||||
#include <openssl/param_build.h>
|
|
||||||
#include <openssl/core_names.h>
|
#include <openssl/core_names.h>
|
||||||
|
#include <openssl/param_build.h>
|
||||||
|
#include <openssl/provider.h>
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER)
|
#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER)
|
||||||
@@ -96,7 +97,37 @@ void ssh_reseed(void){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER)
|
#if defined(WITH_PKCS11_URI)
|
||||||
|
#if defined(WITH_PKCS11_PROVIDER)
|
||||||
|
static OSSL_PROVIDER *provider = NULL;
|
||||||
|
static bool pkcs11_provider_failed = false;
|
||||||
|
|
||||||
|
int pki_load_pkcs11_provider(void)
|
||||||
|
{
|
||||||
|
if (OSSL_PROVIDER_available(NULL, "pkcs11") == 1) {
|
||||||
|
/* the provider is already available.
|
||||||
|
* Loaded through a configuration file? */
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkcs11_provider_failed) {
|
||||||
|
/* the loading failed previously -- do not retry */
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
provider = OSSL_PROVIDER_try_load(NULL, "pkcs11", 1);
|
||||||
|
if (provider != NULL) {
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"Failed to load the pkcs11 provider: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
/* Do not attempt to load it again */
|
||||||
|
pkcs11_provider_failed = true;
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
#else
|
||||||
static ENGINE *engine = NULL;
|
static ENGINE *engine = NULL;
|
||||||
|
|
||||||
ENGINE *pki_get_engine(void)
|
ENGINE *pki_get_engine(void)
|
||||||
@@ -128,7 +159,8 @@ ENGINE *pki_get_engine(void)
|
|||||||
}
|
}
|
||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
#endif /* defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) */
|
#endif /* defined(WITH_PKCS11_PROVIDER) */
|
||||||
|
#endif /* defined(WITH_PKCS11_URI) */
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_EVP_KDF_CTX
|
#ifdef HAVE_OPENSSL_EVP_KDF_CTX
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
@@ -1402,6 +1434,14 @@ void ssh_crypto_finalize(void)
|
|||||||
engine = NULL;
|
engine = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(WITH_PKCS11_URI)
|
||||||
|
#if defined(WITH_PKCS11_PROVIDER)
|
||||||
|
if (provider != NULL) {
|
||||||
|
OSSL_PROVIDER_unload(provider);
|
||||||
|
provider = NULL;
|
||||||
|
}
|
||||||
|
#endif /* WITH_PKCS11_PROVIDER */
|
||||||
|
#endif /* WITH_PKCS11_URI */
|
||||||
|
|
||||||
libcrypto_initialized = 0;
|
libcrypto_initialized = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
123
src/match.c
123
src/match.c
@@ -53,87 +53,72 @@
|
|||||||
|
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
|
|
||||||
#define MAX_MATCH_RECURSION 16
|
/**
|
||||||
|
* @brief Compare a string with a pattern containing wildcards `*` and `?`
|
||||||
/*
|
*
|
||||||
* Returns true if the given string matches the pattern (which may contain ?
|
* This function is an iterative replacement for the previously recursive
|
||||||
* and * as wildcards), and zero if it does not match.
|
* implementation to avoid exponential complexity (DoS) with specific patterns.
|
||||||
|
*
|
||||||
|
* @param[in] s The string to match.
|
||||||
|
* @param[in] pattern The pattern to match against.
|
||||||
|
*
|
||||||
|
* @return 1 if the pattern matches, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
static int match_pattern(const char *s, const char *pattern, size_t limit)
|
static int match_pattern(const char *s, const char *pattern)
|
||||||
{
|
{
|
||||||
bool had_asterisk = false;
|
const char *s_star = NULL; /* Position in s when last `*` was met */
|
||||||
|
const char *p_star = NULL; /* Position in pattern after last `*` */
|
||||||
|
|
||||||
if (s == NULL || pattern == NULL || limit <= 0) {
|
if (s == NULL || pattern == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
while (*s) {
|
||||||
/* If at end of pattern, accept if also at end of string. */
|
/* Case 1: Exact match or '?' wildcard */
|
||||||
if (*pattern == '\0') {
|
if (*pattern == *s || *pattern == '?') {
|
||||||
return (*s == '\0');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip all the asterisks and adjacent question marks */
|
|
||||||
while (*pattern == '*' || (had_asterisk && *pattern == '?')) {
|
|
||||||
if (*pattern == '*') {
|
|
||||||
had_asterisk = true;
|
|
||||||
}
|
|
||||||
pattern++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (had_asterisk) {
|
|
||||||
/* If at end of pattern, accept immediately. */
|
|
||||||
if (!*pattern)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* If next character in pattern is known, optimize. */
|
|
||||||
if (*pattern != '?') {
|
|
||||||
/*
|
|
||||||
* Look instances of the next character in
|
|
||||||
* pattern, and try to match starting from
|
|
||||||
* those.
|
|
||||||
*/
|
|
||||||
for (; *s; s++)
|
|
||||||
if (*s == *pattern && match_pattern(s + 1, pattern + 1, limit - 1)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* Failed. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Move ahead one character at a time and try to
|
|
||||||
* match at each position.
|
|
||||||
*/
|
|
||||||
for (; *s; s++) {
|
|
||||||
if (match_pattern(s, pattern, limit - 1)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Failed. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* There must be at least one more character in the string.
|
|
||||||
* If we are at the end, fail.
|
|
||||||
*/
|
|
||||||
if (!*s) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the next character of the string is acceptable. */
|
|
||||||
if (*pattern != '?' && *pattern != *s) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move to the next character, both in string and in pattern. */
|
|
||||||
s++;
|
s++;
|
||||||
pattern++;
|
pattern++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTREACHED */
|
/* Case 2: '*' wildcard */
|
||||||
|
if (*pattern == '*') {
|
||||||
|
/* Record the position of the star and the current string position.
|
||||||
|
* We optimistically assume * matches 0 characters first.
|
||||||
|
*/
|
||||||
|
p_star = ++pattern;
|
||||||
|
s_star = s;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case 3: Mismatch */
|
||||||
|
if (p_star) {
|
||||||
|
/* If we have seen a star previously, backtrack.
|
||||||
|
* We restore the pattern to just after the star,
|
||||||
|
* but advance the string position (consume one more char for the
|
||||||
|
* star).
|
||||||
|
* No need to backtrack to previous stars as any match of the last
|
||||||
|
* star could be eaten the same way by the previous star.
|
||||||
|
*/
|
||||||
|
pattern = p_star;
|
||||||
|
s = ++s_star;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case 4: Mismatch and no star to backtrack to */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle trailing stars in the pattern
|
||||||
|
* (e.g., pattern "abc*" matching "abc") */
|
||||||
|
while (*pattern == '*') {
|
||||||
|
pattern++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we reached the end of the pattern, it's a match */
|
||||||
|
return (*pattern == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tries to match the string against the comma-separated sequence of subpatterns
|
* Tries to match the string against the comma-separated sequence of subpatterns
|
||||||
* (each possibly preceded by ! to indicate negation).
|
* (each possibly preceded by ! to indicate negation).
|
||||||
@@ -182,7 +167,7 @@ int match_pattern_list(const char *string, const char *pattern,
|
|||||||
sub[subi] = '\0';
|
sub[subi] = '\0';
|
||||||
|
|
||||||
/* Try to match the subpattern against the string. */
|
/* Try to match the subpattern against the string. */
|
||||||
if (match_pattern(string, sub, MAX_MATCH_RECURSION)) {
|
if (match_pattern(string, sub)) {
|
||||||
if (negated) {
|
if (negated) {
|
||||||
return -1; /* Negative */
|
return -1; /* Negative */
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
76
src/misc.c
76
src/misc.c
@@ -37,6 +37,7 @@
|
|||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -459,7 +460,7 @@ char *ssh_get_hexa(const unsigned char *what, size_t len)
|
|||||||
size_t i;
|
size_t i;
|
||||||
size_t hlen = len * 3;
|
size_t hlen = len * 3;
|
||||||
|
|
||||||
if (len > (UINT_MAX - 1) / 3) {
|
if (what == NULL || len < 1 || len > (UINT_MAX - 1) / 3) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2244,4 +2245,77 @@ ssh_libssh_proxy_jumps(void)
|
|||||||
return !(t != NULL && t[0] == '1');
|
return !(t != NULL && t[0] == '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Safely open a file containing some configuration.
|
||||||
|
*
|
||||||
|
* Runs checks if the file can be used as some configuration file (is regular
|
||||||
|
* file and is not too large). If so, returns the opened file (for reading).
|
||||||
|
* Otherwise logs error and returns `NULL`.
|
||||||
|
*
|
||||||
|
* @param filename The path to the file to open.
|
||||||
|
* @param max_file_size Maximum file size that is accepted.
|
||||||
|
*
|
||||||
|
* @returns the opened file or `NULL` on error.
|
||||||
|
*/
|
||||||
|
FILE *ssh_strict_fopen(const char *filename, size_t max_file_size)
|
||||||
|
{
|
||||||
|
FILE *f = NULL;
|
||||||
|
struct stat sb;
|
||||||
|
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||||
|
int r, fd;
|
||||||
|
|
||||||
|
/* open first to avoid TOCTOU */
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
SSH_LOG(SSH_LOG_RARE,
|
||||||
|
"Failed to open a file %s for reading: %s",
|
||||||
|
filename,
|
||||||
|
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the file is sensible for a configuration file */
|
||||||
|
r = fstat(fd, &sb);
|
||||||
|
if (r != 0) {
|
||||||
|
SSH_LOG(SSH_LOG_RARE,
|
||||||
|
"Failed to stat %s: %s",
|
||||||
|
filename,
|
||||||
|
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((sb.st_mode & S_IFMT) != S_IFREG) {
|
||||||
|
SSH_LOG(SSH_LOG_RARE,
|
||||||
|
"The file %s is not a regular file: skipping",
|
||||||
|
filename);
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size_t)sb.st_size > max_file_size) {
|
||||||
|
SSH_LOG(SSH_LOG_RARE,
|
||||||
|
"The file %s is too large (%jd MB > %zu MB): skipping",
|
||||||
|
filename,
|
||||||
|
(intmax_t)sb.st_size / 1024 / 1024,
|
||||||
|
max_file_size / 1024 / 1024);
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = fdopen(fd, "r");
|
||||||
|
if (f == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_RARE,
|
||||||
|
"Failed to open a file %s for reading: %s",
|
||||||
|
filename,
|
||||||
|
ssh_strerror(r, err_msg, SSH_ERRNO_MSG_MAX));
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the flcose() will close also the underlying fd */
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
@@ -861,7 +861,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|||||||
SAFE_FREE(session->opts.global_knownhosts);
|
SAFE_FREE(session->opts.global_knownhosts);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
session->opts.global_knownhosts =
|
session->opts.global_knownhosts =
|
||||||
strdup("/etc/ssh/ssh_known_hosts");
|
strdup(GLOBAL_CONF_DIR "/ssh_known_hosts");
|
||||||
if (session->opts.global_knownhosts == NULL) {
|
if (session->opts.global_knownhosts == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1900,7 +1900,7 @@ int ssh_options_apply(ssh_session session)
|
|||||||
|
|
||||||
if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS) == 0) {
|
if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS) == 0) {
|
||||||
if (session->opts.global_knownhosts == NULL) {
|
if (session->opts.global_knownhosts == NULL) {
|
||||||
tmp = strdup("/etc/ssh/ssh_known_hosts");
|
tmp = strdup(GLOBAL_CONF_DIR "/ssh_known_hosts");
|
||||||
} else {
|
} else {
|
||||||
tmp = ssh_path_expand_escape(session,
|
tmp = ssh_path_expand_escape(session,
|
||||||
session->opts.global_knownhosts);
|
session->opts.global_knownhosts);
|
||||||
|
|||||||
@@ -294,6 +294,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
* or session_state == SSH_SESSION_STATE_INITIAL_KEX
|
* or session_state == SSH_SESSION_STATE_INITIAL_KEX
|
||||||
* - dh_handshake_state == DH_STATE_INIT
|
* - dh_handshake_state == DH_STATE_INIT
|
||||||
* or dh_handshake_state == DH_STATE_INIT_SENT (re-exchange)
|
* or dh_handshake_state == DH_STATE_INIT_SENT (re-exchange)
|
||||||
|
* or dh_handshake_state == DH_STATE_REQUEST_SENT (dh-gex)
|
||||||
* or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
|
* or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
|
||||||
*
|
*
|
||||||
* Transitions:
|
* Transitions:
|
||||||
@@ -313,6 +314,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
|||||||
|
|
||||||
if ((session->dh_handshake_state != DH_STATE_INIT) &&
|
if ((session->dh_handshake_state != DH_STATE_INIT) &&
|
||||||
(session->dh_handshake_state != DH_STATE_INIT_SENT) &&
|
(session->dh_handshake_state != DH_STATE_INIT_SENT) &&
|
||||||
|
(session->dh_handshake_state != DH_STATE_REQUEST_SENT) &&
|
||||||
(session->dh_handshake_state != DH_STATE_FINISHED))
|
(session->dh_handshake_state != DH_STATE_FINISHED))
|
||||||
{
|
{
|
||||||
rc = SSH_PACKET_DENIED;
|
rc = SSH_PACKET_DENIED;
|
||||||
|
|||||||
28
src/pki.c
28
src/pki.c
@@ -701,8 +701,8 @@ int ssh_key_cmp(const ssh_key k1,
|
|||||||
ssh_buffer_get_len(k1->cert));
|
ssh_buffer_get_len(k1->cert));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k1->type == SSH_KEYTYPE_ED25519 ||
|
if (ssh_key_type_plain(k1->type) == SSH_KEYTYPE_ED25519 ||
|
||||||
k1->type == SSH_KEYTYPE_SK_ED25519) {
|
ssh_key_type_plain(k1->type) == SSH_KEYTYPE_SK_ED25519) {
|
||||||
return pki_ed25519_key_cmp(k1, k2, what);
|
return pki_ed25519_key_cmp(k1, k2, what);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1621,14 +1621,16 @@ fail:
|
|||||||
/**
|
/**
|
||||||
* @brief Import a base64 formatted public key from a memory c-string.
|
* @brief Import a base64 formatted public key from a memory c-string.
|
||||||
*
|
*
|
||||||
* @param[in] b64_key The base64 key to format.
|
* Note that the public key is just the base64 part (without the key
|
||||||
*
|
* type prefix and comment suffix you can find in the OpenSSH public
|
||||||
* @param[in] type The type of the key to format.
|
* key file or known_hosts file).
|
||||||
*
|
*
|
||||||
|
* @param[in] b64_key The base64 key to import.
|
||||||
|
* @param[in] type The type of the key to import.
|
||||||
* @param[out] pkey A pointer where the allocated key can be stored. You
|
* @param[out] pkey A pointer where the allocated key can be stored. You
|
||||||
* need to free the memory using ssh_key_free().
|
* need to free the memory using ssh_key_free().
|
||||||
*
|
*
|
||||||
* @return SSH_OK on success, SSH_ERROR on error.
|
* @return `SSH_OK` on success, `SSH_ERROR` on error.
|
||||||
*
|
*
|
||||||
* @see ssh_key_free()
|
* @see ssh_key_free()
|
||||||
*/
|
*/
|
||||||
@@ -1929,14 +1931,16 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
|
|||||||
/**
|
/**
|
||||||
* @brief Import a base64 formatted certificate from a memory c-string.
|
* @brief Import a base64 formatted certificate from a memory c-string.
|
||||||
*
|
*
|
||||||
* @param[in] b64_cert The base64 cert to format.
|
* Note that the certificate is just the base64 part (without the key
|
||||||
|
* type prefix and comment suffix you can find in the OpenSSH certificate
|
||||||
|
* file).
|
||||||
*
|
*
|
||||||
* @param[in] type The type of the cert to format.
|
* @param[in] b64_cert The base64 cert to import.
|
||||||
|
* @param[in] type The type of the cert to import.
|
||||||
|
* @param[out] pkey A pointer where the allocated certificate can be stored.
|
||||||
|
* You need to free the memory using ssh_key_free().
|
||||||
*
|
*
|
||||||
* @param[out] pkey A pointer where the allocated key can be stored. You
|
* @return `SSH_OK` on success, `SSH_ERROR` on error.
|
||||||
* need to free the memory using ssh_key_free().
|
|
||||||
*
|
|
||||||
* @return SSH_OK on success, SSH_ERROR on error.
|
|
||||||
*
|
*
|
||||||
* @see ssh_key_free()
|
* @see ssh_key_free()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -46,7 +46,6 @@
|
|||||||
#include <openssl/param_build.h>
|
#include <openssl/param_build.h>
|
||||||
#if defined(WITH_PKCS11_URI) && defined(WITH_PKCS11_PROVIDER)
|
#if defined(WITH_PKCS11_URI) && defined(WITH_PKCS11_PROVIDER)
|
||||||
#include <openssl/store.h>
|
#include <openssl/store.h>
|
||||||
#include <openssl/provider.h>
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
@@ -1429,6 +1428,8 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* The buffer will contain sensitive information. Make sure it is erased */
|
||||||
|
ssh_buffer_set_secure(buffer);
|
||||||
|
|
||||||
if (key->cert != NULL) {
|
if (key->cert != NULL) {
|
||||||
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
||||||
@@ -2719,9 +2720,6 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_PKCS11_URI
|
#ifdef WITH_PKCS11_URI
|
||||||
#ifdef WITH_PKCS11_PROVIDER
|
|
||||||
static bool pkcs11_provider_failed = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@@ -2787,20 +2785,11 @@ int pki_uri_import(const char *uri_name,
|
|||||||
|
|
||||||
/* The provider can be either configured in openssl.cnf or dynamically
|
/* The provider can be either configured in openssl.cnf or dynamically
|
||||||
* loaded, assuming it does not need any special configuration */
|
* loaded, assuming it does not need any special configuration */
|
||||||
if (OSSL_PROVIDER_available(NULL, "pkcs11") == 0 &&
|
rv = pki_load_pkcs11_provider();
|
||||||
!pkcs11_provider_failed) {
|
if (rv != SSH_OK) {
|
||||||
OSSL_PROVIDER *pkcs11_provider = NULL;
|
SSH_LOG(SSH_LOG_TRACE, "Failed to load or initialize pkcs11 provider");
|
||||||
|
|
||||||
pkcs11_provider = OSSL_PROVIDER_try_load(NULL, "pkcs11", 1);
|
|
||||||
if (pkcs11_provider == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
|
||||||
"Failed to initialize provider: %s",
|
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
/* Do not attempt to load it again */
|
|
||||||
pkcs11_provider_failed = true;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
store = OSSL_STORE_open(uri_name, NULL, NULL, NULL, NULL);
|
store = OSSL_STORE_open(uri_name, NULL, NULL, NULL, NULL);
|
||||||
if (store == NULL) {
|
if (store == NULL) {
|
||||||
|
|||||||
@@ -1355,7 +1355,7 @@ int pki_key_compare(const ssh_key k1,
|
|||||||
case SSH_KEYTYPE_SK_ED25519:
|
case SSH_KEYTYPE_SK_ED25519:
|
||||||
case SSH_KEYTYPE_SK_ED25519_CERT01:
|
case SSH_KEYTYPE_SK_ED25519_CERT01:
|
||||||
/* ed25519 keys handled globally */
|
/* ed25519 keys handled globally */
|
||||||
return 0;
|
return 1;
|
||||||
case SSH_KEYTYPE_ECDSA_P256:
|
case SSH_KEYTYPE_ECDSA_P256:
|
||||||
case SSH_KEYTYPE_ECDSA_P256_CERT01:
|
case SSH_KEYTYPE_ECDSA_P256_CERT01:
|
||||||
case SSH_KEYTYPE_ECDSA_P384:
|
case SSH_KEYTYPE_ECDSA_P384:
|
||||||
@@ -1409,6 +1409,8 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* The buffer will contain sensitive information. Make sure it is erased */
|
||||||
|
ssh_buffer_set_secure(buffer);
|
||||||
|
|
||||||
if (key->cert != NULL) {
|
if (key->cert != NULL) {
|
||||||
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
||||||
|
|||||||
@@ -782,7 +782,7 @@ int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what)
|
|||||||
case SSH_KEYTYPE_ED25519:
|
case SSH_KEYTYPE_ED25519:
|
||||||
case SSH_KEYTYPE_SK_ED25519:
|
case SSH_KEYTYPE_SK_ED25519:
|
||||||
/* ed25519 keys handled globally */
|
/* ed25519 keys handled globally */
|
||||||
rc = 0;
|
rc = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rc = 1;
|
rc = 1;
|
||||||
@@ -864,7 +864,12 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
ssh_string type_s = NULL;
|
ssh_string type_s = NULL;
|
||||||
ssh_string e = NULL;
|
ssh_string e = NULL;
|
||||||
ssh_string n = NULL;
|
ssh_string n = NULL;
|
||||||
|
ssh_string p = NULL;
|
||||||
|
ssh_string q = NULL;
|
||||||
|
ssh_string d = NULL;
|
||||||
|
ssh_string iqmp = NULL;
|
||||||
ssh_string str = NULL;
|
ssh_string str = NULL;
|
||||||
|
int rc;
|
||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
mbedtls_mpi E = {0};
|
mbedtls_mpi E = {0};
|
||||||
mbedtls_mpi N = {0};
|
mbedtls_mpi N = {0};
|
||||||
@@ -872,18 +877,21 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
mbedtls_mpi IQMP = {0};
|
mbedtls_mpi IQMP = {0};
|
||||||
mbedtls_mpi P = {0};
|
mbedtls_mpi P = {0};
|
||||||
mbedtls_mpi Q = {0};
|
mbedtls_mpi Q = {0};
|
||||||
#endif
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
|
||||||
mbedtls_mpi_init(&E);
|
mbedtls_mpi_init(&E);
|
||||||
mbedtls_mpi_init(&N);
|
mbedtls_mpi_init(&N);
|
||||||
|
mbedtls_mpi_init(&D);
|
||||||
|
mbedtls_mpi_init(&IQMP);
|
||||||
|
mbedtls_mpi_init(&P);
|
||||||
|
mbedtls_mpi_init(&Q);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
buffer = ssh_buffer_new();
|
buffer = ssh_buffer_new();
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* The buffer will contain sensitive information. Make sure it is erased */
|
||||||
|
ssh_buffer_set_secure(buffer);
|
||||||
|
|
||||||
if (key->cert != NULL) {
|
if (key->cert != NULL) {
|
||||||
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
rc = ssh_buffer_add_buffer(buffer, key->cert);
|
||||||
@@ -910,159 +918,125 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
|
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case SSH_KEYTYPE_RSA: {
|
case SSH_KEYTYPE_RSA: {
|
||||||
mbedtls_rsa_context *rsa;
|
mbedtls_rsa_context *rsa = NULL;
|
||||||
|
mbedtls_mpi *E_ptr = NULL, *N_ptr = NULL;
|
||||||
|
|
||||||
if (mbedtls_pk_can_do(key->pk, MBEDTLS_PK_RSA) == 0) {
|
if (mbedtls_pk_can_do(key->pk, MBEDTLS_PK_RSA) == 0) {
|
||||||
SSH_BUFFER_FREE(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rsa = mbedtls_pk_rsa(*key->pk);
|
rsa = mbedtls_pk_rsa(*key->pk);
|
||||||
|
|
||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
rc = mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, &E);
|
rc = mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, &E);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = ssh_make_bignum_string(&E);
|
E_ptr = &E;
|
||||||
if (e == NULL) {
|
N_ptr = &N;
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = ssh_make_bignum_string(&N);
|
|
||||||
if (n == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
e = ssh_make_bignum_string(&rsa->E);
|
E_ptr = &rsa->E;
|
||||||
|
N_ptr = &rsa->N;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
e = ssh_make_bignum_string(E_ptr);
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = ssh_make_bignum_string(&rsa->N);
|
n = ssh_make_bignum_string(N_ptr);
|
||||||
if (n == NULL) {
|
if (n == NULL) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (type == SSH_KEY_PUBLIC) {
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
/* The N and E parts are swapped in the public key export ! */
|
/* The N and E parts are swapped in the public key export ! */
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, e);
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, n);
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
} else if (type == SSH_KEY_PRIVATE) {
|
} else if (type == SSH_KEY_PRIVATE) {
|
||||||
ssh_string p = NULL;
|
mbedtls_mpi *P_ptr = NULL, *Q_ptr = NULL, *D_ptr = NULL;
|
||||||
ssh_string q = NULL;
|
mbedtls_mpi *IQMP_ptr = NULL;
|
||||||
ssh_string d = NULL;
|
|
||||||
ssh_string iqmp = NULL;
|
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, n);
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, e);
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
rc = mbedtls_rsa_export(rsa, NULL, &P, &Q, &D, NULL);
|
rc = mbedtls_rsa_export(rsa, NULL, &P, &Q, &D, NULL);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = ssh_make_bignum_string(&P);
|
|
||||||
if (p == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
q = ssh_make_bignum_string(&Q);
|
|
||||||
if (q == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
d = ssh_make_bignum_string(&D);
|
|
||||||
if (d == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = mbedtls_rsa_export_crt(rsa, NULL, NULL, &IQMP);
|
rc = mbedtls_rsa_export_crt(rsa, NULL, NULL, &IQMP);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
iqmp = ssh_make_bignum_string(&IQMP);
|
|
||||||
if (iqmp == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
P_ptr = &P;
|
||||||
|
Q_ptr = &Q;
|
||||||
|
D_ptr = &D;
|
||||||
|
IQMP_ptr = &IQMP;
|
||||||
#else
|
#else
|
||||||
p = ssh_make_bignum_string(&rsa->P);
|
P_ptr = &rsa->P;
|
||||||
if (p == NULL) {
|
Q_ptr = &rsa->Q;
|
||||||
goto fail;
|
D_ptr = &rsa->D;
|
||||||
}
|
IQMP_ptr = &rsa->QP;
|
||||||
|
|
||||||
q = ssh_make_bignum_string(&rsa->Q);
|
|
||||||
if (q == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
d = ssh_make_bignum_string(&rsa->D);
|
|
||||||
if (d == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
iqmp = ssh_make_bignum_string(&rsa->QP);
|
|
||||||
if (iqmp == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
p = ssh_make_bignum_string(P_ptr);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = ssh_make_bignum_string(Q_ptr);
|
||||||
|
if (q == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = ssh_make_bignum_string(D_ptr);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
iqmp = ssh_make_bignum_string(IQMP_ptr);
|
||||||
|
if (iqmp == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, d);
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, iqmp);
|
rc = ssh_buffer_add_ssh_string(buffer, iqmp);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, p);
|
rc = ssh_buffer_add_ssh_string(buffer, p);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, q);
|
rc = ssh_buffer_add_ssh_string(buffer, q);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_burn(d);
|
|
||||||
SSH_STRING_FREE(d);
|
|
||||||
d = NULL;
|
|
||||||
ssh_string_burn(iqmp);
|
|
||||||
SSH_STRING_FREE(iqmp);
|
|
||||||
iqmp = NULL;
|
|
||||||
ssh_string_burn(p);
|
|
||||||
SSH_STRING_FREE(p);
|
|
||||||
p = NULL;
|
|
||||||
ssh_string_burn(q);
|
|
||||||
SSH_STRING_FREE(q);
|
|
||||||
q = NULL;
|
|
||||||
}
|
}
|
||||||
ssh_string_burn(e);
|
|
||||||
SSH_STRING_FREE(e);
|
|
||||||
e = NULL;
|
|
||||||
ssh_string_burn(n);
|
|
||||||
SSH_STRING_FREE(n);
|
|
||||||
n = NULL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SSH_KEYTYPE_ECDSA_P256:
|
case SSH_KEYTYPE_ECDSA_P256:
|
||||||
@@ -1093,37 +1067,27 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, e);
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_burn(e);
|
|
||||||
SSH_STRING_FREE(e);
|
|
||||||
e = NULL;
|
|
||||||
|
|
||||||
if (type == SSH_KEY_PRIVATE) {
|
if (type == SSH_KEY_PRIVATE) {
|
||||||
ssh_string d = NULL;
|
|
||||||
d = ssh_make_bignum_string(&key->ecdsa->MBEDTLS_PRIVATE(d));
|
d = ssh_make_bignum_string(&key->ecdsa->MBEDTLS_PRIVATE(d));
|
||||||
|
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
SSH_BUFFER_FREE(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
return NULL;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, d);
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string_burn(d);
|
|
||||||
SSH_STRING_FREE(d);
|
|
||||||
d = NULL;
|
|
||||||
} else if (key->type == SSH_KEYTYPE_SK_ECDSA) {
|
} else if (key->type == SSH_KEYTYPE_SK_ECDSA) {
|
||||||
/* public key can contain certificate sk information */
|
/* public key can contain certificate sk information */
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_ED25519:
|
case SSH_KEYTYPE_ED25519:
|
||||||
@@ -1131,57 +1095,63 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
if (type == SSH_KEY_PUBLIC) {
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
/* public key can contain certificate sk information */
|
/* public key can contain certificate sk information */
|
||||||
if (key->type == SSH_KEYTYPE_SK_ED25519) {
|
if (key->type == SSH_KEYTYPE_SK_ED25519) {
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = pki_ed25519_private_key_to_blob(buffer, key);
|
rc = pki_ed25519_private_key_to_blob(buffer, key);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
makestring:
|
makestring:
|
||||||
str = ssh_string_new(ssh_buffer_get_len(buffer));
|
str = ssh_string_new(ssh_buffer_get_len(buffer));
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_string_fill(str, ssh_buffer_get(buffer),
|
rc = ssh_string_fill(str,
|
||||||
|
ssh_buffer_get(buffer),
|
||||||
ssh_buffer_get_len(buffer));
|
ssh_buffer_get_len(buffer));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSH_BUFFER_FREE(buffer);
|
|
||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
|
||||||
mbedtls_mpi_free(&N);
|
|
||||||
mbedtls_mpi_free(&E);
|
|
||||||
#endif
|
|
||||||
return str;
|
|
||||||
fail:
|
|
||||||
SSH_BUFFER_FREE(buffer);
|
|
||||||
ssh_string_burn(str);
|
ssh_string_burn(str);
|
||||||
SSH_STRING_FREE(str);
|
SSH_STRING_FREE(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
SSH_BUFFER_FREE(buffer);
|
||||||
ssh_string_burn(e);
|
ssh_string_burn(e);
|
||||||
SSH_STRING_FREE(e);
|
SSH_STRING_FREE(e);
|
||||||
ssh_string_burn(n);
|
ssh_string_burn(n);
|
||||||
SSH_STRING_FREE(n);
|
SSH_STRING_FREE(n);
|
||||||
|
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 MBEDTLS_VERSION_MAJOR > 2
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
mbedtls_mpi_free(&N);
|
mbedtls_mpi_free(&N);
|
||||||
mbedtls_mpi_free(&E);
|
mbedtls_mpi_free(&E);
|
||||||
|
mbedtls_mpi_free(&D);
|
||||||
|
mbedtls_mpi_free(&IQMP);
|
||||||
|
mbedtls_mpi_free(&P);
|
||||||
|
mbedtls_mpi_free(&Q);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_string pki_signature_to_blob(const ssh_signature sig)
|
ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||||
|
|||||||
18
src/poll.c
18
src/poll.c
@@ -422,7 +422,7 @@ void ssh_poll_set_events(ssh_poll_handle p, short events)
|
|||||||
{
|
{
|
||||||
p->events = events;
|
p->events = events;
|
||||||
if (p->ctx != NULL) {
|
if (p->ctx != NULL) {
|
||||||
if (p->lock_cnt == 0) {
|
if (!ssh_poll_is_locked(p)) {
|
||||||
p->ctx->pollfds[p->x.idx].events = events;
|
p->ctx->pollfds[p->x.idx].events = events;
|
||||||
} else if (!(p->ctx->pollfds[p->x.idx].events & POLLOUT)) {
|
} else if (!(p->ctx->pollfds[p->x.idx].events & POLLOUT)) {
|
||||||
/* if locked, allow only setting POLLOUT to prevent recursive
|
/* if locked, allow only setting POLLOUT to prevent recursive
|
||||||
@@ -669,6 +669,20 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns if a poll object is locked.
|
||||||
|
*
|
||||||
|
* @param p Pointer to an already allocated poll object.
|
||||||
|
* @returns true if the poll object is locked; false otherwise.
|
||||||
|
*/
|
||||||
|
bool ssh_poll_is_locked(ssh_poll_handle p)
|
||||||
|
{
|
||||||
|
if (p == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return p->lock_cnt > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Poll all the sockets associated through a poll object with a
|
* @brief Poll all the sockets associated through a poll object with a
|
||||||
* poll context. If any of the events are set after the poll, the
|
* poll context. If any of the events are set after the poll, the
|
||||||
@@ -703,7 +717,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout)
|
|||||||
* output buffer */
|
* output buffer */
|
||||||
for (i = 0; i < ctx->polls_used; i++) {
|
for (i = 0; i < ctx->polls_used; i++) {
|
||||||
/* The lock allows only POLLOUT events: drop the rest */
|
/* The lock allows only POLLOUT events: drop the rest */
|
||||||
if (ctx->pollptrs[i]->lock_cnt > 0) {
|
if (ssh_poll_is_locked(ctx->pollptrs[i])) {
|
||||||
ctx->pollfds[i].events &= POLLOUT;
|
ctx->pollfds[i].events &= POLLOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/scp.c
16
src/scp.c
@@ -862,6 +862,22 @@ int ssh_scp_pull_request(ssh_scp scp)
|
|||||||
size = strtoull(tmp, NULL, 10);
|
size = strtoull(tmp, NULL, 10);
|
||||||
p++;
|
p++;
|
||||||
name = strdup(p);
|
name = strdup(p);
|
||||||
|
/* Catch invalid name:
|
||||||
|
* - empty ones
|
||||||
|
* - containing any forward slash -- directory traversal handled
|
||||||
|
* differently
|
||||||
|
* - special names "." and ".." referring to the current and parent
|
||||||
|
* directories -- they are not expected either
|
||||||
|
*/
|
||||||
|
if (name == NULL || name[0] == '\0' || strchr(name, '/') ||
|
||||||
|
strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
||||||
|
ssh_set_error(scp->session,
|
||||||
|
SSH_FATAL,
|
||||||
|
"Received invalid filename: %s",
|
||||||
|
name == NULL ? "<NULL>" : name);
|
||||||
|
SAFE_FREE(name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
SAFE_FREE(scp->request_name);
|
SAFE_FREE(scp->request_name);
|
||||||
scp->request_name = name;
|
scp->request_name = name;
|
||||||
if (buffer[0] == 'C') {
|
if (buffer[0] == 'C') {
|
||||||
|
|||||||
@@ -495,6 +495,11 @@ static size_t callback_receive_banner(const void *data, size_t len, void *user)
|
|||||||
buffer[i] = '\0';
|
buffer[i] = '\0';
|
||||||
|
|
||||||
str = strdup(buffer);
|
str = strdup(buffer);
|
||||||
|
if (str == NULL) {
|
||||||
|
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/* number of bytes read */
|
/* number of bytes read */
|
||||||
processed = i + 1;
|
processed = i + 1;
|
||||||
session->clientbanner = str;
|
session->clientbanner = str;
|
||||||
@@ -523,6 +528,7 @@ static int ssh_server_kex_termination(void *s){
|
|||||||
ssh_session session = s;
|
ssh_session session = s;
|
||||||
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
||||||
session->session_state != SSH_SESSION_STATE_AUTHENTICATING &&
|
session->session_state != SSH_SESSION_STATE_AUTHENTICATING &&
|
||||||
|
session->session_state != SSH_SESSION_STATE_AUTHENTICATED &&
|
||||||
session->session_state != SSH_SESSION_STATE_DISCONNECTED)
|
session->session_state != SSH_SESSION_STATE_DISCONNECTED)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
|
|||||||
21
src/sftp.c
21
src/sftp.c
@@ -567,7 +567,8 @@ int sftp_init(sftp_session sftp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int sftp_extensions_get_count(sftp_session sftp) {
|
unsigned int sftp_extensions_get_count(sftp_session sftp)
|
||||||
|
{
|
||||||
if (sftp == NULL || sftp->ext == NULL) {
|
if (sftp == NULL || sftp->ext == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -575,15 +576,18 @@ unsigned int sftp_extensions_get_count(sftp_session sftp) {
|
|||||||
return sftp->ext->count;
|
return sftp->ext->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *sftp_extensions_get_name(sftp_session sftp, unsigned int idx) {
|
const char *sftp_extensions_get_name(sftp_session sftp, unsigned int idx)
|
||||||
if (sftp == NULL)
|
{
|
||||||
|
if (sftp == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (sftp->ext == NULL || sftp->ext->name == NULL) {
|
if (sftp->ext == NULL || sftp->ext->name == NULL) {
|
||||||
ssh_set_error_invalid(sftp->session);
|
ssh_set_error_invalid(sftp->session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx > sftp->ext->count) {
|
if (idx >= sftp->ext->count) {
|
||||||
ssh_set_error_invalid(sftp->session);
|
ssh_set_error_invalid(sftp->session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -591,15 +595,18 @@ const char *sftp_extensions_get_name(sftp_session sftp, unsigned int idx) {
|
|||||||
return sftp->ext->name[idx];
|
return sftp->ext->name[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *sftp_extensions_get_data(sftp_session sftp, unsigned int idx) {
|
const char *sftp_extensions_get_data(sftp_session sftp, unsigned int idx)
|
||||||
if (sftp == NULL)
|
{
|
||||||
|
if (sftp == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (sftp->ext == NULL || sftp->ext->name == NULL) {
|
if (sftp->ext == NULL || sftp->ext->name == NULL) {
|
||||||
ssh_set_error_invalid(sftp->session);
|
ssh_set_error_invalid(sftp->session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx > sftp->ext->count) {
|
if (idx >= sftp->ext->count) {
|
||||||
ssh_set_error_invalid(sftp->session);
|
ssh_set_error_invalid(sftp->session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -458,19 +458,24 @@ enum sftp_longname_field_e {
|
|||||||
static char * sftp_parse_longname(const char *longname,
|
static char * sftp_parse_longname(const char *longname,
|
||||||
enum sftp_longname_field_e longname_field)
|
enum sftp_longname_field_e longname_field)
|
||||||
{
|
{
|
||||||
const char *p, *q;
|
const char *p = NULL, *q = NULL;
|
||||||
size_t len, field = 0;
|
size_t len, field = 0;
|
||||||
|
|
||||||
|
if (longname == NULL || longname_field < SFTP_LONGNAME_PERM ||
|
||||||
|
longname_field > SFTP_LONGNAME_NAME) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
p = longname;
|
p = longname;
|
||||||
/*
|
/*
|
||||||
* Find the beginning of the field which is specified
|
* Find the beginning of the field which is specified
|
||||||
* by sftp_longname_field_e.
|
* by sftp_longname_field_e.
|
||||||
*/
|
*/
|
||||||
while (field != longname_field) {
|
while (*p != '\0' && field != longname_field) {
|
||||||
if (isspace(*p)) {
|
if (isspace(*p)) {
|
||||||
field++;
|
field++;
|
||||||
p++;
|
p++;
|
||||||
while (*p && isspace(*p)) {
|
while (*p != '\0' && isspace(*p)) {
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -478,8 +483,13 @@ static char * sftp_parse_longname(const char *longname,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we reached NULL before we got our field fail */
|
||||||
|
if (field != longname_field) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
q = p;
|
q = p;
|
||||||
while (! isspace(*q)) {
|
while (*q != '\0' && !isspace(*q)) {
|
||||||
q++;
|
q++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,17 +556,14 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp,
|
|||||||
if (rc != SSH_OK){
|
if (rc != SSH_OK){
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_DEBUG,
|
SSH_LOG(SSH_LOG_DEBUG, "Flags: %.8" PRIx32, attr->flags);
|
||||||
"Flags: %.8" PRIx32 "\n", attr->flags);
|
|
||||||
|
|
||||||
if (attr->flags & SSH_FILEXFER_ATTR_SIZE) {
|
if (attr->flags & SSH_FILEXFER_ATTR_SIZE) {
|
||||||
rc = ssh_buffer_unpack(buf, "q", &attr->size);
|
rc = ssh_buffer_unpack(buf, "q", &attr->size);
|
||||||
if(rc != SSH_OK) {
|
if(rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SSH_LOG(SSH_LOG_DEBUG,
|
SSH_LOG(SSH_LOG_DEBUG, "Size: %" PRIu64, (uint64_t)attr->size);
|
||||||
"Size: %" PRIu64 "\n",
|
|
||||||
(uint64_t) attr->size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr->flags & SSH_FILEXFER_ATTR_UIDGID) {
|
if (attr->flags & SSH_FILEXFER_ATTR_UIDGID) {
|
||||||
|
|||||||
@@ -478,7 +478,7 @@ void ssh_socket_close(ssh_socket s)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->poll_handle != NULL) {
|
if (s->poll_handle != NULL && !ssh_poll_is_locked(s->poll_handle)) {
|
||||||
ssh_poll_free(s->poll_handle);
|
ssh_poll_free(s->poll_handle);
|
||||||
s->poll_handle = NULL;
|
s->poll_handle = NULL;
|
||||||
}
|
}
|
||||||
@@ -1096,7 +1096,7 @@ jump_thread_func(void *arg)
|
|||||||
cb = ssh_list_pop_head(struct ssh_jump_callbacks_struct *,
|
cb = ssh_list_pop_head(struct ssh_jump_callbacks_struct *,
|
||||||
jump_session->opts.proxy_jumps_user_cb);
|
jump_session->opts.proxy_jumps_user_cb);
|
||||||
|
|
||||||
if (cb != NULL) {
|
if (cb != NULL && cb->before_connection != NULL) {
|
||||||
rc = cb->before_connection(jump_session, cb->userdata);
|
rc = cb->before_connection(jump_session, cb->userdata);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
SSH_LOG(SSH_LOG_WARN, "%s", ssh_get_error(jump_session));
|
SSH_LOG(SSH_LOG_WARN, "%s", ssh_get_error(jump_session));
|
||||||
@@ -1205,6 +1205,8 @@ exit:
|
|||||||
ssh_event_free(event);
|
ssh_event_free(event);
|
||||||
ssh_free(jump_session);
|
ssh_free(jump_session);
|
||||||
|
|
||||||
|
shutdown(jump_thread_data->fd, SHUT_RDWR);
|
||||||
|
close(jump_thread_data->fd);
|
||||||
SAFE_FREE(jump_thread_data);
|
SAFE_FREE(jump_thread_data);
|
||||||
|
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
|
|||||||
@@ -181,7 +181,10 @@ void crypto_free(struct ssh_crypto_struct *crypto)
|
|||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
#elif defined HAVE_GCRYPT_ECC
|
#elif defined HAVE_GCRYPT_ECC
|
||||||
gcry_sexp_release(crypto->ecdh_privkey);
|
gcry_sexp_release(crypto->ecdh_privkey);
|
||||||
#endif
|
#elif defined HAVE_LIBMBEDCRYPTO
|
||||||
|
mbedtls_ecp_keypair_free(crypto->ecdh_privkey);
|
||||||
|
SAFE_FREE(crypto->ecdh_privkey);
|
||||||
|
#endif /* HAVE_LIBGCRYPT */
|
||||||
crypto->ecdh_privkey = NULL;
|
crypto->ecdh_privkey = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ if (NOT WIN32)
|
|||||||
${TORTURE_LINK_LIBRARIES}
|
${TORTURE_LINK_LIBRARIES}
|
||||||
pthread)
|
pthread)
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||||
|
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||||
|
set(TORTURE_LINK_LIBRARIES
|
||||||
|
${TORTURE_LINK_LIBRARIES}
|
||||||
|
OpenSSL::Crypto)
|
||||||
|
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||||
|
|
||||||
# create test library
|
# create test library
|
||||||
add_library(${TORTURE_LIBRARY}
|
add_library(${TORTURE_LIBRARY}
|
||||||
@@ -99,6 +105,7 @@ add_subdirectory(unittests)
|
|||||||
# OpenSSH Capabilities are required for all unit tests
|
# OpenSSH Capabilities are required for all unit tests
|
||||||
find_program(SSH_EXECUTABLE NAMES ssh)
|
find_program(SSH_EXECUTABLE NAMES ssh)
|
||||||
if (SSH_EXECUTABLE)
|
if (SSH_EXECUTABLE)
|
||||||
|
file(SIZE ${SSH_EXECUTABLE} SSH_EXECUTABLE_SIZE)
|
||||||
execute_process(COMMAND ${SSH_EXECUTABLE} -V ERROR_VARIABLE OPENSSH_VERSION_STR)
|
execute_process(COMMAND ${SSH_EXECUTABLE} -V ERROR_VARIABLE OPENSSH_VERSION_STR)
|
||||||
string(REGEX REPLACE "^.*OpenSSH_([0-9]+).[0-9].*$" "\\1" OPENSSH_VERSION_MAJOR "${OPENSSH_VERSION_STR}")
|
string(REGEX REPLACE "^.*OpenSSH_([0-9]+).[0-9].*$" "\\1" OPENSSH_VERSION_MAJOR "${OPENSSH_VERSION_STR}")
|
||||||
string(REGEX REPLACE "^.*OpenSSH_[0-9]+.([0-9]).*$" "\\1" OPENSSH_VERSION_MINOR "${OPENSSH_VERSION_STR}")
|
string(REGEX REPLACE "^.*OpenSSH_[0-9]+.([0-9]).*$" "\\1" OPENSSH_VERSION_MINOR "${OPENSSH_VERSION_STR}")
|
||||||
@@ -163,6 +170,22 @@ if (SSH_EXECUTABLE)
|
|||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_program(DROPBEAR_EXECUTABLE NAMES dbclient)
|
||||||
|
if (DROPBEAR_EXECUTABLE)
|
||||||
|
execute_process(COMMAND ${DROPBEAR_EXECUTABLE} -V ERROR_VARIABLE DROPBEAR_VERSION_STR)
|
||||||
|
string(REGEX REPLACE "^.*Dropbear v([0-9]+)\\.([0-9]+).*$" "\\1.\\2" DROPBEAR_VERSION "${DROPBEAR_VERSION_STR}")
|
||||||
|
set(DROPBEAR_VERSION "${DROPBEAR_VERSION}")
|
||||||
|
|
||||||
|
# HMAC-SHA1 support was removed in version 2025.87
|
||||||
|
if("${DROPBEAR_VERSION}" VERSION_LESS "2025.87")
|
||||||
|
message("Dropbear Version less than 2025.87, enabling dropbear HMAC-SHA1 tests")
|
||||||
|
add_definitions(-DDROPBEAR_SUPPORTS_HMAC_SHA1)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "Could NOT find Dropbear (missing: dbclient executable)")
|
||||||
|
set(DROPBEAR_EXECUTABLE "/bin/false")
|
||||||
|
endif()
|
||||||
|
|
||||||
find_program(SSHD_EXECUTABLE
|
find_program(SSHD_EXECUTABLE
|
||||||
NAME
|
NAME
|
||||||
sshd
|
sshd
|
||||||
@@ -350,10 +373,10 @@ if (FUZZ_TESTING)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target(test_memcheck
|
add_custom_target(test_memcheck
|
||||||
# FIXME: The threads_pki_rsa test is skipped under valgrind as it times out
|
# FIXME: The pkd_hello_i1 test is skipped under valgrind as it times out
|
||||||
# Passing suppression file is also stupid so lets go with override here:
|
# Passing suppression file is also stupid so lets go with override here:
|
||||||
# https://stackoverflow.com/a/56116311
|
# https://stackoverflow.com/a/56116311
|
||||||
COMMAND ${CMAKE_CTEST_COMMAND} -E torture_threads_pki_rsa -E pkd_hello_i1
|
COMMAND ${CMAKE_CTEST_COMMAND} -E pkd_hello_i1
|
||||||
--output-on-failure --force-new-ctest-process --test-action memcheck
|
--output-on-failure --force-new-ctest-process --test-action memcheck
|
||||||
--overwrite MemoryCheckSuppressionFile=${CMAKE_SOURCE_DIR}/tests/valgrind.supp
|
--overwrite MemoryCheckSuppressionFile=${CMAKE_SOURCE_DIR}/tests/valgrind.supp
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||||
|
|||||||
@@ -272,5 +272,5 @@ torture_run_tests(void)
|
|||||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
|
|
||||||
pthread_exit((void *)&rc);
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/crypto.h"
|
#include "libssh/crypto.h"
|
||||||
|
#include "libssh/token.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -96,6 +97,7 @@ static int session_teardown(void **state)
|
|||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
ssh_free(s->ssh.session);
|
ssh_free(s->ssh.session);
|
||||||
|
s->ssh.session = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -148,7 +150,7 @@ static void torture_rekey_default(void **state)
|
|||||||
ssh_disconnect(s->ssh.session);
|
ssh_disconnect(s->ssh.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sanity_check_session(void **state)
|
static void sanity_check_session_size(void **state, uint64_t rekey_limit)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
struct ssh_crypto_struct *c = NULL;
|
struct ssh_crypto_struct *c = NULL;
|
||||||
@@ -156,9 +158,9 @@ static void sanity_check_session(void **state)
|
|||||||
c = s->ssh.session->current_crypto;
|
c = s->ssh.session->current_crypto;
|
||||||
assert_non_null(c);
|
assert_non_null(c);
|
||||||
assert_int_equal(c->in_cipher->max_blocks,
|
assert_int_equal(c->in_cipher->max_blocks,
|
||||||
bytes / c->in_cipher->blocksize);
|
rekey_limit / c->in_cipher->blocksize);
|
||||||
assert_int_equal(c->out_cipher->max_blocks,
|
assert_int_equal(c->out_cipher->max_blocks,
|
||||||
bytes / c->out_cipher->blocksize);
|
rekey_limit / c->out_cipher->blocksize);
|
||||||
/* when strict kex is used, the newkeys reset the sequence number */
|
/* when strict kex is used, the newkeys reset the sequence number */
|
||||||
if ((s->ssh.session->flags & SSH_SESSION_FLAG_KEX_STRICT) != 0) {
|
if ((s->ssh.session->flags & SSH_SESSION_FLAG_KEX_STRICT) != 0) {
|
||||||
assert_int_equal(c->out_cipher->packets, s->ssh.session->send_seq);
|
assert_int_equal(c->out_cipher->packets, s->ssh.session->send_seq);
|
||||||
@@ -170,6 +172,10 @@ static void sanity_check_session(void **state)
|
|||||||
assert_true(c->in_cipher->packets < s->ssh.session->recv_seq);
|
assert_true(c->in_cipher->packets < s->ssh.session->recv_seq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static void sanity_check_session(void **state)
|
||||||
|
{
|
||||||
|
sanity_check_session_size(state, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
/* We lower the rekey limits manually and check that the rekey
|
/* We lower the rekey limits manually and check that the rekey
|
||||||
* really happens when sending data
|
* really happens when sending data
|
||||||
@@ -275,7 +281,7 @@ static int session_setup_sftp_client(void **state)
|
|||||||
/* To trigger rekey by receiving data, the easiest thing is probably to
|
/* To trigger rekey by receiving data, the easiest thing is probably to
|
||||||
* use sftp
|
* use sftp
|
||||||
*/
|
*/
|
||||||
static void torture_rekey_recv(void **state)
|
static void torture_rekey_recv_size(void **state, uint64_t rekey_limit)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
struct ssh_crypto_struct *c = NULL;
|
struct ssh_crypto_struct *c = NULL;
|
||||||
@@ -290,7 +296,7 @@ static void torture_rekey_recv(void **state)
|
|||||||
mode_t mask;
|
mode_t mask;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
sanity_check_session(state);
|
sanity_check_session_size(state, rekey_limit);
|
||||||
/* Copy the initial secret hash = session_id so we know we changed keys later */
|
/* Copy the initial secret hash = session_id so we know we changed keys later */
|
||||||
c = s->ssh.session->current_crypto;
|
c = s->ssh.session->current_crypto;
|
||||||
assert_non_null(c);
|
assert_non_null(c);
|
||||||
@@ -324,8 +330,10 @@ static void torture_rekey_recv(void **state)
|
|||||||
|
|
||||||
/* The rekey limit was restored in the new crypto to the same value */
|
/* The rekey limit was restored in the new crypto to the same value */
|
||||||
c = s->ssh.session->current_crypto;
|
c = s->ssh.session->current_crypto;
|
||||||
assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize);
|
assert_int_equal(c->in_cipher->max_blocks,
|
||||||
assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize);
|
rekey_limit / c->in_cipher->blocksize);
|
||||||
|
assert_int_equal(c->out_cipher->max_blocks,
|
||||||
|
rekey_limit / c->out_cipher->blocksize);
|
||||||
/* Check that the secret hash is different than initially */
|
/* Check that the secret hash is different than initially */
|
||||||
assert_memory_not_equal(secret_hash, c->secret_hash, c->digest_len);
|
assert_memory_not_equal(secret_hash, c->secret_hash, c->digest_len);
|
||||||
free(secret_hash);
|
free(secret_hash);
|
||||||
@@ -333,6 +341,11 @@ static void torture_rekey_recv(void **state)
|
|||||||
torture_sftp_close(s->ssh.tsftp);
|
torture_sftp_close(s->ssh.tsftp);
|
||||||
ssh_disconnect(s->ssh.session);
|
ssh_disconnect(s->ssh.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_rekey_recv(void **state)
|
||||||
|
{
|
||||||
|
torture_rekey_recv_size(state, bytes);
|
||||||
|
}
|
||||||
#endif /* WITH_SFTP */
|
#endif /* WITH_SFTP */
|
||||||
|
|
||||||
/* Rekey time requires rekey after specified time and is off by default.
|
/* Rekey time requires rekey after specified time and is off by default.
|
||||||
@@ -836,6 +849,81 @@ static void torture_rekey_guess_wrong_recv(void **state)
|
|||||||
|
|
||||||
torture_rekey_recv(state);
|
torture_rekey_recv(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_rekey_guess_all_combinations(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
char sshd_config[256] = "";
|
||||||
|
char client_kex[256] = "";
|
||||||
|
const char *supported = NULL;
|
||||||
|
struct ssh_tokens_st *s_tok = NULL;
|
||||||
|
uint64_t rekey_limit = 0;
|
||||||
|
int rc, i, j;
|
||||||
|
|
||||||
|
/* The rekey limit is 1/2 of the transferred file size so we will likely get
|
||||||
|
* 2 rekeys per test, which still runs for acceptable time */
|
||||||
|
rekey_limit = atoll(SSH_EXECUTABLE_SIZE);
|
||||||
|
rekey_limit /= 2;
|
||||||
|
|
||||||
|
if (ssh_fips_mode()) {
|
||||||
|
supported = ssh_kex_get_fips_methods(SSH_KEX);
|
||||||
|
} else {
|
||||||
|
supported = ssh_kex_get_supported_method(SSH_KEX);
|
||||||
|
}
|
||||||
|
assert_non_null(supported);
|
||||||
|
|
||||||
|
s_tok = ssh_tokenize(supported, ',');
|
||||||
|
assert_non_null(s_tok);
|
||||||
|
for (i = 0; s_tok->tokens[i]; i++) {
|
||||||
|
/* Skip algorithms not supported by the OpenSSH server */
|
||||||
|
if (strstr(OPENSSH_KEX, s_tok->tokens[i]) == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_INFO, "Server: %s [skipping]", s_tok->tokens[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SSH_LOG(SSH_LOG_INFO, "Server: %s", s_tok->tokens[i]);
|
||||||
|
snprintf(sshd_config,
|
||||||
|
sizeof(sshd_config),
|
||||||
|
"KexAlgorithms %s",
|
||||||
|
s_tok->tokens[i]);
|
||||||
|
/* This sets an only supported kex algorithm that we do not have as
|
||||||
|
* a first option in the client */
|
||||||
|
torture_update_sshd_config(state, sshd_config);
|
||||||
|
|
||||||
|
for (j = 0; s_tok->tokens[j]; j++) {
|
||||||
|
if (i == j) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
session_setup(state);
|
||||||
|
/* Make the client send the first_kex_packet_follows flag during key
|
||||||
|
* exchange as well as during the rekey */
|
||||||
|
s->ssh.session->send_first_kex_follows = true;
|
||||||
|
|
||||||
|
rc = ssh_options_set(s->ssh.session,
|
||||||
|
SSH_OPTIONS_REKEY_DATA,
|
||||||
|
&rekey_limit);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
|
||||||
|
/* Client kex preference will have the second of the pair and the
|
||||||
|
* server one as a second to negotiate on the second attempt */
|
||||||
|
snprintf(client_kex,
|
||||||
|
sizeof(client_kex),
|
||||||
|
"%s,%s",
|
||||||
|
s_tok->tokens[j],
|
||||||
|
s_tok->tokens[i]);
|
||||||
|
SSH_LOG(SSH_LOG_INFO, "Client: %s", client_kex);
|
||||||
|
rc = ssh_options_set(s->ssh.session,
|
||||||
|
SSH_OPTIONS_KEY_EXCHANGE,
|
||||||
|
client_kex);
|
||||||
|
assert_ssh_return_code(s->ssh.session, rc);
|
||||||
|
session_setup_sftp(state);
|
||||||
|
torture_rekey_recv_size(state, rekey_limit);
|
||||||
|
session_teardown(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_tokens_free(s_tok);
|
||||||
|
}
|
||||||
#endif /* WITH_SFTP */
|
#endif /* WITH_SFTP */
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
@@ -905,6 +993,7 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_recv,
|
cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_recv,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test(torture_rekey_guess_all_combinations),
|
||||||
#endif /* WITH_SFTP */
|
#endif /* WITH_SFTP */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,63 @@ static void session_setup_channel(void **state)
|
|||||||
assert_non_null(s->ssh.tsftp);
|
assert_non_null(s->ssh.tsftp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void session_setup_extensions(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
struct passwd *pwd = NULL;
|
||||||
|
int rc, count;
|
||||||
|
const char *name = NULL, *data = NULL;
|
||||||
|
sftp_session sftp = NULL;
|
||||||
|
|
||||||
|
pwd = getpwnam("bob");
|
||||||
|
assert_non_null(pwd);
|
||||||
|
|
||||||
|
rc = setuid(pwd->pw_uid);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
|
||||||
|
s->ssh.session = torture_ssh_session(s,
|
||||||
|
TORTURE_SSH_SERVER,
|
||||||
|
NULL,
|
||||||
|
TORTURE_SSH_USER_ALICE,
|
||||||
|
NULL);
|
||||||
|
assert_non_null(s->ssh.session);
|
||||||
|
|
||||||
|
s->ssh.tsftp = torture_sftp_session(s->ssh.session);
|
||||||
|
assert_non_null(s->ssh.tsftp);
|
||||||
|
sftp = s->ssh.tsftp->sftp;
|
||||||
|
|
||||||
|
/* null parameter */
|
||||||
|
count = sftp_extensions_get_count(NULL);
|
||||||
|
assert_int_equal(count, 0);
|
||||||
|
|
||||||
|
count = sftp_extensions_get_count(sftp);
|
||||||
|
assert_int_not_equal(count, 0);
|
||||||
|
|
||||||
|
/* first null parameter */
|
||||||
|
name = sftp_extensions_get_name(NULL, 0);
|
||||||
|
assert_null(name);
|
||||||
|
data = sftp_extensions_get_data(NULL, 0);
|
||||||
|
assert_null(data);
|
||||||
|
|
||||||
|
/* First extension */
|
||||||
|
name = sftp_extensions_get_name(sftp, 0);
|
||||||
|
assert_non_null(name);
|
||||||
|
data = sftp_extensions_get_data(sftp, 0);
|
||||||
|
assert_non_null(data);
|
||||||
|
|
||||||
|
/* Last extension */
|
||||||
|
name = sftp_extensions_get_name(sftp, count - 1);
|
||||||
|
assert_non_null(name);
|
||||||
|
data = sftp_extensions_get_data(sftp, count - 1);
|
||||||
|
assert_non_null(data);
|
||||||
|
|
||||||
|
/* Overrun */
|
||||||
|
name = sftp_extensions_get_name(sftp, count);
|
||||||
|
assert_null(name);
|
||||||
|
data = sftp_extensions_get_data(sftp, count);
|
||||||
|
assert_null(data);
|
||||||
|
}
|
||||||
|
|
||||||
static int session_teardown(void **state)
|
static int session_teardown(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -92,7 +149,10 @@ int torture_run_tests(void) {
|
|||||||
session_teardown),
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(session_setup_channel,
|
cmocka_unit_test_setup_teardown(session_setup_channel,
|
||||||
NULL,
|
NULL,
|
||||||
session_teardown)
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(session_setup_extensions,
|
||||||
|
NULL,
|
||||||
|
session_teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ project(fuzzing CXX)
|
|||||||
|
|
||||||
macro(fuzzer name)
|
macro(fuzzer name)
|
||||||
add_executable(${name} ${name}.c)
|
add_executable(${name} ${name}.c)
|
||||||
target_link_libraries(${name}
|
target_link_libraries(${name} PRIVATE ${TORTURE_LINK_LIBRARIES})
|
||||||
PRIVATE
|
|
||||||
ssh::static pthread)
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set_target_properties(${name}
|
set_target_properties(${name}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
/* Simpler gnu89 version of StandaloneFuzzTargetMain.c from LLVM */
|
/* Simpler gnu89 version of StandaloneFuzzTargetMain.c from LLVM */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#if defined(HAVE_LIBCRYPTO) || defined(WITH_GSSAPI)
|
||||||
|
/* for OPENSSL_cleanup() of GSSAPI's OpenSSL context */
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size);
|
int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size);
|
||||||
__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
|
__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
|
||||||
@@ -35,5 +41,9 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
free (buf);
|
free (buf);
|
||||||
printf ("Done!\n");
|
printf ("Done!\n");
|
||||||
|
|
||||||
|
#if defined(HAVE_LIBCRYPTO) || defined(WITH_GSSAPI)
|
||||||
|
OPENSSL_cleanup();
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ if [ ! -d "$TESTDIR/db" ]; then
|
|||||||
directories.tokendir = $TESTDIR/db
|
directories.tokendir = $TESTDIR/db
|
||||||
objectstore.backend = file
|
objectstore.backend = file
|
||||||
log.level = DEBUG
|
log.level = DEBUG
|
||||||
|
# # The hashed ECDSA mechanisms wrongly do not support multi-part operations
|
||||||
|
# https://github.com/softhsm/SoftHSMv2/issues/842
|
||||||
|
slots.mechanisms = -CKM_ECDSA_SHA1,CKM_ECDSA_SHA224,CKM_ECDSA_SHA256,CKM_ECDSA_SHA384,CKM_ECDSA_SHA512
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat "$TESTDIR/softhsm.conf"
|
cat "$TESTDIR/softhsm.conf"
|
||||||
|
|||||||
@@ -17,10 +17,8 @@ set(pkd_hello_src
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(pkd_libs
|
set(pkd_libs
|
||||||
${CMOCKA_LIBRARY}
|
${TORTURE_LINK_LIBRARIES}
|
||||||
ssh::static
|
|
||||||
${ARGP_LIBRARIES}
|
${ARGP_LIBRARIES}
|
||||||
pthread
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(pkd_hello ${pkd_hello_src})
|
add_executable(pkd_hello ${pkd_hello_src})
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
/* Dropbear */
|
/* Dropbear */
|
||||||
|
|
||||||
#define DROPBEAR_BINARY "dbclient"
|
#define DROPBEAR_BINARY DROPBEAR_EXECUTABLE
|
||||||
#define DROPBEAR_KEYGEN "dropbearkey"
|
#define DROPBEAR_KEYGEN "dropbearkey"
|
||||||
|
|
||||||
#define DROPBEAR_CMD_START \
|
#define DROPBEAR_CMD_START \
|
||||||
|
|||||||
@@ -22,6 +22,11 @@
|
|||||||
#include "pkd_keyutil.h"
|
#include "pkd_keyutil.h"
|
||||||
#include "pkd_util.h"
|
#include "pkd_util.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_LIBCRYPTO)
|
||||||
|
/* for OPENSSL_cleanup() of OpenSSL context */
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_ITERATIONS 10
|
#define DEFAULT_ITERATIONS 10
|
||||||
static struct pkd_daemon_args pkd_dargs;
|
static struct pkd_daemon_args pkd_dargs;
|
||||||
|
|
||||||
@@ -410,22 +415,32 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
|||||||
f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown)
|
f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown)
|
||||||
|
|
||||||
|
|
||||||
#define PKDTESTS_MAC_FIPS(f, client, maccmd) \
|
#define PKDTESTS_MAC_FIPS_BASE(f, client, maccmd) \
|
||||||
f(client, ecdsa_256_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_256, teardown) \
|
f(client, ecdsa_256_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_256, teardown) \
|
||||||
f(client, ecdsa_384_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_384, teardown) \
|
f(client, ecdsa_384_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_384, teardown) \
|
||||||
f(client, ecdsa_521_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_521, teardown) \
|
f(client, ecdsa_521_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_521, teardown) \
|
||||||
f(client, rsa_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_rsa, teardown)
|
f(client, rsa_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_rsa, teardown)
|
||||||
|
|
||||||
/* TODO: Include these tests when an older version of dropbear is used. Currently, they have been removed as the latest dropbear version
|
#define PKDTESTS_MAC_FIPS_SHA1(f, client, maccmd) \
|
||||||
does not support these MACs.
|
|
||||||
|
|
||||||
f(client, ecdsa_256_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_256, teardown) \
|
f(client, ecdsa_256_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_256, teardown) \
|
||||||
f(client, ecdsa_384_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_384, teardown) \
|
f(client, ecdsa_384_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_384, teardown) \
|
||||||
f(client, ecdsa_521_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_521, teardown) \
|
f(client, ecdsa_521_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_521, teardown) \
|
||||||
f(client, rsa_hmac_sha1, maccmd("hmac-sha1"), setup_rsa, teardown) \
|
f(client, rsa_hmac_sha1, maccmd("hmac-sha1"), setup_rsa, teardown)
|
||||||
*/
|
|
||||||
|
#ifdef DROPBEAR_SUPPORTS_HMAC_SHA1
|
||||||
|
#define PKDTESTS_MAC_FIPS(f, client, maccmd) \
|
||||||
|
PKDTESTS_MAC_FIPS_BASE(f, client, maccmd) \
|
||||||
|
PKDTESTS_MAC_FIPS_SHA1(f, client, maccmd)
|
||||||
|
#define PKDTESTS_MAC_OPENSSHONLY_FIPS_SHA1(f, client, maccmd)
|
||||||
|
#else
|
||||||
|
#define PKDTESTS_MAC_FIPS(f, client, maccmd) \
|
||||||
|
PKDTESTS_MAC_FIPS_BASE(f, client, maccmd)
|
||||||
|
#define PKDTESTS_MAC_OPENSSHONLY_FIPS_SHA1(f, client, maccmd) \
|
||||||
|
PKDTESTS_MAC_FIPS_SHA1(f, client, maccmd)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PKDTESTS_MAC_OPENSSHONLY_FIPS(f, client, maccmd) \
|
#define PKDTESTS_MAC_OPENSSHONLY_FIPS(f, client, maccmd) \
|
||||||
|
PKDTESTS_MAC_OPENSSHONLY_FIPS_SHA1(f, client, maccmd) \
|
||||||
f(client, ecdsa_256_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_ecdsa_256, teardown) \
|
f(client, ecdsa_256_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_ecdsa_256, teardown) \
|
||||||
f(client, ecdsa_256_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_ecdsa_256, teardown) \
|
f(client, ecdsa_256_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_ecdsa_256, teardown) \
|
||||||
f(client, ecdsa_256_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_256, teardown) \
|
f(client, ecdsa_256_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_256, teardown) \
|
||||||
@@ -990,6 +1005,9 @@ out_finalize:
|
|||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
fprintf(stderr, "ssh_finalize: %d\n", rc);
|
fprintf(stderr, "ssh_finalize: %d\n", rc);
|
||||||
}
|
}
|
||||||
|
#if defined(HAVE_LIBCRYPTO)
|
||||||
|
OPENSSL_cleanup();
|
||||||
|
#endif
|
||||||
out:
|
out:
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ set(server_SRCS
|
|||||||
add_library(testserver STATIC
|
add_library(testserver STATIC
|
||||||
test_server.c
|
test_server.c
|
||||||
default_cb.c
|
default_cb.c
|
||||||
sftpserver_cb.c)
|
sftpserver_cb.c
|
||||||
|
testserver_common.c)
|
||||||
if (WITH_COVERAGE)
|
if (WITH_COVERAGE)
|
||||||
append_coverage_compiler_flags_to_target(testserver)
|
append_coverage_compiler_flags_to_target(testserver)
|
||||||
endif (WITH_COVERAGE)
|
endif (WITH_COVERAGE)
|
||||||
@@ -32,7 +33,7 @@ if (UNIX AND NOT WIN32)
|
|||||||
add_executable(test_server ${server_SRCS})
|
add_executable(test_server ${server_SRCS})
|
||||||
target_compile_options(test_server PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
target_compile_options(test_server PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||||
target_link_libraries(test_server
|
target_link_libraries(test_server
|
||||||
PRIVATE testserver ssh::ssh ${ARGP_LIBRARIES} util)
|
PRIVATE testserver ${TORTURE_LINK_LIBRARIES} ${ARGP_LIBRARIES} util)
|
||||||
if (WITH_COVERAGE)
|
if (WITH_COVERAGE)
|
||||||
append_coverage_compiler_flags_to_target(test_server)
|
append_coverage_compiler_flags_to_target(test_server)
|
||||||
endif (WITH_COVERAGE)
|
endif (WITH_COVERAGE)
|
||||||
|
|||||||
@@ -21,9 +21,11 @@
|
|||||||
* MA 02111-1307, USA.
|
* MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "test_server.h"
|
#include "test_server.h"
|
||||||
#include "default_cb.h"
|
#include "default_cb.h"
|
||||||
|
#include "testserver_common.h"
|
||||||
|
|
||||||
#include <libssh/callbacks.h>
|
#include <libssh/callbacks.h>
|
||||||
#include <libssh/server.h>
|
#include <libssh/server.h>
|
||||||
@@ -448,9 +450,11 @@ static int exec_pty(const char *mode,
|
|||||||
case 0:
|
case 0:
|
||||||
close(cdata->pty_master);
|
close(cdata->pty_master);
|
||||||
if (login_tty(cdata->pty_slave) != 0) {
|
if (login_tty(cdata->pty_slave) != 0) {
|
||||||
|
finalize_openssl();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
execl("/bin/sh", "sh", mode, command, NULL);
|
execl("/bin/sh", "sh", mode, command, NULL);
|
||||||
|
finalize_openssl();
|
||||||
exit(0);
|
exit(0);
|
||||||
default:
|
default:
|
||||||
close(cdata->pty_slave);
|
close(cdata->pty_slave);
|
||||||
@@ -500,6 +504,7 @@ static int exec_nopty(const char *command, struct channel_data_st *cdata)
|
|||||||
close(err[1]);
|
close(err[1]);
|
||||||
/* exec the requested command. */
|
/* exec the requested command. */
|
||||||
execl("/bin/sh", "sh", "-c", command, NULL);
|
execl("/bin/sh", "sh", "-c", command, NULL);
|
||||||
|
finalize_openssl();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test_server.h"
|
#include "test_server.h"
|
||||||
|
#include "testserver_common.h"
|
||||||
|
|
||||||
#include <libssh/priv.h>
|
#include <libssh/priv.h>
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
@@ -288,6 +289,7 @@ int run_server(struct server_state_st *state)
|
|||||||
|
|
||||||
free_server_state(state);
|
free_server_state(state);
|
||||||
SAFE_FREE(state);
|
SAFE_FREE(state);
|
||||||
|
finalize_openssl();
|
||||||
exit(0);
|
exit(0);
|
||||||
case -1:
|
case -1:
|
||||||
fprintf(stderr, "Failed to fork\n");
|
fprintf(stderr, "Failed to fork\n");
|
||||||
@@ -355,11 +357,8 @@ fork_run_server(struct server_state_st *state,
|
|||||||
|
|
||||||
/* The child process starts a server which will listen for connections */
|
/* The child process starts a server which will listen for connections */
|
||||||
rc = run_server(state);
|
rc = run_server(state);
|
||||||
if (rc != 0) {
|
finalize_openssl();
|
||||||
exit(rc);
|
exit(rc);
|
||||||
}
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
case -1:
|
case -1:
|
||||||
strerror_r(errno, err_str, 1024);
|
strerror_r(errno, err_str, 1024);
|
||||||
fprintf(stderr, "Failed to fork: %s\n",
|
fprintf(stderr, "Failed to fork: %s\n",
|
||||||
|
|||||||
36
tests/server/test_server/testserver_common.c
Normal file
36
tests/server/test_server/testserver_common.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 by Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Author: Jakub Jelen <jjelen@redhat.com>
|
||||||
|
*
|
||||||
|
* The SSH Library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* The SSH Library is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with the SSH Library; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
* MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "testserver_common.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_LIBCRYPTO) || defined(WITH_GSSAPI)
|
||||||
|
/* for OPENSSL_cleanup() of GSSAPI's OpenSSL context */
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void finalize_openssl(void)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_LIBCRYPTO) || defined(WITH_GSSAPI)
|
||||||
|
OPENSSL_cleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
26
tests/server/test_server/testserver_common.h
Normal file
26
tests/server/test_server/testserver_common.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the SSH Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 by Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Author: Jakub Jelen <jjelen@redhat.com>
|
||||||
|
*
|
||||||
|
* The SSH Library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* The SSH Library is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with the SSH Library; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
* MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
void finalize_openssl(void);
|
||||||
@@ -451,5 +451,5 @@ torture_run_tests(void)
|
|||||||
teardown_default_server);
|
teardown_default_server);
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
|
|
||||||
pthread_exit((void *)&rc);
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -475,5 +475,5 @@ torture_run_tests(void)
|
|||||||
teardown_default_server);
|
teardown_default_server);
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
|
|
||||||
pthread_exit((void *)&rc);
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,5 +371,5 @@ torture_run_tests(void)
|
|||||||
teardown_default_server);
|
teardown_default_server);
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
|
|
||||||
pthread_exit((void *)&rc);
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ int main(int argc, char **argv)
|
|||||||
const char *banner = NULL;
|
const char *banner = NULL;
|
||||||
ssh_session session = NULL;
|
ssh_session session = NULL;
|
||||||
const char *hostkeys = NULL;
|
const char *hostkeys = NULL;
|
||||||
|
const char *kex = NULL;
|
||||||
int rc = 1;
|
int rc = 1;
|
||||||
|
|
||||||
bool process_config = false;
|
bool process_config = false;
|
||||||
@@ -67,6 +68,13 @@ int main(int argc, char **argv)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enable all supported kex algorithms */
|
||||||
|
kex = ssh_kex_get_supported_method(SSH_KEX);
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, kex);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
rc = ssh_connect(session);
|
rc = ssh_connect(session);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
|
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
|
||||||
|
|||||||
@@ -65,6 +65,8 @@
|
|||||||
#cmakedefine NCAT_EXECUTABLE "${NCAT_EXECUTABLE}"
|
#cmakedefine NCAT_EXECUTABLE "${NCAT_EXECUTABLE}"
|
||||||
#cmakedefine SSHD_EXECUTABLE "${SSHD_EXECUTABLE}"
|
#cmakedefine SSHD_EXECUTABLE "${SSHD_EXECUTABLE}"
|
||||||
#cmakedefine SSH_EXECUTABLE "${SSH_EXECUTABLE}"
|
#cmakedefine SSH_EXECUTABLE "${SSH_EXECUTABLE}"
|
||||||
|
#cmakedefine SSH_EXECUTABLE_SIZE "${SSH_EXECUTABLE_SIZE}"
|
||||||
|
#cmakedefine DROPBEAR_EXECUTABLE "${DROPBEAR_EXECUTABLE}"
|
||||||
#cmakedefine WITH_TIMEOUT ${WITH_TIMEOUT}
|
#cmakedefine WITH_TIMEOUT ${WITH_TIMEOUT}
|
||||||
#cmakedefine TIMEOUT_EXECUTABLE "${TIMEOUT_EXECUTABLE}"
|
#cmakedefine TIMEOUT_EXECUTABLE "${TIMEOUT_EXECUTABLE}"
|
||||||
#cmakedefine SOFTHSM2_LIBRARY "${SOFTHSM2_LIBRARY}"
|
#cmakedefine SOFTHSM2_LIBRARY "${SOFTHSM2_LIBRARY}"
|
||||||
|
|||||||
@@ -52,6 +52,11 @@
|
|||||||
#include <valgrind/valgrind.h>
|
#include <valgrind/valgrind.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_GSSAPI
|
||||||
|
/* for OPENSSL_cleanup() of GSSAPI's OpenSSL context */
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TORTURE_SSHD_SRV_IPV4 "127.0.0.10"
|
#define TORTURE_SSHD_SRV_IPV4 "127.0.0.10"
|
||||||
/* socket wrapper IPv6 prefix fd00::5357:5fxx */
|
/* socket wrapper IPv6 prefix fd00::5357:5fxx */
|
||||||
#define TORTURE_SSHD_SRV_IPV6 "fd00::5357:5f0a"
|
#define TORTURE_SSHD_SRV_IPV6 "fd00::5357:5f0a"
|
||||||
@@ -1848,9 +1853,31 @@ __attribute__((weak)) int torture_run_tests(void)
|
|||||||
}
|
}
|
||||||
#endif /* defined(HAVE_WEAK_ATTRIBUTE) && defined(TORTURE_SHARED) */
|
#endif /* defined(HAVE_WEAK_ATTRIBUTE) && defined(TORTURE_SHARED) */
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
/**
|
||||||
|
* Finalize the torture context. No-op except for OpenSSL or GSSAPI
|
||||||
|
*
|
||||||
|
* When OpenSSL is built without the at-exit handlers, it won't call the
|
||||||
|
* OPENSSL_cleanup() from destructor or at-exit handler, which means we need to
|
||||||
|
* do it manually in the tests.
|
||||||
|
*
|
||||||
|
* It is never a good idea to call this function from the library context as we
|
||||||
|
* can not be sure the libssh is really the last one using the OpenSSL.
|
||||||
|
*
|
||||||
|
* This needs to be called at the end of the main function or any time before
|
||||||
|
* any forked process (servers) exits.
|
||||||
|
*/
|
||||||
|
void torture_finalize(void)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_LIBCRYPTO) || defined(WITH_GSSAPI)
|
||||||
|
OPENSSL_cleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
struct argument_s arguments;
|
struct argument_s arguments;
|
||||||
char *env = getenv("LIBSSH_VERBOSITY");
|
char *env = getenv("LIBSSH_VERBOSITY");
|
||||||
|
int rv;
|
||||||
|
|
||||||
arguments.verbose=0;
|
arguments.verbose=0;
|
||||||
arguments.pattern=NULL;
|
arguments.pattern=NULL;
|
||||||
@@ -1868,5 +1895,9 @@ int main(int argc, char **argv) {
|
|||||||
cmocka_set_test_filter(pattern);
|
cmocka_set_test_filter(pattern);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return torture_run_tests();
|
rv = torture_run_tests();
|
||||||
|
|
||||||
|
torture_finalize();
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,4 +178,6 @@ int torture_change_dir(char *path);
|
|||||||
void torture_setenv(char const* variable, char const* value);
|
void torture_setenv(char const* variable, char const* value);
|
||||||
void torture_unsetenv(char const* variable);
|
void torture_unsetenv(char const* variable);
|
||||||
|
|
||||||
|
void torture_finalize(void);
|
||||||
|
|
||||||
#endif /* _TORTURE_H */
|
#endif /* _TORTURE_H */
|
||||||
|
|||||||
@@ -98,6 +98,13 @@ if (UNIX AND NOT WIN32)
|
|||||||
endif (WITH_SERVER)
|
endif (WITH_SERVER)
|
||||||
endif (UNIX AND NOT WIN32)
|
endif (UNIX AND NOT WIN32)
|
||||||
|
|
||||||
|
if (WITH_SFTP)
|
||||||
|
set(LIBSSH_UNIT_TESTS
|
||||||
|
${LIBSSH_UNIT_TESTS}
|
||||||
|
torture_unit_sftp
|
||||||
|
)
|
||||||
|
endif (WITH_SFTP)
|
||||||
|
|
||||||
foreach(_UNIT_TEST ${LIBSSH_UNIT_TESTS})
|
foreach(_UNIT_TEST ${LIBSSH_UNIT_TESTS})
|
||||||
add_cmocka_test(${_UNIT_TEST}
|
add_cmocka_test(${_UNIT_TEST}
|
||||||
SOURCES ${_UNIT_TEST}.c
|
SOURCES ${_UNIT_TEST}.c
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ extern LIBSSH_THREAD int ssh_log_level;
|
|||||||
#define LIBSSH_TEST_NONEWLINEONELINE "libssh_test_NoNewLineOneline.tmp"
|
#define LIBSSH_TEST_NONEWLINEONELINE "libssh_test_NoNewLineOneline.tmp"
|
||||||
#define LIBSSH_TEST_RECURSIVE_INCLUDE "libssh_test_recursive_include.tmp"
|
#define LIBSSH_TEST_RECURSIVE_INCLUDE "libssh_test_recursive_include.tmp"
|
||||||
#define LIBSSH_TESTCONFIG_MATCH_COMPLEX "libssh_test_match_complex.tmp"
|
#define LIBSSH_TESTCONFIG_MATCH_COMPLEX "libssh_test_match_complex.tmp"
|
||||||
|
#define LIBSSH_TESTCONFIG_LOGLEVEL_MISSING "libssh_test_loglevel_missing.tmp"
|
||||||
|
#define LIBSSH_TESTCONFIG_JUMP "libssh_test_jump.tmp"
|
||||||
|
|
||||||
#define LIBSSH_TESTCONFIG_STRING1 \
|
#define LIBSSH_TESTCONFIG_STRING1 \
|
||||||
"User "USERNAME"\nInclude "LIBSSH_TESTCONFIG2"\n\n"
|
"User "USERNAME"\nInclude "LIBSSH_TESTCONFIG2"\n\n"
|
||||||
@@ -243,6 +245,26 @@ extern LIBSSH_THREAD int ssh_log_level;
|
|||||||
"\tForwardAgent yes\n" \
|
"\tForwardAgent yes\n" \
|
||||||
"\tHostName complex-match\n"
|
"\tHostName complex-match\n"
|
||||||
|
|
||||||
|
#define LIBSSH_TESTCONFIG_LOGLEVEL_MISSING_STRING "LogLevel\n"
|
||||||
|
#define LIBSSH_TESTCONFIG_JUMP_STRING \
|
||||||
|
"# The jump host\n" \
|
||||||
|
"Host ub-jumphost\n" \
|
||||||
|
" HostName 1xxxxxx\n" \
|
||||||
|
" User ubuntu\n" \
|
||||||
|
" IdentityFile ~/of/temp-libssh.pem\n" \
|
||||||
|
" Port 23\n" \
|
||||||
|
" LogLevel DEBUG3\n" \
|
||||||
|
"\n" \
|
||||||
|
"# Cisco Router through Jump Host\n" \
|
||||||
|
"Host cisco-router\n" \
|
||||||
|
" HostName xx.xxxxxxxxx\n" \
|
||||||
|
" User username\n" \
|
||||||
|
" ProxyJump ub-jumphost\n" \
|
||||||
|
" Port 5555\n" \
|
||||||
|
" #RequiredRSASize 512\n" \
|
||||||
|
" PasswordAuthentication yes\n" \
|
||||||
|
" LogLevel DEBUG3\n"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief helper function loading configuration from either file or string
|
* @brief helper function loading configuration from either file or string
|
||||||
*/
|
*/
|
||||||
@@ -293,6 +315,8 @@ static int setup_config_files(void **state)
|
|||||||
unlink(LIBSSH_TEST_NONEWLINEEND);
|
unlink(LIBSSH_TEST_NONEWLINEEND);
|
||||||
unlink(LIBSSH_TEST_NONEWLINEONELINE);
|
unlink(LIBSSH_TEST_NONEWLINEONELINE);
|
||||||
unlink(LIBSSH_TESTCONFIG_MATCH_COMPLEX);
|
unlink(LIBSSH_TESTCONFIG_MATCH_COMPLEX);
|
||||||
|
unlink(LIBSSH_TESTCONFIG_LOGLEVEL_MISSING);
|
||||||
|
unlink(LIBSSH_TESTCONFIG_JUMP);
|
||||||
|
|
||||||
torture_write_file(LIBSSH_TESTCONFIG1,
|
torture_write_file(LIBSSH_TESTCONFIG1,
|
||||||
LIBSSH_TESTCONFIG_STRING1);
|
LIBSSH_TESTCONFIG_STRING1);
|
||||||
@@ -361,6 +385,10 @@ static int setup_config_files(void **state)
|
|||||||
/* Match complex combinations */
|
/* Match complex combinations */
|
||||||
torture_write_file(LIBSSH_TESTCONFIG_MATCH_COMPLEX,
|
torture_write_file(LIBSSH_TESTCONFIG_MATCH_COMPLEX,
|
||||||
LIBSSH_TESTCONFIG_MATCH_COMPLEX_STRING);
|
LIBSSH_TESTCONFIG_MATCH_COMPLEX_STRING);
|
||||||
|
torture_write_file(LIBSSH_TESTCONFIG_LOGLEVEL_MISSING,
|
||||||
|
LIBSSH_TESTCONFIG_LOGLEVEL_MISSING_STRING);
|
||||||
|
torture_write_file(LIBSSH_TESTCONFIG_JUMP,
|
||||||
|
LIBSSH_TESTCONFIG_JUMP_STRING);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -390,6 +418,8 @@ static int teardown_config_files(void **state)
|
|||||||
unlink(LIBSSH_TEST_NONEWLINEEND);
|
unlink(LIBSSH_TEST_NONEWLINEEND);
|
||||||
unlink(LIBSSH_TEST_NONEWLINEONELINE);
|
unlink(LIBSSH_TEST_NONEWLINEONELINE);
|
||||||
unlink(LIBSSH_TESTCONFIG_MATCH_COMPLEX);
|
unlink(LIBSSH_TESTCONFIG_MATCH_COMPLEX);
|
||||||
|
unlink(LIBSSH_TESTCONFIG_LOGLEVEL_MISSING);
|
||||||
|
unlink(LIBSSH_TESTCONFIG_JUMP);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2342,80 +2372,138 @@ static void torture_config_match_pattern(void **state)
|
|||||||
(void) state;
|
(void) state;
|
||||||
|
|
||||||
/* Simple test "a" matches "a" */
|
/* Simple test "a" matches "a" */
|
||||||
rv = match_pattern("a", "a", MAX_MATCH_RECURSION);
|
rv = match_pattern("a", "a");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
/* Simple test "a" does not match "b" */
|
/* Simple test "a" does not match "b" */
|
||||||
rv = match_pattern("a", "b", MAX_MATCH_RECURSION);
|
rv = match_pattern("a", "b");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
|
|
||||||
/* NULL arguments are correctly handled */
|
/* NULL arguments are correctly handled */
|
||||||
rv = match_pattern("a", NULL, MAX_MATCH_RECURSION);
|
rv = match_pattern("a", NULL);
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
rv = match_pattern(NULL, "a", MAX_MATCH_RECURSION);
|
rv = match_pattern(NULL, "a");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
|
|
||||||
/* Simple wildcard ? is handled in pattern */
|
/* Simple wildcard ? is handled in pattern */
|
||||||
rv = match_pattern("a", "?", MAX_MATCH_RECURSION);
|
rv = match_pattern("a", "?");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("aa", "?", MAX_MATCH_RECURSION);
|
rv = match_pattern("aa", "?");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
/* Wildcard in search string */
|
/* Wildcard in search string */
|
||||||
rv = match_pattern("?", "a", MAX_MATCH_RECURSION);
|
rv = match_pattern("?", "a");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
rv = match_pattern("?", "?", MAX_MATCH_RECURSION);
|
rv = match_pattern("?", "?");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
/* Simple wildcard * is handled in pattern */
|
/* Simple wildcard * is handled in pattern */
|
||||||
rv = match_pattern("a", "*", MAX_MATCH_RECURSION);
|
rv = match_pattern("a", "*");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("aa", "*", MAX_MATCH_RECURSION);
|
rv = match_pattern("aa", "*");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
/* Wildcard in search string */
|
/* Wildcard in search string */
|
||||||
rv = match_pattern("*", "a", MAX_MATCH_RECURSION);
|
rv = match_pattern("*", "a");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
rv = match_pattern("*", "*", MAX_MATCH_RECURSION);
|
rv = match_pattern("*", "*");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
/* More complicated patterns */
|
/* More complicated patterns */
|
||||||
rv = match_pattern("a", "*a", MAX_MATCH_RECURSION);
|
rv = match_pattern("a", "*a");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("a", "a*", MAX_MATCH_RECURSION);
|
rv = match_pattern("a", "a*");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("abababc", "*abc", MAX_MATCH_RECURSION);
|
rv = match_pattern("abababc", "*abc");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("ababababca", "*abc", MAX_MATCH_RECURSION);
|
rv = match_pattern("ababababca", "*abc");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
rv = match_pattern("ababababca", "*abc*", MAX_MATCH_RECURSION);
|
rv = match_pattern("ababababca", "*abc*");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
/* Multiple wildcards in row */
|
/* Multiple wildcards in row */
|
||||||
rv = match_pattern("aa", "??", MAX_MATCH_RECURSION);
|
rv = match_pattern("aa", "??");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("bba", "??a", MAX_MATCH_RECURSION);
|
rv = match_pattern("bba", "??a");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("aaa", "**a", MAX_MATCH_RECURSION);
|
rv = match_pattern("aaa", "**a");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("bbb", "**a", MAX_MATCH_RECURSION);
|
rv = match_pattern("bbb", "**a");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
|
|
||||||
/* Consecutive asterisks do not make sense and do not need to recurse */
|
/* Consecutive asterisks do not make sense and do not need to recurse */
|
||||||
rv = match_pattern("hostname", "**********pattern", 5);
|
rv = match_pattern("hostname", "**********pattern");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
rv = match_pattern("hostname", "pattern**********", 5);
|
rv = match_pattern("hostname", "pattern**********");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
rv = match_pattern("pattern", "***********pattern", 5);
|
rv = match_pattern("pattern", "***********pattern");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
rv = match_pattern("pattern", "pattern***********", 5);
|
rv = match_pattern("pattern", "pattern***********");
|
||||||
assert_int_equal(rv, 1);
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
/* Limit the maximum recursion */
|
rv = match_pattern("hostname", "*p*a*t*t*e*r*n*");
|
||||||
rv = match_pattern("hostname", "*p*a*t*t*e*r*n*", 5);
|
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
/* Too much recursion */
|
rv = match_pattern("pattern", "*p*a*t*t*e*r*n*");
|
||||||
rv = match_pattern("pattern", "*p*a*t*t*e*r*n*", 5);
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* Regular Expression Denial of Service */
|
||||||
|
rv = match_pattern("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
rv = match_pattern("ababababababababababababababababababababab",
|
||||||
|
"*a*b*a*b*a*b*a*b*a*b*a*b*a*b*a*b");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* A lot of backtracking */
|
||||||
|
rv = match_pattern("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax",
|
||||||
|
"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*ax");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* Test backtracking: *a matches first 'a', fails on 'b', must backtrack */
|
||||||
|
rv = match_pattern("axaxaxb", "*a*b");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* Test greedy consumption with suffix */
|
||||||
|
rv = match_pattern("foo_bar_baz_bar", "*bar");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* Test exact suffix requirement (ensure no partial match acceptance) */
|
||||||
|
rv = match_pattern("foobar_extra", "*bar");
|
||||||
assert_int_equal(rv, 0);
|
assert_int_equal(rv, 0);
|
||||||
|
|
||||||
|
/* Test multiple distinct wildcards */
|
||||||
|
rv = match_pattern("a_very_long_string_with_a_pattern", "*long*pattern");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* ? inside a * sequence */
|
||||||
|
rv = match_pattern("abcdefg", "a*c?e*g");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* Consecutive mixed wildcards */
|
||||||
|
rv = match_pattern("abc", "*?c");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* ? at the very end after * */
|
||||||
|
rv = match_pattern("abc", "ab?");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
rv = match_pattern("abc", "ab*?");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* Consecutive stars should be collapsed or handled gracefully */
|
||||||
|
rv = match_pattern("abc", "a**c");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
rv = match_pattern("abc", "***");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* Empty string handling */
|
||||||
|
rv = match_pattern("", "*");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
rv = match_pattern("", "?");
|
||||||
|
assert_int_equal(rv, 0);
|
||||||
|
rv = match_pattern("", "");
|
||||||
|
assert_int_equal(rv, 1);
|
||||||
|
|
||||||
|
/* Pattern longer than string */
|
||||||
|
rv = match_pattern("short", "short_but_longer");
|
||||||
|
assert_int_equal(rv, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Identity file can be specified multiple times in the configuration
|
/* Identity file can be specified multiple times in the configuration
|
||||||
@@ -2468,9 +2556,9 @@ static void torture_config_make_absolute_int(void **state, bool no_sshdir_fails)
|
|||||||
char *home = NULL;
|
char *home = NULL;
|
||||||
struct passwd *pw = getpwuid(getuid());
|
struct passwd *pw = getpwuid(getuid());
|
||||||
assert_non_null(pw);
|
assert_non_null(pw);
|
||||||
user = pw->pw_name;
|
user = strdup(pw->pw_name);
|
||||||
assert_non_null(user);
|
assert_non_null(user);
|
||||||
home = pw->pw_dir;
|
home = strdup(pw->pw_dir);
|
||||||
assert_non_null(home);
|
assert_non_null(home);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2528,6 +2616,8 @@ static void torture_config_make_absolute_int(void **state, bool no_sshdir_fails)
|
|||||||
snprintf(h, 256 - 1, "/etc/ssh/~%s/.ssh/config.d/*.conf", user);
|
snprintf(h, 256 - 1, "/etc/ssh/~%s/.ssh/config.d/*.conf", user);
|
||||||
assert_string_equal(result, h);
|
assert_string_equal(result, h);
|
||||||
free(result);
|
free(result);
|
||||||
|
free(home);
|
||||||
|
free(user);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2615,6 +2705,129 @@ static void torture_config_match_complex(void **state)
|
|||||||
ssh_string_free_char(v);
|
ssh_string_free_char(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Missing value to LogLevel configuration option
|
||||||
|
*/
|
||||||
|
static void torture_config_loglevel_missing_value(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session = *state;
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "Bar");
|
||||||
|
|
||||||
|
_parse_config(session, LIBSSH_TESTCONFIG_LOGLEVEL_MISSING, NULL, SSH_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int before_connection(ssh_session jump_session, void *user)
|
||||||
|
{
|
||||||
|
char *v = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
/* During the connection, we force parsing the same configuration file
|
||||||
|
* (would be normally parsed automatically during the connection itself)
|
||||||
|
*/
|
||||||
|
ret = ssh_config_parse_file(jump_session, LIBSSH_TESTCONFIG_JUMP);
|
||||||
|
assert_return_code(ret, errno);
|
||||||
|
|
||||||
|
/* Test the variable presence */
|
||||||
|
ret = ssh_options_get(jump_session, SSH_OPTIONS_HOST, &v);
|
||||||
|
assert_return_code(ret, errno);
|
||||||
|
assert_string_equal(v, "1xxxxxx");
|
||||||
|
ssh_string_free_char(v);
|
||||||
|
|
||||||
|
ret = ssh_options_get(jump_session, SSH_OPTIONS_USER, &v);
|
||||||
|
assert_return_code(ret, errno);
|
||||||
|
assert_string_equal(v, "ubuntu");
|
||||||
|
ssh_string_free_char(v);
|
||||||
|
|
||||||
|
assert_int_equal(jump_session->opts.port, 23);
|
||||||
|
|
||||||
|
/* Fail the connection -- we are in unit tests so it would fail anyway */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_knownhost(ssh_session jump_session, void *user)
|
||||||
|
{
|
||||||
|
(void)jump_session;
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int authenticate(ssh_session jump_session, void *user)
|
||||||
|
{
|
||||||
|
(void)jump_session;
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Reproducer for complex proxy jump
|
||||||
|
*/
|
||||||
|
static void torture_config_jump(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session = *state;
|
||||||
|
struct ssh_jump_callbacks_struct c = {
|
||||||
|
.before_connection = before_connection,
|
||||||
|
.verify_knownhost = verify_knownhost,
|
||||||
|
.authenticate = authenticate,
|
||||||
|
};
|
||||||
|
char *v = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "cisco-router");
|
||||||
|
|
||||||
|
_parse_config(session, LIBSSH_TESTCONFIG_JUMP, NULL, SSH_OK);
|
||||||
|
|
||||||
|
/* Test the variable presence */
|
||||||
|
ret = ssh_options_get(session, SSH_OPTIONS_HOST, &v);
|
||||||
|
assert_return_code(ret, errno);
|
||||||
|
assert_string_equal(v, "xx.xxxxxxxxx");
|
||||||
|
ssh_string_free_char(v);
|
||||||
|
|
||||||
|
ret = ssh_options_get(session, SSH_OPTIONS_USER, &v);
|
||||||
|
assert_return_code(ret, errno);
|
||||||
|
assert_string_equal(v, "username");
|
||||||
|
ssh_string_free_char(v);
|
||||||
|
|
||||||
|
assert_int_equal(session->opts.port, 5555);
|
||||||
|
|
||||||
|
/* At this point, the configuration file is not parsed for the jump host so
|
||||||
|
* we are getting just the the hostname -- the port and username will get
|
||||||
|
* pulled during the session connecting to this host */
|
||||||
|
assert_int_equal(ssh_list_count(session->opts.proxy_jumps), 1);
|
||||||
|
helper_proxy_jump_check(session->opts.proxy_jumps->root,
|
||||||
|
"ub-jumphost",
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Set up the callbacks -- they should verify we are going to connect to the
|
||||||
|
* right host */
|
||||||
|
ret = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND, &c);
|
||||||
|
assert_ssh_return_code(session, ret);
|
||||||
|
|
||||||
|
ret = ssh_connect(session);
|
||||||
|
assert_ssh_return_code_equal(session, ret, SSH_ERROR);
|
||||||
|
|
||||||
|
printf("%s: EOF\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalid configuration files
|
||||||
|
*/
|
||||||
|
static void torture_config_invalid(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session = *state;
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "Bar");
|
||||||
|
|
||||||
|
/* non-regular file -- ignored (or missing on non-unix) so OK */
|
||||||
|
_parse_config(session, "/dev/random", NULL, SSH_OK);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
/* huge file -- ignored (or missing on non-unix) so OK */
|
||||||
|
_parse_config(session, "/proc/kcore", NULL, SSH_OK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void)
|
int torture_run_tests(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@@ -2711,6 +2924,15 @@ int torture_run_tests(void)
|
|||||||
setup, teardown),
|
setup, teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_config_match_complex,
|
cmocka_unit_test_setup_teardown(torture_config_match_complex,
|
||||||
setup, teardown),
|
setup, teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_config_loglevel_missing_value,
|
||||||
|
setup,
|
||||||
|
teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_config_jump,
|
||||||
|
setup,
|
||||||
|
teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_config_invalid,
|
||||||
|
setup,
|
||||||
|
teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -696,6 +696,82 @@ static void torture_knownhosts_algorithms_global(void **state)
|
|||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int setup_bad_knownhosts_file(void **state)
|
||||||
|
{
|
||||||
|
char *tmp_file = NULL;
|
||||||
|
size_t nwritten;
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
tmp_file = torture_create_temp_file(TMP_FILE_NAME);
|
||||||
|
assert_non_null(tmp_file);
|
||||||
|
|
||||||
|
*state = tmp_file;
|
||||||
|
|
||||||
|
fp = fopen(tmp_file, "w");
|
||||||
|
assert_non_null(fp);
|
||||||
|
|
||||||
|
nwritten = fwrite(LOCALHOST_DEFAULT_ED25519,
|
||||||
|
sizeof(char),
|
||||||
|
strlen(LOCALHOST_DEFAULT_ED25519),
|
||||||
|
fp);
|
||||||
|
if (nwritten != strlen(LOCALHOST_DEFAULT_ED25519)) {
|
||||||
|
rc = -1;
|
||||||
|
goto close_fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
nwritten = fwrite("\n", sizeof(char), 1, fp);
|
||||||
|
if (nwritten != 1) {
|
||||||
|
rc = -1;
|
||||||
|
goto close_fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOCALHOST_BAD_LINE "localhost \n"
|
||||||
|
nwritten = fwrite(LOCALHOST_BAD_LINE,
|
||||||
|
sizeof(char),
|
||||||
|
strlen(LOCALHOST_BAD_LINE),
|
||||||
|
fp);
|
||||||
|
if (nwritten != strlen(LOCALHOST_BAD_LINE)) {
|
||||||
|
rc = -1;
|
||||||
|
goto close_fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
close_fp:
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_knownhosts_has_entry(void **state)
|
||||||
|
{
|
||||||
|
const char *knownhosts_file = *state;
|
||||||
|
enum ssh_known_hosts_e found;
|
||||||
|
ssh_session session;
|
||||||
|
bool process_config = false;
|
||||||
|
struct ssh_knownhosts_entry *entry = NULL;
|
||||||
|
|
||||||
|
session = ssh_new();
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
/* This makes sure the global configuration file is not processed */
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config);
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||||
|
/* This makes sure the current-user's known hosts are not used */
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "/dev/null");
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, knownhosts_file);
|
||||||
|
|
||||||
|
/* Error is expected -- this tests the memory is not leaked from this
|
||||||
|
* test case */
|
||||||
|
found = ssh_session_has_known_hosts_entry(session);
|
||||||
|
assert_int_equal(found, SSH_KNOWN_HOSTS_ERROR);
|
||||||
|
|
||||||
|
found = ssh_session_get_known_hosts_entry(session, &entry);
|
||||||
|
assert_int_equal(found, SSH_KNOWN_HOSTS_ERROR);
|
||||||
|
assert_null(entry);
|
||||||
|
|
||||||
|
ssh_free(session);
|
||||||
|
}
|
||||||
#endif /* _WIN32 There is no /dev/null on Windows */
|
#endif /* _WIN32 There is no /dev/null on Windows */
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
@@ -738,6 +814,9 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_knownhosts_algorithms_global,
|
cmocka_unit_test_setup_teardown(torture_knownhosts_algorithms_global,
|
||||||
setup_knownhosts_file,
|
setup_knownhosts_file,
|
||||||
teardown_knownhosts_file),
|
teardown_knownhosts_file),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_knownhosts_has_entry,
|
||||||
|
setup_bad_knownhosts_file,
|
||||||
|
teardown_knownhosts_file),
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1129,6 +1129,36 @@ static void torture_ssh_is_ipaddr(void **state) {
|
|||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_ssh_get_hexa(void **state)
|
||||||
|
{
|
||||||
|
const unsigned char *bin = NULL;
|
||||||
|
char *hex = NULL;
|
||||||
|
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
/* Null pointer should not crash */
|
||||||
|
bin = NULL;
|
||||||
|
hex = ssh_get_hexa(bin, 0);
|
||||||
|
assert_null(hex);
|
||||||
|
|
||||||
|
/* Null pointer should not crash regardless the length */
|
||||||
|
bin = NULL;
|
||||||
|
hex = ssh_get_hexa(bin, 99);
|
||||||
|
assert_null(hex);
|
||||||
|
|
||||||
|
/* Zero length input is not much useful. Just expect NULL too */
|
||||||
|
bin = (const unsigned char *)"";
|
||||||
|
hex = ssh_get_hexa(bin, 0);
|
||||||
|
assert_null(hex);
|
||||||
|
|
||||||
|
/* Valid inputs */
|
||||||
|
bin = (const unsigned char *)"\x00\xFF";
|
||||||
|
hex = ssh_get_hexa(bin, 2);
|
||||||
|
assert_non_null(hex);
|
||||||
|
assert_string_equal(hex, "00:ff");
|
||||||
|
ssh_string_free_char(hex);
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
@@ -1158,6 +1188,7 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test(torture_ssh_check_hostname_syntax),
|
cmocka_unit_test(torture_ssh_check_hostname_syntax),
|
||||||
cmocka_unit_test(torture_ssh_check_username_syntax),
|
cmocka_unit_test(torture_ssh_check_username_syntax),
|
||||||
cmocka_unit_test(torture_ssh_is_ipaddr),
|
cmocka_unit_test(torture_ssh_is_ipaddr),
|
||||||
|
cmocka_unit_test(torture_ssh_get_hexa),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -367,10 +367,14 @@ static void torture_pki_ecdsa_publickey_from_privatekey(void **state)
|
|||||||
static void torture_pki_ecdsa_import_cert_file(void **state)
|
static void torture_pki_ecdsa_import_cert_file(void **state)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
ssh_key pubkey = NULL;
|
||||||
|
ssh_key privkey = NULL;
|
||||||
ssh_key cert = NULL;
|
ssh_key cert = NULL;
|
||||||
enum ssh_keytypes_e type;
|
enum ssh_keytypes_e type, exp_cert_type;
|
||||||
struct pki_st *test_state = *((struct pki_st **)state);
|
struct pki_st *test_state = *((struct pki_st **)state);
|
||||||
|
|
||||||
|
exp_cert_type = test_state->type + 3;
|
||||||
|
|
||||||
/* Importing public key as cert should fail */
|
/* Importing public key as cert should fail */
|
||||||
rc = ssh_pki_import_cert_file(LIBSSH_ECDSA_TESTKEY ".pub", &cert);
|
rc = ssh_pki_import_cert_file(LIBSSH_ECDSA_TESTKEY ".pub", &cert);
|
||||||
assert_int_equal(rc, SSH_ERROR);
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
@@ -380,13 +384,78 @@ static void torture_pki_ecdsa_import_cert_file(void **state)
|
|||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
assert_non_null(cert);
|
assert_non_null(cert);
|
||||||
|
|
||||||
|
rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY ".pub", &pubkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
type = ssh_key_type(cert);
|
type = ssh_key_type(cert);
|
||||||
assert_int_equal(type, test_state->type+3);
|
assert_int_equal(type, exp_cert_type);
|
||||||
|
|
||||||
rc = ssh_key_is_public(cert);
|
rc = ssh_key_is_public(cert);
|
||||||
assert_int_equal(rc, 1);
|
assert_int_equal(rc, 1);
|
||||||
|
|
||||||
|
/* Import matching private key file and verify the pubkey matches */
|
||||||
|
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&privkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(privkey);
|
||||||
|
|
||||||
|
type = ssh_key_type(privkey);
|
||||||
|
assert_true(type == test_state->type);
|
||||||
|
|
||||||
|
/* Basic sanity. */
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(NULL, privkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(pubkey, NULL);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/* A public key doesn't have a cert, copy should fail. */
|
||||||
|
assert_null(pubkey->cert);
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(pubkey, privkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/* Copying the cert to non-cert keys should work fine. */
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(pubkey->cert);
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(privkey->cert);
|
||||||
|
assert_true(privkey->cert_type == exp_cert_type);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 0);
|
||||||
|
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 0);
|
||||||
|
|
||||||
|
/* The private key's cert is already set, another copy should fail. */
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
SSH_KEY_FREE(privkey);
|
||||||
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
|
/* Generate different key and try to assign it this certificate */
|
||||||
|
rc = ssh_pki_generate(test_state->type, 256, &privkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(privkey);
|
||||||
|
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 1);
|
||||||
|
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 1);
|
||||||
|
|
||||||
SSH_KEY_FREE(cert);
|
SSH_KEY_FREE(cert);
|
||||||
|
SSH_KEY_FREE(privkey);
|
||||||
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ecdsa_publickey_base64(void **state)
|
static void torture_pki_ecdsa_publickey_base64(void **state)
|
||||||
|
|||||||
@@ -312,6 +312,8 @@ static void torture_pki_ed25519_publickey_from_privatekey(void **state)
|
|||||||
static void torture_pki_ed25519_import_cert_file(void **state)
|
static void torture_pki_ed25519_import_cert_file(void **state)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
ssh_key pubkey = NULL;
|
||||||
|
ssh_key privkey = NULL;
|
||||||
ssh_key cert = NULL;
|
ssh_key cert = NULL;
|
||||||
enum ssh_keytypes_e type;
|
enum ssh_keytypes_e type;
|
||||||
|
|
||||||
@@ -323,16 +325,88 @@ static void torture_pki_ed25519_import_cert_file(void **state)
|
|||||||
assert_null(cert);
|
assert_null(cert);
|
||||||
|
|
||||||
rc = ssh_pki_import_cert_file(LIBSSH_ED25519_TESTKEY "-cert.pub", &cert);
|
rc = ssh_pki_import_cert_file(LIBSSH_ED25519_TESTKEY "-cert.pub", &cert);
|
||||||
assert_true(rc == 0);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(cert);
|
assert_non_null(cert);
|
||||||
|
|
||||||
|
rc = ssh_pki_import_pubkey_file(LIBSSH_ED25519_TESTKEY ".pub", &pubkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
type = ssh_key_type(cert);
|
type = ssh_key_type(cert);
|
||||||
assert_true(type == SSH_KEYTYPE_ED25519_CERT01);
|
assert_true(type == SSH_KEYTYPE_ED25519_CERT01);
|
||||||
|
|
||||||
rc = ssh_key_is_public(cert);
|
rc = ssh_key_is_public(cert);
|
||||||
assert_true(rc == 1);
|
assert_int_equal(rc, 1);
|
||||||
|
|
||||||
|
/* Skip test if in FIPS mode */
|
||||||
|
if (ssh_fips_mode()) {
|
||||||
|
SSH_KEY_FREE(cert);
|
||||||
|
SSH_KEY_FREE(pubkey);
|
||||||
|
skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Import matching private key file and verify the pubkey matches */
|
||||||
|
rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&privkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(privkey);
|
||||||
|
|
||||||
|
type = ssh_key_type(privkey);
|
||||||
|
assert_true(type == SSH_KEYTYPE_ED25519);
|
||||||
|
|
||||||
|
/* Basic sanity. */
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(NULL, privkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(pubkey, NULL);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/* A public key doesn't have a cert, copy should fail. */
|
||||||
|
assert_null(pubkey->cert);
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(pubkey, privkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/* Copying the cert to non-cert keys should work fine. */
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(pubkey->cert);
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(privkey->cert);
|
||||||
|
assert_true(privkey->cert_type == SSH_KEYTYPE_ED25519_CERT01);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 0);
|
||||||
|
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 0);
|
||||||
|
|
||||||
|
/* The private key's cert is already set, another copy should fail. */
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
SSH_KEY_FREE(privkey);
|
||||||
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
|
/* Generate different key and try to assign it this certificate */
|
||||||
|
rc = ssh_pki_generate(SSH_KEYTYPE_ED25519, 0, &privkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(privkey);
|
||||||
|
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
|
||||||
|
assert_return_code(rc, errno);
|
||||||
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 1);
|
||||||
|
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 1);
|
||||||
|
|
||||||
SSH_KEY_FREE(cert);
|
SSH_KEY_FREE(cert);
|
||||||
|
SSH_KEY_FREE(privkey);
|
||||||
|
SSH_KEY_FREE(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_ed25519_publickey_base64(void **state)
|
static void torture_pki_ed25519_publickey_base64(void **state)
|
||||||
|
|||||||
@@ -373,6 +373,7 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
|||||||
ssh_key pubkey = NULL;
|
ssh_key pubkey = NULL;
|
||||||
ssh_key privkey = NULL;
|
ssh_key privkey = NULL;
|
||||||
ssh_key cert = NULL;
|
ssh_key cert = NULL;
|
||||||
|
enum ssh_keytypes_e type;
|
||||||
|
|
||||||
(void)state; /* unused */
|
(void)state; /* unused */
|
||||||
|
|
||||||
@@ -389,6 +390,13 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(pubkey);
|
assert_non_null(pubkey);
|
||||||
|
|
||||||
|
type = ssh_key_type(cert);
|
||||||
|
assert_true(type == SSH_KEYTYPE_RSA_CERT01);
|
||||||
|
|
||||||
|
rc = ssh_key_is_public(cert);
|
||||||
|
assert_int_equal(rc, 1);
|
||||||
|
|
||||||
|
/* Import matching private key file and verify the pubkey matches */
|
||||||
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0),
|
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0),
|
||||||
passphrase,
|
passphrase,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -397,6 +405,9 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
|||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(privkey);
|
assert_non_null(privkey);
|
||||||
|
|
||||||
|
type = ssh_key_type(privkey);
|
||||||
|
assert_true(type == SSH_KEYTYPE_RSA);
|
||||||
|
|
||||||
/* Basic sanity. */
|
/* Basic sanity. */
|
||||||
rc = ssh_pki_copy_cert_to_privkey(NULL, privkey);
|
rc = ssh_pki_copy_cert_to_privkey(NULL, privkey);
|
||||||
assert_int_equal(rc, SSH_ERROR);
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
@@ -416,6 +427,10 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
|||||||
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
assert_non_null(privkey->cert);
|
assert_non_null(privkey->cert);
|
||||||
|
assert_true(privkey->cert_type == SSH_KEYTYPE_RSA_CERT01);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 0);
|
||||||
|
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 0);
|
||||||
|
|
||||||
/* The private key's cert is already set, another copy should fail. */
|
/* The private key's cert is already set, another copy should fail. */
|
||||||
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
|
||||||
@@ -437,6 +452,9 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
|||||||
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
|
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
|
||||||
assert_int_equal(rc, SSH_ERROR);
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 1);
|
||||||
|
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 1);
|
||||||
|
|
||||||
SSH_KEY_FREE(cert);
|
SSH_KEY_FREE(cert);
|
||||||
SSH_KEY_FREE(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
SSH_KEY_FREE(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|||||||
@@ -58,14 +58,8 @@ static int run_on_threads(void *(*func)(void *))
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NUM_THREADS; ++i) {
|
for (i = 0; i < NUM_THREADS; ++i) {
|
||||||
void *p = NULL;
|
rc = pthread_join(threads[i], NULL);
|
||||||
uint64_t *result;
|
|
||||||
|
|
||||||
rc = pthread_join(threads[i], &p);
|
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
result = (uint64_t *)p;
|
|
||||||
assert_null(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -133,10 +127,9 @@ static int teardown(void **state) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int disable_secmem(void **state)
|
static void
|
||||||
|
disable_secmem(void)
|
||||||
{
|
{
|
||||||
(void) state; /*unused*/
|
|
||||||
|
|
||||||
#if defined(HAVE_LIBGCRYPT)
|
#if defined(HAVE_LIBGCRYPT)
|
||||||
/* gcrypt currently is configured to use only 4kB of locked secmem
|
/* gcrypt currently is configured to use only 4kB of locked secmem
|
||||||
* (see ssh_crypto_init() in src/libcrypt.c)
|
* (see ssh_crypto_init() in src/libcrypt.c)
|
||||||
@@ -147,21 +140,8 @@ static int disable_secmem(void **state)
|
|||||||
|
|
||||||
gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
|
gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||||
gcry_control(GCRYCTL_DISABLE_SECMEM);
|
gcry_control(GCRYCTL_DISABLE_SECMEM);
|
||||||
|
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int enable_secmem(void **state)
|
|
||||||
{
|
|
||||||
(void) state; /*unused*/
|
|
||||||
|
|
||||||
#if defined(HAVE_LIBGCRYPT)
|
|
||||||
/* Re-enable secmem */
|
|
||||||
gcry_control(GCRYCTL_INIT_SECMEM, 4096);
|
|
||||||
gcry_control(GCRYCTL_RESUME_SECMEM_WARN);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *thread_pki_rsa_import_pubkey_file(void *threadid)
|
static void *thread_pki_rsa_import_pubkey_file(void *threadid)
|
||||||
@@ -178,7 +158,7 @@ static void *thread_pki_rsa_import_pubkey_file(void *threadid)
|
|||||||
|
|
||||||
SSH_KEY_FREE(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
pthread_exit(NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_pubkey_file(void **state)
|
static void torture_pki_rsa_import_pubkey_file(void **state)
|
||||||
@@ -211,8 +191,7 @@ static void *thread_pki_rsa_import_privkey_base64_NULL_key(void *threadid)
|
|||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
return NULL;
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state){
|
static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state){
|
||||||
@@ -239,7 +218,8 @@ static void *thread_pki_rsa_import_privkey_base64_NULL_str(void *threadid)
|
|||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
|
|
||||||
SSH_KEY_FREE(key);
|
SSH_KEY_FREE(key);
|
||||||
pthread_exit(NULL);
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_privkey_base64_NULL_str(void **state){
|
static void torture_pki_rsa_import_privkey_base64_NULL_str(void **state){
|
||||||
@@ -281,7 +261,7 @@ static void *thread_pki_rsa_import_privkey_base64(void *threadid)
|
|||||||
free(key_str);
|
free(key_str);
|
||||||
SSH_KEY_FREE(key);
|
SSH_KEY_FREE(key);
|
||||||
|
|
||||||
pthread_exit(NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_privkey_base64(void **state)
|
static void torture_pki_rsa_import_privkey_base64(void **state)
|
||||||
@@ -324,7 +304,8 @@ static void *thread_pki_rsa_publickey_from_privatekey(void *threadid)
|
|||||||
|
|
||||||
SSH_KEY_FREE(key);
|
SSH_KEY_FREE(key);
|
||||||
SSH_KEY_FREE(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
pthread_exit(NULL);
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_publickey_from_privatekey(void **state)
|
static void torture_pki_rsa_publickey_from_privatekey(void **state)
|
||||||
@@ -397,7 +378,8 @@ static void *thread_pki_rsa_copy_cert_to_privkey(void *threadid)
|
|||||||
SSH_KEY_FREE(cert);
|
SSH_KEY_FREE(cert);
|
||||||
SSH_KEY_FREE(privkey);
|
SSH_KEY_FREE(privkey);
|
||||||
SSH_KEY_FREE(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
pthread_exit(NULL);
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
static void torture_pki_rsa_copy_cert_to_privkey(void **state)
|
||||||
@@ -430,7 +412,8 @@ static void *thread_pki_rsa_import_cert_file(void *threadid)
|
|||||||
assert_true(rc == 1);
|
assert_true(rc == 1);
|
||||||
|
|
||||||
SSH_KEY_FREE(cert);
|
SSH_KEY_FREE(cert);
|
||||||
pthread_exit(NULL);
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_cert_file(void **state)
|
static void torture_pki_rsa_import_cert_file(void **state)
|
||||||
@@ -481,7 +464,8 @@ static void *thread_pki_rsa_publickey_base64(void *threadid)
|
|||||||
free(b64_key);
|
free(b64_key);
|
||||||
free(key_buf);
|
free(key_buf);
|
||||||
SSH_KEY_FREE(key);
|
SSH_KEY_FREE(key);
|
||||||
pthread_exit(NULL);
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_publickey_base64(void **state)
|
static void torture_pki_rsa_publickey_base64(void **state)
|
||||||
@@ -545,7 +529,8 @@ static void *thread_pki_rsa_duplicate_key(void *threadid)
|
|||||||
SSH_KEY_FREE(privkey_dup);
|
SSH_KEY_FREE(privkey_dup);
|
||||||
SSH_STRING_FREE_CHAR(b64_key);
|
SSH_STRING_FREE_CHAR(b64_key);
|
||||||
SSH_STRING_FREE_CHAR(b64_key_gen);
|
SSH_STRING_FREE_CHAR(b64_key_gen);
|
||||||
pthread_exit(NULL);
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_duplicate_key(void **state)
|
static void torture_pki_rsa_duplicate_key(void **state)
|
||||||
@@ -628,7 +613,8 @@ static void *thread_pki_rsa_generate_key(void *threadid)
|
|||||||
SSH_KEY_FREE(pubkey);
|
SSH_KEY_FREE(pubkey);
|
||||||
|
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
pthread_exit(NULL);
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_generate_key(void **state)
|
static void torture_pki_rsa_generate_key(void **state)
|
||||||
@@ -686,7 +672,8 @@ static void *thread_pki_rsa_import_privkey_base64_passphrase(void *threadid)
|
|||||||
assert_true(rc == -1);
|
assert_true(rc == -1);
|
||||||
SSH_KEY_FREE(key);
|
SSH_KEY_FREE(key);
|
||||||
#endif
|
#endif
|
||||||
pthread_exit(NULL);
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_pki_rsa_import_privkey_base64_passphrase(void **state)
|
static void torture_pki_rsa_import_privkey_base64_passphrase(void **state)
|
||||||
@@ -737,14 +724,8 @@ static void torture_mixed(void **state)
|
|||||||
|
|
||||||
for (f = 0; f < NUM_TESTS; f++) {
|
for (f = 0; f < NUM_TESTS; f++) {
|
||||||
for (i = 0; i < NUM_THREADS; ++i) {
|
for (i = 0; i < NUM_THREADS; ++i) {
|
||||||
void *p = NULL;
|
rc = pthread_join(threads[f][i], NULL);
|
||||||
uint64_t *result = NULL;
|
|
||||||
|
|
||||||
rc = pthread_join(threads[f][i], &p);
|
|
||||||
assert_int_equal(rc, 0);
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
result = (uint64_t *)p;
|
|
||||||
assert_null(result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -756,16 +737,19 @@ int torture_run_tests(void)
|
|||||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_file,
|
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_file,
|
||||||
setup_rsa_key,
|
setup_rsa_key,
|
||||||
teardown),
|
teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_key,
|
cmocka_unit_test_setup_teardown(
|
||||||
|
torture_pki_rsa_import_privkey_base64_NULL_key,
|
||||||
setup_rsa_key,
|
setup_rsa_key,
|
||||||
teardown),
|
teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_str,
|
cmocka_unit_test_setup_teardown(
|
||||||
|
torture_pki_rsa_import_privkey_base64_NULL_str,
|
||||||
setup_rsa_key,
|
setup_rsa_key,
|
||||||
teardown),
|
teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64,
|
cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64,
|
||||||
setup_rsa_key,
|
setup_rsa_key,
|
||||||
teardown),
|
teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_publickey_from_privatekey,
|
cmocka_unit_test_setup_teardown(
|
||||||
|
torture_pki_rsa_publickey_from_privatekey,
|
||||||
setup_rsa_key,
|
setup_rsa_key,
|
||||||
teardown),
|
teardown),
|
||||||
cmocka_unit_test(torture_pki_rsa_import_privkey_base64_passphrase),
|
cmocka_unit_test(torture_pki_rsa_import_privkey_base64_passphrase),
|
||||||
@@ -781,12 +765,8 @@ int torture_run_tests(void)
|
|||||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_duplicate_key,
|
cmocka_unit_test_setup_teardown(torture_pki_rsa_duplicate_key,
|
||||||
setup_rsa_key,
|
setup_rsa_key,
|
||||||
teardown),
|
teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_pki_rsa_generate_key,
|
cmocka_unit_test(torture_pki_rsa_generate_key),
|
||||||
disable_secmem,
|
cmocka_unit_test_setup_teardown(torture_mixed, setup_rsa_key, teardown),
|
||||||
enable_secmem),
|
|
||||||
cmocka_unit_test_setup_teardown(torture_mixed,
|
|
||||||
setup_rsa_key,
|
|
||||||
teardown),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -801,6 +781,7 @@ int torture_run_tests(void)
|
|||||||
* If the library is statically linked, ssh_init() is not called
|
* If the library is statically linked, ssh_init() is not called
|
||||||
* automatically
|
* automatically
|
||||||
*/
|
*/
|
||||||
|
disable_secmem();
|
||||||
ssh_init();
|
ssh_init();
|
||||||
torture_filter_tests(tests);
|
torture_filter_tests(tests);
|
||||||
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
|||||||
86
tests/unittests/torture_unit_sftp.c
Normal file
86
tests/unittests/torture_unit_sftp.c
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "sftp_common.c"
|
||||||
|
#include "torture.h"
|
||||||
|
|
||||||
|
#define LIBSSH_STATIC
|
||||||
|
|
||||||
|
static void test_sftp_parse_longname(void **state)
|
||||||
|
{
|
||||||
|
const char *lname = NULL;
|
||||||
|
char *value = NULL;
|
||||||
|
|
||||||
|
/* state not used */
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
/* Valid example from SFTP draft, page 18:
|
||||||
|
* https://datatracker.ietf.org/doc/draft-spaghetti-sshm-filexfer/
|
||||||
|
*/
|
||||||
|
lname = "-rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer";
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_PERM);
|
||||||
|
assert_string_equal(value, "-rwxr-xr-x");
|
||||||
|
free(value);
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_OWNER);
|
||||||
|
assert_string_equal(value, "mjos");
|
||||||
|
free(value);
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_GROUP);
|
||||||
|
assert_string_equal(value, "staff");
|
||||||
|
free(value);
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_SIZE);
|
||||||
|
assert_string_equal(value, "348911");
|
||||||
|
free(value);
|
||||||
|
/* This function is broken further as the date contains space which breaks
|
||||||
|
* the parsing altogether */
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_DATE);
|
||||||
|
assert_string_equal(value, "Mar");
|
||||||
|
free(value);
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_TIME);
|
||||||
|
assert_string_equal(value, "25");
|
||||||
|
free(value);
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_NAME);
|
||||||
|
assert_string_equal(value, "14:29");
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sftp_parse_longname_invalid(void **state)
|
||||||
|
{
|
||||||
|
const char *lname = NULL;
|
||||||
|
char *value = NULL;
|
||||||
|
|
||||||
|
/* state not used */
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
/* Invalid inputs should not crash
|
||||||
|
*/
|
||||||
|
lname = NULL;
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_PERM);
|
||||||
|
assert_null(value);
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_NAME);
|
||||||
|
assert_null(value);
|
||||||
|
|
||||||
|
lname = "";
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_PERM);
|
||||||
|
assert_string_equal(value, "");
|
||||||
|
free(value);
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_NAME);
|
||||||
|
assert_null(value);
|
||||||
|
|
||||||
|
lname = "-rwxr-xr-x 1";
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_PERM);
|
||||||
|
assert_string_equal(value, "-rwxr-xr-x");
|
||||||
|
free(value);
|
||||||
|
value = sftp_parse_longname(lname, SFTP_LONGNAME_NAME);
|
||||||
|
assert_null(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int torture_run_tests(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
const struct CMUnitTest tests[] = {
|
||||||
|
cmocka_unit_test(test_sftp_parse_longname),
|
||||||
|
cmocka_unit_test(test_sftp_parse_longname_invalid),
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
@@ -140,6 +140,40 @@
|
|||||||
fun:FIPS_mode_set
|
fun:FIPS_mode_set
|
||||||
fun:OPENSSL_init_library
|
fun:OPENSSL_init_library
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
Threads + Failed PEM decoder do not play well openssl/openssl#29077
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: definite
|
||||||
|
fun:malloc
|
||||||
|
fun:CRYPTO_malloc
|
||||||
|
fun:CRYPTO_zalloc
|
||||||
|
fun:ossl_rcu_read_lock
|
||||||
|
fun:module_find
|
||||||
|
fun:module_run
|
||||||
|
fun:CONF_modules_load
|
||||||
|
fun:CONF_modules_load_file_ex
|
||||||
|
fun:ossl_config_int
|
||||||
|
fun:ossl_config_int
|
||||||
|
fun:ossl_init_config
|
||||||
|
fun:ossl_init_config_ossl_
|
||||||
|
fun:__pthread_once_slow.isra.0
|
||||||
|
fun:pthread_once@@GLIBC_2.34
|
||||||
|
fun:CRYPTO_THREAD_run_once
|
||||||
|
fun:OPENSSL_init_crypto
|
||||||
|
fun:ossl_provider_doall_activated
|
||||||
|
fun:ossl_algorithm_do_all
|
||||||
|
fun:ossl_method_construct.constprop.0
|
||||||
|
fun:inner_evp_generic_fetch.constprop.0
|
||||||
|
fun:evp_generic_do_all
|
||||||
|
fun:EVP_KEYMGMT_do_all_provided
|
||||||
|
fun:ossl_decoder_ctx_setup_for_pkey
|
||||||
|
fun:OSSL_DECODER_CTX_new_for_pkey
|
||||||
|
fun:pem_read_bio_key_decoder
|
||||||
|
fun:pem_read_bio_key
|
||||||
|
fun:PEM_read_bio_PrivateKey_ex
|
||||||
|
fun:pki_private_key_from_base64
|
||||||
|
...
|
||||||
|
}
|
||||||
# Cmocka
|
# Cmocka
|
||||||
{
|
{
|
||||||
This looks like leak from cmocka when the forked server is not properly terminated
|
This looks like leak from cmocka when the forked server is not properly terminated
|
||||||
@@ -207,85 +241,17 @@
|
|||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
match-leak-kinds: reachable
|
match-leak-kinds: reachable
|
||||||
fun:malloc
|
fun:malloc
|
||||||
fun:malloc
|
...
|
||||||
fun:strdup
|
|
||||||
fun:_dl_load_cache_lookup
|
|
||||||
fun:_dl_map_object
|
|
||||||
fun:dl_open_worker_begin
|
|
||||||
fun:_dl_catch_exception
|
|
||||||
fun:dl_open_worker
|
|
||||||
fun:_dl_catch_exception
|
|
||||||
fun:_dl_open
|
|
||||||
fun:do_dlopen
|
|
||||||
fun:_dl_catch_exception
|
|
||||||
fun:_dl_catch_error
|
|
||||||
fun:dlerror_run
|
|
||||||
fun:__libc_dlopen_mode
|
|
||||||
fun:module_load
|
|
||||||
fun:__nss_module_get_function
|
fun:__nss_module_get_function
|
||||||
|
...
|
||||||
fun:getaddrinfo
|
fun:getaddrinfo
|
||||||
...
|
...
|
||||||
fun:krb5_sname_to_principal
|
fun:torture_*
|
||||||
...
|
|
||||||
fun:gss_init_sec_context
|
|
||||||
fun:ssh_packet_userauth_gssapi_response
|
|
||||||
fun:ssh_packet_process
|
|
||||||
fun:ssh_packet_socket_callback
|
|
||||||
fun:ssh_socket_pollcallback
|
|
||||||
fun:ssh_poll_ctx_dopoll
|
|
||||||
fun:ssh_handle_packets
|
|
||||||
fun:ssh_handle_packets_termination
|
|
||||||
fun:ssh_userauth_get_response
|
|
||||||
fun:ssh_userauth_gssapi
|
|
||||||
fun:torture_gssapi_auth_server_identity
|
|
||||||
...
|
...
|
||||||
fun:_cmocka_run_group_tests
|
fun:_cmocka_run_group_tests
|
||||||
fun:torture_run_tests
|
fun:torture_run_tests
|
||||||
fun:main
|
fun:main
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
Reachable memory from getaddrinfo
|
|
||||||
Memcheck:Leak
|
|
||||||
match-leak-kinds: reachable
|
|
||||||
fun:malloc
|
|
||||||
fun:UnknownInlinedFun
|
|
||||||
fun:_dl_new_object
|
|
||||||
fun:_dl_map_object_from_fd
|
|
||||||
fun:_dl_map_object
|
|
||||||
fun:dl_open_worker_begin
|
|
||||||
fun:_dl_catch_exception
|
|
||||||
fun:dl_open_worker
|
|
||||||
fun:_dl_catch_exception
|
|
||||||
fun:_dl_open
|
|
||||||
fun:do_dlopen
|
|
||||||
fun:_dl_catch_exception
|
|
||||||
fun:_dl_catch_error
|
|
||||||
fun:dlerror_run
|
|
||||||
fun:__libc_dlopen_mode
|
|
||||||
fun:module_load
|
|
||||||
fun:__nss_module_get_function
|
|
||||||
fun:getaddrinfo
|
|
||||||
...
|
|
||||||
fun:krb5_sname_to_principal
|
|
||||||
...
|
|
||||||
fun:gss_init_sec_context
|
|
||||||
fun:ssh_packet_userauth_gssapi_response
|
|
||||||
fun:ssh_packet_process
|
|
||||||
fun:ssh_packet_socket_callback
|
|
||||||
fun:ssh_socket_pollcallback
|
|
||||||
fun:ssh_poll_ctx_dopoll
|
|
||||||
fun:ssh_handle_packets
|
|
||||||
fun:ssh_handle_packets_termination
|
|
||||||
fun:ssh_userauth_get_response
|
|
||||||
fun:ssh_userauth_gssapi
|
|
||||||
fun:torture_gssapi_auth_server_identity
|
|
||||||
...
|
|
||||||
fun:_cmocka_run_group_tests
|
|
||||||
fun:torture_run_tests
|
|
||||||
fun:main
|
|
||||||
}
|
|
||||||
|
|
||||||
## libkrb5
|
## libkrb5
|
||||||
# krb5_mcc_generate_new allocates a hashtab on a static global variable
|
# krb5_mcc_generate_new allocates a hashtab on a static global variable
|
||||||
# It doesn't get freed.
|
# It doesn't get freed.
|
||||||
@@ -298,3 +264,28 @@
|
|||||||
...
|
...
|
||||||
fun:krb5_mcc_generate_new*
|
fun:krb5_mcc_generate_new*
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
Error string from acquire creds in krb5
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: reachable
|
||||||
|
fun:malloc
|
||||||
|
...
|
||||||
|
fun:krb5_gss_save_error_string
|
||||||
|
...
|
||||||
|
fun:acquire_cred_context.isra.0
|
||||||
|
fun:acquire_cred_from.isra.0
|
||||||
|
fun:gss_add_cred_from
|
||||||
|
fun:gss_acquire_cred_from
|
||||||
|
}
|
||||||
|
{
|
||||||
|
error string from gss init sec context
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: reachable
|
||||||
|
fun:malloc
|
||||||
|
...
|
||||||
|
fun:krb5_gss_save_error_string
|
||||||
|
...
|
||||||
|
fun:krb5_gss_init_sec_context_ext
|
||||||
|
fun:krb5_gss_init_sec_context
|
||||||
|
fun:gss_init_sec_context
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user